Thursday, July 20, 2017
This time, I think I won't give up. I must repair this code, I'm really annoyed not to be able to run Tao3D anymore except with completely outdated versions of LLVM.
Activating LLVM traces in the compiler, I see a function that looks perfectly normal:
define internal %Tree* @xl_eval(%1*, %Tree*) { allocas: %result = alloca %Tree* store %Tree* %1, %Tree** %result %2 = load i32, i32* inttoptr (i64 4314967428 to i32*) %3 = add i32 %2, 1 store i32 %3, i32* inttoptr (i64 4314967428 to i32*) %stackCheck = icmp ugt i32 %3, 1000 br i1 %stackCheck, label %overflow, label %entryentry: ; preds = %allocas br label %exit
exit: ; preds = %overflow, %entry %4 = load i32, i32* inttoptr (i64 4314967428 to i32*) %5 = sub i32 %4, 1 store i32 %5, i32* inttoptr (i64 4314967428 to i32*) %retval = load %Tree*, %Tree** %result ret %Tree* %retval
overflow: ; preds = %allocas %6 = load %Tree*, %Tree** %result %7 = call %Tree* @xl_stack_overflow(%Tree* %6) br label %exit }
Why would it crash on something that simple?
Found two things in the examples:
(*module)->setDataLayout(runtime->getDataLayout());
and
PM->doInitialization();
The latter got me confused because for some reason createXLFunctionPasses was taking a PassManagerBase instead of a FunctionPassManager, and that base does not have doInitialization.
When there are new things like this, it's very hard to know when they were officially introduced. git blame gives me some history, but that's it.
Now, at least, it does not crash. Now it fails at runtime with:
LLVM ERROR: Target does not support MC emission!
Whaaaat? The thing is called MCJIT, does that not stand for "Machine Code JIT"?
It looks like LLVMInitializeNativeTarget may be the problem. But it's interesting, the post talks about 3.50, and I needed that call at that time. Well, that does not work: the engineBuilder.create() call fails with Unable to find target for this triple (no targets are registered).
Finally figured out that the trick was to add:
InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser(); InitializeNativeTargetDisassembler();
But then, it generates machine code that looks correct, but won't execute. I get a EXC_BAD_ACCESS stepping into the first instruction of my disassembly:
0x101dec000: pushq %r14 0x101dec002: pushq %rbx 0x101dec003: pushq %rax 0x101dec004: movq %rsi, %rbx 0x101dec007: movabsq $0x101576164, %r14 ; imm = 0x101576164 0x101dec011: movl (%r14), %eax 0x101dec014: incl %eax 0x101dec016: movl %eax, (%r14) 0x101dec019: cmpl $0x3e8, %eax ; imm = 0x3E8 0x101dec01e: jbe 0x101dec032
This is the code that increments the recursion stack count check. I cannot use the "Step instruction" si of the debugger on the first instruction. So apparently, I still need something else to tell LLVM that when it generate code, it would be neat to map it in a way that it can actually execute...
More Googling reveals that I apparently need to call finalizeObject on the execution engine. After that, I end up with a good old assert in unresolved_external for symbol xl_stack_overflow.
Added some symbol resolution in unresolved external. After that, the first function works, but the second call to getPointerToFunction returns 0. So that's still not good.
Tried to compile the tutorials, but they don't compile correctly with either LLVM 3.9 or 4.0. This is so crappy.
With clang++, I get:
% clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs ` -O3 -o toy In file included from toy.cpp:1: In file included from /usr/local/Cellar/llvm@3.9/3.9.1_1/include/llvm/ADT/STLExtras.h:20: In file included from /usr/local/Cellar/llvm@3.9/3.9.1_1/bin/../include/c++/v1/algorithm:632: In file included from /usr/local/Cellar/llvm@3.9/3.9.1_1/bin/../include/c++/v1/cstring:61: /usr/local/Cellar/llvm@3.9/3.9.1_1/bin/../include/c++/v1/string.h:61:15: fatal error: 'string.h' file not found #include_next^ 1 error generated.
Interesting, if I use g++ instead of clang++, then I get a different error:
g++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs ` -O3 -o toy In file included from toy.cpp:17: ./../include/KaleidoscopeJIT.h:20:10: fatal error: 'llvm/ExecutionEngine/JITSymbol.h' file not found #include "llvm/ExecutionEngine/JITSymbol.h" ^ 1 error generated.
If I switch to the more modern LLVM 4.0, then I get:
g++ -g toy.cpp `/usr/local/opt/llvm@4/bin/llvm-config --cxxflags --ldflags --system-libs --libs ` -O3 -o toy In file included from toy.cpp:17: ./../include/KaleidoscopeJIT.h:26:10: fatal error: 'llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h' file not found #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" ^ 1 error generated.
The missing RTDyldObjectLinkingLayer.h is precisely the part that I am having trouble with right now.
Looking at this blog, it looks like it's now necessary to create a new module each time a function has been JIT'ed.