Hi all, I need to run c++ prgrams using lli. However, I find lli cannot handle the alias instruction correctly. Following is an example: ------------ example.cc ------------- #include <iostream> using namespace std; class cls { public: cls(); ~cls(); }; cls::cls() { cout << "constructor" << endl; }; cls::~cls() { cout << "destructor" << endl; } int main(int argc, char *argv[]) { cls *A = new cls(); delete A; return 0; } ----------- end of file ----------- I compile and run the program by: $ clang++ -emit-llvm -S example.cc -o example.S $ llvm-as example.S -o example.bc $ lli example.bc and get the "Recursive compilation" error output: lli: /home/dongpeng/Program/llvm/lib/ExecutionEngine/JIT/JIT.cpp:467: void llvm::JIT::runJITOnFunctionUnlocked(llvm::Function*, const llvm::MutexGuard&): Assertion `!isAlreadyCodeGenerating && "Error: Recursive compilation detected!"' failed. 0 lli 0x0000000001323d37 llvm::sys::PrintStackTrace(_IO_FILE*) + 38 1 lli 0x0000000001323fbe 2 lli 0x0000000001323a02 3 libpthread.so.0 0x00007fd4c168b210 4 libc.so.6 0x00007fd4c06de1d5 gsignal + 53 5 libc.so.6 0x00007fd4c06e1388 abort + 328 6 libc.so.6 0x00007fd4c06d7252 7 libc.so.6 0x00007fd4c06d7302 8 lli 0x0000000000cf1620 llvm::JIT::runJITOnFunctionUnlocked(llvm::Function*, llvm::MutexGuard const&) + 66 9 lli 0x0000000000cf1a3a llvm::JIT::getPointerToFunction(llvm::Function*) + 694 10 lli 0x00000000010fb64c llvm::ExecutionEngine::getPointerToGlobal(llvm::GlobalValue const*) + 70 11 lli 0x0000000000cfa2f0 12 lli 0x0000000000cfaca3 13 lli 0x00000000008c9368 14 lli 0x0000000000d6a9e1 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) + 95 15 lli 0x000000000129a53f llvm::FPPassManager::runOnFunction(llvm::Function&) + 385 16 lli 0x000000000129a286 llvm::legacy::FunctionPassManagerImpl::run(llvm::Function&) + 84 17 lli 0x0000000001299e5e llvm::legacy::FunctionPassManager::run(llvm::Function&) + 180 18 lli 0x0000000000cf175c llvm::JIT::jitTheFunction(llvm::Function*, llvm::MutexGuard const&) + 72 19 lli 0x0000000000cf1637 llvm::JIT::runJITOnFunctionUnlocked(llvm::Function*, llvm::MutexGuard const&) + 89 20 lli 0x0000000000cf1a3a llvm::JIT::getPointerToFunction(llvm::Function*) + 694 21 lli 0x0000000000817815 main + 4732 22 libc.so.6 0x00007fd4c06ca995 __libc_start_main + 245 23 lli 0x000000000080d479 Stack dump: 0. Program arguments: lli example.bc 1. Running pass 'X86 Machine Code Emitter' on function '@main' Aborted I look into the problem and find that it is caused by the alias instructions: @_ZN3clsC1Ev = alias void (%class.cls*)* @_ZN3clsC2Ev @_ZN3clsD1Ev = alias void (%class.cls*)* @_ZN3clsD2Ev The first alias is for the constructor and the other one is for the destructor. When finishing JIT the main function, JITEmitter needs to resolve all the names in main. When it is trying to resolve the alias name @_ZN3clsC1Ev, the following code in JITEmitter.cpp will go to resolve and JIT the original name of the alias name. In my case, they are @_ZN3clsC2Ev and @_ZN3clsD2Ev. This procedure will cause a recursive compilation error. ---------------- lib/ExecutionEngine/JIT/JITEmitter.cpp ------------------------ void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference, bool MayNeedFarStub) { if (GlobalVariable *GV dyn_cast<GlobalVariable>(V)) return TheJIT->getOrEmitGlobalVariable(GV); if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false)); One possible solution is to let JITEmitter emit a stub for the name like following: @@ -687,8 +687,19 @@ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) return TheJIT->getOrEmitGlobalVariable(GV); - if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) - return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false)); + if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) { + Function *F const_cast<Function*>(dyn_cast<Function>(GA->resolveAliasedGlobal(false))); + if (F == NULL) { + return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false)); + } else { + void *FnStub = Resolver.getLazyFunctionStubIfAvailable(F); + if (FnStub) + return FnStub; + else + return Resolver.getLazyFunctionStub(F); + } + } + // If we have already compiled the function, return a pointer to its body. Function *F = cast<Function>(V); Attached is the patch. I am not sure it is the correct way to solve the problem. Any comments are appreciated. Thanks for your help! Sincerely, Dongpeng -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140321/ae8cbe6b/attachment.html> -------------- next part -------------- A non-text attachment was scrubbed... Name: JITEmitter.patch Type: application/octet-stream Size: 972 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140321/ae8cbe6b/attachment.obj>
Hi Dongpeng, You probably want to post patches to the llvm-commits list rather than llvmdev. That said:> I need to run c++ prgrams using lli. However, I find lli cannot handle the > alias instruction correctly. Following is an example:The backtrace indicates you're using the old JIT, which we're trying our hardest to get rid of completely. Its replacement is called MCJIT and seems to support your code already (at least on my amd64 Linux): $ lli -use-mcjit example.bc constructor destructor Longer term, you almost certainly want to look into that. If MCJIT is missing features you need, we'd like to know about it so that they can be implemented. Cheers. Tim.
Thanks for your response, Tim! I have posted the patch to the commits mailing list. I also tried to use mcjit however the error came out as: LLVM ERROR: Program used external function '__dso_handle' which could not be resolved! Am I missing some libraries? Thanks,Dongpeng On Fri, Mar 21, 2014 03:19 PM, Tim Northover <t.p.northover at gmail.com> wrote:>Hi Dongpeng,> >You probably want to post patches to the llvm-commits list rather than >llvmdev. That said: > >> I need to run c++ prgrams using lli. However, I find lli cannot handle the >> alias instruction correctly. Following is an example: > >The backtrace indicates you're using the old JIT, which we're trying >our hardest to get rid of completely. Its replacement is called MCJIT >and seems to support your code already (at least on my amd64 Linux): > >$ lli -use-mcjit example.bc >constructor >destructor > >Longer term, you almost certainly want to look into that. If MCJIT is >missing features you need, we'd like to know about it so that they can >be implemented. > >Cheers. > >Tim. > > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140324/3404371d/attachment.html>
Hey, you might want to take a look at this bug report: Bug 12666 – Hitting recursive JIT assert w/ aliases http://llvm.org/bugs/show_bug.cgi?id=12666 Best regards, Johannes On 03/21, Dongpeng Xu wrote:> Hi all, > > > I need to run c++ prgrams using lli. > However, I find lli cannot handle the alias instruction correctly. Following is > an example: > > > ------------ example.cc > ------------- > > > #include > <iostream> > using namespace std; > > > class > cls { > public: > cls(); > > ~cls(); > }; > > > cls::cls() { > > cout << "constructor" << > endl; > }; > > > cls::~cls() { > > cout << "destructor" << > endl; > } > > > int main(int argc, char > *argv[]) > { > cls *A = new > cls(); > delete A; > return > 0; > } > > > ----------- end of file > ----------- > > > I compile and run the program > by: > > > $ clang++ -emit-llvm -S example.cc -o > example.S > $ llvm-as example.S -o example.bc > $ lli > example.bc > > > and get the "Recursive compilation" error > output: > > > lli: > /home/dongpeng/Program/llvm/lib/ExecutionEngine/JIT/JIT.cpp:467: void > llvm::JIT::runJITOnFunctionUnlocked(llvm::Function*, const > llvm::MutexGuard&): Assertion `!isAlreadyCodeGenerating && "Error: > Recursive compilation detected!"' failed. > 0 lli > 0x0000000001323d37 > llvm::sys::PrintStackTrace(_IO_FILE*) + 38 > 1 lli > 0x0000000001323fbe > 2 lli > 0x0000000001323a02 > 3 > libpthread.so.0 0x00007fd4c168b210 > 4 libc.so.6 > 0x00007fd4c06de1d5 gsignal + 53 > 5 libc.so.6 > 0x00007fd4c06e1388 abort + 328 > 6 libc.so.6 > 0x00007fd4c06d7252 > 7 libc.so.6 > 0x00007fd4c06d7302 > 8 lli > 0x0000000000cf1620 > llvm::JIT::runJITOnFunctionUnlocked(llvm::Function*, llvm::MutexGuard > const&) + 66 > 9 lli > 0x0000000000cf1a3a llvm::JIT::getPointerToFunction(llvm::Function*) + > 694 > 10 lli > 0x00000000010fb64c llvm::ExecutionEngine::getPointerToGlobal(llvm::GlobalValue > const*) + 70 > 11 lli > 0x0000000000cfa2f0 > 12 lli > 0x0000000000cfaca3 > 13 lli > 0x00000000008c9368 > 14 lli > 0x0000000000d6a9e1 > llvm::MachineFunctionPass::runOnFunction(llvm::Function&) + 95 > 15 > lli 0x000000000129a53f > llvm::FPPassManager::runOnFunction(llvm::Function&) + 385 > 16 lli > 0x000000000129a286 > llvm::legacy::FunctionPassManagerImpl::run(llvm::Function&) + > 84 > 17 lli > 0x0000000001299e5e llvm::legacy::FunctionPassManager::run(llvm::Function&) > + 180 > 18 lli > 0x0000000000cf175c llvm::JIT::jitTheFunction(llvm::Function*, llvm::MutexGuard > const&) + 72 > 19 lli > 0x0000000000cf1637 llvm::JIT::runJITOnFunctionUnlocked(llvm::Function*, > llvm::MutexGuard const&) + 89 > 20 lli > 0x0000000000cf1a3a > llvm::JIT::getPointerToFunction(llvm::Function*) + 694 > 21 lli > 0x0000000000817815 main + 4732 > 22 > libc.so.6 0x00007fd4c06ca995 __libc_start_main + > 245 > 23 lli > 0x000000000080d479 > Stack dump: > 0. Program > arguments: lli example.bc > 1. Running pass 'X86 > Machine Code Emitter' on function > '@main' > Aborted > > > > > I look into > the problem and find that it is caused by the alias > instructions: > > > @_ZN3clsC1Ev = alias void (%class.cls*)* > @_ZN3clsC2Ev > @_ZN3clsD1Ev = alias void (%class.cls*)* > @_ZN3clsD2Ev > > > The first alias is for the constructor > and the other one is for the destructor. When finishing JIT the main function, > JITEmitter needs to resolve all the names in main. When it is trying to resolve > the alias name @_ZN3clsC1Ev, the following code in JITEmitter.cpp will go to > resolve and JIT the original name of the alias name. In my case, they are > @_ZN3clsC2Ev and @_ZN3clsD2Ev. This procedure will cause a recursive > compilation error. > > > ---------------- > lib/ExecutionEngine/JIT/JITEmitter.cpp > ------------------------ > > > void > *JITEmitter::getPointerToGlobal(GlobalValue *V, void > *Reference, > > > bool MayNeedFarStub) { > if (GlobalVariable *GV > dyn_cast<GlobalVariable>(V)) > return > TheJIT->getOrEmitGlobalVariable(GV); > > > if > (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) > > return > TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false)); > > > > > One possible solution is to let JITEmitter emit a stub for the name like > following: > > > @@ -687,8 +687,19 @@ > if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) > return TheJIT->getOrEmitGlobalVariable(GV); > > - if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) > - return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false)); > + if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) { > + Function *F > const_cast<Function*>(dyn_cast<Function>(GA->resolveAliasedGlobal(false))); > + if (F == NULL) { > + return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false)); > + } else { > + void *FnStub = Resolver.getLazyFunctionStubIfAvailable(F); > + if (FnStub) > + return FnStub; > + else > + return Resolver.getLazyFunctionStub(F); > + } > + } > + > > // If we have already compiled the function, return a pointer to its body. > Function *F = cast<Function>(V); > > > Attached is the patch. I am not sure it is the correct way to solve the > problem. Any comments are appreciated. Thanks for your help! > > > > > Sincerely, > Dongpeng> _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev-- Johannes Doerfert Researcher / PhD Student Compiler Design Lab (Prof. Hack) Saarland University, Computer Science Building E1.3, Room 4.26 Tel. +49 (0)681 302-57521 : doerfert at cs.uni-saarland.de Fax. +49 (0)681 302-3065 : http://www.cdl.uni-saarland.de/people/doerfert -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 230 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140324/4bc98c96/attachment.sig>
Maybe Matching Threads
- [LLVMdev] Exception handling in JIT
- [LLVMdev] Being able to know the jitted code-size before emitting
- [LLVMdev] Being able to know the jitted code-size before emitting
- [LLVMdev] HowToUseJIT: failed assertion on PPC/Mac OS X
- [LLVMdev] Being able to know the jitted code-size before emitting