[cfe-commits] r109681 - in /cfe/trunk: lib/CodeGen/TargetInfo.cpp test/CodeGen/x86_64-arguments.c

Chris Lattner sabre at nondot.org
Wed Jul 28 15:15:08 PDT 2010


Author: lattner
Date: Wed Jul 28 17:15:08 2010
New Revision: 109681

URL: http://llvm.org/viewvc/llvm-project?rev=109681&view=rev
Log:
fix PR7714 by not referencing off the end of a struct when passed by value in
x86-64 abi.  This also improves codegen as well.  Some refactoring is needed of
this code.

Modified:
    cfe/trunk/lib/CodeGen/TargetInfo.cpp
    cfe/trunk/test/CodeGen/x86_64-arguments.c

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=109681&r1=109680&r2=109681&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Wed Jul 28 17:15:08 2010
@@ -1112,7 +1112,12 @@
 
 ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty,
                                           const llvm::Type *CoerceTo) const {
-  if (CoerceTo->isIntegerTy(64) || isa<llvm::PointerType>(CoerceTo)) {
+  // If this is a pointer passed as a pointer, just pass it directly.
+  if ((isa<llvm::PointerType>(CoerceTo) || CoerceTo->isIntegerTy(64)) &&
+      Ty->hasPointerRepresentation())
+    return ABIArgInfo::getExtend();
+  
+  if (isa<llvm::IntegerType>(CoerceTo)) {
     // Integer and pointer types will end up in a general purpose
     // register.
 
@@ -1120,10 +1125,12 @@
     if (const EnumType *EnumTy = Ty->getAs<EnumType>())
       Ty = EnumTy->getDecl()->getIntegerType();
 
-    if (Ty->isIntegralOrEnumerationType() || Ty->hasPointerRepresentation())
+    if (Ty->isIntegralOrEnumerationType())
       return (Ty->isPromotableIntegerType() ?
               ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
     
+    // FIXME: Zap this.
+    
     // If this is a 8/16/32-bit structure that is passed as an int64, then it
     // will be passed in the low 8/16/32-bits of a 64-bit GPR, which is the same
     // as how an i8/i16/i32 is passed.  Coerce to a i8/i16/i32 instead of a i64.
@@ -1320,6 +1327,8 @@
   X86_64ABIInfo::Class Lo, Hi;
   classify(Ty, 0, Lo, Hi);
 
+  uint64_t TySizeInBytes = Context.getTypeSizeInChars(Ty).getQuantity();
+  
   // Check some invariants.
   // FIXME: Enforce these by construction.
   assert((Hi != Memory || Lo == Memory) && "Invalid memory classification.");
@@ -1351,8 +1360,6 @@
     // available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8
     // and %r9 is used.
   case Integer:
-    // It is always safe to classify this as an i64 argument.
-    ResType = llvm::Type::getInt64Ty(VMContext);
     ++neededInt;
       
     // If we can choose a better 8-byte type based on the preferred type, and if
@@ -1361,6 +1368,19 @@
       if (isa<llvm::IntegerType>(PrefTypeLo) ||
           isa<llvm::PointerType>(PrefTypeLo))
         ResType = PrefTypeLo;
+      
+    if (ResType == 0) {
+      // It is always safe to classify this as an integer type up to i64 that
+      // isn't larger than the structure.
+      if (TySizeInBytes == 1)
+        ResType = llvm::Type::getInt8Ty(VMContext);
+      else if (TySizeInBytes == 2)
+        ResType = llvm::Type::getInt16Ty(VMContext);
+      else if (TySizeInBytes <= 4)
+        ResType = llvm::Type::getInt32Ty(VMContext);
+      else
+        ResType = llvm::Type::getInt64Ty(VMContext);
+    }
     break;
 
     // AMD64-ABI 3.2.3p3: Rule 3. If the class is SSE, the next
@@ -1385,8 +1405,7 @@
   case NoClass: break;
       
   case Integer: {
-    // It is always safe to classify this as an i64 argument.
-    const llvm::Type *HiType = llvm::Type::getInt64Ty(VMContext);
+    const llvm::Type *HiType = 0;
     ++neededInt;
 
     // If we can choose a better 8-byte type based on the preferred type, and if
@@ -1395,7 +1414,20 @@
       if (isa<llvm::IntegerType>(PrefTypeHi) ||
           isa<llvm::PointerType>(PrefTypeHi))
         HiType = PrefTypeHi;
-      
+    
+    if (HiType == 0) {
+      // It is always safe to classify this as an integer type up to i64 that
+      // isn't larger than the structure.
+      if (TySizeInBytes == 9)
+        HiType = llvm::Type::getInt8Ty(VMContext);
+      else if (TySizeInBytes == 10)
+        HiType = llvm::Type::getInt16Ty(VMContext);
+      else if (TySizeInBytes <= 12)
+        HiType = llvm::Type::getInt32Ty(VMContext);
+      else
+        HiType = llvm::Type::getInt64Ty(VMContext);
+    }
+    
     ResType = llvm::StructType::get(VMContext, ResType, HiType, NULL);
     break;
   }

Modified: cfe/trunk/test/CodeGen/x86_64-arguments.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/x86_64-arguments.c?rev=109681&r1=109680&r2=109681&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/x86_64-arguments.c (original)
+++ cfe/trunk/test/CodeGen/x86_64-arguments.c Wed Jul 28 17:15:08 2010
@@ -131,3 +131,17 @@
 // CHECK: %y = alloca{{.*}}, align 16
 
 
+
+// PR7714
+struct f23S {
+  short f0;
+  unsigned f1;
+  int f2;
+};
+
+void f23(int A, struct f23S B) {
+  // CHECK: define void @f23(i32 %A, i64 %B.coerce0, i32 %B.coerce1)
+}
+
+
+





More information about the cfe-commits mailing list