diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /clang/lib/Serialization/ASTWriter.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'clang/lib/Serialization/ASTWriter.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 500 |
1 files changed, 353 insertions, 147 deletions
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 0739dcc1ce60..bdf11001473e 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -77,7 +77,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" @@ -100,6 +99,7 @@ #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/Path.h" #include "llvm/Support/SHA1.h" +#include "llvm/Support/TimeProfiler.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -108,9 +108,9 @@ #include <cstdlib> #include <cstring> #include <ctime> -#include <deque> #include <limits> #include <memory> +#include <optional> #include <queue> #include <tuple> #include <utility> @@ -161,12 +161,14 @@ static TypeCode getTypeCodeForTypeClass(Type::TypeClass id) { namespace { -std::set<const FileEntry *> GetAllModuleMaps(const HeaderSearch &HS, - Module *RootModule) { +std::set<const FileEntry *> GetAffectingModuleMaps(const Preprocessor &PP, + Module *RootModule) { std::set<const FileEntry *> ModuleMaps{}; std::set<const Module *> ProcessedModules; SmallVector<const Module *> ModulesToProcess{RootModule}; + const HeaderSearch &HS = PP.getHeaderSearchInfo(); + SmallVector<const FileEntry *, 16> FilesByUID; HS.getFileMgr().GetUniqueIDMapping(FilesByUID); @@ -190,30 +192,36 @@ std::set<const FileEntry *> GetAllModuleMaps(const HeaderSearch &HS, } } - while (!ModulesToProcess.empty()) { - auto *CurrentModule = ModulesToProcess.pop_back_val(); - ProcessedModules.insert(CurrentModule); + const ModuleMap &MM = HS.getModuleMap(); + SourceManager &SourceMgr = PP.getSourceManager(); - auto *ModuleMapFile = - HS.getModuleMap().getModuleMapFileForUniquing(CurrentModule); - if (!ModuleMapFile) { - continue; + auto ForIncludeChain = [&](FileEntryRef F, + llvm::function_ref<void(FileEntryRef)> CB) { + CB(F); + FileID FID = SourceMgr.translateFile(F); + SourceLocation Loc = SourceMgr.getIncludeLoc(FID); + while (Loc.isValid()) { + FID = SourceMgr.getFileID(Loc); + CB(*SourceMgr.getFileEntryRefForID(FID)); + Loc = SourceMgr.getIncludeLoc(FID); } + }; - ModuleMaps.insert(ModuleMapFile); - - for (auto *ImportedModule : (CurrentModule)->Imports) { - if (!ImportedModule || - ProcessedModules.find(ImportedModule) != ProcessedModules.end()) { - continue; - } - ModulesToProcess.push_back(ImportedModule); - } + auto ProcessModuleOnce = [&](const Module *M) { + for (const Module *Mod = M; Mod; Mod = Mod->Parent) + if (ProcessedModules.insert(Mod).second) + if (auto ModuleMapFile = MM.getModuleMapFileForUniquing(Mod)) + ForIncludeChain(*ModuleMapFile, [&](FileEntryRef F) { + ModuleMaps.insert(F); + }); + }; + for (const Module *CurrentModule : ModulesToProcess) { + ProcessModuleOnce(CurrentModule); + for (const Module *ImportedModule : CurrentModule->Imports) + ProcessModuleOnce(ImportedModule); for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses) - if (UndeclaredModule && - ProcessedModules.find(UndeclaredModule) == ProcessedModules.end()) - ModulesToProcess.push_back(UndeclaredModule); + ProcessModuleOnce(UndeclaredModule); } return ModuleMaps; @@ -437,7 +445,7 @@ void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { addSourceLocation(TL.getTypeofLoc()); addSourceLocation(TL.getLParenLoc()); addSourceLocation(TL.getRParenLoc()); - Record.AddTypeSourceInfo(TL.getUnderlyingTInfo()); + Record.AddTypeSourceInfo(TL.getUnmodifiedTInfo()); } void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { @@ -463,8 +471,9 @@ void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) { addSourceLocation(TL.getLAngleLoc()); addSourceLocation(TL.getRAngleLoc()); for (unsigned I = 0; I < TL.getNumArgs(); ++I) - Record.AddTemplateArgumentLocInfo(TL.getTypePtr()->getArg(I).getKind(), - TL.getArgLocInfo(I)); + Record.AddTemplateArgumentLocInfo( + TL.getTypePtr()->getTypeConstraintArguments()[I].getKind(), + TL.getArgLocInfo(I)); } Record.push_back(TL.isDecltypeAuto()); if (TL.isDecltypeAuto()) @@ -560,6 +569,7 @@ void TypeLocWriter::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { addSourceLocation(TL.getNameLoc()); + addSourceLocation(TL.getNameEndLoc()); } void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { @@ -734,6 +744,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_USER_DEFINED_LITERAL); RECORD(EXPR_CXX_STD_INITIALIZER_LIST); RECORD(EXPR_CXX_BOOL_LITERAL); + RECORD(EXPR_CXX_PAREN_LIST_INIT); RECORD(EXPR_CXX_NULL_PTR_LITERAL); RECORD(EXPR_CXX_TYPEID_EXPR); RECORD(EXPR_CXX_TYPEID_TYPE); @@ -786,7 +797,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(MODULE_MAP_FILE); RECORD(IMPORTS); RECORD(ORIGINAL_FILE); - RECORD(ORIGINAL_PCH_DIR); RECORD(ORIGINAL_FILE_ID); RECORD(INPUT_FILE_OFFSETS); @@ -884,6 +894,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(SUBMODULE_TOPHEADER); RECORD(SUBMODULE_UMBRELLA_DIR); RECORD(SUBMODULE_IMPORTS); + RECORD(SUBMODULE_AFFECTING_MODULES); RECORD(SUBMODULE_EXPORTS); RECORD(SUBMODULE_REQUIRES); RECORD(SUBMODULE_EXCLUDED_HEADER); @@ -1017,6 +1028,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DECL_PRAGMA_DETECT_MISMATCH); RECORD(DECL_OMP_DECLARE_REDUCTION); RECORD(DECL_OMP_ALLOCATE); + RECORD(DECL_HLSL_BUFFER); // Statements and Exprs can occur in the Decls and Types block. AddStmtsExprs(Stream, Record); @@ -1034,6 +1046,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(SIGNATURE); RECORD(AST_BLOCK_HASH); RECORD(DIAGNOSTIC_OPTIONS); + RECORD(HEADER_SEARCH_PATHS); RECORD(DIAG_PRAGMA_MAPPINGS); #undef RECORD @@ -1164,6 +1177,35 @@ ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP, Stream.EmitRecord(DIAGNOSTIC_OPTIONS, Record); Record.clear(); + // Header search paths. + Record.clear(); + const HeaderSearchOptions &HSOpts = + PP.getHeaderSearchInfo().getHeaderSearchOpts(); + + // Include entries. + Record.push_back(HSOpts.UserEntries.size()); + for (unsigned I = 0, N = HSOpts.UserEntries.size(); I != N; ++I) { + const HeaderSearchOptions::Entry &Entry = HSOpts.UserEntries[I]; + AddString(Entry.Path, Record); + Record.push_back(static_cast<unsigned>(Entry.Group)); + Record.push_back(Entry.IsFramework); + Record.push_back(Entry.IgnoreSysRoot); + } + + // System header prefixes. + Record.push_back(HSOpts.SystemHeaderPrefixes.size()); + for (unsigned I = 0, N = HSOpts.SystemHeaderPrefixes.size(); I != N; ++I) { + AddString(HSOpts.SystemHeaderPrefixes[I].Prefix, Record); + Record.push_back(HSOpts.SystemHeaderPrefixes[I].IsSystemHeader); + } + + // VFS overlay files. + Record.push_back(HSOpts.VFSOverlayFiles.size()); + for (StringRef VFSOverlayFile : HSOpts.VFSOverlayFiles) + AddString(VFSOverlayFile, Record); + + Stream.EmitRecord(HEADER_SEARCH_PATHS, Record); + // Write out the diagnostic/pragma mappings. WritePragmaDiagnosticMappings(Diags, /* isModule = */ WritingModule); @@ -1187,8 +1229,7 @@ ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP, /// Write the control block. void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, - StringRef isysroot, - const std::string &OutputFile) { + StringRef isysroot) { using namespace llvm; Stream.EnterSubblock(CONTROL_BLOCK_ID, 5); @@ -1283,7 +1324,12 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, if (auto *AdditionalModMaps = Map.getAdditionalModuleMapFiles(WritingModule)) { Record.push_back(AdditionalModMaps->size()); - for (const FileEntry *F : *AdditionalModMaps) + SmallVector<const FileEntry *, 1> ModMaps(AdditionalModMaps->begin(), + AdditionalModMaps->end()); + llvm::sort(ModMaps, [](const FileEntry *A, const FileEntry *B) { + return A->getName() < B->getName(); + }); + for (const FileEntry *F : ModMaps) AddPath(F->getName(), Record); } else { Record.push_back(0); @@ -1385,27 +1431,10 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, // Header search options. Record.clear(); - const HeaderSearchOptions &HSOpts - = PP.getHeaderSearchInfo().getHeaderSearchOpts(); - AddString(HSOpts.Sysroot, Record); - - // Include entries. - Record.push_back(HSOpts.UserEntries.size()); - for (unsigned I = 0, N = HSOpts.UserEntries.size(); I != N; ++I) { - const HeaderSearchOptions::Entry &Entry = HSOpts.UserEntries[I]; - AddString(Entry.Path, Record); - Record.push_back(static_cast<unsigned>(Entry.Group)); - Record.push_back(Entry.IsFramework); - Record.push_back(Entry.IgnoreSysRoot); - } - - // System header prefixes. - Record.push_back(HSOpts.SystemHeaderPrefixes.size()); - for (unsigned I = 0, N = HSOpts.SystemHeaderPrefixes.size(); I != N; ++I) { - AddString(HSOpts.SystemHeaderPrefixes[I].Prefix, Record); - Record.push_back(HSOpts.SystemHeaderPrefixes[I].IsSystemHeader); - } + const HeaderSearchOptions &HSOpts = + PP.getHeaderSearchInfo().getHeaderSearchOpts(); + AddString(HSOpts.Sysroot, Record); AddString(HSOpts.ResourceDir, Record); AddString(HSOpts.ModuleCachePath, Record); AddString(HSOpts.ModuleUserBuildPath, Record); @@ -1463,38 +1492,16 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Record.clear(); Record.push_back(ORIGINAL_FILE); - Record.push_back(SM.getMainFileID().getOpaqueValue()); + AddFileID(SM.getMainFileID(), Record); EmitRecordWithPath(FileAbbrevCode, Record, MainFile->getName()); } Record.clear(); - Record.push_back(SM.getMainFileID().getOpaqueValue()); + AddFileID(SM.getMainFileID(), Record); Stream.EmitRecord(ORIGINAL_FILE_ID, Record); - // Original PCH directory - if (!OutputFile.empty() && OutputFile != "-") { - auto Abbrev = std::make_shared<BitCodeAbbrev>(); - Abbrev->Add(BitCodeAbbrevOp(ORIGINAL_PCH_DIR)); - Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name - unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); - - SmallString<128> OutputPath(OutputFile); - PreparePathForOutput(OutputPath); - StringRef origDir = llvm::sys::path::parent_path(OutputPath); - - RecordData::value_type Record[] = {ORIGINAL_PCH_DIR}; - Stream.EmitRecordWithBlob(AbbrevCode, Record, origDir); - } - - std::set<const FileEntry *> AffectingModuleMaps; - if (WritingModule) { - AffectingModuleMaps = - GetAllModuleMaps(PP.getHeaderSearchInfo(), WritingModule); - } - WriteInputFiles(Context.SourceMgr, - PP.getHeaderSearchInfo().getHeaderSearchOpts(), - AffectingModuleMaps); + PP.getHeaderSearchInfo().getHeaderSearchOpts()); Stream.ExitBlock(); } @@ -1502,19 +1509,20 @@ namespace { /// An input file. struct InputFileEntry { - const FileEntry *File; + FileEntryRef File; bool IsSystemFile; bool IsTransient; bool BufferOverridden; bool IsTopLevelModuleMap; uint32_t ContentHash[2]; + + InputFileEntry(FileEntryRef File) : File(File) {} }; } // namespace -void ASTWriter::WriteInputFiles( - SourceManager &SourceMgr, HeaderSearchOptions &HSOpts, - std::set<const FileEntry *> &AffectingModuleMaps) { +void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, + HeaderSearchOptions &HSOpts) { using namespace llvm; Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4); @@ -1538,9 +1546,9 @@ void ASTWriter::WriteInputFiles( IFHAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); unsigned IFHAbbrevCode = Stream.EmitAbbrev(std::move(IFHAbbrev)); - // Get all ContentCache objects for files, sorted by whether the file is a - // system one or not. System files go at the back, users files at the front. - std::deque<InputFileEntry> SortedFiles; + // Get all ContentCache objects for files. + std::vector<InputFileEntry> UserFiles; + std::vector<InputFileEntry> SystemFiles; for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) { // Get this source location entry. const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I); @@ -1554,18 +1562,11 @@ void ASTWriter::WriteInputFiles( if (!Cache->OrigEntry) continue; - if (isModuleMap(File.getFileCharacteristic()) && - !isSystem(File.getFileCharacteristic()) && - !AffectingModuleMaps.empty() && - AffectingModuleMaps.find(Cache->OrigEntry) == - AffectingModuleMaps.end()) { - SkippedModuleMaps.insert(Cache->OrigEntry); - // Do not emit modulemaps that do not affect current module. + // Do not emit input files that do not affect current module. + if (!IsSLocAffecting[I]) continue; - } - InputFileEntry Entry; - Entry.File = Cache->OrigEntry; + InputFileEntry Entry(*Cache->OrigEntry); Entry.IsSystemFile = isSystem(File.getFileCharacteristic()); Entry.IsTransient = Cache->IsTransient; Entry.BufferOverridden = Cache->BufferOverridden; @@ -1580,9 +1581,8 @@ void ASTWriter::WriteInputFiles( if (MemBuff) ContentHash = hash_value(MemBuff->getBuffer()); else - // FIXME: The path should be taken from the FileEntryRef. PP->Diag(SourceLocation(), diag::err_module_unable_to_hash_content) - << Entry.File->getName(); + << Entry.File.getName(); } auto CH = llvm::APInt(64, ContentHash); Entry.ContentHash[0] = @@ -1591,11 +1591,15 @@ void ASTWriter::WriteInputFiles( static_cast<uint32_t>(CH.getHiBits(32).getZExtValue()); if (Entry.IsSystemFile) - SortedFiles.push_back(Entry); + SystemFiles.push_back(Entry); else - SortedFiles.push_front(Entry); + UserFiles.push_back(Entry); } + // User files go at the front, system files at the back. + auto SortedFiles = llvm::concat<InputFileEntry>(std::move(UserFiles), + std::move(SystemFiles)); + unsigned UserFilesNum = 0; // Write out all of the input files. std::vector<uint64_t> InputFileOffsets; @@ -1618,14 +1622,13 @@ void ASTWriter::WriteInputFiles( RecordData::value_type Record[] = { INPUT_FILE, InputFileOffsets.size(), - (uint64_t)Entry.File->getSize(), + (uint64_t)Entry.File.getSize(), (uint64_t)getTimestampForOutput(Entry.File), Entry.BufferOverridden, Entry.IsTransient, Entry.IsTopLevelModuleMap}; - // FIXME: The path should be taken from the FileEntryRef. - EmitRecordWithPath(IFAbbrevCode, Record, Entry.File->getName()); + EmitRecordWithPath(IFAbbrevCode, Record, Entry.File.getNameAsRequested()); } // Emit content hash for this file. @@ -1830,14 +1833,12 @@ namespace { auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { - uint32_t Value = (ModID << 2) | (unsigned)Role; - assert((Value >> 2) == ModID && "overflow in header module info"); + uint32_t Value = (ModID << 3) | (unsigned)Role; + assert((Value >> 3) == ModID && "overflow in header module info"); LE.write<uint32_t>(Value); } }; - // FIXME: If the header is excluded, we should write out some - // record of that fact. for (auto ModInfo : Data.KnownHeaders) EmitModule(ModInfo.getModule(), ModInfo.getRole()); if (Data.Unresolved.getPointer()) @@ -1879,7 +1880,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { // headers list when emitting resolved headers in the first loop below. // FIXME: It'd be preferable to avoid doing this if we were given // sufficient stat information in the module map. - HS.getModuleMap().resolveHeaderDirectives(M, /*File=*/llvm::None); + HS.getModuleMap().resolveHeaderDirectives(M, /*File=*/std::nullopt); // If the file didn't exist, we can still create a module if we were given // enough information in the module map. @@ -2001,6 +2002,14 @@ static void emitBlob(llvm::BitstreamWriter &Stream, StringRef Blob, // Compress the buffer if possible. We expect that almost all PCM // consumers will not want its contents. SmallVector<uint8_t, 0> CompressedBuffer; + if (llvm::compression::zstd::isAvailable()) { + llvm::compression::zstd::compress( + llvm::arrayRefFromStringRef(Blob.drop_back(1)), CompressedBuffer, 9); + RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED, Blob.size() - 1}; + Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record, + llvm::toStringRef(CompressedBuffer)); + return; + } if (llvm::compression::zlib::isAvailable()) { llvm::compression::zlib::compress( llvm::arrayRefFromStringRef(Blob.drop_back(1)), CompressedBuffer); @@ -2054,7 +2063,6 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // Record the offset of this source-location entry. uint64_t Offset = Stream.GetCurrentBitNo() - SLocEntryOffsetsBase; assert((Offset >> 32) == 0 && "SLocEntry offset too large"); - SLocEntryOffsets.push_back(Offset); // Figure out which record code to use. unsigned Code; @@ -2069,17 +2077,15 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, Record.clear(); Record.push_back(Code); - // Starting offset of this entry within this module, so skip the dummy. - Record.push_back(SLoc->getOffset() - 2); if (SLoc->isFile()) { const SrcMgr::FileInfo &File = SLoc->getFile(); const SrcMgr::ContentCache *Content = &File.getContentCache(); - if (Content->OrigEntry && !SkippedModuleMaps.empty() && - SkippedModuleMaps.find(Content->OrigEntry) != - SkippedModuleMaps.end()) { - // Do not emit files that were not listed as inputs. + // Do not emit files that were not listed as inputs. + if (!IsSLocAffecting[I]) continue; - } + SLocEntryOffsets.push_back(Offset); + // Starting offset of this entry within this module, so skip the dummy. + Record.push_back(getAdjustedOffset(SLoc->getOffset()) - 2); AddSourceLocation(File.getIncludeLoc(), Record); Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding Record.push_back(File.hasLineDirectives()); @@ -2093,7 +2099,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, assert(InputFileIDs[Content->OrigEntry] != 0 && "Missed file entry"); Record.push_back(InputFileIDs[Content->OrigEntry]); - Record.push_back(File.NumCreatedFIDs); + Record.push_back(getAdjustedNumCreatedFIDs(FID)); FileDeclIDsTy::iterator FDI = FileDeclIDs.find(FID); if (FDI != FileDeclIDs.end()) { @@ -2115,7 +2121,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, // We add one to the size so that we capture the trailing NULL // that is required by llvm::MemoryBuffer::getMemBuffer (on // the reader side). - llvm::Optional<llvm::MemoryBufferRef> Buffer = + std::optional<llvm::MemoryBufferRef> Buffer = Content->getBufferOrNone(PP.getDiagnostics(), PP.getFileManager()); StringRef Name = Buffer ? Buffer->getBufferIdentifier() : ""; Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record, @@ -2129,7 +2135,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, if (EmitBlob) { // Include the implicit terminating null character in the on-disk buffer // if we're writing it uncompressed. - llvm::Optional<llvm::MemoryBufferRef> Buffer = + std::optional<llvm::MemoryBufferRef> Buffer = Content->getBufferOrNone(PP.getDiagnostics(), PP.getFileManager()); if (!Buffer) Buffer = llvm::MemoryBufferRef("<<<INVALID BUFFER>>>", ""); @@ -2140,6 +2146,9 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, } else { // The source location entry is a macro expansion. const SrcMgr::ExpansionInfo &Expansion = SLoc->getExpansion(); + SLocEntryOffsets.push_back(Offset); + // Starting offset of this entry within this module, so skip the dummy. + Record.push_back(getAdjustedOffset(SLoc->getOffset()) - 2); LocSeq::State Seq; AddSourceLocation(Expansion.getSpellingLoc(), Record, Seq); AddSourceLocation(Expansion.getExpansionLocStart(), Record, Seq); @@ -2153,7 +2162,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, SourceLocation::UIntTy NextOffset = SourceMgr.getNextLocalOffset(); if (I + 1 != N) NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset(); - Record.push_back(NextOffset - SLoc->getOffset() - 1); + Record.push_back(getAdjustedOffset(NextOffset - SLoc->getOffset()) - 1); Stream.EmitRecordWithAbbrev(SLocExpansionAbbrv, Record); } } @@ -2177,7 +2186,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, { RecordData::value_type Record[] = { SOURCE_LOCATION_OFFSETS, SLocEntryOffsets.size(), - SourceMgr.getNextLocalOffset() - 1 /* skip dummy */, + getAdjustedOffset(SourceMgr.getNextLocalOffset()) - 1 /* skip dummy */, SLocEntryOffsetsBase - SourceManagerBlockOffset}; Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, bytes(SLocEntryOffsets)); @@ -2213,8 +2222,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, if (L.first.ID < 0) continue; - // Emit the file ID - Record.push_back(L.first.ID); + AddFileID(L.first, Record); // Emit the line entries Record.push_back(L.second.size()); @@ -2341,11 +2349,14 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { // Construct the list of identifiers with macro directives that need to be // serialized. SmallVector<const IdentifierInfo *, 128> MacroIdentifiers; - for (auto &Id : PP.getIdentifierTable()) - if (Id.second->hadMacroDefinition() && - (!Id.second->isFromAST() || - Id.second->hasChangedSinceDeserialization())) - MacroIdentifiers.push_back(Id.second); + // It is meaningless to emit macros for named modules. It only wastes times + // and spaces. + if (!isWritingStdCXXNamedModules()) + for (auto &Id : PP.getIdentifierTable()) + if (Id.second->hadMacroDefinition() && + (!Id.second->isFromAST() || + Id.second->hasChangedSinceDeserialization())) + MacroIdentifiers.push_back(Id.second); // Sort the set of macro definitions that need to be serialized by the // name of the macro, to provide a stable ordering. llvm::sort(MacroIdentifiers, llvm::deref<std::less<>>()); @@ -2577,7 +2588,7 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec, uint64_t Offset = Stream.GetCurrentBitNo() - MacroOffsetsBase; assert((Offset >> 32) == 0 && "Preprocessed entity offset too large"); PreprocessedEntityOffsets.push_back( - PPEntityOffset((*E)->getSourceRange(), Offset)); + PPEntityOffset(getAdjustedRange((*E)->getSourceRange()), Offset)); if (auto *MD = dyn_cast<MacroDefinitionRecord>(*E)) { // Record this macro definition's ID. @@ -2677,12 +2688,12 @@ unsigned ASTWriter::getLocalOrImportedSubmoduleID(const Module *Mod) { } unsigned ASTWriter::getSubmoduleID(Module *Mod) { + unsigned ID = getLocalOrImportedSubmoduleID(Mod); // FIXME: This can easily happen, if we have a reference to a submodule that // did not result in us loading a module file for that submodule. For // instance, a cross-top-level-module 'conflict' declaration will hit this. - unsigned ID = getLocalOrImportedSubmoduleID(Mod); - assert((ID || !Mod) && - "asked for module ID for non-local, non-imported module"); + // assert((ID || !Mod) && + // "asked for module ID for non-local, non-imported module"); return ID; } @@ -2882,6 +2893,14 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) { Stream.EmitRecord(SUBMODULE_IMPORTS, Record); } + // Emit the modules affecting compilation that were not imported. + if (!Mod->AffectingClangModules.empty()) { + RecordData Record; + for (auto *I : Mod->AffectingClangModules) + Record.push_back(getSubmoduleID(I)); + Stream.EmitRecord(SUBMODULE_AFFECTING_MODULES, Record); + } + // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; @@ -3016,7 +3035,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, Record.push_back(FileIDAndFile.second.StateTransitions.size()); for (auto &StatePoint : FileIDAndFile.second.StateTransitions) { - Record.push_back(StatePoint.Offset); + Record.push_back(getAdjustedOffset(StatePoint.Offset)); AddDiagState(StatePoint.State, false); } } @@ -4350,7 +4369,8 @@ void ASTRecordWriter::AddAttr(const Attr *A) { // FIXME: Clang can't handle the serialization/deserialization of // preferred_name properly now. See // https://github.com/llvm/llvm-project/issues/56490 for example. - if (!A || (isa<PreferredNameAttr>(A) && Writer->isWritingNamedModules())) + if (!A || (isa<PreferredNameAttr>(A) && + Writer->isWritingStdCXXNamedModules())) return Record.push_back(0); Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs @@ -4375,15 +4395,37 @@ void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) { void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) { AddSourceLocation(Tok.getLocation(), Record); - 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()); + + if (Tok.isAnnotation()) { + AddSourceLocation(Tok.getAnnotationEndLoc(), Record); + switch (Tok.getKind()) { + case tok::annot_pragma_loop_hint: { + auto *Info = static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue()); + AddToken(Info->PragmaName, Record); + AddToken(Info->Option, Record); + Record.push_back(Info->Toks.size()); + for (const auto &T : Info->Toks) + AddToken(T, Record); + break; + } + // Some annotation tokens do not use the PtrData field. + case tok::annot_pragma_openmp: + case tok::annot_pragma_openmp_end: + case tok::annot_pragma_unused: + break; + default: + llvm_unreachable("missing serialization code for annotation token"); + } + } else { + Record.push_back(Tok.getLength()); + // FIXME: When reading literal tokens, reconstruct the literal pointer if it + // is needed. + AddIdentifierRef(Tok.getIdentifierInfo(), Record); + } } void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) { @@ -4425,11 +4467,11 @@ void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record, void ASTWriter::AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record) { Record.push_back(Version.getMajor()); - if (Optional<unsigned> Minor = Version.getMinor()) + if (std::optional<unsigned> Minor = Version.getMinor()) Record.push_back(*Minor + 1); else Record.push_back(0); - if (Optional<unsigned> Subminor = Version.getSubminor()) + if (std::optional<unsigned> Subminor = Version.getSubminor()) Record.push_back(*Subminor + 1); else Record.push_back(0); @@ -4481,11 +4523,11 @@ time_t ASTWriter::getTimestampForOutput(const FileEntry *E) const { return IncludeTimestamps ? E->getModificationTime() : 0; } -ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, - const std::string &OutputFile, +ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, StringRef OutputFile, Module *WritingModule, StringRef isysroot, bool hasErrors, bool ShouldCacheASTInMemory) { + llvm::TimeTraceScope scope("WriteAST", OutputFile); WritingAST = true; ASTHasCompilerErrors = hasErrors; @@ -4501,8 +4543,7 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, Context = &SemaRef.Context; PP = &SemaRef.PP; this->WritingModule = WritingModule; - ASTFileSignature Signature = - WriteASTCore(SemaRef, isysroot, OutputFile, WritingModule); + ASTFileSignature Signature = WriteASTCore(SemaRef, isysroot, WritingModule); Context = nullptr; PP = nullptr; this->WritingModule = nullptr; @@ -4527,8 +4568,69 @@ static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, } } +void ASTWriter::collectNonAffectingInputFiles() { + SourceManager &SrcMgr = PP->getSourceManager(); + unsigned N = SrcMgr.local_sloc_entry_size(); + + IsSLocAffecting.resize(N, true); + + if (!WritingModule) + return; + + auto AffectingModuleMaps = GetAffectingModuleMaps(*PP, WritingModule); + + unsigned FileIDAdjustment = 0; + unsigned OffsetAdjustment = 0; + + NonAffectingFileIDAdjustments.reserve(N); + NonAffectingOffsetAdjustments.reserve(N); + + NonAffectingFileIDAdjustments.push_back(FileIDAdjustment); + NonAffectingOffsetAdjustments.push_back(OffsetAdjustment); + + for (unsigned I = 1; I != N; ++I) { + const SrcMgr::SLocEntry *SLoc = &SrcMgr.getLocalSLocEntry(I); + FileID FID = FileID::get(I); + assert(&SrcMgr.getSLocEntry(FID) == SLoc); + + if (!SLoc->isFile()) + continue; + const SrcMgr::FileInfo &File = SLoc->getFile(); + const SrcMgr::ContentCache *Cache = &File.getContentCache(); + if (!Cache->OrigEntry) + continue; + + if (!isModuleMap(File.getFileCharacteristic()) || + AffectingModuleMaps.empty() || + AffectingModuleMaps.find(Cache->OrigEntry) != AffectingModuleMaps.end()) + continue; + + IsSLocAffecting[I] = false; + + FileIDAdjustment += 1; + // Even empty files take up one element in the offset table. + OffsetAdjustment += SrcMgr.getFileIDSize(FID) + 1; + + // If the previous file was non-affecting as well, just extend its entry + // with our information. + if (!NonAffectingFileIDs.empty() && + NonAffectingFileIDs.back().ID == FID.ID - 1) { + NonAffectingFileIDs.back() = FID; + NonAffectingRanges.back().setEnd(SrcMgr.getLocForEndOfFile(FID)); + NonAffectingFileIDAdjustments.back() = FileIDAdjustment; + NonAffectingOffsetAdjustments.back() = OffsetAdjustment; + continue; + } + + NonAffectingFileIDs.push_back(FID); + NonAffectingRanges.emplace_back(SrcMgr.getLocForStartOfFile(FID), + SrcMgr.getLocForEndOfFile(FID)); + NonAffectingFileIDAdjustments.push_back(FileIDAdjustment); + NonAffectingOffsetAdjustments.push_back(OffsetAdjustment); + } +} + ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, - const std::string &OutputFile, Module *WritingModule) { using namespace llvm; @@ -4541,6 +4643,8 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, ASTContext &Context = SemaRef.Context; Preprocessor &PP = SemaRef.PP; + collectNonAffectingInputFiles(); + // Set up predefined declaration IDs. auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) { if (D) { @@ -4682,7 +4786,7 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, } // Write the control block - WriteControlBlock(PP, Context, isysroot, OutputFile); + WriteControlBlock(PP, Context, isysroot); // Write the remaining AST contents. Stream.FlushToWord(); @@ -5205,7 +5309,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) { break; case UPD_ADDED_ATTR_TO_RECORD: - Record.AddAttributes(llvm::makeArrayRef(Update.getAttr())); + Record.AddAttributes(llvm::ArrayRef(Update.getAttr())); break; } } @@ -5229,8 +5333,75 @@ void ASTWriter::AddAlignPackInfo(const Sema::AlignPackInfo &Info, Record.push_back(Raw); } +FileID ASTWriter::getAdjustedFileID(FileID FID) const { + if (FID.isInvalid() || PP->getSourceManager().isLoadedFileID(FID) || + NonAffectingFileIDs.empty()) + return FID; + auto It = llvm::lower_bound(NonAffectingFileIDs, FID); + unsigned Idx = std::distance(NonAffectingFileIDs.begin(), It); + unsigned Offset = NonAffectingFileIDAdjustments[Idx]; + return FileID::get(FID.getOpaqueValue() - Offset); +} + +unsigned ASTWriter::getAdjustedNumCreatedFIDs(FileID FID) const { + unsigned NumCreatedFIDs = PP->getSourceManager() + .getLocalSLocEntry(FID.ID) + .getFile() + .NumCreatedFIDs; + + unsigned AdjustedNumCreatedFIDs = 0; + for (unsigned I = FID.ID, N = I + NumCreatedFIDs; I != N; ++I) + if (IsSLocAffecting[I]) + ++AdjustedNumCreatedFIDs; + return AdjustedNumCreatedFIDs; +} + +SourceLocation ASTWriter::getAdjustedLocation(SourceLocation Loc) const { + if (Loc.isInvalid()) + return Loc; + return Loc.getLocWithOffset(-getAdjustment(Loc.getOffset())); +} + +SourceRange ASTWriter::getAdjustedRange(SourceRange Range) const { + return SourceRange(getAdjustedLocation(Range.getBegin()), + getAdjustedLocation(Range.getEnd())); +} + +SourceLocation::UIntTy +ASTWriter::getAdjustedOffset(SourceLocation::UIntTy Offset) const { + return Offset - getAdjustment(Offset); +} + +SourceLocation::UIntTy +ASTWriter::getAdjustment(SourceLocation::UIntTy Offset) const { + if (NonAffectingRanges.empty()) + return 0; + + if (PP->getSourceManager().isLoadedOffset(Offset)) + return 0; + + if (Offset > NonAffectingRanges.back().getEnd().getOffset()) + return NonAffectingOffsetAdjustments.back(); + + if (Offset < NonAffectingRanges.front().getBegin().getOffset()) + return 0; + + auto Contains = [](const SourceRange &Range, SourceLocation::UIntTy Offset) { + return Range.getEnd().getOffset() < Offset; + }; + + auto It = llvm::lower_bound(NonAffectingRanges, Offset, Contains); + unsigned Idx = std::distance(NonAffectingRanges.begin(), It); + return NonAffectingOffsetAdjustments[Idx]; +} + +void ASTWriter::AddFileID(FileID FID, RecordDataImpl &Record) { + Record.push_back(getAdjustedFileID(FID).getOpaqueValue()); +} + void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record, SourceLocationSequence *Seq) { + Loc = getAdjustedLocation(Loc); Record.push_back(SourceLocationEncoding::encode(Loc, Seq)); } @@ -5472,7 +5643,7 @@ void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { // a function/objc method, should not have TU as lexical context. // TemplateTemplateParmDecls that are part of an alias template, should not // have TU as lexical context. - if (isa<ParmVarDecl>(D) || isa<TemplateTemplateParmDecl>(D)) + if (isa<ParmVarDecl, TemplateTemplateParmDecl>(D)) return; SourceManager &SM = Context->getSourceManager(); @@ -5484,6 +5655,7 @@ void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) { if (FID.isInvalid()) return; assert(SM.getSLocEntry(FID).isFile()); + assert(IsSLocAffecting[FID.ID]); std::unique_ptr<DeclIDInFileInfo> &Info = FileDeclIDs[FID]; if (!Info) @@ -5775,7 +5947,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { AddDeclRef(D->getLambdaContextDecl()); AddTypeSourceInfo(Lambda.MethodTyInfo); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { - const LambdaCapture &Capture = Lambda.Captures[I]; + const LambdaCapture &Capture = Lambda.Captures.front()[I]; AddSourceLocation(Capture.getLocation()); Record->push_back(Capture.isImplicit()); Record->push_back(Capture.getCaptureKind()); @@ -5786,7 +5958,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { break; case LCK_ByCopy: case LCK_ByRef: - VarDecl *Var = + ValueDecl *Var = Capture.capturesVariable() ? Capture.getCapturedVar() : nullptr; AddDeclRef(Var); AddSourceLocation(Capture.isPackExpansion() ? Capture.getEllipsisLoc() @@ -6618,9 +6790,12 @@ void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) { Record.push_back(C->getTotalComponentListNum()); Record.push_back(C->getTotalComponentsNum()); Record.AddSourceLocation(C->getLParenLoc()); + bool HasIteratorModifier = false; for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) { Record.push_back(C->getMapTypeModifier(I)); Record.AddSourceLocation(C->getMapTypeModifierLoc(I)); + if (C->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_iterator) + HasIteratorModifier = true; } Record.AddNestedNameSpecifierLoc(C->getMapperQualifierLoc()); Record.AddDeclarationNameInfo(C->getMapperIdInfo()); @@ -6631,6 +6806,8 @@ void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) { Record.AddStmt(E); for (auto *E : C->mapperlists()) Record.AddStmt(E); + if (HasIteratorModifier) + Record.AddStmt(C->getIteratorModifier()); for (auto *D : C->all_decls()) Record.AddDeclRef(D); for (auto N : C->all_num_lists()) @@ -6672,13 +6849,17 @@ void OMPClauseWriter::VisitOMPPriorityClause(OMPPriorityClause *C) { void OMPClauseWriter::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) { VisitOMPClauseWithPreInit(C); + Record.writeEnum(C->getModifier()); Record.AddStmt(C->getGrainsize()); + Record.AddSourceLocation(C->getModifierLoc()); Record.AddSourceLocation(C->getLParenLoc()); } void OMPClauseWriter::VisitOMPNumTasksClause(OMPNumTasksClause *C) { VisitOMPClauseWithPreInit(C); + Record.writeEnum(C->getModifier()); Record.AddStmt(C->getNumTasks()); + Record.AddSourceLocation(C->getModifierLoc()); Record.AddSourceLocation(C->getLParenLoc()); } @@ -6866,6 +7047,23 @@ void OMPClauseWriter::VisitOMPAtomicDefaultMemOrderClause( Record.AddSourceLocation(C->getAtomicDefaultMemOrderKindKwLoc()); } +void OMPClauseWriter::VisitOMPAtClause(OMPAtClause *C) { + Record.push_back(C->getAtKind()); + Record.AddSourceLocation(C->getLParenLoc()); + Record.AddSourceLocation(C->getAtKindKwLoc()); +} + +void OMPClauseWriter::VisitOMPSeverityClause(OMPSeverityClause *C) { + Record.push_back(C->getSeverityKind()); + Record.AddSourceLocation(C->getLParenLoc()); + Record.AddSourceLocation(C->getSeverityKindKwLoc()); +} + +void OMPClauseWriter::VisitOMPMessageClause(OMPMessageClause *C) { + Record.AddStmt(C->getMessageString()); + Record.AddSourceLocation(C->getLParenLoc()); +} + void OMPClauseWriter::VisitOMPNontemporalClause(OMPNontemporalClause *C) { Record.push_back(C->varlist_size()); Record.AddSourceLocation(C->getLParenLoc()); @@ -6891,8 +7089,10 @@ void OMPClauseWriter::VisitOMPExclusiveClause(OMPExclusiveClause *C) { void OMPClauseWriter::VisitOMPOrderClause(OMPOrderClause *C) { Record.writeEnum(C->getKind()); + Record.writeEnum(C->getModifier()); Record.AddSourceLocation(C->getLParenLoc()); Record.AddSourceLocation(C->getKindKwLoc()); + Record.AddSourceLocation(C->getModifierKwLoc()); } void OMPClauseWriter::VisitOMPUsesAllocatorsClause(OMPUsesAllocatorsClause *C) { @@ -6922,6 +7122,12 @@ void OMPClauseWriter::VisitOMPBindClause(OMPBindClause *C) { Record.AddSourceLocation(C->getBindKindLoc()); } +void OMPClauseWriter::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) { + VisitOMPClauseWithPreInit(C); + Record.AddStmt(C->getSize()); + Record.AddSourceLocation(C->getLParenLoc()); +} + void ASTRecordWriter::writeOMPTraitInfo(const OMPTraitInfo *TI) { writeUInt32(TI->Sets.size()); for (const auto &Set : TI->Sets) { |