================
@@ -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

Reply via email to