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

mats petersson via cfe-dev cfe-dev at lists.llvm.org
Thu May 18 01:32:34 PDT 2017


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/586dd02c/attachment.html>


More information about the cfe-dev mailing list