As discussed on llvm-dev (https://lists.llvm.org/pipermail/llvm-dev/2021-October/153080.html), there has been a recurring problem of missing extension attributes on call arguments.
This patch tries to improve on the situation by intorducing a 'NoExt' attribute that is (at least in theory, at the moment) mandatory for a struct passed in an integer register. By demanding that a (narrow) integer argument has one of the sign/zero/no extension attributes, cases where this has been forgotten in the FE can be isolated.
Changes:
- Clang FE:
- A new bit ZeroExt in ABIArgInfo. If Kind is Extend, it is SignExt or ZeroExt, or else NoExt is implied.
- A new method ABIArgInfo::getNoExtend(), used by SystemZABIInfo::classifyArgumentType() for a struct-in-reg argument. (CGCall.cpp:CodeGenTypes::arrangeLLVMFunctionInfo() calls SystemZABIInfo::computeInfo() and the argument types are classified. How about Swift (or SPIR_KERNEL) CCs: should they also have narrow integer arguments extended on SystemZ?)
- IR: new attribute NoExt, handled by parser, emitter etc. Adding one bit IsNoExt ArgFlagsTy grew it past the 3-byte size, so the static_assert was incremented to match the new size of 4 bytes. Any problem with this?
- SystemZ backend:
- Default sign extension of <=32 bit arguments added, which can be disabled with '-no-arg-exts'.
- New option -verify-int-arg-exts (default off), that when passed checks that all <=32 bit integer arguments have a valid extension attribute. Verifying extension of return values and outgoing call arguments: Incoming function parameters and call results could also be checked, but they are not needed for correctness, but only to let the backend assume they are sign-extended properly.
- A lot of tests updated, mostly with -no-arg-exts, which makes sense in cases like testing for a three-address instruction selection. It seems reasonable to simply disable this default sign-extension during testing, but in a way it may in the future be better to instead update the tests. There are more tests that can be updated - I have only changed the ones that seemed trivial so far. (args-04.ll: This is testing incoming arguments, but it is returning them without extension. This is a little weird as structs are never returned in a reg..?)
- Documentation: Explanation of the NoExt attribute and why it is mandatory.
The comment for getTypeForExtReturn() may be related to this issue..? "// Return the type that should be used to zero or sign extend a zeroext/signext integer return value. FIXME: Some C calling conventions require the return type to be promoted, but this is not true all the time, e.g. i1/i8/i16 on x86/x86_64. It is also not necessary for non-C calling conventions. The frontend should handle this and include all of the necessary information."
So far, this is a work in progress so feel free to make suggestions...
This is not SystemZ-specific, so instead of "struct in reg" I suggest "high bits are undefined". That should be accurate when this attribute is used on any target.