Reputation: 1029
I am working through the LLVM Kaleidoscope tutorial. Everything is working fine except for local externs (as opposed to things like the math functions).
[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
is declared in my code, per the tutorial, as
/// putchard - putchar that takes a double and returns 0.
extern "C" DLLEXPORT double putchard(double X) {
fputc((char)X, stderr);
return 0;
}
Other posts online suggest that this issue could be caused by not compiling with -rdynamic
, but I am.
The actual error is occuring with the following code
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());
and some investigation with GDB reveals that the hasError
flag of ExprSymbol.getAddress()
is true, which is why the cantFail
is failing. As to why that flag is set, I'm at a loss.
It appears not to be an issue with the function itself: from within GDB, I can successfully run call putchard(120)
, so the symbol definitely exists in the executable.
Finally, my makefile looks like
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
Upvotes: 2
Views: 694
Reputation: 46
I ran into exactly the same issue in LLVM 8.
The problem is the symbol resolver doesn't try to find the requested symbol in local process's address, and an Expected<T>
requires mandatory checking for errors.
I changed KaleidoscopeJIT.h
a bit to get over it.
Replace the KaleidoscopeJIT's constructor with this one:
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);
}
The only change is, if no symbol is found after calling ObjectLayer.findSymbol()
, it will turn to RTDyldMemoryManager::getSymbolAddressInProcess()
to find and create the JITSymbol object.
Upvotes: 3