diff options
Diffstat (limited to 'clang/lib/Serialization/ASTWriter.cpp')
| -rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 419 |
1 files changed, 275 insertions, 144 deletions
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index f0b12009feb..725896309ef 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -835,7 +835,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(LOCAL_REDECLARATIONS); RECORD(OBJC_CATEGORIES); RECORD(MACRO_OFFSET); - RECORD(MACRO_UPDATES); + RECORD(MACRO_TABLE); // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); @@ -1787,11 +1787,47 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // Preprocessor Serialization //===----------------------------------------------------------------------===// -static int compareMacroDefinitions(const void *XPtr, const void *YPtr) { - const std::pair<const IdentifierInfo *, MacroInfo *> &X = - *(const std::pair<const IdentifierInfo *, MacroInfo *>*)XPtr; - const std::pair<const IdentifierInfo *, MacroInfo *> &Y = - *(const std::pair<const IdentifierInfo *, MacroInfo *>*)YPtr; +namespace { +class ASTMacroTableTrait { +public: + typedef IdentID key_type; + typedef key_type key_type_ref; + + struct Data { + uint32_t MacroDirectivesOffset; + }; + + typedef Data data_type; + typedef const data_type &data_type_ref; + + static unsigned ComputeHash(IdentID IdID) { + return llvm::hash_value(IdID); + } + + std::pair<unsigned,unsigned> + static EmitKeyDataLength(raw_ostream& Out, + key_type_ref Key, data_type_ref Data) { + unsigned KeyLen = 4; // IdentID. + unsigned DataLen = 4; // MacroDirectivesOffset. + return std::make_pair(KeyLen, DataLen); + } + + static void EmitKey(raw_ostream& Out, key_type_ref Key, unsigned KeyLen) { + clang::io::Emit32(Out, Key); + } + + static void EmitData(raw_ostream& Out, key_type_ref Key, data_type_ref Data, + unsigned) { + clang::io::Emit32(Out, Data.MacroDirectivesOffset); + } +}; +} // end anonymous namespace + +static int compareMacroDirectives(const void *XPtr, const void *YPtr) { + const std::pair<const IdentifierInfo *, MacroDirective *> &X = + *(const std::pair<const IdentifierInfo *, MacroDirective *>*)XPtr; + const std::pair<const IdentifierInfo *, MacroDirective *> &Y = + *(const std::pair<const IdentifierInfo *, MacroDirective *>*)YPtr; return X.first->getName().compare(Y.first->getName()); } @@ -1837,24 +1873,68 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n"); - // Loop over all the macro definitions that are live at the end of the file, + // Loop over all the macro directives that are live at the end of the file, // emitting each to the PP section. - // Construct the list of macro definitions that need to be serialized. + // Construct the list of macro directives that need to be serialized. SmallVector<std::pair<const IdentifierInfo *, MacroDirective *>, 2> - MacrosToEmit; - for (Preprocessor::macro_iterator I = PP.macro_begin(Chain == 0), - E = PP.macro_end(Chain == 0); + MacroDirectives; + for (Preprocessor::macro_iterator + I = PP.macro_begin(/*IncludeExternalMacros=*/false), + E = PP.macro_end(/*IncludeExternalMacros=*/false); I != E; ++I) { - if (!IsModule || I->second->isPublic()) { - MacrosToEmit.push_back(std::make_pair(I->first, I->second)); - } + MacroDirectives.push_back(std::make_pair(I->first, I->second)); } // Sort the set of macro definitions that need to be serialized by the // name of the macro, to provide a stable ordering. - llvm::array_pod_sort(MacrosToEmit.begin(), MacrosToEmit.end(), - &compareMacroDefinitions); + llvm::array_pod_sort(MacroDirectives.begin(), MacroDirectives.end(), + &compareMacroDirectives); + + OnDiskChainedHashTableGenerator<ASTMacroTableTrait> Generator; + + // Emit the macro directives as a list and associate the offset with the + // identifier they belong to. + for (unsigned I = 0, N = MacroDirectives.size(); I != N; ++I) { + const IdentifierInfo *Name = MacroDirectives[I].first; + uint64_t MacroDirectiveOffset = Stream.GetCurrentBitNo(); + MacroDirective *MD = MacroDirectives[I].second; + + // If the macro or identifier need no updates, don't write the macro history + // for this one. + if (MD->isFromPCH() && !MD->hasChangedAfterLoad() && + Name->isFromAST() && !Name->hasChangedSinceDeserialization()) + continue; + + // Emit the macro directives in reverse source order. + for (; MD; MD = MD->getPrevious()) { + if (shouldIgnoreMacro(MD, IsModule, PP)) + continue; + MacroID InfoID = getMacroRef(MD->getInfo(), Name); + if (InfoID == 0) + continue; + + Record.push_back(InfoID); + AddSourceLocation(MD->getLocation(), Record); + AddSourceLocation(MD->getUndefLoc(), Record); + AddSourceLocation(MD->getVisibilityLocation(), Record); + Record.push_back(MD->isImported()); + Record.push_back(MD->isPublic()); + Record.push_back(MD->isAmbiguous()); + } + if (Record.empty()) + continue; + + Stream.EmitRecord(PP_MACRO_DIRECTIVE_HISTORY, Record); + Record.clear(); + + IdentMacroDirectivesOffsetMap[Name] = MacroDirectiveOffset; + + IdentID NameID = getIdentifierRef(Name); + ASTMacroTableTrait::Data data; + data.MacroDirectivesOffset = MacroDirectiveOffset; + Generator.insert(NameID, data); + } /// \brief Offsets of each of the macros into the bitstream, indexed by /// the local macro ID @@ -1864,101 +1944,107 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { /// defined. std::vector<uint32_t> MacroOffsets; - for (unsigned I = 0, N = MacrosToEmit.size(); I != N; ++I) { - const IdentifierInfo *Name = MacrosToEmit[I].first; + for (unsigned I = 0, N = MacroInfosToEmit.size(); I != N; ++I) { + const IdentifierInfo *Name = MacroInfosToEmit[I].Name; + MacroInfo *MI = MacroInfosToEmit[I].MI; + MacroID ID = MacroInfosToEmit[I].ID; - for (MacroDirective *MD = MacrosToEmit[I].second; MD; - MD = MD->getPrevious()) { - if (shouldIgnoreMacro(MD, IsModule, PP)) - continue; - - MacroID ID = getMacroRef(MD); - if (!ID) - continue; + if (ID < FirstMacroID) { + assert(0 && "Loaded MacroInfo entered MacroInfosToEmit ?"); + continue; + } - // Skip macros from a AST file if we're chaining. - if (Chain && MD->isImported() && !MD->hasChangedAfterLoad()) - 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); - if (ID < FirstMacroID) { - // This will have been dealt with via an update record. - assert(MacroUpdates.count(MD) > 0 && "Missing macro update"); - continue; - } + MacroOffsets[Index] = Stream.GetCurrentBitNo(); + } - // 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); + AddIdentifierRef(Name, Record); + Record.push_back(inferSubmoduleIDFromLocation(MI->getDefinitionLoc())); + AddSourceLocation(MI->getDefinitionLoc(), Record); + AddSourceLocation(MI->getDefinitionEndLoc(), Record); + Record.push_back(MI->isUsed()); + unsigned Code; + if (MI->isObjectLike()) { + Code = PP_MACRO_OBJECT_LIKE; + } else { + Code = PP_MACRO_FUNCTION_LIKE; - MacroOffsets[Index] = Stream.GetCurrentBitNo(); - } + Record.push_back(MI->isC99Varargs()); + Record.push_back(MI->isGNUVarargs()); + Record.push_back(MI->hasCommaPasting()); + Record.push_back(MI->getNumArgs()); + for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end(); + I != E; ++I) + AddIdentifierRef(*I, Record); + } - AddIdentifierRef(Name, Record); - addMacroRef(MD, Record); - const MacroInfo *MI = MD->getInfo(); - Record.push_back(inferSubmoduleIDFromLocation(MI->getDefinitionLoc())); - AddSourceLocation(MI->getDefinitionLoc(), Record); - AddSourceLocation(MI->getDefinitionEndLoc(), Record); - AddSourceLocation(MD->getUndefLoc(), Record); - Record.push_back(MI->isUsed()); - Record.push_back(MD->isPublic()); - AddSourceLocation(MD->getVisibilityLocation(), Record); - unsigned Code; - if (MI->isObjectLike()) { - Code = PP_MACRO_OBJECT_LIKE; - } else { - Code = PP_MACRO_FUNCTION_LIKE; - - Record.push_back(MI->isC99Varargs()); - Record.push_back(MI->isGNUVarargs()); - Record.push_back(MI->hasCommaPasting()); - Record.push_back(MI->getNumArgs()); - for (MacroInfo::arg_iterator I = MI->arg_begin(), E = MI->arg_end(); - I != E; ++I) - AddIdentifierRef(*I, Record); - } + // If we have a detailed preprocessing record, record the macro definition + // ID that corresponds to this macro. + if (PPRec) + Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]); - // If we have a detailed preprocessing record, record the macro definition - // ID that corresponds to this macro. - if (PPRec) - Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]); + Stream.EmitRecord(Code, Record); + Record.clear(); - Stream.EmitRecord(Code, Record); + // Emit the tokens array. + for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) { + // Note that we know that the preprocessor does not have any annotation + // tokens in it because they are created by the parser, and thus can't + // be in a macro definition. + const Token &Tok = MI->getReplacementToken(TokNo); + + Record.push_back(Tok.getLocation().getRawEncoding()); + Record.push_back(Tok.getLength()); + + // FIXME: When reading literal tokens, reconstruct the literal pointer + // if it is needed. + AddIdentifierRef(Tok.getIdentifierInfo(), Record); + // FIXME: Should translate token kind to a stable encoding. + Record.push_back(Tok.getKind()); + // FIXME: Should translate token flags to a stable encoding. + Record.push_back(Tok.getFlags()); + + Stream.EmitRecord(PP_TOKEN, Record); Record.clear(); - - // Emit the tokens array. - for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) { - // Note that we know that the preprocessor does not have any annotation - // tokens in it because they are created by the parser, and thus can't - // be in a macro definition. - const Token &Tok = MI->getReplacementToken(TokNo); - - Record.push_back(Tok.getLocation().getRawEncoding()); - Record.push_back(Tok.getLength()); - - // FIXME: When reading literal tokens, reconstruct the literal pointer - // if it is needed. - AddIdentifierRef(Tok.getIdentifierInfo(), Record); - // FIXME: Should translate token kind to a stable encoding. - Record.push_back(Tok.getKind()); - // FIXME: Should translate token flags to a stable encoding. - Record.push_back(Tok.getFlags()); - - Stream.EmitRecord(PP_TOKEN, Record); - Record.clear(); - } - ++NumMacros; } + ++NumMacros; } + Stream.ExitBlock(); - // Write the offsets table for macro IDs. + // Create the on-disk hash table in a buffer. + SmallString<4096> MacroTable; + uint32_t BucketOffset; + { + llvm::raw_svector_ostream Out(MacroTable); + // Make sure that no bucket is at offset 0 + clang::io::Emit32(Out, 0); + BucketOffset = Generator.Emit(Out); + } + + // Write the macro table using namespace llvm; BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + Abbrev->Add(BitCodeAbbrevOp(MACRO_TABLE)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned MacroTableAbbrev = Stream.EmitAbbrev(Abbrev); + + Record.push_back(MACRO_TABLE); + Record.push_back(BucketOffset); + Stream.EmitRecordWithBlob(MacroTableAbbrev, Record, MacroTable.str()); + Record.clear(); + + // Write the offsets table for macro IDs. + using namespace llvm; + Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID @@ -2801,13 +2887,61 @@ class ASTIdentifierTableTrait { if (!II->hadMacroDefinition()) return false; - if (Macro || (Macro = PP.getMacroDirectiveHistory(II))) - return !shouldIgnoreMacro(Macro, IsModule, PP) && - (!IsModule || Macro->isPublic()); + if (Macro || (Macro = PP.getMacroDirectiveHistory(II))) { + if (!IsModule) + return !shouldIgnoreMacro(Macro, IsModule, PP); + SubmoduleID ModID; + if (getFirstPublicSubmoduleMacro(Macro, ModID)) + return true; + } return false; } + MacroDirective *getFirstPublicSubmoduleMacro(MacroDirective *MD, + SubmoduleID &ModID) { + if (shouldIgnoreMacro(MD, IsModule, PP)) + return 0; + ModID = getSubmoduleID(MD); + if (ModID == 0) + return 0; + if (MD->isDefined() && MD->isPublic()) + return MD; + return getNextPublicSubmoduleMacro(MD, ModID); + } + + MacroDirective *getNextPublicSubmoduleMacro(MacroDirective *MD, + SubmoduleID &ModID) { + while (MD) { + MD = getNextSubmoduleMacro(MD, ModID); + if (MD && MD->isDefined() && MD->isPublic()) + return MD; + } + return 0; + } + + MacroDirective *getNextSubmoduleMacro(MacroDirective *CurrMD, + SubmoduleID &CurrModID) { + SubmoduleID OrigID = CurrModID; + while ((CurrMD = CurrMD->getPrevious())) { + if (shouldIgnoreMacro(CurrMD, IsModule, PP)) + return 0; + CurrModID = getSubmoduleID(CurrMD); + if (CurrModID == 0) + return 0; + if (CurrModID != OrigID) + return CurrMD; + } + return 0; + } + + SubmoduleID getSubmoduleID(MacroDirective *MD) { + MacroInfo *MI = MD->getInfo(); + if (unsigned ID = MI->getOwningModuleID()) + return ID; + return Writer.inferSubmoduleIDFromLocation(MI->getDefinitionLoc()); + } + public: typedef IdentifierInfo* key_type; typedef key_type key_type_ref; @@ -2832,14 +2966,15 @@ public: DataLen += 2; // 2 bytes for builtin ID DataLen += 2; // 2 bytes for flags if (hadMacroDefinition(II, Macro)) { - for (MacroDirective *M = Macro; M; M = M->getPrevious()) { - if (shouldIgnoreMacro(M, IsModule, PP)) - continue; - if (Writer.getMacroRef(M) != 0) - DataLen += 4; + DataLen += 4; // MacroDirectives offset. + if (IsModule) { + SubmoduleID ModID; + for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, ModID); + MD; MD = getNextPublicSubmoduleMacro(MD, ModID)) { + DataLen += 4; // MacroInfo ID. + } + DataLen += 4; } - - DataLen += 4; } for (IdentifierResolver::iterator D = IdResolver.begin(II), @@ -2878,6 +3013,7 @@ public: Bits = 0; bool HadMacroDefinition = hadMacroDefinition(II, Macro); Bits = (Bits << 1) | unsigned(HadMacroDefinition); + Bits = (Bits << 1) | unsigned(IsModule); Bits = (Bits << 1) | unsigned(II->isExtensionToken()); Bits = (Bits << 1) | unsigned(II->isPoisoned()); Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier()); @@ -2885,15 +3021,18 @@ public: clang::io::Emit16(Out, Bits); if (HadMacroDefinition) { - // Write all of the macro IDs associated with this identifier. - for (MacroDirective *M = Macro; M; M = M->getPrevious()) { - if (shouldIgnoreMacro(M, IsModule, PP)) - continue; - if (MacroID ID = Writer.getMacroRef(M)) - clang::io::Emit32(Out, ID); + clang::io::Emit32(Out, Writer.getMacroDirectivesOffset(II)); + if (IsModule) { + // Write the IDs of macros coming from different submodules. + SubmoduleID ModID; + for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, ModID); + MD; MD = getNextPublicSubmoduleMacro(MD, ModID)) { + MacroID InfoID = Writer.getMacroID(MD->getInfo()); + assert(InfoID); + clang::io::Emit32(Out, InfoID); + } + clang::io::Emit32(Out, 0); } - - clang::io::Emit32(Out, 0); } // Emit the declaration IDs in reverse order, because the @@ -3968,7 +4107,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, } } - WriteMacroUpdates(); WriteDeclUpdatesBlocks(); WriteDeclReplacementsBlock(); WriteRedeclarations(); @@ -3985,21 +4123,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, 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); - Record.push_back(inferSubmoduleIDFromLocation(I->second.UndefLoc)); - } - Stream.EmitRecord(MACRO_UPDATES, Record); -} - /// \brief Go through the declaration update blocks and resolve declaration /// pointers into declaration IDs. void ASTWriter::ResolveDeclUpdatesBlocks() { @@ -4095,10 +4218,6 @@ void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Recor Record.push_back(getIdentifierRef(II)); } -void ASTWriter::addMacroRef(MacroDirective *MD, RecordDataImpl &Record) { - Record.push_back(getMacroRef(MD)); -} - IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { if (II == 0) return 0; @@ -4109,19 +4228,35 @@ IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) { return ID; } -MacroID ASTWriter::getMacroRef(MacroDirective *MD) { +MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) { // 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 (MD == 0 || MD->getInfo()->isBuiltinMacro()) + if (MI == 0 || MI->isBuiltinMacro()) return 0; - MacroID &ID = MacroIDs[MD]; - if (ID == 0) + MacroID &ID = MacroIDs[MI]; + if (ID == 0) { ID = NextMacroID++; + MacroInfoToEmitData Info = { Name, MI, ID }; + MacroInfosToEmit.push_back(Info); + } return ID; } +MacroID ASTWriter::getMacroID(MacroInfo *MI) { + if (MI == 0 || MI->isBuiltinMacro()) + return 0; + + assert(MacroIDs.find(MI) != MacroIDs.end() && "Macro not emitted!"); + return MacroIDs[MI]; +} + +uint64_t ASTWriter::getMacroDirectivesOffset(const IdentifierInfo *Name) { + assert(IdentMacroDirectivesOffsetMap[Name] && "not set!"); + return IdentMacroDirectivesOffsetMap[Name]; +} + void ASTWriter::AddSelectorRef(const Selector SelRef, RecordDataImpl &Record) { Record.push_back(getSelectorRef(SelRef)); } @@ -4861,9 +4996,9 @@ void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) { StoredID = ID; } -void ASTWriter::MacroRead(serialization::MacroID ID, MacroDirective *MD) { +void ASTWriter::MacroRead(serialization::MacroID ID, MacroInfo *MI) { // Always keep the highest ID. See \p TypeRead() for more information. - MacroID &StoredID = MacroIDs[MD]; + MacroID &StoredID = MacroIDs[MI]; if (ID > StoredID) StoredID = ID; } @@ -4897,10 +5032,6 @@ void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) { SubmoduleIDs[Mod] = ID; } -void ASTWriter::UndefinedMacro(MacroDirective *MD) { - MacroUpdates[MD].UndefLoc = MD->getUndefLoc(); -} - void ASTWriter::CompletedTagDefinition(const TagDecl *D) { assert(D->isCompleteDefinition()); assert(!WritingAST && "Already writing the AST!"); |

