use of com.oracle.svm.core.graal.llvm.util.LLVMIRBuilder in project graal by oracle.
the class LLVMGenerator method createJNIWrapper.
/*
* Calling a native function from Java code requires filling the JavaFrameAnchor with the return
* address of the call. This wrapper allows this by creating an intermediary call frame from
* which the return address can be accessed. The parameters to this wrapper are the anchor, the
* native callee, and the arguments to the callee.
*/
LLVMValueRef createJNIWrapper(LLVMValueRef callee, boolean nativeABI, int numArgs, int anchorIPOffset) {
LLVMTypeRef calleeType = LLVMIRBuilder.getElementType(LLVMIRBuilder.typeOf(callee));
String wrapperName = JNI_WRAPPER_BASE_NAME + LLVMIRBuilder.intrinsicType(calleeType) + (nativeABI ? "_native" : "");
LLVMValueRef transitionWrapper = builder.getNamedFunction(wrapperName);
if (transitionWrapper == null) {
try (LLVMIRBuilder tempBuilder = new LLVMIRBuilder(builder)) {
LLVMTypeRef wrapperType = prependArgumentTypes(calleeType, nativeABI ? 0 : SpecialRegister.count(), tempBuilder.rawPointerType(), LLVMIRBuilder.typeOf(callee));
transitionWrapper = tempBuilder.addFunction(wrapperName, wrapperType);
LLVMIRBuilder.setLinkage(transitionWrapper, LinkageType.LinkOnce);
tempBuilder.setGarbageCollector(transitionWrapper, GCStrategy.CompressedPointers);
tempBuilder.setFunctionAttribute(transitionWrapper, Attribute.NoInline);
LLVMBasicBlockRef block = tempBuilder.appendBasicBlock(transitionWrapper, "main");
tempBuilder.positionAtEnd(block);
LLVMValueRef anchor = LLVMIRBuilder.getParam(transitionWrapper, 0 + (nativeABI ? 0 : SpecialRegister.count()));
LLVMValueRef lastIPAddr = tempBuilder.buildGEP(anchor, tempBuilder.constantInt(anchorIPOffset));
LLVMValueRef callIP = tempBuilder.buildReturnAddress(tempBuilder.constantInt(0));
LLVMValueRef castedLastIPAddr = tempBuilder.buildBitcast(lastIPAddr, tempBuilder.pointerType(tempBuilder.rawPointerType()));
tempBuilder.buildStore(callIP, castedLastIPAddr);
LLVMValueRef[] args = new LLVMValueRef[numArgs];
for (int i = 0; i < numArgs; ++i) {
if (!nativeABI && i < SpecialRegister.count()) {
args[i] = LLVMIRBuilder.getParam(transitionWrapper, i);
} else {
args[i] = LLVMIRBuilder.getParam(transitionWrapper, i + 2);
}
}
LLVMValueRef target = LLVMIRBuilder.getParam(transitionWrapper, 1 + (nativeABI ? 0 : SpecialRegister.count()));
LLVMValueRef ret = tempBuilder.buildCall(target, args);
tempBuilder.setCallSiteAttribute(ret, Attribute.GCLeafFunction);
if (LLVMIRBuilder.isVoidType(LLVMIRBuilder.getReturnType(calleeType))) {
tempBuilder.buildRetVoid();
} else {
tempBuilder.buildRet(ret);
}
}
}
return transitionWrapper;
}
Aggregations