summaryrefslogtreecommitdiffstats
path: root/lib/Serialization/ASTWriter.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-01-27 01:47:08 +0000
committerDouglas Gregor <dgregor@apple.com>2012-01-27 01:47:08 +0000
commitcff9f26ce0ed76d555cd33b3dca84dd5cdf376af (patch)
tree6186247a39adb73209e02819b1d3078a7ec00dde /lib/Serialization/ASTWriter.cpp
parent6895a644ca9df03af14ad06deaa950a09dd352d2 (diff)
Reimplement (de-)serialization of Objective-C categories to eliminate
the direct serialization of the linked-list structure. Instead, use a scheme similar to how we handle redeclarations, with redeclaration lists on the side. This addresses several issues: - In cases involving mixing and matching of many categories across many modules, the linked-list structure would not be consistent across different modules, and categories would get lost. - If a module is loaded after the class definition and its other categories have already been loaded, we wouldn't see any categories in the newly-loaded module. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149112 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Serialization/ASTWriter.cpp')
-rw-r--r--lib/Serialization/ASTWriter.cpp90
1 files changed, 58 insertions, 32 deletions
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index c5f9b2dc88..838ec35173 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -798,11 +798,12 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(KNOWN_NAMESPACES);
RECORD(MODULE_OFFSET_MAP);
RECORD(SOURCE_MANAGER_LINE_TABLE);
- RECORD(OBJC_CHAINED_CATEGORIES);
+ RECORD(OBJC_CATEGORIES_MAP);
RECORD(FILE_SORTED_DECLS);
RECORD(IMPORTED_MODULES);
RECORD(MERGED_DECLARATIONS);
RECORD(LOCAL_REDECLARATIONS);
+ RECORD(OBJC_CATEGORIES);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
@@ -2975,6 +2976,57 @@ void ASTWriter::WriteRedeclarations() {
Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedeclChains);
}
+void ASTWriter::WriteObjCCategories() {
+ llvm::SmallVector<ObjCCategoriesInfo, 2> CategoriesMap;
+ RecordData Categories;
+
+ for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) {
+ unsigned Size = 0;
+ unsigned StartIndex = Categories.size();
+
+ ObjCInterfaceDecl *Class = ObjCClassesWithCategories[I];
+
+ // Allocate space for the size.
+ Categories.push_back(0);
+
+ // Add the categories.
+ for (ObjCCategoryDecl *Cat = Class->getCategoryList();
+ Cat; Cat = Cat->getNextClassCategory(), ++Size) {
+ assert(getDeclID(Cat) != 0 && "Bogus category");
+ AddDeclRef(Cat, Categories);
+ }
+
+ // Update the size.
+ Categories[StartIndex] = Size;
+
+ // Record this interface -> category map.
+ ObjCCategoriesInfo CatInfo = { getDeclID(Class), StartIndex };
+ CategoriesMap.push_back(CatInfo);
+ }
+
+ // Sort the categories map by the definition ID, since the reader will be
+ // performing binary searches on this information.
+ llvm::array_pod_sort(CategoriesMap.begin(), CategoriesMap.end());
+
+ // Emit the categories map.
+ using namespace llvm;
+ llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(OBJC_CATEGORIES_MAP));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned AbbrevID = Stream.EmitAbbrev(Abbrev);
+
+ RecordData Record;
+ Record.push_back(OBJC_CATEGORIES_MAP);
+ Record.push_back(CategoriesMap.size());
+ Stream.EmitRecordWithBlob(AbbrevID, Record,
+ reinterpret_cast<char*>(CategoriesMap.data()),
+ CategoriesMap.size() * sizeof(ObjCCategoriesInfo));
+
+ // Emit the category lists.
+ Stream.EmitRecord(OBJC_CATEGORIES, Categories);
+}
+
void ASTWriter::WriteMergedDecls() {
if (!Chain || Chain->MergedDecls.empty())
return;
@@ -3492,9 +3544,9 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
WriteDeclUpdatesBlocks();
WriteDeclReplacementsBlock();
- WriteChainedObjCCategories();
WriteMergedDecls();
WriteRedeclarations();
+ WriteObjCCategories();
// Some simple statistics
Record.clear();
@@ -3573,29 +3625,6 @@ void ASTWriter::WriteDeclReplacementsBlock() {
Stream.EmitRecord(DECL_REPLACEMENTS, Record);
}
-void ASTWriter::WriteChainedObjCCategories() {
- if (LocalChainedObjCCategories.empty())
- return;
-
- RecordData Record;
- for (SmallVector<ChainedObjCCategoriesData, 16>::iterator
- I = LocalChainedObjCCategories.begin(),
- E = LocalChainedObjCCategories.end(); I != E; ++I) {
- ChainedObjCCategoriesData &Data = *I;
- if (isRewritten(Data.Interface))
- continue;
-
- assert(Data.Interface->getCategoryList());
- serialization::DeclID
- HeadCatID = getDeclID(Data.Interface->getCategoryList());
-
- Record.push_back(getDeclID(Data.Interface));
- Record.push_back(HeadCatID);
- Record.push_back(getDeclID(Data.TailCategory));
- }
- Stream.EmitRecord(OBJC_CHAINED_CATEGORIES, Record);
-}
-
void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) {
Record.push_back(Loc.getRawEncoding());
}
@@ -4447,13 +4476,10 @@ void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
assert(!WritingAST && "Already writing the AST!");
if (!IFD->isFromASTFile())
return; // Declaration not imported from PCH.
- if (CatD->getNextClassCategory() &&
- !CatD->getNextClassCategory()->isFromASTFile())
- return; // We already recorded that the tail of a category chain should be
- // attached to an interface.
-
- ChainedObjCCategoriesData Data = { IFD, CatD };
- LocalChainedObjCCategories.push_back(Data);
+
+ assert(IFD->getDefinition() && "Category on a class without a definition?");
+ ObjCClassesWithCategories.insert(
+ const_cast<ObjCInterfaceDecl *>(IFD->getDefinition()));
}