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>
Reasonably Related 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