use of org.robovm.compiler.llvm.Label 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);
}
use of org.robovm.compiler.llvm.Label in project robovm by robovm.
the class GlobalValueMethodCompiler method doCompile.
protected Function doCompile(ModuleBuilder moduleBuilder, SootMethod method) {
AnnotationTag globalValueAnnotation = getAnnotation(method, GLOBAL_VALUE);
validateGlobalValueMethod(method, globalValueAnnotation);
boolean optional = readBooleanElem(globalValueAnnotation, "optional", false);
boolean dereference = readBooleanElem(globalValueAnnotation, "dereference", true);
Function fn = createMethodFunction(method);
moduleBuilder.addFunction(fn);
Type valueType = getStructMemberType(method);
// Load the address of the resolved @GlobalValue method
Variable valuePtr = fn.newVariable(new PointerType(valueType));
Global valuePtrPtr = new Global(Symbols.globalValuePtrSymbol(method), _private, new NullConstant(I8_PTR));
moduleBuilder.addGlobal(valuePtrPtr);
fn.add(new Load(valuePtr, new ConstantBitcast(valuePtrPtr.ref(), new PointerType(valuePtr.getType()))));
Label nullLabel = new Label();
Label notNullLabel = new Label();
Variable nullCheck = fn.newVariable(I1);
fn.add(new Icmp(nullCheck, Condition.eq, valuePtr.ref(), new NullConstant(valuePtr.getType())));
fn.add(new Br(nullCheck.ref(), fn.newBasicBlockRef(nullLabel), fn.newBasicBlockRef(notNullLabel)));
fn.newBasicBlock(nullLabel);
VariableRef env = fn.getParameterRef(0);
call(fn, BC_THROW_UNSATISIFED_LINK_ERROR, env, moduleBuilder.getString(String.format((optional ? "Optional " : "") + "@GlobalValue method %s.%s%s not bound", className, method.getName(), getDescriptor(method))));
fn.add(new Unreachable());
fn.newBasicBlock(notNullLabel);
if (method.getParameterCount() == 0) {
// Getter
Value result = loadValueForGetter(method, fn, valueType, valuePtr.ref(), env, dereference, MarshalerFlags.CALL_TYPE_GLOBAL_VALUE);
fn.add(new Ret(result));
} else {
// Setter
// 'env' is parameter 0, the value we're interested in is at index 1
Value value = fn.getParameterRef(1);
storeValueForSetter(method, fn, valueType, valuePtr.ref(), env, value, MarshalerFlags.CALL_TYPE_GLOBAL_VALUE);
fn.add(new Ret());
}
return fn;
}
use of org.robovm.compiler.llvm.Label in project robovm by robovm.
the class NativeMethodCompiler method createNative.
private FunctionRef createNative(ModuleBuilder mb, SootMethod method) {
String targetInternalName = getInternalName(method.getDeclaringClass());
String methodName = method.getName();
String methodDesc = getDescriptor(method);
FunctionType nativeFunctionType = Types.getNativeFunctionType(methodDesc, method.isStatic());
String shortName = mangleNativeMethod(targetInternalName, methodName);
String longName = mangleNativeMethod(targetInternalName, methodName, methodDesc);
/*
* To support statically linked native method implementation we create
* weak stub functions with the same names as the expected JNI functions
* (long and short names). These will be discarded by the linker if
* proper functions are available at link time.
*
* The weak stub with the short JNI name just calls the weak stub with
* the long name.
*
* The weak stub with the long name calls _bcResolveNative() which will
* try to resolve the native method against dynamically loaded JNI libs.
* If _bcResolveNative() finds a matching symbol in a dynamic lib or an
* implementation has previously been registered using JNI
* RegisterNatives() that will be stored in the native method pointer
* passed to it and returned. The stub will call the implementation
* returned by _bcResolveNative(). If no implementation can be found
* _bcResolveNative() throws an UnsatisfiedLinkError and doesn't return
* to the stub.
*
* The limitation of this approach is that RegisterNatives() only works
* for dynamically linked native methods and can only be used prior to
* the first call of such a method. Native methods can never be rewired
* or unregistered.
*/
/*
* The function with the long JNI name. This is the one that calls
* _bcResolveNative() and then calls the implementation.
*/
Function fn = new FunctionBuilder(longName, nativeFunctionType).linkage(weak).build();
Global g = new Global(Symbols.nativeMethodPtrSymbol(targetInternalName, methodName, methodDesc), new NullConstant(I8_PTR));
mb.addGlobal(g);
FunctionRef ldcFn = FunctionBuilder.ldcInternal(targetInternalName).ref();
Value theClass = call(fn, ldcFn, fn.getParameterRef(0));
Value implI8Ptr = call(fn, BC_RESOLVE_NATIVE, fn.getParameterRef(0), theClass, mb.getString(methodName), mb.getString(methodDesc), mb.getString(shortName), mb.getString(longName), g.ref());
Variable nullTest = fn.newVariable(I1);
fn.add(new Icmp(nullTest, Condition.ne, implI8Ptr, new NullConstant(I8_PTR)));
Label trueLabel = new Label();
Label falseLabel = new Label();
fn.add(new Br(nullTest.ref(), fn.newBasicBlockRef(trueLabel), fn.newBasicBlockRef(falseLabel)));
fn.newBasicBlock(falseLabel);
if (fn.getType().getReturnType() instanceof IntegerType) {
fn.add(new Ret(new IntegerConstant(0, (IntegerType) fn.getType().getReturnType())));
} else if (fn.getType().getReturnType() instanceof FloatingPointType) {
fn.add(new Ret(new FloatingPointConstant(0.0, (FloatingPointType) fn.getType().getReturnType())));
} else if (fn.getType().getReturnType() instanceof PointerType) {
fn.add(new Ret(new NullConstant((PointerType) fn.getType().getReturnType())));
} else {
fn.add(new Ret());
}
fn.newBasicBlock(trueLabel);
Variable impl = fn.newVariable(nativeFunctionType);
fn.add(new Bitcast(impl, implI8Ptr, impl.getType()));
Value result = call(fn, impl.ref(), fn.getParameterRefs());
fn.add(new Ret(result));
mb.addFunction(fn);
FunctionRef targetFn = fn.ref();
if (!isLongNativeFunctionNameRequired(method)) {
/*
* Generate a function with the short JNI name. This just calls the
* function with the long name.
*/
Function fnShort = new FunctionBuilder(shortName, nativeFunctionType).linkage(weak).build();
Value resultInner = call(fnShort, fn.ref(), fnShort.getParameterRefs());
fnShort.add(new Ret(resultInner));
mb.addFunction(fnShort);
targetFn = fnShort.ref();
}
return targetFn;
}
use of org.robovm.compiler.llvm.Label in project robovm by robovm.
the class MethodCompiler method if_.
private void if_(IfStmt stmt) {
ConditionExpr condition = (ConditionExpr) stmt.getCondition();
Value op1 = immediate(stmt, (Immediate) condition.getOp1());
Value op2 = immediate(stmt, (Immediate) condition.getOp2());
Icmp.Condition c = null;
if (condition instanceof EqExpr) {
c = Icmp.Condition.eq;
} else if (condition instanceof NeExpr) {
c = Icmp.Condition.ne;
} else if (condition instanceof GtExpr) {
c = Icmp.Condition.sgt;
} else if (condition instanceof LtExpr) {
c = Icmp.Condition.slt;
} else if (condition instanceof GeExpr) {
c = Icmp.Condition.sge;
} else if (condition instanceof LeExpr) {
c = Icmp.Condition.sle;
}
Variable result = function.newVariable(Type.I1);
function.add(new Icmp(result, c, op1, op2)).attach(stmt);
Unit nextUnit = sootMethod.getActiveBody().getUnits().getSuccOf(stmt);
function.add(new Br(new VariableRef(result), function.newBasicBlockRef(new Label(stmt.getTarget())), function.newBasicBlockRef(new Label(nextUnit)))).attach(stmt);
}
use of org.robovm.compiler.llvm.Label in project robovm by robovm.
the class AbstractMethodCompiler method compileSynchronizedWrapper.
private void compileSynchronizedWrapper(ModuleBuilder moduleBuilder, SootMethod method) {
String targetName = Symbols.methodSymbol(method);
Function syncFn = FunctionBuilder.synchronizedWrapper(method);
moduleBuilder.addFunction(syncFn);
FunctionType functionType = syncFn.getType();
FunctionRef target = new FunctionRef(targetName, functionType);
Value monitor = null;
if (method.isStatic()) {
FunctionRef fn = FunctionBuilder.ldcInternal(sootMethod.getDeclaringClass()).ref();
monitor = call(syncFn, fn, syncFn.getParameterRef(0));
} else {
monitor = syncFn.getParameterRef(1);
}
call(syncFn, MONITORENTER, syncFn.getParameterRef(0), monitor);
BasicBlockRef bbSuccess = syncFn.newBasicBlockRef(new Label("success"));
BasicBlockRef bbFailure = syncFn.newBasicBlockRef(new Label("failure"));
trycatchAllEnter(syncFn, bbSuccess, bbFailure);
syncFn.newBasicBlock(bbSuccess.getLabel());
Value result = call(syncFn, target, syncFn.getParameterRefs());
trycatchLeave(syncFn);
call(syncFn, MONITOREXIT, syncFn.getParameterRef(0), monitor);
syncFn.add(new Ret(result));
syncFn.newBasicBlock(bbFailure.getLabel());
trycatchLeave(syncFn);
call(syncFn, MONITOREXIT, syncFn.getParameterRef(0), monitor);
call(syncFn, BC_THROW_IF_EXCEPTION_OCCURRED, syncFn.getParameterRef(0));
syncFn.add(new Unreachable());
}
Aggregations