Patch D123580 changed to use bit fields for strings in long and short mode. As a result, this changes the layout of these strings on AIX because bit fields on AIX are 4 bytes, which breaks the ABI compatibility with earlier strings before the change on AIX. This patch applies the fix proposed by @hubert.reinterpretcast in https://reviews.llvm.org/D127672#3590741 to make string layout compatible. This patch will also make test cases alignof.compile.pass.cpp and sizeof.compile.pass.cpp introduced in D127672 (later reverted) pass on AIX.
Details
- Reviewers
ldionne philnik Mordante hubert.reinterpretcast - Group Reviewers
Restricted Project - Commits
- rG60f7bdfd0317: [libc++][AIX] Make basic_string layout compatible with earlier version
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
libcxx/include/string | ||
---|---|---|
724 | How exactly is this different from using __atrribute__((__packed__))? If it's not I would suggest to put __is_long_ and __cap_ into it's own struct and mark only that as __attribute__((__packed__))to avoid the explicit padding and alignas() specifiers. |
libcxx/include/string | ||
---|---|---|
724 | That should work. Any preference between base class, anonymous struct, or named member? The named member version is the most pragmatic (does not change whether the type is standard layout, does not use language extension). |
libcxx/include/string | ||
---|---|---|
724 | I think an anonymous struct would be the best option. That makes it almost identical to the current version, so there wouldn't have to be any code changes elsewhere. |
libcxx/include/string | ||
---|---|---|
724 | Changed to use anonymous struct and attribute((packed)) as suggested, thanks! |
Thanks for working on this!
The build failure is unrelated, can you rebase before reuploading this patch?
libcxx/include/string | ||
---|---|---|
726–734 | Please add a comment explaining why we packed is needed. | |
760 | Does __long have a fixed size too? If so can add a static_assert for it too? |
Addressed comments.
- add comments explaining why attribute __packed__ is used;
- add static_assert for struct __long.
libcxx/include/string | ||
---|---|---|
759 | This assumes that pointer is not a type (maybe some sort of fancy smart pointer) that has a higher alignment requirement than sizeof(size_type) * 2. |
SGTM, but for now I prefer to leave the approval to people more familiar with the details of this patch and AIX.
Addressed the comment to consider potential padding in the assert added for struct __long.
libcxx/include/string | ||
---|---|---|
759 | Good point, thanks! Modified the assert to take padding into account. |
libcxx/include/string | ||
---|---|---|
758–759 | This reduces to: ((2 * sizeof(size_type) - 1) / sizeof(pointer) + 2) * sizeof(pointer) but I think now that there are many other ways for this to go wrong (pointer requires less alignment than its size, alignment of size_type causes trailing padding, etc.). Maybe: struct __long_size_ref { size_type __x, __y; pointer __z; }; static_assert(sizeof(__long) == sizeof(__long_size_ref)); |
libcxx/include/string | ||
---|---|---|
758–759 | How about we just drop the static_assert? I've got a patch that adds tests which static_asserts the size and alignment of specific instantiations of basic_string. That's a lot more reliable than hoping to get the size and alignment right for user-defined types. |
libcxx/include/string | ||
---|---|---|
758–759 | Sounds good. |
LGTM with my comment addressed.
libcxx/include/string | ||
---|---|---|
726–735 | Could you have this comment just once above the __long and __short structs? Having it cloned makes it a lot easier for them to get out of sync. |
libcxx/include/string | ||
---|---|---|
726–735 | For sure. Thanks very much for your review and good suggestions! |
How exactly is this different from using __atrribute__((__packed__))? If it's not I would suggest to put __is_long_ and __cap_ into it's own struct and mark only that as __attribute__((__packed__))to avoid the explicit padding and alignas() specifiers.