[cfe-commits] r143596 - /cfe/trunk/lib/CodeGen/TargetInfo.cpp

Akira Hatanaka ahatanaka at mips.com
Wed Nov 2 16:54:50 PDT 2011


Author: ahatanak
Date: Wed Nov  2 18:54:49 2011
New Revision: 143596

URL: http://llvm.org/viewvc/llvm-project?rev=143596&view=rev
Log:
Convert the type of a structure passed by value if it has double precision
fields in order to ease handling of such structures in backend. 


Modified:
    cfe/trunk/lib/CodeGen/TargetInfo.cpp

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=143596&r1=143595&r2=143596&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Wed Nov  2 18:54:49 2011
@@ -2994,6 +2994,7 @@
 class MipsABIInfo : public ABIInfo {
   static const unsigned MinABIStackAlignInBytes = 4;
   bool IsO32;
+  llvm::Type* HandleStructTy(QualType Ty) const;
 public:
   MipsABIInfo(CodeGenTypes &CGT, bool _IsO32) : ABIInfo(CGT), IsO32(_IsO32) {}
 
@@ -3026,6 +3027,72 @@
 };
 }
 
+// In N32/64, an aligned double precision floating point field is passed in
+// a register.
+llvm::Type* MipsABIInfo::HandleStructTy(QualType Ty) const {
+  if (IsO32)
+    return 0;
+
+  const RecordType *RT = Ty->getAsStructureType();
+
+  if (!RT)
+    return 0;
+
+  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.");
+  
+  SmallVector<llvm::Type*, 8> ArgList;
+  uint64_t LastOffset = 0;
+  unsigned idx = 0;
+  llvm::IntegerType *I64 = llvm::IntegerType::get(getVMContext(), 64);
+
+  for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+       i != e; ++i, ++idx) {
+    const QualType Ty = (*i)->getType();
+    const BuiltinType *BT = Ty->getAs<BuiltinType>();
+
+    if (!BT || BT->getKind() != BuiltinType::Double)
+      continue;
+
+    uint64_t Offset = Layout.getFieldOffset(idx);
+    if (Offset % 64) // Ignore doubles that are not aligned.
+      continue;
+
+    // Add ((Offset - LastOffset) / 64) args of type i64.
+    for (unsigned j = (Offset - LastOffset) / 64; j > 0; --j)
+      ArgList.push_back(I64);
+
+    // Add double type.
+    ArgList.push_back(llvm::Type::getDoubleTy(getVMContext()));
+    LastOffset = Offset + 64;
+  }
+
+  // This structure 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)
+    ArgList.push_back(I64);
+
+  // Whatever is left over goes into a structure consisting of sub-doubleword
+  // types. For example, if the size of the remainder is 40-bytes,
+  // struct {i32, i8} is added to ArgList.
+  unsigned R = (StructSize - LastOffset) % 64;
+  SmallVector<llvm::Type*, 3> ArgList2;
+  
+  for (; R; R &= (R - 1))
+    ArgList2.insert(ArgList2.begin(),
+                    llvm::IntegerType::get(getVMContext(), (R & (R - 1)) ^ R));
+
+  if (!ArgList2.empty())
+    ArgList.push_back(llvm::StructType::get(getVMContext(), ArgList2));
+
+  return llvm::StructType::get(getVMContext(), ArgList);
+}
+
 ABIArgInfo MipsABIInfo::classifyArgumentType(QualType Ty) const {
   if (isAggregateTypeForABI(Ty)) {
     // Ignore empty aggregates.
@@ -3037,6 +3104,10 @@
     if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty))
       return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
 
+    llvm::Type *ResType;
+    if ((ResType = HandleStructTy(Ty)))
+      return ABIArgInfo::getDirect(ResType);
+
     return ABIArgInfo::getIndirect(0);
   }
 





More information about the cfe-commits mailing list