Issue with LLVM JIT (LLJIT)

Viewed 25

I am following a tutorial on making JIT compiler with LLVM (code is shown below and most recent version of LLVM is used). Everything works other than this line (if I comment this function, code compiles):

 return (T)symbol.get().getAddress();

which gives the following error:

JIT.cpp:22:29: error: ‘std::remove_reference_t<llvm::orc::ExecutorAddr> {aka class llvm::orc::ExecutorAddr}’ has no member named ‘getAddress’
 return (T)symbol.get().getAddress();

Code

#pragma once

#include <llvm/ExecutionEngine/Orc/LLJIT.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <memory>
#include <type_traits>

namespace FooLang
{
class JIT
{
private:
std::unique_ptr<llvm::orc::LLJIT> lljit;

public:
JIT(std::unique_ptr<llvm::orc::LLJIT> _lljit) : lljit(std::move(_lljit)) {}

void registerSymbols(
    llvm::function_ref<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)> symbolMap) {
    auto &mainJitDylib = this->lljit->getMainJITDylib();
    llvm::cantFail(mainJitDylib.define(
        absoluteSymbols(symbolMap(llvm::orc::MangleAndInterner(
            mainJitDylib.getExecutionSession(), this->lljit->getDataLayout())))));
}

template <typename T, typename = std::enable_if_t<std::is_pointer<T>::value && std::is_function<std::remove_pointer_t<T>>::value>>
llvm::Expected<T> lookup(const std::string &name)
{
    auto symbol = this->lljit->lookup(name);

    if (!symbol)
    {
        return symbol.takeError();
    }

    return (T)symbol.get().getAddress();
}

template <typename T, typename = std::enable_if_t<std::is_function<T>::value>>
inline llvm::Expected<T *> lookup(const std::string &name)
{
    return this->lookup<T *>(name);
}

static llvm::Expected<JIT> create(std::unique_ptr<llvm::Module> &module, std::unique_ptr<llvm::LLVMContext> &context)
{
    auto lljit = llvm::orc::LLJITBuilder().create();
    auto &jd = lljit.get()->getMainJITDylib();

    jd.addGenerator(llvm::cantFail(llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess('_')));

    if (!lljit)
    {
        return lljit.takeError();
    }

    if (auto err = lljit.get()->addIRModule(llvm::orc::ThreadSafeModule(std::move(module), std::move(context))))
    {
        return std::move(err);
    }

    return JIT(std::move(lljit.get()));
}
};
 } // namespace FooLang

And it is used like following:

int run(IRgen* ir_gen)
{
auto jit = JIT::create(ir_gen->module, ir_gen->llvm_context);

jit->registerSymbols(
    [&](llvm::orc::MangleAndInterner interner) {
        llvm::orc::SymbolMap symbolMap;
        // Add symbols here
        symbolMap[interner("printf")] = llvm::JITEvaluatedSymbol::fromPointer(printf);
        return symbolMap;
    });


auto entry = jit->lookup<int()>("main");
if (!entry)
{
    llvm::errs() << entry.takeError();
    return 1;
}

return entry.get()();
}
1 Answers
Related