================
@@ -263,8 +290,78 @@ ArgInfo AArch64TargetInfo::classifyArgumentType(
Ty, IsNamedArg, NVec, NPred, UnpaddedCoerceToSeq, NSRN, NPRN);
}
- reportNYI("Aggregate argument type handling");
- return ArgInfo::getIgnore();
+ // Aggregates of at most 16 bytes are passed directly in registers or on
+ // the stack.
+ if (Size <= 128) {
+ uint64_t AlignBits;
+ if (Opts.Kind == AArch64ABIKind::AAPCS) {
+ // An 8-byte slot when the unadjusted alignment is below 16 bytes, and
+ // a 16-byte slot otherwise.
+ AlignBits = Ty->getUnadjustedAlignment().value() * 8;
+ AlignBits = AlignBits < 128 ? 64 : 128;
+ } else {
+ // The larger of the ABI alignment and the pointer width.
+ uint64_t PointerWidth = Opts.IsILP32 ? 32 : 64;
+ AlignBits = std::max(Ty->getAlignment().value() * 8, PointerWidth);
+ }
+ Size = llvm::alignTo(Size, AlignBits);
+
+ const Type *BaseTy;
+ if ((Size == 64 || Size == 128) && AlignBits == 64 &&
+ containsOnlyPointers(Ty)) {
+ // A record of 64-bit pointers in an 8-byte slot is coerced to a pointer
+ // or an array of pointers.
+ BaseTy = TB.getPointerType(64, llvm::Align(8));
+ } else {
+ // Every other aggregate is coerced to an integer of the slot width, or
+ // an array of those integers.
+ BaseTy = TB.getIntegerType(AlignBits, llvm::Align(AlignBits / 8),
+ /*Signed=*/false);
+ }
+
+ if (Size == AlignBits)
+ return ArgInfo::getDirect(BaseTy);
+ return ArgInfo::getDirect(TB.getArrayType(BaseTy, Size / AlignBits, Size));
+ }
+
+ return getNaturalAlignIndirect(Ty, getAllocaAddrSpace(), /*ByVal=*/false);
+}
+
+// True for a record whose bases and fields are plain pointers, or records of
+// such pointers. A plain pointer is a 64-bit pointer with no address-space
+// qualifier. An array field is inspected through its base element. False for
an
+// empty record and for a type that is not a record.
+bool AArch64TargetInfo::containsOnlyPointers(const Type *Ty) const {
+ if (Ty->isEmptyRecord())
+ return false;
+
+ const auto *RT = dyn_cast<RecordType>(Ty);
+ if (!RT)
+ return false;
+
+ for (const FieldInfo &Base : RT->getBaseClasses())
+ if (!containsOnlyPointers(Base.FieldType))
+ return false;
+
+ for (const FieldInfo &Field : RT->getFields()) {
+ const Type *FT = Field.FieldType;
+ while (const auto *AT = dyn_cast<ArrayType>(FT)) {
+ // TODO: Consider whether this should accept matrix types. Clang
+ // doesn't, but that's probably an error.
----------------
madhur13490 wrote:
nit: matrix elements have to be integer or floating-point, so a matrix of
pointers can't exist. I think the TODO and the break can go and this can just
be a plain while (dyn_cast<ArrayType>) loop.
https://github.com/llvm/llvm-project/pull/230631
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits