[cfe-commits] r156650 - in /cfe/trunk: lib/CodeGen/TargetInfo.cpp test/CodeGen/mips-byval-arg.c test/CodeGen/mips64-class-return.cpp

Akira Hatanaka ahatanaka at mips.com
Fri May 11 14:56:58 PDT 2012


Author: ahatanak
Date: Fri May 11 16:56:58 2012
New Revision: 156650

URL: http://llvm.org/viewvc/llvm-project?rev=156650&view=rev
Log:
Coerce byval aggregate arguments to integers whose size matches the integer
register size of the target architecture.
 

Added:
    cfe/trunk/test/CodeGen/mips-byval-arg.c
Modified:
    cfe/trunk/lib/CodeGen/TargetInfo.cpp
    cfe/trunk/test/CodeGen/mips64-class-return.cpp

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=156650&r1=156649&r2=156650&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Fri May 11 16:56:58 2012
@@ -3156,7 +3156,8 @@
 class MipsABIInfo : public ABIInfo {
   bool IsO32;
   unsigned MinABIStackAlignInBytes;
-  llvm::Type* HandleAggregates(QualType Ty) const;
+  llvm::Type* CoerceToIntArgs(uint64_t TySize) const;
+  llvm::Type* HandleAggregates(QualType Ty, uint64_t TySize) const;
   llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size) const;
   llvm::Type* getPaddingType(uint64_t Align, uint64_t Offset) const;
 public:
@@ -3190,11 +3191,29 @@
 };
 }
 
+llvm::Type* MipsABIInfo::CoerceToIntArgs(uint64_t TySize) const {
+  SmallVector<llvm::Type*, 8> ArgList;
+  llvm::IntegerType *IntTy = llvm::IntegerType::get(getVMContext(),
+                                                    MinABIStackAlignInBytes * 8);
+
+  // Add (TySize / MinABIStackAlignInBytes) args of IntTy.
+  for (unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
+    ArgList.push_back(IntTy);
+
+  // If necessary, add one more integer type to ArgList.
+  unsigned R = TySize % (MinABIStackAlignInBytes * 8);
+
+  if (R)
+    ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
+
+  return llvm::StructType::get(getVMContext(), ArgList);
+}
+
 // In N32/64, an aligned double precision floating point field is passed in
 // a register.
-llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty) const {
+llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const {
   if (IsO32)
-    return 0;
+    return CoerceToIntArgs(TySize);
 
   if (Ty->isComplexType())
     return CGT.ConvertType(Ty);
@@ -3203,12 +3222,11 @@
 
   // Unions are passed in integer registers.
   if (!RT || !RT->isStructureOrClassType())
-    return 0;
+    return CoerceToIntArgs(TySize);
 
   const RecordDecl *RD = RT->getDecl();
   const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
-  uint64_t StructSize = getContext().getTypeSize(Ty);
-  assert(!(StructSize % 8) && "Size of structure must be multiple of 8.");
+  assert(!(TySize % 8) && "Size of structure must be multiple of 8.");
   
   uint64_t LastOffset = 0;
   unsigned idx = 0;
@@ -3238,17 +3256,13 @@
     LastOffset = Offset + 64;
   }
 
-  // This struct/class doesn't have an aligned double field.
-  if (!LastOffset)
-    return 0;
-
-  // Add ((StructSize - LastOffset) / 64) args of type i64.
-  for (unsigned N = (StructSize - LastOffset) / 64; N; --N)
+  // Add ((TySize - LastOffset) / 64) args of type i64.
+  for (unsigned N = (TySize - LastOffset) / 64; N; --N)
     ArgList.push_back(I64);
 
   // If the size of the remainder is not zero, add one more integer type to
   // ArgList.
-  unsigned R = (StructSize - LastOffset) % 64;
+  unsigned R = (TySize - LastOffset) % 64;
   if (R)
     ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
 
@@ -3256,23 +3270,23 @@
 }
 
 llvm::Type *MipsABIInfo::getPaddingType(uint64_t Align, uint64_t Offset) const {
-  // Padding is inserted only for N32/64.
-  if (IsO32)
-    return 0;
+  assert((Offset % MinABIStackAlignInBytes) == 0);
 
-  assert(Align <= 16 && "Alignment larger than 16 not handled.");
-  return (Align == 16 && Offset & 0xf) ?
-    llvm::IntegerType::get(getVMContext(), 64) : 0;
+  if ((Align - 1) & Offset)
+    return llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
+
+  return 0;
 }
 
 ABIArgInfo
 MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
   uint64_t OrigOffset = Offset;
-  uint64_t TySize =
-    llvm::RoundUpToAlignment(getContext().getTypeSize(Ty), 64) / 8;
+  uint64_t TySize = getContext().getTypeSize(Ty);
   uint64_t Align = getContext().getTypeAlign(Ty) / 8;
-  Offset = llvm::RoundUpToAlignment(Offset, std::max(Align, (uint64_t)8));
-  Offset += TySize;
+
+  Align = std::max(Align, (uint64_t)MinABIStackAlignInBytes);
+  Offset = llvm::RoundUpToAlignment(Offset, Align);
+  Offset += llvm::RoundUpToAlignment(TySize, Align * 8) / 8;
 
   if (isAggregateTypeForABI(Ty)) {
     // Ignore empty aggregates.
@@ -3282,20 +3296,15 @@
     // Records with non trivial destructors/constructors should not be passed
     // by value.
     if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty)) {
-      Offset = OrigOffset + 8;
+      Offset = OrigOffset + MinABIStackAlignInBytes;
       return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
     }
 
-    // If we have reached here, aggregates are passed either indirectly via a
-    // byval pointer or directly by coercing to another structure type. In the
-    // latter case, padding is inserted if the offset of the aggregate is
-    // unaligned.
-    llvm::Type *ResType = HandleAggregates(Ty);
-
-    if (!ResType)
-      return ABIArgInfo::getIndirect(0);
-
-    return ABIArgInfo::getDirect(ResType, 0, getPaddingType(Align, OrigOffset));
+    // If we have reached here, aggregates are passed directly by coercing to
+    // another structure type. Padding is inserted if the offset of the
+    // aggregate is unaligned.
+    return ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0,
+                                 getPaddingType(Align, OrigOffset));
   }
 
   // Treat an enum type as its underlying type.
@@ -3385,7 +3394,7 @@
   RetInfo = classifyReturnType(FI.getReturnType());
 
   // Check if a pointer to an aggregate is passed as a hidden argument.  
-  uint64_t Offset = RetInfo.isIndirect() ? 8 : 0;
+  uint64_t Offset = RetInfo.isIndirect() ? MinABIStackAlignInBytes : 0;
 
   for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
        it != ie; ++it)

Added: cfe/trunk/test/CodeGen/mips-byval-arg.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/mips-byval-arg.c?rev=156650&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/mips-byval-arg.c (added)
+++ cfe/trunk/test/CodeGen/mips-byval-arg.c Fri May 11 16:56:58 2012
@@ -0,0 +1,15 @@
+// RUN: %clang -target mipsel-unknown-linux -ccc-clang-archs mipsel -O3 -S -o - -emit-llvm %s | FileCheck %s -check-prefix=O32
+// RUN: %clang -target mips64el-unknown-linux -ccc-clang-archs mips64el -O3 -S -mabi=n64 -o - -emit-llvm %s | FileCheck %s -check-prefix=N64
+
+typedef struct {
+  float f[3];
+} S0;
+
+extern void foo2(S0);
+
+// O32: define void @foo1(i32 %a0.coerce0, i32 %a0.coerce1, i32 %a0.coerce2)
+// N64: define void @foo1(i64 %a0.coerce0, i32 %a0.coerce1)
+
+void foo1(S0 a0) {
+  foo2(a0);
+}

Modified: cfe/trunk/test/CodeGen/mips64-class-return.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/mips64-class-return.cpp?rev=156650&r1=156649&r2=156650&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/mips64-class-return.cpp (original)
+++ cfe/trunk/test/CodeGen/mips64-class-return.cpp Fri May 11 16:56:58 2012
@@ -39,7 +39,7 @@
   gd2 = a0;
 }
 
-// CHECK: define void @_Z4foo42D0(%class.D0* nocapture byval %a0)
+// CHECK: define void @_Z4foo42D0(i64 %a0.coerce0, i64 %a0.coerce1)
 void foo4(D0 a0) {
   gd0 = a0;
 }





More information about the cfe-commits mailing list