<div dir="ltr">+Lang for all your ORC related inquiries</div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, May 17, 2016 at 12:13 PM, Larry Gritz via llvm-dev <span dir="ltr"><<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">When using ORC JIT, I'm having trouble with external function resolution (that is, of a function defined in the app, with C linkage).<br>
<br>
I add a declaration for the function to my IR, and when I use MCJIT, it finds it and all is well, But when I use ORC JIT (I *think* correctly, at least it closely matches what I see in the tutorial), I get an LLVM error, "Program used external function 'sqr' which could not be resolved."<br>
<br>
(Excuse my coming to the ORC party late, I've been stuck on an older LLVM for my DSL, and am only now jumping forward several versions at once, with some growing pains.)<br>
<br>
I've boiled it down to the minimal example below. When I build with orc=0, thus using MCJIT, it works fine and I get the expected output. When I build with orc=1, it fails as I described.<br>
<br>
I'm having this trouble with LLVM 3.7 and 3.8, on both Linux and OSX.<br>
<br>
I figure I'm probably just getting some part of the magic incantation wrong. Can anybody help a poor guy out and spot the error of my ways?<br>
<br>
-----<br>
<br>
#include <llvm/ADT/STLExtras.h><br>
#include <llvm/Bitcode/ReaderWriter.h><br>
#include <llvm/ExecutionEngine/ExecutionEngine.h><br>
#include <llvm/ExecutionEngine/Orc/CompileUtils.h><br>
#include <llvm/ExecutionEngine/RuntimeDyld.h><br>
#include <llvm/ExecutionEngine/Orc/IRCompileLayer.h><br>
#include <llvm/ExecutionEngine/Orc/LambdaResolver.h><br>
#include <llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h><br>
#include <llvm/IR/DataLayout.h><br>
#include <llvm/IR/IRBuilder.h><br>
#include <llvm/IR/LegacyPassManager.h><br>
#include <llvm/IR/LLVMContext.h><br>
#include <llvm/IR/Mangler.h><br>
#include <llvm/IR/Module.h><br>
#include <llvm/IR/Verifier.h><br>
#include <llvm/Support/TargetSelect.h><br>
#include <llvm/Target/TargetMachine.h><br>
#include <llvm/Transforms/IPO.h><br>
#include <llvm/Transforms/IPO/PassManagerBuilder.h><br>
#include <llvm/Transforms/Scalar.h><br>
#include <llvm/Transforms/Utils/UnifyFunctionExitNodes.h><br>
<br>
template <typename T><br>
inline std::vector<T> singletonSet (T t)<br>
{<br>
    std::vector<T> Vec;<br>
    Vec.push_back(std::move(t));<br>
    return Vec;<br>
}<br>
<br>
<br>
///<br>
/// THIS is the function I want my IR to call<br>
///<br>
extern "C" {<br>
float sqr (float x) { return x*x; }<br>
}<br>
<br>
<br>
void<br>
simple ()<br>
{<br>
    llvm::InitializeAllTargets();<br>
    llvm::InitializeAllTargetMCs();<br>
    llvm::InitializeAllAsmPrinters();<br>
    llvm::InitializeAllAsmParsers();<br>
    llvm::LLVMContext Context;<br>
    std::unique_ptr<llvm::TargetMachine> TM (llvm::EngineBuilder().selectTarget());<br>
    std::unique_ptr<llvm::DataLayout> DL;<br>
    DL.reset (new llvm::DataLayout (TM->createDataLayout()));<br>
    std::unique_ptr<llvm::ExecutionEngine> EE;<br>
    typedef llvm::orc::ObjectLinkingLayer<> ObjLayerT;<br>
    typedef llvm::orc::IRCompileLayer<ObjLayerT> CompileLayerT;<br>
    typedef CompileLayerT::ModuleSetHandleT ModuleHandleT;<br>
    ObjLayerT Objlayer;<br>
    CompileLayerT Compilelayer (Objlayer, llvm::orc::SimpleCompiler(*TM));<br>
    std::unique_ptr<llvm::Module> M (new llvm::Module("module", Context));<br>
    M->setDataLayout (*DL);<br>
<br>
    // Declare stub for external function sqr<br>
    auto type_float = llvm::Type::getFloatTy (Context);<br>
    llvm::Type* one_float[] = { type_float };<br>
    llvm::FunctionType *functype_ff = llvm::FunctionType::get (type_float, one_float, false);<br>
    llvm::Function::Create (functype_ff, llvm::Function::ExternalLinkage,<br>
                            "sqr", M.get());<br>
<br>
    // Create myfunc and generate its IR, which just calls sqr on its argument<br>
    llvm::Function *myfunc = llvm::Function::Create (functype_ff,<br>
                                                     llvm::Function::ExternalLinkage,<br>
                                                     "myfunc", M.get());<br>
    llvm::IRBuilder<> builder (Context);<br>
    auto block = llvm::BasicBlock::Create (Context, "", myfunc);<br>
    builder.SetInsertPoint (block);<br>
    llvm::Value *a = llvm::cast<llvm::Value>(myfunc->arg_begin());<br>
    llvm::Value *asq = builder.CreateCall (M->getFunction ("sqr"), a);<br>
    builder.CreateRet (asq);<br>
<br>
    // Set up compilation<br>
    if (orc) {<br>
        auto Resolver = llvm::orc::createLambdaResolver(<br>
            // External lookup functor<br>
            [&](const std::string &name) {<br>
                if (auto Sym = Compilelayer.findSymbol(name, true))<br>
                    return llvm::RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());<br>
                // If not found as a symbol, look up in current process.<br>
                // Why doesn't this work?<br>
                if (auto Addr = llvm::RTDyldMemoryManager::getSymbolAddressInProcess(name))<br>
                    return llvm::RuntimeDyld::SymbolInfo(Addr, llvm::JITSymbolFlags::Exported);<br>
                return llvm::RuntimeDyld::SymbolInfo(nullptr);<br>
            },<br>
            // Dylib lookup functor<br>
            [&](const std::string &name) { return nullptr; }<br>
        );<br>
        Compilelayer.addModuleSet (singletonSet(std::move(M)),<br>
                                   llvm::make_unique<llvm::SectionMemoryManager>(),<br>
                                   std::move(Resolver));<br>
    } else {<br>
        // MCJIT<br>
        std::string engine_errors;<br>
        llvm::EngineBuilder engine_builder (std::move(M));<br>
        engine_builder.setEngineKind (llvm::EngineKind::JIT)<br>
                      .setOptLevel (llvm::CodeGenOpt::Default) // Aggressive?<br>
                      .setErrorStr (&engine_errors);<br>
        EE.reset (engine_builder.create());<br>
        EE->finalizeObject ();<br>
    }<br>
<br>
    // Ask for a callable function<br>
    typedef float (*FuncFloatFloat)(float);<br>
    FuncFloatFloat my_executable_function = NULL;<br>
    if (orc) {<br>
        auto ExprSymbol = Compilelayer.findSymbol ("myfunc", true);<br>
        my_executable_function = (FuncFloatFloat) ExprSymbol.getAddress ();<br>
    } else {<br>
        my_executable_function = (FuncFloatFloat) EE->getFunctionAddress ("myfunc");<br>
    }<br>
<br>
    assert (my_executable_function);<br>
    printf ("myfunc(42.0f) = %g\n", (*my_executable_function)(42.0f));<br>
}<br>
<br>
<br>
<br>
--<br>
Larry Gritz<br>
<a href="mailto:lg@larrygritz.com">lg@larrygritz.com</a><br>
<br>
<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div><br></div>