Kaleidoscope tutorial: extern functions failing

Hi all,

I am new to LLVM and have been working through the Kaleidoscope tutorial. Everything is working fine so far except for local externs (as opposed to things like the math functions, which are working). Note that I have seen this bug with the reference code listing, as well as my own code. link to code: https://llvm.org/docs/tutorial/LangImpl05.html#full-code-listing

[c34n10 kaleidoscope] ./toy

extern sin(x); sin(1);
Read extern:
declare double @sin(double)

Evaluated to 0.841471
extern putchard(x); putchard(120);
Read extern:
declare double @putchard(double)

Failure value returned from cantFail wrapped call
UNREACHABLE executed at ~/project/llvm/include/llvm/Support/Error.h:732!
Aborted (core dumped)

sin is, of course, defined in libm. 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 (on the cantFail line)

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. I have run through GDB with both the sin and putchard examples, to try and see where they are diverging. I’m not totally sure, but I think the divergence might be happening on line 347 of RuntimeDyld.cpp:

if (auto IOrErr = processRelocationRef(SectionID, I, Obj, LocalSections, Stubs))

That is, in the sin example, this expression is false; in the putchard example, it is true. However there may be something earlier on that I missed – there were a few thousand lines of GDB logging to diff through.

It appears not to be an issue with the function itself, nor the compilation/link process: from within GDB, I can successfully run call putchard(120), so the symbol is definitely being included in the executable. Just for some reason the JIT can’t find it.

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

Please let me know if I can provide any additional code or debug information. I don’t know a ton about LLVM so am a bit lost as to where to go from here.

(Note: I also have posted this question on the LLVM IRC channel, and on Stack.)

Thank you so much! I’m very excited to start working with LLVM and have just been stuck on this issue for a couple of days.

Best,
Eli Baum
eli.baum@yale.edu

Hi Eli,

Could you replace this code:

double (FP)() = (double ()())(intptr_t)cantFail(ExprSymbol.getAddress());

with:

double (FP)() = nullptr;
if (auto ExprAddr = ExprSymbol.getAddress())
FP = (double(
)())*ExprAddr;
else {
logAllUnhandledErrors(ExprAddr.takeError(), llvm::errs(), “kaleidoscope error:”);
exit(1);
}

Then reproduce the error?

That should allow us to log the error that RuntimeDyld is returning from processRelocationRef. I guess this will be an unimplemented relocation on Windows. It will be helpful to know which one it is.

Cheers,
Lang.

Hi Lang,

Here you go:

[c34n09 kaleidoscope] ./kld
kaleidoscope interpreter

extern putchard(x); putchard(120);
kaleidoscope error:Symbols not found: { putchard }
pure virtual method called
terminate called without an active exception
Aborted (core dumped)

Also, I’m on Linux (RHEL 7.4). I did see in a source file some kind of Windows extern issue, but that’s not relevant here… :confused:

Thanks so much for your help,
Eli