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/llvm-dev/attachments/20170518/e4f37c13/attachment.html>
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/llvm-dev/attachments/20170518/586dd02c/attachment.html>
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/llvm-dev/attachments/20170518/007e79da/attachment.html>