[LLVMdev] Object layout bug for C++ derived class with long long integer

Christophe de Dinechin christophe at taodyne.com
Sat Feb 27 03:17:00 PST 2010

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.


More information about the llvm-dev mailing list