[cfe-commits] r68196 - in /cfe/trunk: lib/CodeGen/CGCall.cpp test/CodeGen/x86_32-arguments.c

Daniel Dunbar daniel at zuster.org
Wed Apr 1 00:08:39 PDT 2009


Author: ddunbar
Date: Wed Apr  1 02:08:38 2009
New Revision: 68196

URL: http://llvm.org/viewvc/llvm-project?rev=68196&view=rev
Log:
x86-32 Darwin ABI: Single element arrays can be part of "single
element structures", which have different ABI rules.
 - Current return-arguments-32 status is: 1 out of 1000 failures (-7)

 - Also, vectors inside "single element structs" require special
   handling.

Modified:
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/test/CodeGen/x86_32-arguments.c

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=68196&r1=68195&r2=68196&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Wed Apr  1 02:08:38 2009
@@ -167,7 +167,7 @@
 ///
 /// \return The field declaration for the single non-empty field, if
 /// it exists.
-static const FieldDecl *isSingleElementStruct(QualType T) {
+static const Type *isSingleElementStruct(QualType T, ASTContext &Context) {
   const RecordType *RT = T->getAsStructureType();
   if (!RT)
     return 0;
@@ -176,20 +176,25 @@
   if (RD->hasFlexibleArrayMember())
     return 0;
 
-  const FieldDecl *Found = 0;
+  const Type *Found = 0;
   for (RecordDecl::field_iterator i = RD->field_begin(), 
          e = RD->field_end(); i != e; ++i) {
     const FieldDecl *FD = *i;
     QualType FT = FD->getType();
 
+    // Treat single element arrays as the element
+    if (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT))
+      if (AT->getSize().getZExtValue() == 1)
+        FT = AT->getElementType();
+
     if (isEmptyRecord(FT)) {
       // Ignore
     } else if (Found) {
       return 0;
     } else if (!CodeGenFunction::hasAggregateLLVMType(FT)) {
-      Found = FD;
+      Found = FT.getTypePtr();
     } else {
-      Found = isSingleElementStruct(FT);
+      Found = isSingleElementStruct(FT, Context);
       if (!Found)
         return 0;
     }
@@ -253,6 +258,10 @@
 class X86_32ABIInfo : public ABIInfo {
   bool IsDarwin;
 
+  static bool isRegisterSize(unsigned Size) {
+    return (Size == 8 || Size == 16 || Size == 32 || Size == 64);
+  }
+
 public:
   ABIArgInfo classifyReturnType(QualType RetTy, 
                                 ASTContext &Context) const;
@@ -305,9 +314,7 @@
     if (!IsDarwin && !RetTy->isAnyComplexType())
       return ABIArgInfo::getIndirect(0);
     // Classify "single element" structs as their element type.
-    const FieldDecl *SeltFD = isSingleElementStruct(RetTy);
-    if (SeltFD) {
-      QualType SeltTy = SeltFD->getType()->getDesugaredType();
+    if (const Type *SeltTy = isSingleElementStruct(RetTy, Context)) {
       if (const BuiltinType *BT = SeltTy->getAsBuiltinType()) {
         // FIXME: This is gross, it would be nice if we could just
         // pass back SeltTy and have clients deal with it. Is it worth
@@ -326,21 +333,22 @@
         llvm::Type *PtrTy = 
           llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
         return ABIArgInfo::getCoerce(PtrTy);
+      } else if (SeltTy->isVectorType()) {
+        // 64- and 128-bit vectors are never returned in a
+        // register when inside a structure.
+        uint64_t Size = Context.getTypeSize(RetTy);
+        if (Size == 64 || Size == 128)
+          return ABIArgInfo::getIndirect(0);
+
+        return classifyReturnType(QualType(SeltTy, 0), Context);
       }
     }
 
     uint64_t Size = Context.getTypeSize(RetTy);
-    if (Size == 8) {
-      return ABIArgInfo::getCoerce(llvm::Type::Int8Ty);
-    } else if (Size == 16) {
-      return ABIArgInfo::getCoerce(llvm::Type::Int16Ty);
-    } else if (Size == 32) {
-      return ABIArgInfo::getCoerce(llvm::Type::Int32Ty);
-    } else if (Size == 64) {
-      return ABIArgInfo::getCoerce(llvm::Type::Int64Ty);
-    } else {
-      return ABIArgInfo::getIndirect(0);
-    }
+    if (isRegisterSize(Size))
+      return ABIArgInfo::getCoerce(llvm::IntegerType::get(Size));
+
+    return ABIArgInfo::getIndirect(0);
   } else {
     return ABIArgInfo::getDirect();
   }

Modified: cfe/trunk/test/CodeGen/x86_32-arguments.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/x86_32-arguments.c?rev=68196&r1=68195&r2=68196&view=diff

==============================================================================
--- cfe/trunk/test/CodeGen/x86_32-arguments.c (original)
+++ cfe/trunk/test/CodeGen/x86_32-arguments.c Wed Apr  1 02:08:38 2009
@@ -63,7 +63,7 @@
 void f9_2(struct s9 a0) {
 }
 
-// Return of small structures and unions...
+// Return of small structures and unions
 
 // RUN: grep 'float @f10()' %t &&
 struct s10 {
@@ -71,12 +71,14 @@
   float f;
 } f10(void) {}
 
-// Small vectors and 1 x {i64,double} are returned in registers...
+// Small vectors and 1 x {i64,double} are returned in registers
 
 // RUN: grep 'i32 @f11()' %t &&
 // RUN: grep -F 'void @f12(<2 x i32>* noalias sret %agg.result)' %t &&
 // RUN: grep 'i64 @f13()' %t &&
 // RUN: grep 'i64 @f14()' %t &&
+// RUN: grep '<2 x i64> @f15()' %t &&
+// RUN: grep '<2 x i64> @f16()' %t &&
 typedef short T11 __attribute__ ((vector_size (4)));
 T11 f11(void) {}
 typedef int T12 __attribute__ ((vector_size (8)));
@@ -85,5 +87,34 @@
 T13 f13(void) {}
 typedef double T14 __attribute__ ((vector_size (8)));
 T14 f14(void) {}
+typedef long long T15 __attribute__ ((vector_size (16)));
+T15 f15(void) {}
+typedef double T16 __attribute__ ((vector_size (16)));
+T16 f16(void) {}
+
+// And when the single element in a struct (but not for 64 and
+// 128-bits).
+
+// RUN: grep 'i32 @f17()' %t &&
+// RUN: grep -F 'void @f18(%0* noalias sret %agg.result)' %t &&
+// RUN: grep -F 'void @f19(%1* noalias sret %agg.result)' %t &&
+// RUN: grep -F 'void @f20(%2* noalias sret %agg.result)' %t &&
+// RUN: grep -F 'void @f21(%3* noalias sret %agg.result)' %t &&
+// RUN: grep -F 'void @f22(%4* noalias sret %agg.result)' %t &&
+struct { T11 a; } f17(void) {}
+struct { T12 a; } f18(void) {}
+struct { T13 a; } f19(void) {}
+struct { T14 a; } f20(void) {}
+struct { T15 a; } f21(void) {}
+struct { T16 a; } f22(void) {}
+
+// Single element structures are handled specially
+
+// RUN: grep -F 'float @f23()' %t &&
+// RUN: grep -F 'float @f24()' %t &&
+// RUN: grep -F 'float @f25()' %t &&
+struct { float a; } f23(void) {}
+struct { float a[1]; } f24(void) {}
+struct { struct {} a; struct { float a[1]; } b; } f25(void) {}
 
 // RUN: true





More information about the cfe-commits mailing list