use of org.robovm.compiler.llvm.FunctionRef in project robovm by robovm.
the class ClassCompiler method createVTableStruct.
private Constant createVTableStruct() {
VTable vtable = config.getVTableCache().get(sootClass);
String name = Symbols.vtableSymbol(getInternalName(sootClass));
for (VTable.Entry entry : vtable.getEntries()) {
FunctionRef fref = entry.getFunctionRef();
if (fref != null && !mb.hasSymbol(fref.getName())) {
mb.addFunctionDeclaration(new FunctionDeclaration(fref));
}
}
Global vtableStruct = new Global(name, Linkage._private, vtable.getStruct(), true);
mb.addGlobal(vtableStruct);
return new ConstantBitcast(vtableStruct.ref(), I8_PTR);
}
use of org.robovm.compiler.llvm.FunctionRef in project robovm by robovm.
the class ITable method getStruct.
public StructureConstant getStruct(ModuleBuilder mb, SootClass clazz) {
if (clazz.isInterface()) {
throw new IllegalArgumentException("Expected a class got an interface: " + clazz.getName());
}
ArrayConstantBuilder table = new ArrayConstantBuilder(I8_PTR);
for (Entry entry : entries) {
ResolvedEntry resolvedEntry = entry.resolve(clazz);
if (resolvedEntry == null) {
FunctionRef defaultFunctionRef = entry.getFunctionRef();
if (defaultFunctionRef != null) {
if (!mb.hasSymbol(defaultFunctionRef.getName())) {
mb.addFunctionDeclaration(new FunctionDeclaration(defaultFunctionRef));
}
table.add(new ConstantBitcast(defaultFunctionRef, I8_PTR));
} else {
table.add(new ConstantBitcast(BC_ABSTRACT_METHOD_CALLED, I8_PTR));
}
} else if (Modifier.isAbstract(resolvedEntry.getModifiers())) {
table.add(new ConstantBitcast(BC_ABSTRACT_METHOD_CALLED, I8_PTR));
} else if (!Modifier.isPublic(resolvedEntry.getModifiers())) {
table.add(new ConstantBitcast(BC_NON_PUBLIC_METHOD_CALLED, I8_PTR));
} else {
/*
* Found a non-abstract method implementation. Either on the
* class, in one of its super classes or a default method in an
* implemented interface.
*/
FunctionRef functionRef = resolvedEntry.getFunctionRef();
if (!resolvedEntry.declaringClass.equals(clazz.getName())) {
if (!mb.hasSymbol(functionRef.getName())) {
mb.addFunctionDeclaration(new FunctionDeclaration(functionRef));
}
}
table.add(new ConstantBitcast(functionRef, I8_PTR));
}
}
return new StructureConstantBuilder().add(new IntegerConstant((short) entries.length)).add(table.build()).build();
}
use of org.robovm.compiler.llvm.FunctionRef in project robovm by robovm.
the class Intrinsics method getIntrinsic.
public static FunctionRef getIntrinsic(SootMethod currMethod, Stmt stmt, InvokeExpr expr) {
SootMethodRef methodRef = expr.getMethodRef();
FunctionRef fref = SIMPLE_INTRINSICS.get(getInternalName(methodRef.declaringClass()) + "/" + methodRef.name() + getDescriptor(methodRef));
if (fref != null) {
return fref;
}
if (methodRef.name().startsWith("memmove") && "org.robovm.rt.VM".equals(methodRef.declaringClass().getName())) {
return new FunctionRef("intrinsics.org_robovm_rt_VM_" + methodRef.name(), new FunctionType(VOID, ENV_PTR, I64, I64, I64));
}
if ("arraycopy".equals(methodRef.name()) && "java.lang.System".equals(methodRef.declaringClass().getName()) && "_getChars".equals(currMethod.getName()) && "java.lang.String".equals(currMethod.getDeclaringClass().getName())) {
return new FunctionRef("intrinsics.java_lang_System_arraycopy_C", new FunctionType(VOID, ENV_PTR, OBJECT_PTR, I32, OBJECT_PTR, I32, I32));
}
return null;
}
use of org.robovm.compiler.llvm.FunctionRef in project robovm by robovm.
the class NativeMethodCompiler method doCompile.
protected Function doCompile(ModuleBuilder moduleBuilder, SootMethod method) {
Function fn = createMethodFunction(method);
moduleBuilder.addFunction(fn);
Value env = fn.getParameterRef(0);
ArrayList<Value> args = new ArrayList<Value>(Arrays.asList(fn.getParameterRefs()));
if (method.isStatic()) {
// Add the current class as second parameter
FunctionRef ldcFn = FunctionBuilder.ldcInternal(sootMethod.getDeclaringClass()).ref();
Value clazz = call(fn, ldcFn, env);
args.add(1, clazz);
}
pushNativeFrame(fn);
FunctionRef targetFn = createNative(moduleBuilder, method);
Value result = call(fn, targetFn, args);
popNativeFrame(fn);
call(fn, BC_THROW_IF_EXCEPTION_OCCURRED, env);
fn.add(new Ret(result));
return fn;
}
use of org.robovm.compiler.llvm.FunctionRef 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;
}
Aggregations