[cfe-dev] [llvm-dev] Struct padding

Hongbin Zheng via cfe-dev cfe-dev at lists.llvm.org
Thu May 18 01:39:05 PDT 2017


the packed + aligned attribute will automatically introduce explicit
padding byte array:
https://godbolt.org/g/TlHX2g

Sometimes Clang will decide to automatically pack the struct/class in C++,
I don't know the details here, but looks like it is related to inheritance.

Thanks
Hongbin


On Thu, May 18, 2017 at 1:32 AM, mats petersson <mats at planetcatfish.com>
wrote:

> How do you mean that a byte array is added? Because at least in my
> experiments, I don't see that:
>
> struct A
> {
>     int a;
>     char b;
>     long c;
> };
>
> struct A a;
>
> produces:
>
> ; ModuleID = 'pad.c'
> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
> target triple = "x86_64-unknown-linux-gnu"
>
> %struct.A = type { i32, i8, i64 }
>
> @a = common global %struct.A zeroinitializer, align 8
>
> !llvm.ident = !{!0}
>
>
> Adding a call to printf,
>
> extern int printf(const char *fmt, ...);
> void func(struct A* a)
> {
>     printf("c=%ld", a->c);
> }
>
> and outputting assembler, we can see that the offset to "c" in that struct
> is 8:
>
> func:                                   # @func
>     .cfi_startproc
> # BB#0:                                 # %entry
>     movq    8(%rdi), %rsi
>     movl    $.L.str, %edi
>     xorl    %eax, %eax
>     jmp    printf                  # TAILCALL
>
> So, can you provide an example of this padding, because I don't see it.
> This is clang 3.8, but 3.9 did the same thing (I went back to 3.8 to check
> if it was different)
>
> There will be padding in the actual data structure, based on the need for
> aligning (better performance if not required by the hardware), so if we for
> example initalize the data:
> struct A a = { 3, 'a', 4711 };
> then there will be LLVM-code like this:
> @a = global %struct.A { i32 3, i8 97, i64 4711 }, align 8
> and in the machine code there will be:
> a:
>     .long    3                       # 0x3
>     .byte    97                      # 0x61
>     .zero    3
>     .quad    4711                    # 0x1267
>
> Because three bytes of zeros are needed to fill the data between the 'a'
> and the long of 4711. But nowhere other than in the machine-code is that
> padding anything  more than "difference between theoretical closest offset
> and aligned offset".
>
> --
> Mats
>
> On 18 May 2017 at 09:14, Hongbin Zheng <etherzhhb at gmail.com> wrote:
>
>> Hi Mats,
>>
>> When the struct is packed, explicit byte array is introduced to pad the
>> struct. (I saw this happened in clang 3.9.)
>>
>> I want to check if a byte or byte array in an LLVM struct is introduce
>> for explicit padding or not.
>>
>> I don't need to worry about this problem in case the newest clang do not
>> introduce byte array anymore.
>>
>> Thanks
>> Hongbin
>>
>> On Thu, May 18, 2017 at 1:03 AM, mats petersson <mats at planetcatfish.com>
>> wrote:
>>
>>> What are you actually trying to achieve? LLVM knows the alignment and
>>> size of each component. You could iterate over the different types and
>>> identify when there is a difference in "calculated total size and the
>>> current alignment requirement", but LLVM does automatically pad structures
>>> [unless you specifically ask it not to].
>>>
>>> Note that there is no actual field added for padding, it's just the size
>>> and alignment itself.
>>>
>>> --
>>> Mats
>>>
>>> On 18 May 2017 at 08:51, Hongbin Zheng via cfe-dev <
>>> cfe-dev at lists.llvm.org> wrote:
>>>
>>>> Hi Jonas,
>>>>
>>>> Thanks a lot.
>>>> In an LLVM pass, how can I check the related information? will clang
>>>> emit some metadata table?
>>>>
>>>> Thanks
>>>> Hongbin
>>>>
>>>> On Thu, May 18, 2017 at 12:47 AM, Jonas Devlieghere <
>>>> jonas at devlieghere.com> wrote:
>>>>
>>>>> Hi Hongbin,
>>>>>
>>>>> You can pass `-Wpadded` to clang. For your particular example it will
>>>>> print something along the lines of
>>>>>
>>>>> ```
>>>>> warning: padding struct 'foo1' with 7 bytes to align 'x' [-Wpadded]
>>>>>     long x;
>>>>> ```
>>>>>
>>>>> Jonas
>>>>>
>>>>> On Thu, May 18, 2017 at 9:15 AM, Hongbin Zheng via llvm-dev <
>>>>> llvm-dev at lists.llvm.org> wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> I am wondering how I can tell whether a field of a struct is
>>>>>> introduced by padding or not.
>>>>>>
>>>>>> For example, if I have a struct:
>>>>>>
>>>>>> struct foo1 {
>>>>>>     char *p;     /* 8 bytes */
>>>>>>     char c;      /* 1 byte
>>>>>>     long x;      /* 8 bytes */
>>>>>> };
>>>>>>
>>>>>> clang may generate:
>>>>>>
>>>>>> struct foo1 {
>>>>>>     char *p;     /* 8 bytes */
>>>>>>     char c;      /* 1 byte
>>>>>>     char pad[7]; /* 7 bytes */
>>>>>>     long x;      /* 8 bytes */
>>>>>> };
>>>>>>
>>>>>> Is there any way that I can tell the "pad" array is generated by
>>>>>> padding?
>>>>>>
>>>>>> Thanks a lot
>>>>>> Hongbin
>>>>>>
>>>>>> _______________________________________________
>>>>>> LLVM Developers mailing list
>>>>>> llvm-dev at lists.llvm.org
>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>>>>>
>>>>>>
>>>>>
>>>>
>>>> _______________________________________________
>>>> cfe-dev mailing list
>>>> cfe-dev at lists.llvm.org
>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170518/007e79da/attachment.html>


More information about the cfe-dev mailing list