Bug In Module::getConstantPointerRef ?

I was about to post a bug concerning this, but I thought I'd check with
you folks first. The symptom is a SIGSEGV in my program in the standard
library template for red black trees (bits/stl_tree.h). The crash occurs
as the result of an LLVM Module method, getConstantPointerRef which
looks like:

// Accessor for the underlying GlobalValRefMap...
ConstantPointerRef *Module::getConstantPointerRef(GlobalValue *V){
  // Create ref map lazily on demand...
  if (GVRefMap == 0) GVRefMap = new GlobalValueRefMap();
                                                                                                                                                             
  GlobalValueRefMap::iterator I = GVRefMap->Map.find(V);
  if (I != GVRefMap->Map.end()) return I->second;
                                                                                                                                                             
  ConstantPointerRef *Ref = new ConstantPointerRef(V);
  GVRefMap->Map[V] = Ref;
  return Ref;
}

I have verified that my GlobalValue* parameter is valid. The crash
happens during the call to GVRefMap->Map.find(V). The code looks okay to
me on visual inspection but it does produce a crash.

When I debug it, I get this stack trace:

(gdb) where
#0 0x080b480b in std::_Rb_tree<llvm::GlobalValue*, std::pair<llvm::GlobalValue* const, llvm::ConstantPointerRef*>, std::_Select1st<std::pair<llvm::GlobalValue* const, llvm::ConstantPointerRef*> >, std::less<llvm::GlobalValue*>, std::allocator<std::pair<llvm::GlobalValue* const, llvm::ConstantPointerRef*> > >
     ::find(llvm::GlobalValue* const&) (this=0x4022d36c, __k=@0xbfffcc44) at stl_tree.h:1268
#1 0x080b35bc in std::map<llvm::GlobalValue*, llvm::ConstantPointerRef*, std::less<llvm::GlobalValue*>, std::allocator<std::pair<llvm::GlobalValue* const, llvm::ConstantPointerRef*> > >
    ::find(llvm::GlobalValue* const&) (this=0x4022d36c, __x=@0xbfffcc44) at stl_map.h:468
#2 0x08067d6d in llvm::Module::getConstantPointerRef(llvm::GlobalValue*) (this=0x81d4348, V=0x81d34f8) at /proj/work/llvm/llvm/lib/VMCore/Module.cpp:320
#3 0x08060497 in llvm::ConstantPointerRef::get(llvm::GlobalValue*) (GV=0x81d34f8) at /proj/work/llvm/llvm/lib/VMCore/Constants.cpp:908

Looking deeper, I noticed that the _M_header field of the red black tree
is null:

(gdb) p *GVRefMap
$22 = {Map = {
    _M_t = {<_Rb_tree_base<std::pair<llvm::GlobalValue* const, llvm::ConstantPointerRef*>,std::allocator<std::pair<llvm::GlobalValue* const, llvm::ConstantPointerRef*> > >>
            = {<_Rb_tree_alloc_base<std::pair<llvm::GlobalValue* const, llvm::ConstantPointerRef*>,std::allocator<std::pair<llvm::GlobalValue* const, llvm::ConstantPointerRef*> >,true>>
              = {_M_header = 0x0}, <No data fields>}, _M_node_count = 0,
              _M_key_compare = {<binary_function<llvm::GlobalValue*,llvm::GlobalValue*,bool>> = {<No data fields>}, <No data fields>}}}}

which is what causes the crash. The _Rb_tree::find call
(stl_tree.h:1268) is executing a line of code like this:

_Link_type __x = _M_root(); // Current node.

The _M_root() call is de-referencing the _M_header field.

This could, ostensibly, be a bug in std::_Rb_tree template but it could
also be a usage problem.

Note that the GVRefMap (in Module.cpp) has no constructor and just uses
the default. Presumably the default constructor of the std::map (member
Map) is also called but that constructor doesn't do much (i.e. provide a
value for _M_header).

One other note: this used to work a couple weeks ago. I just did a cvs
update and rebuilt LLVM. My code hasn't changed.

Any thoughts? Anyone seen this?

Reid.

Nothing has really changed in this part of the compiler for a long time,
and I don't think we are abusing std::map's here. Is it possible that
part of your tree is out of sync with the rest of it or something? Maybe
make clean would help?

-Chris

Sorry to trouble you with this. It was my own memory corruption problem. I accidentally allocated the LLVM Module in a memory segment type that is known to be buggy. Using the std::operator new makes the problem go away. Oops.

SORRY

Reid (really glad I didn’t file a bug report now) Spencer.