未找到 LLVM JIT 符号

问题描述 投票:0回答:4

我正在尝试编写一个程序来 JIT 一些代码。 JITTed 代码需要回调正在运行的应用程序以获得运行时支持,并且在实现函数时找不到运行时支持符号。

我尝试遵循万花筒教程。我需要在运行时从一些 IR 生成的代码中调用函数。例如,我想从一些 llvm IR 调用这个函数。

extern "C" void* llvmNewVector() {
    return new vector<int>();
}

根据万花筒教程,它应该在应用程序的运行时声明为 extern“C”。在 LLVM IR 中,我创建了一个函数原型,并且正确生成了 IR(检查我正在执行的函数后没有错误)。

在我看来,需要做更多的事情才能将此函数链接到 jitted 代码,但 Kaleidscope 教程似乎没有这样做。

我的问题是,由于外部符号未解析,因此即时代码无法实现。

以下代码打印“made it here”,但没有进一步说明。

cerr << "made it here." << endl;
auto Sym = ExitOnErr(TheJIT->lookup(name));
NativeCodePtr FP = (NativeCodePtr)Sym.getAddress();
assert(FP && "Failed to find function ");
cerr << "returning jitted function " << name << endl;
return FP;

我确信我做错了什么或遗漏了某些步骤,但我一直无法找到它。

我得到的输出是:

made it here.
JIT session error: Symbols not found: { llvmNewVector }
Failed to materialize symbols: { my_test }

代码是使用 LLVM-9 编译的,带有以下标志:

clang++ -I. -g -I../include/ -std=c++11 -fexceptions -fvisibility=hidden -fno-rtti -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.cpp 

使用以下链接进行链接:

llvm-config --libs
c++ llvm jit
4个回答
4
投票

我遇到了同样的问题,可以通过以下方式解决:

教程中的以下代码行的目标是解析主机进程中的符号,但似乎不起作用。

ES.getMainJITDylib().setGenerator(
    cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess(DL)));

因此,我手动注册了我想要链接的符号,如下所示:

SymbolMap M;
// Register every symbol that can be accessed from the JIT'ed code.
M[Mangle("llvmNewVector")] = JITEvaluatedSymbol(
    pointerToJITTargetAddress(&llvmNewVector), JITSymbolFlags());
}
cantFail(ES.getMainJITDylib().define(absoluteSymbols(M)));

我在上面提到的教程中的两行代码之后添加了此代码。


2
投票

为 clang 添加

-Xlinker --export-dynamic
选项怎么样?

我在教程中遇到了类似的问题。 在我的环境(Ubuntu 20.04)中,

sin
cos
可以解析,但
printd
putchard
(Kaleidscope处理器源代码中定义的函数)不能解析。

编译后,可以在程序的dynamic符号表中看到函数名吗?

objdump -T program | grep llvmNewVector

如果 objdump 中没有

-T
选项(例如 Mac),则情况可能并非如此。 就我而言,
printd
putchard
都不会出现在动态符号表中(但出现在符号表中)。

要将这些函数名称添加到动态符号表中,需要为 clang 传递

-Xlinker --export-dynamic
选项(实际上,该选项传递给 ld),例如(这是教程中的一个),

clang++ -Xlinker --export-dynamic -g toy.cpp `llvm-config --ldflags --system-libs --libs all` -O3 -o toy

编译后,函数名称出现在动态符号表中,并且教程的示例运行良好。


1
投票

这取决于您使用的 llvm 版本。 LLVM 10 有 LLJIT 类,它通过以下方式为我工作

      auto J = ExitOnErr(LLJITBuilder().create());
      auto M = createDemoModule();
    
      auto &dl = J->getDataLayout();
      MangleAndInterner Mangle(J->getExecutionSession(), dl);
      auto &jd = J->getMainJITDylib();
    
      auto s = absoluteSymbols({{ Mangle("printd"), JITEvaluatedSymbol(pointerToJITTargetAddress(&printd), JITSymbolFlags::Exported)}});
      jd.define(s);

printd 函数定义在同一个文件中

extern "C" int32_t printd() {
    std::cout << "calling " << __FUNCTION__ << "...\n";
    return 11;
}

0
投票

对于使用 LLVM-16 的任何人,这里有一个解决方案:

int main() {
    ...

    TheJIT = ExitOnError(llvm::orc::KaleidoscopeJIT::Create());

    auto &jd = TheJIT->getMainJITDylib();
    auto mangle = llvm::orc::MangleAndInterner(jd.getExecutionSession(), TheJIT->getDataLayout());

    auto s = [](llvm::orc::MangleAndInterner interner) {
        llvm::orc::SymbolMap symbolMap;
        symbolMap[interner("putchard")] = {
            llvm::pointerToJITTargetAddress(&putchard),
            llvm::JITSymbolFlags(),
        };
        symbolMap[interner("printd")] = {
            llvm::pointerToJITTargetAddress(&printd),
            llvm::JITSymbolFlags(),
        };
        return llvm::orc::absoluteSymbols(symbolMap);
    }(mangle);

    ExitOnError(jd.define(s));

    
    ...
    MainLoop();
}
© www.soinside.com 2019 - 2024. All rights reserved.