[cfe-dev] CGRecordLayoutBuilder for MS ABI
r4start
r4start at gmail.com
Wed Nov 2 02:29:28 PDT 2011
On 02/11/2011 13:17, John McCall wrote:
> On Nov 2, 2011, at 1:32 AM, r4start wrote:
>> On 02/11/2011 10:12, John McCall wrote:
>>> I'm sorry if I've asked this before, but have you verified that this is the
>>> correct condition? Specifically, does the ABI not re-use vbptrs from
>>> non-primary non-virtual bases?
>>>
>>> For example, consider this hierarchy:
>>> class A { int a; };
>>> class B { int b; virtual void foo(); };
>>> class C : public virtual A { int c; };
>>> class D { int d; };
>>> class E : public B, public virtual D { int e; };
>>>
>>> Does class E ultimately have two vbptrs or one?
>> In this test E will be have one vbptr. But if class E was declared like this "class E : public C, public virtual D" my code will generate 2 vbptr.
>> I fix it.
> Heh. Yes, that's the test I meant, sorry. Thanks.
>
>>> I'm still not sure why this is necessary. AppendField should already
>>> be adding padding to bring NextFieldOffset up to VBPtrOffset. The
>>> only time it doesn't add that padding explicitly is when the ABI
>>> alignment of the field type being added would implicitly introduce it.
>> As you can see AppendField just does :
>> 1. Save field type in types;
>> 2. Renew NextField offset (NextField = fieldOffset + fieldSize).
> Ah, sorry, you're right. Shows how rusty I am with this code. Then
> the appropriate thing to do is to call
> AppendPadding(fieldOffset, getTypeAlignment(vbptr));
> before calling AppendField.
>
> Also, AppendField should at least get an
> assert(fieldOffset == NextFieldOffset);
> or better yet the fieldOffset argument should disappear completely.
>
>>> + if (alignedNextFieldOffset< fieldOffset ||
>>> + (!Packed&& (fieldOffset != NextFieldOffset))) {
>> class D {
>> public:
>> virtual void b(){}
>> double a;
>> };
>> struct I : public virtual D
>> {
>> virtual ~I(){}
>> double q;
>> };
>> For this example, we see that fieldOffset = 0x10 for q and alignedNextFieldOffset = 0x10, but NextFieldOffset = 0x0c.
>> Second condition wrong for MS ABI and useless for other ABI.
> It's not wrong. Like I've said several times now, LLVM struct types
> have very specific layout rules that are more complicated than
> "one field starts immediately after the last". The rules are based
> roughly on C, except greatly simplified, which means they're
> not always correct for the actual source-language struct.
> Sometimes the source-language struct has more padding than
> the IR rules would dictate; if so, we have to add extra padding
> bytes manually. Sometimes the source-language struct has
> *less* padding than the IR rules would dictate; if so, we have to
> use packed IR structs even when the source-language struct
> doesn't have __attribute__((packed)) on it.
>
> So in your example, it's okay for there not to be a [4 x i8]
> between the vbptr and the double because the target data for
> Win32 knows that 'double' needs to be 8-byte aligned and so
> implicitly puts padding there. Contrariwise, it's not okay for
> there not to be a [4 x i8] between the vfptr and the vbptr
> because the target data for Win32 only knows that pointers
> need to be 4-byte aligned, so it wouldn't implicitly put padding
> there.
>
> And if the AST layout told us something even crazier, like
> that the double has to be at offset 12 even though it has 8-byte
> alignment under this target data, then we'd have to give up
> and use a packed LLVM struct type to represent it.
>
> John.
>
Thanks for the clarification.
I will return Packed in condition,
I was baffled by that StructLayout adds 4 bytes alignment at the end.
- Dmitry.
More information about the cfe-dev
mailing list