[cfe-dev] 'struct' member alignment query

Martin J. O'Riordan via cfe-dev cfe-dev at lists.llvm.org
Thu Feb 9 11:57:55 PST 2017


I can verify that this does work though, even if I don’t understand the semantics or rationale.

 

Thanks,

 

            MartinO

 

From: Martin J. O'Riordan [mailto:martin.oriordan at movidius.com] 
Sent: 09 February 2017 19:55
To: 'Richard Smith' <richard at metafoo.co.uk>
Cc: 'Clang Dev' <cfe-dev at lists.llvm.org>; 'Tim Northover' <t.p.northover at gmail.com>
Subject: RE: [cfe-dev] 'struct' member alignment query

 

Hi Richard,

 

How does ‘packed’ work in this context?  I thought ‘packed’ would cause the whole aggregate to eliminate padding, rather than just changing the alignment requirements of a single member.

 

What I want is that the outer aggregate is aligned in the normal way according the maximum alignment requirements of its members.  However, I want to also have a member which itself is an aggregate with its usual internal padding retained, but changed its alignment constraint (essentially lying) within the context of the enclosing aggregate.

 

Would ‘packed’ not just unilaterally remove the padding?

 

For example (assuming char is 1-byte and int is 4, and natural alignment):

 

struct Inner {

  char c;

  int  i;

};

Inner x;

 

I can reasonably assume on a naturally aligned system that the following would hold true (undefined ISO behaviour ignored regarding address arithmetic - assume a simple conventional 32-bit Von Neumann address space):

 

sizeof(Inner) == 8

((unsigned)&x & 7) == 0

((unsigned)&x.i - (unsigned)&x.c) == 4

offsetof(Outer, c) == 0

offsetof(Outer, i) == 4

 

Now what I want to do is:

 

struct Outer {

  char aa;

  int  bb;

  char cc;

  [magic attribute] Inner xx;

  char dd;

  int  ee;

};

Outer y;

 

Such that:

 

sizeof(Outer) == 24

((unsigned)&y & 7) == 0

((unsigned)&y.xx.i - (unsigned)&y.xx.c) == 4

((unsigned)&y.xx.i - (unsigned)&y) == 13

offsetof(Inner, bb) == 4

offsetof(Inner, cc) == 8

offsetof(Inner, xx) == 9

offsetof(Inner, dd) == 17

offsetof(Inner, ee) == 20

 

so padding is still present within the layout of ‘xx’, and also as normal for the member alignment of ‘aa’, ‘bb’, ‘cc’, ‘dd’ and ‘ee’ within ‘Outer’, but not for ‘xx’.

 

This is useful when overlaying structures on registers in a memory-mapped device which can have weird arrangements, and avoid the need for dirty little macro arithmetic tricks which are sadly very common in embedded systems device driver code.

 

So forgive me if I am misunderstanding ‘packed’ (and I probably am), but will this not cause the members of ‘Inner’ as a member of ‘Outer’ to become packed ((unsigned)&i == (unsigned)&c + 1), or does it simply loosen the alignment constraint within the members of ‘Outer’ to achieve what I intend?  I usually interpret ‘packed’ as all-or-nothing.  So if I replace ‘[magic attribute]’ with ‘__attribute__((packed))’, this will achieve the effect I require?  What if I want to force alignment of ‘xx’ to 2-bytes instead of 1?

 

The only reasonably portable way I know of doing this kind of thing, is to always pack structures, and to explicitly provide the dummy padding bytes (including bitfield alignment magic such as ‘int:0;’), but while these are mostly-portable, they are not absolute in the context of a specific implementation - which is where ‘__attribute__((aligned(x)))’ is necessary.

 

In any case, the incongruity of using ‘aligned’ in a ‘typedef’ versus explicitly on the member is quite unintuitive, though I fully understand the need for CLang to maintain compatibility with GCC in this regard.

 

Thanks,

 

            MartinO

 

From: metafoo at gmail.com <mailto:metafoo at gmail.com>  [mailto:metafoo at gmail.com] On Behalf Of Richard Smith
Sent: 09 February 2017 18:03
To: Martin J. O'Riordan <Martin.ORiordan at movidius.com <mailto:Martin.ORiordan at movidius.com> >
Cc: Clang Dev <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org> >; Tim Northover <t.p.northover at gmail.com <mailto:t.p.northover at gmail.com> >
Subject: Re: [cfe-dev] 'struct' member alignment query

 

The "right" way to get this effect is to use __attribute__((packed)) on the field.

 

On 9 Feb 2017 9:33 am, "Martin J. O'Riordan via cfe-dev" <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org> > wrote:

Wow!  Thanks for the response, that worked perfectly.

I never would have expected that the indirect 'typedef' approach would behave any differently to the more direct annotation!  I feel that this is probably an unintended GCC behaviour/bug, though CLang is 100% right to maintain compatibility with GCC.

But it solved my problem, thanks very much,

        MartinO


-----Original Message-----
From: Tim Northover [mailto:t.p.northover at gmail.com <mailto:t.p.northover at gmail.com> ]
Sent: 09 February 2017 15:08
To: Martin J. O'Riordan <Martin.ORiordan at movidius.com <mailto:Martin.ORiordan at movidius.com> >
Cc: cfe-dev <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org> >
Subject: Re: [cfe-dev] 'struct' member alignment query

On 9 February 2017 at 02:56, Martin J. O'Riordan via cfe-dev <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org> > wrote:
> Is this expected behaviour in 'clang', and if so, is there another way
> I can coerce the 'struct' member 'alignCheck2' onto another less
> constrained alignment boundary?

It's expected, but I think only because of GCC compatibility because it's really not obvious behaviour. The workaround, which still mystifies me, is to go via a typedef:

typedef AlignCheck_t __attribute__((aligned(1))) UnAlignCheck_t;

then you can put that in the struct and it'll be laid out without any padding.

Tim.

_______________________________________________
cfe-dev mailing list
cfe-dev at lists.llvm.org <mailto: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/20170209/e1fffe38/attachment.html>


More information about the cfe-dev mailing list