[llvm-commits] [llvm-gcc-4.2] r51723 - in /llvm-gcc-4.2/trunk/gcc: config/i386/llvm-i386-target.h config/i386/llvm-i386.cpp config/rs6000/llvm-rs6000.cpp llvm-abi.h

Dale Johannesen dalej at apple.com
Thu May 29 18:23:12 PDT 2008


Author: johannes
Date: Thu May 29 20:23:12 2008
New Revision: 51723

URL: http://llvm.org/viewvc/llvm-project?rev=51723&view=rev
Log:
X86-64 ABI fix.  Revert isSingleElementStructOrArray
change in favor of a more general version which handles
the case where there's more than one element correctly.
Fixes gcc.dg/compat/struct-layout-1.exp/t003
and many more.


Modified:
    llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h
    llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp
    llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp
    llvm-gcc-4.2/trunk/gcc/llvm-abi.h

Modified: llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h?rev=51723&r1=51722&r2=51723&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h (original)
+++ llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h Thu May 29 20:23:12 2008
@@ -95,17 +95,18 @@
    considered as if they were the type of the data field. */
 #ifndef LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR
 #define LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR(X) \
-  isSingleElementStructOrArray(X, true, false, false)
+  isSingleElementStructOrArray(X, true, false)
 #endif
 
+extern bool llvm_x86_should_pass_aggregate_in_integer_regs(tree, unsigned*);
+
 /* LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS - Return true if this aggregate
    value should be passed in integer registers.  This differs from the usual
-   handling in that x86-64 passes single-int-element unions as the type of the 
-   field. */
-#define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X)                \
-  (TARGET_64BIT ?                                                    \
-   !isSingleElementStructOrArray((X), true, true, true) :            \
-   !isSingleElementStructOrArray((X), false, true, false))
+   handling in that x86-64 passes 128-bit structs and unions which only
+   contain data in the first 64 bits, as 64-bit objects.  (These can be
+   created by abusing __attribute__((aligned)).  */
+#define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X, Y)             \
+  llvm_x86_should_pass_aggregate_in_integer_regs((X), (Y))
 
 extern bool llvm_x86_should_pass_vector_in_integer_regs(tree);
 

Modified: llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp?rev=51723&r1=51722&r2=51723&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp Thu May 29 20:23:12 2008
@@ -1288,4 +1288,38 @@
   return Loc;
 }
 
+/// llvm_x86_should_pass_aggregate_in_integer_regs - x86-32 is same as the
+/// default.  x86-64 detects the case where a type is 16 bytes long but
+/// only 8 of them are passed, the rest being padding (*size is set to 8
+/// to identify this case).
+bool llvm_x86_should_pass_aggregate_in_integer_regs(tree type, unsigned *size)
+{
+  *size = 0;
+  if (TARGET_64BIT) {
+    enum x86_64_reg_class Class[MAX_CLASSES];
+    enum machine_mode Mode = ix86_getNaturalModeForType(type);
+    int NumClasses = ix86_ClassifyArgument(Mode, type, Class, 0);
+    if (NumClasses == 1 && (Class[0] == X86_64_INTEGERSI_CLASS ||
+                            Class[0] == X86_64_INTEGER_CLASS)) {
+      /* 8 byte object, one int register */
+      return true;
+    }
+    if (NumClasses == 2 && (Class[0] == X86_64_INTEGERSI_CLASS ||
+                            Class[0] == X86_64_INTEGER_CLASS)) {
+      if (Class[1] == X86_64_INTEGERSI_CLASS ||
+          Class[1] == X86_64_INTEGER_CLASS)
+        /* 16 byte object, 2 int registers */
+        return true;
+      if (Class[1] == X86_64_NO_CLASS) {
+        /* 16 byte object, only 1st register has information */
+        *size = 8;
+        return true;
+      }
+    }
+    return false;    
+  }
+  else 
+    return !isSingleElementStructOrArray(type, false, true);
+}
+
 /* LLVM LOCAL end (ENTIRE FILE!)  */

Modified: llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp?rev=51723&r1=51722&r2=51723&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp Thu May 29 20:23:12 2008
@@ -404,7 +404,7 @@
   // some zero-length fields as well, must be passed as the field type.
   // Note this does not apply to long double.
   // This is required for ABI correctness.  
-  tree tType = isSingleElementStructOrArray(TreeType, true, false, false);
+  tree tType = isSingleElementStructOrArray(TreeType, true, false);
   if (tType && int_size_in_bytes(tType)==Bytes && TYPE_MODE(tType)!=TFmode &&
       (TREE_CODE(tType)!=VECTOR_TYPE || Bytes==16))
     return false;
@@ -437,7 +437,7 @@
   // Other single-element structs may be passed this way as well, but
   // only if the type size matches the element's type size (structs that
   // violate this can be created with __aligned__).
-  tree tType = isSingleElementStructOrArray(TreeType, true, false, false);
+  tree tType = isSingleElementStructOrArray(TreeType, true, false);
   if (tType && int_size_in_bytes(tType)==SrcSize && TYPE_MODE(tType)!=TFmode &&
       (TREE_CODE(tType)!=VECTOR_TYPE || SrcSize==16)) {
     Elts.push_back(ConvertType(tType));

Modified: llvm-gcc-4.2/trunk/gcc/llvm-abi.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-abi.h?rev=51723&r1=51722&r2=51723&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Thu May 29 20:23:12 2008
@@ -138,21 +138,17 @@
 /// rejectFatBitField, and the single element is a bitfield of a type that's
 /// bigger than the struct, return null anyway.
 static tree isSingleElementStructOrArray(tree type, bool ignoreZeroLength,
-                                         bool rejectFatBitfield,
-                                         bool acceptUnions) {
+                                         bool rejectFatBitfield) {
   // Scalars are good.
   if (!isAggregateTreeType(type)) return type;
   
   tree FoundField = 0;
   switch (TREE_CODE(type)) {
   case QUAL_UNION_TYPE:
+  case UNION_TYPE:     // Single element unions don't count.
   case COMPLEX_TYPE:   // Complex values are like 2-element records.
   default:
     return 0;
-  case UNION_TYPE:     // Single element unions don't count.
-    if (!acceptUnions)
-      return 0;
-    // fall through
   case RECORD_TYPE:
     // If this record has variable length, reject it.
     if (TREE_CODE(TYPE_SIZE(type)) != INTEGER_CST)
@@ -178,15 +174,13 @@
         }
       }
     return FoundField ? isSingleElementStructOrArray(FoundField, 
-                                                     ignoreZeroLength, false,
-                                                     false)
+                                                     ignoreZeroLength, false)
                       : 0;
   case ARRAY_TYPE:
     const ArrayType *Ty = dyn_cast<ArrayType>(ConvertType(type));
     if (!Ty || Ty->getNumElements() != 1)
       return 0;
-    return isSingleElementStructOrArray(TREE_TYPE(type), false, false, 
-                                        false);
+    return isSingleElementStructOrArray(TREE_TYPE(type), false, false);
   }
 }
 
@@ -283,8 +277,8 @@
 // single element is a bitfield of a type bigger than the struct; the code
 // for field-by-field struct passing does not handle this one right.
 #ifndef LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS
-#define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X) \
-   !isSingleElementStructOrArray(X, false, true, false)
+#define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X, Y) \
+   !isSingleElementStructOrArray((X), false, true)
 #endif
 
 // LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR - Return a TYPE tree if this single
@@ -295,7 +289,7 @@
 // by abusing the __aligned__ attribute.)
 #ifndef LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR
 #define LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR(X) \
-  isSingleElementStructOrArray(X, false, false, false)
+  isSingleElementStructOrArray(X, false, false)
 #endif
 
 // LLVM_SHOULD_RETURN_VECTOR_AS_SCALAR - Return a TYPE tree if this vector type
@@ -408,6 +402,7 @@
   /// their fields.
   void HandleArgument(tree type, std::vector<const Type*> &ScalarElts,
                       ParameterAttributes *Attributes = NULL) {
+    unsigned Size = 0;
     const Type *Ty = ConvertType(type);
     // Figure out if this field is zero bits wide, e.g. {} or [0 x int].  Do
     // not include variable sized fields here.
@@ -418,7 +413,7 @@
       ScalarElts.push_back(PtrTy);
     } else if (Ty->getTypeID()==Type::VectorTyID) {
       if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) {
-        PassInIntegerRegisters(type, Ty, ScalarElts);
+        PassInIntegerRegisters(type, Ty, ScalarElts, 0);
       } else {
         C.HandleScalarArgument(Ty, type);
         ScalarElts.push_back(Ty);
@@ -444,8 +439,8 @@
         *Attributes |= 
           ParamAttr::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
       }
-    } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type)) {
-      PassInIntegerRegisters(type, Ty, ScalarElts);
+    } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type, &Size)) {
+      PassInIntegerRegisters(type, Ty, ScalarElts, Size);
     } else if (isZeroSizedStructOrUnion(type)) {
       // Zero sized struct or union, just drop it!
       ;
@@ -526,10 +521,15 @@
     
   /// PassInIntegerRegisters - Given an aggregate value that should be passed in
   /// integer registers, convert it to a structure containing ints and pass all
-  /// of the struct elements in.
+  /// of the struct elements in.  If Size is set we pass only that many bytes.
   void PassInIntegerRegisters(tree type, const Type *Ty,
-                              std::vector<const Type*> &ScalarElts) {
-    unsigned Size = TREE_INT_CST_LOW(TYPE_SIZE(type))/8;
+                              std::vector<const Type*> &ScalarElts,
+                              unsigned origSize) {
+    unsigned Size;
+    if (origSize)
+      Size = origSize;
+    else
+      Size = TREE_INT_CST_LOW(TYPE_SIZE(type))/8;
 
     // FIXME: We should preserve all aggregate value alignment information.
     // Work around to preserve some aggregate value alignment information:
@@ -568,7 +568,7 @@
       Elts.push_back(Type::Int8Ty);
       Size -= 1;
     }
-    assert(Size == 0 && "Didn't cover value?");
+    assert((origSize || Size == 0) && "Didn't cover value?");
     const StructType *STy = StructType::get(Elts, false);
 
     unsigned i = 0;





More information about the llvm-commits mailing list