From 820e0203079afd64b0de422832f9e0b31a27c0c8 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 11 Mar 2009 00:07:04 +0000 Subject: [PATCH] More Next objc2's gc ivar layout bitmap work. Work in progress. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66615 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Type.h | 9 +++ lib/CodeGen/CGObjCMac.cpp | 131 +++++++++++++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 3 deletions(-) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 2487da61c8..2698a2e16a 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -369,6 +369,10 @@ public: /// interface types. bool hasPointerRepresentation() const; + /// hasObjCPointerRepresentation - Whether this type can represent + /// an objective pointer type for the purpose of GC'ability + bool hasObjCPointerRepresentation() const; + // Type Checking Functions: Check to see if this type is structurally the // specified type, ignoring typedefs and qualifiers, and return a pointer to // the best type we can. @@ -1866,6 +1870,11 @@ inline bool Type::hasPointerRepresentation() const { isObjCQualifiedInterfaceType()); } +inline bool Type::hasObjCPointerRepresentation() const { + return (isObjCInterfaceType() || isObjCQualifiedIdType() || + isObjCQualifiedInterfaceType()); +} + /// Insertion operator for diagnostics. This allows sending QualType's into a /// diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 9f3e3035d3..45e4b1286c 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -308,6 +308,7 @@ public: class CGObjCCommonMac : public CodeGen::CGObjCRuntime { class GC_IVAR { + public: unsigned int ivar_bytepos; unsigned int ivar_size; GC_IVAR() : ivar_bytepos(0), ivar_size(0) {} @@ -2461,11 +2462,15 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const llvm::StructLayout *Layout, const std::vector& RecFields, unsigned int BytePos, bool ForStrongLayout, int &Index, int &SkIndex, bool &HasUnion) { - bool is_union = (RD && RD->isUnion()); + bool IsUnion = (RD && RD->isUnion()); + uint64_t MaxUnionIvarSize = 0; + uint64_t MaxSkippedUnionIvarSize = 0; + FieldDecl *MaxField = 0; + FieldDecl *MaxSkippedField = 0; unsigned int base = 0; if (RecFields.empty()) return; - if (is_union) + if (IsUnion) base = BytePos + GetIvarBaseOffset(Layout, RecFields[0]); for (unsigned i = 0; i < RecFields.size(); i++) { @@ -2478,6 +2483,10 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const llvm::StructLayout *Layout, std::vector NestedRecFields; if (FQT->isUnionType()) HasUnion = true; + else + assert(FQT->isRecordType() && + "only union/record is supported for ivar layout bitmap"); + const RecordType *RT = FQT->getAsRecordType(); const RecordDecl *RD = RT->getDecl(); // FIXME - Find a more efficiant way of passing records down. @@ -2493,8 +2502,124 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const llvm::StructLayout *Layout, continue; } else if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { - FQT = Array->getElementType(); + const ConstantArrayType *CArray = + dyn_cast_or_null(Array); + assert(CArray && "only array with know element size is supported"); + FQT = CArray->getElementType(); + assert(!FQT->isUnionType() && + "layout for array of unions not supported"); + if (FQT->isRecordType()) { + uint64_t ElCount = CArray->getSize().getZExtValue(); + int OldIndex = Index; + int OldSkIndex = SkIndex; + + std::vector ElementRecFields; + // FIXME - Use a common routine with the above! + const RecordType *RT = FQT->getAsRecordType(); + const RecordDecl *RD = RT->getDecl(); + // FIXME - Find a more efficiant way of passing records down. + unsigned j = 0; + for (RecordDecl::field_iterator i = RD->field_begin(), + e = RD->field_end(); i != e; ++i) + ElementRecFields[j++] = (*i); + BuildAggrIvarLayout(Layout, RD, + ElementRecFields, + BytePos + GetIvarBaseOffset(Layout, Field), + ForStrongLayout, Index, SkIndex, + HasUnion); + // Replicate layout information for each array element. Note that + // one element is already done. + uint64_t ElIx = 1; + for (int FirstIndex = Index, FirstSkIndex = SkIndex; + ElIx < ElCount; ElIx++) { + uint64_t Size = CGM.getContext().getTypeSize(RT); + for (int i = OldIndex+1; i <= FirstIndex; ++i) + { + IvarsInfo[++Index].ivar_bytepos = + IvarsInfo[i].ivar_bytepos + Size*ElIx; + IvarsInfo[Index].ivar_size = IvarsInfo[i].ivar_size; + } + + for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i) + { + SkipIvars[++SkIndex].ivar_bytepos = + SkipIvars[i].ivar_bytepos + Size*ElIx; + SkipIvars[SkIndex].ivar_size = SkipIvars[i].ivar_size; + } + } + continue; + } + } + // At this point, we are done with Record/Union and array there of. + // For other arrays we are down to its element type. + QualType::GCAttrTypes GCAttr = QualType::GCNone; + do { + if (FQT.isObjCGCStrong() || FQT.isObjCGCWeak()) { + GCAttr = FQT.isObjCGCStrong() ? QualType::Strong : QualType::Weak; + break; + } + else if (FQT->hasObjCPointerRepresentation()) { + GCAttr = QualType::Strong; + break; + } + else if (const PointerType *PT = FQT->getAsPointerType()) { + FQT = PT->getPointeeType(); + } + else { + break; + } + } while (true); + if ((ForStrongLayout && GCAttr == QualType::Strong) + || (!ForStrongLayout && GCAttr == QualType::Weak)) { + if (IsUnion) + { + uint64_t UnionIvarSize = CGM.getContext().getTypeSize(Field->getType()); + if (UnionIvarSize > MaxUnionIvarSize) + { + MaxUnionIvarSize = UnionIvarSize; + MaxField = Field; + } + } + else + { + IvarsInfo[++Index].ivar_bytepos = + BytePos + GetIvarBaseOffset(Layout, Field); + IvarsInfo[Index].ivar_size = + CGM.getContext().getTypeSize(Field->getType()); + } } + else if ((ForStrongLayout && + (GCAttr == QualType::GCNone || GCAttr == QualType::Weak)) + || (!ForStrongLayout && GCAttr != QualType::Weak)) { + if (IsUnion) + { + uint64_t UnionIvarSize = CGM.getContext().getTypeSize(Field->getType()); + if (UnionIvarSize > MaxSkippedUnionIvarSize) + { + MaxSkippedUnionIvarSize = UnionIvarSize; + MaxSkippedField = Field; + } + } + else + { + SkipIvars[++SkIndex].ivar_bytepos = + BytePos + GetIvarBaseOffset(Layout, Field); + SkipIvars[SkIndex].ivar_size = + CGM.getContext().getTypeSize(Field->getType()); + } + } + } + if (MaxField) + { + IvarsInfo[++Index].ivar_bytepos = + BytePos + GetIvarBaseOffset(Layout, MaxField); + IvarsInfo[Index].ivar_size = MaxUnionIvarSize; + } + if (MaxSkippedField) + { + SkipIvars[++SkIndex].ivar_bytepos = + BytePos + GetIvarBaseOffset(Layout, MaxSkippedField); + SkipIvars[SkIndex].ivar_size = MaxSkippedUnionIvarSize; } return; } -- 2.40.0