LLVM 万花筒教程在本地外部失败
LLVM Kaleidoscope tutorial failing on local extern
我正在完成 LLVM Kaleidoscope tutorial。除了 local externs(与数学函数之类的东西相反)外,一切都运行良好。
[c34n10 kaleidoscope] ./toy
ready> extern sin(x); sin(1);
ready> Read extern:
declare double @sin(double)
ready> ready> Evaluated to 0.841471
ready> extern putchard(x); putchard(120);
ready> Read extern:
declare double @putchard(double)
ready> ready> Failure value returned from cantFail wrapped call
UNREACHABLE executed at /gpfs/loomis/project/fas/manohar/emb99/llvm/include/llvm/Support/Error.h:732!
Aborted (core dumped)
根据教程,putchard
在我的代码中声明为
/// putchard - putchar that takes a double and returns 0.
extern "C" DLLEXPORT double putchard(double X) {
fputc((char)X, stderr);
return 0;
}
网上其他帖子说这个问题可能是因为没有用-rdynamic
编译造成的,但我是。
实际错误发生在以下代码
auto ExprSymbol = TheJIT->findSymbol("__anon_expr");
assert(ExprSymbol && "Function not found");
// cast to double-returning function
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
fprintf(stderr, "Evaluated to %f\n", FP());
并且对 GDB 的一些调查显示 ExprSymbol.getAddress()
的 hasError
标志为真,这就是 cantFail
失败的原因。至于为什么要设置那个flag,我一头雾水。
这似乎不是函数本身的问题:在 GDB 中,我可以成功 运行 call putchard(120)
,因此该符号肯定存在于可执行文件中。
最后,我的 makefile 看起来像
LIBS=core orcjit native analysis executionengine instcombine object runtimedyld scalaropts support
FLAGS=`llvm-config --cxxflags --ldflags --system-libs --libs $(LIBS)`
%: %.cpp
clang++ -v -g3 -O0 $^ -o $@ $(FLAGS) -rdynamic
我 运行 在 LLVM 8 中遇到了完全相同的问题。
问题是符号解析器没有尝试在本地进程的地址中找到请求的符号,并且 Expected<T>
需要强制检查错误。
我稍微改变了 KaleidoscopeJIT.h
来克服它。
用这个替换 KaleidoscopeJIT 的构造函数:
KaleidoscopeJIT()
: Resolver(createLegacyLookupResolver(
ES,
[this](const std::string &Name) {
auto symbol = ObjectLayer.findSymbol(Name, true);
if (!symbol)
{
if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name))
return JITSymbol(SymAddr, JITSymbolFlags::Exported);
}
return symbol;
},
[](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })),
TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
ObjectLayer(ES,
[this](VModuleKey) {
return ObjLayerT::Resources{
std::make_shared<SectionMemoryManager>(), Resolver};
}),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
}
唯一的变化是,如果在调用ObjectLayer.findSymbol()
后没有找到符号,它将转向RTDyldMemoryManager::getSymbolAddressInProcess()
寻找并创建JITSymbol对象。
我正在完成 LLVM Kaleidoscope tutorial。除了 local externs(与数学函数之类的东西相反)外,一切都运行良好。
[c34n10 kaleidoscope] ./toy
ready> extern sin(x); sin(1);
ready> Read extern:
declare double @sin(double)
ready> ready> Evaluated to 0.841471
ready> extern putchard(x); putchard(120);
ready> Read extern:
declare double @putchard(double)
ready> ready> Failure value returned from cantFail wrapped call
UNREACHABLE executed at /gpfs/loomis/project/fas/manohar/emb99/llvm/include/llvm/Support/Error.h:732!
Aborted (core dumped)
根据教程,putchard
在我的代码中声明为
/// putchard - putchar that takes a double and returns 0.
extern "C" DLLEXPORT double putchard(double X) {
fputc((char)X, stderr);
return 0;
}
网上其他帖子说这个问题可能是因为没有用-rdynamic
编译造成的,但我是。
实际错误发生在以下代码
auto ExprSymbol = TheJIT->findSymbol("__anon_expr");
assert(ExprSymbol && "Function not found");
// cast to double-returning function
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
fprintf(stderr, "Evaluated to %f\n", FP());
并且对 GDB 的一些调查显示 ExprSymbol.getAddress()
的 hasError
标志为真,这就是 cantFail
失败的原因。至于为什么要设置那个flag,我一头雾水。
这似乎不是函数本身的问题:在 GDB 中,我可以成功 运行 call putchard(120)
,因此该符号肯定存在于可执行文件中。
最后,我的 makefile 看起来像
LIBS=core orcjit native analysis executionengine instcombine object runtimedyld scalaropts support
FLAGS=`llvm-config --cxxflags --ldflags --system-libs --libs $(LIBS)`
%: %.cpp
clang++ -v -g3 -O0 $^ -o $@ $(FLAGS) -rdynamic
我 运行 在 LLVM 8 中遇到了完全相同的问题。
问题是符号解析器没有尝试在本地进程的地址中找到请求的符号,并且 Expected<T>
需要强制检查错误。
我稍微改变了 KaleidoscopeJIT.h
来克服它。
用这个替换 KaleidoscopeJIT 的构造函数:
KaleidoscopeJIT()
: Resolver(createLegacyLookupResolver(
ES,
[this](const std::string &Name) {
auto symbol = ObjectLayer.findSymbol(Name, true);
if (!symbol)
{
if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name))
return JITSymbol(SymAddr, JITSymbolFlags::Exported);
}
return symbol;
},
[](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })),
TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
ObjectLayer(ES,
[this](VModuleKey) {
return ObjLayerT::Resources{
std::make_shared<SectionMemoryManager>(), Resolver};
}),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
}
唯一的变化是,如果在调用ObjectLayer.findSymbol()
后没有找到符号,它将转向RTDyldMemoryManager::getSymbolAddressInProcess()
寻找并创建JITSymbol对象。