[LLVMdev] Offset to C++ structure members

Paul J. Lucas paul at lucasmail.org
Tue Oct 2 11:33:05 PDT 2012


On Oct 1, 2012, at 9:58 PM, Eli Friedman <eli.friedman at gmail.com> wrote:

> Using GEP on an i8* is a bit nicer to the optimizer, though, because
> using ptrtoint/inttoptr has effects on alias analysis.

My understanding is that, in order to use GEP, you have to provide the LLVM code with the struct layout, i.e., build a StructType object.  In my case, that struct is declared in C++ code already and, in order to use GEP, I'd have to replicate the struct layout (exactly as the C++ compiler would) in LLVM code -- something that I'd rather not do, not to mention that it's fairly "brittle" even if I could manage to get it right.  (Simple structs would probably be easy, but struct that have virtual functions or multiple base classes would be much harder.)

> I'm not entirely sure how you're using mbr_offset_of

Given 't', an instance of some class T, and some member T::m, find the integer offset in bytes from &t to &t.m.  This offset, when added to &t, should be &t.m.

I'm using mbr_offset_of to get the C++ compiler to do the work of telling me what the correct offset is for the already existing struct.

> but it's broken if there are any classes with virtual bases involved.

Really?  This simple code works just fine:

        struct A             { int ai; };
        struct X : virtual A { int xi; };
        struct Y : virtual A { int yi; };

        struct S : X, Y {
          string a;
          string b;
        };

        template<class ClassType,class MbrType> inline
        ptrdiff_t mbr_offset_of( MbrType ClassType::*p ) {
          ClassType const *const c = static_cast<ClassType*>( nullptr );
          return reinterpret_cast<ptrdiff_t>( &(c->*p) );
        }

        int main() {
          ptrdiff_t offset = mbr_offset_of( &S::b );
          S s;
          string *p = (string*)((char*)&s + offset);
          p->assign( "Hello, world!" );
          cout << *p << endl;
         return 0;
        }

Despite that, however, the equivalent code in LLVM (once I introduce a base class for S, even just ordinary inheritance), crashes.  I don't understand why, however.  I print out the offset, and it's the correct value that's getting added to the Pointer.

- Paul



More information about the llvm-dev mailing list