r200307 - [ARM] Fix AAPCS-VFP non-compliance when returning HFA from variadic functions.

Amara Emerson amara.emerson at arm.com
Tue Jan 28 02:56:37 PST 2014


Author: aemerson
Date: Tue Jan 28 04:56:36 2014
New Revision: 200307

URL: http://llvm.org/viewvc/llvm-project?rev=200307&view=rev
Log:
[ARM] Fix AAPCS-VFP non-compliance when returning HFA from variadic functions.

Arguments and return values must always be marshalled as for the base
AAPCS when the callee is a variadic function.

Patch by Oliver Stannard!

Modified:
    cfe/trunk/lib/CodeGen/TargetInfo.cpp
    cfe/trunk/test/CodeGen/arm-aapcs-vfp.c
    cfe/trunk/test/CodeGen/arm-homogenous.c

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=200307&r1=200306&r2=200307&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Tue Jan 28 04:56:36 2014
@@ -3099,10 +3099,10 @@ public:
   ABIKind getABIKind() const { return Kind; }
 
 private:
-  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyReturnType(QualType RetTy, bool isVariadic) const;
   ABIArgInfo classifyArgumentType(QualType RetTy, int *VFPRegs,
                                   unsigned &AllocatedVFP,
-                                  bool &IsHA) const;
+                                  bool &IsHA, bool isVariadic) const;
   bool isIllegalVectorType(QualType Ty) const;
 
   virtual void computeInfo(CGFunctionInfo &FI) const;
@@ -3198,7 +3198,7 @@ void ARMABIInfo::computeInfo(CGFunctionI
   // unallocated are marked as unavailable. 
   unsigned AllocatedVFP = 0;
   int VFPRegs[16] = { 0 };
-  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), FI.isVariadic());
   for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
        it != ie; ++it) {
     unsigned PreAllocation = AllocatedVFP;
@@ -3206,10 +3206,12 @@ void ARMABIInfo::computeInfo(CGFunctionI
     // 6.1.2.3 There is one VFP co-processor register class using registers
     // s0-s15 (d0-d7) for passing arguments.
     const unsigned NumVFPs = 16;
-    it->info = classifyArgumentType(it->type, VFPRegs, AllocatedVFP, IsHA);
+    it->info = classifyArgumentType(it->type, VFPRegs, AllocatedVFP, IsHA, FI.isVariadic());
     // If we do not have enough VFP registers for the HA, any VFP registers
     // that are unallocated are marked as unavailable. To achieve this, we add
     // padding of (NumVFPs - PreAllocation) floats.
+    // Note that IsHA will only be set when using the AAPCS-VFP calling convention,
+    // and the callee is not variadic.
     if (IsHA && AllocatedVFP > NumVFPs && PreAllocation < NumVFPs) {
       llvm::Type *PaddingTy = llvm::ArrayType::get(
           llvm::Type::getFloatTy(getVMContext()), NumVFPs - PreAllocation);
@@ -3360,7 +3362,7 @@ static void markAllocatedVFPs(int *VFPRe
 
 ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, int *VFPRegs,
                                             unsigned &AllocatedVFP,
-                                            bool &IsHA) const {
+                                            bool &IsHA, bool isVariadic) const {
   // We update number of allocated VFPs according to
   // 6.1.2.1 The following argument types are VFP CPRCs:
   //   A single-precision floating-point type (including promoted
@@ -3424,7 +3426,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentT
   if (isEmptyRecord(getContext(), Ty, true))
     return ABIArgInfo::getIgnore();
 
-  if (getABIKind() == ARMABIInfo::AAPCS_VFP) {
+  if (getABIKind() == ARMABIInfo::AAPCS_VFP && !isVariadic) {
     // Homogeneous Aggregates need to be expanded when we can fit the aggregate
     // into VFP registers.
     const Type *Base = 0;
@@ -3566,7 +3568,7 @@ static bool isIntegerLikeType(QualType T
   return true;
 }
 
-ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
+ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic) const {
   if (RetTy->isVoidType())
     return ABIArgInfo::getIgnore();
 
@@ -3622,7 +3624,7 @@ ABIArgInfo ARMABIInfo::classifyReturnTyp
     return ABIArgInfo::getIgnore();
 
   // Check for homogeneous aggregates with AAPCS-VFP.
-  if (getABIKind() == AAPCS_VFP) {
+  if (getABIKind() == AAPCS_VFP && !isVariadic) {
     const Type *Base = 0;
     if (isHomogeneousAggregate(RetTy, Base, getContext())) {
       assert(Base && "Base class should be set for homogeneous aggregate");

Modified: cfe/trunk/test/CodeGen/arm-aapcs-vfp.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm-aapcs-vfp.c?rev=200307&r1=200306&r2=200307&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/arm-aapcs-vfp.c (original)
+++ cfe/trunk/test/CodeGen/arm-aapcs-vfp.c Tue Jan 28 04:56:36 2014
@@ -25,6 +25,11 @@ struct homogeneous_struct test_struct(st
   return struct_callee(arg);
 }
 
+// CHECK: define arm_aapcs_vfpcc void @test_struct_variadic(%struct.homogeneous_struct* {{.*}}, [4 x i32] %{{.*}}, ...)
+struct homogeneous_struct test_struct_variadic(struct homogeneous_struct arg, ...) {
+  return struct_callee(arg);
+}
+
 struct nested_array {
   double d[4];
 };

Modified: cfe/trunk/test/CodeGen/arm-homogenous.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/arm-homogenous.c?rev=200307&r1=200306&r2=200307&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/arm-homogenous.c (original)
+++ cfe/trunk/test/CodeGen/arm-homogenous.c Tue Jan 28 04:56:36 2014
@@ -173,6 +173,14 @@ void test_struct_of_four_doubles(void) {
   takes_struct_of_four_doubles(3.0, g_s4d, g_s4d, 4.0);
 }
 
+extern void takes_struct_of_four_doubles_variadic(double a, struct_of_four_doubles b, struct_of_four_doubles c, double d, ...);
+
+void test_struct_of_four_doubles_variadic(void) {
+// CHECK: test_struct_of_four_doubles_variadic
+// CHECK: call arm_aapcs_vfpcc void (double, [4 x i64], [4 x i64], double, ...)* @takes_struct_of_four_doubles_variadic(double {{.*}}, [4 x i64] {{.*}}, [4 x i64] {{.*}}, double {{.*}})
+  takes_struct_of_four_doubles_variadic(3.0, g_s4d, g_s4d, 4.0);
+}
+
 extern void takes_struct_with_backfill(float f1, double a, float f2, struct_of_four_doubles b, struct_of_four_doubles c, double d);
 void test_struct_with_backfill(void) {
 // CHECK: test_struct_with_backfill





More information about the cfe-commits mailing list