This is an archive of the discontinued LLVM Phabricator instance.

[ARM] Conform to AAPCS when passing overaligned composites as arguments
ClosedPublic

Authored by chill on Apr 24 2018, 7:58 AM.

Details

Summary

The "Procedure Call Procedure Call Standard for the ARM® Architecture" (https://static.docs.arm.com/ihi0042/f/IHI0042F_aapcs.pdf), specifies that composite types are passed according to their natural alignment:

5.5 Parameter Passing
...
B.5 If the argument is an alignment adjusted type its value is passed as a copy of the actual value. The
copy will have an alignment defined as follows.

  • For a Fundamental Data Type, the alignment is the natural alignment of that type, after any

promotions

  • For a Composite Type, the alignment of the copy will have 4-byte alignment if its natural alignment is <= 4 and 8-byte alignment if its natural alignment is >= 8

The "natural alignment" is defined as the maximum of the alignment of the top-level components:

4.3 Composite Types
...

  • The natural alignment of a composite type is the maximum of each of the member alignments of the 'top-level' members of the composite type i.e. before any alignment adjustment of the entire composite is applied

clang, however, uses the actual alignment of the composite, instead of the natural alignment.

This patch fixes passing of composite types to use the natural alignment. With this patch clang conforms to AAPCS and is compatible with GCC.

Diff Detail

Repository
rC Clang

Event Timeline

chill created this revision.Apr 24 2018, 7:58 AM

I'd like to see some tests for __attribute((packed)).

lib/CodeGen/TargetInfo.cpp
5822

Whitespace.

chill added a comment.May 3 2018, 10:07 AM

I'd like to see some tests for __attribute((packed)).

Thanks, indeed it does not work correctly on packed structures. Back to the drawing board ...

chill updated this revision to Diff 149252.May 31 2018, 2:29 AM

Update:

  • similar changes needed for AArch64
  • added/updated tests

I'm not sure Apple will want to mess with their ABI like this... adding some reviewers.

Otherwise LGTM.

lib/CodeGen/TargetInfo.cpp
5815–5817

I'd rather do alignment computations in bytes, rather than bits (can we use getTypeAlignInChars here?)

chill updated this revision to Diff 149536.Jun 1 2018, 1:07 PM

Update:

  • fix only APCS, don't touch other ABIs
  • misc other
chill marked 2 inline comments as done.Jun 1 2018, 1:09 PM

I'm not sure Apple will want to mess with their ABI like this... adding some reviewers.

Fair enough, I'd rather not touch it :)

I'm not sure it's appropriate to impose this as an overhead on all targets.

I'm not sure it's appropriate to impose this as an overhead on all targets.

You mean the overhead of increasing the size of TypeInfo? That's fair.

I'm not sure it's appropriate to impose this as an overhead on all targets.

You mean the overhead of increasing the size of TypeInfo? That's fair.

Yeah. It seems like something that could be pretty easily computed retroactively in the places that need it. It might be okay to have a ASTContext-level cache for it; that cache would just stay empty in practice for most compiler invocations.

chill updated this revision to Diff 150148.Jun 6 2018, 8:51 AM

Update: refactor a bit to not impose size overhead on targets, which don't use natural alignment.

Okay, as a code change this seems more reasonable to me. I haven't really thought through the ABI-compatibility issues, though. CC'ing Tim.

I'm fine with the ABI changes, but I'm not very convinced by the "NaturalAlignment" name.

Far from being a privileged alignment kind, it seems to take account of a pretty arbitrary set of modifiers. In fact, I can't help wondering if what's really happened is that ARM has decided to document existing GCC practice as the path of least resistance and scrambled for a name. This would be fine in ARM-specific code but could be quite misleading in the generic ASTContext. Personally I'd go for ARMNaturalAlignment and stop pretending it's something anyone else needs to care about (at least until some other ABI comes along that does).

lib/CodeGen/TargetInfo.cpp
5069

I think the max/min logic is more confusing here than the alternative:

Alignment = Alignment < 128 ? 64 : 128;
chill added a comment.Jun 25 2018, 2:14 AM

I'm fine with the ABI changes, but I'm not very convinced by the "NaturalAlignment" name.

I'd rather not put target names in API functions. The meaning of that field is pretty target
independent ("alignment of type, before alignment adjustments")
If we use it only in ARM/AArch64 we can put a comment in that sense and
maybe rename it to UnadjustedAlignement or something else more descriptive than NaturalAlignement ?

lib/CodeGen/TargetInfo.cpp
5069

I'll change it.

I'd rather not put target names in API functions. The meaning of that field is pretty target independent ("alignment of type, before alignment adjustments")

Except that rule only applies to aggregates. Scalar types get their alignment adjusted anyway I believe. The definition is ridiculously arbitrary.

If we use it only in ARM/AArch64 we can put a comment in that sense and maybe rename it to UnadjustedAlignement or something else more descriptive than NaturalAlignement?

I could just about live with that (or UnnaturalAlignment, though perhaps best not).

chill updated this revision to Diff 152679.Jun 25 2018, 6:31 AM

Update: use "unadjusted alignment" instead of "natural alignment", rename things accordingly.

efriedma added inline comments.Jul 23 2018, 4:56 PM
lib/AST/ASTContext.cpp
2088

This "default" isn't right; there are a lot of non-canonical types which need to be handled here (which getTypeAlign handles, but this doesn't).

Could you just write something like if (const auto *RTy = T->getAs<RecordType>()) [...] else return getTypeAlign(T);?

chill updated this revision to Diff 157662.Jul 27 2018, 4:01 AM

Fixed to properly examine the canonical type when getting it's unadjusted alignment.

chill marked an inline comment as done.Jul 27 2018, 4:02 AM

Thanks for pointing this!

This revision is now accepted and ready to land.Jul 27 2018, 4:30 PM
This revision was automatically updated to reflect the committed changes.

hey there, I've run into problems with stripping static-libs on arm when using llvm/clang-7. Could you imagine this patch being at fault?

strip: armv7a-unknown-linux-gnueabihf-strip --strip-unneeded -R .comment -R .GCC.command.line -R .note.gnu.gold-version
   lib/libbz2.so.1.0.6
   usr/bin/bzip2recover
   bin/bzip2
   usr/lib/libbz2.a
armv7a-unknown-linux-gnueabihf-strip: /var/tmp/portage/app-arch/bzip2-1.0.6-r10/image/usr/lib/stImUpsE/bzlib.o: Failed to find link section for section 11
armv7a-unknown-linux-gnueabihf-strip: /var/tmp/portage/app-arch/bzip2-1.0.6-r10/image/usr/lib/stImUpsE/bzlib.o: Failed to find link section for section 11

Starting multiple threads on the LLVM mailing lists with the same message is spam. Please don't do that.

If you think you've run into a bug, file a bug report at bugs.llvm.org. For general questions, send an email to llvm-dev.