Search in sources :

Example 1 with LLVMIRBuilder

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;
}
Also used : LLVMBasicBlockRef(com.oracle.svm.shadowed.org.bytedeco.llvm.LLVM.LLVMBasicBlockRef) LLVMIRBuilder(com.oracle.svm.core.graal.llvm.util.LLVMIRBuilder) LLVMValueRef(com.oracle.svm.shadowed.org.bytedeco.llvm.LLVM.LLVMValueRef) LLVMTypeRef(com.oracle.svm.shadowed.org.bytedeco.llvm.LLVM.LLVMTypeRef) InlineAssemblyConstraint(com.oracle.svm.core.graal.llvm.util.LLVMIRBuilder.InlineAssemblyConstraint)

Aggregations

LLVMIRBuilder (com.oracle.svm.core.graal.llvm.util.LLVMIRBuilder)1 InlineAssemblyConstraint (com.oracle.svm.core.graal.llvm.util.LLVMIRBuilder.InlineAssemblyConstraint)1 LLVMBasicBlockRef (com.oracle.svm.shadowed.org.bytedeco.llvm.LLVM.LLVMBasicBlockRef)1 LLVMTypeRef (com.oracle.svm.shadowed.org.bytedeco.llvm.LLVM.LLVMTypeRef)1 LLVMValueRef (com.oracle.svm.shadowed.org.bytedeco.llvm.LLVM.LLVMValueRef)1