use of org.robovm.compiler.llvm.BasicBlockRef in project robovm by robovm.
the class BridgeMethodCompiler method doCompile.
protected Function doCompile(ModuleBuilder moduleBuilder, SootMethod method) {
validateBridgeMethod(method);
AnnotationTag bridgeAnnotation = getAnnotation(method, BRIDGE);
boolean dynamic = readBooleanElem(bridgeAnnotation, "dynamic", false);
boolean optional = readBooleanElem(bridgeAnnotation, "optional", false);
boolean useCWrapper = requiresCWrapper(method);
Function fn = createMethodFunction(method);
moduleBuilder.addFunction(fn);
Type[] parameterTypes = fn.getType().getParameterTypes();
String[] parameterNames = fn.getParameterNames();
ArrayList<Argument> args = new ArrayList<Argument>();
for (int i = 0; i < parameterTypes.length; i++) {
args.add(new Argument(new VariableRef(parameterNames[i], parameterTypes[i])));
}
VariableRef env = fn.getParameterRef(0);
// Load the address of the resolved @Bridge method
Variable targetFn = fn.newVariable(I8_PTR);
if (!dynamic) {
Global targetFnPtr = new Global(Symbols.bridgePtrSymbol(method), _private, new NullConstant(I8_PTR));
moduleBuilder.addGlobal(targetFnPtr);
fn.add(new Load(targetFn, targetFnPtr.ref()));
Label nullLabel = new Label();
Label notNullLabel = new Label();
Variable nullCheck = fn.newVariable(I1);
fn.add(new Icmp(nullCheck, Condition.eq, targetFn.ref(), new NullConstant(I8_PTR)));
fn.add(new Br(nullCheck.ref(), fn.newBasicBlockRef(nullLabel), fn.newBasicBlockRef(notNullLabel)));
fn.newBasicBlock(nullLabel);
call(fn, optional ? BC_THROW_UNSATISIFED_LINK_ERROR_OPTIONAL_BRIDGE_NOT_BOUND : BC_THROW_UNSATISIFED_LINK_ERROR_BRIDGE_NOT_BOUND, env, moduleBuilder.getString(className), moduleBuilder.getString(method.getName()), moduleBuilder.getString(getDescriptor(method)));
fn.add(new Unreachable());
fn.newBasicBlock(notNullLabel);
} else {
// Dynamic @Bridge methods pass the target function pointer as a
// long in the first parameter.
fn.add(new Inttoptr(targetFn, fn.getParameterRef(1), targetFn.getType()));
args.remove(1);
}
// Marshal args
// Remove Env* from args
args.remove(0);
// Save the Object->handle mapping for each marshaled object. We need it
// after the native call to call updateObject() on the marshaler for
// each value. Since the LLVM variables that store these values are used
// after the native call we get the nice side effect that neither the
// Java objects nor the handles can be garbage collected while we're in
// native code.
List<MarshaledArg> marshaledArgs = new ArrayList<MarshaledArg>();
FunctionType targetFnType = getBridgeFunctionType(method, dynamic, false);
Type[] targetParameterTypes = targetFnType.getParameterTypes();
if (!method.isStatic()) {
MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, MarshalSite.RECEIVER));
MarshaledArg marshaledArg = new MarshaledArg();
marshaledArg.paramIndex = MarshalSite.RECEIVER;
marshaledArgs.add(marshaledArg);
Type nativeType = targetParameterTypes[0];
Value nativeValue = marshalObjectToNative(fn, marshalerMethod, marshaledArg, useCWrapper ? I8_PTR : nativeType, env, args.get(0).getValue(), MarshalerFlags.CALL_TYPE_BRIDGE);
args.set(0, new Argument(nativeValue));
}
for (int i = 0, argIdx = 0; i < method.getParameterCount(); i++) {
if (dynamic && i == 0) {
// Skip the target function pointer for dynamic bridge methods.
continue;
}
if (!method.isStatic() && argIdx == 0) {
// Skip the receiver in args. It doesn't correspond to a parameter.
argIdx++;
}
soot.Type type = method.getParameterType(i);
if (needsMarshaler(type)) {
MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, i));
// The return type of the marshaler's toNative() method is derived from the target function type.
Type nativeType = targetParameterTypes[argIdx];
if (nativeType instanceof PrimitiveType) {
Value nativeValue = marshalValueObjectToNative(fn, marshalerMethod, nativeType, env, args.get(argIdx).getValue(), MarshalerFlags.CALL_TYPE_BRIDGE);
args.set(argIdx, new Argument(nativeValue));
} else {
ParameterAttribute[] parameterAttributes = new ParameterAttribute[0];
if (isPassByValue(method, i) || isStructRet(method, i)) {
// The parameter must not be null. We assume that Structs
// never have a NULL handle so we just check that the Java
// Object isn't null.
call(fn, CHECK_NULL, env, args.get(argIdx).getValue());
}
MarshaledArg marshaledArg = new MarshaledArg();
marshaledArg.paramIndex = i;
marshaledArgs.add(marshaledArg);
Value nativeValue = marshalObjectToNative(fn, marshalerMethod, marshaledArg, useCWrapper ? I8_PTR : nativeType, env, args.get(argIdx).getValue(), MarshalerFlags.CALL_TYPE_BRIDGE);
args.set(argIdx, new Argument(nativeValue, parameterAttributes));
}
} else {
args.set(argIdx, new Argument(marshalPrimitiveToNative(fn, method, i, args.get(argIdx).getValue())));
}
argIdx++;
}
Variable structResult = null;
Value targetFnRef = null;
if (useCWrapper) {
args.add(0, new Argument(targetFn.ref()));
if (targetFnType.getReturnType() instanceof StructureType) {
// Allocate space on the stack big enough to hold the returned struct
Variable tmp = fn.newVariable(new PointerType(targetFnType.getReturnType()));
fn.add(new Alloca(tmp, targetFnType.getReturnType()));
structResult = fn.newVariable(I8_PTR);
fn.add(new Bitcast(structResult, tmp.ref(), I8_PTR));
args.add(1, new Argument(structResult.ref()));
}
String wrapperName = Symbols.bridgeCSymbol(method);
FunctionType wrapperFnType = getBridgeFunctionType(method, dynamic, true);
getCWrapperFunctions().add(createBridgeCWrapper(targetFnType.getReturnType(), targetFnType.getParameterTypes(), wrapperFnType.getParameterTypes(), wrapperName));
FunctionRef wrapperFnRef = getBridgeCWrapperRef(targetFnType, wrapperName);
moduleBuilder.addFunctionDeclaration(new FunctionDeclaration(wrapperFnRef));
targetFnRef = wrapperFnRef;
} else {
Variable tmp = fn.newVariable(targetFnType);
fn.add(new Bitcast(tmp, targetFn.ref(), targetFnType));
targetFnRef = tmp.ref();
}
// Execute the call to native code
BasicBlockRef bbSuccess = fn.newBasicBlockRef(new Label("success"));
BasicBlockRef bbFailure = fn.newBasicBlockRef(new Label("failure"));
pushNativeFrame(fn);
trycatchAllEnter(fn, env, bbSuccess, bbFailure);
fn.newBasicBlock(bbSuccess.getLabel());
Value result = callWithArguments(fn, targetFnRef, args);
trycatchLeave(fn, env);
popNativeFrame(fn);
updateObject(method, fn, env, MarshalerFlags.CALL_TYPE_BRIDGE, marshaledArgs);
// Marshal the return value
if (needsMarshaler(method.getReturnType())) {
MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method));
String targetClassName = getInternalName(method.getReturnType());
if (structResult != null) {
// Copy to the heap.
DataLayout dataLayout = config.getDataLayout();
Value heapCopy = call(fn, BC_COPY_STRUCT, env, structResult.ref(), new IntegerConstant(dataLayout.getAllocSize(targetFnType.getReturnType())));
result = marshalNativeToObject(fn, marshalerMethod, null, env, targetClassName, heapCopy, MarshalerFlags.CALL_TYPE_BRIDGE);
} else if (targetFnType.getReturnType() instanceof PrimitiveType) {
result = marshalNativeToValueObject(fn, marshalerMethod, env, targetClassName, result, MarshalerFlags.CALL_TYPE_BRIDGE);
} else {
result = marshalNativeToObject(fn, marshalerMethod, null, env, targetClassName, result, MarshalerFlags.CALL_TYPE_BRIDGE);
}
} else {
result = marshalNativeToPrimitive(fn, method, result);
}
fn.add(new Ret(result));
fn.newBasicBlock(bbFailure.getLabel());
trycatchLeave(fn, env);
popNativeFrame(fn);
Value ex = call(fn, BC_EXCEPTION_CLEAR, env);
// Call Marshaler.updateObject() for each object that was marshaled before
// the call.
updateObject(method, fn, env, MarshalerFlags.CALL_TYPE_BRIDGE, marshaledArgs);
call(fn, BC_THROW, env, ex);
fn.add(new Unreachable());
return fn;
}
use of org.robovm.compiler.llvm.BasicBlockRef in project robovm by robovm.
the class MethodCompiler method tableSwitch.
private void tableSwitch(TableSwitchStmt stmt) {
Map<IntegerConstant, BasicBlockRef> targets = new HashMap<IntegerConstant, BasicBlockRef>();
for (int i = stmt.getLowIndex(); i <= stmt.getHighIndex(); i++) {
Unit target = stmt.getTarget(i - stmt.getLowIndex());
targets.put(new IntegerConstant(i), function.newBasicBlockRef(new Label(target)));
}
BasicBlockRef def = function.newBasicBlockRef(new Label(stmt.getDefaultTarget()));
Value key = immediate(stmt, (Immediate) stmt.getKey());
function.add(new Switch(key, def, targets)).attach(stmt);
}
use of org.robovm.compiler.llvm.BasicBlockRef in project robovm by robovm.
the class CallbackMethodCompiler method compileCallback.
private Function compileCallback(ModuleBuilder moduleBuilder, SootMethod method) {
Function callbackFn = null;
FunctionType nativeFnType = null;
boolean useCWrapper = requiresCWrapper(method);
if (useCWrapper) {
// The C wrapper is the function which is called by native code. It
// handles structs passed/returned by value. It calls an LLVM function
// which has the same signature but all structs passed/returned by value
// replaced by pointers (i8*).
FunctionRef callbackCWrapperRef = getCallbackCWrapperRef(method, Symbols.callbackCSymbol(method));
getCWrapperFunctions().add(createCallbackCWrapper(callbackCWrapperRef.getType(), callbackCWrapperRef.getName(), Symbols.callbackInnerCSymbol(method)));
moduleBuilder.addFunctionDeclaration(new FunctionDeclaration(callbackCWrapperRef));
Type callbackRetType = callbackCWrapperRef.getType().getReturnType() instanceof StructureType ? I8_PTR : callbackCWrapperRef.getType().getReturnType();
Type[] callbackParamTypes = new Type[callbackCWrapperRef.getType().getParameterTypes().length];
for (int i = 0; i < callbackParamTypes.length; i++) {
Type t = callbackCWrapperRef.getType().getParameterTypes()[i];
if (t instanceof StructureType) {
t = I8_PTR;
}
callbackParamTypes[i] = t;
}
moduleBuilder.addAlias(new Alias(Symbols.callbackPtrSymbol(method), Linkage._private, new ConstantBitcast(callbackCWrapperRef, I8_PTR)));
callbackFn = new FunctionBuilder(Symbols.callbackInnerCSymbol(method), new FunctionType(callbackRetType, callbackParamTypes)).build();
nativeFnType = callbackCWrapperRef.getType();
} else {
FunctionType callbackFnType = getCallbackFunctionType(method, false);
callbackFn = FunctionBuilder.callback(method, callbackFnType);
moduleBuilder.addAlias(new Alias(Symbols.callbackPtrSymbol(method), Linkage._private, new ConstantBitcast(callbackFn.ref(), I8_PTR)));
nativeFnType = callbackFnType;
}
moduleBuilder.addFunction(callbackFn);
String targetName = method.isSynchronized() ? Symbols.synchronizedWrapperSymbol(method) : Symbols.methodSymbol(method);
FunctionRef targetFn = new FunctionRef(targetName, getFunctionType(method));
// Increase the attach count for the current thread (attaches the thread
// if not attached)
Value env = call(callbackFn, BC_ATTACH_THREAD_FROM_CALLBACK);
BasicBlockRef bbSuccess = callbackFn.newBasicBlockRef(new Label("success"));
BasicBlockRef bbFailure = callbackFn.newBasicBlockRef(new Label("failure"));
pushCallbackFrame(callbackFn, env);
trycatchAllEnter(callbackFn, env, bbSuccess, bbFailure);
callbackFn.newBasicBlock(bbSuccess.getLabel());
List<MarshaledArg> marshaledArgs = new ArrayList<MarshaledArg>();
ArrayList<Value> args = new ArrayList<Value>();
args.add(env);
if (!method.isStatic()) {
MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, MarshalSite.RECEIVER));
MarshaledArg marshaledArg = new MarshaledArg();
marshaledArg.paramIndex = MarshalSite.RECEIVER;
marshaledArgs.add(marshaledArg);
Value arg = callbackFn.getParameterRef(0);
String targetClassName = getInternalName(method.getDeclaringClass());
arg = marshalNativeToObject(callbackFn, marshalerMethod, marshaledArg, env, targetClassName, arg, MarshalerFlags.CALL_TYPE_CALLBACK);
args.add(arg);
}
for (int i = 0, argIdx = 0; i < method.getParameterCount(); i++, argIdx++) {
if (!method.isStatic() && argIdx == 0) {
argIdx++;
}
Value arg = callbackFn.getParameterRef(argIdx);
soot.Type type = method.getParameterType(i);
if (needsMarshaler(type)) {
MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, i));
String targetClassName = getInternalName(type);
if (arg.getType() instanceof PrimitiveType) {
arg = marshalNativeToValueObject(callbackFn, marshalerMethod, env, targetClassName, arg, MarshalerFlags.CALL_TYPE_CALLBACK);
} else {
MarshaledArg marshaledArg = new MarshaledArg();
marshaledArg.paramIndex = i;
marshaledArgs.add(marshaledArg);
Type nativeType = nativeFnType.getParameterTypes()[argIdx];
if (nativeType instanceof StructureType) {
// Struct passed by value on the stack. Make a heap copy of the data and marshal that.
DataLayout dataLayout = config.getDataLayout();
Value heapCopy = call(callbackFn, BC_COPY_STRUCT, env, arg, new IntegerConstant(dataLayout.getAllocSize(nativeType)));
arg = marshalNativeToObject(callbackFn, marshalerMethod, marshaledArg, env, targetClassName, heapCopy, MarshalerFlags.CALL_TYPE_CALLBACK);
} else {
arg = marshalNativeToObject(callbackFn, marshalerMethod, marshaledArg, env, targetClassName, arg, MarshalerFlags.CALL_TYPE_CALLBACK);
}
}
} else {
arg = marshalNativeToPrimitive(callbackFn, method, i, arg);
}
args.add(arg);
}
Value result = call(callbackFn, targetFn, args);
// Call Marshaler.updateNative() for each object that was marshaled before
// the call.
updateNative(method, callbackFn, env, MarshalerFlags.CALL_TYPE_CALLBACK, marshaledArgs);
// Marshal the returned value to a native value before returning
if (needsMarshaler(method.getReturnType())) {
MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method));
Type nativeType = callbackFn.getType().getReturnType();
if (nativeType instanceof PrimitiveType) {
result = marshalValueObjectToNative(callbackFn, marshalerMethod, nativeType, env, result, MarshalerFlags.CALL_TYPE_CALLBACK);
} else {
result = marshalObjectToNative(callbackFn, marshalerMethod, null, nativeType, env, result, MarshalerFlags.CALL_TYPE_CALLBACK);
}
} else {
result = marshalPrimitiveToNative(callbackFn, method, result);
}
trycatchLeave(callbackFn, env);
popCallbackFrame(callbackFn, env);
call(callbackFn, BC_DETACH_THREAD_FROM_CALLBACK, env);
callbackFn.add(new Ret(result));
callbackFn.newBasicBlock(bbFailure.getLabel());
trycatchLeave(callbackFn, env);
popCallbackFrame(callbackFn, env);
Value ex = call(callbackFn, BC_EXCEPTION_CLEAR, env);
// Call Marshaler.updateNative() for each object that was marshaled before
// the call.
updateNative(method, callbackFn, env, MarshalerFlags.CALL_TYPE_CALLBACK, marshaledArgs);
call(callbackFn, BC_DETACH_THREAD_FROM_CALLBACK, env);
call(callbackFn, BC_THROW, env, ex);
callbackFn.add(new Unreachable());
return callbackFn;
}
use of org.robovm.compiler.llvm.BasicBlockRef 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.BasicBlockRef in project robovm by robovm.
the class MethodCompiler method lookupSwitch.
private void lookupSwitch(LookupSwitchStmt stmt) {
Map<IntegerConstant, BasicBlockRef> targets = new HashMap<IntegerConstant, BasicBlockRef>();
for (int i = 0; i < stmt.getTargetCount(); i++) {
int value = stmt.getLookupValue(i);
Unit target = stmt.getTarget(i);
targets.put(new IntegerConstant(value), function.newBasicBlockRef(new Label(target)));
}
BasicBlockRef def = function.newBasicBlockRef(new Label(stmt.getDefaultTarget()));
Value key = immediate(stmt, (Immediate) stmt.getKey());
function.add(new Switch(key, def, targets)).attach(stmt);
}
Aggregations