Object layout bug for C++ derived class with long long integer

I have a simple C++ class that looks like this:

  struct Foo { Thing *first; Blob *second; unsigned long third; };

Then I have a derived C++ class that look like this:

  struct Bar : Foo { long long fourth; }

I generate JIT code to access 'fourth' from a Foo * as follows:

  BarPtr = CreateBitCast(FooPtr, BarPtrTy);
  FourthPtr = CreateConstGEP2_32(BarPtr, 0, 3);
  FourthValue = CreateLoad(FourthPtr);
  ConstantValue = ConstantInt::get(FourthValue->getType(), 0x2A4);
  ComparisonValue = CreateICmpEQ(FourthValue, ConstantValue);

This appears to work on Linux and MacOSX with LLVM 2.6 and LLVM 2.7. On Windows, however, where I only have LLVM 2.6 with MINGW/MSYS, the generated code looks like this:

  0x13df70b3: mov $0x2a4,%ecx
  0x13df70b8: xor 0xc(%edi),%ecx
  0x13df70bb: or 0x10(%edi),%ecx
  0x13df70be: test %ecx,%ecx
  0x13df70c0: jne 0x13df70ec

This is wrong compared to the native layout of the C++ object. What the generated code does is compare against values at ecx+12..19, but the C++ object has 'fourth' at ecx+16..23. The compiler inserts some padding in Foo between third (32-bit) and fourth (64-bit), presumably for alignment reasons.

My question is why LLVM doesn't do the same thing. I'm not sure if this is a layout bug in LLVM, if I need some magic incantation to tell LLVM to align 'fourth' to its natural boundary, or if my LLVM declaration of 'Bar' is incorrect. Any suggestion as to the correct resolution would be appreciated.

Thanks
Christophe

Hello, Christophe

I have a simple C++ class that looks like this:

       struct Foo { Thing *first; Blob *second; unsigned long third; };

Then I have a derived C++ class that look like this:

       struct Bar : Foo { long long fourth; }

How does the generated LLVM IR for these structs look like?

This is wrong compared to the native layout of the C++ object.

What is the "native layout of the C++ object"? How is it defined?

The compiler inserts some padding in Foo between third (32-bit) and fourth (64-bit), presumably for alignment reasons.

Which compiler? llvm-gcc tries to follow the mainline gcc for mingw
platform. There were some changes post-2.6 wrt long long native
alignment, you might try to look into code at svn head.

How does the generated LLVM IR for these structs look like?

For Foo:

I mean what was the IR generated by llvm-gcc for such code.

llvm-gcc tries to follow the mainline gcc for mingw
platform. There were some changes post-2.6 wrt long long native
alignment, you might try to look into code at svn head.

Unfortunately, svn head is incompatible with 2.6 (see an earlier email I sent on the list). Since 2.6 is what people get today from tools like apt-get or MacPorts, 2.7 is not really an option for me yet.

Then you should workaround this bug somehow, sorry.

That's what I did for now by replacing the ulong with ulonglong.

Thanks again.
Christophe