]> granicus.if.org Git - clang/commitdiff
Fix the calling convention for structs/unions containing SSE vectors on
authorEli Friedman <eli.friedman@gmail.com>
Sat, 13 Jun 2009 21:37:10 +0000 (21:37 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Sat, 13 Jun 2009 21:37:10 +0000 (21:37 +0000)
x86-32.  This is slightly messy, but I think it's consistent with gcc.

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

lib/CodeGen/TargetABIInfo.cpp
test/CodeGen/x86_32-arguments.c

index 6f7bea2340a9e661e24ffb00b31be6af20fff09c..361e5c0005cc7811e081c8ddbdf564b1cc0681cb 100644 (file)
@@ -159,6 +159,23 @@ static bool areAllFields32Or64BitBasicType(const RecordDecl *RD,
   return true;
 }
 
+static bool typeContainsSSEVector(const RecordDecl *RD, ASTContext &Context) {
+  for (RecordDecl::field_iterator i = RD->field_begin(Context),
+         e = RD->field_end(Context); i != e; ++i) {
+    const FieldDecl *FD = *i;
+
+    if (FD->getType()->isVectorType() &&
+        Context.getTypeSize(FD->getType()) >= 128)
+      return true;
+
+    if (const RecordType* RT = FD->getType()->getAsRecordType())
+      if (typeContainsSSEVector(RT->getDecl(), Context))
+        return true;
+  }
+
+  return false;
+}
+
 namespace {
 /// DefaultABIInfo - The default implementation for ABI specific
 /// details. This implementation provides information which results in
@@ -193,6 +210,9 @@ class X86_32ABIInfo : public ABIInfo {
 
   static bool shouldReturnTypeInRegister(QualType Ty, ASTContext &Context);
 
+  static unsigned getIndirectArgumentAlignment(QualType Ty,
+                                               ASTContext &Context);
+
 public:
   ABIArgInfo classifyReturnType(QualType RetTy,
                                 ASTContext &Context) const;
@@ -350,6 +370,16 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
   }
 }
 
+unsigned X86_32ABIInfo::getIndirectArgumentAlignment(QualType Ty,
+                                                     ASTContext &Context) {
+  unsigned Align = Context.getTypeAlign(Ty);
+  if (Align < 128) return 0;
+  if (const RecordType* RT = Ty->getAsRecordType())
+    if (typeContainsSSEVector(RT->getDecl(), Context))
+      return 16;
+  return 0;
+}
+
 ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
                                                ASTContext &Context) const {
   // FIXME: Set alignment on indirect arguments.
@@ -357,11 +387,11 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
     // Structures with flexible arrays are always indirect.
     if (const RecordType *RT = Ty->getAsStructureType())
       if (RT->getDecl()->hasFlexibleArrayMember())
-        return ABIArgInfo::getIndirect(0);
+        return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty, 
+                                                                    Context));
 
     // Ignore empty structs.
-    uint64_t Size = Context.getTypeSize(Ty);
-    if (Ty->isStructureType() && Size == 0)
+    if (Ty->isStructureType() && Context.getTypeSize(Ty) == 0)
       return ABIArgInfo::getIgnore();
 
     // Expand structs with size <= 128-bits which consist only of
@@ -373,7 +403,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
         return ABIArgInfo::getExpand();
     }
 
-    return ABIArgInfo::getIndirect(0);
+    return ABIArgInfo::getIndirect(getIndirectArgumentAlignment(Ty, Context));
   } else {
     return (Ty->isPromotableIntegerType() ?
             ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
index 8980c66b20727057f21d596f47f74ac9232774e9..43a3ab246c71dff0d242923d5ce016e76646c335 100644 (file)
@@ -154,4 +154,9 @@ struct s37 { float c[1][1]; } f37(void) {}
 // RUN: grep 'define void @f38(.struct.s38. noalias sret .agg.result)' %t &&
 struct s38 { char a[3]; short b; } f38(void) {}
 
+// RUN: grep 'define void @f39(.struct.s39. byval align 16 .x)' %t &&
+typedef int v39 __attribute((vector_size(16)));
+struct s39 { v39 x; };
+void f39(struct s39 x) {}
+
 // RUN: true