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

Chris Lattner sabre at nondot.org
Wed Jul 28 16:06:14 PDT 2010


Author: lattner
Date: Wed Jul 28 18:06:14 2010
New Revision: 109689

URL: http://llvm.org/viewvc/llvm-project?rev=109689&view=rev
Log:
use Get8ByteTypeAtOffset for the return value path as well so we
don't get errors similar to PR7714 on the return path.

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=109689&r1=109688&r2=109689&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Wed Jul 28 18:06:14 2010
@@ -1198,6 +1198,62 @@
   return ABIArgInfo::getIndirect(0);
 }
 
+/// Get8ByteTypeAtOffset - The ABI specifies that a value should be passed in an
+/// 8-byte GPR.  This means that we either have a scalar or we are talking about
+/// the high or low part of an up-to-16-byte struct.  This routine picks the
+/// best LLVM IR type to represent this, which may be i64 or may be anything
+/// else that the backend will pass in a GPR that works better (e.g. i8, %foo*,
+/// etc).
+///
+/// PrefType is an LLVM IR type that corresponds to (part of) the IR type for
+/// the source type.  IROffset is an offset in bytes into the LLVM IR type that
+/// the 8-byte value references.  PrefType may be null.
+///
+/// SourceTy is the source level type for the entire argument.  SourceOffset is
+/// an offset into this that we're processing (which is always either 0 or 8).
+///
+static const llvm::Type *Get8ByteTypeAtOffset(const llvm::Type *PrefType,
+                                              unsigned IROffset,
+                                              QualType SourceTy,
+                                              unsigned SourceOffset,
+                                              const llvm::TargetData &TD,
+                                              llvm::LLVMContext &VMContext,
+                                              ASTContext &Context) {
+  // Pointers are always 8-bytes at offset 0.
+  if (IROffset == 0 && PrefType && isa<llvm::PointerType>(PrefType))
+    return PrefType;
+
+  // TODO: 1/2/4/8 byte integers are also interesting, but we have to know that
+  // the "hole" is not used in the containing struct (just undef padding).
+
+  if (const llvm::StructType *STy =
+          dyn_cast_or_null<llvm::StructType>(PrefType)) {
+    // If this is a struct, recurse into the field at the specified offset.
+    const llvm::StructLayout *SL = TD.getStructLayout(STy);
+    if (IROffset < SL->getSizeInBytes()) {
+      unsigned FieldIdx = SL->getElementContainingOffset(IROffset);
+      IROffset -= SL->getElementOffset(FieldIdx);
+      
+      return Get8ByteTypeAtOffset(STy->getElementType(FieldIdx), IROffset,
+                                  SourceTy, SourceOffset, TD,VMContext,Context);
+    }      
+  }
+  
+  // Okay, we don't have any better idea of what to pass, so we pass this in an
+  // integer register that isn't too big to fit the rest of the struct.
+  uint64_t TySizeInBytes = Context.getTypeSizeInChars(SourceTy).getQuantity();
+
+  // It is always safe to classify this as an integer type up to i64 that
+  // isn't larger than the structure.
+  switch (unsigned(TySizeInBytes-SourceOffset)) {
+  case 1:  return llvm::Type::getInt8Ty(VMContext);
+  case 2:  return llvm::Type::getInt16Ty(VMContext);
+  case 3:
+  case 4:  return llvm::Type::getInt32Ty(VMContext);
+  default: return llvm::Type::getInt64Ty(VMContext);
+  }  
+}
+
 ABIArgInfo X86_64ABIInfo::
 classifyReturnType(QualType RetTy, llvm::LLVMContext &VMContext) const {
   // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
@@ -1227,7 +1283,8 @@
     // AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next
     // available register of the sequence %rax, %rdx is used.
   case Integer:
-    ResType = llvm::Type::getInt64Ty(VMContext); break;
+    ResType = Get8ByteTypeAtOffset(0, 0, RetTy, 0, TD, VMContext, Context);
+    break;
 
     // AMD64-ABI 3.2.3p4: Rule 4. If the class is SSE, the next
     // available SSE register of the sequence %xmm0, %xmm1 is used.
@@ -1261,10 +1318,12 @@
   case ComplexX87: // Previously handled.
   case NoClass: break;
 
-  case Integer:
-    ResType = llvm::StructType::get(VMContext, ResType,
-                                    llvm::Type::getInt64Ty(VMContext), NULL);
+  case Integer: {
+    const llvm::Type *HiType = 
+      Get8ByteTypeAtOffset(0, 8, RetTy, 8, TD, VMContext, Context);
+    ResType = llvm::StructType::get(VMContext, ResType, HiType, NULL);
     break;
+  }
   case SSE:
     ResType = llvm::StructType::get(VMContext, ResType,
                                     llvm::Type::getDoubleTy(VMContext), NULL);
@@ -1295,62 +1354,6 @@
   return getCoerceResult(RetTy, ResType);
 }
 
-/// Get8ByteTypeAtOffset - The ABI specifies that a value should be passed in an
-/// 8-byte GPR.  This means that we either have a scalar or we are talking about
-/// the high or low part of an up-to-16-byte struct.  This routine picks the
-/// best LLVM IR type to represent this, which may be i64 or may be anything
-/// else that the backend will pass in a GPR that works better (e.g. i8, %foo*,
-/// etc).
-///
-/// PrefType is an LLVM IR type that corresponds to (part of) the IR type for
-/// the source type.  IROffset is an offset in bytes into the LLVM IR type that
-/// the 8-byte value references.  PrefType may be null.
-///
-/// SourceTy is the source level type for the entire argument.  SourceOffset is
-/// an offset into this that we're processing (which is always either 0 or 8).
-///
-static const llvm::Type *Get8ByteTypeAtOffset(const llvm::Type *PrefType,
-                                              unsigned IROffset,
-                                              QualType SourceTy,
-                                              unsigned SourceOffset,
-                                              const llvm::TargetData &TD,
-                                              llvm::LLVMContext &VMContext,
-                                              ASTContext &Context) {
-  // Pointers are always 8-bytes at offset 0.
-  if (IROffset == 0 && PrefType && isa<llvm::PointerType>(PrefType))
-    return PrefType;
-
-  // TODO: 1/2/4/8 byte integers are also interesting, but we have to know that
-  // the "hole" is not used in the containing struct (just undef padding).
-
-  if (const llvm::StructType *STy =
-          dyn_cast_or_null<llvm::StructType>(PrefType)) {
-    // If this is a struct, recurse into the field at the specified offset.
-    const llvm::StructLayout *SL = TD.getStructLayout(STy);
-    if (IROffset < SL->getSizeInBytes()) {
-      unsigned FieldIdx = SL->getElementContainingOffset(IROffset);
-      IROffset -= SL->getElementOffset(FieldIdx);
-      
-      return Get8ByteTypeAtOffset(STy->getElementType(FieldIdx), IROffset,
-                                  SourceTy, SourceOffset, TD,VMContext,Context);
-    }      
-  }
-  
-  // Okay, we don't have any better idea of what to pass, so we pass this in an
-  // integer register that isn't too big to fit the rest of the struct.
-  uint64_t TySizeInBytes = Context.getTypeSizeInChars(SourceTy).getQuantity();
-
-  // It is always safe to classify this as an integer type up to i64 that
-  // isn't larger than the structure.
-  switch (unsigned(TySizeInBytes-SourceOffset)) {
-  case 1:  return llvm::Type::getInt8Ty(VMContext);
-  case 2:  return llvm::Type::getInt16Ty(VMContext);
-  case 3:
-  case 4:  return llvm::Type::getInt32Ty(VMContext);
-  default: return llvm::Type::getInt64Ty(VMContext);
-  }  
-}
-
 ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty,
                                                llvm::LLVMContext &VMContext,
                                                unsigned &neededInt,

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=109689&r1=109688&r2=109689&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/x86_64-arguments.c (original)
+++ cfe/trunk/test/CodeGen/x86_64-arguments.c Wed Jul 28 18:06:14 2010
@@ -139,9 +139,16 @@
   int f2;
 };
 
+
 void f23(int A, struct f23S B) {
   // CHECK: define void @f23(i32 %A, i64 %B.coerce0, i32 %B.coerce1)
 }
 
+struct f24s { long a; int b; };
 
+struct f23S f24(struct f23S *X, struct f24s *P2) {
+  return *X;
+  
+  // CHECK: define %struct.f24s @f24(%struct.f23S* %X, %struct.f24s* %P2)
+}
 





More information about the cfe-commits mailing list