CGRecordLayout: what difference should be between types returned by getLLVMType and getBaseSubobjectLLVMType

Hi all,

I see that CGRecordLayout has two member functions:

llvm::StructType * getLLVMType () const

llvm::StructType * getBaseSubobjectLLVMType () const

The second one is used only by EmitNullConstant when the parameter asCompleteObject is false.

What kind of type should the function getBaseSubobjectLLVMType return? Should it always be less or equal to the type returned by getLLVMType?

For one of my tests I have that getBaseSubobjectLLVMType returns a bigger packed version of the type returned by getLLVMType. It is bigger because padding has been added.

Kind regards,


Are you sure the base subobject type is actually bigger? If so, that’s a bug. Note that unpacked LLVM struct types can have tail padding, so these two structs have the same size on a 64-bit platform:
{ i8*, i32 }
<{ i8*, i32, [4 x i8] }>

The size is rounded up to the natural alignment of the struct.

The second function returns a type that is usable in a derived class. This class might lower to <{ void (i8*), i8 }> as the base subobject type and { void (i8)*, i8 } as the complete type, for example:
class A {
virtual void f();
char a;

Because when B derives from A, it can use the tail padding of A like so:
class B : public A {
char b;

B’s LLVM type could be <{ <{ void (i8*)*, i8 }>, i8 }>

That was a bug in the function CGRecordLowering::determinePacked. It was fixed in revision 218577 on the 28th of September.

The bug was that padding was added only to the base subobject LLVM type.

The complete type looked like: { %class.a, i32}

And subobject type looked like: <%class.a, [2 x i8], i32}>