use of org.robovm.compiler.llvm.ArrayType 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.ArrayType in project robovm by robovm.
the class MethodCompiler method doCompile.
protected Function doCompile(ModuleBuilder moduleBuilder, SootMethod method) {
function = createMethodFunction(method);
moduleBuilder.addFunction(function);
this.moduleBuilder = moduleBuilder;
env = function.getParameterRef(0);
trapsAt = new HashMap<Unit, List<Trap>>();
Body body = method.retrieveActiveBody();
NopStmt prependedNop = null;
if (method.isStatic() && !body.getUnits().getFirst().getBoxesPointingToThis().isEmpty()) {
// Fix for issue #1. This prevents an NPE in Soot's ArrayBoundsCheckerAnalysis. The NPE
// occurs for static methods which start with a unit that is the target of some other
// unit. We work around this by inserting a nop statement as the first unit in such
// methods. See http://www.sable.mcgill.ca/listarchives/soot-list/msg01397.html.
Unit insertionPoint = body.getUnits().getFirst();
prependedNop = Jimple.v().newNopStmt();
body.getUnits().getNonPatchingChain().insertBefore(prependedNop, insertionPoint);
}
PackManager.v().getPack("jtp").apply(body);
PackManager.v().getPack("jop").apply(body);
PackManager.v().getPack("jap").apply(body);
if (body.getUnits().getFirst() == prependedNop && prependedNop.getBoxesPointingToThis().isEmpty()) {
// Remove the nop we inserted above to work around the bug in Soot's
// ArrayBoundsCheckerAnalysis which has now been run.
body.getUnits().getNonPatchingChain().removeFirst();
}
PatchingChain<Unit> units = body.getUnits();
Map<Unit, List<Unit>> branchTargets = getBranchTargets(body);
Map<Unit, Integer> trapHandlers = getTrapHandlers(body);
Map<Unit, Integer> selChanges = new HashMap<Unit, Integer>();
int multiANewArrayMaxDims = 0;
Set<Local> locals = new HashSet<Local>();
boolean emitCheckStackOverflow = false;
for (Unit unit : units) {
if (unit instanceof DefinitionStmt) {
DefinitionStmt stmt = (DefinitionStmt) unit;
if (stmt.getLeftOp() instanceof Local) {
Local local = (Local) stmt.getLeftOp();
if (!locals.contains(local)) {
Type type = getLocalType(local.getType());
Alloca alloca = new Alloca(function.newVariable(local.getName(), type), type);
alloca.attach(local);
function.add(alloca);
locals.add(local);
}
}
if (stmt.getRightOp() instanceof NewMultiArrayExpr) {
NewMultiArrayExpr expr = (NewMultiArrayExpr) stmt.getRightOp();
multiANewArrayMaxDims = Math.max(multiANewArrayMaxDims, expr.getSizeCount());
}
if (stmt.getRightOp() instanceof InvokeExpr) {
emitCheckStackOverflow = true;
}
}
if (unit instanceof InvokeStmt) {
emitCheckStackOverflow = true;
}
}
dims = null;
if (multiANewArrayMaxDims > 0) {
dims = function.newVariable("dims", new PointerType(new ArrayType(multiANewArrayMaxDims, I32)));
function.add(new Alloca(dims, new ArrayType(multiANewArrayMaxDims, I32)));
}
if (emitCheckStackOverflow) {
call(CHECK_STACK_OVERFLOW);
}
Value trycatchContext = null;
if (!body.getTraps().isEmpty()) {
List<List<Trap>> recordedTraps = new ArrayList<List<Trap>>();
for (Unit unit : units) {
// Calculate the predecessor units of unit
Set<Unit> incoming = new HashSet<Unit>();
if (units.getFirst() != unit && units.getPredOf(unit).fallsThrough()) {
incoming.add(units.getPredOf(unit));
}
if (branchTargets.keySet().contains(unit)) {
incoming.addAll(branchTargets.get(unit));
}
if (unit == units.getFirst() || trapHandlers.containsKey(unit) || trapsDiffer(unit, incoming)) {
List<Trap> traps = getTrapsAt(unit);
if (traps.isEmpty()) {
selChanges.put(unit, 0);
} else {
int index = recordedTraps.indexOf(traps);
if (index == -1) {
index = recordedTraps.size();
recordedTraps.add(traps);
}
selChanges.put(unit, index + 1);
}
}
}
StructureConstantBuilder landingPadsPtrs = new StructureConstantBuilder();
for (List<Trap> traps : recordedTraps) {
StructureConstantBuilder landingPads = new StructureConstantBuilder();
for (Trap trap : traps) {
SootClass exClass = trap.getException();
StructureConstantBuilder landingPad = new StructureConstantBuilder();
if ("java.lang.Throwable".equals(exClass.getName()) || exClass.isPhantom()) {
landingPad.add(new NullConstant(I8_PTR));
} else {
catches.add(getInternalName(exClass));
if (exClass == sootClass) {
/*
* The class being compiled is an exception class
* with a catch clause which catches itself. We
* cannot reference the info struct directly since
* we don't know the type of it and it hasn't been
* emitted by ClassCompiler yet. Use the internal
* i8* alias instead which ClassCompiler will emit.
* See #1007.
*/
landingPad.add(new AliasRef(Symbols.infoStructSymbol(getInternalName(exClass)) + "_i8ptr", I8_PTR));
} else {
Global g = new Global(Symbols.infoStructSymbol(getInternalName(exClass)), I8_PTR, true);
if (!moduleBuilder.hasSymbol(g.getName())) {
moduleBuilder.addGlobal(g);
}
landingPad.add(g.ref());
}
}
landingPad.add(new IntegerConstant(trapHandlers.get(trap.getHandlerUnit()) + 1));
landingPads.add(landingPad.build());
}
landingPads.add(new StructureConstantBuilder().add(new NullConstant(I8_PTR)).add(new IntegerConstant(0)).build());
Global g = moduleBuilder.newGlobal(landingPads.build(), true);
landingPadsPtrs.add(new ConstantBitcast(g.ref(), I8_PTR));
}
Global g = moduleBuilder.newGlobal(landingPadsPtrs.build(), true);
Variable ctx = function.newVariable(TRYCATCH_CONTEXT_PTR);
Variable bcCtx = function.newVariable(BC_TRYCATCH_CONTEXT_PTR);
function.add(new Alloca(bcCtx, BC_TRYCATCH_CONTEXT));
Variable selPtr = function.newVariable(new PointerType(I32));
function.add(new Getelementptr(selPtr, bcCtx.ref(), 0, 0, 1));
function.add(new Store(new IntegerConstant(0), selPtr.ref()));
Variable bcCtxLandingPadsPtr = function.newVariable(I8_PTR_PTR);
function.add(new Getelementptr(bcCtxLandingPadsPtr, bcCtx.ref(), 0, 1));
function.add(new Store(new ConstantBitcast(g.ref(), I8_PTR), bcCtxLandingPadsPtr.ref()));
function.add(new Bitcast(ctx, bcCtx.ref(), TRYCATCH_CONTEXT_PTR));
trycatchContext = ctx.ref();
Value result = call(RVM_TRYCATCH_ENTER, env, trycatchContext);
Map<IntegerConstant, BasicBlockRef> alt = new TreeMap<IntegerConstant, BasicBlockRef>();
for (Entry<Unit, Integer> entry : trapHandlers.entrySet()) {
alt.put(new IntegerConstant(entry.getValue() + 1), function.newBasicBlockRef(new Label(entry.getKey())));
}
function.add(new Switch(result, function.newBasicBlockRef(new Label(units.getFirst())), alt));
if (!branchTargets.containsKey(units.getFirst())) {
function.newBasicBlock(new Label(units.getFirst()));
}
}
if ("<clinit>".equals(method.getName())) {
initializeClassFields();
}
for (Unit unit : units) {
if (branchTargets.containsKey(unit) || trapHandlers.containsKey(unit)) {
BasicBlock oldBlock = function.getCurrentBasicBlock();
function.newBasicBlock(new Label(unit));
if (oldBlock != null) {
Instruction last = oldBlock.last();
if (last == null || !isTerminator(last)) {
oldBlock.add(new Br(function.newBasicBlockRef(new Label(unit))));
}
}
}
if (selChanges.containsKey(unit)) {
int sel = selChanges.get(unit);
// trycatchContext->sel = sel
Variable selPtr = function.newVariable(new PointerType(I32));
function.add(new Getelementptr(selPtr, trycatchContext, 0, 1)).attach(unit);
function.add(new Store(new IntegerConstant(sel), selPtr.ref())).attach(unit);
}
if (unit instanceof DefinitionStmt) {
assign((DefinitionStmt) unit);
} else if (unit instanceof ReturnStmt) {
if (!body.getTraps().isEmpty()) {
trycatchLeave(function);
}
return_((ReturnStmt) unit);
} else if (unit instanceof ReturnVoidStmt) {
if (!body.getTraps().isEmpty()) {
trycatchLeave(function);
}
returnVoid((ReturnVoidStmt) unit);
} else if (unit instanceof IfStmt) {
if_((IfStmt) unit);
} else if (unit instanceof LookupSwitchStmt) {
lookupSwitch((LookupSwitchStmt) unit);
} else if (unit instanceof TableSwitchStmt) {
tableSwitch((TableSwitchStmt) unit);
} else if (unit instanceof GotoStmt) {
goto_((GotoStmt) unit);
} else if (unit instanceof ThrowStmt) {
throw_((ThrowStmt) unit);
} else if (unit instanceof InvokeStmt) {
invoke((InvokeStmt) unit);
} else if (unit instanceof EnterMonitorStmt) {
enterMonitor((EnterMonitorStmt) unit);
} else if (unit instanceof ExitMonitorStmt) {
exitMonitor((ExitMonitorStmt) unit);
} else if (unit instanceof NopStmt) {
nop((NopStmt) unit);
} else {
throw new IllegalArgumentException("Unknown Unit type: " + unit.getClass());
}
}
if (this.className.equals("java/lang/Object") && "<init>".equals(method.getName())) {
// If it is the object will be registered for finalization.
for (BasicBlock bb : function.getBasicBlocks()) {
if (bb.last() instanceof Ret) {
// Insert a call to register_finalizable() before this ret
Call call = new Call(REGISTER_FINALIZABLE, env, function.getParameterRef(1));
call.attach(bb.last().getAttachment(Unit.class));
bb.insertBefore(bb.last(), call);
}
}
}
return function;
}
use of org.robovm.compiler.llvm.ArrayType in project robovm by robovm.
the class BroMethodCompiler method marshalObjectToNative.
protected Value marshalObjectToNative(Function fn, MarshalerMethod marshalerMethod, MarshaledArg marshaledArg, Type nativeType, Value env, Value object, long flags) {
Invokestatic invokestatic = marshalerMethod.getInvokeStatic(sootMethod.getDeclaringClass());
trampolines.add(invokestatic);
Value handle = call(fn, invokestatic.getFunctionRef(), env, object, new IntegerConstant(flags));
Variable nativeValue = fn.newVariable(nativeType);
if (nativeType instanceof StructureType || nativeType instanceof ArrayType) {
Variable tmp = fn.newVariable(new PointerType(nativeType));
fn.add(new Inttoptr(tmp, handle, tmp.getType()));
fn.add(new Load(nativeValue, tmp.ref()));
} else {
fn.add(new Inttoptr(nativeValue, handle, nativeType));
}
if (marshaledArg != null) {
marshaledArg.handle = handle;
marshaledArg.object = object;
}
return nativeValue.ref();
}
use of org.robovm.compiler.llvm.ArrayType in project robovm by robovm.
the class BroMethodCompiler method getLoType.
protected static String getLoType(final Type type, String base, int index, Map<String, String> structs) {
if (type instanceof StructureType) {
StringBuilder sb = new StringBuilder();
StructureType st = (StructureType) type;
sb.append("{");
String name = String.format("%s_%04d", base, index);
for (int i = 0; i < st.getTypeCount(); i++) {
Type t = st.getTypeAt(i);
if (i == 0 && t instanceof StructureType) {
if (((StructureType) t).getTypeCount() == 0) {
// Skip empty structs as first member
continue;
}
}
// Only support arrays embedded in structs
StringBuilder dims = new StringBuilder();
while (t instanceof ArrayType) {
ArrayType at = (ArrayType) t;
dims.append('[').append(at.getSize()).append(']');
t = ((ArrayType) t).getElementType();
}
sb.append(getLoType(t, name, i, structs)).append(" m" + i).append(dims).append(";");
}
sb.append("}");
structs.put(name, sb.toString());
return "struct " + name;
} else {
return getHiType(type);
}
}
use of org.robovm.compiler.llvm.ArrayType in project robovm by robovm.
the class CallbackMethodCompilerTest method testCreateCallbackCWrapperComplexNestedStructByValReturnAndParameter.
@Test
public void testCreateCallbackCWrapperComplexNestedStructByValReturnAndParameter() {
StructureType structType = new StructureType(new StructureType(I8, I16), new StructureType(I32, I64), new StructureType(FLOAT, DOUBLE), new ArrayType(100, I32), new ArrayType(10, new StructureType(FLOAT, FLOAT)), new ArrayType(5, new ArrayType(10, I32)), new StructureType(I8_PTR, new PointerType(new StructureType(I32))));
assertEquals("struct f_0001_0006 {void* m0;void* m1;};\n" + "struct f_0001_0004 {float m0;float m1;};\n" + "struct f_0001_0002 {float m0;double m1;};\n" + "struct f_0001_0001 {int m0;long long m1;};\n" + "struct f_0001_0000 {char m0;short m1;};\n" + "struct f_0001 {struct f_0001_0000 m0;struct f_0001_0001 m1;struct f_0001_0002 m2;int m3[100];struct f_0001_0004 m4[10];int m5[5][10];struct f_0001_0006 m6;};\n" + "struct f_0000_0006 {void* m0;void* m1;};\n" + "struct f_0000_0004 {float m0;float m1;};\n" + "struct f_0000_0002 {float m0;double m1;};\n" + "struct f_0000_0001 {int m0;long long m1;};\n" + "struct f_0000_0000 {char m0;short m1;};\n" + "struct f_0000 {struct f_0000_0000 m0;struct f_0000_0001 m1;struct f_0000_0002 m2;int m3[100];struct f_0000_0004 m4[10];int m5[5][10];struct f_0000_0006 m6;};\n" + "void* f_inner(void*);\n" + "struct f_0000 f(struct f_0001 p0) {\n" + " return *((struct f_0000*) f_inner((void*) &p0));\n" + "}\n", CallbackMethodCompiler.createCallbackCWrapper(new FunctionType(structType, structType), "f", "f_inner"));
}
Aggregations