diff options
Diffstat (limited to 'clang/lib/Serialization/ASTWriter.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 127 |
1 files changed, 100 insertions, 27 deletions
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 19a236fde2f..76eb1a1a8a1 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -820,6 +820,8 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(MERGED_DECLARATIONS); RECORD(LOCAL_REDECLARATIONS); RECORD(OBJC_CATEGORIES); + RECORD(MACRO_OFFSET); + RECORD(MACRO_UPDATES); // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); @@ -1702,37 +1704,46 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { PP.getMacroInfoHistory(Name))); } + /// \brief Offsets of each of the macros into the bitstream, indexed by + /// the local macro ID + /// + /// For each identifier that is associated with a macro, this map + /// provides the offset into the bitstream where that macro is + /// defined. + std::vector<uint32_t> MacroOffsets; + for (unsigned I = 0, N = MacrosToEmit.size(); I != N; ++I) { const IdentifierInfo *Name = MacrosToEmit[I].first; - MacroInfo *MI = MacrosToEmit[I].second; - // History of macro definitions for this identifier in chronological order. - SmallVector<MacroInfo*, 8> MacroHistory; - while (MI) { - MacroHistory.push_back(MI); - MI = MI->getPreviousDefinition(); - } + for (MacroInfo *MI = MacrosToEmit[I].second; MI; + MI = MI->getPreviousDefinition()) { + MacroID ID = getMacroRef(MI); + if (!ID) + continue; + + // Skip macros from a AST file if we're chaining. + if (Chain && MI->isFromAST() && !MI->hasChangedAfterLoad()) + continue; - while (!MacroHistory.empty()) { - MI = MacroHistory.pop_back_val(); - - // Don't emit builtin macros like __LINE__ to the AST file unless they - // have been redefined by the header (in which case they are not - // isBuiltinMacro). - // Also skip macros from a AST file if we're chaining. - - // FIXME: There is a (probably minor) optimization we could do here, if - // the macro comes from the original PCH but the identifier comes from a - // chained PCH, by storing the offset into the original PCH rather than - // writing the macro definition a second time. - if (MI->isBuiltinMacro() || - (Chain && - Name->isFromAST() && !Name->hasChangedSinceDeserialization() && - MI->isFromAST() && !MI->hasChangedAfterLoad())) + if (ID < FirstMacroID) { + // This will have been dealt with via an update record. + assert(MacroUpdates.count(MI) > 0 && "Missing macro update"); continue; + } + + // Record the local offset of this macro. + unsigned Index = ID - FirstMacroID; + if (Index == MacroOffsets.size()) + MacroOffsets.push_back(Stream.GetCurrentBitNo()); + else { + if (Index > MacroOffsets.size()) + MacroOffsets.resize(Index + 1); + + MacroOffsets[Index] = Stream.GetCurrentBitNo(); + } AddIdentifierRef(Name, Record); - MacroOffsets[Name] = Stream.GetCurrentBitNo(); + addMacroRef(MI, Record); AddSourceLocation(MI->getDefinitionLoc(), Record); AddSourceLocation(MI->getUndefLoc(), Record); Record.push_back(MI->isUsed()); @@ -1785,6 +1796,22 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { } } Stream.ExitBlock(); + + // Write the offsets table for macro IDs. + using namespace llvm; + BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + + unsigned MacroOffsetAbbrev = Stream.EmitAbbrev(Abbrev); + Record.clear(); + Record.push_back(MACRO_OFFSET); + Record.push_back(MacroOffsets.size()); + Record.push_back(FirstMacroID - NUM_PREDEF_MACRO_IDS); + Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record, + data(MacroOffsets)); } void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) { @@ -2608,7 +2635,7 @@ public: clang::io::Emit16(Out, Bits); if (HadMacroDefinition) { - clang::io::Emit32(Out, Writer.getMacroOffset(II)); + clang::io::Emit32(Out, Writer.getMacroRef(Macro)); clang::io::Emit32(Out, Writer.inferSubmoduleIDFromLocation(Macro->getDefinitionLoc())); } @@ -3182,7 +3209,8 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream) ASTHasCompilerErrors(false), FirstDeclID(NUM_PREDEF_DECL_IDS), NextDeclID(FirstDeclID), FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID), - FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), + FirstIdentID(NUM_PREDEF_IDENT_IDS), NextIdentID(FirstIdentID), + FirstMacroID(NUM_PREDEF_MACRO_IDS), NextMacroID(FirstMacroID), FirstSubmoduleID(NUM_PREDEF_SUBMODULE_IDS), NextSubmoduleID(FirstSubmoduleID), FirstSelectorID(NUM_PREDEF_SELECTOR_IDS), NextSelectorID(FirstSelectorID), @@ -3517,6 +3545,7 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, Out.write(FileName.data(), FileName.size()); io::Emit32(Out, (*M)->SLocEntryBaseOffset); io::Emit32(Out, (*M)->BaseIdentifierID); + io::Emit32(Out, (*M)->BaseMacroID); io::Emit32(Out, (*M)->BasePreprocessedEntityID); io::Emit32(Out, (*M)->BaseSubmoduleID); io::Emit32(Out, (*M)->BaseSelectorID); @@ -3630,7 +3659,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, Stream.EmitRecord(IMPORTED_MODULES, ImportedModules); } } - + + WriteMacroUpdates(); WriteDeclUpdatesBlocks(); WriteDeclReplacementsBlock(); WriteMergedDecls(); @@ -3647,6 +3677,20 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, Stream.ExitBlock(); } +void ASTWriter::WriteMacroUpdates() { + if (MacroUpdates.empty()) + return; + + RecordData Record; + for (MacroUpdatesMap::iterator I = MacroUpdates.begin(), + E = MacroUpdates.end(); + I != E; ++I) { + addMacroRef(I->first, Record); + AddSourceLocation(I->second.UndefLoc, Record); + } + Stream.EmitRecord(MACRO_UPDATES, Record); +} + /// \brief Go through the declaration update blocks and resolve declaration /// pointers into declaration IDs. void ASTWriter::ResolveDeclUpdatesBlocks() { @@ -3742,6 +3786,10 @@ void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Recor Record.push_back(getIdentifierRef(II)); } +void ASTWriter::addMacroRef(MacroInfo *MI, RecordDataImpl &Record) { + Record.push_back(getMacroRef(MI)); +} + IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { if (II == 0) return 0; @@ -3752,6 +3800,19 @@ IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { return ID; } +MacroID ASTWriter::getMacroRef(MacroInfo *MI) { + // Don't emit builtin macros like __LINE__ to the AST file unless they + // have been redefined by the header (in which case they are not + // isBuiltinMacro). + if (MI == 0 || MI->isBuiltinMacro()) + return 0; + + MacroID &ID = MacroIDs[MI]; + if (ID == 0) + ID = NextMacroID++; + return ID; +} + void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) { Record.push_back(getSelectorRef(SelRef)); } @@ -4464,6 +4525,7 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { assert(FirstDeclID == NextDeclID && FirstTypeID == NextTypeID && FirstIdentID == NextIdentID && + FirstMacroID == NextMacroID && FirstSubmoduleID == NextSubmoduleID && FirstSelectorID == NextSelectorID && "Setting chain after writing has started."); @@ -4473,11 +4535,13 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) { FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls(); FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes(); FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers(); + FirstMacroID = NUM_PREDEF_MACRO_IDS + Chain->getTotalNumMacros(); FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules(); FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors(); NextDeclID = FirstDeclID; NextTypeID = FirstTypeID; NextIdentID = FirstIdentID; + NextMacroID = FirstMacroID; NextSelectorID = FirstSelectorID; NextSubmoduleID = FirstSubmoduleID; } @@ -4488,6 +4552,10 @@ void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { DeserializedMacroNames.push_back(II); } +void ASTWriter::MacroRead(serialization::MacroID ID, MacroInfo *MI) { + MacroIDs[MI] = ID; +} + void ASTWriter::TypeRead(TypeIdx Idx, QualType T) { // Always take the highest-numbered type index. This copes with an interesting // case for chained AST writing where we schedule writing the type and then, @@ -4518,6 +4586,10 @@ void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) { SubmoduleIDs[Mod] = ID; } +void ASTWriter::UndefinedMacro(MacroInfo *MI) { + MacroUpdates[MI].UndefLoc = MI->getUndefLoc(); +} + void ASTWriter::CompletedTagDefinition(const TagDecl *D) { assert(D->isCompleteDefinition()); assert(!WritingAST && "Already writing the AST!"); @@ -4531,6 +4603,7 @@ void ASTWriter::CompletedTagDefinition(const TagDecl *D) { } } } + void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) { assert(!WritingAST && "Already writing the AST!"); |