This patch marks the class _Flags as packed because the design assumes that it
is packed and a number of tests also assume that it is packed. However on AIX
the class is not packed unless it is marked as such.
Details
- Reviewers
nemanjai hubert.reinterpretcast daltenty xingxue Mordante ldionne • Quuxplusone - Group Reviewers
Restricted Project Restricted Project - Commits
- rG96918f2af67f: [libcxx] String format class marked as packed
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
libcxx/include/__format/parser_std_format_spec.h | ||
---|---|---|
112–113 | Use double-underscore form to avoid macro problems. Actually, are we assuming GNU attribute support in general "everywhere"? |
Thanks for fixing these build issues!
libcxx/include/__format/parser_std_format_spec.h | ||
---|---|---|
112–113 | Is there something like godbolt where I can check the layout on AIX online?
I theory yes. The pre-commit CI tests all supported platforms. So when the CI passes it works. (The ASAN errors are unrelated.) But I think it would be cleaner to make the packing conditional. |
libcxx/include/__format/parser_std_format_spec.h | ||
---|---|---|
112–113 |
Yes: godbolt |
libcxx/include/__format/parser_std_format_spec.h | ||
---|---|---|
112–113 | Thanks I wasn't aware godbolt also has AIX support. Good to know for the future. |
I've updated the packed attribute and added the under-under for it.
In terms of using the attribute I know that other parts of libcxx already
use it so I figured it would be safe to use as it would be nothing new.
LGTM from the AIX viewpoint. The resulting layout is similar to what would happen (even without the attribute) on Linux.
Please wait for the libc++ group approval.
LGTM. When I make the changes to this type I might make the __packed__ conditional. But that depends on how it looks in the final version. At least now I know I can check AIX on godbolt.
You have a typo in your commit message (becuase). Generally LGTM with a small style comment. I'd also like to better understand the motivation before shipping this: can someone explain why/how the tests currently depend on the class being packed?
libcxx/include/__format/parser_std_format_spec.h | ||
---|---|---|
112–113 | Can't we put that attribute at the beginning of the class declaration, i.e. class _LIBCPP_TYPE_VIS __attribute__((__packed__)) _Flags? This whole time I thought the attribute applied to something different because of the (IMO) unusual placement. |
Thank you for catching that. I'll fix the typo before I commit.
I can explain why the tests depend on the class being packed. All of the tests check the size of the class Parser with an assert like this one:
static_assert(sizeof(Parser<char>) == 2 * sizeof(uint32_t));
The class _Flags is part of the Parser class and so if _Flags is not packed then Parser will be larger and the assert will fail.
The tests and asserts were added when the original Formatter implementations were done. (See 7fb9f99f3bb645337b4f4e6a2a3515219be82011 from patch https://reviews.llvm.org/D103670) . I didn't add the original implementation but I think the reason for these asserts was that the author wanted to make sure that the data structures where small.
libcxx/include/__format/parser_std_format_spec.h | ||
---|---|---|
112–113 | No, we are consciously not using naked GNU attributes in the headers. I'd also ask for an explicit alignment, even if it is 1. |
libcxx/include/__format/parser_std_format_spec.h | ||
---|---|---|
56 | If I ran the zoo, I'd make this struct __attribute__((__packed__)) only on AIX, and leave it "normal" everywhere else. I'm worried that a packed struct might behave observably differently on some non-AIX platform and have some effect that we didn't expect. But I'm not aware of any concrete problem with how you've got it now. Pre-existing nit: I would also move lines 83–87 down next to line 110 to keep all the members together. |
libcxx/include/__format/parser_std_format_spec.h | ||
---|---|---|
112–113 | Like __LIBCPP_HIDE_FROM_ABI etc., they are encapsulated and restricted to platforms that are known to support them. I consider a naked packed attribute generally a bug, see also the clang warning around members of packed structures. This isn't a huge issue here as everything is uint8_t or smaller, but better to be consistent. |
libcxx/include/__format/parser_std_format_spec.h | ||
---|---|---|
56 | As commented below this _Flags class will be changed, so for now I don't mind the unconditional __packed__. I discovered some issues with the current design:
In this new design I will test whether __packed__ is still needed on AIX or not. (The goal is to keep the struct small so it can be passed in registers.) I learned godbolt has AIX support so that makes testing a lot easier. |
Updated to use _Pragma pack instead of using the attribute.
Also, made the change only for AIX.
I think this version addresses all of the comments made. The parameterized form of the macro can be added when needed. Confirming LGTM.
libcxx/include/__config | ||
---|---|---|
1444 | Yes, I agree this is the better form (the effect of the packing is controlled by the argument, unlike the attribute, which accepts no arguments). The effect on the alignment of the members is mitigated with this form (if the parameter is not 1). If we need this parameterized in the future, the following works (even if pack is defined as a macro): #define _LIBCPP_PACKED_FOR_AIX_IMPL(X) _Pragma( # X ) #define _LIBCPP_PACKED_FOR_AIX(X) _LIBCPP_PACKED_FOR_AIX_IMPL( pack( X ) ) |
libcxx/include/__format/parser_std_format_spec.h | ||
---|---|---|
112–113 | Hmm, I missed this part of the review, but TBH I think the solution we ended with is kind of over-engineered. Having to push/pop a pragma just for this seems overkill. Also, @joerg , we support a limited number of compilers, and we do frequently use things (e.g. builtins) without creating an unnecessary "abstraction layer" on top by e.g. creating a _LIBCPP_FOO macro. I spun up D121009, let's move the discussion there. |
Yes, I agree this is the better form (the effect of the packing is controlled by the argument, unlike the attribute, which accepts no arguments). The effect on the alignment of the members is mitigated with this form (if the parameter is not 1).
If we need this parameterized in the future, the following works (even if pack is defined as a macro):