r206729 - ARM64: Do not expand variadic HFA/HVA arguments with the Darwin ABI.

Bob Wilson bob.wilson at apple.com
Sun Apr 20 18:23:40 PDT 2014


Author: bwilson
Date: Sun Apr 20 20:23:39 2014
New Revision: 206729

URL: http://llvm.org/viewvc/llvm-project?rev=206729&view=rev
Log:
ARM64: Do not expand variadic HFA/HVA arguments with the Darwin ABI.

Unlike the standard AAPCS64 ABI, variadic arguments are always passed on the
stack with the Darwin ABI, and this was not being considered when deciding
whether to expand HFA/HVA arguments in a call. An HFA argument with a "float"
base type was being expanded into separate "float" arguments, each of which
was then extended to a double, resulting in a serious mismatch from what is
expected by the va_arg implementation. <rdar://problem/15777067>

Modified:
    cfe/trunk/lib/CodeGen/TargetInfo.cpp
    cfe/trunk/test/CodeGen/arm64-arguments.c

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=206729&r1=206728&r2=206729&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Sun Apr 20 20:23:39 2014
@@ -3158,7 +3158,7 @@ private:
   ABIArgInfo classifyReturnType(QualType RetTy) const;
   ABIArgInfo classifyArgumentType(QualType RetTy, unsigned &AllocatedVFP,
                                   bool &IsHA, unsigned &AllocatedGPR,
-                                  bool &IsSmallAggr) const;
+                                  bool &IsSmallAggr, bool IsNamedArg) const;
   bool isIllegalVectorType(QualType Ty) const;
 
   virtual void computeInfo(CGFunctionInfo &FI) const {
@@ -3169,11 +3169,19 @@ private:
     // and Floating-point Registers (with one register per member of the HFA or
     // HVA). Otherwise, the NSRN is set to 8.
     unsigned AllocatedVFP = 0;
+
     // To correctly handle small aggregates, we need to keep track of the number
     // of GPRs allocated so far. If the small aggregate can't all fit into
     // registers, it will be on stack. We don't allow the aggregate to be
     // partially in registers.
     unsigned AllocatedGPR = 0;
+
+    // Find the number of named arguments. Variadic arguments get special
+    // treatment with the Darwin ABI.
+    unsigned NumRequiredArgs = (FI.isVariadic() ?
+                                FI.getRequiredArgs().getNumRequiredArgs() :
+                                FI.arg_size());
+
     FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
     for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
          it != ie; ++it) {
@@ -3181,8 +3189,10 @@ private:
       bool IsHA = false, IsSmallAggr = false;
       const unsigned NumVFPs = 8;
       const unsigned NumGPRs = 8;
+      bool IsNamedArg = ((it - FI.arg_begin()) <
+                         static_cast<signed>(NumRequiredArgs));
       it->info = classifyArgumentType(it->type, AllocatedVFP, IsHA,
-                                      AllocatedGPR, IsSmallAggr);
+                                      AllocatedGPR, IsSmallAggr, IsNamedArg);
 
       // Under AAPCS the 64-bit stack slot alignment means we can't pass HAs
       // as sequences of floats since they'll get "holes" inserted as
@@ -3253,7 +3263,8 @@ ABIArgInfo ARM64ABIInfo::classifyArgumen
                                               unsigned &AllocatedVFP,
                                               bool &IsHA,
                                               unsigned &AllocatedGPR,
-                                              bool &IsSmallAggr) const {
+                                              bool &IsSmallAggr,
+                                              bool IsNamedArg) const {
   // Handle illegal vector types here.
   if (isIllegalVectorType(Ty)) {
     uint64_t Size = getContext().getTypeSize(Ty);
@@ -3327,8 +3338,15 @@ ABIArgInfo ARM64ABIInfo::classifyArgumen
   const Type *Base = 0;
   uint64_t Members = 0;
   if (isHomogeneousAggregate(Ty, Base, getContext(), &Members)) {
-    AllocatedVFP += Members;
     IsHA = true;
+    if (!IsNamedArg && isDarwinPCS()) {
+      // With the Darwin ABI, variadic arguments are always passed on the stack
+      // and should not be expanded. Treat variadic HFAs as arrays of doubles.
+      uint64_t Size = getContext().getTypeSize(Ty);
+      llvm::Type *BaseTy = llvm::Type::getDoubleTy(getVMContext());
+      return ABIArgInfo::getDirect(llvm::ArrayType::get(BaseTy, Size / 64));
+    }
+    AllocatedVFP += Members;
     return ABIArgInfo::getExpand();
   }
 
@@ -3641,8 +3659,8 @@ llvm::Value *ARM64ABIInfo::EmitAAPCSVAAr
 
   unsigned AllocatedGPR = 0, AllocatedVFP = 0;
   bool IsHA = false, IsSmallAggr = false;
-  ABIArgInfo AI =
-      classifyArgumentType(Ty, AllocatedVFP, IsHA, AllocatedGPR, IsSmallAggr);
+  ABIArgInfo AI = classifyArgumentType(Ty, AllocatedVFP, IsHA, AllocatedGPR,
+                                       IsSmallAggr, false /*IsNamedArg*/);
 
   return EmitAArch64VAArg(VAListAddr, Ty, AllocatedGPR, AllocatedVFP,
                           AI.isIndirect(), CGF);

Modified: cfe/trunk/test/CodeGen/arm64-arguments.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm64-arguments.c?rev=206729&r1=206728&r2=206729&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/arm64-arguments.c (original)
+++ cfe/trunk/test/CodeGen/arm64-arguments.c Sun Apr 20 20:23:39 2014
@@ -640,6 +640,12 @@ float test_hfa(int n, ...) {
   return h.d;
 }
 
+float test_hfa_call(struct HFA *a) {
+// CHECK-LABEL: define float @test_hfa_call(%struct.HFA* %a)
+// CHECK: call float (i32, ...)* @test_hfa(i32 1, [2 x double] {{.*}})
+  test_hfa(1, *a);
+}
+
 struct TooBigHFA {
   float a, b, c, d, e;
 };





More information about the cfe-commits mailing list