On Mon, Jun 22, 2009 at 4:43 PM, Chris Lattner <clattner at apple.com> wrote:> > On Jun 22, 2009, at 2:19 PM, Kasra wrote: > > Hi, > > for some reason I could not get the machine code generator for x86 > working. The interpreter is the only thing that works, is there > anything that I am missing here? > > This recently changed. In your main program, please #include > "llvm/Target/TargetSelect.h" and call InitializeNativeTarget(); before > setting up the execution engine,Actually, you also need to include: #include <llvm/ExecutionEngine/JIT.h> or #include <llvm/ExecutionEngine/Interpreter.h> If not, you can get a segfault. To reproduce, apply: Index: tools/lli/lli.cpp ==================================================================--- tools/lli/lli.cpp (revision 73952) +++ tools/lli/lli.cpp (working copy) @@ -18,8 +18,9 @@ #include "llvm/Type.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ExecutionEngine/Interpreter.h" +//#include "llvm/ExecutionEngine/JIT.h" +//#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" Note that lli compiles OK with the patch. However: [tmp]$ lli test6.bc 0 lli 0x0000000000d91488 1 lli 0x0000000000d91969 2 libpthread.so.0 0x00000034cb20ed30 3 lli 0x0000000000af7c02 llvm::SmallVectorImpl<llvm::ModuleProvider*>::size() const + 12 4 lli 0x0000000000af5bfc llvm::ExecutionEngine::runStaticConstructorsDestructors(bool) + 40 5 lli 0x0000000000772b33 main + 1366 6 libc.so.6 0x00000034ca61e32a __libc_start_main + 250 7 lli 0x0000000000772009 Stack dump: 0. Program arguments: lli test6.bc Segmentation fault I do not quite understand why, but it appears that the constructor of the static variable static struct RegisterJIT { RegisterJIT() { JIT::Register(); } } JITRegistrator; in lib/ExecutionEngine/JIT/JIT.cpp is only called if either JIT.h or Interpreter.h is included. When they are not included, JIT::Register() is not called, and ExecutionEngine::JITCtor and ExecutionEngine::InterpCtor are both NULL, and ExecutionEngine::create() returns NULL. This is not caught by (in lli.cpp): if (!EE && !ErrorMsg.empty()) { std::cerr << argv[0] << ":error creating EE: " << ErrorMsg << "\n"; exit(1); } as ErrorMsg is empty. Then it segfaults line 190. This is quite nasty behavior. I don't know what the proper fix is, but relying on static constructors seems misplaced. And certainly, a missing header should not result in a runtime fault. Thanks, Eric.
On Tue, Jun 23, 2009 at 02:31:36AM -0700, Eric Rannaud wrote:> On Mon, Jun 22, 2009 at 4:43 PM, Chris Lattner <clattner at apple.com> > wrote: > I do not quite understand why, but it appears that the constructor of > the static variable > > static struct RegisterJIT { > RegisterJIT() { JIT::Register(); } > } JITRegistrator; > > in lib/ExecutionEngine/JIT/JIT.cpp is only called if either JIT.h or > Interpreter.h is included. When they are not included, JIT::Register() > is not called, and ExecutionEngine::JITCtor and > ExecutionEngine::InterpCtor are both NULL, and ExecutionEngine::create() > returns NULL. > > ... > > This is quite nasty behavior. I don't know what the proper fix is, but > relying on static constructors seems misplaced. And certainly, a missing > header should not result in a runtime fault.So, at a minimum, JITRegistrator and InterpRegistrator should not have static linkage. But that is still not enough. As they both are in a static library (libLLVMJIT.a and libLLVMInterpreter.a), to appear in the final 'lli' binary all the time, the linker flag --whole-archive needs to be used (see ld(1)). Without the flag, JITRegistrator and InterpRegistrator are only included if the .o they live in (JIT.o and Interpreter.o) are used. This becomes very obscure. I would personally fix this by getting rid of global variable constructors for initialization purposes. Otherwise, I'm not sure where such a linker flag should be added. It would also need to be added to `llvm-config --ldflags`. Thanks, Eric.
Eric Rannaud
2009-Jun-23 19:04 UTC
[LLVMdev] [PATCH] Catch NULL return value of ExecutionEngine::create()
ExecutionEngine::create() can return NULL with an empty error message (admittedly, it did so because of global variable initialization problems). The code currently lets NULL go through if ErrorMsg is empty, and segfaults later. When EE is NULL but ErrorMsg is empty, simply do not try to print it and exit. Index: tools/lli/lli.cpp =================================================================== --- tools/lli/lli.cpp (revision 73978) +++ tools/lli/lli.cpp (working copy) @@ -144,8 +144,11 @@ InitializeNativeTarget(); EE = ExecutionEngine::create(MP, ForceInterpreter, &ErrorMsg, OLvl); - if (!EE && !ErrorMsg.empty()) { - std::cerr << argv[0] << ":error creating EE: " << ErrorMsg << "\n"; + if (!EE) { + if (!ErrorMsg.empty()) + std::cerr << argv[0] << ":error creating EE: " << ErrorMsg << "\n"; + else + std::cerr << argv[0] << ":error creating EE\n"; exit(1); }
Chris Lattner
2009-Jul-07 18:32 UTC
[LLVMdev] [PATCH] Catch NULL return value of ExecutionEngine::create()
On Jun 23, 2009, at 12:04 PM, Eric Rannaud wrote:> ExecutionEngine::create() can return NULL with an empty error message > (admittedly, it did so because of global variable initialization > problems). The code currently lets NULL go through if ErrorMsg is > empty, > and segfaults later. > > When EE is NULL but ErrorMsg is empty, simply do not try to > print it and exit.Nice catch. Please send patches as attachments so that they don't word wrap or get mangled by your mailer. Since it is small, I manually applied this patch here: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20090706/080247.html Thanks! -Chris> > Index: tools/lli/lli.cpp > ==================================================================> --- tools/lli/lli.cpp (revision 73978) > +++ tools/lli/lli.cpp (working copy) > @@ -144,8 +144,11 @@ > InitializeNativeTarget(); > > EE = ExecutionEngine::create(MP, ForceInterpreter, &ErrorMsg, OLvl); > - if (!EE && !ErrorMsg.empty()) { > - std::cerr << argv[0] << ":error creating EE: " << ErrorMsg << > "\n"; > + if (!EE) { > + if (!ErrorMsg.empty()) > + std::cerr << argv[0] << ":error creating EE: " << ErrorMsg << > "\n"; > + else > + std::cerr << argv[0] << ":error creating EE\n"; > exit(1); > } > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev