> 6. When ExecutionEngine::create was called with parameter > "GVsWithCode" set to its default value of true, I got a segfault when > trying to get a pointer to one of my globals. JIT::getMemoryForGV was > returning NULL in that case. Explicitly passing false for > "GVsWithCode" cleared it up.That's no good. Could you send me a stack trace and explain how you got that to happen? I was the last one to touch that code. In your case, I would definitely set that parameter to false. For some reason, OpenCL requires that code and globals be allocated together contiguously, and because backwards compatibility with them is somehow more important than doing the right thing, that's still the default behavior. See http://llvm.org/bugs/show_bug.cgi?id=4483 . Reid
On Tue, Oct 6, 2009 at 4:15 PM, Reid Kleckner <rnk at mit.edu> wrote:>> 6. When ExecutionEngine::create was called with parameter >> "GVsWithCode" set to its default value of true, I got a segfault when >> trying to get a pointer to one of my globals. JIT::getMemoryForGV was >> returning NULL in that case. Explicitly passing false for >> "GVsWithCode" cleared it up. > > That's no good. Could you send me a stack trace and explain how you > got that to happen? I was the last one to touch that code.Stack trace attached. It's not very informative; it just tells us that it's got a null pointer that it thinks is a pointer to the global, and it's trying to initialize that global. What I did was load a module from a MemoryBuffer, use an ExistingModuleProvider to feed it to the ExecutionEngine, then start looping through its globals and get their addresses so I can refer to their values while compiling another module. The segfault happened on the first one it encountered, a linkonce constant int32. I can try and reduce it for you if you need. The comment above create said that passing true was "unsafe", so I figured it was a known issue and plowed ahead with the upgrade. -------------- next part -------------- #0 0xb7d4cc1c in memcpy () from /lib/i686/cmov/libc.so.6 #1 0x08851ead in StoreIntToMemory (IntVal=@0xbfe685b0, Dst=0x0, StoreBytes=4) at ExecutionEngine.cpp:783 #2 0x08851f7d in llvm::ExecutionEngine::StoreValueToMemory (this=0x97596f8, Val=@0xbfe685a8, Ptr=0x0, Ty=0x970e5f4) at ExecutionEngine.cpp:809 #3 0x88542a8 in llvm::ExecutionEngine::InitializeMemory (this=0x97596f8, Init=0x9732d70, Addr=0x0) at ExecutionEngine.cpp:931 #4 0x0885471c in llvm::ExecutionEngine::EmitGlobalVariable (this=0x97596f8, GV=0x981d7a4) at ExecutionEngine.cpp:1062 #5 0x08855169 in llvm::ExecutionEngine::getPointerToGlobal (this=0x97596f8, GV=0x981d7a4) at ExecutionEngine.cpp:481
On Tue, Oct 6, 2009 at 5:08 PM, Kenneth Uildriks <kennethuil at gmail.com> wrote:> On Tue, Oct 6, 2009 at 4:15 PM, Reid Kleckner <rnk at mit.edu> wrote: >>> 6. When ExecutionEngine::create was called with parameter >>> "GVsWithCode" set to its default value of true, I got a segfault when >>> trying to get a pointer to one of my globals. JIT::getMemoryForGV was >>> returning NULL in that case. Explicitly passing false for >>> "GVsWithCode" cleared it up. >> >> That's no good. Could you send me a stack trace and explain how you >> got that to happen? I was the last one to touch that code. > > Stack trace attached. It's not very informative; it just tells us > that it's got a null pointer that it thinks is a pointer to the > global, and it's trying to initialize that global. > > What I did was load a module from a MemoryBuffer, use an > ExistingModuleProvider to feed it to the ExecutionEngine, then start > looping through its globals and get their addresses so I can refer to > their values while compiling another module. The segfault happened on > the first one it encountered, a linkonce constant int32. > > I can try and reduce it for you if you need. The comment above create > said that passing true was "unsafe", so I figured it was a known issue > and plowed ahead with the upgrade. >Also, the null pointer is coming from a call to JCE->allocateSpace(). This is a virtual function; I'm trying to discover what subclass it is.
On Tue, Oct 6, 2009 at 5:49 PM, Reid Kleckner <rnk at mit.edu> wrote:>> Also, the null pointer is coming from a call to JCE->allocateSpace(). >> This is a virtual function; I'm trying to discover what subclass it >> is. > > So, there's JITEmitter::allocateSpace which overrides > JITCodeEmitter::allocateSpace(), but *most* of the time it just calls > JITCodeEmitter::allocateSpace(). In particular, it does that if the > emitter is already emitting a function (BufferBegin will be non-null). > If there is no current function, it asks the JITMemoryManager for > some space (JITMemoryManager::allocateSpace), which looked broken the > last time I checked, but should work in theory. I can't see any way > that it would return NULL, though. > > Reid >It just occurred to me... in the case where it's failing, the ExecutionEngine was trying to JIT a global, and it had never JITted any functions! I'll work up a small test case, but I think it's relevant since the thing is trying to allocate the globals with the functions.
> > It just occurred to me... in the case where it's failing, the > ExecutionEngine was trying to JIT a global, and it had never JITted > any functions! I'll work up a small test case, but I think it's > relevant since the thing is trying to allocate the globals with the > functions. >That was it! The following small test program crashes in getPointerToGlobal: #include "llvm/Module.h" #include "llvm/Function.h" #include "llvm/InlineAsm.h" #include "llvm/Support/IRBuilder.h" #include "llvm/ModuleProvider.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/Support/raw_os_ostream.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetSelect.h" #include "llvm/ExecutionEngine/JIT.h" #include <assert.h> using namespace llvm; static raw_stdout_ostream raw_cout; int main(int argc, char** argv) { // Test JITting a variable without JITting any functions.' Module* mod = new Module("test", getGlobalContext()); GlobalVariable* gv = cast<GlobalVariable>(mod->getOrInsertGlobal("TestGV", Type::getInt32Ty(getGlobalContext()))); gv->setInitializer(ConstantInt::get( Type::getInt32Ty(getGlobalContext()), 24601)); ModuleProvider* modp = new ExistingModuleProvider(mod); InitializeNativeTarget(); std::string errstring; ExecutionEngine* eeng = ExecutionEngine::create(modp, false, &errstring, CodeGenOpt::Default, true); if ( eeng == NULL ) { raw_cout << errstring << "\n"; exit(-1); } raw_cout << "Fixing to get pointer to global\n"; void* gvp = eeng->getPointerToGlobal(gv); raw_cout << "Got pointer to global\n"; raw_cout << "gv = " << *((int*)gvp) << "\n"; exit(0); }