This is an archive of the discontinued LLVM Phabricator instance.

[libcxx] String format class marked as packed
ClosedPublic

Authored by stefanp on Feb 11 2022, 10:59 AM.

Details

Summary

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.

Diff Detail

Event Timeline

stefanp requested review of this revision.Feb 11 2022, 10:59 AM
stefanp created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptFeb 11 2022, 10:59 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
stefanp added reviewers: Restricted Project, Mordante.Feb 11 2022, 11:06 AM
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've been working on some changes regarding this class. In that new version unconditionally pack the struct on all platforms might lead to sub-optimal code. For the current code I don't see an issue with the packing.

Actually, are we assuming GNU attribute support in general "everywhere"?

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

Is there something like godbolt where I can check the layout on AIX online?

Yes: godbolt

https://godbolt.org/z/9j49baqsM

Mordante added inline comments.Feb 14 2022, 9:03 AM
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.

stefanp updated this revision to Diff 408545.Feb 14 2022, 11:57 AM

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.

Mordante accepted this revision as: Mordante.Feb 14 2022, 1:14 PM

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.

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?

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.

stefanp updated this revision to Diff 408842.Feb 15 2022, 6:02 AM

Moved the attribute to the top of the class.
Typo in the comment.

stefanp edited the summary of this revision. (Show Details)Feb 15 2022, 6:04 AM
joerg added a subscriber: joerg.Feb 15 2022, 7:12 AM
joerg added inline comments.
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.

ldionne accepted this revision.Feb 15 2022, 11:19 AM

LGTM since this looks good to @Mordante, who wrote this code in the first place. I'm curious to better understand what @joerg 's comment is, though.

libcxx/include/__format/parser_std_format_spec.h
112–113

Can you elaborate?

This revision is now accepted and ready to land.Feb 15 2022, 11:19 AM
Quuxplusone accepted this revision.Feb 15 2022, 1:02 PM
Quuxplusone added a subscriber: Quuxplusone.
Quuxplusone added inline comments.
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.

joerg added inline comments.Feb 15 2022, 3:33 PM
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.

Mordante added inline comments.Feb 17 2022, 11:02 AM
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:

  • A formatter is-a parser, when changing it to has-a parser it leads to a lot less code duplication in the binary. On an old branch I can reduce 12KB of object size. (I believe I can get an even better size reduction.)
  • The is-a design makes it hard/impossible to make the format member function const qualified. This will become mandatory after LWG3636 you filed is accepted. I also believe this change makes it easier to implement P2286 Formatting ranges, which AFAIK is still targetting C++23.

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.

libcxx/include/__format/parser_std_format_spec.h
112–113

@ldionne, what are your thoughts on creating such a macro? Something like __LIBCPP_PACKED(1).

stefanp updated this revision to Diff 410029.Feb 18 2022, 2:35 PM

Updated to use _Pragma pack instead of using the attribute.
Also, made the change only for AIX.

hubert.reinterpretcast accepted this revision.EditedFeb 18 2022, 3:14 PM

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 ) )
This revision was automatically updated to reflect the committed changes.
ldionne added inline comments.Mar 4 2022, 9:36 AM
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.

Herald added a project: Restricted Project. · View Herald TranscriptMar 4 2022, 9:36 AM