]> granicus.if.org Git - clang/commitdiff
ARM byval: when type alignment is bigger than ABI alignment, we can't guarantee
authorManman Ren <mren@apple.com>
Mon, 5 Nov 2012 22:42:46 +0000 (22:42 +0000)
committerManman Ren <mren@apple.com>
Mon, 5 Nov 2012 22:42:46 +0000 (22:42 +0000)
the type alignment of the byval argument. This patch will disable byval in this case,
it also increases the size threshold for turning on byval.

A backend fix will be attempted.

rdar://12596507

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167416 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/TargetInfo.cpp

index f07e9548b159f845a8aa1fce0a9c206d41eeef4b..90603371805d80c3f90ffb6db3af9ec76aa0a2b6 100644 (file)
@@ -3220,8 +3220,16 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, int *VFPRegs,
   }
 
   // Support byval for ARM.
-  if (getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(64) ||
-      getContext().getTypeAlign(Ty) > 64) {
+  // The ABI alignment for APCS is 4-byte and for AAPCS at least 4-byte and at most 8-byte.
+  // Byval can't handle the case where type alignment is bigger than ABI alignment.
+  // We also increase the threshold for byval due to its overhead.
+  uint64_t ABIAlign = 4;
+  uint64_t TyAlign = getContext().getTypeAlign(Ty) / 8;
+  if (getABIKind() == ARMABIInfo::AAPCS_VFP ||
+      getABIKind() == ARMABIInfo::AAPCS)
+    ABIAlign = std::min(std::max(TyAlign, (uint64_t)4), (uint64_t)8);
+  if (getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(64*8) &&
+      TyAlign <= ABIAlign) {
     return ABIArgInfo::getIndirect(0, /*ByVal=*/true);
   }