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

Dale Johannesen dalej at apple.com
Fri May 30 16:16:47 PDT 2008


Author: johannes
Date: Fri May 30 18:16:47 2008
New Revision: 51799

URL: http://llvm.org/viewvc/llvm-project?rev=51799&view=rev
Log:
More x86-64 ABI conformance.  Handles struct parameters
shorter than 16 bytes and not multiple of size 8 the same
way as gcc (although arguably not correctly).


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/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=51799&r1=51798&r2=51799&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 Fri May 30 18:16:47 2008
@@ -98,15 +98,16 @@
   isSingleElementStructOrArray(X, true, false)
 #endif
 
-extern bool llvm_x86_should_pass_aggregate_in_integer_regs(tree, unsigned*);
+extern bool llvm_x86_should_pass_aggregate_in_integer_regs(tree, 
+                                                          unsigned*, bool*);
 
 /* 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 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))
+#define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X, Y, Z)             \
+  llvm_x86_should_pass_aggregate_in_integer_regs((X), (Y), (Z))
 
 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=51799&r1=51798&r2=51799&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 Fri May 30 18:16:47 2008
@@ -1291,25 +1291,32 @@
 /// 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)
+/// to identify this case).  It also pads out the size to that of a full
+/// register.  This means we'll be loading bytes off the end of the object
+/// in some cases.  That's what gcc does, so it must be OK, right?  Right?
+bool llvm_x86_should_pass_aggregate_in_integer_regs(tree type, unsigned *size,
+                                                    bool *DontCheckAlignment)
 {
   *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);
+    *DontCheckAlignment= true;
     if (NumClasses == 1 && (Class[0] == X86_64_INTEGERSI_CLASS ||
                             Class[0] == X86_64_INTEGER_CLASS)) {
       /* 8 byte object, one int register */
+      *size = 8;
       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)
+          Class[1] == X86_64_INTEGER_CLASS) {
         /* 16 byte object, 2 int registers */
+        *size = 16;
         return true;
+      }
       if (Class[1] == X86_64_NO_CLASS) {
         /* 16 byte object, only 1st register has information */
         *size = 8;

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=51799&r1=51798&r2=51799&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Fri May 30 18:16:47 2008
@@ -277,7 +277,7 @@
 // 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, Y) \
+#define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X, Y, Z) \
    !isSingleElementStructOrArray((X), false, true)
 #endif
 
@@ -403,6 +403,7 @@
   void HandleArgument(tree type, std::vector<const Type*> &ScalarElts,
                       ParameterAttributes *Attributes = NULL) {
     unsigned Size = 0;
+    bool DontCheckAlignment = false;
     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.
@@ -413,7 +414,7 @@
       ScalarElts.push_back(PtrTy);
     } else if (Ty->getTypeID()==Type::VectorTyID) {
       if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) {
-        PassInIntegerRegisters(type, Ty, ScalarElts, 0);
+        PassInIntegerRegisters(type, Ty, ScalarElts, 0, false);
       } else {
         C.HandleScalarArgument(Ty, type);
         ScalarElts.push_back(Ty);
@@ -439,8 +440,9 @@
         *Attributes |= 
           ParamAttr::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
       }
-    } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type, &Size)) {
-      PassInIntegerRegisters(type, Ty, ScalarElts, Size);
+    } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type, &Size,
+                                                     &DontCheckAlignment)) {
+      PassInIntegerRegisters(type, Ty, ScalarElts, Size, DontCheckAlignment);
     } else if (isZeroSizedStructOrUnion(type)) {
       // Zero sized struct or union, just drop it!
       ;
@@ -524,7 +526,7 @@
   /// 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 origSize) {
+                              unsigned origSize, bool DontCheckAlignment) {
     unsigned Size;
     if (origSize)
       Size = origSize;
@@ -537,7 +539,7 @@
     // from Int64 alignment. ARM backend needs this.
     unsigned Align = TYPE_ALIGN(type)/8;
     unsigned Int64Align = getTargetData().getABITypeAlignment(Type::Int64Ty);
-    bool UseInt64 = (Align >= Int64Align);
+    bool UseInt64 = DontCheckAlignment ? true : (Align >= Int64Align);
 
     // FIXME: In cases where we can, we should use the original struct.
     // Consider cases like { int, int } and {int, short} for example!  This will





More information about the llvm-commits mailing list