[cfe-dev] [RFC] Pragma pack/align

Jason Liu via cfe-dev cfe-dev at lists.llvm.org
Wed May 23 13:46:05 PDT 2018


Currently Clang implements pragma pack mostly in the same way of what
Microsoft Windows compiler does:
https://msdn.microsoft.com/en-us/library/2e70t5y1.aspx
However, there are platforms where pragma pack has different
syntax/semantics. For example,
https://www.ibm.com/support/knowledgecenter/SSGH2K_13.1.2/com.ibm.xlc131.aix.doc/compiler_ref/pragma_pack.html

Some differences worth noting:
#pragma pack(number) with GCC/MSVC would not affect internal stack, meaning
if we have

#pragma pack(4)
#pragma pack(pop)

pragma pack(pop) won’t be able to pop anything, and pragma pack(4) is still
in effect; however, some flavours of the pragma is such that #pragma pack(4)
 is the same as #pragma pack(push, 4) would be with GCC/MSVC.

There seems to be existing code in clang/lib/Parse/ParsePragma.cpp that
touches upon this:

 if (Tok.is(tok::numeric_constant)) {
    Alignment = Tok;

    PP.Lex(Tok);

    // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
    // the push/pop stack.
    // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
    Action =
        PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;

Basically, the behaviour is tweaked to be the "push" semantic for "Apple".
Is this direct querying for the specific "flavour" of pack the preferable
way of managing semantic differences for pragma pack? Also, the enumeration
type is called PragmaMsStackAction. If the enumeration is used for more
than Microsoft-specific pragmas, doesn't it make sense to change it to a
more generic name, say PragmaStackAction?

#pragma align is another pragma I want to mention here. Currently, #pragma
align = power/ #pragma align = natural are the same, and they set the
attribute MaxFieldAlignmentAttr to be 0, which later gets overridden by the
code in lib/AST/RecordLayoutBuilder.cpp to be the normal alignment value.
However, align power and natural are different on AIX. Natural alignment is
the same alignment rule on other platform, but power alignment have some
special alignment rule on AIX. So I think what makes sense here is to keep
the existing behavior for existing platforms, and do something different for
 #pragma align = power/ #pragma align = natural for AIX platform.
This is the doc for align(power/natural) on AIX:
https://www.ibm.com/support/knowledgecenter/SSGH2K_13.1.2/com.ibm.xlc131.aix.doc/compiler_ref/opt_align.html
The implementation for those two pragmas I have in mind is very similar to
that of pragma align = Mac68k, which is to attach a new clang::Attr attribute
on RecordDecls that are affected by pragma align = power/natural(Notice
that those clang::Attr do not have source form and are for internal usage
only), and we would query consume those clang::Attr off the RecordDecl in
lib/AST/RecordLayoutBuilder.cpp.

Lastly, I want to talk about the interaction model behind the align and pack
 pragmas as they could end up "overriding" each other’s setting.
The existing implementation for pragma align and pragma pack allows pragma
pack(pop) to pop pragma align settings, and pragma align(reset) to pop pragma
pack settings. Existing unit test case is here:
https://github.com/llvm-mirror/clang/blob/master/test/Sema/pragma-pack-and-options-align.c

However, the stack effect between align and pack pragmas I intend to pursue
is different and here are some examples:

#pragma align(natural)
#pragma pack(2)
// section 1

Remarks: code in section 1 would have their natural alignment reduced by
pack(2).

#pragma pack(2)
#pragma align(natural)
// section 1

Remarks: code in section 1 would have their natural alignment; the pack(2) does
not apply.

Additional complication comes in with pragma align(reset) and pragma
pack(pop). Here’s some examples:

#pragma align(power)
#pragma align(natural)
#pragma pack(2)
#pragma align(reset)

Remarks: pragma align(power) is in effect. The pragma pack(2) is removed
along with the pragma align(natural).

#pragma pack(2)
#pragma align(natural)
#pragma pack(pop)

Remarks: pragma pack(pop) won’t be able to pop the stack, because pragma
align(natural) sets a baseline, and there is no pragma pack applied to that
baseline.

As you can see from the examples, the model behind pragma align/pack is that
 pragma align sets a new baseline (sits on top of all preceding pack pragmas),
and pragma align(reset) unwinds all pack pragmas sitting on top of a pragma
align baseline.

There are two options I can try to pursue here:

   1. Implement the new stack effect model for all platforms.
   Pros : new mental model behind the stack effect might make more sense
   for some users.
   Cons: but it would break existing user code (if user are actually using
   those pragma align). Hopefully pragma align is not used pervasively on
   existing platforms, otherwise, it is a deal breaker.
   2. Implement the new stack effect only on specific platform(AIX), keep
   existing behavior for existing platforms.
   Pros: no existing user code will get break.
   Cons: it might be ugly to have different stack effect for different
   platforms.

I’m leaning towards on option 1 at this time because it’s cleaner solution
if people think the new mental model is better, and are okay with the fact
that some user code will get compiled differently if they use pragma align
and pragma pack together already.

Please let me know if there are any concerns or questions about my current
proposal and design. Your feedback is appreciated.

Regards,

Jason Liu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20180523/3daf3196/attachment.html>


More information about the cfe-dev mailing list