9070 lines · cpp
1//===- ASTWriter.cpp - AST File Writer ------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines the ASTWriter class, which writes AST files.10//11//===----------------------------------------------------------------------===//12 13#include "ASTCommon.h"14#include "ASTReaderInternals.h"15#include "MultiOnDiskHashTable.h"16#include "TemplateArgumentHasher.h"17#include "clang/AST/ASTContext.h"18#include "clang/AST/ASTUnresolvedSet.h"19#include "clang/AST/AbstractTypeWriter.h"20#include "clang/AST/Attr.h"21#include "clang/AST/Decl.h"22#include "clang/AST/DeclBase.h"23#include "clang/AST/DeclCXX.h"24#include "clang/AST/DeclContextInternals.h"25#include "clang/AST/DeclFriend.h"26#include "clang/AST/DeclObjC.h"27#include "clang/AST/DeclTemplate.h"28#include "clang/AST/DeclarationName.h"29#include "clang/AST/Expr.h"30#include "clang/AST/ExprCXX.h"31#include "clang/AST/LambdaCapture.h"32#include "clang/AST/NestedNameSpecifier.h"33#include "clang/AST/OpenACCClause.h"34#include "clang/AST/OpenMPClause.h"35#include "clang/AST/RawCommentList.h"36#include "clang/AST/TemplateName.h"37#include "clang/AST/Type.h"38#include "clang/AST/TypeLoc.h"39#include "clang/AST/TypeLocVisitor.h"40#include "clang/Basic/Diagnostic.h"41#include "clang/Basic/DiagnosticOptions.h"42#include "clang/Basic/FileEntry.h"43#include "clang/Basic/FileManager.h"44#include "clang/Basic/FileSystemOptions.h"45#include "clang/Basic/IdentifierTable.h"46#include "clang/Basic/LLVM.h"47#include "clang/Basic/Lambda.h"48#include "clang/Basic/LangOptions.h"49#include "clang/Basic/Module.h"50#include "clang/Basic/ObjCRuntime.h"51#include "clang/Basic/OpenACCKinds.h"52#include "clang/Basic/OpenCLOptions.h"53#include "clang/Basic/SourceLocation.h"54#include "clang/Basic/SourceManager.h"55#include "clang/Basic/SourceManagerInternals.h"56#include "clang/Basic/Specifiers.h"57#include "clang/Basic/TargetInfo.h"58#include "clang/Basic/TargetOptions.h"59#include "clang/Basic/Version.h"60#include "clang/Lex/HeaderSearch.h"61#include "clang/Lex/HeaderSearchOptions.h"62#include "clang/Lex/MacroInfo.h"63#include "clang/Lex/ModuleMap.h"64#include "clang/Lex/PreprocessingRecord.h"65#include "clang/Lex/Preprocessor.h"66#include "clang/Lex/PreprocessorOptions.h"67#include "clang/Lex/Token.h"68#include "clang/Sema/IdentifierResolver.h"69#include "clang/Sema/ObjCMethodList.h"70#include "clang/Sema/Sema.h"71#include "clang/Sema/SemaCUDA.h"72#include "clang/Sema/SemaObjC.h"73#include "clang/Sema/Weak.h"74#include "clang/Serialization/ASTBitCodes.h"75#include "clang/Serialization/ASTReader.h"76#include "clang/Serialization/ASTRecordWriter.h"77#include "clang/Serialization/InMemoryModuleCache.h"78#include "clang/Serialization/ModuleCache.h"79#include "clang/Serialization/ModuleFile.h"80#include "clang/Serialization/ModuleFileExtension.h"81#include "clang/Serialization/SerializationDiagnostic.h"82#include "llvm/ADT/APFloat.h"83#include "llvm/ADT/APInt.h"84#include "llvm/ADT/ArrayRef.h"85#include "llvm/ADT/DenseMap.h"86#include "llvm/ADT/DenseSet.h"87#include "llvm/ADT/PointerIntPair.h"88#include "llvm/ADT/STLExtras.h"89#include "llvm/ADT/ScopeExit.h"90#include "llvm/ADT/SmallPtrSet.h"91#include "llvm/ADT/SmallString.h"92#include "llvm/ADT/SmallVector.h"93#include "llvm/ADT/StringRef.h"94#include "llvm/Bitstream/BitCodes.h"95#include "llvm/Bitstream/BitstreamWriter.h"96#include "llvm/Support/Compression.h"97#include "llvm/Support/DJB.h"98#include "llvm/Support/EndianStream.h"99#include "llvm/Support/ErrorHandling.h"100#include "llvm/Support/LEB128.h"101#include "llvm/Support/MemoryBuffer.h"102#include "llvm/Support/OnDiskHashTable.h"103#include "llvm/Support/Path.h"104#include "llvm/Support/SHA1.h"105#include "llvm/Support/TimeProfiler.h"106#include "llvm/Support/VersionTuple.h"107#include "llvm/Support/raw_ostream.h"108#include <algorithm>109#include <cassert>110#include <cstdint>111#include <cstdlib>112#include <cstring>113#include <ctime>114#include <limits>115#include <memory>116#include <optional>117#include <queue>118#include <tuple>119#include <utility>120#include <vector>121 122using namespace clang;123using namespace clang::serialization;124 125template <typename T, typename Allocator>126static StringRef bytes(const std::vector<T, Allocator> &v) {127 if (v.empty()) return StringRef();128 return StringRef(reinterpret_cast<const char*>(&v[0]),129 sizeof(T) * v.size());130}131 132template <typename T>133static StringRef bytes(const SmallVectorImpl<T> &v) {134 return StringRef(reinterpret_cast<const char*>(v.data()),135 sizeof(T) * v.size());136}137 138static std::string bytes(const std::vector<bool> &V) {139 std::string Str;140 Str.reserve(V.size() / 8);141 for (unsigned I = 0, E = V.size(); I < E;) {142 char Byte = 0;143 for (unsigned Bit = 0; Bit < 8 && I < E; ++Bit, ++I)144 Byte |= V[I] << Bit;145 Str += Byte;146 }147 return Str;148}149 150//===----------------------------------------------------------------------===//151// Type serialization152//===----------------------------------------------------------------------===//153 154static TypeCode getTypeCodeForTypeClass(Type::TypeClass id) {155 switch (id) {156#define TYPE_BIT_CODE(CLASS_ID, CODE_ID, CODE_VALUE) \157 case Type::CLASS_ID: return TYPE_##CODE_ID;158#include "clang/Serialization/TypeBitCodes.def"159 case Type::Builtin:160 llvm_unreachable("shouldn't be serializing a builtin type this way");161 }162 llvm_unreachable("bad type kind");163}164 165namespace {166 167struct AffectingModuleMaps {168 llvm::DenseSet<FileID> DefinitionFileIDs;169 llvm::DenseSet<const FileEntry *> DefinitionFiles;170};171 172std::optional<AffectingModuleMaps>173GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) {174 if (!PP.getHeaderSearchInfo()175 .getHeaderSearchOpts()176 .ModulesPruneNonAffectingModuleMaps)177 return std::nullopt;178 179 const HeaderSearch &HS = PP.getHeaderSearchInfo();180 const SourceManager &SM = PP.getSourceManager();181 const ModuleMap &MM = HS.getModuleMap();182 183 // Module maps used only by textual headers are special. Their FileID is184 // non-affecting, but their FileEntry is (i.e. must be written as InputFile).185 enum AffectedReason : bool {186 AR_TextualHeader = 0,187 AR_ImportOrTextualHeader = 1,188 };189 auto AssignMostImportant = [](AffectedReason &LHS, AffectedReason RHS) {190 LHS = std::max(LHS, RHS);191 };192 llvm::DenseMap<FileID, AffectedReason> ModuleMaps;193 llvm::DenseMap<const Module *, AffectedReason> ProcessedModules;194 auto CollectModuleMapsForHierarchy = [&](const Module *M,195 AffectedReason Reason) {196 M = M->getTopLevelModule();197 198 // We need to process the header either when it was not present or when we199 // previously flagged module map as textual headers and now we found a200 // proper import.201 if (auto [It, Inserted] = ProcessedModules.insert({M, Reason});202 !Inserted && Reason <= It->second) {203 return;204 } else {205 It->second = Reason;206 }207 208 std::queue<const Module *> Q;209 Q.push(M);210 while (!Q.empty()) {211 const Module *Mod = Q.front();212 Q.pop();213 214 // The containing module map is affecting, because it's being pointed215 // into by Module::DefinitionLoc.216 if (auto F = MM.getContainingModuleMapFileID(Mod); F.isValid())217 AssignMostImportant(ModuleMaps[F], Reason);218 // For inferred modules, the module map that allowed inferring is not219 // related to the virtual containing module map file. It did affect the220 // compilation, though.221 if (auto UniqF = MM.getModuleMapFileIDForUniquing(Mod); UniqF.isValid())222 AssignMostImportant(ModuleMaps[UniqF], Reason);223 224 for (auto *SubM : Mod->submodules())225 Q.push(SubM);226 }227 };228 229 // Handle all the affecting modules referenced from the root module.230 231 CollectModuleMapsForHierarchy(RootModule, AR_ImportOrTextualHeader);232 233 std::queue<const Module *> Q;234 Q.push(RootModule);235 while (!Q.empty()) {236 const Module *CurrentModule = Q.front();237 Q.pop();238 239 for (const Module *ImportedModule : CurrentModule->Imports)240 CollectModuleMapsForHierarchy(ImportedModule, AR_ImportOrTextualHeader);241 for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses)242 CollectModuleMapsForHierarchy(UndeclaredModule, AR_ImportOrTextualHeader);243 244 for (auto *M : CurrentModule->submodules())245 Q.push(M);246 }247 248 // Handle textually-included headers that belong to other modules.249 250 SmallVector<OptionalFileEntryRef, 16> FilesByUID;251 HS.getFileMgr().GetUniqueIDMapping(FilesByUID);252 253 if (FilesByUID.size() > HS.header_file_size())254 FilesByUID.resize(HS.header_file_size());255 256 for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) {257 OptionalFileEntryRef File = FilesByUID[UID];258 if (!File)259 continue;260 261 const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File);262 if (!HFI)263 continue; // We have no information on this being a header file.264 if (!HFI->isCompilingModuleHeader && HFI->isModuleHeader)265 continue; // Modular header, handled in the above module-based loop.266 if (!HFI->isCompilingModuleHeader && !HFI->IsLocallyIncluded)267 continue; // Non-modular header not included locally is not affecting.268 269 for (const auto &KH : HS.findResolvedModulesForHeader(*File))270 if (const Module *M = KH.getModule())271 CollectModuleMapsForHierarchy(M, AR_TextualHeader);272 }273 274 // FIXME: This algorithm is not correct for module map hierarchies where275 // module map file defining a (sub)module of a top-level module X includes276 // a module map file that defines a (sub)module of another top-level module Y.277 // Whenever X is affecting and Y is not, "replaying" this PCM file will fail278 // when parsing module map files for X due to not knowing about the `extern`279 // module map for Y.280 //281 // We don't have a good way to fix it here. We could mark all children of282 // affecting module map files as being affecting as well, but that's283 // expensive. SourceManager does not model the edge from parent to child284 // SLocEntries, so instead, we would need to iterate over leaf module map285 // files, walk up their include hierarchy and check whether we arrive at an286 // affecting module map.287 //288 // Instead of complicating and slowing down this function, we should probably289 // just ban module map hierarchies where module map defining a (sub)module X290 // includes a module map defining a module that's not a submodule of X.291 292 llvm::DenseSet<const FileEntry *> ModuleFileEntries;293 llvm::DenseSet<FileID> ModuleFileIDs;294 for (auto [FID, Reason] : ModuleMaps) {295 if (Reason == AR_ImportOrTextualHeader)296 ModuleFileIDs.insert(FID);297 if (auto *FE = SM.getFileEntryForID(FID))298 ModuleFileEntries.insert(FE);299 }300 301 AffectingModuleMaps R;302 R.DefinitionFileIDs = std::move(ModuleFileIDs);303 R.DefinitionFiles = std::move(ModuleFileEntries);304 return std::move(R);305}306 307class ASTTypeWriter {308 ASTWriter &Writer;309 ASTWriter::RecordData Record;310 ASTRecordWriter BasicWriter;311 312public:313 ASTTypeWriter(ASTContext &Context, ASTWriter &Writer)314 : Writer(Writer), BasicWriter(Context, Writer, Record) {}315 316 uint64_t write(QualType T) {317 if (T.hasLocalNonFastQualifiers()) {318 Qualifiers Qs = T.getLocalQualifiers();319 BasicWriter.writeQualType(T.getLocalUnqualifiedType());320 BasicWriter.writeQualifiers(Qs);321 return BasicWriter.Emit(TYPE_EXT_QUAL, Writer.getTypeExtQualAbbrev());322 }323 324 const Type *typePtr = T.getTypePtr();325 serialization::AbstractTypeWriter<ASTRecordWriter> atw(BasicWriter);326 atw.write(typePtr);327 return BasicWriter.Emit(getTypeCodeForTypeClass(typePtr->getTypeClass()),328 /*abbrev*/ 0);329 }330};331 332class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {333 ASTRecordWriter &Record;334 335 void addSourceLocation(SourceLocation Loc) { Record.AddSourceLocation(Loc); }336 void addSourceRange(SourceRange Range) { Record.AddSourceRange(Range); }337 338public:339 TypeLocWriter(ASTRecordWriter &Record) : Record(Record) {}340 341#define ABSTRACT_TYPELOC(CLASS, PARENT)342#define TYPELOC(CLASS, PARENT) \343 void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);344#include "clang/AST/TypeLocNodes.def"345 346 void VisitArrayTypeLoc(ArrayTypeLoc TyLoc);347 void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc);348 void VisitTagTypeLoc(TagTypeLoc TL);349};350 351} // namespace352 353void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {354 // nothing to do355}356 357void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {358 addSourceLocation(TL.getBuiltinLoc());359 if (TL.needsExtraLocalData()) {360 Record.push_back(TL.getWrittenTypeSpec());361 Record.push_back(static_cast<uint64_t>(TL.getWrittenSignSpec()));362 Record.push_back(static_cast<uint64_t>(TL.getWrittenWidthSpec()));363 Record.push_back(TL.hasModeAttr());364 }365}366 367void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {368 addSourceLocation(TL.getNameLoc());369}370 371void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {372 addSourceLocation(TL.getStarLoc());373}374 375void TypeLocWriter::VisitDecayedTypeLoc(DecayedTypeLoc TL) {376 // nothing to do377}378 379void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {380 // nothing to do381}382 383void TypeLocWriter::VisitArrayParameterTypeLoc(ArrayParameterTypeLoc TL) {384 // nothing to do385}386 387void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {388 addSourceLocation(TL.getCaretLoc());389}390 391void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {392 addSourceLocation(TL.getAmpLoc());393}394 395void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {396 addSourceLocation(TL.getAmpAmpLoc());397}398 399void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {400 addSourceLocation(TL.getStarLoc());401 Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());402}403 404void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {405 addSourceLocation(TL.getLBracketLoc());406 addSourceLocation(TL.getRBracketLoc());407 Record.push_back(TL.getSizeExpr() ? 1 : 0);408 if (TL.getSizeExpr())409 Record.AddStmt(TL.getSizeExpr());410}411 412void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {413 VisitArrayTypeLoc(TL);414}415 416void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {417 VisitArrayTypeLoc(TL);418}419 420void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {421 VisitArrayTypeLoc(TL);422}423 424void TypeLocWriter::VisitDependentSizedArrayTypeLoc(425 DependentSizedArrayTypeLoc TL) {426 VisitArrayTypeLoc(TL);427}428 429void TypeLocWriter::VisitDependentAddressSpaceTypeLoc(430 DependentAddressSpaceTypeLoc TL) {431 addSourceLocation(TL.getAttrNameLoc());432 SourceRange range = TL.getAttrOperandParensRange();433 addSourceLocation(range.getBegin());434 addSourceLocation(range.getEnd());435 Record.AddStmt(TL.getAttrExprOperand());436}437 438void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(439 DependentSizedExtVectorTypeLoc TL) {440 addSourceLocation(TL.getNameLoc());441}442 443void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {444 addSourceLocation(TL.getNameLoc());445}446 447void TypeLocWriter::VisitDependentVectorTypeLoc(448 DependentVectorTypeLoc TL) {449 addSourceLocation(TL.getNameLoc());450}451 452void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {453 addSourceLocation(TL.getNameLoc());454}455 456void TypeLocWriter::VisitConstantMatrixTypeLoc(ConstantMatrixTypeLoc TL) {457 addSourceLocation(TL.getAttrNameLoc());458 SourceRange range = TL.getAttrOperandParensRange();459 addSourceLocation(range.getBegin());460 addSourceLocation(range.getEnd());461 Record.AddStmt(TL.getAttrRowOperand());462 Record.AddStmt(TL.getAttrColumnOperand());463}464 465void TypeLocWriter::VisitDependentSizedMatrixTypeLoc(466 DependentSizedMatrixTypeLoc TL) {467 addSourceLocation(TL.getAttrNameLoc());468 SourceRange range = TL.getAttrOperandParensRange();469 addSourceLocation(range.getBegin());470 addSourceLocation(range.getEnd());471 Record.AddStmt(TL.getAttrRowOperand());472 Record.AddStmt(TL.getAttrColumnOperand());473}474 475void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) {476 addSourceLocation(TL.getLocalRangeBegin());477 addSourceLocation(TL.getLParenLoc());478 addSourceLocation(TL.getRParenLoc());479 addSourceRange(TL.getExceptionSpecRange());480 addSourceLocation(TL.getLocalRangeEnd());481 for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i)482 Record.AddDeclRef(TL.getParam(i));483}484 485void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {486 VisitFunctionTypeLoc(TL);487}488 489void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {490 VisitFunctionTypeLoc(TL);491}492 493void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {494 addSourceLocation(TL.getElaboratedKeywordLoc());495 Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());496 addSourceLocation(TL.getNameLoc());497}498 499void TypeLocWriter::VisitUsingTypeLoc(UsingTypeLoc TL) {500 addSourceLocation(TL.getElaboratedKeywordLoc());501 Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());502 addSourceLocation(TL.getNameLoc());503}504 505void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {506 addSourceLocation(TL.getElaboratedKeywordLoc());507 Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());508 addSourceLocation(TL.getNameLoc());509}510 511void TypeLocWriter::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) {512 if (TL.getNumProtocols()) {513 addSourceLocation(TL.getProtocolLAngleLoc());514 addSourceLocation(TL.getProtocolRAngleLoc());515 }516 for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)517 addSourceLocation(TL.getProtocolLoc(i));518}519 520void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {521 addSourceLocation(TL.getTypeofLoc());522 addSourceLocation(TL.getLParenLoc());523 addSourceLocation(TL.getRParenLoc());524}525 526void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {527 addSourceLocation(TL.getTypeofLoc());528 addSourceLocation(TL.getLParenLoc());529 addSourceLocation(TL.getRParenLoc());530 Record.AddTypeSourceInfo(TL.getUnmodifiedTInfo());531}532 533void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {534 addSourceLocation(TL.getDecltypeLoc());535 addSourceLocation(TL.getRParenLoc());536}537 538void TypeLocWriter::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {539 addSourceLocation(TL.getKWLoc());540 addSourceLocation(TL.getLParenLoc());541 addSourceLocation(TL.getRParenLoc());542 Record.AddTypeSourceInfo(TL.getUnderlyingTInfo());543}544 545void ASTRecordWriter::AddConceptReference(const ConceptReference *CR) {546 assert(CR);547 AddNestedNameSpecifierLoc(CR->getNestedNameSpecifierLoc());548 AddSourceLocation(CR->getTemplateKWLoc());549 AddDeclarationNameInfo(CR->getConceptNameInfo());550 AddDeclRef(CR->getFoundDecl());551 AddDeclRef(CR->getNamedConcept());552 push_back(CR->getTemplateArgsAsWritten() != nullptr);553 if (CR->getTemplateArgsAsWritten())554 AddASTTemplateArgumentListInfo(CR->getTemplateArgsAsWritten());555}556 557void TypeLocWriter::VisitPackIndexingTypeLoc(PackIndexingTypeLoc TL) {558 addSourceLocation(TL.getEllipsisLoc());559}560 561void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) {562 addSourceLocation(TL.getNameLoc());563 auto *CR = TL.getConceptReference();564 Record.push_back(TL.isConstrained() && CR);565 if (TL.isConstrained() && CR)566 Record.AddConceptReference(CR);567 Record.push_back(TL.isDecltypeAuto());568 if (TL.isDecltypeAuto())569 addSourceLocation(TL.getRParenLoc());570}571 572void TypeLocWriter::VisitDeducedTemplateSpecializationTypeLoc(573 DeducedTemplateSpecializationTypeLoc TL) {574 addSourceLocation(TL.getElaboratedKeywordLoc());575 Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());576 addSourceLocation(TL.getTemplateNameLoc());577}578 579void TypeLocWriter::VisitTagTypeLoc(TagTypeLoc TL) {580 addSourceLocation(TL.getElaboratedKeywordLoc());581 Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());582 addSourceLocation(TL.getNameLoc());583}584 585void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {586 VisitTagTypeLoc(TL);587}588 589void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {590 VisitTagTypeLoc(TL);591}592 593void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) { VisitTagTypeLoc(TL); }594 595void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {596 Record.AddAttr(TL.getAttr());597}598 599void TypeLocWriter::VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) {600 // Nothing to do601}602 603void TypeLocWriter::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) {604 // Nothing to do.605}606 607void TypeLocWriter::VisitHLSLAttributedResourceTypeLoc(608 HLSLAttributedResourceTypeLoc TL) {609 // Nothing to do.610}611 612void TypeLocWriter::VisitHLSLInlineSpirvTypeLoc(HLSLInlineSpirvTypeLoc TL) {613 // Nothing to do.614}615 616void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {617 addSourceLocation(TL.getNameLoc());618}619 620void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(621 SubstTemplateTypeParmTypeLoc TL) {622 addSourceLocation(TL.getNameLoc());623}624 625void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc(626 SubstTemplateTypeParmPackTypeLoc TL) {627 addSourceLocation(TL.getNameLoc());628}629 630void TypeLocWriter::VisitSubstBuiltinTemplatePackTypeLoc(631 SubstBuiltinTemplatePackTypeLoc TL) {632 addSourceLocation(TL.getNameLoc());633}634 635void TypeLocWriter::VisitTemplateSpecializationTypeLoc(636 TemplateSpecializationTypeLoc TL) {637 addSourceLocation(TL.getElaboratedKeywordLoc());638 Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());639 addSourceLocation(TL.getTemplateKeywordLoc());640 addSourceLocation(TL.getTemplateNameLoc());641 addSourceLocation(TL.getLAngleLoc());642 addSourceLocation(TL.getRAngleLoc());643 for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)644 Record.AddTemplateArgumentLocInfo(TL.getArgLoc(i));645}646 647void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) {648 addSourceLocation(TL.getLParenLoc());649 addSourceLocation(TL.getRParenLoc());650}651 652void TypeLocWriter::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {653 addSourceLocation(TL.getExpansionLoc());654}655 656void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {657 addSourceLocation(TL.getElaboratedKeywordLoc());658 Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());659 addSourceLocation(TL.getNameLoc());660}661 662void TypeLocWriter::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {663 addSourceLocation(TL.getEllipsisLoc());664}665 666void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {667 addSourceLocation(TL.getNameLoc());668 addSourceLocation(TL.getNameEndLoc());669}670 671void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {672 Record.push_back(TL.hasBaseTypeAsWritten());673 addSourceLocation(TL.getTypeArgsLAngleLoc());674 addSourceLocation(TL.getTypeArgsRAngleLoc());675 for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i)676 Record.AddTypeSourceInfo(TL.getTypeArgTInfo(i));677 addSourceLocation(TL.getProtocolLAngleLoc());678 addSourceLocation(TL.getProtocolRAngleLoc());679 for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)680 addSourceLocation(TL.getProtocolLoc(i));681}682 683void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {684 addSourceLocation(TL.getStarLoc());685}686 687void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) {688 addSourceLocation(TL.getKWLoc());689 addSourceLocation(TL.getLParenLoc());690 addSourceLocation(TL.getRParenLoc());691}692 693void TypeLocWriter::VisitPipeTypeLoc(PipeTypeLoc TL) {694 addSourceLocation(TL.getKWLoc());695}696void TypeLocWriter::VisitBitIntTypeLoc(clang::BitIntTypeLoc TL) {697 addSourceLocation(TL.getNameLoc());698}699void TypeLocWriter::VisitDependentBitIntTypeLoc(700 clang::DependentBitIntTypeLoc TL) {701 addSourceLocation(TL.getNameLoc());702}703 704void TypeLocWriter::VisitPredefinedSugarTypeLoc(705 clang::PredefinedSugarTypeLoc TL) {706 // Nothing to do.707}708 709void ASTWriter::WriteTypeAbbrevs() {710 using namespace llvm;711 712 std::shared_ptr<BitCodeAbbrev> Abv;713 714 // Abbreviation for TYPE_EXT_QUAL715 Abv = std::make_shared<BitCodeAbbrev>();716 Abv->Add(BitCodeAbbrevOp(serialization::TYPE_EXT_QUAL));717 Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type718 Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 3)); // Quals719 TypeExtQualAbbrev = Stream.EmitAbbrev(std::move(Abv));720}721 722//===----------------------------------------------------------------------===//723// ASTWriter Implementation724//===----------------------------------------------------------------------===//725 726static void EmitBlockID(unsigned ID, const char *Name,727 llvm::BitstreamWriter &Stream,728 ASTWriter::RecordDataImpl &Record) {729 Record.clear();730 Record.push_back(ID);731 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);732 733 // Emit the block name if present.734 if (!Name || Name[0] == 0)735 return;736 Record.clear();737 while (*Name)738 Record.push_back(*Name++);739 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);740}741 742static void EmitRecordID(unsigned ID, const char *Name,743 llvm::BitstreamWriter &Stream,744 ASTWriter::RecordDataImpl &Record) {745 Record.clear();746 Record.push_back(ID);747 while (*Name)748 Record.push_back(*Name++);749 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);750}751 752static void AddStmtsExprs(llvm::BitstreamWriter &Stream,753 ASTWriter::RecordDataImpl &Record) {754#define RECORD(X) EmitRecordID(X, #X, Stream, Record)755 RECORD(STMT_STOP);756 RECORD(STMT_NULL_PTR);757 RECORD(STMT_REF_PTR);758 RECORD(STMT_NULL);759 RECORD(STMT_COMPOUND);760 RECORD(STMT_CASE);761 RECORD(STMT_DEFAULT);762 RECORD(STMT_LABEL);763 RECORD(STMT_ATTRIBUTED);764 RECORD(STMT_IF);765 RECORD(STMT_SWITCH);766 RECORD(STMT_WHILE);767 RECORD(STMT_DO);768 RECORD(STMT_FOR);769 RECORD(STMT_GOTO);770 RECORD(STMT_INDIRECT_GOTO);771 RECORD(STMT_CONTINUE);772 RECORD(STMT_BREAK);773 RECORD(STMT_RETURN);774 RECORD(STMT_DECL);775 RECORD(STMT_GCCASM);776 RECORD(STMT_MSASM);777 RECORD(EXPR_PREDEFINED);778 RECORD(EXPR_DECL_REF);779 RECORD(EXPR_INTEGER_LITERAL);780 RECORD(EXPR_FIXEDPOINT_LITERAL);781 RECORD(EXPR_FLOATING_LITERAL);782 RECORD(EXPR_IMAGINARY_LITERAL);783 RECORD(EXPR_STRING_LITERAL);784 RECORD(EXPR_CHARACTER_LITERAL);785 RECORD(EXPR_PAREN);786 RECORD(EXPR_PAREN_LIST);787 RECORD(EXPR_UNARY_OPERATOR);788 RECORD(EXPR_SIZEOF_ALIGN_OF);789 RECORD(EXPR_ARRAY_SUBSCRIPT);790 RECORD(EXPR_CALL);791 RECORD(EXPR_MEMBER);792 RECORD(EXPR_BINARY_OPERATOR);793 RECORD(EXPR_COMPOUND_ASSIGN_OPERATOR);794 RECORD(EXPR_CONDITIONAL_OPERATOR);795 RECORD(EXPR_IMPLICIT_CAST);796 RECORD(EXPR_CSTYLE_CAST);797 RECORD(EXPR_COMPOUND_LITERAL);798 RECORD(EXPR_EXT_VECTOR_ELEMENT);799 RECORD(EXPR_INIT_LIST);800 RECORD(EXPR_DESIGNATED_INIT);801 RECORD(EXPR_DESIGNATED_INIT_UPDATE);802 RECORD(EXPR_IMPLICIT_VALUE_INIT);803 RECORD(EXPR_NO_INIT);804 RECORD(EXPR_VA_ARG);805 RECORD(EXPR_ADDR_LABEL);806 RECORD(EXPR_STMT);807 RECORD(EXPR_CHOOSE);808 RECORD(EXPR_GNU_NULL);809 RECORD(EXPR_SHUFFLE_VECTOR);810 RECORD(EXPR_BLOCK);811 RECORD(EXPR_GENERIC_SELECTION);812 RECORD(EXPR_OBJC_STRING_LITERAL);813 RECORD(EXPR_OBJC_BOXED_EXPRESSION);814 RECORD(EXPR_OBJC_ARRAY_LITERAL);815 RECORD(EXPR_OBJC_DICTIONARY_LITERAL);816 RECORD(EXPR_OBJC_ENCODE);817 RECORD(EXPR_OBJC_SELECTOR_EXPR);818 RECORD(EXPR_OBJC_PROTOCOL_EXPR);819 RECORD(EXPR_OBJC_IVAR_REF_EXPR);820 RECORD(EXPR_OBJC_PROPERTY_REF_EXPR);821 RECORD(EXPR_OBJC_KVC_REF_EXPR);822 RECORD(EXPR_OBJC_MESSAGE_EXPR);823 RECORD(STMT_OBJC_FOR_COLLECTION);824 RECORD(STMT_OBJC_CATCH);825 RECORD(STMT_OBJC_FINALLY);826 RECORD(STMT_OBJC_AT_TRY);827 RECORD(STMT_OBJC_AT_SYNCHRONIZED);828 RECORD(STMT_OBJC_AT_THROW);829 RECORD(EXPR_OBJC_BOOL_LITERAL);830 RECORD(STMT_CXX_CATCH);831 RECORD(STMT_CXX_TRY);832 RECORD(STMT_CXX_FOR_RANGE);833 RECORD(EXPR_CXX_OPERATOR_CALL);834 RECORD(EXPR_CXX_MEMBER_CALL);835 RECORD(EXPR_CXX_REWRITTEN_BINARY_OPERATOR);836 RECORD(EXPR_CXX_CONSTRUCT);837 RECORD(EXPR_CXX_TEMPORARY_OBJECT);838 RECORD(EXPR_CXX_STATIC_CAST);839 RECORD(EXPR_CXX_DYNAMIC_CAST);840 RECORD(EXPR_CXX_REINTERPRET_CAST);841 RECORD(EXPR_CXX_CONST_CAST);842 RECORD(EXPR_CXX_ADDRSPACE_CAST);843 RECORD(EXPR_CXX_FUNCTIONAL_CAST);844 RECORD(EXPR_USER_DEFINED_LITERAL);845 RECORD(EXPR_CXX_STD_INITIALIZER_LIST);846 RECORD(EXPR_CXX_BOOL_LITERAL);847 RECORD(EXPR_CXX_PAREN_LIST_INIT);848 RECORD(EXPR_CXX_NULL_PTR_LITERAL);849 RECORD(EXPR_CXX_TYPEID_EXPR);850 RECORD(EXPR_CXX_TYPEID_TYPE);851 RECORD(EXPR_CXX_THIS);852 RECORD(EXPR_CXX_THROW);853 RECORD(EXPR_CXX_DEFAULT_ARG);854 RECORD(EXPR_CXX_DEFAULT_INIT);855 RECORD(EXPR_CXX_BIND_TEMPORARY);856 RECORD(EXPR_CXX_SCALAR_VALUE_INIT);857 RECORD(EXPR_CXX_NEW);858 RECORD(EXPR_CXX_DELETE);859 RECORD(EXPR_CXX_PSEUDO_DESTRUCTOR);860 RECORD(EXPR_EXPR_WITH_CLEANUPS);861 RECORD(EXPR_CXX_DEPENDENT_SCOPE_MEMBER);862 RECORD(EXPR_CXX_DEPENDENT_SCOPE_DECL_REF);863 RECORD(EXPR_CXX_UNRESOLVED_CONSTRUCT);864 RECORD(EXPR_CXX_UNRESOLVED_MEMBER);865 RECORD(EXPR_CXX_UNRESOLVED_LOOKUP);866 RECORD(EXPR_CXX_EXPRESSION_TRAIT);867 RECORD(EXPR_CXX_NOEXCEPT);868 RECORD(EXPR_OPAQUE_VALUE);869 RECORD(EXPR_BINARY_CONDITIONAL_OPERATOR);870 RECORD(EXPR_TYPE_TRAIT);871 RECORD(EXPR_ARRAY_TYPE_TRAIT);872 RECORD(EXPR_PACK_EXPANSION);873 RECORD(EXPR_SIZEOF_PACK);874 RECORD(EXPR_PACK_INDEXING);875 RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM);876 RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK);877 RECORD(EXPR_FUNCTION_PARM_PACK);878 RECORD(EXPR_MATERIALIZE_TEMPORARY);879 RECORD(EXPR_CUDA_KERNEL_CALL);880 RECORD(EXPR_CXX_UUIDOF_EXPR);881 RECORD(EXPR_CXX_UUIDOF_TYPE);882 RECORD(EXPR_LAMBDA);883#undef RECORD884}885 886void ASTWriter::WriteBlockInfoBlock() {887 RecordData Record;888 Stream.EnterBlockInfoBlock();889 890#define BLOCK(X) EmitBlockID(X ## _ID, #X, Stream, Record)891#define RECORD(X) EmitRecordID(X, #X, Stream, Record)892 893 // Control Block.894 BLOCK(CONTROL_BLOCK);895 RECORD(METADATA);896 RECORD(MODULE_NAME);897 RECORD(MODULE_DIRECTORY);898 RECORD(MODULE_MAP_FILE);899 RECORD(IMPORT);900 RECORD(ORIGINAL_FILE);901 RECORD(ORIGINAL_FILE_ID);902 RECORD(INPUT_FILE_OFFSETS);903 904 BLOCK(OPTIONS_BLOCK);905 RECORD(LANGUAGE_OPTIONS);906 RECORD(CODEGEN_OPTIONS);907 RECORD(TARGET_OPTIONS);908 RECORD(FILE_SYSTEM_OPTIONS);909 RECORD(HEADER_SEARCH_OPTIONS);910 RECORD(PREPROCESSOR_OPTIONS);911 912 BLOCK(INPUT_FILES_BLOCK);913 RECORD(INPUT_FILE);914 RECORD(INPUT_FILE_HASH);915 916 // AST Top-Level Block.917 BLOCK(AST_BLOCK);918 RECORD(TYPE_OFFSET);919 RECORD(DECL_OFFSET);920 RECORD(IDENTIFIER_OFFSET);921 RECORD(IDENTIFIER_TABLE);922 RECORD(EAGERLY_DESERIALIZED_DECLS);923 RECORD(MODULAR_CODEGEN_DECLS);924 RECORD(SPECIAL_TYPES);925 RECORD(STATISTICS);926 RECORD(TENTATIVE_DEFINITIONS);927 RECORD(SELECTOR_OFFSETS);928 RECORD(METHOD_POOL);929 RECORD(PP_COUNTER_VALUE);930 RECORD(SOURCE_LOCATION_OFFSETS);931 RECORD(EXT_VECTOR_DECLS);932 RECORD(UNUSED_FILESCOPED_DECLS);933 RECORD(PPD_ENTITIES_OFFSETS);934 RECORD(VTABLE_USES);935 RECORD(PPD_SKIPPED_RANGES);936 RECORD(REFERENCED_SELECTOR_POOL);937 RECORD(TU_UPDATE_LEXICAL);938 RECORD(SEMA_DECL_REFS);939 RECORD(WEAK_UNDECLARED_IDENTIFIERS);940 RECORD(PENDING_IMPLICIT_INSTANTIATIONS);941 RECORD(UPDATE_VISIBLE);942 RECORD(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD);943 RECORD(RELATED_DECLS_MAP);944 RECORD(DECL_UPDATE_OFFSETS);945 RECORD(DECL_UPDATES);946 RECORD(CUDA_SPECIAL_DECL_REFS);947 RECORD(HEADER_SEARCH_TABLE);948 RECORD(FP_PRAGMA_OPTIONS);949 RECORD(OPENCL_EXTENSIONS);950 RECORD(OPENCL_EXTENSION_TYPES);951 RECORD(OPENCL_EXTENSION_DECLS);952 RECORD(DELEGATING_CTORS);953 RECORD(KNOWN_NAMESPACES);954 RECORD(MODULE_OFFSET_MAP);955 RECORD(SOURCE_MANAGER_LINE_TABLE);956 RECORD(OBJC_CATEGORIES_MAP);957 RECORD(FILE_SORTED_DECLS);958 RECORD(IMPORTED_MODULES);959 RECORD(OBJC_CATEGORIES);960 RECORD(MACRO_OFFSET);961 RECORD(INTERESTING_IDENTIFIERS);962 RECORD(UNDEFINED_BUT_USED);963 RECORD(LATE_PARSED_TEMPLATE);964 RECORD(OPTIMIZE_PRAGMA_OPTIONS);965 RECORD(MSSTRUCT_PRAGMA_OPTIONS);966 RECORD(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS);967 RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES);968 RECORD(DELETE_EXPRS_TO_ANALYZE);969 RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH);970 RECORD(PP_CONDITIONAL_STACK);971 RECORD(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS);972 RECORD(PP_ASSUME_NONNULL_LOC);973 RECORD(PP_UNSAFE_BUFFER_USAGE);974 RECORD(VTABLES_TO_EMIT);975 976 // SourceManager Block.977 BLOCK(SOURCE_MANAGER_BLOCK);978 RECORD(SM_SLOC_FILE_ENTRY);979 RECORD(SM_SLOC_BUFFER_ENTRY);980 RECORD(SM_SLOC_BUFFER_BLOB);981 RECORD(SM_SLOC_BUFFER_BLOB_COMPRESSED);982 RECORD(SM_SLOC_EXPANSION_ENTRY);983 984 // Preprocessor Block.985 BLOCK(PREPROCESSOR_BLOCK);986 RECORD(PP_MACRO_DIRECTIVE_HISTORY);987 RECORD(PP_MACRO_FUNCTION_LIKE);988 RECORD(PP_MACRO_OBJECT_LIKE);989 RECORD(PP_MODULE_MACRO);990 RECORD(PP_TOKEN);991 992 // Submodule Block.993 BLOCK(SUBMODULE_BLOCK);994 RECORD(SUBMODULE_METADATA);995 RECORD(SUBMODULE_DEFINITION);996 RECORD(SUBMODULE_UMBRELLA_HEADER);997 RECORD(SUBMODULE_HEADER);998 RECORD(SUBMODULE_TOPHEADER);999 RECORD(SUBMODULE_UMBRELLA_DIR);1000 RECORD(SUBMODULE_IMPORTS);1001 RECORD(SUBMODULE_AFFECTING_MODULES);1002 RECORD(SUBMODULE_EXPORTS);1003 RECORD(SUBMODULE_REQUIRES);1004 RECORD(SUBMODULE_EXCLUDED_HEADER);1005 RECORD(SUBMODULE_LINK_LIBRARY);1006 RECORD(SUBMODULE_CONFIG_MACRO);1007 RECORD(SUBMODULE_CONFLICT);1008 RECORD(SUBMODULE_PRIVATE_HEADER);1009 RECORD(SUBMODULE_TEXTUAL_HEADER);1010 RECORD(SUBMODULE_PRIVATE_TEXTUAL_HEADER);1011 RECORD(SUBMODULE_INITIALIZERS);1012 RECORD(SUBMODULE_EXPORT_AS);1013 1014 // Comments Block.1015 BLOCK(COMMENTS_BLOCK);1016 RECORD(COMMENTS_RAW_COMMENT);1017 1018 // Decls and Types block.1019 BLOCK(DECLTYPES_BLOCK);1020 RECORD(TYPE_EXT_QUAL);1021 RECORD(TYPE_COMPLEX);1022 RECORD(TYPE_POINTER);1023 RECORD(TYPE_BLOCK_POINTER);1024 RECORD(TYPE_LVALUE_REFERENCE);1025 RECORD(TYPE_RVALUE_REFERENCE);1026 RECORD(TYPE_MEMBER_POINTER);1027 RECORD(TYPE_CONSTANT_ARRAY);1028 RECORD(TYPE_INCOMPLETE_ARRAY);1029 RECORD(TYPE_VARIABLE_ARRAY);1030 RECORD(TYPE_VECTOR);1031 RECORD(TYPE_EXT_VECTOR);1032 RECORD(TYPE_FUNCTION_NO_PROTO);1033 RECORD(TYPE_FUNCTION_PROTO);1034 RECORD(TYPE_TYPEDEF);1035 RECORD(TYPE_TYPEOF_EXPR);1036 RECORD(TYPE_TYPEOF);1037 RECORD(TYPE_RECORD);1038 RECORD(TYPE_ENUM);1039 RECORD(TYPE_OBJC_INTERFACE);1040 RECORD(TYPE_OBJC_OBJECT_POINTER);1041 RECORD(TYPE_DECLTYPE);1042 RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM);1043 RECORD(TYPE_UNRESOLVED_USING);1044 RECORD(TYPE_INJECTED_CLASS_NAME);1045 RECORD(TYPE_OBJC_OBJECT);1046 RECORD(TYPE_TEMPLATE_TYPE_PARM);1047 RECORD(TYPE_TEMPLATE_SPECIALIZATION);1048 RECORD(TYPE_DEPENDENT_NAME);1049 RECORD(TYPE_DEPENDENT_SIZED_ARRAY);1050 RECORD(TYPE_PAREN);1051 RECORD(TYPE_MACRO_QUALIFIED);1052 RECORD(TYPE_PACK_EXPANSION);1053 RECORD(TYPE_ATTRIBUTED);1054 RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK);1055 RECORD(TYPE_SUBST_BUILTIN_TEMPLATE_PACK);1056 RECORD(TYPE_AUTO);1057 RECORD(TYPE_UNARY_TRANSFORM);1058 RECORD(TYPE_ATOMIC);1059 RECORD(TYPE_DECAYED);1060 RECORD(TYPE_ADJUSTED);1061 RECORD(TYPE_OBJC_TYPE_PARAM);1062 RECORD(LOCAL_REDECLARATIONS);1063 RECORD(DECL_TYPEDEF);1064 RECORD(DECL_TYPEALIAS);1065 RECORD(DECL_ENUM);1066 RECORD(DECL_RECORD);1067 RECORD(DECL_ENUM_CONSTANT);1068 RECORD(DECL_FUNCTION);1069 RECORD(DECL_OBJC_METHOD);1070 RECORD(DECL_OBJC_INTERFACE);1071 RECORD(DECL_OBJC_PROTOCOL);1072 RECORD(DECL_OBJC_IVAR);1073 RECORD(DECL_OBJC_AT_DEFS_FIELD);1074 RECORD(DECL_OBJC_CATEGORY);1075 RECORD(DECL_OBJC_CATEGORY_IMPL);1076 RECORD(DECL_OBJC_IMPLEMENTATION);1077 RECORD(DECL_OBJC_COMPATIBLE_ALIAS);1078 RECORD(DECL_OBJC_PROPERTY);1079 RECORD(DECL_OBJC_PROPERTY_IMPL);1080 RECORD(DECL_FIELD);1081 RECORD(DECL_MS_PROPERTY);1082 RECORD(DECL_VAR);1083 RECORD(DECL_IMPLICIT_PARAM);1084 RECORD(DECL_PARM_VAR);1085 RECORD(DECL_FILE_SCOPE_ASM);1086 RECORD(DECL_BLOCK);1087 RECORD(DECL_CONTEXT_LEXICAL);1088 RECORD(DECL_CONTEXT_VISIBLE);1089 RECORD(DECL_CONTEXT_MODULE_LOCAL_VISIBLE);1090 RECORD(DECL_NAMESPACE);1091 RECORD(DECL_NAMESPACE_ALIAS);1092 RECORD(DECL_USING);1093 RECORD(DECL_USING_SHADOW);1094 RECORD(DECL_USING_DIRECTIVE);1095 RECORD(DECL_UNRESOLVED_USING_VALUE);1096 RECORD(DECL_UNRESOLVED_USING_TYPENAME);1097 RECORD(DECL_LINKAGE_SPEC);1098 RECORD(DECL_EXPORT);1099 RECORD(DECL_CXX_RECORD);1100 RECORD(DECL_CXX_METHOD);1101 RECORD(DECL_CXX_CONSTRUCTOR);1102 RECORD(DECL_CXX_DESTRUCTOR);1103 RECORD(DECL_CXX_CONVERSION);1104 RECORD(DECL_ACCESS_SPEC);1105 RECORD(DECL_FRIEND);1106 RECORD(DECL_FRIEND_TEMPLATE);1107 RECORD(DECL_CLASS_TEMPLATE);1108 RECORD(DECL_CLASS_TEMPLATE_SPECIALIZATION);1109 RECORD(DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION);1110 RECORD(DECL_VAR_TEMPLATE);1111 RECORD(DECL_VAR_TEMPLATE_SPECIALIZATION);1112 RECORD(DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION);1113 RECORD(DECL_FUNCTION_TEMPLATE);1114 RECORD(DECL_TEMPLATE_TYPE_PARM);1115 RECORD(DECL_NON_TYPE_TEMPLATE_PARM);1116 RECORD(DECL_TEMPLATE_TEMPLATE_PARM);1117 RECORD(DECL_CONCEPT);1118 RECORD(DECL_REQUIRES_EXPR_BODY);1119 RECORD(DECL_TYPE_ALIAS_TEMPLATE);1120 RECORD(DECL_STATIC_ASSERT);1121 RECORD(DECL_CXX_BASE_SPECIFIERS);1122 RECORD(DECL_CXX_CTOR_INITIALIZERS);1123 RECORD(DECL_INDIRECTFIELD);1124 RECORD(DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK);1125 RECORD(DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK);1126 RECORD(DECL_IMPORT);1127 RECORD(DECL_OMP_THREADPRIVATE);1128 RECORD(DECL_EMPTY);1129 RECORD(DECL_OBJC_TYPE_PARAM);1130 RECORD(DECL_OMP_CAPTUREDEXPR);1131 RECORD(DECL_PRAGMA_COMMENT);1132 RECORD(DECL_PRAGMA_DETECT_MISMATCH);1133 RECORD(DECL_OMP_DECLARE_REDUCTION);1134 RECORD(DECL_OMP_ALLOCATE);1135 RECORD(DECL_HLSL_BUFFER);1136 RECORD(DECL_OPENACC_DECLARE);1137 RECORD(DECL_OPENACC_ROUTINE);1138 1139 // Statements and Exprs can occur in the Decls and Types block.1140 AddStmtsExprs(Stream, Record);1141 1142 BLOCK(PREPROCESSOR_DETAIL_BLOCK);1143 RECORD(PPD_MACRO_EXPANSION);1144 RECORD(PPD_MACRO_DEFINITION);1145 RECORD(PPD_INCLUSION_DIRECTIVE);1146 1147 // Decls and Types block.1148 BLOCK(EXTENSION_BLOCK);1149 RECORD(EXTENSION_METADATA);1150 1151 BLOCK(UNHASHED_CONTROL_BLOCK);1152 RECORD(SIGNATURE);1153 RECORD(AST_BLOCK_HASH);1154 RECORD(DIAGNOSTIC_OPTIONS);1155 RECORD(HEADER_SEARCH_PATHS);1156 RECORD(DIAG_PRAGMA_MAPPINGS);1157 RECORD(HEADER_SEARCH_ENTRY_USAGE);1158 RECORD(VFS_USAGE);1159 1160#undef RECORD1161#undef BLOCK1162 Stream.ExitBlock();1163}1164 1165/// Prepares a path for being written to an AST file by converting it1166/// to an absolute path and removing nested './'s.1167///1168/// \return \c true if the path was changed.1169static bool cleanPathForOutput(FileManager &FileMgr,1170 SmallVectorImpl<char> &Path) {1171 bool Changed = FileMgr.makeAbsolutePath(Path);1172 return Changed | llvm::sys::path::remove_dots(Path);1173}1174 1175/// Adjusts the given filename to only write out the portion of the1176/// filename that is not part of the system root directory.1177///1178/// \param Filename the file name to adjust.1179///1180/// \param BaseDir When non-NULL, the PCH file is a relocatable AST file and1181/// the returned filename will be adjusted by this root directory.1182///1183/// \returns either the original filename (if it needs no adjustment) or the1184/// adjusted filename (which points into the @p Filename parameter).1185static const char *1186adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) {1187 assert(Filename && "No file name to adjust?");1188 1189 if (BaseDir.empty())1190 return Filename;1191 1192 // Verify that the filename and the system root have the same prefix.1193 unsigned Pos = 0;1194 for (; Filename[Pos] && Pos < BaseDir.size(); ++Pos)1195 if (Filename[Pos] != BaseDir[Pos])1196 return Filename; // Prefixes don't match.1197 1198 // We hit the end of the filename before we hit the end of the system root.1199 if (!Filename[Pos])1200 return Filename;1201 1202 // If there's not a path separator at the end of the base directory nor1203 // immediately after it, then this isn't within the base directory.1204 if (!llvm::sys::path::is_separator(Filename[Pos])) {1205 if (!llvm::sys::path::is_separator(BaseDir.back()))1206 return Filename;1207 } else {1208 // If the file name has a '/' at the current position, skip over the '/'.1209 // We distinguish relative paths from absolute paths by the1210 // absence of '/' at the beginning of relative paths.1211 //1212 // FIXME: This is wrong. We distinguish them by asking if the path is1213 // absolute, which isn't the same thing. And there might be multiple '/'s1214 // in a row. Use a better mechanism to indicate whether we have emitted an1215 // absolute or relative path.1216 ++Pos;1217 }1218 1219 return Filename + Pos;1220}1221 1222std::pair<ASTFileSignature, ASTFileSignature>1223ASTWriter::createSignature() const {1224 StringRef AllBytes(Buffer.data(), Buffer.size());1225 1226 llvm::SHA1 Hasher;1227 Hasher.update(AllBytes.slice(ASTBlockRange.first, ASTBlockRange.second));1228 ASTFileSignature ASTBlockHash = ASTFileSignature::create(Hasher.result());1229 1230 // Add the remaining bytes:1231 // 1. Before the unhashed control block.1232 Hasher.update(AllBytes.slice(0, UnhashedControlBlockRange.first));1233 // 2. Between the unhashed control block and the AST block.1234 Hasher.update(1235 AllBytes.slice(UnhashedControlBlockRange.second, ASTBlockRange.first));1236 // 3. After the AST block.1237 Hasher.update(AllBytes.substr(ASTBlockRange.second));1238 ASTFileSignature Signature = ASTFileSignature::create(Hasher.result());1239 1240 return std::make_pair(ASTBlockHash, Signature);1241}1242 1243ASTFileSignature ASTWriter::createSignatureForNamedModule() const {1244 llvm::SHA1 Hasher;1245 Hasher.update(StringRef(Buffer.data(), Buffer.size()));1246 1247 assert(WritingModule);1248 assert(WritingModule->isNamedModule());1249 1250 // We need to combine all the export imported modules no matter1251 // we used it or not.1252 for (auto [ExportImported, _] : WritingModule->Exports)1253 Hasher.update(ExportImported->Signature);1254 1255 // We combine all the used modules to make sure the signature is precise.1256 // Consider the case like:1257 //1258 // // a.cppm1259 // export module a;1260 // export inline int a() { ... }1261 //1262 // // b.cppm1263 // export module b;1264 // import a;1265 // export inline int b() { return a(); }1266 //1267 // Since both `a()` and `b()` are inline, we need to make sure the BMI of1268 // `b.pcm` will change after the implementation of `a()` changes. We can't1269 // get that naturally since we won't record the body of `a()` during the1270 // writing process. We can't reuse ODRHash here since ODRHash won't calculate1271 // the called function recursively. So ODRHash will be problematic if `a()`1272 // calls other inline functions.1273 //1274 // Probably we can solve this by a new hash mechanism. But the safety and1275 // efficiency may a problem too. Here we just combine the hash value of the1276 // used modules conservatively.1277 for (Module *M : TouchedTopLevelModules)1278 Hasher.update(M->Signature);1279 1280 return ASTFileSignature::create(Hasher.result());1281}1282 1283static void BackpatchSignatureAt(llvm::BitstreamWriter &Stream,1284 const ASTFileSignature &S, uint64_t BitNo) {1285 for (uint8_t Byte : S) {1286 Stream.BackpatchByte(BitNo, Byte);1287 BitNo += 8;1288 }1289}1290 1291ASTFileSignature ASTWriter::backpatchSignature() {1292 if (isWritingStdCXXNamedModules()) {1293 ASTFileSignature Signature = createSignatureForNamedModule();1294 BackpatchSignatureAt(Stream, Signature, SignatureOffset);1295 return Signature;1296 }1297 1298 if (!WritingModule ||1299 !PP->getHeaderSearchInfo().getHeaderSearchOpts().ModulesHashContent)1300 return {};1301 1302 // For implicit modules, write the hash of the PCM as its signature.1303 ASTFileSignature ASTBlockHash;1304 ASTFileSignature Signature;1305 std::tie(ASTBlockHash, Signature) = createSignature();1306 1307 BackpatchSignatureAt(Stream, ASTBlockHash, ASTBlockHashOffset);1308 BackpatchSignatureAt(Stream, Signature, SignatureOffset);1309 1310 return Signature;1311}1312 1313void ASTWriter::writeUnhashedControlBlock(Preprocessor &PP) {1314 using namespace llvm;1315 1316 // Flush first to prepare the PCM hash (signature).1317 Stream.FlushToWord();1318 UnhashedControlBlockRange.first = Stream.GetCurrentBitNo() >> 3;1319 1320 // Enter the block and prepare to write records.1321 RecordData Record;1322 Stream.EnterSubblock(UNHASHED_CONTROL_BLOCK_ID, 5);1323 1324 // For implicit modules and C++20 named modules, write the hash of the PCM as1325 // its signature.1326 if (isWritingStdCXXNamedModules() ||1327 (WritingModule &&1328 PP.getHeaderSearchInfo().getHeaderSearchOpts().ModulesHashContent)) {1329 // At this point, we don't know the actual signature of the file or the AST1330 // block - we're only able to compute those at the end of the serialization1331 // process. Let's store dummy signatures for now, and replace them with the1332 // real ones later on.1333 // The bitstream VBR-encodes record elements, which makes backpatching them1334 // really difficult. Let's store the signatures as blobs instead - they are1335 // guaranteed to be word-aligned, and we control their format/encoding.1336 auto Dummy = ASTFileSignature::createDummy();1337 SmallString<128> Blob{Dummy.begin(), Dummy.end()};1338 1339 // We don't need AST Block hash in named modules.1340 if (!isWritingStdCXXNamedModules()) {1341 auto Abbrev = std::make_shared<BitCodeAbbrev>();1342 Abbrev->Add(BitCodeAbbrevOp(AST_BLOCK_HASH));1343 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));1344 unsigned ASTBlockHashAbbrev = Stream.EmitAbbrev(std::move(Abbrev));1345 1346 Record.push_back(AST_BLOCK_HASH);1347 Stream.EmitRecordWithBlob(ASTBlockHashAbbrev, Record, Blob);1348 ASTBlockHashOffset = Stream.GetCurrentBitNo() - Blob.size() * 8;1349 Record.clear();1350 }1351 1352 auto Abbrev = std::make_shared<BitCodeAbbrev>();1353 Abbrev->Add(BitCodeAbbrevOp(SIGNATURE));1354 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));1355 unsigned SignatureAbbrev = Stream.EmitAbbrev(std::move(Abbrev));1356 1357 Record.push_back(SIGNATURE);1358 Stream.EmitRecordWithBlob(SignatureAbbrev, Record, Blob);1359 SignatureOffset = Stream.GetCurrentBitNo() - Blob.size() * 8;1360 Record.clear();1361 }1362 1363 const auto &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();1364 1365 // Diagnostic options.1366 const auto &Diags = PP.getDiagnostics();1367 const DiagnosticOptions &DiagOpts = Diags.getDiagnosticOptions();1368 if (!HSOpts.ModulesSkipDiagnosticOptions) {1369#define DIAGOPT(Name, Bits, Default) Record.push_back(DiagOpts.Name);1370#define ENUM_DIAGOPT(Name, Type, Bits, Default) \1371 Record.push_back(static_cast<unsigned>(DiagOpts.get##Name()));1372#include "clang/Basic/DiagnosticOptions.def"1373 Record.push_back(DiagOpts.Warnings.size());1374 for (unsigned I = 0, N = DiagOpts.Warnings.size(); I != N; ++I)1375 AddString(DiagOpts.Warnings[I], Record);1376 Record.push_back(DiagOpts.Remarks.size());1377 for (unsigned I = 0, N = DiagOpts.Remarks.size(); I != N; ++I)1378 AddString(DiagOpts.Remarks[I], Record);1379 // Note: we don't serialize the log or serialization file names, because1380 // they are generally transient files and will almost always be overridden.1381 Stream.EmitRecord(DIAGNOSTIC_OPTIONS, Record);1382 Record.clear();1383 }1384 1385 // Header search paths.1386 if (!HSOpts.ModulesSkipHeaderSearchPaths) {1387 // Include entries.1388 Record.push_back(HSOpts.UserEntries.size());1389 for (unsigned I = 0, N = HSOpts.UserEntries.size(); I != N; ++I) {1390 const HeaderSearchOptions::Entry &Entry = HSOpts.UserEntries[I];1391 AddString(Entry.Path, Record);1392 Record.push_back(static_cast<unsigned>(Entry.Group));1393 Record.push_back(Entry.IsFramework);1394 Record.push_back(Entry.IgnoreSysRoot);1395 }1396 1397 // System header prefixes.1398 Record.push_back(HSOpts.SystemHeaderPrefixes.size());1399 for (unsigned I = 0, N = HSOpts.SystemHeaderPrefixes.size(); I != N; ++I) {1400 AddString(HSOpts.SystemHeaderPrefixes[I].Prefix, Record);1401 Record.push_back(HSOpts.SystemHeaderPrefixes[I].IsSystemHeader);1402 }1403 1404 // VFS overlay files.1405 Record.push_back(HSOpts.VFSOverlayFiles.size());1406 for (StringRef VFSOverlayFile : HSOpts.VFSOverlayFiles)1407 AddString(VFSOverlayFile, Record);1408 1409 Stream.EmitRecord(HEADER_SEARCH_PATHS, Record);1410 }1411 1412 if (!HSOpts.ModulesSkipPragmaDiagnosticMappings)1413 WritePragmaDiagnosticMappings(Diags, /* isModule = */ WritingModule);1414 1415 // Header search entry usage.1416 {1417 auto HSEntryUsage = PP.getHeaderSearchInfo().computeUserEntryUsage();1418 auto Abbrev = std::make_shared<BitCodeAbbrev>();1419 Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_ENTRY_USAGE));1420 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Number of bits.1421 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Bit vector.1422 unsigned HSUsageAbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));1423 RecordData::value_type Record[] = {HEADER_SEARCH_ENTRY_USAGE,1424 HSEntryUsage.size()};1425 Stream.EmitRecordWithBlob(HSUsageAbbrevCode, Record, bytes(HSEntryUsage));1426 }1427 1428 // VFS usage.1429 {1430 auto VFSUsage = PP.getHeaderSearchInfo().collectVFSUsageAndClear();1431 auto Abbrev = std::make_shared<BitCodeAbbrev>();1432 Abbrev->Add(BitCodeAbbrevOp(VFS_USAGE));1433 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Number of bits.1434 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Bit vector.1435 unsigned VFSUsageAbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));1436 RecordData::value_type Record[] = {VFS_USAGE, VFSUsage.size()};1437 Stream.EmitRecordWithBlob(VFSUsageAbbrevCode, Record, bytes(VFSUsage));1438 }1439 1440 // Leave the options block.1441 Stream.ExitBlock();1442 UnhashedControlBlockRange.second = Stream.GetCurrentBitNo() >> 3;1443}1444 1445/// Write the control block.1446void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) {1447 using namespace llvm;1448 1449 SourceManager &SourceMgr = PP.getSourceManager();1450 FileManager &FileMgr = PP.getFileManager();1451 1452 Stream.EnterSubblock(CONTROL_BLOCK_ID, 5);1453 RecordData Record;1454 1455 // Metadata1456 auto MetadataAbbrev = std::make_shared<BitCodeAbbrev>();1457 MetadataAbbrev->Add(BitCodeAbbrevOp(METADATA));1458 MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Major1459 MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Minor1460 MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang maj.1461 MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min.1462 MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable1463 // Standard C++ module1464 MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));1465 MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Timestamps1466 MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors1467 MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag1468 unsigned MetadataAbbrevCode = Stream.EmitAbbrev(std::move(MetadataAbbrev));1469 assert((!WritingModule || isysroot.empty()) &&1470 "writing module as a relocatable PCH?");1471 {1472 RecordData::value_type Record[] = {METADATA,1473 VERSION_MAJOR,1474 VERSION_MINOR,1475 CLANG_VERSION_MAJOR,1476 CLANG_VERSION_MINOR,1477 !isysroot.empty(),1478 isWritingStdCXXNamedModules(),1479 IncludeTimestamps,1480 ASTHasCompilerErrors};1481 Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,1482 getClangFullRepositoryVersion());1483 }1484 1485 if (WritingModule) {1486 // Module name1487 auto Abbrev = std::make_shared<BitCodeAbbrev>();1488 Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME));1489 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name1490 unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));1491 RecordData::value_type Record[] = {MODULE_NAME};1492 Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name);1493 1494 auto BaseDir = [&]() -> std::optional<SmallString<128>> {1495 if (PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd) {1496 // Use the current working directory as the base path for all inputs.1497 auto CWD = FileMgr.getOptionalDirectoryRef(".");1498 return CWD->getName();1499 }1500 if (WritingModule->Directory) {1501 return WritingModule->Directory->getName();1502 }1503 return std::nullopt;1504 }();1505 if (BaseDir) {1506 cleanPathForOutput(FileMgr, *BaseDir);1507 1508 // If the home of the module is the current working directory, then we1509 // want to pick up the cwd of the build process loading the module, not1510 // our cwd, when we load this module.1511 if (!PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd &&1512 (!PP.getHeaderSearchInfo()1513 .getHeaderSearchOpts()1514 .ModuleMapFileHomeIsCwd ||1515 WritingModule->Directory->getName() != ".")) {1516 // Module directory.1517 auto Abbrev = std::make_shared<BitCodeAbbrev>();1518 Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY));1519 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Directory1520 unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));1521 1522 RecordData::value_type Record[] = {MODULE_DIRECTORY};1523 Stream.EmitRecordWithBlob(AbbrevCode, Record, *BaseDir);1524 }1525 1526 // Write out all other paths relative to the base directory if possible.1527 BaseDirectory.assign(BaseDir->begin(), BaseDir->end());1528 } else if (!isysroot.empty()) {1529 // Write out paths relative to the sysroot if possible.1530 BaseDirectory = std::string(isysroot);1531 }1532 }1533 1534 // Module map file1535 if (WritingModule && WritingModule->Kind == Module::ModuleMapModule) {1536 Record.clear();1537 1538 auto &Map = PP.getHeaderSearchInfo().getModuleMap();1539 AddPath(WritingModule->PresumedModuleMapFile.empty()1540 ? Map.getModuleMapFileForUniquing(WritingModule)1541 ->getNameAsRequested()1542 : StringRef(WritingModule->PresumedModuleMapFile),1543 Record);1544 1545 // Additional module map files.1546 if (auto *AdditionalModMaps =1547 Map.getAdditionalModuleMapFiles(WritingModule)) {1548 Record.push_back(AdditionalModMaps->size());1549 SmallVector<FileEntryRef, 1> ModMaps(AdditionalModMaps->begin(),1550 AdditionalModMaps->end());1551 llvm::sort(ModMaps, [](FileEntryRef A, FileEntryRef B) {1552 return A.getName() < B.getName();1553 });1554 for (FileEntryRef F : ModMaps)1555 AddPath(F.getName(), Record);1556 } else {1557 Record.push_back(0);1558 }1559 1560 Stream.EmitRecord(MODULE_MAP_FILE, Record);1561 }1562 1563 // Imports1564 if (Chain) {1565 auto Abbrev = std::make_shared<BitCodeAbbrev>();1566 Abbrev->Add(BitCodeAbbrevOp(IMPORT));1567 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Kind1568 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ImportLoc1569 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Module name len1570 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Standard C++ mod1571 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File size1572 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File timestamp1573 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File name len1574 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Strings1575 unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));1576 1577 SmallString<128> Blob;1578 1579 for (ModuleFile &M : Chain->getModuleManager()) {1580 // Skip modules that weren't directly imported.1581 if (!M.isDirectlyImported())1582 continue;1583 1584 Record.clear();1585 Blob.clear();1586 1587 Record.push_back(IMPORT);1588 Record.push_back((unsigned)M.Kind); // FIXME: Stable encoding1589 AddSourceLocation(M.ImportLoc, Record);1590 AddStringBlob(M.ModuleName, Record, Blob);1591 Record.push_back(M.StandardCXXModule);1592 1593 // We don't want to hard code the information about imported modules1594 // in the C++20 named modules.1595 if (M.StandardCXXModule) {1596 Record.push_back(0);1597 Record.push_back(0);1598 Record.push_back(0);1599 } else {1600 // If we have calculated signature, there is no need to store1601 // the size or timestamp.1602 Record.push_back(M.Signature ? 0 : M.File.getSize());1603 Record.push_back(M.Signature ? 0 : getTimestampForOutput(M.File));1604 1605 llvm::append_range(Blob, M.Signature);1606 1607 AddPathBlob(M.FileName, Record, Blob);1608 }1609 1610 Stream.EmitRecordWithBlob(AbbrevCode, Record, Blob);1611 }1612 }1613 1614 // Write the options block.1615 Stream.EnterSubblock(OPTIONS_BLOCK_ID, 4);1616 1617 // Language options.1618 Record.clear();1619 const LangOptions &LangOpts = PP.getLangOpts();1620#define LANGOPT(Name, Bits, Default, Compatibility, Description) \1621 Record.push_back(LangOpts.Name);1622#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \1623 Record.push_back(static_cast<unsigned>(LangOpts.get##Name()));1624#include "clang/Basic/LangOptions.def"1625#define SANITIZER(NAME, ID) \1626 Record.push_back(LangOpts.Sanitize.has(SanitizerKind::ID));1627#include "clang/Basic/Sanitizers.def"1628 1629 Record.push_back(LangOpts.ModuleFeatures.size());1630 for (StringRef Feature : LangOpts.ModuleFeatures)1631 AddString(Feature, Record);1632 1633 Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind());1634 AddVersionTuple(LangOpts.ObjCRuntime.getVersion(), Record);1635 1636 AddString(LangOpts.CurrentModule, Record);1637 1638 // Comment options.1639 Record.push_back(LangOpts.CommentOpts.BlockCommandNames.size());1640 for (const auto &I : LangOpts.CommentOpts.BlockCommandNames) {1641 AddString(I, Record);1642 }1643 Record.push_back(LangOpts.CommentOpts.ParseAllComments);1644 1645 // OpenMP offloading options.1646 Record.push_back(LangOpts.OMPTargetTriples.size());1647 for (auto &T : LangOpts.OMPTargetTriples)1648 AddString(T.getTriple(), Record);1649 1650 AddString(LangOpts.OMPHostIRFile, Record);1651 1652 Stream.EmitRecord(LANGUAGE_OPTIONS, Record);1653 1654 // Codegen options.1655 // FIXME: Replace with C++20 `using enum CodeGenOptions::CompatibilityKind`.1656 using CK = CodeGenOptions::CompatibilityKind;1657 Record.clear();1658 const CodeGenOptions &CGOpts = getCodeGenOpts();1659#define CODEGENOPT(Name, Bits, Default, Compatibility) \1660 if constexpr (CK::Compatibility != CK::Benign) \1661 Record.push_back(static_cast<unsigned>(CGOpts.Name));1662#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility) \1663 if constexpr (CK::Compatibility != CK::Benign) \1664 Record.push_back(static_cast<unsigned>(CGOpts.get##Name()));1665#define DEBUGOPT(Name, Bits, Default, Compatibility)1666#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility)1667#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility)1668#include "clang/Basic/CodeGenOptions.def"1669 Stream.EmitRecord(CODEGEN_OPTIONS, Record);1670 1671 // Target options.1672 Record.clear();1673 const TargetInfo &Target = PP.getTargetInfo();1674 const TargetOptions &TargetOpts = Target.getTargetOpts();1675 AddString(TargetOpts.Triple, Record);1676 AddString(TargetOpts.CPU, Record);1677 AddString(TargetOpts.TuneCPU, Record);1678 AddString(TargetOpts.ABI, Record);1679 Record.push_back(TargetOpts.FeaturesAsWritten.size());1680 for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) {1681 AddString(TargetOpts.FeaturesAsWritten[I], Record);1682 }1683 Record.push_back(TargetOpts.Features.size());1684 for (unsigned I = 0, N = TargetOpts.Features.size(); I != N; ++I) {1685 AddString(TargetOpts.Features[I], Record);1686 }1687 Stream.EmitRecord(TARGET_OPTIONS, Record);1688 1689 // File system options.1690 Record.clear();1691 const FileSystemOptions &FSOpts = FileMgr.getFileSystemOpts();1692 AddString(FSOpts.WorkingDir, Record);1693 Stream.EmitRecord(FILE_SYSTEM_OPTIONS, Record);1694 1695 // Header search options.1696 Record.clear();1697 const HeaderSearchOptions &HSOpts =1698 PP.getHeaderSearchInfo().getHeaderSearchOpts();1699 1700 SmallString<256> HSOpts_ModuleCachePath;1701 normalizeModuleCachePath(PP.getFileManager(), HSOpts.ModuleCachePath,1702 HSOpts_ModuleCachePath);1703 1704 AddString(HSOpts.Sysroot, Record);1705 AddString(HSOpts.ResourceDir, Record);1706 AddString(HSOpts_ModuleCachePath, Record);1707 AddString(HSOpts.ModuleUserBuildPath, Record);1708 Record.push_back(HSOpts.DisableModuleHash);1709 Record.push_back(HSOpts.ImplicitModuleMaps);1710 Record.push_back(HSOpts.ModuleMapFileHomeIsCwd);1711 Record.push_back(HSOpts.EnablePrebuiltImplicitModules);1712 Record.push_back(HSOpts.UseBuiltinIncludes);1713 Record.push_back(HSOpts.UseStandardSystemIncludes);1714 Record.push_back(HSOpts.UseStandardCXXIncludes);1715 Record.push_back(HSOpts.UseLibcxx);1716 // Write out the specific module cache path that contains the module files.1717 AddString(PP.getHeaderSearchInfo().getModuleCachePath(), Record);1718 Stream.EmitRecord(HEADER_SEARCH_OPTIONS, Record);1719 1720 // Preprocessor options.1721 Record.clear();1722 const PreprocessorOptions &PPOpts = PP.getPreprocessorOpts();1723 1724 // If we're building an implicit module with a context hash, the importer is1725 // guaranteed to have the same macros defined on the command line. Skip1726 // writing them.1727 bool SkipMacros = BuildingImplicitModule && !HSOpts.DisableModuleHash;1728 bool WriteMacros = !SkipMacros;1729 Record.push_back(WriteMacros);1730 if (WriteMacros) {1731 // Macro definitions.1732 Record.push_back(PPOpts.Macros.size());1733 for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) {1734 AddString(PPOpts.Macros[I].first, Record);1735 Record.push_back(PPOpts.Macros[I].second);1736 }1737 }1738 1739 // Includes1740 Record.push_back(PPOpts.Includes.size());1741 for (unsigned I = 0, N = PPOpts.Includes.size(); I != N; ++I)1742 AddString(PPOpts.Includes[I], Record);1743 1744 // Macro includes1745 Record.push_back(PPOpts.MacroIncludes.size());1746 for (unsigned I = 0, N = PPOpts.MacroIncludes.size(); I != N; ++I)1747 AddString(PPOpts.MacroIncludes[I], Record);1748 1749 Record.push_back(PPOpts.UsePredefines);1750 // Detailed record is important since it is used for the module cache hash.1751 Record.push_back(PPOpts.DetailedRecord);1752 AddString(PPOpts.ImplicitPCHInclude, Record);1753 Record.push_back(static_cast<unsigned>(PPOpts.ObjCXXARCStandardLibrary));1754 Stream.EmitRecord(PREPROCESSOR_OPTIONS, Record);1755 1756 // Leave the options block.1757 Stream.ExitBlock();1758 1759 // Original file name and file ID1760 if (auto MainFile =1761 SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID())) {1762 auto FileAbbrev = std::make_shared<BitCodeAbbrev>();1763 FileAbbrev->Add(BitCodeAbbrevOp(ORIGINAL_FILE));1764 FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File ID1765 FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name1766 unsigned FileAbbrevCode = Stream.EmitAbbrev(std::move(FileAbbrev));1767 1768 Record.clear();1769 Record.push_back(ORIGINAL_FILE);1770 AddFileID(SourceMgr.getMainFileID(), Record);1771 EmitRecordWithPath(FileAbbrevCode, Record, MainFile->getName());1772 }1773 1774 Record.clear();1775 AddFileID(SourceMgr.getMainFileID(), Record);1776 Stream.EmitRecord(ORIGINAL_FILE_ID, Record);1777 1778 WriteInputFiles(SourceMgr);1779 Stream.ExitBlock();1780}1781 1782namespace {1783 1784/// An input file.1785struct InputFileEntry {1786 FileEntryRef File;1787 bool IsSystemFile;1788 bool IsTransient;1789 bool BufferOverridden;1790 bool IsTopLevel;1791 bool IsModuleMap;1792 uint32_t ContentHash[2];1793 1794 InputFileEntry(FileEntryRef File) : File(File) {}1795 1796 void trySetContentHash(1797 Preprocessor &PP,1798 llvm::function_ref<std::optional<llvm::MemoryBufferRef>()> GetMemBuff) {1799 ContentHash[0] = 0;1800 ContentHash[1] = 0;1801 1802 if (!PP.getHeaderSearchInfo()1803 .getHeaderSearchOpts()1804 .ValidateASTInputFilesContent)1805 return;1806 1807 auto MemBuff = GetMemBuff();1808 if (!MemBuff) {1809 PP.Diag(SourceLocation(), diag::err_module_unable_to_hash_content)1810 << File.getName();1811 return;1812 }1813 1814 uint64_t Hash = xxh3_64bits(MemBuff->getBuffer());1815 ContentHash[0] = uint32_t(Hash);1816 ContentHash[1] = uint32_t(Hash >> 32);1817 }1818};1819 1820} // namespace1821 1822SourceLocation ASTWriter::getAffectingIncludeLoc(const SourceManager &SourceMgr,1823 const SrcMgr::FileInfo &File) {1824 SourceLocation IncludeLoc = File.getIncludeLoc();1825 if (IncludeLoc.isValid()) {1826 FileID IncludeFID = SourceMgr.getFileID(IncludeLoc);1827 assert(IncludeFID.isValid() && "IncludeLoc in invalid file");1828 if (!IsSLocAffecting[IncludeFID.ID])1829 IncludeLoc = SourceLocation();1830 }1831 return IncludeLoc;1832}1833 1834void ASTWriter::WriteInputFiles(SourceManager &SourceMgr) {1835 using namespace llvm;1836 1837 Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4);1838 1839 // Create input-file abbreviation.1840 auto IFAbbrev = std::make_shared<BitCodeAbbrev>();1841 IFAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE));1842 IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID1843 IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size1844 IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time1845 IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Overridden1846 IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Transient1847 IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Top-level1848 IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Module map1849 IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // Name as req. len1850 IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name as req. + name1851 unsigned IFAbbrevCode = Stream.EmitAbbrev(std::move(IFAbbrev));1852 1853 // Create input file hash abbreviation.1854 auto IFHAbbrev = std::make_shared<BitCodeAbbrev>();1855 IFHAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE_HASH));1856 IFHAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));1857 IFHAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));1858 unsigned IFHAbbrevCode = Stream.EmitAbbrev(std::move(IFHAbbrev));1859 1860 uint64_t InputFilesOffsetBase = Stream.GetCurrentBitNo();1861 1862 // Get all ContentCache objects for files.1863 std::vector<InputFileEntry> UserFiles;1864 std::vector<InputFileEntry> SystemFiles;1865 for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) {1866 // Get this source location entry.1867 const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I);1868 assert(&SourceMgr.getSLocEntry(FileID::get(I)) == SLoc);1869 1870 // We only care about file entries that were not overridden.1871 if (!SLoc->isFile())1872 continue;1873 const SrcMgr::FileInfo &File = SLoc->getFile();1874 const SrcMgr::ContentCache *Cache = &File.getContentCache();1875 if (!Cache->OrigEntry)1876 continue;1877 1878 // Do not emit input files that do not affect current module.1879 if (!IsSLocFileEntryAffecting[I])1880 continue;1881 1882 InputFileEntry Entry(*Cache->OrigEntry);1883 Entry.IsSystemFile = isSystem(File.getFileCharacteristic());1884 Entry.IsTransient = Cache->IsTransient;1885 Entry.BufferOverridden = Cache->BufferOverridden;1886 1887 FileID IncludeFileID = SourceMgr.getFileID(File.getIncludeLoc());1888 Entry.IsTopLevel = IncludeFileID.isInvalid() || IncludeFileID.ID < 0 ||1889 !IsSLocFileEntryAffecting[IncludeFileID.ID];1890 Entry.IsModuleMap = isModuleMap(File.getFileCharacteristic());1891 1892 Entry.trySetContentHash(*PP, [&] { return Cache->getBufferIfLoaded(); });1893 1894 if (Entry.IsSystemFile)1895 SystemFiles.push_back(Entry);1896 else1897 UserFiles.push_back(Entry);1898 }1899 1900 // FIXME: Make providing input files not in the SourceManager more flexible.1901 // The SDKSettings.json file is necessary for correct evaluation of1902 // availability annotations.1903 StringRef Sysroot = PP->getHeaderSearchInfo().getHeaderSearchOpts().Sysroot;1904 if (!Sysroot.empty()) {1905 SmallString<128> SDKSettingsJSON = Sysroot;1906 llvm::sys::path::append(SDKSettingsJSON, "SDKSettings.json");1907 FileManager &FM = PP->getFileManager();1908 if (auto FE = FM.getOptionalFileRef(SDKSettingsJSON)) {1909 InputFileEntry Entry(*FE);1910 Entry.IsSystemFile = true;1911 Entry.IsTransient = false;1912 Entry.BufferOverridden = false;1913 Entry.IsTopLevel = true;1914 Entry.IsModuleMap = false;1915 std::unique_ptr<MemoryBuffer> MB;1916 Entry.trySetContentHash(*PP, [&]() -> std::optional<MemoryBufferRef> {1917 if (auto MBOrErr = FM.getBufferForFile(Entry.File)) {1918 MB = std::move(*MBOrErr);1919 return MB->getMemBufferRef();1920 }1921 return std::nullopt;1922 });1923 SystemFiles.push_back(Entry);1924 }1925 }1926 1927 // User files go at the front, system files at the back.1928 auto SortedFiles = llvm::concat<InputFileEntry>(std::move(UserFiles),1929 std::move(SystemFiles));1930 1931 unsigned UserFilesNum = 0;1932 // Write out all of the input files.1933 std::vector<uint64_t> InputFileOffsets;1934 for (const auto &Entry : SortedFiles) {1935 uint32_t &InputFileID = InputFileIDs[Entry.File];1936 if (InputFileID != 0)1937 continue; // already recorded this file.1938 1939 // Record this entry's offset.1940 InputFileOffsets.push_back(Stream.GetCurrentBitNo() - InputFilesOffsetBase);1941 1942 InputFileID = InputFileOffsets.size();1943 1944 if (!Entry.IsSystemFile)1945 ++UserFilesNum;1946 1947 // Emit size/modification time for this file.1948 // And whether this file was overridden.1949 {1950 SmallString<128> NameAsRequested = Entry.File.getNameAsRequested();1951 SmallString<128> Name = Entry.File.getName();1952 1953 PreparePathForOutput(NameAsRequested);1954 PreparePathForOutput(Name);1955 1956 if (Name == NameAsRequested)1957 Name.clear();1958 1959 RecordData::value_type Record[] = {1960 INPUT_FILE,1961 InputFileOffsets.size(),1962 (uint64_t)Entry.File.getSize(),1963 (uint64_t)getTimestampForOutput(Entry.File),1964 Entry.BufferOverridden,1965 Entry.IsTransient,1966 Entry.IsTopLevel,1967 Entry.IsModuleMap,1968 NameAsRequested.size()};1969 1970 Stream.EmitRecordWithBlob(IFAbbrevCode, Record,1971 (NameAsRequested + Name).str());1972 }1973 1974 // Emit content hash for this file.1975 {1976 RecordData::value_type Record[] = {INPUT_FILE_HASH, Entry.ContentHash[0],1977 Entry.ContentHash[1]};1978 Stream.EmitRecordWithAbbrev(IFHAbbrevCode, Record);1979 }1980 }1981 1982 Stream.ExitBlock();1983 1984 // Create input file offsets abbreviation.1985 auto OffsetsAbbrev = std::make_shared<BitCodeAbbrev>();1986 OffsetsAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE_OFFSETS));1987 OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # input files1988 OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # non-system1989 // input files1990 OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Array1991 unsigned OffsetsAbbrevCode = Stream.EmitAbbrev(std::move(OffsetsAbbrev));1992 1993 // Write input file offsets.1994 RecordData::value_type Record[] = {INPUT_FILE_OFFSETS,1995 InputFileOffsets.size(), UserFilesNum};1996 Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, bytes(InputFileOffsets));1997}1998 1999//===----------------------------------------------------------------------===//2000// Source Manager Serialization2001//===----------------------------------------------------------------------===//2002 2003/// Create an abbreviation for the SLocEntry that refers to a2004/// file.2005static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {2006 using namespace llvm;2007 2008 auto Abbrev = std::make_shared<BitCodeAbbrev>();2009 Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_FILE_ENTRY));2010 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset2011 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location2012 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic2013 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives2014 // FileEntry fields.2015 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Input File ID2016 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumCreatedFIDs2017 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 24)); // FirstDeclIndex2018 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumDecls2019 return Stream.EmitAbbrev(std::move(Abbrev));2020}2021 2022/// Create an abbreviation for the SLocEntry that refers to a2023/// buffer.2024static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {2025 using namespace llvm;2026 2027 auto Abbrev = std::make_shared<BitCodeAbbrev>();2028 Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_ENTRY));2029 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset2030 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location2031 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic2032 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives2033 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob2034 return Stream.EmitAbbrev(std::move(Abbrev));2035}2036 2037/// Create an abbreviation for the SLocEntry that refers to a2038/// buffer's blob.2039static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream,2040 bool Compressed) {2041 using namespace llvm;2042 2043 auto Abbrev = std::make_shared<BitCodeAbbrev>();2044 Abbrev->Add(BitCodeAbbrevOp(Compressed ? SM_SLOC_BUFFER_BLOB_COMPRESSED2045 : SM_SLOC_BUFFER_BLOB));2046 if (Compressed)2047 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Uncompressed size2048 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob2049 return Stream.EmitAbbrev(std::move(Abbrev));2050}2051 2052/// Create an abbreviation for the SLocEntry that refers to a macro2053/// expansion.2054static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) {2055 using namespace llvm;2056 2057 auto Abbrev = std::make_shared<BitCodeAbbrev>();2058 Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_EXPANSION_ENTRY));2059 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset2060 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location2061 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Start location2062 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // End location2063 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is token range2064 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length2065 return Stream.EmitAbbrev(std::move(Abbrev));2066}2067 2068/// Emit key length and data length as ULEB-encoded data, and return them as a2069/// pair.2070static std::pair<unsigned, unsigned>2071emitULEBKeyDataLength(unsigned KeyLen, unsigned DataLen, raw_ostream &Out) {2072 llvm::encodeULEB128(KeyLen, Out);2073 llvm::encodeULEB128(DataLen, Out);2074 return std::make_pair(KeyLen, DataLen);2075}2076 2077namespace {2078 2079 // Trait used for the on-disk hash table of header search information.2080 class HeaderFileInfoTrait {2081 ASTWriter &Writer;2082 2083 public:2084 HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {}2085 2086 struct key_type {2087 StringRef Filename;2088 off_t Size;2089 time_t ModTime;2090 };2091 using key_type_ref = const key_type &;2092 2093 using UnresolvedModule =2094 llvm::PointerIntPair<Module *, 2, ModuleMap::ModuleHeaderRole>;2095 2096 struct data_type {2097 data_type(const HeaderFileInfo &HFI, bool AlreadyIncluded,2098 ArrayRef<ModuleMap::KnownHeader> KnownHeaders,2099 UnresolvedModule Unresolved)2100 : HFI(HFI), AlreadyIncluded(AlreadyIncluded),2101 KnownHeaders(KnownHeaders), Unresolved(Unresolved) {}2102 2103 HeaderFileInfo HFI;2104 bool AlreadyIncluded;2105 SmallVector<ModuleMap::KnownHeader, 1> KnownHeaders;2106 UnresolvedModule Unresolved;2107 };2108 using data_type_ref = const data_type &;2109 2110 using hash_value_type = unsigned;2111 using offset_type = unsigned;2112 2113 hash_value_type ComputeHash(key_type_ref key) {2114 // The hash is based only on size/time of the file, so that the reader can2115 // match even when symlinking or excess path elements ("foo/../", "../")2116 // change the form of the name. However, complete path is still the key.2117 uint8_t buf[sizeof(key.Size) + sizeof(key.ModTime)];2118 memcpy(buf, &key.Size, sizeof(key.Size));2119 memcpy(buf + sizeof(key.Size), &key.ModTime, sizeof(key.ModTime));2120 return llvm::xxh3_64bits(buf);2121 }2122 2123 std::pair<unsigned, unsigned>2124 EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {2125 unsigned KeyLen = key.Filename.size() + 1 + 8 + 8;2126 unsigned DataLen = 1 + sizeof(IdentifierID);2127 for (auto ModInfo : Data.KnownHeaders)2128 if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule()))2129 DataLen += 4;2130 if (Data.Unresolved.getPointer())2131 DataLen += 4;2132 return emitULEBKeyDataLength(KeyLen, DataLen, Out);2133 }2134 2135 void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) {2136 using namespace llvm::support;2137 2138 endian::Writer LE(Out, llvm::endianness::little);2139 LE.write<uint64_t>(key.Size);2140 KeyLen -= 8;2141 LE.write<uint64_t>(key.ModTime);2142 KeyLen -= 8;2143 Out.write(key.Filename.data(), KeyLen);2144 }2145 2146 void EmitData(raw_ostream &Out, key_type_ref key,2147 data_type_ref Data, unsigned DataLen) {2148 using namespace llvm::support;2149 2150 endian::Writer LE(Out, llvm::endianness::little);2151 uint64_t Start = Out.tell(); (void)Start;2152 2153 unsigned char Flags = (Data.AlreadyIncluded << 6)2154 | (Data.HFI.isImport << 5)2155 | (Writer.isWritingStdCXXNamedModules() ? 0 :2156 Data.HFI.isPragmaOnce << 4)2157 | (Data.HFI.DirInfo << 1);2158 LE.write<uint8_t>(Flags);2159 2160 if (Data.HFI.LazyControllingMacro.isID())2161 LE.write<IdentifierID>(Data.HFI.LazyControllingMacro.getID());2162 else2163 LE.write<IdentifierID>(2164 Writer.getIdentifierRef(Data.HFI.LazyControllingMacro.getPtr()));2165 2166 auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) {2167 if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) {2168 uint32_t Value = (ModID << 3) | (unsigned)Role;2169 assert((Value >> 3) == ModID && "overflow in header module info");2170 LE.write<uint32_t>(Value);2171 }2172 };2173 2174 for (auto ModInfo : Data.KnownHeaders)2175 EmitModule(ModInfo.getModule(), ModInfo.getRole());2176 if (Data.Unresolved.getPointer())2177 EmitModule(Data.Unresolved.getPointer(), Data.Unresolved.getInt());2178 2179 assert(Out.tell() - Start == DataLen && "Wrong data length");2180 }2181 };2182 2183} // namespace2184 2185/// Write the header search block for the list of files that2186///2187/// \param HS The header search structure to save.2188void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {2189 HeaderFileInfoTrait GeneratorTrait(*this);2190 llvm::OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator;2191 SmallVector<const char *, 4> SavedStrings;2192 unsigned NumHeaderSearchEntries = 0;2193 2194 // Find all unresolved headers for the current module. We generally will2195 // have resolved them before we get here, but not necessarily: we might be2196 // compiling a preprocessed module, where there is no requirement for the2197 // original files to exist any more.2198 const HeaderFileInfo Empty; // So we can take a reference.2199 if (WritingModule) {2200 llvm::SmallVector<Module *, 16> Worklist(1, WritingModule);2201 while (!Worklist.empty()) {2202 Module *M = Worklist.pop_back_val();2203 // We don't care about headers in unimportable submodules.2204 if (M->isUnimportable())2205 continue;2206 2207 // Map to disk files where possible, to pick up any missing stat2208 // information. This also means we don't need to check the unresolved2209 // headers list when emitting resolved headers in the first loop below.2210 // FIXME: It'd be preferable to avoid doing this if we were given2211 // sufficient stat information in the module map.2212 HS.getModuleMap().resolveHeaderDirectives(M, /*File=*/std::nullopt);2213 2214 // If the file didn't exist, we can still create a module if we were given2215 // enough information in the module map.2216 for (const auto &U : M->MissingHeaders) {2217 // Check that we were given enough information to build a module2218 // without this file existing on disk.2219 if (!U.Size || (!U.ModTime && IncludeTimestamps)) {2220 PP->Diag(U.FileNameLoc, diag::err_module_no_size_mtime_for_header)2221 << WritingModule->getFullModuleName() << U.Size.has_value()2222 << U.FileName;2223 continue;2224 }2225 2226 // Form the effective relative pathname for the file.2227 SmallString<128> Filename(M->Directory->getName());2228 llvm::sys::path::append(Filename, U.FileName);2229 PreparePathForOutput(Filename);2230 2231 StringRef FilenameDup = strdup(Filename.c_str());2232 SavedStrings.push_back(FilenameDup.data());2233 2234 HeaderFileInfoTrait::key_type Key = {2235 FilenameDup, *U.Size, IncludeTimestamps ? *U.ModTime : 0};2236 HeaderFileInfoTrait::data_type Data = {2237 Empty, false, {}, {M, ModuleMap::headerKindToRole(U.Kind)}};2238 // FIXME: Deal with cases where there are multiple unresolved header2239 // directives in different submodules for the same header.2240 Generator.insert(Key, Data, GeneratorTrait);2241 ++NumHeaderSearchEntries;2242 }2243 auto SubmodulesRange = M->submodules();2244 Worklist.append(SubmodulesRange.begin(), SubmodulesRange.end());2245 }2246 }2247 2248 SmallVector<OptionalFileEntryRef, 16> FilesByUID;2249 HS.getFileMgr().GetUniqueIDMapping(FilesByUID);2250 2251 if (FilesByUID.size() > HS.header_file_size())2252 FilesByUID.resize(HS.header_file_size());2253 2254 for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) {2255 OptionalFileEntryRef File = FilesByUID[UID];2256 if (!File)2257 continue;2258 2259 const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File);2260 if (!HFI)2261 continue; // We have no information on this being a header file.2262 if (!HFI->isCompilingModuleHeader && HFI->isModuleHeader)2263 continue; // Header file info is tracked by the owning module file.2264 if (!HFI->isCompilingModuleHeader && !HFI->IsLocallyIncluded)2265 continue; // Header file info is tracked by the including module file.2266 2267 // Massage the file path into an appropriate form.2268 StringRef Filename = File->getName();2269 SmallString<128> FilenameTmp(Filename);2270 if (PreparePathForOutput(FilenameTmp)) {2271 // If we performed any translation on the file name at all, we need to2272 // save this string, since the generator will refer to it later.2273 Filename = StringRef(strdup(FilenameTmp.c_str()));2274 SavedStrings.push_back(Filename.data());2275 }2276 2277 bool Included = HFI->IsLocallyIncluded || PP->alreadyIncluded(*File);2278 2279 HeaderFileInfoTrait::key_type Key = {2280 Filename, File->getSize(), getTimestampForOutput(*File)2281 };2282 HeaderFileInfoTrait::data_type Data = {2283 *HFI, Included, HS.getModuleMap().findResolvedModulesForHeader(*File), {}2284 };2285 Generator.insert(Key, Data, GeneratorTrait);2286 ++NumHeaderSearchEntries;2287 }2288 2289 // Create the on-disk hash table in a buffer.2290 SmallString<4096> TableData;2291 uint32_t BucketOffset;2292 {2293 using namespace llvm::support;2294 2295 llvm::raw_svector_ostream Out(TableData);2296 // Make sure that no bucket is at offset 02297 endian::write<uint32_t>(Out, 0, llvm::endianness::little);2298 BucketOffset = Generator.Emit(Out, GeneratorTrait);2299 }2300 2301 // Create a blob abbreviation2302 using namespace llvm;2303 2304 auto Abbrev = std::make_shared<BitCodeAbbrev>();2305 Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_TABLE));2306 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));2307 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));2308 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));2309 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));2310 unsigned TableAbbrev = Stream.EmitAbbrev(std::move(Abbrev));2311 2312 // Write the header search table2313 RecordData::value_type Record[] = {HEADER_SEARCH_TABLE, BucketOffset,2314 NumHeaderSearchEntries, TableData.size()};2315 Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData);2316 2317 // Free all of the strings we had to duplicate.2318 for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I)2319 free(const_cast<char *>(SavedStrings[I]));2320}2321 2322static void emitBlob(llvm::BitstreamWriter &Stream, StringRef Blob,2323 unsigned SLocBufferBlobCompressedAbbrv,2324 unsigned SLocBufferBlobAbbrv) {2325 using RecordDataType = ASTWriter::RecordData::value_type;2326 2327 // Compress the buffer if possible. We expect that almost all PCM2328 // consumers will not want its contents.2329 SmallVector<uint8_t, 0> CompressedBuffer;2330 if (llvm::compression::zstd::isAvailable()) {2331 llvm::compression::zstd::compress(2332 llvm::arrayRefFromStringRef(Blob.drop_back(1)), CompressedBuffer, 9);2333 RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED, Blob.size() - 1};2334 Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record,2335 llvm::toStringRef(CompressedBuffer));2336 return;2337 }2338 if (llvm::compression::zlib::isAvailable()) {2339 llvm::compression::zlib::compress(2340 llvm::arrayRefFromStringRef(Blob.drop_back(1)), CompressedBuffer);2341 RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED, Blob.size() - 1};2342 Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record,2343 llvm::toStringRef(CompressedBuffer));2344 return;2345 }2346 2347 RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB};2348 Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, Blob);2349}2350 2351/// Writes the block containing the serialized form of the2352/// source manager.2353///2354/// TODO: We should probably use an on-disk hash table (stored in a2355/// blob), indexed based on the file name, so that we only create2356/// entries for files that we actually need. In the common case (no2357/// errors), we probably won't have to create file entries for any of2358/// the files in the AST.2359void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) {2360 RecordData Record;2361 2362 // Enter the source manager block.2363 Stream.EnterSubblock(SOURCE_MANAGER_BLOCK_ID, 4);2364 const uint64_t SourceManagerBlockOffset = Stream.GetCurrentBitNo();2365 2366 // Abbreviations for the various kinds of source-location entries.2367 unsigned SLocFileAbbrv = CreateSLocFileAbbrev(Stream);2368 unsigned SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream);2369 unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream, false);2370 unsigned SLocBufferBlobCompressedAbbrv =2371 CreateSLocBufferBlobAbbrev(Stream, true);2372 unsigned SLocExpansionAbbrv = CreateSLocExpansionAbbrev(Stream);2373 2374 // Write out the source location entry table. We skip the first2375 // entry, which is always the same dummy entry.2376 std::vector<uint32_t> SLocEntryOffsets;2377 uint64_t SLocEntryOffsetsBase = Stream.GetCurrentBitNo();2378 SLocEntryOffsets.reserve(SourceMgr.local_sloc_entry_size() - 1);2379 for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size();2380 I != N; ++I) {2381 // Get this source location entry.2382 const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I);2383 FileID FID = FileID::get(I);2384 assert(&SourceMgr.getSLocEntry(FID) == SLoc);2385 2386 // Record the offset of this source-location entry.2387 uint64_t Offset = Stream.GetCurrentBitNo() - SLocEntryOffsetsBase;2388 assert((Offset >> 32) == 0 && "SLocEntry offset too large");2389 2390 // Figure out which record code to use.2391 unsigned Code;2392 if (SLoc->isFile()) {2393 const SrcMgr::ContentCache *Cache = &SLoc->getFile().getContentCache();2394 if (Cache->OrigEntry) {2395 Code = SM_SLOC_FILE_ENTRY;2396 } else2397 Code = SM_SLOC_BUFFER_ENTRY;2398 } else2399 Code = SM_SLOC_EXPANSION_ENTRY;2400 Record.clear();2401 Record.push_back(Code);2402 2403 if (SLoc->isFile()) {2404 const SrcMgr::FileInfo &File = SLoc->getFile();2405 const SrcMgr::ContentCache *Content = &File.getContentCache();2406 // Do not emit files that were not listed as inputs.2407 if (!IsSLocAffecting[I])2408 continue;2409 SLocEntryOffsets.push_back(Offset);2410 // Starting offset of this entry within this module, so skip the dummy.2411 Record.push_back(getAdjustedOffset(SLoc->getOffset()) - 2);2412 AddSourceLocation(getAffectingIncludeLoc(SourceMgr, File), Record);2413 Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding2414 Record.push_back(File.hasLineDirectives());2415 2416 bool EmitBlob = false;2417 if (Content->OrigEntry) {2418 assert(Content->OrigEntry == Content->ContentsEntry &&2419 "Writing to AST an overridden file is not supported");2420 2421 // The source location entry is a file. Emit input file ID.2422 assert(InputFileIDs[*Content->OrigEntry] != 0 && "Missed file entry");2423 Record.push_back(InputFileIDs[*Content->OrigEntry]);2424 2425 Record.push_back(getAdjustedNumCreatedFIDs(FID));2426 2427 FileDeclIDsTy::iterator FDI = FileDeclIDs.find(FID);2428 if (FDI != FileDeclIDs.end()) {2429 Record.push_back(FDI->second->FirstDeclIndex);2430 Record.push_back(FDI->second->DeclIDs.size());2431 } else {2432 Record.push_back(0);2433 Record.push_back(0);2434 }2435 2436 Stream.EmitRecordWithAbbrev(SLocFileAbbrv, Record);2437 2438 if (Content->BufferOverridden || Content->IsTransient)2439 EmitBlob = true;2440 } else {2441 // The source location entry is a buffer. The blob associated2442 // with this entry contains the contents of the buffer.2443 2444 // We add one to the size so that we capture the trailing NULL2445 // that is required by llvm::MemoryBuffer::getMemBuffer (on2446 // the reader side).2447 std::optional<llvm::MemoryBufferRef> Buffer = Content->getBufferOrNone(2448 SourceMgr.getDiagnostics(), SourceMgr.getFileManager());2449 StringRef Name = Buffer ? Buffer->getBufferIdentifier() : "";2450 Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,2451 StringRef(Name.data(), Name.size() + 1));2452 EmitBlob = true;2453 }2454 2455 if (EmitBlob) {2456 // Include the implicit terminating null character in the on-disk buffer2457 // if we're writing it uncompressed.2458 std::optional<llvm::MemoryBufferRef> Buffer = Content->getBufferOrNone(2459 SourceMgr.getDiagnostics(), SourceMgr.getFileManager());2460 if (!Buffer)2461 Buffer = llvm::MemoryBufferRef("<<<INVALID BUFFER>>>", "");2462 StringRef Blob(Buffer->getBufferStart(), Buffer->getBufferSize() + 1);2463 emitBlob(Stream, Blob, SLocBufferBlobCompressedAbbrv,2464 SLocBufferBlobAbbrv);2465 }2466 } else {2467 // The source location entry is a macro expansion.2468 const SrcMgr::ExpansionInfo &Expansion = SLoc->getExpansion();2469 SLocEntryOffsets.push_back(Offset);2470 // Starting offset of this entry within this module, so skip the dummy.2471 Record.push_back(getAdjustedOffset(SLoc->getOffset()) - 2);2472 AddSourceLocation(Expansion.getSpellingLoc(), Record);2473 AddSourceLocation(Expansion.getExpansionLocStart(), Record);2474 AddSourceLocation(Expansion.isMacroArgExpansion()2475 ? SourceLocation()2476 : Expansion.getExpansionLocEnd(),2477 Record);2478 Record.push_back(Expansion.isExpansionTokenRange());2479 2480 // Compute the token length for this macro expansion.2481 SourceLocation::UIntTy NextOffset = SourceMgr.getNextLocalOffset();2482 if (I + 1 != N)2483 NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset();2484 Record.push_back(getAdjustedOffset(NextOffset - SLoc->getOffset()) - 1);2485 Stream.EmitRecordWithAbbrev(SLocExpansionAbbrv, Record);2486 }2487 }2488 2489 Stream.ExitBlock();2490 2491 if (SLocEntryOffsets.empty())2492 return;2493 2494 // Write the source-location offsets table into the AST block. This2495 // table is used for lazily loading source-location information.2496 using namespace llvm;2497 2498 auto Abbrev = std::make_shared<BitCodeAbbrev>();2499 Abbrev->Add(BitCodeAbbrevOp(SOURCE_LOCATION_OFFSETS));2500 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs2501 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // total size2502 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // base offset2503 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets2504 unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(std::move(Abbrev));2505 {2506 RecordData::value_type Record[] = {2507 SOURCE_LOCATION_OFFSETS, SLocEntryOffsets.size(),2508 getAdjustedOffset(SourceMgr.getNextLocalOffset()) - 1 /* skip dummy */,2509 SLocEntryOffsetsBase - SourceManagerBlockOffset};2510 Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record,2511 bytes(SLocEntryOffsets));2512 }2513 2514 // Write the line table. It depends on remapping working, so it must come2515 // after the source location offsets.2516 if (SourceMgr.hasLineTable()) {2517 LineTableInfo &LineTable = SourceMgr.getLineTable();2518 2519 Record.clear();2520 2521 // Emit the needed file names.2522 llvm::DenseMap<int, int> FilenameMap;2523 FilenameMap[-1] = -1; // For unspecified filenames.2524 for (const auto &L : LineTable) {2525 if (L.first.ID < 0)2526 continue;2527 for (auto &LE : L.second) {2528 if (FilenameMap.insert(std::make_pair(LE.FilenameID,2529 FilenameMap.size() - 1)).second)2530 AddPath(LineTable.getFilename(LE.FilenameID), Record);2531 }2532 }2533 Record.push_back(0);2534 2535 // Emit the line entries2536 for (const auto &L : LineTable) {2537 // Only emit entries for local files.2538 if (L.first.ID < 0)2539 continue;2540 2541 AddFileID(L.first, Record);2542 2543 // Emit the line entries2544 Record.push_back(L.second.size());2545 for (const auto &LE : L.second) {2546 Record.push_back(LE.FileOffset);2547 Record.push_back(LE.LineNo);2548 Record.push_back(FilenameMap[LE.FilenameID]);2549 Record.push_back((unsigned)LE.FileKind);2550 Record.push_back(LE.IncludeOffset);2551 }2552 }2553 2554 Stream.EmitRecord(SOURCE_MANAGER_LINE_TABLE, Record);2555 }2556}2557 2558//===----------------------------------------------------------------------===//2559// Preprocessor Serialization2560//===----------------------------------------------------------------------===//2561 2562static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule,2563 const Preprocessor &PP) {2564 if (MacroInfo *MI = MD->getMacroInfo())2565 if (MI->isBuiltinMacro())2566 return true;2567 2568 if (IsModule) {2569 SourceLocation Loc = MD->getLocation();2570 if (Loc.isInvalid())2571 return true;2572 if (PP.getSourceManager().getFileID(Loc) == PP.getPredefinesFileID())2573 return true;2574 }2575 2576 return false;2577}2578 2579/// Writes the block containing the serialized form of the2580/// preprocessor.2581void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {2582 uint64_t MacroOffsetsBase = Stream.GetCurrentBitNo();2583 2584 PreprocessingRecord *PPRec = PP.getPreprocessingRecord();2585 if (PPRec)2586 WritePreprocessorDetail(*PPRec, MacroOffsetsBase);2587 2588 RecordData Record;2589 RecordData ModuleMacroRecord;2590 2591 // If the preprocessor __COUNTER__ value has been bumped, remember it.2592 if (PP.getCounterValue() != 0) {2593 RecordData::value_type Record[] = {PP.getCounterValue()};2594 Stream.EmitRecord(PP_COUNTER_VALUE, Record);2595 }2596 2597 // If we have a recorded #pragma assume_nonnull, remember it so it can be2598 // replayed when the preamble terminates into the main file.2599 SourceLocation AssumeNonNullLoc =2600 PP.getPreambleRecordedPragmaAssumeNonNullLoc();2601 if (AssumeNonNullLoc.isValid()) {2602 assert(PP.isRecordingPreamble());2603 AddSourceLocation(AssumeNonNullLoc, Record);2604 Stream.EmitRecord(PP_ASSUME_NONNULL_LOC, Record);2605 Record.clear();2606 }2607 2608 if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) {2609 assert(!IsModule);2610 auto SkipInfo = PP.getPreambleSkipInfo();2611 if (SkipInfo) {2612 Record.push_back(true);2613 AddSourceLocation(SkipInfo->HashTokenLoc, Record);2614 AddSourceLocation(SkipInfo->IfTokenLoc, Record);2615 Record.push_back(SkipInfo->FoundNonSkipPortion);2616 Record.push_back(SkipInfo->FoundElse);2617 AddSourceLocation(SkipInfo->ElseLoc, Record);2618 } else {2619 Record.push_back(false);2620 }2621 for (const auto &Cond : PP.getPreambleConditionalStack()) {2622 AddSourceLocation(Cond.IfLoc, Record);2623 Record.push_back(Cond.WasSkipping);2624 Record.push_back(Cond.FoundNonSkip);2625 Record.push_back(Cond.FoundElse);2626 }2627 Stream.EmitRecord(PP_CONDITIONAL_STACK, Record);2628 Record.clear();2629 }2630 2631 // Write the safe buffer opt-out region map in PP2632 for (SourceLocation &S : PP.serializeSafeBufferOptOutMap())2633 AddSourceLocation(S, Record);2634 Stream.EmitRecord(PP_UNSAFE_BUFFER_USAGE, Record);2635 Record.clear();2636 2637 // Enter the preprocessor block.2638 Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3);2639 2640 // If the AST file contains __DATE__ or __TIME__ emit a warning about this.2641 // FIXME: Include a location for the use, and say which one was used.2642 if (PP.SawDateOrTime())2643 PP.Diag(SourceLocation(), diag::warn_module_uses_date_time) << IsModule;2644 2645 // Loop over all the macro directives that are live at the end of the file,2646 // emitting each to the PP section.2647 2648 // Construct the list of identifiers with macro directives that need to be2649 // serialized.2650 SmallVector<const IdentifierInfo *, 128> MacroIdentifiers;2651 // It is meaningless to emit macros for named modules. It only wastes times2652 // and spaces.2653 if (!isWritingStdCXXNamedModules())2654 for (auto &Id : PP.getIdentifierTable())2655 if (Id.second->hadMacroDefinition() &&2656 (!Id.second->isFromAST() ||2657 Id.second->hasChangedSinceDeserialization()))2658 MacroIdentifiers.push_back(Id.second);2659 // Sort the set of macro definitions that need to be serialized by the2660 // name of the macro, to provide a stable ordering.2661 llvm::sort(MacroIdentifiers, llvm::deref<std::less<>>());2662 2663 // Emit the macro directives as a list and associate the offset with the2664 // identifier they belong to.2665 for (const IdentifierInfo *Name : MacroIdentifiers) {2666 MacroDirective *MD = PP.getLocalMacroDirectiveHistory(Name);2667 uint64_t StartOffset = Stream.GetCurrentBitNo() - MacroOffsetsBase;2668 assert((StartOffset >> 32) == 0 && "Macro identifiers offset too large");2669 2670 // Write out any exported module macros.2671 bool EmittedModuleMacros = false;2672 // C+=20 Header Units are compiled module interfaces, but they preserve2673 // macros that are live (i.e. have a defined value) at the end of the2674 // compilation. So when writing a header unit, we preserve only the final2675 // value of each macro (and discard any that are undefined). Header units2676 // do not have sub-modules (although they might import other header units).2677 // PCH files, conversely, retain the history of each macro's define/undef2678 // and of leaf macros in sub modules.2679 if (IsModule && WritingModule->isHeaderUnit()) {2680 // This is for the main TU when it is a C++20 header unit.2681 // We preserve the final state of defined macros, and we do not emit ones2682 // that are undefined.2683 if (!MD || shouldIgnoreMacro(MD, IsModule, PP) ||2684 MD->getKind() == MacroDirective::MD_Undefine)2685 continue;2686 AddSourceLocation(MD->getLocation(), Record);2687 Record.push_back(MD->getKind());2688 if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) {2689 Record.push_back(getMacroRef(DefMD->getInfo(), Name));2690 } else if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {2691 Record.push_back(VisMD->isPublic());2692 }2693 ModuleMacroRecord.push_back(getSubmoduleID(WritingModule));2694 AddMacroRef(MD->getMacroInfo(), Name, ModuleMacroRecord);2695 Stream.EmitRecord(PP_MODULE_MACRO, ModuleMacroRecord);2696 ModuleMacroRecord.clear();2697 EmittedModuleMacros = true;2698 } else {2699 // Emit the macro directives in reverse source order.2700 for (; MD; MD = MD->getPrevious()) {2701 // Once we hit an ignored macro, we're done: the rest of the chain2702 // will all be ignored macros.2703 if (shouldIgnoreMacro(MD, IsModule, PP))2704 break;2705 AddSourceLocation(MD->getLocation(), Record);2706 Record.push_back(MD->getKind());2707 if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) {2708 Record.push_back(getMacroRef(DefMD->getInfo(), Name));2709 } else if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {2710 Record.push_back(VisMD->isPublic());2711 }2712 }2713 2714 // We write out exported module macros for PCH as well.2715 auto Leafs = PP.getLeafModuleMacros(Name);2716 SmallVector<ModuleMacro *, 8> Worklist(Leafs);2717 llvm::DenseMap<ModuleMacro *, unsigned> Visits;2718 while (!Worklist.empty()) {2719 auto *Macro = Worklist.pop_back_val();2720 2721 // Emit a record indicating this submodule exports this macro.2722 ModuleMacroRecord.push_back(getSubmoduleID(Macro->getOwningModule()));2723 AddMacroRef(Macro->getMacroInfo(), Name, ModuleMacroRecord);2724 for (auto *M : Macro->overrides())2725 ModuleMacroRecord.push_back(getSubmoduleID(M->getOwningModule()));2726 2727 Stream.EmitRecord(PP_MODULE_MACRO, ModuleMacroRecord);2728 ModuleMacroRecord.clear();2729 2730 // Enqueue overridden macros once we've visited all their ancestors.2731 for (auto *M : Macro->overrides())2732 if (++Visits[M] == M->getNumOverridingMacros())2733 Worklist.push_back(M);2734 2735 EmittedModuleMacros = true;2736 }2737 }2738 if (Record.empty() && !EmittedModuleMacros)2739 continue;2740 2741 IdentMacroDirectivesOffsetMap[Name] = StartOffset;2742 Stream.EmitRecord(PP_MACRO_DIRECTIVE_HISTORY, Record);2743 Record.clear();2744 }2745 2746 /// Offsets of each of the macros into the bitstream, indexed by2747 /// the local macro ID2748 ///2749 /// For each identifier that is associated with a macro, this map2750 /// provides the offset into the bitstream where that macro is2751 /// defined.2752 std::vector<uint32_t> MacroOffsets;2753 2754 for (unsigned I = 0, N = MacroInfosToEmit.size(); I != N; ++I) {2755 const IdentifierInfo *Name = MacroInfosToEmit[I].Name;2756 MacroInfo *MI = MacroInfosToEmit[I].MI;2757 MacroID ID = MacroInfosToEmit[I].ID;2758 2759 if (ID < FirstMacroID) {2760 assert(0 && "Loaded MacroInfo entered MacroInfosToEmit ?");2761 continue;2762 }2763 2764 // Record the local offset of this macro.2765 unsigned Index = ID - FirstMacroID;2766 if (Index >= MacroOffsets.size())2767 MacroOffsets.resize(Index + 1);2768 2769 uint64_t Offset = Stream.GetCurrentBitNo() - MacroOffsetsBase;2770 assert((Offset >> 32) == 0 && "Macro offset too large");2771 MacroOffsets[Index] = Offset;2772 2773 AddIdentifierRef(Name, Record);2774 AddSourceLocation(MI->getDefinitionLoc(), Record);2775 AddSourceLocation(MI->getDefinitionEndLoc(), Record);2776 Record.push_back(MI->isUsed());2777 Record.push_back(MI->isUsedForHeaderGuard());2778 Record.push_back(MI->getNumTokens());2779 unsigned Code;2780 if (MI->isObjectLike()) {2781 Code = PP_MACRO_OBJECT_LIKE;2782 } else {2783 Code = PP_MACRO_FUNCTION_LIKE;2784 2785 Record.push_back(MI->isC99Varargs());2786 Record.push_back(MI->isGNUVarargs());2787 Record.push_back(MI->hasCommaPasting());2788 Record.push_back(MI->getNumParams());2789 for (const IdentifierInfo *Param : MI->params())2790 AddIdentifierRef(Param, Record);2791 }2792 2793 // If we have a detailed preprocessing record, record the macro definition2794 // ID that corresponds to this macro.2795 if (PPRec)2796 Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]);2797 2798 Stream.EmitRecord(Code, Record);2799 Record.clear();2800 2801 // Emit the tokens array.2802 for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) {2803 // Note that we know that the preprocessor does not have any annotation2804 // tokens in it because they are created by the parser, and thus can't2805 // be in a macro definition.2806 const Token &Tok = MI->getReplacementToken(TokNo);2807 AddToken(Tok, Record);2808 Stream.EmitRecord(PP_TOKEN, Record);2809 Record.clear();2810 }2811 ++NumMacros;2812 }2813 2814 Stream.ExitBlock();2815 2816 // Write the offsets table for macro IDs.2817 using namespace llvm;2818 2819 auto Abbrev = std::make_shared<BitCodeAbbrev>();2820 Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET));2821 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros2822 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // base offset2823 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));2824 2825 unsigned MacroOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));2826 {2827 RecordData::value_type Record[] = {MACRO_OFFSET, MacroOffsets.size(),2828 MacroOffsetsBase - ASTBlockStartOffset};2829 Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record, bytes(MacroOffsets));2830 }2831}2832 2833void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec,2834 uint64_t MacroOffsetsBase) {2835 if (PPRec.local_begin() == PPRec.local_end())2836 return;2837 2838 SmallVector<PPEntityOffset, 64> PreprocessedEntityOffsets;2839 2840 // Enter the preprocessor block.2841 Stream.EnterSubblock(PREPROCESSOR_DETAIL_BLOCK_ID, 3);2842 2843 // If the preprocessor has a preprocessing record, emit it.2844 unsigned NumPreprocessingRecords = 0;2845 using namespace llvm;2846 2847 // Set up the abbreviation for2848 unsigned InclusionAbbrev = 0;2849 {2850 auto Abbrev = std::make_shared<BitCodeAbbrev>();2851 Abbrev->Add(BitCodeAbbrevOp(PPD_INCLUSION_DIRECTIVE));2852 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length2853 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes2854 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind2855 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // imported module2856 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));2857 InclusionAbbrev = Stream.EmitAbbrev(std::move(Abbrev));2858 }2859 2860 unsigned FirstPreprocessorEntityID = NUM_PREDEF_PP_ENTITY_IDS;2861 unsigned NextPreprocessorEntityID = FirstPreprocessorEntityID;2862 RecordData Record;2863 for (PreprocessingRecord::iterator E = PPRec.local_begin(),2864 EEnd = PPRec.local_end();2865 E != EEnd;2866 (void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) {2867 Record.clear();2868 2869 uint64_t Offset = Stream.GetCurrentBitNo() - MacroOffsetsBase;2870 assert((Offset >> 32) == 0 && "Preprocessed entity offset too large");2871 SourceRange R = getAdjustedRange((*E)->getSourceRange());2872 PreprocessedEntityOffsets.emplace_back(2873 getRawSourceLocationEncoding(R.getBegin()),2874 getRawSourceLocationEncoding(R.getEnd()), Offset);2875 2876 if (auto *MD = dyn_cast<MacroDefinitionRecord>(*E)) {2877 // Record this macro definition's ID.2878 MacroDefinitions[MD] = NextPreprocessorEntityID;2879 2880 AddIdentifierRef(MD->getName(), Record);2881 Stream.EmitRecord(PPD_MACRO_DEFINITION, Record);2882 continue;2883 }2884 2885 if (auto *ME = dyn_cast<MacroExpansion>(*E)) {2886 Record.push_back(ME->isBuiltinMacro());2887 if (ME->isBuiltinMacro())2888 AddIdentifierRef(ME->getName(), Record);2889 else2890 Record.push_back(MacroDefinitions[ME->getDefinition()]);2891 Stream.EmitRecord(PPD_MACRO_EXPANSION, Record);2892 continue;2893 }2894 2895 if (auto *ID = dyn_cast<InclusionDirective>(*E)) {2896 Record.push_back(PPD_INCLUSION_DIRECTIVE);2897 Record.push_back(ID->getFileName().size());2898 Record.push_back(ID->wasInQuotes());2899 Record.push_back(static_cast<unsigned>(ID->getKind()));2900 Record.push_back(ID->importedModule());2901 SmallString<64> Buffer;2902 Buffer += ID->getFileName();2903 // Check that the FileEntry is not null because it was not resolved and2904 // we create a PCH even with compiler errors.2905 if (ID->getFile())2906 Buffer += ID->getFile()->getName();2907 Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer);2908 continue;2909 }2910 2911 llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter");2912 }2913 Stream.ExitBlock();2914 2915 // Write the offsets table for the preprocessing record.2916 if (NumPreprocessingRecords > 0) {2917 assert(PreprocessedEntityOffsets.size() == NumPreprocessingRecords);2918 2919 // Write the offsets table for identifier IDs.2920 using namespace llvm;2921 2922 auto Abbrev = std::make_shared<BitCodeAbbrev>();2923 Abbrev->Add(BitCodeAbbrevOp(PPD_ENTITIES_OFFSETS));2924 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));2925 unsigned PPEOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));2926 2927 RecordData::value_type Record[] = {PPD_ENTITIES_OFFSETS};2928 Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record,2929 bytes(PreprocessedEntityOffsets));2930 }2931 2932 // Write the skipped region table for the preprocessing record.2933 ArrayRef<SourceRange> SkippedRanges = PPRec.getSkippedRanges();2934 if (SkippedRanges.size() > 0) {2935 std::vector<PPSkippedRange> SerializedSkippedRanges;2936 SerializedSkippedRanges.reserve(SkippedRanges.size());2937 for (auto const& Range : SkippedRanges)2938 SerializedSkippedRanges.emplace_back(2939 getRawSourceLocationEncoding(Range.getBegin()),2940 getRawSourceLocationEncoding(Range.getEnd()));2941 2942 using namespace llvm;2943 auto Abbrev = std::make_shared<BitCodeAbbrev>();2944 Abbrev->Add(BitCodeAbbrevOp(PPD_SKIPPED_RANGES));2945 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));2946 unsigned PPESkippedRangeAbbrev = Stream.EmitAbbrev(std::move(Abbrev));2947 2948 Record.clear();2949 Record.push_back(PPD_SKIPPED_RANGES);2950 Stream.EmitRecordWithBlob(PPESkippedRangeAbbrev, Record,2951 bytes(SerializedSkippedRanges));2952 }2953}2954 2955unsigned ASTWriter::getLocalOrImportedSubmoduleID(const Module *Mod) {2956 if (!Mod)2957 return 0;2958 2959 auto Known = SubmoduleIDs.find(Mod);2960 if (Known != SubmoduleIDs.end())2961 return Known->second;2962 2963 auto *Top = Mod->getTopLevelModule();2964 if (Top != WritingModule &&2965 (getLangOpts().CompilingPCH ||2966 !Top->fullModuleNameIs(StringRef(getLangOpts().CurrentModule))))2967 return 0;2968 2969 return SubmoduleIDs[Mod] = NextSubmoduleID++;2970}2971 2972unsigned ASTWriter::getSubmoduleID(Module *Mod) {2973 unsigned ID = getLocalOrImportedSubmoduleID(Mod);2974 // FIXME: This can easily happen, if we have a reference to a submodule that2975 // did not result in us loading a module file for that submodule. For2976 // instance, a cross-top-level-module 'conflict' declaration will hit this.2977 // assert((ID || !Mod) &&2978 // "asked for module ID for non-local, non-imported module");2979 return ID;2980}2981 2982/// Compute the number of modules within the given tree (including the2983/// given module).2984static unsigned getNumberOfModules(Module *Mod) {2985 unsigned ChildModules = 0;2986 for (auto *Submodule : Mod->submodules())2987 ChildModules += getNumberOfModules(Submodule);2988 2989 return ChildModules + 1;2990}2991 2992void ASTWriter::WriteSubmodules(Module *WritingModule, ASTContext *Context) {2993 // Enter the submodule description block.2994 Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5);2995 2996 // Write the abbreviations needed for the submodules block.2997 using namespace llvm;2998 2999 auto Abbrev = std::make_shared<BitCodeAbbrev>();3000 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_DEFINITION));3001 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID3002 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent3003 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // Kind3004 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Definition location3005 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Inferred allowed by3006 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework3007 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit3008 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem3009 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExternC3010 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules...3011 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit...3012 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild...3013 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConfigMacrosExh...3014 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModuleMapIsPriv...3015 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // NamedModuleHasN...3016 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name3017 unsigned DefinitionAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3018 3019 Abbrev = std::make_shared<BitCodeAbbrev>();3020 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_HEADER));3021 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name3022 unsigned UmbrellaAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3023 3024 Abbrev = std::make_shared<BitCodeAbbrev>();3025 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_HEADER));3026 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name3027 unsigned HeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3028 3029 Abbrev = std::make_shared<BitCodeAbbrev>();3030 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TOPHEADER));3031 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name3032 unsigned TopHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3033 3034 Abbrev = std::make_shared<BitCodeAbbrev>();3035 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_DIR));3036 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name3037 unsigned UmbrellaDirAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3038 3039 Abbrev = std::make_shared<BitCodeAbbrev>();3040 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_REQUIRES));3041 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // State3042 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature3043 unsigned RequiresAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3044 3045 Abbrev = std::make_shared<BitCodeAbbrev>();3046 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXCLUDED_HEADER));3047 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name3048 unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3049 3050 Abbrev = std::make_shared<BitCodeAbbrev>();3051 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TEXTUAL_HEADER));3052 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name3053 unsigned TextualHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3054 3055 Abbrev = std::make_shared<BitCodeAbbrev>();3056 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_HEADER));3057 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name3058 unsigned PrivateHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3059 3060 Abbrev = std::make_shared<BitCodeAbbrev>();3061 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_TEXTUAL_HEADER));3062 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name3063 unsigned PrivateTextualHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3064 3065 Abbrev = std::make_shared<BitCodeAbbrev>();3066 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY));3067 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework3068 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name3069 unsigned LinkLibraryAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3070 3071 Abbrev = std::make_shared<BitCodeAbbrev>();3072 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFIG_MACRO));3073 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Macro name3074 unsigned ConfigMacroAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3075 3076 Abbrev = std::make_shared<BitCodeAbbrev>();3077 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFLICT));3078 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Other module3079 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Message3080 unsigned ConflictAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3081 3082 Abbrev = std::make_shared<BitCodeAbbrev>();3083 Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXPORT_AS));3084 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Macro name3085 unsigned ExportAsAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3086 3087 // Write the submodule metadata block.3088 RecordData::value_type Record[] = {3089 getNumberOfModules(WritingModule),3090 FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS};3091 Stream.EmitRecord(SUBMODULE_METADATA, Record);3092 3093 // Write all of the submodules.3094 std::queue<Module *> Q;3095 Q.push(WritingModule);3096 while (!Q.empty()) {3097 Module *Mod = Q.front();3098 Q.pop();3099 unsigned ID = getSubmoduleID(Mod);3100 3101 uint64_t ParentID = 0;3102 if (Mod->Parent) {3103 assert(SubmoduleIDs[Mod->Parent] && "Submodule parent not written?");3104 ParentID = SubmoduleIDs[Mod->Parent];3105 }3106 3107 SourceLocationEncoding::RawLocEncoding DefinitionLoc =3108 getRawSourceLocationEncoding(getAdjustedLocation(Mod->DefinitionLoc));3109 3110 ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap();3111 FileID UnadjustedInferredFID;3112 if (Mod->IsInferred)3113 UnadjustedInferredFID = ModMap.getModuleMapFileIDForUniquing(Mod);3114 int InferredFID = getAdjustedFileID(UnadjustedInferredFID).getOpaqueValue();3115 3116 // Emit the definition of the block.3117 {3118 RecordData::value_type Record[] = {SUBMODULE_DEFINITION,3119 ID,3120 ParentID,3121 (RecordData::value_type)Mod->Kind,3122 DefinitionLoc,3123 (RecordData::value_type)InferredFID,3124 Mod->IsFramework,3125 Mod->IsExplicit,3126 Mod->IsSystem,3127 Mod->IsExternC,3128 Mod->InferSubmodules,3129 Mod->InferExplicitSubmodules,3130 Mod->InferExportWildcard,3131 Mod->ConfigMacrosExhaustive,3132 Mod->ModuleMapIsPrivate,3133 Mod->NamedModuleHasInit};3134 Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);3135 }3136 3137 // Emit the requirements.3138 for (const auto &R : Mod->Requirements) {3139 RecordData::value_type Record[] = {SUBMODULE_REQUIRES, R.RequiredState};3140 Stream.EmitRecordWithBlob(RequiresAbbrev, Record, R.FeatureName);3141 }3142 3143 // Emit the umbrella header, if there is one.3144 if (std::optional<Module::Header> UmbrellaHeader =3145 Mod->getUmbrellaHeaderAsWritten()) {3146 RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_HEADER};3147 Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record,3148 UmbrellaHeader->NameAsWritten);3149 } else if (std::optional<Module::DirectoryName> UmbrellaDir =3150 Mod->getUmbrellaDirAsWritten()) {3151 RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_DIR};3152 Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record,3153 UmbrellaDir->NameAsWritten);3154 }3155 3156 // Emit the headers.3157 struct {3158 unsigned RecordKind;3159 unsigned Abbrev;3160 Module::HeaderKind HeaderKind;3161 } HeaderLists[] = {3162 {SUBMODULE_HEADER, HeaderAbbrev, Module::HK_Normal},3163 {SUBMODULE_TEXTUAL_HEADER, TextualHeaderAbbrev, Module::HK_Textual},3164 {SUBMODULE_PRIVATE_HEADER, PrivateHeaderAbbrev, Module::HK_Private},3165 {SUBMODULE_PRIVATE_TEXTUAL_HEADER, PrivateTextualHeaderAbbrev,3166 Module::HK_PrivateTextual},3167 {SUBMODULE_EXCLUDED_HEADER, ExcludedHeaderAbbrev, Module::HK_Excluded}3168 };3169 for (const auto &HL : HeaderLists) {3170 RecordData::value_type Record[] = {HL.RecordKind};3171 for (const auto &H : Mod->getHeaders(HL.HeaderKind))3172 Stream.EmitRecordWithBlob(HL.Abbrev, Record, H.NameAsWritten);3173 }3174 3175 // Emit the top headers.3176 {3177 RecordData::value_type Record[] = {SUBMODULE_TOPHEADER};3178 for (FileEntryRef H : Mod->getTopHeaders(PP->getFileManager())) {3179 SmallString<128> HeaderName(H.getName());3180 PreparePathForOutput(HeaderName);3181 Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, HeaderName);3182 }3183 }3184 3185 // Emit the imports.3186 if (!Mod->Imports.empty()) {3187 RecordData Record;3188 for (auto *I : Mod->Imports)3189 Record.push_back(getSubmoduleID(I));3190 Stream.EmitRecord(SUBMODULE_IMPORTS, Record);3191 }3192 3193 // Emit the modules affecting compilation that were not imported.3194 if (!Mod->AffectingClangModules.empty()) {3195 RecordData Record;3196 for (auto *I : Mod->AffectingClangModules)3197 Record.push_back(getSubmoduleID(I));3198 Stream.EmitRecord(SUBMODULE_AFFECTING_MODULES, Record);3199 }3200 3201 // Emit the exports.3202 if (!Mod->Exports.empty()) {3203 RecordData Record;3204 for (const auto &E : Mod->Exports) {3205 // FIXME: This may fail; we don't require that all exported modules3206 // are local or imported.3207 Record.push_back(getSubmoduleID(E.getPointer()));3208 Record.push_back(E.getInt());3209 }3210 Stream.EmitRecord(SUBMODULE_EXPORTS, Record);3211 }3212 3213 //FIXME: How do we emit the 'use'd modules? They may not be submodules.3214 // Might be unnecessary as use declarations are only used to build the3215 // module itself.3216 3217 // TODO: Consider serializing undeclared uses of modules.3218 3219 // Emit the link libraries.3220 for (const auto &LL : Mod->LinkLibraries) {3221 RecordData::value_type Record[] = {SUBMODULE_LINK_LIBRARY,3222 LL.IsFramework};3223 Stream.EmitRecordWithBlob(LinkLibraryAbbrev, Record, LL.Library);3224 }3225 3226 // Emit the conflicts.3227 for (const auto &C : Mod->Conflicts) {3228 // FIXME: This may fail; we don't require that all conflicting modules3229 // are local or imported.3230 RecordData::value_type Record[] = {SUBMODULE_CONFLICT,3231 getSubmoduleID(C.Other)};3232 Stream.EmitRecordWithBlob(ConflictAbbrev, Record, C.Message);3233 }3234 3235 // Emit the configuration macros.3236 for (const auto &CM : Mod->ConfigMacros) {3237 RecordData::value_type Record[] = {SUBMODULE_CONFIG_MACRO};3238 Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, CM);3239 }3240 3241 // Emit the reachable initializers.3242 // The initializer may only be unreachable in reduced BMI.3243 if (Context && !GeneratingReducedBMI) {3244 RecordData Inits;3245 for (Decl *D : Context->getModuleInitializers(Mod))3246 if (wasDeclEmitted(D))3247 AddDeclRef(D, Inits);3248 if (!Inits.empty())3249 Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits);3250 }3251 3252 // Emit the name of the re-exported module, if any.3253 if (!Mod->ExportAsModule.empty()) {3254 RecordData::value_type Record[] = {SUBMODULE_EXPORT_AS};3255 Stream.EmitRecordWithBlob(ExportAsAbbrev, Record, Mod->ExportAsModule);3256 }3257 3258 // Queue up the submodules of this module.3259 for (auto *M : Mod->submodules())3260 Q.push(M);3261 }3262 3263 Stream.ExitBlock();3264 3265 assert((NextSubmoduleID - FirstSubmoduleID ==3266 getNumberOfModules(WritingModule)) &&3267 "Wrong # of submodules; found a reference to a non-local, "3268 "non-imported submodule?");3269}3270 3271void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,3272 bool isModule) {3273 llvm::SmallDenseMap<const DiagnosticsEngine::DiagState *, unsigned, 64>3274 DiagStateIDMap;3275 unsigned CurrID = 0;3276 RecordData Record;3277 3278 auto EncodeDiagStateFlags =3279 [](const DiagnosticsEngine::DiagState *DS) -> unsigned {3280 unsigned Result = (unsigned)DS->ExtBehavior;3281 for (unsigned Val :3282 {(unsigned)DS->IgnoreAllWarnings, (unsigned)DS->EnableAllWarnings,3283 (unsigned)DS->WarningsAsErrors, (unsigned)DS->ErrorsAsFatal,3284 (unsigned)DS->SuppressSystemWarnings})3285 Result = (Result << 1) | Val;3286 return Result;3287 };3288 3289 unsigned Flags = EncodeDiagStateFlags(Diag.DiagStatesByLoc.FirstDiagState);3290 Record.push_back(Flags);3291 3292 auto AddDiagState = [&](const DiagnosticsEngine::DiagState *State,3293 bool IncludeNonPragmaStates) {3294 // Ensure that the diagnostic state wasn't modified since it was created.3295 // We will not correctly round-trip this information otherwise.3296 assert(Flags == EncodeDiagStateFlags(State) &&3297 "diag state flags vary in single AST file");3298 3299 // If we ever serialize non-pragma mappings outside the initial state, the3300 // code below will need to consider more than getDefaultMapping.3301 assert(!IncludeNonPragmaStates ||3302 State == Diag.DiagStatesByLoc.FirstDiagState);3303 3304 unsigned &DiagStateID = DiagStateIDMap[State];3305 Record.push_back(DiagStateID);3306 3307 if (DiagStateID == 0) {3308 DiagStateID = ++CurrID;3309 SmallVector<std::pair<unsigned, DiagnosticMapping>> Mappings;3310 3311 // Add a placeholder for the number of mappings.3312 auto SizeIdx = Record.size();3313 Record.emplace_back();3314 for (const auto &I : *State) {3315 // Maybe skip non-pragmas.3316 if (!I.second.isPragma() && !IncludeNonPragmaStates)3317 continue;3318 // Skip default mappings. We have a mapping for every diagnostic ever3319 // emitted, regardless of whether it was customized.3320 if (!I.second.isPragma() &&3321 I.second == Diag.getDiagnosticIDs()->getDefaultMapping(I.first))3322 continue;3323 Mappings.push_back(I);3324 }3325 3326 // Sort by diag::kind for deterministic output.3327 llvm::sort(Mappings, llvm::less_first());3328 3329 for (const auto &I : Mappings) {3330 Record.push_back(I.first);3331 Record.push_back(I.second.serialize());3332 }3333 // Update the placeholder.3334 Record[SizeIdx] = (Record.size() - SizeIdx) / 2;3335 }3336 };3337 3338 AddDiagState(Diag.DiagStatesByLoc.FirstDiagState, isModule);3339 3340 // Reserve a spot for the number of locations with state transitions.3341 auto NumLocationsIdx = Record.size();3342 Record.emplace_back();3343 3344 // Emit the state transitions.3345 unsigned NumLocations = 0;3346 for (auto &FileIDAndFile : Diag.DiagStatesByLoc.Files) {3347 if (!FileIDAndFile.first.isValid() ||3348 !FileIDAndFile.second.HasLocalTransitions)3349 continue;3350 ++NumLocations;3351 3352 AddFileID(FileIDAndFile.first, Record);3353 3354 Record.push_back(FileIDAndFile.second.StateTransitions.size());3355 for (auto &StatePoint : FileIDAndFile.second.StateTransitions) {3356 Record.push_back(getAdjustedOffset(StatePoint.Offset));3357 AddDiagState(StatePoint.State, false);3358 }3359 }3360 3361 // Backpatch the number of locations.3362 Record[NumLocationsIdx] = NumLocations;3363 3364 // Emit CurDiagStateLoc. Do it last in order to match source order.3365 //3366 // This also protects against a hypothetical corner case with simulating3367 // -Werror settings for implicit modules in the ASTReader, where reading3368 // CurDiagState out of context could change whether warning pragmas are3369 // treated as errors.3370 AddSourceLocation(Diag.DiagStatesByLoc.CurDiagStateLoc, Record);3371 AddDiagState(Diag.DiagStatesByLoc.CurDiagState, false);3372 3373 Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record);3374}3375 3376//===----------------------------------------------------------------------===//3377// Type Serialization3378//===----------------------------------------------------------------------===//3379 3380/// Write the representation of a type to the AST stream.3381void ASTWriter::WriteType(ASTContext &Context, QualType T) {3382 TypeIdx &IdxRef = TypeIdxs[T];3383 if (IdxRef.getValue() == 0) // we haven't seen this type before.3384 IdxRef = TypeIdx(0, NextTypeID++);3385 TypeIdx Idx = IdxRef;3386 3387 assert(Idx.getModuleFileIndex() == 0 && "Re-writing a type from a prior AST");3388 assert(Idx.getValue() >= FirstTypeID && "Writing predefined type");3389 3390 // Emit the type's representation.3391 uint64_t Offset =3392 ASTTypeWriter(Context, *this).write(T) - DeclTypesBlockStartOffset;3393 3394 // Record the offset for this type.3395 uint64_t Index = Idx.getValue() - FirstTypeID;3396 if (TypeOffsets.size() == Index)3397 TypeOffsets.emplace_back(Offset);3398 else if (TypeOffsets.size() < Index) {3399 TypeOffsets.resize(Index + 1);3400 TypeOffsets[Index].set(Offset);3401 } else {3402 llvm_unreachable("Types emitted in wrong order");3403 }3404}3405 3406//===----------------------------------------------------------------------===//3407// Declaration Serialization3408//===----------------------------------------------------------------------===//3409 3410static bool IsInternalDeclFromFileContext(const Decl *D) {3411 auto *ND = dyn_cast<NamedDecl>(D);3412 if (!ND)3413 return false;3414 3415 if (!D->getDeclContext()->getRedeclContext()->isFileContext())3416 return false;3417 3418 return ND->getFormalLinkage() == Linkage::Internal;3419}3420 3421/// Write the block containing all of the declaration IDs3422/// lexically declared within the given DeclContext.3423///3424/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the3425/// bitstream, or 0 if no block was written.3426uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,3427 const DeclContext *DC) {3428 if (DC->decls_empty())3429 return 0;3430 3431 // In reduced BMI, we don't care the declarations in functions.3432 if (GeneratingReducedBMI && DC->isFunctionOrMethod())3433 return 0;3434 3435 uint64_t Offset = Stream.GetCurrentBitNo();3436 SmallVector<DeclID, 128> KindDeclPairs;3437 for (const auto *D : DC->decls()) {3438 if (DoneWritingDeclsAndTypes && !wasDeclEmitted(D))3439 continue;3440 3441 // We don't need to write decls with internal linkage into reduced BMI.3442 // If such decls gets emitted due to it get used from inline functions,3443 // the program illegal. However, there are too many use of static inline3444 // functions in the global module fragment and it will be breaking change3445 // to forbid that. So we have to allow to emit such declarations from GMF.3446 if (GeneratingReducedBMI && !D->isFromExplicitGlobalModule() &&3447 IsInternalDeclFromFileContext(D))3448 continue;3449 3450 KindDeclPairs.push_back(D->getKind());3451 KindDeclPairs.push_back(GetDeclRef(D).getRawValue());3452 }3453 3454 ++NumLexicalDeclContexts;3455 RecordData::value_type Record[] = {DECL_CONTEXT_LEXICAL};3456 Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record,3457 bytes(KindDeclPairs));3458 return Offset;3459}3460 3461void ASTWriter::WriteTypeDeclOffsets() {3462 using namespace llvm;3463 3464 // Write the type offsets array3465 auto Abbrev = std::make_shared<BitCodeAbbrev>();3466 Abbrev->Add(BitCodeAbbrevOp(TYPE_OFFSET));3467 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types3468 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block3469 unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3470 {3471 RecordData::value_type Record[] = {TYPE_OFFSET, TypeOffsets.size()};3472 Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, bytes(TypeOffsets));3473 }3474 3475 // Write the declaration offsets array3476 Abbrev = std::make_shared<BitCodeAbbrev>();3477 Abbrev->Add(BitCodeAbbrevOp(DECL_OFFSET));3478 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations3479 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block3480 unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3481 {3482 RecordData::value_type Record[] = {DECL_OFFSET, DeclOffsets.size()};3483 Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets));3484 }3485}3486 3487void ASTWriter::WriteFileDeclIDsMap() {3488 using namespace llvm;3489 3490 SmallVector<std::pair<FileID, DeclIDInFileInfo *>, 64> SortedFileDeclIDs;3491 SortedFileDeclIDs.reserve(FileDeclIDs.size());3492 for (const auto &P : FileDeclIDs)3493 SortedFileDeclIDs.push_back(std::make_pair(P.first, P.second.get()));3494 llvm::sort(SortedFileDeclIDs, llvm::less_first());3495 3496 // Join the vectors of DeclIDs from all files.3497 SmallVector<DeclID, 256> FileGroupedDeclIDs;3498 for (auto &FileDeclEntry : SortedFileDeclIDs) {3499 DeclIDInFileInfo &Info = *FileDeclEntry.second;3500 Info.FirstDeclIndex = FileGroupedDeclIDs.size();3501 llvm::stable_sort(Info.DeclIDs);3502 for (auto &LocDeclEntry : Info.DeclIDs)3503 FileGroupedDeclIDs.push_back(LocDeclEntry.second.getRawValue());3504 }3505 3506 auto Abbrev = std::make_shared<BitCodeAbbrev>();3507 Abbrev->Add(BitCodeAbbrevOp(FILE_SORTED_DECLS));3508 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));3509 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));3510 unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));3511 RecordData::value_type Record[] = {FILE_SORTED_DECLS,3512 FileGroupedDeclIDs.size()};3513 Stream.EmitRecordWithBlob(AbbrevCode, Record, bytes(FileGroupedDeclIDs));3514}3515 3516void ASTWriter::WriteComments(ASTContext &Context) {3517 Stream.EnterSubblock(COMMENTS_BLOCK_ID, 3);3518 auto _ = llvm::make_scope_exit([this] { Stream.ExitBlock(); });3519 if (!PP->getPreprocessorOpts().WriteCommentListToPCH)3520 return;3521 3522 // Don't write comments to BMI to reduce the size of BMI.3523 // If language services (e.g., clangd) want such abilities,3524 // we can offer a special option then.3525 if (isWritingStdCXXNamedModules())3526 return;3527 3528 RecordData Record;3529 for (const auto &FO : Context.Comments.OrderedComments) {3530 for (const auto &OC : FO.second) {3531 const RawComment *I = OC.second;3532 Record.clear();3533 AddSourceRange(I->getSourceRange(), Record);3534 Record.push_back(I->getKind());3535 Record.push_back(I->isTrailingComment());3536 Record.push_back(I->isAlmostTrailingComment());3537 Stream.EmitRecord(COMMENTS_RAW_COMMENT, Record);3538 }3539 }3540}3541 3542//===----------------------------------------------------------------------===//3543// Global Method Pool and Selector Serialization3544//===----------------------------------------------------------------------===//3545 3546namespace {3547 3548// Trait used for the on-disk hash table used in the method pool.3549class ASTMethodPoolTrait {3550 ASTWriter &Writer;3551 3552public:3553 using key_type = Selector;3554 using key_type_ref = key_type;3555 3556 struct data_type {3557 SelectorID ID;3558 ObjCMethodList Instance, Factory;3559 };3560 using data_type_ref = const data_type &;3561 3562 using hash_value_type = unsigned;3563 using offset_type = unsigned;3564 3565 explicit ASTMethodPoolTrait(ASTWriter &Writer) : Writer(Writer) {}3566 3567 static hash_value_type ComputeHash(Selector Sel) {3568 return serialization::ComputeHash(Sel);3569 }3570 3571 std::pair<unsigned, unsigned>3572 EmitKeyDataLength(raw_ostream& Out, Selector Sel,3573 data_type_ref Methods) {3574 unsigned KeyLen =3575 2 + (Sel.getNumArgs() ? Sel.getNumArgs() * sizeof(IdentifierID)3576 : sizeof(IdentifierID));3577 unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts3578 for (const ObjCMethodList *Method = &Methods.Instance; Method;3579 Method = Method->getNext())3580 if (ShouldWriteMethodListNode(Method))3581 DataLen += sizeof(DeclID);3582 for (const ObjCMethodList *Method = &Methods.Factory; Method;3583 Method = Method->getNext())3584 if (ShouldWriteMethodListNode(Method))3585 DataLen += sizeof(DeclID);3586 return emitULEBKeyDataLength(KeyLen, DataLen, Out);3587 }3588 3589 void EmitKey(raw_ostream& Out, Selector Sel, unsigned) {3590 using namespace llvm::support;3591 3592 endian::Writer LE(Out, llvm::endianness::little);3593 uint64_t Start = Out.tell();3594 assert((Start >> 32) == 0 && "Selector key offset too large");3595 Writer.SetSelectorOffset(Sel, Start);3596 unsigned N = Sel.getNumArgs();3597 LE.write<uint16_t>(N);3598 if (N == 0)3599 N = 1;3600 for (unsigned I = 0; I != N; ++I)3601 LE.write<IdentifierID>(3602 Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I)));3603 }3604 3605 void EmitData(raw_ostream& Out, key_type_ref,3606 data_type_ref Methods, unsigned DataLen) {3607 using namespace llvm::support;3608 3609 endian::Writer LE(Out, llvm::endianness::little);3610 uint64_t Start = Out.tell(); (void)Start;3611 LE.write<uint32_t>(Methods.ID);3612 unsigned NumInstanceMethods = 0;3613 for (const ObjCMethodList *Method = &Methods.Instance; Method;3614 Method = Method->getNext())3615 if (ShouldWriteMethodListNode(Method))3616 ++NumInstanceMethods;3617 3618 unsigned NumFactoryMethods = 0;3619 for (const ObjCMethodList *Method = &Methods.Factory; Method;3620 Method = Method->getNext())3621 if (ShouldWriteMethodListNode(Method))3622 ++NumFactoryMethods;3623 3624 unsigned InstanceBits = Methods.Instance.getBits();3625 assert(InstanceBits < 4);3626 unsigned InstanceHasMoreThanOneDeclBit =3627 Methods.Instance.hasMoreThanOneDecl();3628 unsigned FullInstanceBits = (NumInstanceMethods << 3) |3629 (InstanceHasMoreThanOneDeclBit << 2) |3630 InstanceBits;3631 unsigned FactoryBits = Methods.Factory.getBits();3632 assert(FactoryBits < 4);3633 unsigned FactoryHasMoreThanOneDeclBit =3634 Methods.Factory.hasMoreThanOneDecl();3635 unsigned FullFactoryBits = (NumFactoryMethods << 3) |3636 (FactoryHasMoreThanOneDeclBit << 2) |3637 FactoryBits;3638 LE.write<uint16_t>(FullInstanceBits);3639 LE.write<uint16_t>(FullFactoryBits);3640 for (const ObjCMethodList *Method = &Methods.Instance; Method;3641 Method = Method->getNext())3642 if (ShouldWriteMethodListNode(Method))3643 LE.write<DeclID>((DeclID)Writer.getDeclID(Method->getMethod()));3644 for (const ObjCMethodList *Method = &Methods.Factory; Method;3645 Method = Method->getNext())3646 if (ShouldWriteMethodListNode(Method))3647 LE.write<DeclID>((DeclID)Writer.getDeclID(Method->getMethod()));3648 3649 assert(Out.tell() - Start == DataLen && "Data length is wrong");3650 }3651 3652private:3653 static bool ShouldWriteMethodListNode(const ObjCMethodList *Node) {3654 return (Node->getMethod() && !Node->getMethod()->isFromASTFile());3655 }3656};3657 3658} // namespace3659 3660/// Write ObjC data: selectors and the method pool.3661///3662/// The method pool contains both instance and factory methods, stored3663/// in an on-disk hash table indexed by the selector. The hash table also3664/// contains an empty entry for every other selector known to Sema.3665void ASTWriter::WriteSelectors(Sema &SemaRef) {3666 using namespace llvm;3667 3668 // Do we have to do anything at all?3669 if (SemaRef.ObjC().MethodPool.empty() && SelectorIDs.empty())3670 return;3671 unsigned NumTableEntries = 0;3672 // Create and write out the blob that contains selectors and the method pool.3673 {3674 llvm::OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator;3675 ASTMethodPoolTrait Trait(*this);3676 3677 // Create the on-disk hash table representation. We walk through every3678 // selector we've seen and look it up in the method pool.3679 SelectorOffsets.resize(NextSelectorID - FirstSelectorID);3680 for (auto &SelectorAndID : SelectorIDs) {3681 Selector S = SelectorAndID.first;3682 SelectorID ID = SelectorAndID.second;3683 SemaObjC::GlobalMethodPool::iterator F =3684 SemaRef.ObjC().MethodPool.find(S);3685 ASTMethodPoolTrait::data_type Data = {3686 ID,3687 ObjCMethodList(),3688 ObjCMethodList()3689 };3690 if (F != SemaRef.ObjC().MethodPool.end()) {3691 Data.Instance = F->second.first;3692 Data.Factory = F->second.second;3693 }3694 // Only write this selector if it's not in an existing AST or something3695 // changed.3696 if (Chain && ID < FirstSelectorID) {3697 // Selector already exists. Did it change?3698 bool changed = false;3699 for (ObjCMethodList *M = &Data.Instance; M && M->getMethod();3700 M = M->getNext()) {3701 if (!M->getMethod()->isFromASTFile()) {3702 changed = true;3703 Data.Instance = *M;3704 break;3705 }3706 }3707 for (ObjCMethodList *M = &Data.Factory; M && M->getMethod();3708 M = M->getNext()) {3709 if (!M->getMethod()->isFromASTFile()) {3710 changed = true;3711 Data.Factory = *M;3712 break;3713 }3714 }3715 if (!changed)3716 continue;3717 } else if (Data.Instance.getMethod() || Data.Factory.getMethod()) {3718 // A new method pool entry.3719 ++NumTableEntries;3720 }3721 Generator.insert(S, Data, Trait);3722 }3723 3724 // Create the on-disk hash table in a buffer.3725 SmallString<4096> MethodPool;3726 uint32_t BucketOffset;3727 {3728 using namespace llvm::support;3729 3730 ASTMethodPoolTrait Trait(*this);3731 llvm::raw_svector_ostream Out(MethodPool);3732 // Make sure that no bucket is at offset 03733 endian::write<uint32_t>(Out, 0, llvm::endianness::little);3734 BucketOffset = Generator.Emit(Out, Trait);3735 }3736 3737 // Create a blob abbreviation3738 auto Abbrev = std::make_shared<BitCodeAbbrev>();3739 Abbrev->Add(BitCodeAbbrevOp(METHOD_POOL));3740 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));3741 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));3742 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));3743 unsigned MethodPoolAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3744 3745 // Write the method pool3746 {3747 RecordData::value_type Record[] = {METHOD_POOL, BucketOffset,3748 NumTableEntries};3749 Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool);3750 }3751 3752 // Create a blob abbreviation for the selector table offsets.3753 Abbrev = std::make_shared<BitCodeAbbrev>();3754 Abbrev->Add(BitCodeAbbrevOp(SELECTOR_OFFSETS));3755 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size3756 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID3757 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));3758 unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3759 3760 // Write the selector offsets table.3761 {3762 RecordData::value_type Record[] = {3763 SELECTOR_OFFSETS, SelectorOffsets.size(),3764 FirstSelectorID - NUM_PREDEF_SELECTOR_IDS};3765 Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,3766 bytes(SelectorOffsets));3767 }3768 }3769}3770 3771/// Write the selectors referenced in @selector expression into AST file.3772void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) {3773 using namespace llvm;3774 3775 if (SemaRef.ObjC().ReferencedSelectors.empty())3776 return;3777 3778 RecordData Record;3779 ASTRecordWriter Writer(SemaRef.Context, *this, Record);3780 3781 // Note: this writes out all references even for a dependent AST. But it is3782 // very tricky to fix, and given that @selector shouldn't really appear in3783 // headers, probably not worth it. It's not a correctness issue.3784 for (auto &SelectorAndLocation : SemaRef.ObjC().ReferencedSelectors) {3785 Selector Sel = SelectorAndLocation.first;3786 SourceLocation Loc = SelectorAndLocation.second;3787 Writer.AddSelectorRef(Sel);3788 Writer.AddSourceLocation(Loc);3789 }3790 Writer.Emit(REFERENCED_SELECTOR_POOL);3791}3792 3793//===----------------------------------------------------------------------===//3794// Identifier Table Serialization3795//===----------------------------------------------------------------------===//3796 3797/// Determine the declaration that should be put into the name lookup table to3798/// represent the given declaration in this module. This is usually D itself,3799/// but if D was imported and merged into a local declaration, we want the most3800/// recent local declaration instead. The chosen declaration will be the most3801/// recent declaration in any module that imports this one.3802static NamedDecl *getDeclForLocalLookup(const LangOptions &LangOpts,3803 NamedDecl *D) {3804 if (!LangOpts.Modules || !D->isFromASTFile())3805 return D;3806 3807 if (Decl *Redecl = D->getPreviousDecl()) {3808 // For Redeclarable decls, a prior declaration might be local.3809 for (; Redecl; Redecl = Redecl->getPreviousDecl()) {3810 // If we find a local decl, we're done.3811 if (!Redecl->isFromASTFile()) {3812 // Exception: in very rare cases (for injected-class-names), not all3813 // redeclarations are in the same semantic context. Skip ones in a3814 // different context. They don't go in this lookup table at all.3815 if (!Redecl->getDeclContext()->getRedeclContext()->Equals(3816 D->getDeclContext()->getRedeclContext()))3817 continue;3818 return cast<NamedDecl>(Redecl);3819 }3820 3821 // If we find a decl from a (chained-)PCH stop since we won't find a3822 // local one.3823 if (Redecl->getOwningModuleID() == 0)3824 break;3825 }3826 } else if (Decl *First = D->getCanonicalDecl()) {3827 // For Mergeable decls, the first decl might be local.3828 if (!First->isFromASTFile())3829 return cast<NamedDecl>(First);3830 }3831 3832 // All declarations are imported. Our most recent declaration will also be3833 // the most recent one in anyone who imports us.3834 return D;3835}3836 3837namespace {3838 3839bool IsInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset,3840 bool IsModule, bool IsCPlusPlus) {3841 bool NeedDecls = !IsModule || !IsCPlusPlus;3842 3843 bool IsInteresting =3844 II->getNotableIdentifierID() != tok::NotableIdentifierKind::not_notable ||3845 II->getBuiltinID() != Builtin::ID::NotBuiltin ||3846 II->getObjCKeywordID() != tok::ObjCKeywordKind::objc_not_keyword;3847 if (MacroOffset ||3848 (II->hasMacroDefinition() &&3849 II->hasFETokenInfoChangedSinceDeserialization()) ||3850 II->isPoisoned() || (!IsModule && IsInteresting) ||3851 II->hasRevertedTokenIDToIdentifier() ||3852 (NeedDecls && II->getFETokenInfo()))3853 return true;3854 3855 return false;3856}3857 3858bool IsInterestingNonMacroIdentifier(const IdentifierInfo *II,3859 ASTWriter &Writer) {3860 bool IsModule = Writer.isWritingModule();3861 bool IsCPlusPlus = Writer.getLangOpts().CPlusPlus;3862 return IsInterestingIdentifier(II, /*MacroOffset=*/0, IsModule, IsCPlusPlus);3863}3864 3865class ASTIdentifierTableTrait {3866 ASTWriter &Writer;3867 Preprocessor &PP;3868 IdentifierResolver *IdResolver;3869 bool IsModule;3870 bool NeedDecls;3871 ASTWriter::RecordData *InterestingIdentifierOffsets;3872 3873 /// Determines whether this is an "interesting" identifier that needs a3874 /// full IdentifierInfo structure written into the hash table. Notably, this3875 /// doesn't check whether the name has macros defined; use PublicMacroIterator3876 /// to check that.3877 bool isInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset) {3878 return IsInterestingIdentifier(II, MacroOffset, IsModule,3879 Writer.getLangOpts().CPlusPlus);3880 }3881 3882public:3883 using key_type = const IdentifierInfo *;3884 using key_type_ref = key_type;3885 3886 using data_type = IdentifierID;3887 using data_type_ref = data_type;3888 3889 using hash_value_type = unsigned;3890 using offset_type = unsigned;3891 3892 ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP,3893 IdentifierResolver *IdResolver, bool IsModule,3894 ASTWriter::RecordData *InterestingIdentifierOffsets)3895 : Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule),3896 NeedDecls(!IsModule || !Writer.getLangOpts().CPlusPlus),3897 InterestingIdentifierOffsets(InterestingIdentifierOffsets) {}3898 3899 bool needDecls() const { return NeedDecls; }3900 3901 static hash_value_type ComputeHash(const IdentifierInfo* II) {3902 return llvm::djbHash(II->getName());3903 }3904 3905 bool isInterestingIdentifier(const IdentifierInfo *II) {3906 auto MacroOffset = Writer.getMacroDirectivesOffset(II);3907 return isInterestingIdentifier(II, MacroOffset);3908 }3909 3910 std::pair<unsigned, unsigned>3911 EmitKeyDataLength(raw_ostream &Out, const IdentifierInfo *II, IdentifierID ID) {3912 // Record the location of the identifier data. This is used when generating3913 // the mapping from persistent IDs to strings.3914 Writer.SetIdentifierOffset(II, Out.tell());3915 3916 auto MacroOffset = Writer.getMacroDirectivesOffset(II);3917 3918 // Emit the offset of the key/data length information to the interesting3919 // identifiers table if necessary.3920 if (InterestingIdentifierOffsets &&3921 isInterestingIdentifier(II, MacroOffset))3922 InterestingIdentifierOffsets->push_back(Out.tell());3923 3924 unsigned KeyLen = II->getLength() + 1;3925 unsigned DataLen = sizeof(IdentifierID); // bytes for the persistent ID << 13926 if (isInterestingIdentifier(II, MacroOffset)) {3927 DataLen += 2; // 2 bytes for builtin ID3928 DataLen += 2; // 2 bytes for flags3929 if (MacroOffset || (II->hasMacroDefinition() &&3930 II->hasFETokenInfoChangedSinceDeserialization()))3931 DataLen += 4; // MacroDirectives offset.3932 3933 if (NeedDecls && IdResolver)3934 DataLen += std::distance(IdResolver->begin(II), IdResolver->end()) *3935 sizeof(DeclID);3936 }3937 return emitULEBKeyDataLength(KeyLen, DataLen, Out);3938 }3939 3940 void EmitKey(raw_ostream &Out, const IdentifierInfo *II, unsigned KeyLen) {3941 Out.write(II->getNameStart(), KeyLen);3942 }3943 3944 void EmitData(raw_ostream &Out, const IdentifierInfo *II, IdentifierID ID,3945 unsigned) {3946 using namespace llvm::support;3947 3948 endian::Writer LE(Out, llvm::endianness::little);3949 3950 auto MacroOffset = Writer.getMacroDirectivesOffset(II);3951 if (!isInterestingIdentifier(II, MacroOffset)) {3952 LE.write<IdentifierID>(ID << 1);3953 return;3954 }3955 3956 LE.write<IdentifierID>((ID << 1) | 0x01);3957 uint32_t Bits = (uint32_t)II->getObjCOrBuiltinID();3958 assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader.");3959 LE.write<uint16_t>(Bits);3960 Bits = 0;3961 bool HasMacroDefinition =3962 (MacroOffset != 0) || (II->hasMacroDefinition() &&3963 II->hasFETokenInfoChangedSinceDeserialization());3964 Bits = (Bits << 1) | unsigned(HasMacroDefinition);3965 Bits = (Bits << 1) | unsigned(II->isExtensionToken());3966 Bits = (Bits << 1) | unsigned(II->isPoisoned());3967 Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());3968 Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());3969 LE.write<uint16_t>(Bits);3970 3971 if (HasMacroDefinition)3972 LE.write<uint32_t>(MacroOffset);3973 3974 if (NeedDecls && IdResolver) {3975 // Emit the declaration IDs in reverse order, because the3976 // IdentifierResolver provides the declarations as they would be3977 // visible (e.g., the function "stat" would come before the struct3978 // "stat"), but the ASTReader adds declarations to the end of the list3979 // (so we need to see the struct "stat" before the function "stat").3980 // Only emit declarations that aren't from a chained PCH, though.3981 SmallVector<NamedDecl *, 16> Decls(IdResolver->decls(II));3982 for (NamedDecl *D : llvm::reverse(Decls))3983 LE.write<DeclID>((DeclID)Writer.getDeclID(3984 getDeclForLocalLookup(PP.getLangOpts(), D)));3985 }3986 }3987};3988 3989} // namespace3990 3991/// If the \param IdentifierID ID is a local Identifier ID. If the higher3992/// bits of ID is 0, it implies that the ID doesn't come from AST files.3993static bool isLocalIdentifierID(IdentifierID ID) { return !(ID >> 32); }3994 3995/// Write the identifier table into the AST file.3996///3997/// The identifier table consists of a blob containing string data3998/// (the actual identifiers themselves) and a separate "offsets" index3999/// that maps identifier IDs to locations within the blob.4000void ASTWriter::WriteIdentifierTable(Preprocessor &PP,4001 IdentifierResolver *IdResolver,4002 bool IsModule) {4003 using namespace llvm;4004 4005 RecordData InterestingIdents;4006 4007 // Create and write out the blob that contains the identifier4008 // strings.4009 {4010 llvm::OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;4011 ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule,4012 IsModule ? &InterestingIdents : nullptr);4013 4014 // Create the on-disk hash table representation. We only store offsets4015 // for identifiers that appear here for the first time.4016 IdentifierOffsets.resize(NextIdentID - FirstIdentID);4017 for (auto IdentIDPair : IdentifierIDs) {4018 const IdentifierInfo *II = IdentIDPair.first;4019 IdentifierID ID = IdentIDPair.second;4020 assert(II && "NULL identifier in identifier table");4021 4022 // Write out identifiers if either the ID is local or the identifier has4023 // changed since it was loaded.4024 if (isLocalIdentifierID(ID) || II->hasChangedSinceDeserialization() ||4025 (Trait.needDecls() &&4026 II->hasFETokenInfoChangedSinceDeserialization()))4027 Generator.insert(II, ID, Trait);4028 }4029 4030 // Create the on-disk hash table in a buffer.4031 SmallString<4096> IdentifierTable;4032 uint32_t BucketOffset;4033 {4034 using namespace llvm::support;4035 4036 llvm::raw_svector_ostream Out(IdentifierTable);4037 // Make sure that no bucket is at offset 04038 endian::write<uint32_t>(Out, 0, llvm::endianness::little);4039 BucketOffset = Generator.Emit(Out, Trait);4040 }4041 4042 // Create a blob abbreviation4043 auto Abbrev = std::make_shared<BitCodeAbbrev>();4044 Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_TABLE));4045 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));4046 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));4047 unsigned IDTableAbbrev = Stream.EmitAbbrev(std::move(Abbrev));4048 4049 // Write the identifier table4050 RecordData::value_type Record[] = {IDENTIFIER_TABLE, BucketOffset};4051 Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable);4052 }4053 4054 // Write the offsets table for identifier IDs.4055 auto Abbrev = std::make_shared<BitCodeAbbrev>();4056 Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_OFFSET));4057 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers4058 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));4059 unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));4060 4061#ifndef NDEBUG4062 for (unsigned I = 0, N = IdentifierOffsets.size(); I != N; ++I)4063 assert(IdentifierOffsets[I] && "Missing identifier offset?");4064#endif4065 4066 RecordData::value_type Record[] = {IDENTIFIER_OFFSET,4067 IdentifierOffsets.size()};4068 Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record,4069 bytes(IdentifierOffsets));4070 4071 // In C++, write the list of interesting identifiers (those that are4072 // defined as macros, poisoned, or similar unusual things).4073 if (!InterestingIdents.empty())4074 Stream.EmitRecord(INTERESTING_IDENTIFIERS, InterestingIdents);4075}4076 4077void ASTWriter::handleVTable(CXXRecordDecl *RD) {4078 if (!RD->isInNamedModule())4079 return;4080 4081 PendingEmittingVTables.push_back(RD);4082}4083 4084void ASTWriter::addTouchedModuleFile(serialization::ModuleFile *MF) {4085 TouchedModuleFiles.insert(MF);4086}4087 4088//===----------------------------------------------------------------------===//4089// DeclContext's Name Lookup Table Serialization4090//===----------------------------------------------------------------------===//4091 4092namespace {4093 4094class ASTDeclContextNameLookupTraitBase {4095protected:4096 ASTWriter &Writer;4097 using DeclIDsTy = llvm::SmallVector<LocalDeclID, 64>;4098 DeclIDsTy DeclIDs;4099 4100public:4101 /// A start and end index into DeclIDs, representing a sequence of decls.4102 using data_type = std::pair<unsigned, unsigned>;4103 using data_type_ref = const data_type &;4104 4105 using hash_value_type = unsigned;4106 using offset_type = unsigned;4107 4108 explicit ASTDeclContextNameLookupTraitBase(ASTWriter &Writer)4109 : Writer(Writer) {}4110 4111 data_type getData(const DeclIDsTy &LocalIDs) {4112 unsigned Start = DeclIDs.size();4113 for (auto ID : LocalIDs)4114 DeclIDs.push_back(ID);4115 return std::make_pair(Start, DeclIDs.size());4116 }4117 4118 data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) {4119 unsigned Start = DeclIDs.size();4120 DeclIDs.insert(4121 DeclIDs.end(),4122 DeclIDIterator<GlobalDeclID, LocalDeclID>(FromReader.begin()),4123 DeclIDIterator<GlobalDeclID, LocalDeclID>(FromReader.end()));4124 return std::make_pair(Start, DeclIDs.size());4125 }4126 4127 void EmitFileRef(raw_ostream &Out, ModuleFile *F) const {4128 assert(Writer.hasChain() &&4129 "have reference to loaded module file but no chain?");4130 4131 using namespace llvm::support;4132 Writer.addTouchedModuleFile(F);4133 endian::write<uint32_t>(Out, Writer.getChain()->getModuleFileID(F),4134 llvm::endianness::little);4135 }4136 4137 std::pair<unsigned, unsigned> EmitKeyDataLengthBase(raw_ostream &Out,4138 DeclarationNameKey Name,4139 data_type_ref Lookup) {4140 unsigned KeyLen = 1;4141 switch (Name.getKind()) {4142 case DeclarationName::Identifier:4143 case DeclarationName::CXXLiteralOperatorName:4144 case DeclarationName::CXXDeductionGuideName:4145 KeyLen += sizeof(IdentifierID);4146 break;4147 case DeclarationName::ObjCZeroArgSelector:4148 case DeclarationName::ObjCOneArgSelector:4149 case DeclarationName::ObjCMultiArgSelector:4150 KeyLen += 4;4151 break;4152 case DeclarationName::CXXOperatorName:4153 KeyLen += 1;4154 break;4155 case DeclarationName::CXXConstructorName:4156 case DeclarationName::CXXDestructorName:4157 case DeclarationName::CXXConversionFunctionName:4158 case DeclarationName::CXXUsingDirective:4159 break;4160 }4161 4162 // length of DeclIDs.4163 unsigned DataLen = sizeof(DeclID) * (Lookup.second - Lookup.first);4164 4165 return {KeyLen, DataLen};4166 }4167 4168 void EmitKeyBase(raw_ostream &Out, DeclarationNameKey Name) {4169 using namespace llvm::support;4170 4171 endian::Writer LE(Out, llvm::endianness::little);4172 LE.write<uint8_t>(Name.getKind());4173 switch (Name.getKind()) {4174 case DeclarationName::Identifier:4175 case DeclarationName::CXXLiteralOperatorName:4176 case DeclarationName::CXXDeductionGuideName:4177 LE.write<IdentifierID>(Writer.getIdentifierRef(Name.getIdentifier()));4178 return;4179 case DeclarationName::ObjCZeroArgSelector:4180 case DeclarationName::ObjCOneArgSelector:4181 case DeclarationName::ObjCMultiArgSelector:4182 LE.write<uint32_t>(Writer.getSelectorRef(Name.getSelector()));4183 return;4184 case DeclarationName::CXXOperatorName:4185 assert(Name.getOperatorKind() < NUM_OVERLOADED_OPERATORS &&4186 "Invalid operator?");4187 LE.write<uint8_t>(Name.getOperatorKind());4188 return;4189 case DeclarationName::CXXConstructorName:4190 case DeclarationName::CXXDestructorName:4191 case DeclarationName::CXXConversionFunctionName:4192 case DeclarationName::CXXUsingDirective:4193 return;4194 }4195 4196 llvm_unreachable("Invalid name kind?");4197 }4198 4199 void EmitDataBase(raw_ostream &Out, data_type Lookup, unsigned DataLen) {4200 using namespace llvm::support;4201 4202 endian::Writer LE(Out, llvm::endianness::little);4203 uint64_t Start = Out.tell(); (void)Start;4204 for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I)4205 LE.write<DeclID>((DeclID)DeclIDs[I]);4206 assert(Out.tell() - Start == DataLen && "Data length is wrong");4207 }4208};4209 4210class ModuleLevelNameLookupTrait : public ASTDeclContextNameLookupTraitBase {4211public:4212 using primary_module_hash_type = unsigned;4213 4214 using key_type = std::pair<DeclarationNameKey, primary_module_hash_type>;4215 using key_type_ref = key_type;4216 4217 explicit ModuleLevelNameLookupTrait(ASTWriter &Writer)4218 : ASTDeclContextNameLookupTraitBase(Writer) {}4219 4220 static bool EqualKey(key_type_ref a, key_type_ref b) { return a == b; }4221 4222 hash_value_type ComputeHash(key_type Key) {4223 llvm::FoldingSetNodeID ID;4224 ID.AddInteger(Key.first.getHash());4225 ID.AddInteger(Key.second);4226 return ID.computeStableHash();4227 }4228 4229 std::pair<unsigned, unsigned>4230 EmitKeyDataLength(raw_ostream &Out, key_type Key, data_type_ref Lookup) {4231 auto [KeyLen, DataLen] = EmitKeyDataLengthBase(Out, Key.first, Lookup);4232 KeyLen += sizeof(Key.second);4233 return emitULEBKeyDataLength(KeyLen, DataLen, Out);4234 }4235 4236 void EmitKey(raw_ostream &Out, key_type Key, unsigned) {4237 EmitKeyBase(Out, Key.first);4238 llvm::support::endian::Writer LE(Out, llvm::endianness::little);4239 LE.write<primary_module_hash_type>(Key.second);4240 }4241 4242 void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup,4243 unsigned DataLen) {4244 EmitDataBase(Out, Lookup, DataLen);4245 }4246};4247 4248class ASTDeclContextNameTrivialLookupTrait4249 : public ASTDeclContextNameLookupTraitBase {4250public:4251 using key_type = DeclarationNameKey;4252 using key_type_ref = key_type;4253 4254public:4255 using ASTDeclContextNameLookupTraitBase::ASTDeclContextNameLookupTraitBase;4256 4257 using ASTDeclContextNameLookupTraitBase::getData;4258 4259 static bool EqualKey(key_type_ref a, key_type_ref b) { return a == b; }4260 4261 hash_value_type ComputeHash(key_type Name) { return Name.getHash(); }4262 4263 std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out,4264 DeclarationNameKey Name,4265 data_type_ref Lookup) {4266 auto [KeyLen, DataLen] = EmitKeyDataLengthBase(Out, Name, Lookup);4267 return emitULEBKeyDataLength(KeyLen, DataLen, Out);4268 }4269 4270 void EmitKey(raw_ostream &Out, DeclarationNameKey Name, unsigned) {4271 return EmitKeyBase(Out, Name);4272 }4273 4274 void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup,4275 unsigned DataLen) {4276 EmitDataBase(Out, Lookup, DataLen);4277 }4278};4279 4280static bool isModuleLocalDecl(NamedDecl *D) {4281 // For decls not in a file context, they should have the same visibility4282 // with their parent.4283 if (auto *Parent = dyn_cast<NamedDecl>(D->getNonTransparentDeclContext());4284 Parent && !D->getNonTransparentDeclContext()->isFileContext())4285 return isModuleLocalDecl(Parent);4286 4287 // Deduction Guide are special here. Since their logical parent context are4288 // not their actual parent.4289 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))4290 if (auto *CDGD = dyn_cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl()))4291 return isModuleLocalDecl(CDGD->getDeducedTemplate());4292 4293 if (D->getFormalLinkage() != Linkage::Module)4294 return false;4295 4296 // It is hard for the serializer to judge if the in-class friend declaration4297 // is visible or not, so we just transfer the task to Sema. It should be a4298 // safe decision since Sema is able to handle the lookup rules for in-class4299 // friend declarations good enough already.4300 if (D->getFriendObjectKind() &&4301 isa<CXXRecordDecl>(D->getLexicalDeclContext()))4302 return false;4303 4304 return true;4305}4306 4307static bool isTULocalInNamedModules(NamedDecl *D) {4308 Module *NamedModule = D->getTopLevelOwningNamedModule();4309 if (!NamedModule)4310 return false;4311 4312 // For none-top level decls, we choose to move it to the general visible4313 // lookup table. Since the consumer may get its parent somehow and performs4314 // a lookup in it (considering looking up the operator function in lambda).4315 // The difference between module local lookup table and TU local lookup table4316 // is, the consumers still have a chance to lookup in the module local lookup4317 // table but **now** the consumers won't read the TU local lookup table if4318 // the consumer is not the original TU.4319 //4320 // FIXME: It seems to be an optimization chance (and also a more correct4321 // semantics) to remain the TULocal lookup table and performing similar lookup4322 // with the module local lookup table except that we only allow the lookups4323 // with the same module unit.4324 if (!D->getNonTransparentDeclContext()->isFileContext())4325 return false;4326 4327 return D->getLinkageInternal() == Linkage::Internal;4328}4329 4330class ASTDeclContextNameLookupTrait4331 : public ASTDeclContextNameTrivialLookupTrait {4332public:4333 using TULocalDeclsMapTy = llvm::DenseMap<key_type, DeclIDsTy>;4334 4335 using ModuleLevelDeclsMapTy =4336 llvm::DenseMap<ModuleLevelNameLookupTrait::key_type, DeclIDsTy>;4337 4338private:4339 enum class LookupVisibility {4340 GenerallyVisibile,4341 // The decls can only be found by other TU in the same module.4342 // Note a clang::Module models a module unit instead of logical module4343 // in C++20.4344 ModuleLocalVisible,4345 // The decls can only be found by the TU itself that defines it.4346 TULocal,4347 };4348 4349 LookupVisibility getLookupVisibility(NamedDecl *D) const {4350 // Only named modules have other lookup visibility.4351 if (!Writer.isWritingStdCXXNamedModules())4352 return LookupVisibility::GenerallyVisibile;4353 4354 if (isModuleLocalDecl(D))4355 return LookupVisibility::ModuleLocalVisible;4356 if (isTULocalInNamedModules(D))4357 return LookupVisibility::TULocal;4358 4359 // A trick to handle enum constants. The enum constants is special since4360 // they can be found directly without their parent context. This makes it4361 // tricky to decide if an EnumConstantDecl is visible or not by their own4362 // visibilities. E.g., for a class member, we can assume it is visible if4363 // the user get its parent somehow. But for an enum constant, the users may4364 // access if without its parent context. Although we can fix the problem in4365 // Sema lookup process, it might be too complex, we just make a trick here.4366 // Note that we only removes enum constant from the lookup table from its4367 // parent of parent. We DON'T remove the enum constant from its parent. So4368 // we don't need to care about merging problems here.4369 if (auto *ECD = dyn_cast<EnumConstantDecl>(D);4370 ECD && DC.isFileContext() && ECD->getTopLevelOwningNamedModule()) {4371 if (llvm::all_of(4372 DC.noload_lookup(4373 cast<EnumDecl>(ECD->getDeclContext())->getDeclName()),4374 [](auto *Found) {4375 return Found->isInvisibleOutsideTheOwningModule();4376 }))4377 return ECD->isFromExplicitGlobalModule() ||4378 ECD->isInAnonymousNamespace()4379 ? LookupVisibility::TULocal4380 : LookupVisibility::ModuleLocalVisible;4381 }4382 4383 return LookupVisibility::GenerallyVisibile;4384 }4385 4386 DeclContext &DC;4387 ModuleLevelDeclsMapTy ModuleLocalDeclsMap;4388 TULocalDeclsMapTy TULocalDeclsMap;4389 4390public:4391 using ASTDeclContextNameTrivialLookupTrait::4392 ASTDeclContextNameTrivialLookupTrait;4393 4394 ASTDeclContextNameLookupTrait(ASTWriter &Writer, DeclContext &DC)4395 : ASTDeclContextNameTrivialLookupTrait(Writer), DC(DC) {}4396 4397 template <typename Coll> data_type getData(const Coll &Decls) {4398 unsigned Start = DeclIDs.size();4399 for (NamedDecl *D : Decls) {4400 NamedDecl *DeclForLocalLookup =4401 getDeclForLocalLookup(Writer.getLangOpts(), D);4402 4403 if (Writer.getDoneWritingDeclsAndTypes() &&4404 !Writer.wasDeclEmitted(DeclForLocalLookup))4405 continue;4406 4407 // Try to avoid writing internal decls to reduced BMI.4408 // See comments in ASTWriter::WriteDeclContextLexicalBlock for details.4409 if (Writer.isGeneratingReducedBMI() &&4410 !DeclForLocalLookup->isFromExplicitGlobalModule() &&4411 IsInternalDeclFromFileContext(DeclForLocalLookup))4412 continue;4413 4414 auto ID = Writer.GetDeclRef(DeclForLocalLookup);4415 4416 switch (getLookupVisibility(DeclForLocalLookup)) {4417 case LookupVisibility::ModuleLocalVisible:4418 if (UnsignedOrNone PrimaryModuleHash =4419 getPrimaryModuleHash(D->getOwningModule())) {4420 auto Key = std::make_pair(D->getDeclName(), *PrimaryModuleHash);4421 auto Iter = ModuleLocalDeclsMap.find(Key);4422 if (Iter == ModuleLocalDeclsMap.end())4423 ModuleLocalDeclsMap.insert({Key, DeclIDsTy{ID}});4424 else4425 Iter->second.push_back(ID);4426 continue;4427 }4428 break;4429 case LookupVisibility::TULocal: {4430 auto Iter = TULocalDeclsMap.find(D->getDeclName());4431 if (Iter == TULocalDeclsMap.end())4432 TULocalDeclsMap.insert({D->getDeclName(), DeclIDsTy{ID}});4433 else4434 Iter->second.push_back(ID);4435 continue;4436 }4437 case LookupVisibility::GenerallyVisibile:4438 // Generally visible decls go into the general lookup table.4439 break;4440 }4441 4442 DeclIDs.push_back(ID);4443 }4444 return std::make_pair(Start, DeclIDs.size());4445 }4446 4447 const ModuleLevelDeclsMapTy &getModuleLocalDecls() {4448 return ModuleLocalDeclsMap;4449 }4450 4451 const TULocalDeclsMapTy &getTULocalDecls() { return TULocalDeclsMap; }4452};4453 4454} // namespace4455 4456namespace {4457class LazySpecializationInfoLookupTrait {4458 ASTWriter &Writer;4459 llvm::SmallVector<serialization::reader::LazySpecializationInfo, 64> Specs;4460 4461public:4462 using key_type = unsigned;4463 using key_type_ref = key_type;4464 4465 /// A start and end index into Specs, representing a sequence of decls.4466 using data_type = std::pair<unsigned, unsigned>;4467 using data_type_ref = const data_type &;4468 4469 using hash_value_type = unsigned;4470 using offset_type = unsigned;4471 4472 explicit LazySpecializationInfoLookupTrait(ASTWriter &Writer)4473 : Writer(Writer) {}4474 4475 template <typename Col, typename Col2>4476 data_type getData(Col &&C, Col2 &ExistingInfo) {4477 unsigned Start = Specs.size();4478 for (auto *D : C) {4479 NamedDecl *ND = getDeclForLocalLookup(Writer.getLangOpts(),4480 const_cast<NamedDecl *>(D));4481 Specs.push_back(GlobalDeclID(Writer.GetDeclRef(ND).getRawValue()));4482 }4483 for (const serialization::reader::LazySpecializationInfo &Info :4484 ExistingInfo)4485 Specs.push_back(Info);4486 return std::make_pair(Start, Specs.size());4487 }4488 4489 data_type ImportData(4490 const reader::LazySpecializationInfoLookupTrait::data_type &FromReader) {4491 unsigned Start = Specs.size();4492 for (auto ID : FromReader)4493 Specs.push_back(ID);4494 return std::make_pair(Start, Specs.size());4495 }4496 4497 static bool EqualKey(key_type_ref a, key_type_ref b) { return a == b; }4498 4499 hash_value_type ComputeHash(key_type Name) { return Name; }4500 4501 void EmitFileRef(raw_ostream &Out, ModuleFile *F) const {4502 assert(Writer.hasChain() &&4503 "have reference to loaded module file but no chain?");4504 4505 using namespace llvm::support;4506 Writer.addTouchedModuleFile(F);4507 endian::write<uint32_t>(Out, Writer.getChain()->getModuleFileID(F),4508 llvm::endianness::little);4509 }4510 4511 std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out,4512 key_type HashValue,4513 data_type_ref Lookup) {4514 // 4 bytes for each slot.4515 unsigned KeyLen = 4;4516 unsigned DataLen = sizeof(serialization::reader::LazySpecializationInfo) *4517 (Lookup.second - Lookup.first);4518 4519 return emitULEBKeyDataLength(KeyLen, DataLen, Out);4520 }4521 4522 void EmitKey(raw_ostream &Out, key_type HashValue, unsigned) {4523 using namespace llvm::support;4524 4525 endian::Writer LE(Out, llvm::endianness::little);4526 LE.write<uint32_t>(HashValue);4527 }4528 4529 void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup,4530 unsigned DataLen) {4531 using namespace llvm::support;4532 4533 endian::Writer LE(Out, llvm::endianness::little);4534 uint64_t Start = Out.tell();4535 (void)Start;4536 for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I) {4537 LE.write<DeclID>(Specs[I].getRawValue());4538 }4539 assert(Out.tell() - Start == DataLen && "Data length is wrong");4540 }4541};4542 4543unsigned CalculateODRHashForSpecs(const Decl *Spec) {4544 ArrayRef<TemplateArgument> Args;4545 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Spec))4546 Args = CTSD->getTemplateArgs().asArray();4547 else if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Spec))4548 Args = VTSD->getTemplateArgs().asArray();4549 else if (auto *FD = dyn_cast<FunctionDecl>(Spec))4550 Args = FD->getTemplateSpecializationArgs()->asArray();4551 else4552 llvm_unreachable("New Specialization Kind?");4553 4554 return StableHashForTemplateArguments(Args);4555}4556} // namespace4557 4558void ASTWriter::GenerateSpecializationInfoLookupTable(4559 const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,4560 llvm::SmallVectorImpl<char> &LookupTable, bool IsPartial) {4561 assert(D->isFirstDecl());4562 4563 // Create the on-disk hash table representation.4564 MultiOnDiskHashTableGenerator<reader::LazySpecializationInfoLookupTrait,4565 LazySpecializationInfoLookupTrait>4566 Generator;4567 LazySpecializationInfoLookupTrait Trait(*this);4568 4569 llvm::MapVector<unsigned, llvm::SmallVector<const NamedDecl *, 4>>4570 SpecializationMaps;4571 4572 for (auto *Specialization : Specializations) {4573 unsigned HashedValue = CalculateODRHashForSpecs(Specialization);4574 4575 auto Iter = SpecializationMaps.find(HashedValue);4576 if (Iter == SpecializationMaps.end())4577 Iter = SpecializationMaps4578 .try_emplace(HashedValue,4579 llvm::SmallVector<const NamedDecl *, 4>())4580 .first;4581 4582 Iter->second.push_back(cast<NamedDecl>(Specialization));4583 }4584 4585 auto *Lookups =4586 Chain ? Chain->getLoadedSpecializationsLookupTables(D, IsPartial)4587 : nullptr;4588 4589 for (auto &[HashValue, Specs] : SpecializationMaps) {4590 SmallVector<serialization::reader::LazySpecializationInfo, 16>4591 ExisitingSpecs;4592 // We have to merge the lookup table manually here. We can't depend on the4593 // merge mechanism offered by4594 // clang::serialization::MultiOnDiskHashTableGenerator since that generator4595 // assumes the we'll get the same value with the same key.4596 // And also underlying llvm::OnDiskChainedHashTableGenerator assumes that we4597 // won't insert the values with the same key twice. So we have to merge the4598 // lookup table here manually.4599 if (Lookups)4600 ExisitingSpecs = Lookups->Table.find(HashValue);4601 4602 Generator.insert(HashValue, Trait.getData(Specs, ExisitingSpecs), Trait);4603 }4604 4605 Generator.emit(LookupTable, Trait, Lookups ? &Lookups->Table : nullptr);4606}4607 4608uint64_t ASTWriter::WriteSpecializationInfoLookupTable(4609 const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,4610 bool IsPartial) {4611 4612 llvm::SmallString<4096> LookupTable;4613 GenerateSpecializationInfoLookupTable(D, Specializations, LookupTable,4614 IsPartial);4615 4616 uint64_t Offset = Stream.GetCurrentBitNo();4617 RecordData::value_type Record[] = {static_cast<RecordData::value_type>(4618 IsPartial ? DECL_PARTIAL_SPECIALIZATIONS : DECL_SPECIALIZATIONS)};4619 Stream.EmitRecordWithBlob(IsPartial ? DeclPartialSpecializationsAbbrev4620 : DeclSpecializationsAbbrev,4621 Record, LookupTable);4622 4623 return Offset;4624}4625 4626/// Returns ture if all of the lookup result are either external, not emitted or4627/// predefined. In such cases, the lookup result is not interesting and we don't4628/// need to record the result in the current being written module. Return false4629/// otherwise.4630static bool isLookupResultNotInteresting(ASTWriter &Writer,4631 StoredDeclsList &Result) {4632 for (auto *D : Result.getLookupResult()) {4633 auto *LocalD = getDeclForLocalLookup(Writer.getLangOpts(), D);4634 if (LocalD->isFromASTFile())4635 continue;4636 4637 // We can only be sure whether the local declaration is reachable4638 // after we done writing the declarations and types.4639 if (Writer.getDoneWritingDeclsAndTypes() && !Writer.wasDeclEmitted(LocalD))4640 continue;4641 4642 // We don't need to emit the predefined decls.4643 if (Writer.isDeclPredefined(LocalD))4644 continue;4645 4646 return false;4647 }4648 4649 return true;4650}4651 4652void ASTWriter::GenerateNameLookupTable(4653 ASTContext &Context, const DeclContext *ConstDC,4654 llvm::SmallVectorImpl<char> &LookupTable,4655 llvm::SmallVectorImpl<char> &ModuleLocalLookupTable,4656 llvm::SmallVectorImpl<char> &TULookupTable) {4657 assert(!ConstDC->hasLazyLocalLexicalLookups() &&4658 !ConstDC->hasLazyExternalLexicalLookups() &&4659 "must call buildLookups first");4660 4661 // FIXME: We need to build the lookups table, which is logically const.4662 auto *DC = const_cast<DeclContext*>(ConstDC);4663 assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table");4664 4665 // Create the on-disk hash table representation.4666 MultiOnDiskHashTableGenerator<reader::ASTDeclContextNameLookupTrait,4667 ASTDeclContextNameLookupTrait>4668 Generator;4669 ASTDeclContextNameLookupTrait Trait(*this, *DC);4670 4671 // The first step is to collect the declaration names which we need to4672 // serialize into the name lookup table, and to collect them in a stable4673 // order.4674 SmallVector<DeclarationName, 16> Names;4675 4676 // We also track whether we're writing out the DeclarationNameKey for4677 // constructors or conversion functions.4678 bool IncludeConstructorNames = false;4679 bool IncludeConversionNames = false;4680 4681 for (auto &[Name, Result] : *DC->buildLookup()) {4682 // If there are no local declarations in our lookup result, we4683 // don't need to write an entry for the name at all. If we can't4684 // write out a lookup set without performing more deserialization,4685 // just skip this entry.4686 //4687 // Also in reduced BMI, we'd like to avoid writing unreachable4688 // declarations in GMF, so we need to avoid writing declarations4689 // that entirely external or unreachable.4690 if (GeneratingReducedBMI && isLookupResultNotInteresting(*this, Result))4691 continue;4692 // We also skip empty results. If any of the results could be external and4693 // the currently available results are empty, then all of the results are4694 // external and we skip it above. So the only way we get here with an empty4695 // results is when no results could have been external *and* we have4696 // external results.4697 //4698 // FIXME: While we might want to start emitting on-disk entries for negative4699 // lookups into a decl context as an optimization, today we *have* to skip4700 // them because there are names with empty lookup results in decl contexts4701 // which we can't emit in any stable ordering: we lookup constructors and4702 // conversion functions in the enclosing namespace scope creating empty4703 // results for them. This in almost certainly a bug in Clang's name lookup,4704 // but that is likely to be hard or impossible to fix and so we tolerate it4705 // here by omitting lookups with empty results.4706 if (Result.getLookupResult().empty())4707 continue;4708 4709 switch (Name.getNameKind()) {4710 default:4711 Names.push_back(Name);4712 break;4713 4714 case DeclarationName::CXXConstructorName:4715 IncludeConstructorNames = true;4716 break;4717 4718 case DeclarationName::CXXConversionFunctionName:4719 IncludeConversionNames = true;4720 break;4721 }4722 }4723 4724 // Sort the names into a stable order.4725 llvm::sort(Names);4726 4727 if (IncludeConstructorNames || IncludeConversionNames) {4728 // We need to establish an ordering of constructor and conversion function4729 // names, and they don't have an intrinsic ordering. We also need to write4730 // out all constructor and conversion function results if we write out any4731 // of them, because they're all tracked under the same lookup key.4732 llvm::SmallPtrSet<DeclarationName, 8> AddedNames;4733 for (Decl *ChildD : cast<CXXRecordDecl>(DC)->decls()) {4734 if (auto *ChildND = dyn_cast<NamedDecl>(ChildD)) {4735 auto Name = ChildND->getDeclName();4736 switch (Name.getNameKind()) {4737 default:4738 continue;4739 4740 case DeclarationName::CXXConstructorName:4741 if (!IncludeConstructorNames)4742 continue;4743 break;4744 4745 case DeclarationName::CXXConversionFunctionName:4746 if (!IncludeConversionNames)4747 continue;4748 break;4749 }4750 if (AddedNames.insert(Name).second)4751 Names.push_back(Name);4752 }4753 }4754 }4755 // Next we need to do a lookup with each name into this decl context to fully4756 // populate any results from external sources. We don't actually use the4757 // results of these lookups because we only want to use the results after all4758 // results have been loaded and the pointers into them will be stable.4759 for (auto &Name : Names)4760 DC->lookup(Name);4761 4762 // Now we need to insert the results for each name into the hash table. For4763 // constructor names and conversion function names, we actually need to merge4764 // all of the results for them into one list of results each and insert4765 // those.4766 SmallVector<NamedDecl *, 8> ConstructorDecls;4767 SmallVector<NamedDecl *, 8> ConversionDecls;4768 4769 // Now loop over the names, either inserting them or appending for the two4770 // special cases.4771 for (auto &Name : Names) {4772 DeclContext::lookup_result Result = DC->noload_lookup(Name);4773 4774 switch (Name.getNameKind()) {4775 default:4776 Generator.insert(Name, Trait.getData(Result), Trait);4777 break;4778 4779 case DeclarationName::CXXConstructorName:4780 ConstructorDecls.append(Result.begin(), Result.end());4781 break;4782 4783 case DeclarationName::CXXConversionFunctionName:4784 ConversionDecls.append(Result.begin(), Result.end());4785 break;4786 }4787 }4788 4789 // Handle our two special cases if we ended up having any. We arbitrarily use4790 // the first declaration's name here because the name itself isn't part of4791 // the key, only the kind of name is used.4792 if (!ConstructorDecls.empty())4793 Generator.insert(ConstructorDecls.front()->getDeclName(),4794 Trait.getData(ConstructorDecls), Trait);4795 if (!ConversionDecls.empty())4796 Generator.insert(ConversionDecls.front()->getDeclName(),4797 Trait.getData(ConversionDecls), Trait);4798 4799 // Create the on-disk hash table. Also emit the existing imported and4800 // merged table if there is one.4801 auto *Lookups = Chain ? Chain->getLoadedLookupTables(DC) : nullptr;4802 Generator.emit(LookupTable, Trait, Lookups ? &Lookups->Table : nullptr);4803 4804 const auto &ModuleLocalDecls = Trait.getModuleLocalDecls();4805 if (!ModuleLocalDecls.empty()) {4806 MultiOnDiskHashTableGenerator<reader::ModuleLocalNameLookupTrait,4807 ModuleLevelNameLookupTrait>4808 ModuleLocalLookupGenerator;4809 ModuleLevelNameLookupTrait ModuleLocalTrait(*this);4810 4811 for (const auto &ModuleLocalIter : ModuleLocalDecls) {4812 const auto &Key = ModuleLocalIter.first;4813 const auto &IDs = ModuleLocalIter.second;4814 ModuleLocalLookupGenerator.insert(Key, ModuleLocalTrait.getData(IDs),4815 ModuleLocalTrait);4816 }4817 4818 auto *ModuleLocalLookups =4819 Chain ? Chain->getModuleLocalLookupTables(DC) : nullptr;4820 ModuleLocalLookupGenerator.emit(4821 ModuleLocalLookupTable, ModuleLocalTrait,4822 ModuleLocalLookups ? &ModuleLocalLookups->Table : nullptr);4823 }4824 4825 const auto &TULocalDecls = Trait.getTULocalDecls();4826 if (!TULocalDecls.empty() && !isGeneratingReducedBMI()) {4827 MultiOnDiskHashTableGenerator<reader::ASTDeclContextNameLookupTrait,4828 ASTDeclContextNameTrivialLookupTrait>4829 TULookupGenerator;4830 ASTDeclContextNameTrivialLookupTrait TULocalTrait(*this);4831 4832 for (const auto &TULocalIter : TULocalDecls) {4833 const auto &Key = TULocalIter.first;4834 const auto &IDs = TULocalIter.second;4835 TULookupGenerator.insert(Key, TULocalTrait.getData(IDs), TULocalTrait);4836 }4837 4838 auto *TULocalLookups = Chain ? Chain->getTULocalLookupTables(DC) : nullptr;4839 TULookupGenerator.emit(TULookupTable, TULocalTrait,4840 TULocalLookups ? &TULocalLookups->Table : nullptr);4841 }4842}4843 4844/// Write the block containing all of the declaration IDs4845/// visible from the given DeclContext.4846///4847/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the4848/// bitstream, or 0 if no block was written.4849void ASTWriter::WriteDeclContextVisibleBlock(4850 ASTContext &Context, DeclContext *DC, VisibleLookupBlockOffsets &Offsets) {4851 assert(!Offsets);4852 4853 // If we imported a key declaration of this namespace, write the visible4854 // lookup results as an update record for it rather than including them4855 // on this declaration. We will only look at key declarations on reload.4856 if (isa<NamespaceDecl>(DC) && Chain &&4857 Chain->getKeyDeclaration(cast<Decl>(DC))->isFromASTFile()) {4858 // Only do this once, for the first local declaration of the namespace.4859 for (auto *Prev = cast<NamespaceDecl>(DC)->getPreviousDecl(); Prev;4860 Prev = Prev->getPreviousDecl())4861 if (!Prev->isFromASTFile())4862 return;4863 4864 // Note that we need to emit an update record for the primary context.4865 UpdatedDeclContexts.insert(DC->getPrimaryContext());4866 4867 // Make sure all visible decls are written. They will be recorded later. We4868 // do this using a side data structure so we can sort the names into4869 // a deterministic order.4870 StoredDeclsMap *Map = DC->getPrimaryContext()->buildLookup();4871 SmallVector<std::pair<DeclarationName, DeclContext::lookup_result>, 16>4872 LookupResults;4873 if (Map) {4874 LookupResults.reserve(Map->size());4875 for (auto &Entry : *Map)4876 LookupResults.push_back(4877 std::make_pair(Entry.first, Entry.second.getLookupResult()));4878 }4879 4880 llvm::sort(LookupResults, llvm::less_first());4881 for (auto &NameAndResult : LookupResults) {4882 DeclarationName Name = NameAndResult.first;4883 DeclContext::lookup_result Result = NameAndResult.second;4884 if (Name.getNameKind() == DeclarationName::CXXConstructorName ||4885 Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {4886 // We have to work around a name lookup bug here where negative lookup4887 // results for these names get cached in namespace lookup tables (these4888 // names should never be looked up in a namespace).4889 assert(Result.empty() && "Cannot have a constructor or conversion "4890 "function name in a namespace!");4891 continue;4892 }4893 4894 for (NamedDecl *ND : Result) {4895 if (ND->isFromASTFile())4896 continue;4897 4898 if (DoneWritingDeclsAndTypes && !wasDeclEmitted(ND))4899 continue;4900 4901 // We don't need to force emitting internal decls into reduced BMI.4902 // See comments in ASTWriter::WriteDeclContextLexicalBlock for details.4903 if (GeneratingReducedBMI && !ND->isFromExplicitGlobalModule() &&4904 IsInternalDeclFromFileContext(ND))4905 continue;4906 4907 GetDeclRef(ND);4908 }4909 }4910 4911 return;4912 }4913 4914 if (DC->getPrimaryContext() != DC)4915 return;4916 4917 // Skip contexts which don't support name lookup.4918 if (!DC->isLookupContext())4919 return;4920 4921 // If not in C++, we perform name lookup for the translation unit via the4922 // IdentifierInfo chains, don't bother to build a visible-declarations table.4923 if (DC->isTranslationUnit() && !Context.getLangOpts().CPlusPlus)4924 return;4925 4926 // Serialize the contents of the mapping used for lookup. Note that,4927 // although we have two very different code paths, the serialized4928 // representation is the same for both cases: a declaration name,4929 // followed by a size, followed by references to the visible4930 // declarations that have that name.4931 StoredDeclsMap *Map = DC->buildLookup();4932 if (!Map || Map->empty())4933 return;4934 4935 Offsets.VisibleOffset = Stream.GetCurrentBitNo();4936 // Create the on-disk hash table in a buffer.4937 SmallString<4096> LookupTable;4938 SmallString<4096> ModuleLocalLookupTable;4939 SmallString<4096> TULookupTable;4940 GenerateNameLookupTable(Context, DC, LookupTable, ModuleLocalLookupTable,4941 TULookupTable);4942 4943 // Write the lookup table4944 RecordData::value_type Record[] = {DECL_CONTEXT_VISIBLE};4945 Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record,4946 LookupTable);4947 ++NumVisibleDeclContexts;4948 4949 if (!ModuleLocalLookupTable.empty()) {4950 Offsets.ModuleLocalOffset = Stream.GetCurrentBitNo();4951 assert(Offsets.ModuleLocalOffset > Offsets.VisibleOffset);4952 // Write the lookup table4953 RecordData::value_type ModuleLocalRecord[] = {4954 DECL_CONTEXT_MODULE_LOCAL_VISIBLE};4955 Stream.EmitRecordWithBlob(DeclModuleLocalVisibleLookupAbbrev,4956 ModuleLocalRecord, ModuleLocalLookupTable);4957 ++NumModuleLocalDeclContexts;4958 }4959 4960 if (!TULookupTable.empty()) {4961 Offsets.TULocalOffset = Stream.GetCurrentBitNo();4962 // Write the lookup table4963 RecordData::value_type TULocalDeclsRecord[] = {4964 DECL_CONTEXT_TU_LOCAL_VISIBLE};4965 Stream.EmitRecordWithBlob(DeclTULocalLookupAbbrev, TULocalDeclsRecord,4966 TULookupTable);4967 ++NumTULocalDeclContexts;4968 }4969}4970 4971/// Write an UPDATE_VISIBLE block for the given context.4972///4973/// UPDATE_VISIBLE blocks contain the declarations that are added to an existing4974/// DeclContext in a dependent AST file. As such, they only exist for the TU4975/// (in C++), for namespaces, and for classes with forward-declared unscoped4976/// enumeration members (in C++11).4977void ASTWriter::WriteDeclContextVisibleUpdate(ASTContext &Context,4978 const DeclContext *DC) {4979 StoredDeclsMap *Map = DC->getLookupPtr();4980 if (!Map || Map->empty())4981 return;4982 4983 // Create the on-disk hash table in a buffer.4984 SmallString<4096> LookupTable;4985 SmallString<4096> ModuleLocalLookupTable;4986 SmallString<4096> TULookupTable;4987 GenerateNameLookupTable(Context, DC, LookupTable, ModuleLocalLookupTable,4988 TULookupTable);4989 4990 // If we're updating a namespace, select a key declaration as the key for the4991 // update record; those are the only ones that will be checked on reload.4992 if (isa<NamespaceDecl>(DC))4993 DC = cast<DeclContext>(Chain->getKeyDeclaration(cast<Decl>(DC)));4994 4995 // Write the lookup table4996 RecordData::value_type Record[] = {UPDATE_VISIBLE,4997 getDeclID(cast<Decl>(DC)).getRawValue()};4998 Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable);4999 5000 if (!ModuleLocalLookupTable.empty()) {5001 // Write the module local lookup table5002 RecordData::value_type ModuleLocalRecord[] = {5003 UPDATE_MODULE_LOCAL_VISIBLE, getDeclID(cast<Decl>(DC)).getRawValue()};5004 Stream.EmitRecordWithBlob(ModuleLocalUpdateVisibleAbbrev, ModuleLocalRecord,5005 ModuleLocalLookupTable);5006 }5007 5008 if (!TULookupTable.empty()) {5009 RecordData::value_type GMFRecord[] = {5010 UPDATE_TU_LOCAL_VISIBLE, getDeclID(cast<Decl>(DC)).getRawValue()};5011 Stream.EmitRecordWithBlob(TULocalUpdateVisibleAbbrev, GMFRecord,5012 TULookupTable);5013 }5014}5015 5016/// Write an FP_PRAGMA_OPTIONS block for the given FPOptions.5017void ASTWriter::WriteFPPragmaOptions(const FPOptionsOverride &Opts) {5018 RecordData::value_type Record[] = {Opts.getAsOpaqueInt()};5019 Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record);5020}5021 5022/// Write an OPENCL_EXTENSIONS block for the given OpenCLOptions.5023void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {5024 if (!SemaRef.Context.getLangOpts().OpenCL)5025 return;5026 5027 const OpenCLOptions &Opts = SemaRef.getOpenCLOptions();5028 RecordData Record;5029 for (const auto &I:Opts.OptMap) {5030 AddString(I.getKey(), Record);5031 auto V = I.getValue();5032 Record.push_back(V.Supported ? 1 : 0);5033 Record.push_back(V.Enabled ? 1 : 0);5034 Record.push_back(V.WithPragma ? 1 : 0);5035 Record.push_back(V.Avail);5036 Record.push_back(V.Core);5037 Record.push_back(V.Opt);5038 }5039 Stream.EmitRecord(OPENCL_EXTENSIONS, Record);5040}5041void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) {5042 if (SemaRef.CUDA().ForceHostDeviceDepth > 0) {5043 RecordData::value_type Record[] = {SemaRef.CUDA().ForceHostDeviceDepth};5044 Stream.EmitRecord(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH, Record);5045 }5046}5047 5048void ASTWriter::WriteObjCCategories() {5049 if (ObjCClassesWithCategories.empty())5050 return;5051 5052 SmallVector<ObjCCategoriesInfo, 2> CategoriesMap;5053 RecordData Categories;5054 5055 for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) {5056 unsigned Size = 0;5057 unsigned StartIndex = Categories.size();5058 5059 ObjCInterfaceDecl *Class = ObjCClassesWithCategories[I];5060 5061 // Allocate space for the size.5062 Categories.push_back(0);5063 5064 // Add the categories.5065 for (ObjCInterfaceDecl::known_categories_iterator5066 Cat = Class->known_categories_begin(),5067 CatEnd = Class->known_categories_end();5068 Cat != CatEnd; ++Cat, ++Size) {5069 assert(getDeclID(*Cat).isValid() && "Bogus category");5070 AddDeclRef(*Cat, Categories);5071 }5072 5073 // Update the size.5074 Categories[StartIndex] = Size;5075 5076 // Record this interface -> category map.5077 ObjCCategoriesInfo CatInfo = { getDeclID(Class), StartIndex };5078 CategoriesMap.push_back(CatInfo);5079 }5080 5081 // Sort the categories map by the definition ID, since the reader will be5082 // performing binary searches on this information.5083 llvm::array_pod_sort(CategoriesMap.begin(), CategoriesMap.end());5084 5085 // Emit the categories map.5086 using namespace llvm;5087 5088 auto Abbrev = std::make_shared<BitCodeAbbrev>();5089 Abbrev->Add(BitCodeAbbrevOp(OBJC_CATEGORIES_MAP));5090 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries5091 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));5092 unsigned AbbrevID = Stream.EmitAbbrev(std::move(Abbrev));5093 5094 RecordData::value_type Record[] = {OBJC_CATEGORIES_MAP, CategoriesMap.size()};5095 Stream.EmitRecordWithBlob(AbbrevID, Record,5096 reinterpret_cast<char *>(CategoriesMap.data()),5097 CategoriesMap.size() * sizeof(ObjCCategoriesInfo));5098 5099 // Emit the category lists.5100 Stream.EmitRecord(OBJC_CATEGORIES, Categories);5101}5102 5103void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) {5104 Sema::LateParsedTemplateMapT &LPTMap = SemaRef.LateParsedTemplateMap;5105 5106 if (LPTMap.empty())5107 return;5108 5109 RecordData Record;5110 for (auto &LPTMapEntry : LPTMap) {5111 const FunctionDecl *FD = LPTMapEntry.first;5112 LateParsedTemplate &LPT = *LPTMapEntry.second;5113 AddDeclRef(FD, Record);5114 AddDeclRef(LPT.D, Record);5115 Record.push_back(LPT.FPO.getAsOpaqueInt());5116 Record.push_back(LPT.Toks.size());5117 5118 for (const auto &Tok : LPT.Toks) {5119 AddToken(Tok, Record);5120 }5121 }5122 Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record);5123}5124 5125/// Write the state of 'pragma clang optimize' at the end of the module.5126void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) {5127 RecordData Record;5128 SourceLocation PragmaLoc = SemaRef.getOptimizeOffPragmaLocation();5129 AddSourceLocation(PragmaLoc, Record);5130 Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record);5131}5132 5133/// Write the state of 'pragma ms_struct' at the end of the module.5134void ASTWriter::WriteMSStructPragmaOptions(Sema &SemaRef) {5135 RecordData Record;5136 Record.push_back(SemaRef.MSStructPragmaOn ? PMSST_ON : PMSST_OFF);5137 Stream.EmitRecord(MSSTRUCT_PRAGMA_OPTIONS, Record);5138}5139 5140/// Write the state of 'pragma pointers_to_members' at the end of the5141//module.5142void ASTWriter::WriteMSPointersToMembersPragmaOptions(Sema &SemaRef) {5143 RecordData Record;5144 Record.push_back(SemaRef.MSPointerToMemberRepresentationMethod);5145 AddSourceLocation(SemaRef.ImplicitMSInheritanceAttrLoc, Record);5146 Stream.EmitRecord(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS, Record);5147}5148 5149/// Write the state of 'pragma align/pack' at the end of the module.5150void ASTWriter::WritePackPragmaOptions(Sema &SemaRef) {5151 // Don't serialize pragma align/pack state for modules, since it should only5152 // take effect on a per-submodule basis.5153 if (WritingModule)5154 return;5155 5156 RecordData Record;5157 AddAlignPackInfo(SemaRef.AlignPackStack.CurrentValue, Record);5158 AddSourceLocation(SemaRef.AlignPackStack.CurrentPragmaLocation, Record);5159 Record.push_back(SemaRef.AlignPackStack.Stack.size());5160 for (const auto &StackEntry : SemaRef.AlignPackStack.Stack) {5161 AddAlignPackInfo(StackEntry.Value, Record);5162 AddSourceLocation(StackEntry.PragmaLocation, Record);5163 AddSourceLocation(StackEntry.PragmaPushLocation, Record);5164 AddString(StackEntry.StackSlotLabel, Record);5165 }5166 Stream.EmitRecord(ALIGN_PACK_PRAGMA_OPTIONS, Record);5167}5168 5169/// Write the state of 'pragma float_control' at the end of the module.5170void ASTWriter::WriteFloatControlPragmaOptions(Sema &SemaRef) {5171 // Don't serialize pragma float_control state for modules,5172 // since it should only take effect on a per-submodule basis.5173 if (WritingModule)5174 return;5175 5176 RecordData Record;5177 Record.push_back(SemaRef.FpPragmaStack.CurrentValue.getAsOpaqueInt());5178 AddSourceLocation(SemaRef.FpPragmaStack.CurrentPragmaLocation, Record);5179 Record.push_back(SemaRef.FpPragmaStack.Stack.size());5180 for (const auto &StackEntry : SemaRef.FpPragmaStack.Stack) {5181 Record.push_back(StackEntry.Value.getAsOpaqueInt());5182 AddSourceLocation(StackEntry.PragmaLocation, Record);5183 AddSourceLocation(StackEntry.PragmaPushLocation, Record);5184 AddString(StackEntry.StackSlotLabel, Record);5185 }5186 Stream.EmitRecord(FLOAT_CONTROL_PRAGMA_OPTIONS, Record);5187}5188 5189/// Write Sema's collected list of declarations with unverified effects.5190void ASTWriter::WriteDeclsWithEffectsToVerify(Sema &SemaRef) {5191 if (SemaRef.DeclsWithEffectsToVerify.empty())5192 return;5193 RecordData Record;5194 for (const auto *D : SemaRef.DeclsWithEffectsToVerify) {5195 AddDeclRef(D, Record);5196 }5197 Stream.EmitRecord(DECLS_WITH_EFFECTS_TO_VERIFY, Record);5198}5199 5200void ASTWriter::WriteModuleFileExtension(Sema &SemaRef,5201 ModuleFileExtensionWriter &Writer) {5202 // Enter the extension block.5203 Stream.EnterSubblock(EXTENSION_BLOCK_ID, 4);5204 5205 // Emit the metadata record abbreviation.5206 auto Abv = std::make_shared<llvm::BitCodeAbbrev>();5207 Abv->Add(llvm::BitCodeAbbrevOp(EXTENSION_METADATA));5208 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));5209 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));5210 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));5211 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));5212 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));5213 unsigned Abbrev = Stream.EmitAbbrev(std::move(Abv));5214 5215 // Emit the metadata record.5216 RecordData Record;5217 auto Metadata = Writer.getExtension()->getExtensionMetadata();5218 Record.push_back(EXTENSION_METADATA);5219 Record.push_back(Metadata.MajorVersion);5220 Record.push_back(Metadata.MinorVersion);5221 Record.push_back(Metadata.BlockName.size());5222 Record.push_back(Metadata.UserInfo.size());5223 SmallString<64> Buffer;5224 Buffer += Metadata.BlockName;5225 Buffer += Metadata.UserInfo;5226 Stream.EmitRecordWithBlob(Abbrev, Record, Buffer);5227 5228 // Emit the contents of the extension block.5229 Writer.writeExtensionContents(SemaRef, Stream);5230 5231 // Exit the extension block.5232 Stream.ExitBlock();5233}5234 5235//===----------------------------------------------------------------------===//5236// General Serialization Routines5237//===----------------------------------------------------------------------===//5238 5239void ASTRecordWriter::AddAttr(const Attr *A) {5240 auto &Record = *this;5241 // FIXME: Clang can't handle the serialization/deserialization of5242 // preferred_name properly now. See5243 // https://github.com/llvm/llvm-project/issues/56490 for example.5244 if (!A ||5245 (isa<PreferredNameAttr>(A) && (Writer->isWritingStdCXXNamedModules() ||5246 Writer->isWritingStdCXXHeaderUnit())))5247 return Record.push_back(0);5248 5249 Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs5250 5251 Record.AddIdentifierRef(A->getAttrName());5252 Record.AddIdentifierRef(A->getScopeName());5253 Record.AddSourceRange(A->getRange());5254 Record.AddSourceLocation(A->getScopeLoc());5255 Record.push_back(A->getParsedKind());5256 Record.push_back(A->getSyntax());5257 Record.push_back(A->getAttributeSpellingListIndexRaw());5258 Record.push_back(A->isRegularKeywordAttribute());5259 5260#include "clang/Serialization/AttrPCHWrite.inc"5261}5262 5263/// Emit the list of attributes to the specified record.5264void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {5265 push_back(Attrs.size());5266 for (const auto *A : Attrs)5267 AddAttr(A);5268}5269 5270void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) {5271 AddSourceLocation(Tok.getLocation(), Record);5272 // FIXME: Should translate token kind to a stable encoding.5273 Record.push_back(Tok.getKind());5274 // FIXME: Should translate token flags to a stable encoding.5275 Record.push_back(Tok.getFlags());5276 5277 if (Tok.isAnnotation()) {5278 AddSourceLocation(Tok.getAnnotationEndLoc(), Record);5279 switch (Tok.getKind()) {5280 case tok::annot_pragma_loop_hint: {5281 auto *Info = static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());5282 AddToken(Info->PragmaName, Record);5283 AddToken(Info->Option, Record);5284 Record.push_back(Info->Toks.size());5285 for (const auto &T : Info->Toks)5286 AddToken(T, Record);5287 break;5288 }5289 case tok::annot_pragma_pack: {5290 auto *Info =5291 static_cast<Sema::PragmaPackInfo *>(Tok.getAnnotationValue());5292 Record.push_back(static_cast<unsigned>(Info->Action));5293 AddString(Info->SlotLabel, Record);5294 AddToken(Info->Alignment, Record);5295 break;5296 }5297 // Some annotation tokens do not use the PtrData field.5298 case tok::annot_pragma_openmp:5299 case tok::annot_pragma_openmp_end:5300 case tok::annot_pragma_unused:5301 case tok::annot_pragma_openacc:5302 case tok::annot_pragma_openacc_end:5303 case tok::annot_repl_input_end:5304 break;5305 default:5306 llvm_unreachable("missing serialization code for annotation token");5307 }5308 } else {5309 Record.push_back(Tok.getLength());5310 // FIXME: When reading literal tokens, reconstruct the literal pointer if it5311 // is needed.5312 AddIdentifierRef(Tok.getIdentifierInfo(), Record);5313 }5314}5315 5316void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) {5317 Record.push_back(Str.size());5318 llvm::append_range(Record, Str);5319}5320 5321void ASTWriter::AddStringBlob(StringRef Str, RecordDataImpl &Record,5322 SmallVectorImpl<char> &Blob) {5323 Record.push_back(Str.size());5324 llvm::append_range(Blob, Str);5325}5326 5327bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) {5328 assert(WritingAST && "can't prepare path for output when not writing AST");5329 5330 // Leave special file names as they are.5331 StringRef PathStr(Path.data(), Path.size());5332 if (PathStr == "<built-in>" || PathStr == "<command line>")5333 return false;5334 5335 bool Changed = cleanPathForOutput(PP->getFileManager(), Path);5336 5337 // Remove a prefix to make the path relative, if relevant.5338 const char *PathBegin = Path.data();5339 const char *PathPtr =5340 adjustFilenameForRelocatableAST(PathBegin, BaseDirectory);5341 if (PathPtr != PathBegin) {5342 Path.erase(Path.begin(), Path.begin() + (PathPtr - PathBegin));5343 Changed = true;5344 }5345 5346 return Changed;5347}5348 5349void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) {5350 SmallString<128> FilePath(Path);5351 PreparePathForOutput(FilePath);5352 AddString(FilePath, Record);5353}5354 5355void ASTWriter::AddPathBlob(StringRef Path, RecordDataImpl &Record,5356 SmallVectorImpl<char> &Blob) {5357 SmallString<128> FilePath(Path);5358 PreparePathForOutput(FilePath);5359 AddStringBlob(FilePath, Record, Blob);5360}5361 5362void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record,5363 StringRef Path) {5364 SmallString<128> FilePath(Path);5365 PreparePathForOutput(FilePath);5366 Stream.EmitRecordWithBlob(Abbrev, Record, FilePath);5367}5368 5369void ASTWriter::AddVersionTuple(const VersionTuple &Version,5370 RecordDataImpl &Record) {5371 Record.push_back(Version.getMajor());5372 if (std::optional<unsigned> Minor = Version.getMinor())5373 Record.push_back(*Minor + 1);5374 else5375 Record.push_back(0);5376 if (std::optional<unsigned> Subminor = Version.getSubminor())5377 Record.push_back(*Subminor + 1);5378 else5379 Record.push_back(0);5380}5381 5382/// Note that the identifier II occurs at the given offset5383/// within the identifier table.5384void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {5385 IdentifierID ID = IdentifierIDs[II];5386 // Only store offsets new to this AST file. Other identifier names are looked5387 // up earlier in the chain and thus don't need an offset.5388 if (!isLocalIdentifierID(ID))5389 return;5390 5391 // For local identifiers, the module file index must be 0.5392 5393 assert(ID != 0);5394 ID -= NUM_PREDEF_IDENT_IDS;5395 assert(ID < IdentifierOffsets.size());5396 IdentifierOffsets[ID] = Offset;5397}5398 5399/// Note that the selector Sel occurs at the given offset5400/// within the method pool/selector table.5401void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {5402 unsigned ID = SelectorIDs[Sel];5403 assert(ID && "Unknown selector");5404 // Don't record offsets for selectors that are also available in a different5405 // file.5406 if (ID < FirstSelectorID)5407 return;5408 SelectorOffsets[ID - FirstSelectorID] = Offset;5409}5410 5411ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream,5412 SmallVectorImpl<char> &Buffer, ModuleCache &ModCache,5413 const CodeGenOptions &CodeGenOpts,5414 ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,5415 bool IncludeTimestamps, bool BuildingImplicitModule,5416 bool GeneratingReducedBMI)5417 : Stream(Stream), Buffer(Buffer), ModCache(ModCache),5418 CodeGenOpts(CodeGenOpts), IncludeTimestamps(IncludeTimestamps),5419 BuildingImplicitModule(BuildingImplicitModule),5420 GeneratingReducedBMI(GeneratingReducedBMI) {5421 for (const auto &Ext : Extensions) {5422 if (auto Writer = Ext->createExtensionWriter(*this))5423 ModuleFileExtensionWriters.push_back(std::move(Writer));5424 }5425}5426 5427ASTWriter::~ASTWriter() = default;5428 5429const LangOptions &ASTWriter::getLangOpts() const {5430 assert(WritingAST && "can't determine lang opts when not writing AST");5431 return PP->getLangOpts();5432}5433 5434time_t ASTWriter::getTimestampForOutput(const FileEntry *E) const {5435 return IncludeTimestamps ? E->getModificationTime() : 0;5436}5437 5438ASTFileSignature5439ASTWriter::WriteAST(llvm::PointerUnion<Sema *, Preprocessor *> Subject,5440 StringRef OutputFile, Module *WritingModule,5441 StringRef isysroot, bool ShouldCacheASTInMemory) {5442 llvm::TimeTraceScope scope("WriteAST", OutputFile);5443 WritingAST = true;5444 5445 Sema *SemaPtr = dyn_cast<Sema *>(Subject);5446 Preprocessor &PPRef =5447 SemaPtr ? SemaPtr->getPreprocessor() : *cast<Preprocessor *>(Subject);5448 5449 ASTHasCompilerErrors = PPRef.getDiagnostics().hasUncompilableErrorOccurred();5450 5451 // Emit the file header.5452 Stream.Emit((unsigned)'C', 8);5453 Stream.Emit((unsigned)'P', 8);5454 Stream.Emit((unsigned)'C', 8);5455 Stream.Emit((unsigned)'H', 8);5456 5457 WriteBlockInfoBlock();5458 5459 PP = &PPRef;5460 this->WritingModule = WritingModule;5461 ASTFileSignature Signature = WriteASTCore(SemaPtr, isysroot, WritingModule);5462 PP = nullptr;5463 this->WritingModule = nullptr;5464 this->BaseDirectory.clear();5465 5466 WritingAST = false;5467 5468 if (ShouldCacheASTInMemory) {5469 // Construct MemoryBuffer and update buffer manager.5470 ModCache.getInMemoryModuleCache().addBuiltPCM(5471 OutputFile, llvm::MemoryBuffer::getMemBufferCopy(5472 StringRef(Buffer.begin(), Buffer.size())));5473 }5474 return Signature;5475}5476 5477template<typename Vector>5478static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec) {5479 for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end();5480 I != E; ++I) {5481 Writer.GetDeclRef(*I);5482 }5483}5484 5485template <typename Vector>5486static void AddLazyVectorEmiitedDecls(ASTWriter &Writer, Vector &Vec,5487 ASTWriter::RecordData &Record) {5488 for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end();5489 I != E; ++I) {5490 Writer.AddEmittedDeclRef(*I, Record);5491 }5492}5493 5494void ASTWriter::computeNonAffectingInputFiles() {5495 SourceManager &SrcMgr = PP->getSourceManager();5496 unsigned N = SrcMgr.local_sloc_entry_size();5497 5498 IsSLocAffecting.resize(N, true);5499 IsSLocFileEntryAffecting.resize(N, true);5500 5501 if (!WritingModule)5502 return;5503 5504 auto AffectingModuleMaps = GetAffectingModuleMaps(*PP, WritingModule);5505 5506 unsigned FileIDAdjustment = 0;5507 unsigned OffsetAdjustment = 0;5508 5509 NonAffectingFileIDAdjustments.reserve(N);5510 NonAffectingOffsetAdjustments.reserve(N);5511 5512 NonAffectingFileIDAdjustments.push_back(FileIDAdjustment);5513 NonAffectingOffsetAdjustments.push_back(OffsetAdjustment);5514 5515 for (unsigned I = 1; I != N; ++I) {5516 const SrcMgr::SLocEntry *SLoc = &SrcMgr.getLocalSLocEntry(I);5517 FileID FID = FileID::get(I);5518 assert(&SrcMgr.getSLocEntry(FID) == SLoc);5519 5520 if (!SLoc->isFile())5521 continue;5522 const SrcMgr::FileInfo &File = SLoc->getFile();5523 const SrcMgr::ContentCache *Cache = &File.getContentCache();5524 if (!Cache->OrigEntry)5525 continue;5526 5527 // Don't prune anything other than module maps.5528 if (!isModuleMap(File.getFileCharacteristic()))5529 continue;5530 5531 // Don't prune module maps if all are guaranteed to be affecting.5532 if (!AffectingModuleMaps)5533 continue;5534 5535 // Don't prune module maps that are affecting.5536 if (AffectingModuleMaps->DefinitionFileIDs.contains(FID))5537 continue;5538 5539 IsSLocAffecting[I] = false;5540 IsSLocFileEntryAffecting[I] =5541 AffectingModuleMaps->DefinitionFiles.contains(*Cache->OrigEntry);5542 5543 FileIDAdjustment += 1;5544 // Even empty files take up one element in the offset table.5545 OffsetAdjustment += SrcMgr.getFileIDSize(FID) + 1;5546 5547 // If the previous file was non-affecting as well, just extend its entry5548 // with our information.5549 if (!NonAffectingFileIDs.empty() &&5550 NonAffectingFileIDs.back().ID == FID.ID - 1) {5551 NonAffectingFileIDs.back() = FID;5552 NonAffectingRanges.back().setEnd(SrcMgr.getLocForEndOfFile(FID));5553 NonAffectingFileIDAdjustments.back() = FileIDAdjustment;5554 NonAffectingOffsetAdjustments.back() = OffsetAdjustment;5555 continue;5556 }5557 5558 NonAffectingFileIDs.push_back(FID);5559 NonAffectingRanges.emplace_back(SrcMgr.getLocForStartOfFile(FID),5560 SrcMgr.getLocForEndOfFile(FID));5561 NonAffectingFileIDAdjustments.push_back(FileIDAdjustment);5562 NonAffectingOffsetAdjustments.push_back(OffsetAdjustment);5563 }5564 5565 if (!PP->getHeaderSearchInfo().getHeaderSearchOpts().ModulesIncludeVFSUsage)5566 return;5567 5568 FileManager &FileMgr = PP->getFileManager();5569 FileMgr.trackVFSUsage(true);5570 // Lookup the paths in the VFS to trigger `-ivfsoverlay` usage tracking.5571 for (StringRef Path :5572 PP->getHeaderSearchInfo().getHeaderSearchOpts().VFSOverlayFiles)5573 FileMgr.getVirtualFileSystem().exists(Path);5574 for (unsigned I = 1; I != N; ++I) {5575 if (IsSLocAffecting[I]) {5576 const SrcMgr::SLocEntry *SLoc = &SrcMgr.getLocalSLocEntry(I);5577 if (!SLoc->isFile())5578 continue;5579 const SrcMgr::FileInfo &File = SLoc->getFile();5580 const SrcMgr::ContentCache *Cache = &File.getContentCache();5581 if (!Cache->OrigEntry)5582 continue;5583 FileMgr.getVirtualFileSystem().exists(5584 Cache->OrigEntry->getNameAsRequested());5585 }5586 }5587 FileMgr.trackVFSUsage(false);5588}5589 5590void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {5591 ASTContext &Context = SemaRef.Context;5592 5593 bool isModule = WritingModule != nullptr;5594 5595 // Set up predefined declaration IDs.5596 auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) {5597 if (D) {5598 assert(D->isCanonicalDecl() && "predefined decl is not canonical");5599 DeclIDs[D] = ID;5600 PredefinedDecls.insert(D);5601 }5602 };5603 RegisterPredefDecl(Context.getTranslationUnitDecl(),5604 PREDEF_DECL_TRANSLATION_UNIT_ID);5605 RegisterPredefDecl(Context.ObjCIdDecl, PREDEF_DECL_OBJC_ID_ID);5606 RegisterPredefDecl(Context.ObjCSelDecl, PREDEF_DECL_OBJC_SEL_ID);5607 RegisterPredefDecl(Context.ObjCClassDecl, PREDEF_DECL_OBJC_CLASS_ID);5608 RegisterPredefDecl(Context.ObjCProtocolClassDecl,5609 PREDEF_DECL_OBJC_PROTOCOL_ID);5610 RegisterPredefDecl(Context.Int128Decl, PREDEF_DECL_INT_128_ID);5611 RegisterPredefDecl(Context.UInt128Decl, PREDEF_DECL_UNSIGNED_INT_128_ID);5612 RegisterPredefDecl(Context.ObjCInstanceTypeDecl,5613 PREDEF_DECL_OBJC_INSTANCETYPE_ID);5614 RegisterPredefDecl(Context.BuiltinVaListDecl, PREDEF_DECL_BUILTIN_VA_LIST_ID);5615 RegisterPredefDecl(Context.VaListTagDecl, PREDEF_DECL_VA_LIST_TAG);5616 RegisterPredefDecl(Context.BuiltinMSVaListDecl,5617 PREDEF_DECL_BUILTIN_MS_VA_LIST_ID);5618 RegisterPredefDecl(Context.MSGuidTagDecl,5619 PREDEF_DECL_BUILTIN_MS_GUID_ID);5620 RegisterPredefDecl(Context.MSTypeInfoTagDecl,5621 PREDEF_DECL_BUILTIN_MS_TYPE_INFO_TAG_ID);5622 RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID);5623 RegisterPredefDecl(Context.CFConstantStringTypeDecl,5624 PREDEF_DECL_CF_CONSTANT_STRING_ID);5625 RegisterPredefDecl(Context.CFConstantStringTagDecl,5626 PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID);5627#define BuiltinTemplate(BTName) \5628 RegisterPredefDecl(Context.Decl##BTName, PREDEF_DECL##BTName##_ID);5629#include "clang/Basic/BuiltinTemplates.inc"5630 5631 const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();5632 5633 // Force all top level declarations to be emitted.5634 //5635 // We start emitting top level declarations from the module purview to5636 // implement the eliding unreachable declaration feature.5637 for (const auto *D : TU->noload_decls()) {5638 if (D->isFromASTFile())5639 continue;5640 5641 if (GeneratingReducedBMI) {5642 if (D->isFromExplicitGlobalModule())5643 continue;5644 5645 // Don't force emitting static entities.5646 //5647 // Technically, all static entities shouldn't be in reduced BMI. The5648 // language also specifies that the program exposes TU-local entities5649 // is ill-formed. However, in practice, there are a lot of projects5650 // uses `static inline` in the headers. So we can't get rid of all5651 // static entities in reduced BMI now.5652 if (IsInternalDeclFromFileContext(D))5653 continue;5654 }5655 5656 // If we're writing C++ named modules, don't emit declarations which are5657 // not from modules by default. They may be built in declarations (be5658 // handled above) or implcit declarations (see the implementation of5659 // `Sema::Initialize()` for example).5660 if (isWritingStdCXXNamedModules() && !D->getOwningModule() &&5661 D->isImplicit())5662 continue;5663 5664 GetDeclRef(D);5665 }5666 5667 if (GeneratingReducedBMI)5668 return;5669 5670 // Writing all of the tentative definitions in this file, in5671 // TentativeDefinitions order. Generally, this record will be empty for5672 // headers.5673 AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions);5674 5675 // Writing all of the file scoped decls in this file.5676 if (!isModule)5677 AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls);5678 5679 // Writing all of the delegating constructors we still need5680 // to resolve.5681 if (!isModule)5682 AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls);5683 5684 // Writing all of the ext_vector declarations.5685 AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls);5686 5687 // Writing all of the VTable uses information.5688 if (!SemaRef.VTableUses.empty())5689 for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I)5690 GetDeclRef(SemaRef.VTableUses[I].first);5691 5692 // Writing all of the UnusedLocalTypedefNameCandidates.5693 for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates)5694 GetDeclRef(TD);5695 5696 // Writing all of pending implicit instantiations.5697 for (const auto &I : SemaRef.PendingInstantiations)5698 GetDeclRef(I.first);5699 assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&5700 "There are local ones at end of translation unit!");5701 5702 // Writing some declaration references.5703 if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) {5704 GetDeclRef(SemaRef.getStdNamespace());5705 GetDeclRef(SemaRef.getStdBadAlloc());5706 GetDeclRef(SemaRef.getStdAlignValT());5707 }5708 5709 if (Context.getcudaConfigureCallDecl() ||5710 Context.getcudaGetParameterBufferDecl() ||5711 Context.getcudaLaunchDeviceDecl()) {5712 GetDeclRef(Context.getcudaConfigureCallDecl());5713 GetDeclRef(Context.getcudaGetParameterBufferDecl());5714 GetDeclRef(Context.getcudaLaunchDeviceDecl());5715 }5716 5717 // Writing all of the known namespaces.5718 for (const auto &I : SemaRef.KnownNamespaces)5719 if (!I.second)5720 GetDeclRef(I.first);5721 5722 // Writing all used, undefined objects that require definitions.5723 SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;5724 SemaRef.getUndefinedButUsed(Undefined);5725 for (const auto &I : Undefined)5726 GetDeclRef(I.first);5727 5728 // Writing all delete-expressions that we would like to5729 // analyze later in AST.5730 if (!isModule)5731 for (const auto &DeleteExprsInfo :5732 SemaRef.getMismatchingDeleteExpressions())5733 GetDeclRef(DeleteExprsInfo.first);5734 5735 // Make sure visible decls, added to DeclContexts previously loaded from5736 // an AST file, are registered for serialization. Likewise for template5737 // specializations added to imported templates.5738 for (const auto *I : DeclsToEmitEvenIfUnreferenced)5739 GetDeclRef(I);5740 DeclsToEmitEvenIfUnreferenced.clear();5741 5742 // Make sure all decls associated with an identifier are registered for5743 // serialization, if we're storing decls with identifiers.5744 if (!WritingModule || !getLangOpts().CPlusPlus) {5745 llvm::SmallVector<const IdentifierInfo*, 256> IIs;5746 for (const auto &ID : SemaRef.PP.getIdentifierTable()) {5747 const IdentifierInfo *II = ID.second;5748 if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization() ||5749 II->hasFETokenInfoChangedSinceDeserialization())5750 IIs.push_back(II);5751 }5752 // Sort the identifiers to visit based on their name.5753 llvm::sort(IIs, llvm::deref<std::less<>>());5754 const LangOptions &LangOpts = getLangOpts();5755 for (const IdentifierInfo *II : IIs)5756 for (NamedDecl *D : SemaRef.IdResolver.decls(II))5757 GetDeclRef(getDeclForLocalLookup(LangOpts, D));5758 }5759 5760 // Write all of the DeclsToCheckForDeferredDiags.5761 for (auto *D : SemaRef.DeclsToCheckForDeferredDiags)5762 GetDeclRef(D);5763 5764 // Write all classes that need to emit the vtable definitions if required.5765 if (isWritingStdCXXNamedModules())5766 for (CXXRecordDecl *RD : PendingEmittingVTables)5767 GetDeclRef(RD);5768 else5769 PendingEmittingVTables.clear();5770}5771 5772void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) {5773 ASTContext &Context = SemaRef.Context;5774 5775 bool isModule = WritingModule != nullptr;5776 5777 // Write the record containing external, unnamed definitions.5778 if (!EagerlyDeserializedDecls.empty())5779 Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls);5780 5781 if (!ModularCodegenDecls.empty())5782 Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls);5783 5784 // Write the record containing tentative definitions.5785 RecordData TentativeDefinitions;5786 AddLazyVectorEmiitedDecls(*this, SemaRef.TentativeDefinitions,5787 TentativeDefinitions);5788 if (!TentativeDefinitions.empty())5789 Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions);5790 5791 // Write the record containing unused file scoped decls.5792 RecordData UnusedFileScopedDecls;5793 if (!isModule)5794 AddLazyVectorEmiitedDecls(*this, SemaRef.UnusedFileScopedDecls,5795 UnusedFileScopedDecls);5796 if (!UnusedFileScopedDecls.empty())5797 Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls);5798 5799 // Write the record containing ext_vector type names.5800 RecordData ExtVectorDecls;5801 AddLazyVectorEmiitedDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls);5802 if (!ExtVectorDecls.empty())5803 Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls);5804 5805 // Write the record containing VTable uses information.5806 RecordData VTableUses;5807 if (!SemaRef.VTableUses.empty()) {5808 for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) {5809 CXXRecordDecl *D = SemaRef.VTableUses[I].first;5810 if (!wasDeclEmitted(D))5811 continue;5812 5813 AddDeclRef(D, VTableUses);5814 AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses);5815 VTableUses.push_back(SemaRef.VTablesUsed[D]);5816 }5817 Stream.EmitRecord(VTABLE_USES, VTableUses);5818 }5819 5820 // Write the record containing potentially unused local typedefs.5821 RecordData UnusedLocalTypedefNameCandidates;5822 for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates)5823 AddEmittedDeclRef(TD, UnusedLocalTypedefNameCandidates);5824 if (!UnusedLocalTypedefNameCandidates.empty())5825 Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES,5826 UnusedLocalTypedefNameCandidates);5827 5828 if (!GeneratingReducedBMI) {5829 // Write the record containing pending implicit instantiations.5830 RecordData PendingInstantiations;5831 for (const auto &I : SemaRef.PendingInstantiations) {5832 if (!wasDeclEmitted(I.first))5833 continue;5834 5835 AddDeclRef(I.first, PendingInstantiations);5836 AddSourceLocation(I.second, PendingInstantiations);5837 }5838 if (!PendingInstantiations.empty())5839 Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);5840 }5841 5842 auto AddEmittedDeclRefOrZero = [this](RecordData &Refs, Decl *D) {5843 if (!D || !wasDeclEmitted(D))5844 Refs.push_back(0);5845 else5846 AddDeclRef(D, Refs);5847 };5848 5849 // Write the record containing declaration references of Sema.5850 RecordData SemaDeclRefs;5851 if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) {5852 AddEmittedDeclRefOrZero(SemaDeclRefs, SemaRef.getStdNamespace());5853 AddEmittedDeclRefOrZero(SemaDeclRefs, SemaRef.getStdBadAlloc());5854 AddEmittedDeclRefOrZero(SemaDeclRefs, SemaRef.getStdAlignValT());5855 }5856 if (!SemaDeclRefs.empty())5857 Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs);5858 5859 // Write the record containing decls to be checked for deferred diags.5860 RecordData DeclsToCheckForDeferredDiags;5861 for (auto *D : SemaRef.DeclsToCheckForDeferredDiags)5862 if (wasDeclEmitted(D))5863 AddDeclRef(D, DeclsToCheckForDeferredDiags);5864 if (!DeclsToCheckForDeferredDiags.empty())5865 Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS,5866 DeclsToCheckForDeferredDiags);5867 5868 // Write the record containing CUDA-specific declaration references.5869 RecordData CUDASpecialDeclRefs;5870 if (auto *CudaCallDecl = Context.getcudaConfigureCallDecl(),5871 *CudaGetParamDecl = Context.getcudaGetParameterBufferDecl(),5872 *CudaLaunchDecl = Context.getcudaLaunchDeviceDecl();5873 CudaCallDecl || CudaGetParamDecl || CudaLaunchDecl) {5874 AddEmittedDeclRefOrZero(CUDASpecialDeclRefs, CudaCallDecl);5875 AddEmittedDeclRefOrZero(CUDASpecialDeclRefs, CudaGetParamDecl);5876 AddEmittedDeclRefOrZero(CUDASpecialDeclRefs, CudaLaunchDecl);5877 Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs);5878 }5879 5880 // Write the delegating constructors.5881 RecordData DelegatingCtorDecls;5882 if (!isModule)5883 AddLazyVectorEmiitedDecls(*this, SemaRef.DelegatingCtorDecls,5884 DelegatingCtorDecls);5885 if (!DelegatingCtorDecls.empty())5886 Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls);5887 5888 // Write the known namespaces.5889 RecordData KnownNamespaces;5890 for (const auto &I : SemaRef.KnownNamespaces) {5891 if (!I.second && wasDeclEmitted(I.first))5892 AddDeclRef(I.first, KnownNamespaces);5893 }5894 if (!KnownNamespaces.empty())5895 Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces);5896 5897 // Write the undefined internal functions and variables, and inline functions.5898 RecordData UndefinedButUsed;5899 SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;5900 SemaRef.getUndefinedButUsed(Undefined);5901 for (const auto &I : Undefined) {5902 if (!wasDeclEmitted(I.first))5903 continue;5904 5905 AddDeclRef(I.first, UndefinedButUsed);5906 AddSourceLocation(I.second, UndefinedButUsed);5907 }5908 if (!UndefinedButUsed.empty())5909 Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed);5910 5911 // Write all delete-expressions that we would like to5912 // analyze later in AST.5913 RecordData DeleteExprsToAnalyze;5914 if (!isModule) {5915 for (const auto &DeleteExprsInfo :5916 SemaRef.getMismatchingDeleteExpressions()) {5917 if (!wasDeclEmitted(DeleteExprsInfo.first))5918 continue;5919 5920 AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze);5921 DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size());5922 for (const auto &DeleteLoc : DeleteExprsInfo.second) {5923 AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze);5924 DeleteExprsToAnalyze.push_back(DeleteLoc.second);5925 }5926 }5927 }5928 if (!DeleteExprsToAnalyze.empty())5929 Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze);5930 5931 RecordData VTablesToEmit;5932 for (CXXRecordDecl *RD : PendingEmittingVTables) {5933 if (!wasDeclEmitted(RD))5934 continue;5935 5936 AddDeclRef(RD, VTablesToEmit);5937 }5938 5939 if (!VTablesToEmit.empty())5940 Stream.EmitRecord(VTABLES_TO_EMIT, VTablesToEmit);5941}5942 5943ASTFileSignature ASTWriter::WriteASTCore(Sema *SemaPtr, StringRef isysroot,5944 Module *WritingModule) {5945 using namespace llvm;5946 5947 bool isModule = WritingModule != nullptr;5948 5949 // Make sure that the AST reader knows to finalize itself.5950 if (Chain)5951 Chain->finalizeForWriting();5952 5953 // This needs to be done very early, since everything that writes5954 // SourceLocations or FileIDs depends on it.5955 computeNonAffectingInputFiles();5956 5957 writeUnhashedControlBlock(*PP);5958 5959 // Don't reuse type ID and Identifier ID from readers for C++ standard named5960 // modules since we want to support no-transitive-change model for named5961 // modules. The theory for no-transitive-change model is,5962 // for a user of a named module, the user can only access the indirectly5963 // imported decls via the directly imported module. So that it is possible to5964 // control what matters to the users when writing the module. It would be5965 // problematic if the users can reuse the type IDs and identifier IDs from5966 // indirectly imported modules arbitrarily. So we choose to clear these ID5967 // here.5968 if (isWritingStdCXXNamedModules()) {5969 TypeIdxs.clear();5970 IdentifierIDs.clear();5971 }5972 5973 // Look for any identifiers that were named while processing the5974 // headers, but are otherwise not needed. We add these to the hash5975 // table to enable checking of the predefines buffer in the case5976 // where the user adds new macro definitions when building the AST5977 // file.5978 //5979 // We do this before emitting any Decl and Types to make sure the5980 // Identifier ID is stable.5981 SmallVector<const IdentifierInfo *, 128> IIs;5982 for (const auto &ID : PP->getIdentifierTable())5983 if (IsInterestingNonMacroIdentifier(ID.second, *this))5984 IIs.push_back(ID.second);5985 // Sort the identifiers lexicographically before getting the references so5986 // that their order is stable.5987 llvm::sort(IIs, llvm::deref<std::less<>>());5988 for (const IdentifierInfo *II : IIs)5989 getIdentifierRef(II);5990 5991 // Write the set of weak, undeclared identifiers. We always write the5992 // entire table, since later PCH files in a PCH chain are only interested in5993 // the results at the end of the chain.5994 RecordData WeakUndeclaredIdentifiers;5995 if (SemaPtr) {5996 for (const auto &WeakUndeclaredIdentifierList :5997 SemaPtr->WeakUndeclaredIdentifiers) {5998 const IdentifierInfo *const II = WeakUndeclaredIdentifierList.first;5999 for (const auto &WI : WeakUndeclaredIdentifierList.second) {6000 AddIdentifierRef(II, WeakUndeclaredIdentifiers);6001 AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers);6002 AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers);6003 }6004 }6005 }6006 6007 // Form the record of special types.6008 RecordData SpecialTypes;6009 if (SemaPtr) {6010 ASTContext &Context = SemaPtr->Context;6011 AddTypeRef(Context, Context.getRawCFConstantStringType(), SpecialTypes);6012 AddTypeRef(Context, Context.getFILEType(), SpecialTypes);6013 AddTypeRef(Context, Context.getjmp_bufType(), SpecialTypes);6014 AddTypeRef(Context, Context.getsigjmp_bufType(), SpecialTypes);6015 AddTypeRef(Context, Context.ObjCIdRedefinitionType, SpecialTypes);6016 AddTypeRef(Context, Context.ObjCClassRedefinitionType, SpecialTypes);6017 AddTypeRef(Context, Context.ObjCSelRedefinitionType, SpecialTypes);6018 AddTypeRef(Context, Context.getucontext_tType(), SpecialTypes);6019 }6020 6021 if (SemaPtr)6022 PrepareWritingSpecialDecls(*SemaPtr);6023 6024 // Write the control block6025 WriteControlBlock(*PP, isysroot);6026 6027 // Write the remaining AST contents.6028 Stream.FlushToWord();6029 ASTBlockRange.first = Stream.GetCurrentBitNo() >> 3;6030 Stream.EnterSubblock(AST_BLOCK_ID, 5);6031 ASTBlockStartOffset = Stream.GetCurrentBitNo();6032 6033 // This is so that older clang versions, before the introduction6034 // of the control block, can read and reject the newer PCH format.6035 {6036 RecordData Record = {VERSION_MAJOR};6037 Stream.EmitRecord(METADATA_OLD_FORMAT, Record);6038 }6039 6040 // For method pool in the module, if it contains an entry for a selector,6041 // the entry should be complete, containing everything introduced by that6042 // module and all modules it imports. It's possible that the entry is out of6043 // date, so we need to pull in the new content here.6044 6045 // It's possible that updateOutOfDateSelector can update SelectorIDs. To be6046 // safe, we copy all selectors out.6047 if (SemaPtr) {6048 llvm::SmallVector<Selector, 256> AllSelectors;6049 for (auto &SelectorAndID : SelectorIDs)6050 AllSelectors.push_back(SelectorAndID.first);6051 for (auto &Selector : AllSelectors)6052 SemaPtr->ObjC().updateOutOfDateSelector(Selector);6053 }6054 6055 if (Chain) {6056 // Write the mapping information describing our module dependencies and how6057 // each of those modules were mapped into our own offset/ID space, so that6058 // the reader can build the appropriate mapping to its own offset/ID space.6059 // The map consists solely of a blob with the following format:6060 // *(module-kind:i86061 // module-name-len:i16 module-name:len*i86062 // source-location-offset:i326063 // identifier-id:i326064 // preprocessed-entity-id:i326065 // macro-definition-id:i326066 // submodule-id:i326067 // selector-id:i326068 // declaration-id:i326069 // c++-base-specifiers-id:i326070 // type-id:i32)6071 //6072 // module-kind is the ModuleKind enum value. If it is MK_PrebuiltModule,6073 // MK_ExplicitModule or MK_ImplicitModule, then the module-name is the6074 // module name. Otherwise, it is the module file name.6075 auto Abbrev = std::make_shared<BitCodeAbbrev>();6076 Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP));6077 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));6078 unsigned ModuleOffsetMapAbbrev = Stream.EmitAbbrev(std::move(Abbrev));6079 SmallString<2048> Buffer;6080 {6081 llvm::raw_svector_ostream Out(Buffer);6082 for (ModuleFile &M : Chain->ModuleMgr) {6083 using namespace llvm::support;6084 6085 endian::Writer LE(Out, llvm::endianness::little);6086 LE.write<uint8_t>(static_cast<uint8_t>(M.Kind));6087 StringRef Name = M.isModule() ? M.ModuleName : M.FileName;6088 LE.write<uint16_t>(Name.size());6089 Out.write(Name.data(), Name.size());6090 6091 // Note: if a base ID was uint max, it would not be possible to load6092 // another module after it or have more than one entity inside it.6093 uint32_t None = std::numeric_limits<uint32_t>::max();6094 6095 auto writeBaseIDOrNone = [&](auto BaseID, bool ShouldWrite) {6096 assert(BaseID < std::numeric_limits<uint32_t>::max() && "base id too high");6097 if (ShouldWrite)6098 LE.write<uint32_t>(BaseID);6099 else6100 LE.write<uint32_t>(None);6101 };6102 6103 // These values should be unique within a chain, since they will be read6104 // as keys into ContinuousRangeMaps.6105 writeBaseIDOrNone(M.BaseSubmoduleID, M.LocalNumSubmodules);6106 writeBaseIDOrNone(M.BaseSelectorID, M.LocalNumSelectors);6107 }6108 }6109 RecordData::value_type Record[] = {MODULE_OFFSET_MAP};6110 Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record,6111 Buffer.data(), Buffer.size());6112 }6113 6114 if (SemaPtr)6115 WriteDeclAndTypes(SemaPtr->Context);6116 6117 WriteFileDeclIDsMap();6118 WriteSourceManagerBlock(PP->getSourceManager());6119 if (SemaPtr)6120 WriteComments(SemaPtr->Context);6121 WritePreprocessor(*PP, isModule);6122 WriteHeaderSearch(PP->getHeaderSearchInfo());6123 if (SemaPtr) {6124 WriteSelectors(*SemaPtr);6125 WriteReferencedSelectorsPool(*SemaPtr);6126 WriteLateParsedTemplates(*SemaPtr);6127 }6128 WriteIdentifierTable(*PP, SemaPtr ? &SemaPtr->IdResolver : nullptr, isModule);6129 if (SemaPtr) {6130 WriteFPPragmaOptions(SemaPtr->CurFPFeatureOverrides());6131 WriteOpenCLExtensions(*SemaPtr);6132 WriteCUDAPragmas(*SemaPtr);6133 }6134 6135 // If we're emitting a module, write out the submodule information.6136 if (WritingModule)6137 WriteSubmodules(WritingModule, SemaPtr ? &SemaPtr->Context : nullptr);6138 6139 Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);6140 6141 if (SemaPtr)6142 WriteSpecialDeclRecords(*SemaPtr);6143 6144 // Write the record containing weak undeclared identifiers.6145 if (!WeakUndeclaredIdentifiers.empty())6146 Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS,6147 WeakUndeclaredIdentifiers);6148 6149 if (!WritingModule) {6150 // Write the submodules that were imported, if any.6151 struct ModuleInfo {6152 uint64_t ID;6153 Module *M;6154 ModuleInfo(uint64_t ID, Module *M) : ID(ID), M(M) {}6155 };6156 llvm::SmallVector<ModuleInfo, 64> Imports;6157 if (SemaPtr) {6158 for (const auto *I : SemaPtr->Context.local_imports()) {6159 assert(SubmoduleIDs.contains(I->getImportedModule()));6160 Imports.push_back(ModuleInfo(SubmoduleIDs[I->getImportedModule()],6161 I->getImportedModule()));6162 }6163 }6164 6165 if (!Imports.empty()) {6166 auto Cmp = [](const ModuleInfo &A, const ModuleInfo &B) {6167 return A.ID < B.ID;6168 };6169 auto Eq = [](const ModuleInfo &A, const ModuleInfo &B) {6170 return A.ID == B.ID;6171 };6172 6173 // Sort and deduplicate module IDs.6174 llvm::sort(Imports, Cmp);6175 Imports.erase(llvm::unique(Imports, Eq), Imports.end());6176 6177 RecordData ImportedModules;6178 for (const auto &Import : Imports) {6179 ImportedModules.push_back(Import.ID);6180 // FIXME: If the module has macros imported then later has declarations6181 // imported, this location won't be the right one as a location for the6182 // declaration imports.6183 AddSourceLocation(PP->getModuleImportLoc(Import.M), ImportedModules);6184 }6185 6186 Stream.EmitRecord(IMPORTED_MODULES, ImportedModules);6187 }6188 }6189 6190 WriteObjCCategories();6191 if (SemaPtr) {6192 if (!WritingModule) {6193 WriteOptimizePragmaOptions(*SemaPtr);6194 WriteMSStructPragmaOptions(*SemaPtr);6195 WriteMSPointersToMembersPragmaOptions(*SemaPtr);6196 }6197 WritePackPragmaOptions(*SemaPtr);6198 WriteFloatControlPragmaOptions(*SemaPtr);6199 WriteDeclsWithEffectsToVerify(*SemaPtr);6200 }6201 6202 // Some simple statistics6203 RecordData::value_type Record[] = {NumStatements,6204 NumMacros,6205 NumLexicalDeclContexts,6206 NumVisibleDeclContexts,6207 NumModuleLocalDeclContexts,6208 NumTULocalDeclContexts};6209 Stream.EmitRecord(STATISTICS, Record);6210 Stream.ExitBlock();6211 Stream.FlushToWord();6212 ASTBlockRange.second = Stream.GetCurrentBitNo() >> 3;6213 6214 // Write the module file extension blocks.6215 if (SemaPtr)6216 for (const auto &ExtWriter : ModuleFileExtensionWriters)6217 WriteModuleFileExtension(*SemaPtr, *ExtWriter);6218 6219 return backpatchSignature();6220}6221 6222void ASTWriter::EnteringModulePurview() {6223 // In C++20 named modules, all entities before entering the module purview6224 // lives in the GMF.6225 if (GeneratingReducedBMI)6226 DeclUpdatesFromGMF.swap(DeclUpdates);6227}6228 6229// Add update records for all mangling numbers and static local numbers.6230// These aren't really update records, but this is a convenient way of6231// tagging this rare extra data onto the declarations.6232void ASTWriter::AddedManglingNumber(const Decl *D, unsigned Number) {6233 if (D->isFromASTFile())6234 return;6235 6236 DeclUpdates[D].push_back(DeclUpdate(DeclUpdateKind::ManglingNumber, Number));6237}6238void ASTWriter::AddedStaticLocalNumbers(const Decl *D, unsigned Number) {6239 if (D->isFromASTFile())6240 return;6241 6242 DeclUpdates[D].push_back(6243 DeclUpdate(DeclUpdateKind::StaticLocalNumber, Number));6244}6245 6246void ASTWriter::AddedAnonymousNamespace(const TranslationUnitDecl *TU,6247 NamespaceDecl *AnonNamespace) {6248 // If the translation unit has an anonymous namespace, and we don't already6249 // have an update block for it, write it as an update block.6250 // FIXME: Why do we not do this if there's already an update block?6251 if (NamespaceDecl *NS = TU->getAnonymousNamespace()) {6252 ASTWriter::UpdateRecord &Record = DeclUpdates[TU];6253 if (Record.empty())6254 Record.push_back(6255 DeclUpdate(DeclUpdateKind::CXXAddedAnonymousNamespace, NS));6256 }6257}6258 6259void ASTWriter::WriteDeclAndTypes(ASTContext &Context) {6260 // Keep writing types, declarations, and declaration update records6261 // until we've emitted all of them.6262 RecordData DeclUpdatesOffsetsRecord;6263 Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/ 6);6264 DeclTypesBlockStartOffset = Stream.GetCurrentBitNo();6265 WriteTypeAbbrevs();6266 WriteDeclAbbrevs();6267 do {6268 WriteDeclUpdatesBlocks(Context, DeclUpdatesOffsetsRecord);6269 while (!DeclTypesToEmit.empty()) {6270 DeclOrType DOT = DeclTypesToEmit.front();6271 DeclTypesToEmit.pop();6272 if (DOT.isType())6273 WriteType(Context, DOT.getType());6274 else6275 WriteDecl(Context, DOT.getDecl());6276 }6277 } while (!DeclUpdates.empty());6278 6279 DoneWritingDeclsAndTypes = true;6280 6281 // DelayedNamespace is only meaningful in reduced BMI.6282 // See the comments of DelayedNamespace for details.6283 assert(DelayedNamespace.empty() || GeneratingReducedBMI);6284 RecordData DelayedNamespaceRecord;6285 for (NamespaceDecl *NS : DelayedNamespace) {6286 LookupBlockOffsets Offsets;6287 6288 Offsets.LexicalOffset = WriteDeclContextLexicalBlock(Context, NS);6289 WriteDeclContextVisibleBlock(Context, NS, Offsets);6290 6291 if (Offsets.LexicalOffset)6292 Offsets.LexicalOffset -= DeclTypesBlockStartOffset;6293 6294 // Write the offset relative to current block.6295 if (Offsets.VisibleOffset)6296 Offsets.VisibleOffset -= DeclTypesBlockStartOffset;6297 6298 if (Offsets.ModuleLocalOffset)6299 Offsets.ModuleLocalOffset -= DeclTypesBlockStartOffset;6300 6301 if (Offsets.TULocalOffset)6302 Offsets.TULocalOffset -= DeclTypesBlockStartOffset;6303 6304 AddDeclRef(NS, DelayedNamespaceRecord);6305 AddLookupOffsets(Offsets, DelayedNamespaceRecord);6306 }6307 6308 // The process of writing lexical and visible block for delayed namespace6309 // shouldn't introduce any new decls, types or update to emit.6310 assert(DeclTypesToEmit.empty());6311 assert(DeclUpdates.empty());6312 6313 Stream.ExitBlock();6314 6315 // These things can only be done once we've written out decls and types.6316 WriteTypeDeclOffsets();6317 if (!DeclUpdatesOffsetsRecord.empty())6318 Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);6319 6320 if (!DelayedNamespaceRecord.empty())6321 Stream.EmitRecord(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD,6322 DelayedNamespaceRecord);6323 6324 if (!RelatedDeclsMap.empty()) {6325 // TODO: on disk hash table for related decls mapping might be more6326 // efficent becuase it allows lazy deserialization.6327 RecordData RelatedDeclsMapRecord;6328 for (const auto &Pair : RelatedDeclsMap) {6329 RelatedDeclsMapRecord.push_back(Pair.first.getRawValue());6330 RelatedDeclsMapRecord.push_back(Pair.second.size());6331 for (const auto &Lambda : Pair.second)6332 RelatedDeclsMapRecord.push_back(Lambda.getRawValue());6333 }6334 6335 auto Abv = std::make_shared<llvm::BitCodeAbbrev>();6336 Abv->Add(llvm::BitCodeAbbrevOp(RELATED_DECLS_MAP));6337 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array));6338 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));6339 unsigned FunctionToLambdaMapAbbrev = Stream.EmitAbbrev(std::move(Abv));6340 Stream.EmitRecord(RELATED_DECLS_MAP, RelatedDeclsMapRecord,6341 FunctionToLambdaMapAbbrev);6342 }6343 6344 if (!SpecializationsUpdates.empty()) {6345 WriteSpecializationsUpdates(/*IsPartial=*/false);6346 SpecializationsUpdates.clear();6347 }6348 6349 if (!PartialSpecializationsUpdates.empty()) {6350 WriteSpecializationsUpdates(/*IsPartial=*/true);6351 PartialSpecializationsUpdates.clear();6352 }6353 6354 const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();6355 // Create a lexical update block containing all of the declarations in the6356 // translation unit that do not come from other AST files.6357 SmallVector<DeclID, 128> NewGlobalKindDeclPairs;6358 for (const auto *D : TU->noload_decls()) {6359 if (D->isFromASTFile())6360 continue;6361 6362 // In reduced BMI, skip unreached declarations.6363 if (!wasDeclEmitted(D))6364 continue;6365 6366 NewGlobalKindDeclPairs.push_back(D->getKind());6367 NewGlobalKindDeclPairs.push_back(GetDeclRef(D).getRawValue());6368 }6369 6370 auto Abv = std::make_shared<llvm::BitCodeAbbrev>();6371 Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL));6372 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));6373 unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv));6374 6375 RecordData::value_type Record[] = {TU_UPDATE_LEXICAL};6376 Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,6377 bytes(NewGlobalKindDeclPairs));6378 6379 Abv = std::make_shared<llvm::BitCodeAbbrev>();6380 Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE));6381 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));6382 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));6383 UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv));6384 6385 Abv = std::make_shared<llvm::BitCodeAbbrev>();6386 Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_MODULE_LOCAL_VISIBLE));6387 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));6388 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));6389 ModuleLocalUpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv));6390 6391 Abv = std::make_shared<llvm::BitCodeAbbrev>();6392 Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_TU_LOCAL_VISIBLE));6393 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));6394 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));6395 TULocalUpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv));6396 6397 // And a visible updates block for the translation unit.6398 WriteDeclContextVisibleUpdate(Context, TU);6399 6400 // If we have any extern "C" names, write out a visible update for them.6401 if (Context.ExternCContext)6402 WriteDeclContextVisibleUpdate(Context, Context.ExternCContext);6403 6404 // Write the visible updates to DeclContexts.6405 for (auto *DC : UpdatedDeclContexts)6406 WriteDeclContextVisibleUpdate(Context, DC);6407}6408 6409void ASTWriter::WriteSpecializationsUpdates(bool IsPartial) {6410 auto RecordType = IsPartial ? CXX_ADDED_TEMPLATE_PARTIAL_SPECIALIZATION6411 : CXX_ADDED_TEMPLATE_SPECIALIZATION;6412 6413 auto Abv = std::make_shared<llvm::BitCodeAbbrev>();6414 Abv->Add(llvm::BitCodeAbbrevOp(RecordType));6415 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));6416 Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));6417 auto UpdateSpecializationAbbrev = Stream.EmitAbbrev(std::move(Abv));6418 6419 auto &SpecUpdates =6420 IsPartial ? PartialSpecializationsUpdates : SpecializationsUpdates;6421 for (auto &SpecializationUpdate : SpecUpdates) {6422 const NamedDecl *D = SpecializationUpdate.first;6423 6424 llvm::SmallString<4096> LookupTable;6425 GenerateSpecializationInfoLookupTable(D, SpecializationUpdate.second,6426 LookupTable, IsPartial);6427 6428 // Write the lookup table6429 RecordData::value_type Record[] = {6430 static_cast<RecordData::value_type>(RecordType),6431 getDeclID(D).getRawValue()};6432 Stream.EmitRecordWithBlob(UpdateSpecializationAbbrev, Record, LookupTable);6433 }6434}6435 6436void ASTWriter::WriteDeclUpdatesBlocks(ASTContext &Context,6437 RecordDataImpl &OffsetsRecord) {6438 if (DeclUpdates.empty())6439 return;6440 6441 DeclUpdateMap LocalUpdates;6442 LocalUpdates.swap(DeclUpdates);6443 6444 for (auto &DeclUpdate : LocalUpdates) {6445 const Decl *D = DeclUpdate.first;6446 6447 bool HasUpdatedBody = false;6448 bool HasAddedVarDefinition = false;6449 RecordData RecordData;6450 ASTRecordWriter Record(Context, *this, RecordData);6451 for (auto &Update : DeclUpdate.second) {6452 DeclUpdateKind Kind = Update.getKind();6453 6454 // An updated body is emitted last, so that the reader doesn't need6455 // to skip over the lazy body to reach statements for other records.6456 if (Kind == DeclUpdateKind::CXXAddedFunctionDefinition)6457 HasUpdatedBody = true;6458 else if (Kind == DeclUpdateKind::CXXAddedVarDefinition)6459 HasAddedVarDefinition = true;6460 else6461 Record.push_back(llvm::to_underlying(Kind));6462 6463 switch (Kind) {6464 case DeclUpdateKind::CXXAddedImplicitMember:6465 case DeclUpdateKind::CXXAddedAnonymousNamespace:6466 assert(Update.getDecl() && "no decl to add?");6467 Record.AddDeclRef(Update.getDecl());6468 break;6469 case DeclUpdateKind::CXXAddedFunctionDefinition:6470 case DeclUpdateKind::CXXAddedVarDefinition:6471 break;6472 6473 case DeclUpdateKind::CXXPointOfInstantiation:6474 // FIXME: Do we need to also save the template specialization kind here?6475 Record.AddSourceLocation(Update.getLoc());6476 break;6477 6478 case DeclUpdateKind::CXXInstantiatedDefaultArgument:6479 Record.writeStmtRef(6480 cast<ParmVarDecl>(Update.getDecl())->getDefaultArg());6481 break;6482 6483 case DeclUpdateKind::CXXInstantiatedDefaultMemberInitializer:6484 Record.AddStmt(6485 cast<FieldDecl>(Update.getDecl())->getInClassInitializer());6486 break;6487 6488 case DeclUpdateKind::CXXInstantiatedClassDefinition: {6489 auto *RD = cast<CXXRecordDecl>(D);6490 UpdatedDeclContexts.insert(RD->getPrimaryContext());6491 Record.push_back(RD->isParamDestroyedInCallee());6492 Record.push_back(llvm::to_underlying(RD->getArgPassingRestrictions()));6493 Record.AddCXXDefinitionData(RD);6494 Record.AddOffset(WriteDeclContextLexicalBlock(Context, RD));6495 6496 // This state is sometimes updated by template instantiation, when we6497 // switch from the specialization referring to the template declaration6498 // to it referring to the template definition.6499 if (auto *MSInfo = RD->getMemberSpecializationInfo()) {6500 Record.push_back(MSInfo->getTemplateSpecializationKind());6501 Record.AddSourceLocation(MSInfo->getPointOfInstantiation());6502 } else {6503 auto *Spec = cast<ClassTemplateSpecializationDecl>(RD);6504 Record.push_back(Spec->getTemplateSpecializationKind());6505 Record.AddSourceLocation(Spec->getPointOfInstantiation());6506 6507 // The instantiation might have been resolved to a partial6508 // specialization. If so, record which one.6509 auto From = Spec->getInstantiatedFrom();6510 if (auto PartialSpec =6511 From.dyn_cast<ClassTemplatePartialSpecializationDecl*>()) {6512 Record.push_back(true);6513 Record.AddDeclRef(PartialSpec);6514 Record.AddTemplateArgumentList(6515 &Spec->getTemplateInstantiationArgs());6516 } else {6517 Record.push_back(false);6518 }6519 }6520 Record.push_back(llvm::to_underlying(RD->getTagKind()));6521 Record.AddSourceLocation(RD->getLocation());6522 Record.AddSourceLocation(RD->getBeginLoc());6523 Record.AddSourceRange(RD->getBraceRange());6524 6525 // Instantiation may change attributes; write them all out afresh.6526 Record.push_back(D->hasAttrs());6527 if (D->hasAttrs())6528 Record.AddAttributes(D->getAttrs());6529 6530 // FIXME: Ensure we don't get here for explicit instantiations.6531 break;6532 }6533 6534 case DeclUpdateKind::CXXResolvedDtorDelete:6535 Record.AddDeclRef(Update.getDecl());6536 Record.AddStmt(cast<CXXDestructorDecl>(D)->getOperatorDeleteThisArg());6537 break;6538 6539 case DeclUpdateKind::CXXResolvedDtorGlobDelete:6540 Record.AddDeclRef(Update.getDecl());6541 break;6542 6543 case DeclUpdateKind::CXXResolvedExceptionSpec: {6544 auto prototype =6545 cast<FunctionDecl>(D)->getType()->castAs<FunctionProtoType>();6546 Record.writeExceptionSpecInfo(prototype->getExceptionSpecInfo());6547 break;6548 }6549 6550 case DeclUpdateKind::CXXDeducedReturnType:6551 Record.push_back(GetOrCreateTypeID(Context, Update.getType()));6552 break;6553 6554 case DeclUpdateKind::DeclMarkedUsed:6555 break;6556 6557 case DeclUpdateKind::ManglingNumber:6558 case DeclUpdateKind::StaticLocalNumber:6559 Record.push_back(Update.getNumber());6560 break;6561 6562 case DeclUpdateKind::DeclMarkedOpenMPThreadPrivate:6563 Record.AddSourceRange(6564 D->getAttr<OMPThreadPrivateDeclAttr>()->getRange());6565 break;6566 6567 case DeclUpdateKind::DeclMarkedOpenMPAllocate: {6568 auto *A = D->getAttr<OMPAllocateDeclAttr>();6569 Record.push_back(A->getAllocatorType());6570 Record.AddStmt(A->getAllocator());6571 Record.AddStmt(A->getAlignment());6572 Record.AddSourceRange(A->getRange());6573 break;6574 }6575 6576 case DeclUpdateKind::DeclMarkedOpenMPDeclareTarget:6577 Record.push_back(D->getAttr<OMPDeclareTargetDeclAttr>()->getMapType());6578 Record.AddSourceRange(6579 D->getAttr<OMPDeclareTargetDeclAttr>()->getRange());6580 break;6581 6582 case DeclUpdateKind::DeclExported:6583 Record.push_back(getSubmoduleID(Update.getModule()));6584 break;6585 6586 case DeclUpdateKind::AddedAttrToRecord:6587 Record.AddAttributes(llvm::ArrayRef(Update.getAttr()));6588 break;6589 }6590 }6591 6592 // Add a trailing update record, if any. These must go last because we6593 // lazily load their attached statement.6594 if (!GeneratingReducedBMI || !CanElideDeclDef(D)) {6595 if (HasUpdatedBody) {6596 const auto *Def = cast<FunctionDecl>(D);6597 Record.push_back(6598 llvm::to_underlying(DeclUpdateKind::CXXAddedFunctionDefinition));6599 Record.push_back(Def->isInlined());6600 Record.AddSourceLocation(Def->getInnerLocStart());6601 Record.AddFunctionDefinition(Def);6602 } else if (HasAddedVarDefinition) {6603 const auto *VD = cast<VarDecl>(D);6604 Record.push_back(6605 llvm::to_underlying(DeclUpdateKind::CXXAddedVarDefinition));6606 Record.push_back(VD->isInline());6607 Record.push_back(VD->isInlineSpecified());6608 Record.AddVarDeclInit(VD);6609 }6610 }6611 6612 AddDeclRef(D, OffsetsRecord);6613 OffsetsRecord.push_back(Record.Emit(DECL_UPDATES));6614 }6615}6616 6617void ASTWriter::AddAlignPackInfo(const Sema::AlignPackInfo &Info,6618 RecordDataImpl &Record) {6619 uint32_t Raw = Sema::AlignPackInfo::getRawEncoding(Info);6620 Record.push_back(Raw);6621}6622 6623FileID ASTWriter::getAdjustedFileID(FileID FID) const {6624 if (FID.isInvalid() || PP->getSourceManager().isLoadedFileID(FID) ||6625 NonAffectingFileIDs.empty())6626 return FID;6627 auto It = llvm::lower_bound(NonAffectingFileIDs, FID);6628 unsigned Idx = std::distance(NonAffectingFileIDs.begin(), It);6629 unsigned Offset = NonAffectingFileIDAdjustments[Idx];6630 return FileID::get(FID.getOpaqueValue() - Offset);6631}6632 6633unsigned ASTWriter::getAdjustedNumCreatedFIDs(FileID FID) const {6634 unsigned NumCreatedFIDs = PP->getSourceManager()6635 .getLocalSLocEntry(FID.ID)6636 .getFile()6637 .NumCreatedFIDs;6638 6639 unsigned AdjustedNumCreatedFIDs = 0;6640 for (unsigned I = FID.ID, N = I + NumCreatedFIDs; I != N; ++I)6641 if (IsSLocAffecting[I])6642 ++AdjustedNumCreatedFIDs;6643 return AdjustedNumCreatedFIDs;6644}6645 6646SourceLocation ASTWriter::getAdjustedLocation(SourceLocation Loc) const {6647 if (Loc.isInvalid())6648 return Loc;6649 return Loc.getLocWithOffset(-getAdjustment(Loc.getOffset()));6650}6651 6652SourceRange ASTWriter::getAdjustedRange(SourceRange Range) const {6653 return SourceRange(getAdjustedLocation(Range.getBegin()),6654 getAdjustedLocation(Range.getEnd()));6655}6656 6657SourceLocation::UIntTy6658ASTWriter::getAdjustedOffset(SourceLocation::UIntTy Offset) const {6659 return Offset - getAdjustment(Offset);6660}6661 6662SourceLocation::UIntTy6663ASTWriter::getAdjustment(SourceLocation::UIntTy Offset) const {6664 if (NonAffectingRanges.empty())6665 return 0;6666 6667 if (PP->getSourceManager().isLoadedOffset(Offset))6668 return 0;6669 6670 if (Offset > NonAffectingRanges.back().getEnd().getOffset())6671 return NonAffectingOffsetAdjustments.back();6672 6673 if (Offset < NonAffectingRanges.front().getBegin().getOffset())6674 return 0;6675 6676 auto Contains = [](const SourceRange &Range, SourceLocation::UIntTy Offset) {6677 return Range.getEnd().getOffset() < Offset;6678 };6679 6680 auto It = llvm::lower_bound(NonAffectingRanges, Offset, Contains);6681 unsigned Idx = std::distance(NonAffectingRanges.begin(), It);6682 return NonAffectingOffsetAdjustments[Idx];6683}6684 6685void ASTWriter::AddFileID(FileID FID, RecordDataImpl &Record) {6686 Record.push_back(getAdjustedFileID(FID).getOpaqueValue());6687}6688 6689SourceLocationEncoding::RawLocEncoding6690ASTWriter::getRawSourceLocationEncoding(SourceLocation Loc) {6691 SourceLocation::UIntTy BaseOffset = 0;6692 unsigned ModuleFileIndex = 0;6693 6694 // See SourceLocationEncoding.h for the encoding details.6695 if (PP->getSourceManager().isLoadedSourceLocation(Loc) && Loc.isValid()) {6696 assert(getChain());6697 auto SLocMapI = getChain()->GlobalSLocOffsetMap.find(6698 SourceManager::MaxLoadedOffset - Loc.getOffset() - 1);6699 assert(SLocMapI != getChain()->GlobalSLocOffsetMap.end() &&6700 "Corrupted global sloc offset map");6701 ModuleFile *F = SLocMapI->second;6702 BaseOffset = F->SLocEntryBaseOffset - 2;6703 // 0 means the location is not loaded. So we need to add 1 to the index to6704 // make it clear.6705 ModuleFileIndex = F->Index + 1;6706 assert(&getChain()->getModuleManager()[F->Index] == F);6707 }6708 6709 return SourceLocationEncoding::encode(Loc, BaseOffset, ModuleFileIndex);6710}6711 6712void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) {6713 Loc = getAdjustedLocation(Loc);6714 Record.push_back(getRawSourceLocationEncoding(Loc));6715}6716 6717void ASTWriter::AddSourceRange(SourceRange Range, RecordDataImpl &Record) {6718 AddSourceLocation(Range.getBegin(), Record);6719 AddSourceLocation(Range.getEnd(), Record);6720}6721 6722void ASTRecordWriter::AddAPFloat(const llvm::APFloat &Value) {6723 AddAPInt(Value.bitcastToAPInt());6724}6725 6726void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record) {6727 Record.push_back(getIdentifierRef(II));6728}6729 6730IdentifierID ASTWriter::getIdentifierRef(const IdentifierInfo *II) {6731 if (!II)6732 return 0;6733 6734 IdentifierID &ID = IdentifierIDs[II];6735 if (ID == 0)6736 ID = NextIdentID++;6737 return ID;6738}6739 6740MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) {6741 // Don't emit builtin macros like __LINE__ to the AST file unless they6742 // have been redefined by the header (in which case they are not6743 // isBuiltinMacro).6744 if (!MI || MI->isBuiltinMacro())6745 return 0;6746 6747 MacroID &ID = MacroIDs[MI];6748 if (ID == 0) {6749 ID = NextMacroID++;6750 MacroInfoToEmitData Info = { Name, MI, ID };6751 MacroInfosToEmit.push_back(Info);6752 }6753 return ID;6754}6755 6756uint32_t ASTWriter::getMacroDirectivesOffset(const IdentifierInfo *Name) {6757 return IdentMacroDirectivesOffsetMap.lookup(Name);6758}6759 6760void ASTRecordWriter::AddSelectorRef(const Selector SelRef) {6761 Record->push_back(Writer->getSelectorRef(SelRef));6762}6763 6764SelectorID ASTWriter::getSelectorRef(Selector Sel) {6765 if (Sel.getAsOpaquePtr() == nullptr) {6766 return 0;6767 }6768 6769 SelectorID SID = SelectorIDs[Sel];6770 if (SID == 0 && Chain) {6771 // This might trigger a ReadSelector callback, which will set the ID for6772 // this selector.6773 Chain->LoadSelector(Sel);6774 SID = SelectorIDs[Sel];6775 }6776 if (SID == 0) {6777 SID = NextSelectorID++;6778 SelectorIDs[Sel] = SID;6779 }6780 return SID;6781}6782 6783void ASTRecordWriter::AddCXXTemporary(const CXXTemporary *Temp) {6784 AddDeclRef(Temp->getDestructor());6785}6786 6787void ASTRecordWriter::AddTemplateArgumentLocInfo(6788 const TemplateArgumentLoc &Arg) {6789 const TemplateArgumentLocInfo &Info = Arg.getLocInfo();6790 switch (auto K = Arg.getArgument().getKind()) {6791 case TemplateArgument::Expression:6792 AddStmt(Info.getAsExpr());6793 break;6794 case TemplateArgument::Type:6795 AddTypeSourceInfo(Info.getAsTypeSourceInfo());6796 break;6797 case TemplateArgument::Template:6798 case TemplateArgument::TemplateExpansion:6799 AddSourceLocation(Arg.getTemplateKWLoc());6800 AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc());6801 AddSourceLocation(Arg.getTemplateNameLoc());6802 if (K == TemplateArgument::TemplateExpansion)6803 AddSourceLocation(Arg.getTemplateEllipsisLoc());6804 break;6805 case TemplateArgument::Null:6806 case TemplateArgument::Integral:6807 case TemplateArgument::Declaration:6808 case TemplateArgument::NullPtr:6809 case TemplateArgument::StructuralValue:6810 case TemplateArgument::Pack:6811 // FIXME: Is this right?6812 break;6813 }6814}6815 6816void ASTRecordWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg) {6817 AddTemplateArgument(Arg.getArgument());6818 6819 if (Arg.getArgument().getKind() == TemplateArgument::Expression) {6820 bool InfoHasSameExpr6821 = Arg.getArgument().getAsExpr() == Arg.getLocInfo().getAsExpr();6822 Record->push_back(InfoHasSameExpr);6823 if (InfoHasSameExpr)6824 return; // Avoid storing the same expr twice.6825 }6826 AddTemplateArgumentLocInfo(Arg);6827}6828 6829void ASTRecordWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo) {6830 if (!TInfo) {6831 AddTypeRef(QualType());6832 return;6833 }6834 6835 AddTypeRef(TInfo->getType());6836 AddTypeLoc(TInfo->getTypeLoc());6837}6838 6839void ASTRecordWriter::AddTypeLoc(TypeLoc TL) {6840 TypeLocWriter TLW(*this);6841 for (; !TL.isNull(); TL = TL.getNextTypeLoc())6842 TLW.Visit(TL);6843}6844 6845void ASTWriter::AddTypeRef(ASTContext &Context, QualType T,6846 RecordDataImpl &Record) {6847 Record.push_back(GetOrCreateTypeID(Context, T));6848}6849 6850template <typename IdxForTypeTy>6851static TypeID MakeTypeID(ASTContext &Context, QualType T,6852 IdxForTypeTy IdxForType) {6853 if (T.isNull())6854 return PREDEF_TYPE_NULL_ID;6855 6856 unsigned FastQuals = T.getLocalFastQualifiers();6857 T.removeLocalFastQualifiers();6858 6859 if (T.hasLocalNonFastQualifiers())6860 return IdxForType(T).asTypeID(FastQuals);6861 6862 assert(!T.hasLocalQualifiers());6863 6864 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr()))6865 return TypeIdxFromBuiltin(BT).asTypeID(FastQuals);6866 6867 if (T == Context.AutoDeductTy)6868 return TypeIdx(0, PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals);6869 if (T == Context.AutoRRefDeductTy)6870 return TypeIdx(0, PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals);6871 6872 return IdxForType(T).asTypeID(FastQuals);6873}6874 6875TypeID ASTWriter::GetOrCreateTypeID(ASTContext &Context, QualType T) {6876 return MakeTypeID(Context, T, [&](QualType T) -> TypeIdx {6877 if (T.isNull())6878 return TypeIdx();6879 assert(!T.getLocalFastQualifiers());6880 6881 TypeIdx &Idx = TypeIdxs[T];6882 if (Idx.getValue() == 0) {6883 if (DoneWritingDeclsAndTypes) {6884 assert(0 && "New type seen after serializing all the types to emit!");6885 return TypeIdx();6886 }6887 6888 // We haven't seen this type before. Assign it a new ID and put it6889 // into the queue of types to emit.6890 Idx = TypeIdx(0, NextTypeID++);6891 DeclTypesToEmit.push(T);6892 }6893 return Idx;6894 });6895}6896 6897void ASTWriter::AddLookupOffsets(const LookupBlockOffsets &Offsets,6898 RecordDataImpl &Record) {6899 Record.push_back(Offsets.LexicalOffset);6900 Record.push_back(Offsets.VisibleOffset);6901 Record.push_back(Offsets.ModuleLocalOffset);6902 Record.push_back(Offsets.TULocalOffset);6903}6904 6905void ASTWriter::AddMacroRef(MacroInfo *MI, const IdentifierInfo *Name,6906 RecordDataImpl &Record) {6907 MacroID MacroRef = getMacroRef(MI, Name);6908 Record.push_back(MacroRef >> 32);6909 Record.push_back(MacroRef & llvm::maskTrailingOnes<MacroID>(32));6910}6911 6912void ASTWriter::AddEmittedDeclRef(const Decl *D, RecordDataImpl &Record) {6913 if (!wasDeclEmitted(D))6914 return;6915 6916 AddDeclRef(D, Record);6917}6918 6919void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) {6920 Record.push_back(GetDeclRef(D).getRawValue());6921}6922 6923LocalDeclID ASTWriter::GetDeclRef(const Decl *D) {6924 assert(WritingAST && "Cannot request a declaration ID before AST writing");6925 6926 if (!D) {6927 return LocalDeclID();6928 }6929 6930 // If the DeclUpdate from the GMF gets touched, emit it.6931 if (auto *Iter = DeclUpdatesFromGMF.find(D);6932 Iter != DeclUpdatesFromGMF.end()) {6933 for (DeclUpdate &Update : Iter->second)6934 DeclUpdates[D].push_back(Update);6935 DeclUpdatesFromGMF.erase(Iter);6936 }6937 6938 // If D comes from an AST file, its declaration ID is already known and6939 // fixed.6940 if (D->isFromASTFile()) {6941 if (isWritingStdCXXNamedModules() && D->getOwningModule())6942 TouchedTopLevelModules.insert(D->getOwningModule()->getTopLevelModule());6943 6944 return LocalDeclID(D->getGlobalID());6945 }6946 6947 assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer");6948 LocalDeclID &ID = DeclIDs[D];6949 if (ID.isInvalid()) {6950 if (DoneWritingDeclsAndTypes) {6951 assert(0 && "New decl seen after serializing all the decls to emit!");6952 return LocalDeclID();6953 }6954 6955 // We haven't seen this declaration before. Give it a new ID and6956 // enqueue it in the list of declarations to emit.6957 ID = NextDeclID++;6958 DeclTypesToEmit.push(const_cast<Decl *>(D));6959 }6960 6961 return ID;6962}6963 6964LocalDeclID ASTWriter::getDeclID(const Decl *D) {6965 if (!D)6966 return LocalDeclID();6967 6968 // If D comes from an AST file, its declaration ID is already known and6969 // fixed.6970 if (D->isFromASTFile())6971 return LocalDeclID(D->getGlobalID());6972 6973 assert(DeclIDs.contains(D) && "Declaration not emitted!");6974 return DeclIDs[D];6975}6976 6977bool ASTWriter::wasDeclEmitted(const Decl *D) const {6978 assert(D);6979 6980 assert(DoneWritingDeclsAndTypes &&6981 "wasDeclEmitted should only be called after writing declarations");6982 6983 if (D->isFromASTFile())6984 return true;6985 6986 bool Emitted = DeclIDs.contains(D);6987 assert((Emitted || (!D->getOwningModule() && isWritingStdCXXNamedModules()) ||6988 GeneratingReducedBMI) &&6989 "The declaration within modules can only be omitted in reduced BMI.");6990 return Emitted;6991}6992 6993void ASTWriter::associateDeclWithFile(const Decl *D, LocalDeclID ID) {6994 assert(ID.isValid());6995 assert(D);6996 6997 SourceLocation Loc = D->getLocation();6998 if (Loc.isInvalid())6999 return;7000 7001 // We only keep track of the file-level declarations of each file.7002 if (!D->getLexicalDeclContext()->isFileContext())7003 return;7004 // FIXME: ParmVarDecls that are part of a function type of a parameter of7005 // a function/objc method, should not have TU as lexical context.7006 // TemplateTemplateParmDecls that are part of an alias template, should not7007 // have TU as lexical context.7008 if (isa<ParmVarDecl, TemplateTemplateParmDecl>(D))7009 return;7010 7011 SourceManager &SM = PP->getSourceManager();7012 SourceLocation FileLoc = SM.getFileLoc(Loc);7013 assert(SM.isLocalSourceLocation(FileLoc));7014 auto [FID, Offset] = SM.getDecomposedLoc(FileLoc);7015 if (FID.isInvalid())7016 return;7017 assert(SM.getSLocEntry(FID).isFile());7018 assert(IsSLocAffecting[FID.ID]);7019 7020 std::unique_ptr<DeclIDInFileInfo> &Info = FileDeclIDs[FID];7021 if (!Info)7022 Info = std::make_unique<DeclIDInFileInfo>();7023 7024 std::pair<unsigned, LocalDeclID> LocDecl(Offset, ID);7025 LocDeclIDsTy &Decls = Info->DeclIDs;7026 Decls.push_back(LocDecl);7027}7028 7029unsigned ASTWriter::getAnonymousDeclarationNumber(const NamedDecl *D) {7030 assert(needsAnonymousDeclarationNumber(D) &&7031 "expected an anonymous declaration");7032 7033 // Number the anonymous declarations within this context, if we've not7034 // already done so.7035 auto It = AnonymousDeclarationNumbers.find(D);7036 if (It == AnonymousDeclarationNumbers.end()) {7037 auto *DC = D->getLexicalDeclContext();7038 numberAnonymousDeclsWithin(DC, [&](const NamedDecl *ND, unsigned Number) {7039 AnonymousDeclarationNumbers[ND] = Number;7040 });7041 7042 It = AnonymousDeclarationNumbers.find(D);7043 assert(It != AnonymousDeclarationNumbers.end() &&7044 "declaration not found within its lexical context");7045 }7046 7047 return It->second;7048}7049 7050void ASTRecordWriter::AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc,7051 DeclarationName Name) {7052 switch (Name.getNameKind()) {7053 case DeclarationName::CXXConstructorName:7054 case DeclarationName::CXXDestructorName:7055 case DeclarationName::CXXConversionFunctionName:7056 AddTypeSourceInfo(DNLoc.getNamedTypeInfo());7057 break;7058 7059 case DeclarationName::CXXOperatorName:7060 AddSourceRange(DNLoc.getCXXOperatorNameRange());7061 break;7062 7063 case DeclarationName::CXXLiteralOperatorName:7064 AddSourceLocation(DNLoc.getCXXLiteralOperatorNameLoc());7065 break;7066 7067 case DeclarationName::Identifier:7068 case DeclarationName::ObjCZeroArgSelector:7069 case DeclarationName::ObjCOneArgSelector:7070 case DeclarationName::ObjCMultiArgSelector:7071 case DeclarationName::CXXUsingDirective:7072 case DeclarationName::CXXDeductionGuideName:7073 break;7074 }7075}7076 7077void ASTRecordWriter::AddDeclarationNameInfo(7078 const DeclarationNameInfo &NameInfo) {7079 AddDeclarationName(NameInfo.getName());7080 AddSourceLocation(NameInfo.getLoc());7081 AddDeclarationNameLoc(NameInfo.getInfo(), NameInfo.getName());7082}7083 7084void ASTRecordWriter::AddQualifierInfo(const QualifierInfo &Info) {7085 AddNestedNameSpecifierLoc(Info.QualifierLoc);7086 Record->push_back(Info.NumTemplParamLists);7087 for (unsigned i = 0, e = Info.NumTemplParamLists; i != e; ++i)7088 AddTemplateParameterList(Info.TemplParamLists[i]);7089}7090 7091void ASTRecordWriter::AddNestedNameSpecifierLoc(7092 NestedNameSpecifierLoc QualifierLoc) {7093 // Nested name specifiers usually aren't too long. I think that 8 would7094 // typically accommodate the vast majority.7095 SmallVector<NestedNameSpecifierLoc , 8> NestedNames;7096 7097 // Push each of the nested-name-specifiers's onto a stack for7098 // serialization in reverse order.7099 while (QualifierLoc) {7100 NestedNames.push_back(QualifierLoc);7101 QualifierLoc = QualifierLoc.getAsNamespaceAndPrefix().Prefix;7102 }7103 7104 Record->push_back(NestedNames.size());7105 while(!NestedNames.empty()) {7106 QualifierLoc = NestedNames.pop_back_val();7107 NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier();7108 NestedNameSpecifier::Kind Kind = Qualifier.getKind();7109 Record->push_back(llvm::to_underlying(Kind));7110 switch (Kind) {7111 case NestedNameSpecifier::Kind::Namespace:7112 AddDeclRef(Qualifier.getAsNamespaceAndPrefix().Namespace);7113 AddSourceRange(QualifierLoc.getLocalSourceRange());7114 break;7115 7116 case NestedNameSpecifier::Kind::Type: {7117 TypeLoc TL = QualifierLoc.castAsTypeLoc();7118 AddTypeRef(TL.getType());7119 AddTypeLoc(TL);7120 AddSourceLocation(QualifierLoc.getLocalSourceRange().getEnd());7121 break;7122 }7123 7124 case NestedNameSpecifier::Kind::Global:7125 AddSourceLocation(QualifierLoc.getLocalSourceRange().getEnd());7126 break;7127 7128 case NestedNameSpecifier::Kind::MicrosoftSuper:7129 AddDeclRef(Qualifier.getAsMicrosoftSuper());7130 AddSourceRange(QualifierLoc.getLocalSourceRange());7131 break;7132 7133 case NestedNameSpecifier::Kind::Null:7134 llvm_unreachable("unexpected null nested name specifier");7135 }7136 }7137}7138 7139void ASTRecordWriter::AddTemplateParameterList(7140 const TemplateParameterList *TemplateParams) {7141 assert(TemplateParams && "No TemplateParams!");7142 AddSourceLocation(TemplateParams->getTemplateLoc());7143 AddSourceLocation(TemplateParams->getLAngleLoc());7144 AddSourceLocation(TemplateParams->getRAngleLoc());7145 7146 Record->push_back(TemplateParams->size());7147 for (const auto &P : *TemplateParams)7148 AddDeclRef(P);7149 if (const Expr *RequiresClause = TemplateParams->getRequiresClause()) {7150 Record->push_back(true);7151 writeStmtRef(RequiresClause);7152 } else {7153 Record->push_back(false);7154 }7155}7156 7157/// Emit a template argument list.7158void ASTRecordWriter::AddTemplateArgumentList(7159 const TemplateArgumentList *TemplateArgs) {7160 assert(TemplateArgs && "No TemplateArgs!");7161 Record->push_back(TemplateArgs->size());7162 for (int i = 0, e = TemplateArgs->size(); i != e; ++i)7163 AddTemplateArgument(TemplateArgs->get(i));7164}7165 7166void ASTRecordWriter::AddASTTemplateArgumentListInfo(7167 const ASTTemplateArgumentListInfo *ASTTemplArgList) {7168 assert(ASTTemplArgList && "No ASTTemplArgList!");7169 AddSourceLocation(ASTTemplArgList->LAngleLoc);7170 AddSourceLocation(ASTTemplArgList->RAngleLoc);7171 Record->push_back(ASTTemplArgList->NumTemplateArgs);7172 const TemplateArgumentLoc *TemplArgs = ASTTemplArgList->getTemplateArgs();7173 for (int i = 0, e = ASTTemplArgList->NumTemplateArgs; i != e; ++i)7174 AddTemplateArgumentLoc(TemplArgs[i]);7175}7176 7177void ASTRecordWriter::AddUnresolvedSet(const ASTUnresolvedSet &Set) {7178 Record->push_back(Set.size());7179 for (ASTUnresolvedSet::const_iterator7180 I = Set.begin(), E = Set.end(); I != E; ++I) {7181 AddDeclRef(I.getDecl());7182 Record->push_back(I.getAccess());7183 }7184}7185 7186// FIXME: Move this out of the main ASTRecordWriter interface.7187void ASTRecordWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base) {7188 Record->push_back(Base.isVirtual());7189 Record->push_back(Base.isBaseOfClass());7190 Record->push_back(Base.getAccessSpecifierAsWritten());7191 Record->push_back(Base.getInheritConstructors());7192 AddTypeSourceInfo(Base.getTypeSourceInfo());7193 AddSourceRange(Base.getSourceRange());7194 AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc()7195 : SourceLocation());7196}7197 7198static uint64_t EmitCXXBaseSpecifiers(ASTContext &Context, ASTWriter &W,7199 ArrayRef<CXXBaseSpecifier> Bases) {7200 ASTWriter::RecordData Record;7201 ASTRecordWriter Writer(Context, W, Record);7202 Writer.push_back(Bases.size());7203 7204 for (auto &Base : Bases)7205 Writer.AddCXXBaseSpecifier(Base);7206 7207 return Writer.Emit(serialization::DECL_CXX_BASE_SPECIFIERS);7208}7209 7210// FIXME: Move this out of the main ASTRecordWriter interface.7211void ASTRecordWriter::AddCXXBaseSpecifiers(ArrayRef<CXXBaseSpecifier> Bases) {7212 AddOffset(EmitCXXBaseSpecifiers(getASTContext(), *Writer, Bases));7213}7214 7215static uint64_t7216EmitCXXCtorInitializers(ASTContext &Context, ASTWriter &W,7217 ArrayRef<CXXCtorInitializer *> CtorInits) {7218 ASTWriter::RecordData Record;7219 ASTRecordWriter Writer(Context, W, Record);7220 Writer.push_back(CtorInits.size());7221 7222 for (auto *Init : CtorInits) {7223 if (Init->isBaseInitializer()) {7224 Writer.push_back(CTOR_INITIALIZER_BASE);7225 Writer.AddTypeSourceInfo(Init->getTypeSourceInfo());7226 Writer.push_back(Init->isBaseVirtual());7227 } else if (Init->isDelegatingInitializer()) {7228 Writer.push_back(CTOR_INITIALIZER_DELEGATING);7229 Writer.AddTypeSourceInfo(Init->getTypeSourceInfo());7230 } else if (Init->isMemberInitializer()){7231 Writer.push_back(CTOR_INITIALIZER_MEMBER);7232 Writer.AddDeclRef(Init->getMember());7233 } else {7234 Writer.push_back(CTOR_INITIALIZER_INDIRECT_MEMBER);7235 Writer.AddDeclRef(Init->getIndirectMember());7236 }7237 7238 Writer.AddSourceLocation(Init->getMemberLocation());7239 Writer.AddStmt(Init->getInit());7240 Writer.AddSourceLocation(Init->getLParenLoc());7241 Writer.AddSourceLocation(Init->getRParenLoc());7242 Writer.push_back(Init->isWritten());7243 if (Init->isWritten())7244 Writer.push_back(Init->getSourceOrder());7245 }7246 7247 return Writer.Emit(serialization::DECL_CXX_CTOR_INITIALIZERS);7248}7249 7250// FIXME: Move this out of the main ASTRecordWriter interface.7251void ASTRecordWriter::AddCXXCtorInitializers(7252 ArrayRef<CXXCtorInitializer *> CtorInits) {7253 AddOffset(EmitCXXCtorInitializers(getASTContext(), *Writer, CtorInits));7254}7255 7256void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {7257 auto &Data = D->data();7258 7259 Record->push_back(Data.IsLambda);7260 7261 BitsPacker DefinitionBits;7262 7263#define FIELD(Name, Width, Merge) \7264 if (!DefinitionBits.canWriteNextNBits(Width)) { \7265 Record->push_back(DefinitionBits); \7266 DefinitionBits.reset(0); \7267 } \7268 DefinitionBits.addBits(Data.Name, Width);7269 7270#include "clang/AST/CXXRecordDeclDefinitionBits.def"7271#undef FIELD7272 7273 Record->push_back(DefinitionBits);7274 7275 // getODRHash will compute the ODRHash if it has not been previously7276 // computed.7277 Record->push_back(D->getODRHash());7278 7279 bool ModulesCodegen =7280 !D->isDependentType() &&7281 D->getTemplateSpecializationKind() !=7282 TSK_ExplicitInstantiationDeclaration &&7283 (Writer->getLangOpts().ModulesDebugInfo || D->isInNamedModule());7284 Record->push_back(ModulesCodegen);7285 if (ModulesCodegen)7286 Writer->AddDeclRef(D, Writer->ModularCodegenDecls);7287 7288 // IsLambda bit is already saved.7289 7290 AddUnresolvedSet(Data.Conversions.get(getASTContext()));7291 Record->push_back(Data.ComputedVisibleConversions);7292 if (Data.ComputedVisibleConversions)7293 AddUnresolvedSet(Data.VisibleConversions.get(getASTContext()));7294 // Data.Definition is the owning decl, no need to write it.7295 7296 if (!Data.IsLambda) {7297 Record->push_back(Data.NumBases);7298 if (Data.NumBases > 0)7299 AddCXXBaseSpecifiers(Data.bases());7300 7301 // FIXME: Make VBases lazily computed when needed to avoid storing them.7302 Record->push_back(Data.NumVBases);7303 if (Data.NumVBases > 0)7304 AddCXXBaseSpecifiers(Data.vbases());7305 7306 AddDeclRef(D->getFirstFriend());7307 } else {7308 auto &Lambda = D->getLambdaData();7309 7310 BitsPacker LambdaBits;7311 LambdaBits.addBits(Lambda.DependencyKind, /*Width=*/2);7312 LambdaBits.addBit(Lambda.IsGenericLambda);7313 LambdaBits.addBits(Lambda.CaptureDefault, /*Width=*/2);7314 LambdaBits.addBits(Lambda.NumCaptures, /*Width=*/15);7315 LambdaBits.addBit(Lambda.HasKnownInternalLinkage);7316 Record->push_back(LambdaBits);7317 7318 Record->push_back(Lambda.NumExplicitCaptures);7319 Record->push_back(Lambda.ManglingNumber);7320 Record->push_back(D->getDeviceLambdaManglingNumber());7321 // The lambda context declaration and index within the context are provided7322 // separately, so that they can be used for merging.7323 AddTypeSourceInfo(Lambda.MethodTyInfo);7324 for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {7325 const LambdaCapture &Capture = Lambda.Captures.front()[I];7326 AddSourceLocation(Capture.getLocation());7327 7328 BitsPacker CaptureBits;7329 CaptureBits.addBit(Capture.isImplicit());7330 CaptureBits.addBits(Capture.getCaptureKind(), /*Width=*/3);7331 Record->push_back(CaptureBits);7332 7333 switch (Capture.getCaptureKind()) {7334 case LCK_StarThis:7335 case LCK_This:7336 case LCK_VLAType:7337 break;7338 case LCK_ByCopy:7339 case LCK_ByRef:7340 ValueDecl *Var =7341 Capture.capturesVariable() ? Capture.getCapturedVar() : nullptr;7342 AddDeclRef(Var);7343 AddSourceLocation(Capture.isPackExpansion() ? Capture.getEllipsisLoc()7344 : SourceLocation());7345 break;7346 }7347 }7348 }7349}7350 7351void ASTRecordWriter::AddVarDeclInit(const VarDecl *VD) {7352 const Expr *Init = VD->getInit();7353 if (!Init) {7354 push_back(0);7355 return;7356 }7357 7358 uint64_t Val = 1;7359 if (EvaluatedStmt *ES = VD->getEvaluatedStmt()) {7360 // This may trigger evaluation, so run it first7361 if (VD->hasInitWithSideEffects())7362 Val |= 16;7363 assert(ES->CheckedForSideEffects);7364 Val |= (ES->HasConstantInitialization ? 2 : 0);7365 Val |= (ES->HasConstantDestruction ? 4 : 0);7366 APValue *Evaluated = VD->getEvaluatedValue();7367 // If the evaluated result is constant, emit it.7368 if (Evaluated && (Evaluated->isInt() || Evaluated->isFloat()))7369 Val |= 8;7370 }7371 push_back(Val);7372 if (Val & 8) {7373 AddAPValue(*VD->getEvaluatedValue());7374 }7375 7376 writeStmtRef(Init);7377}7378 7379void ASTWriter::ReaderInitialized(ASTReader *Reader) {7380 assert(Reader && "Cannot remove chain");7381 assert((!Chain || Chain == Reader) && "Cannot replace chain");7382 assert(FirstDeclID == NextDeclID &&7383 FirstTypeID == NextTypeID &&7384 FirstIdentID == NextIdentID &&7385 FirstMacroID == NextMacroID &&7386 FirstSubmoduleID == NextSubmoduleID &&7387 FirstSelectorID == NextSelectorID &&7388 "Setting chain after writing has started.");7389 7390 Chain = Reader;7391 7392 FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules();7393 FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors();7394 NextSelectorID = FirstSelectorID;7395 NextSubmoduleID = FirstSubmoduleID;7396}7397 7398void ASTWriter::IdentifierRead(IdentifierID ID, IdentifierInfo *II) {7399 // Don't reuse Type ID from external modules for named modules. See the7400 // comments in WriteASTCore for details.7401 if (isWritingStdCXXNamedModules())7402 return;7403 7404 IdentifierID &StoredID = IdentifierIDs[II];7405 unsigned OriginalModuleFileIndex = StoredID >> 32;7406 7407 // Always keep the local identifier ID. See \p TypeRead() for more7408 // information.7409 if (OriginalModuleFileIndex == 0 && StoredID)7410 return;7411 7412 // Otherwise, keep the highest ID since the module file comes later has7413 // higher module file indexes.7414 if (ID > StoredID)7415 StoredID = ID;7416}7417 7418void ASTWriter::MacroRead(serialization::MacroID ID, MacroInfo *MI) {7419 // Always keep the highest ID. See \p TypeRead() for more information.7420 MacroID &StoredID = MacroIDs[MI];7421 unsigned OriginalModuleFileIndex = StoredID >> 32;7422 7423 // Always keep the local macro ID. See \p TypeRead() for more information.7424 if (OriginalModuleFileIndex == 0 && StoredID)7425 return;7426 7427 // Otherwise, keep the highest ID since the module file comes later has7428 // higher module file indexes.7429 if (ID > StoredID)7430 StoredID = ID;7431}7432 7433void ASTWriter::TypeRead(TypeIdx Idx, QualType T) {7434 // Don't reuse Type ID from external modules for named modules. See the7435 // comments in WriteASTCore for details.7436 if (isWritingStdCXXNamedModules())7437 return;7438 7439 // Always take the type index that comes in later module files.7440 // This copes with an interesting7441 // case for chained AST writing where we schedule writing the type and then,7442 // later, deserialize the type from another AST. In this case, we want to7443 // keep the entry from a later module so that we can properly write it out to7444 // the AST file.7445 TypeIdx &StoredIdx = TypeIdxs[T];7446 7447 // Ignore it if the type comes from the current being written module file.7448 // Since the current module file being written logically has the highest7449 // index.7450 unsigned ModuleFileIndex = StoredIdx.getModuleFileIndex();7451 if (ModuleFileIndex == 0 && StoredIdx.getValue())7452 return;7453 7454 // Otherwise, keep the highest ID since the module file comes later has7455 // higher module file indexes.7456 if (Idx.getModuleFileIndex() >= StoredIdx.getModuleFileIndex())7457 StoredIdx = Idx;7458}7459 7460void ASTWriter::PredefinedDeclBuilt(PredefinedDeclIDs ID, const Decl *D) {7461 assert(D->isCanonicalDecl() && "predefined decl is not canonical");7462 DeclIDs[D] = LocalDeclID(ID);7463 PredefinedDecls.insert(D);7464}7465 7466void ASTWriter::SelectorRead(SelectorID ID, Selector S) {7467 // Always keep the highest ID. See \p TypeRead() for more information.7468 SelectorID &StoredID = SelectorIDs[S];7469 if (ID > StoredID)7470 StoredID = ID;7471}7472 7473void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID,7474 MacroDefinitionRecord *MD) {7475 assert(!MacroDefinitions.contains(MD));7476 MacroDefinitions[MD] = ID;7477}7478 7479void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) {7480 assert(!SubmoduleIDs.contains(Mod));7481 SubmoduleIDs[Mod] = ID;7482}7483 7484void ASTWriter::CompletedTagDefinition(const TagDecl *D) {7485 if (Chain && Chain->isProcessingUpdateRecords()) return;7486 assert(D->isCompleteDefinition());7487 assert(!WritingAST && "Already writing the AST!");7488 if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {7489 // We are interested when a PCH decl is modified.7490 if (RD->isFromASTFile()) {7491 // A forward reference was mutated into a definition. Rewrite it.7492 // FIXME: This happens during template instantiation, should we7493 // have created a new definition decl instead ?7494 assert(isTemplateInstantiation(RD->getTemplateSpecializationKind()) &&7495 "completed a tag from another module but not by instantiation?");7496 DeclUpdates[RD].push_back(7497 DeclUpdate(DeclUpdateKind::CXXInstantiatedClassDefinition));7498 }7499 }7500}7501 7502static bool isImportedDeclContext(ASTReader *Chain, const Decl *D) {7503 if (D->isFromASTFile())7504 return true;7505 7506 // The predefined __va_list_tag struct is imported if we imported any decls.7507 // FIXME: This is a gross hack.7508 return D == D->getASTContext().getVaListTagDecl();7509}7510 7511void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {7512 if (Chain && Chain->isProcessingUpdateRecords()) return;7513 assert(DC->isLookupContext() &&7514 "Should not add lookup results to non-lookup contexts!");7515 7516 // TU is handled elsewhere.7517 if (isa<TranslationUnitDecl>(DC))7518 return;7519 7520 // Namespaces are handled elsewhere, except for template instantiations of7521 // FunctionTemplateDecls in namespaces. We are interested in cases where the7522 // local instantiations are added to an imported context. Only happens when7523 // adding ADL lookup candidates, for example templated friends.7524 if (isa<NamespaceDecl>(DC) && D->getFriendObjectKind() == Decl::FOK_None &&7525 !isa<FunctionTemplateDecl>(D))7526 return;7527 7528 // We're only interested in cases where a local declaration is added to an7529 // imported context.7530 if (D->isFromASTFile() || !isImportedDeclContext(Chain, cast<Decl>(DC)))7531 return;7532 7533 assert(DC == DC->getPrimaryContext() && "added to non-primary context");7534 assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!");7535 assert(!WritingAST && "Already writing the AST!");7536 if (UpdatedDeclContexts.insert(DC) && !cast<Decl>(DC)->isFromASTFile()) {7537 // We're adding a visible declaration to a predefined decl context. Ensure7538 // that we write out all of its lookup results so we don't get a nasty7539 // surprise when we try to emit its lookup table.7540 llvm::append_range(DeclsToEmitEvenIfUnreferenced, DC->decls());7541 }7542 DeclsToEmitEvenIfUnreferenced.push_back(D);7543}7544 7545void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {7546 if (Chain && Chain->isProcessingUpdateRecords()) return;7547 assert(D->isImplicit());7548 7549 // We're only interested in cases where a local declaration is added to an7550 // imported context.7551 if (D->isFromASTFile() || !isImportedDeclContext(Chain, RD))7552 return;7553 7554 if (!isa<CXXMethodDecl>(D))7555 return;7556 7557 // A decl coming from PCH was modified.7558 assert(RD->isCompleteDefinition());7559 assert(!WritingAST && "Already writing the AST!");7560 DeclUpdates[RD].push_back(7561 DeclUpdate(DeclUpdateKind::CXXAddedImplicitMember, D));7562}7563 7564void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {7565 if (Chain && Chain->isProcessingUpdateRecords()) return;7566 assert(!DoneWritingDeclsAndTypes && "Already done writing updates!");7567 if (!Chain) return;7568 Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {7569 // If we don't already know the exception specification for this redecl7570 // chain, add an update record for it.7571 if (isUnresolvedExceptionSpec(cast<FunctionDecl>(D)7572 ->getType()7573 ->castAs<FunctionProtoType>()7574 ->getExceptionSpecType()))7575 DeclUpdates[D].push_back(DeclUpdateKind::CXXResolvedExceptionSpec);7576 });7577}7578 7579void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {7580 if (Chain && Chain->isProcessingUpdateRecords()) return;7581 assert(!WritingAST && "Already writing the AST!");7582 if (!Chain) return;7583 Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {7584 DeclUpdates[D].push_back(7585 DeclUpdate(DeclUpdateKind::CXXDeducedReturnType, ReturnType));7586 });7587}7588 7589void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD,7590 const FunctionDecl *Delete,7591 Expr *ThisArg) {7592 if (Chain && Chain->isProcessingUpdateRecords()) return;7593 assert(!WritingAST && "Already writing the AST!");7594 assert(Delete && "Not given an operator delete");7595 if (!Chain) return;7596 Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) {7597 DeclUpdates[D].push_back(7598 DeclUpdate(DeclUpdateKind::CXXResolvedDtorDelete, Delete));7599 });7600}7601 7602void ASTWriter::ResolvedOperatorGlobDelete(const CXXDestructorDecl *DD,7603 const FunctionDecl *GlobDelete) {7604 if (Chain && Chain->isProcessingUpdateRecords())7605 return;7606 assert(!WritingAST && "Already writing the AST!");7607 assert(GlobDelete && "Not given an operator delete");7608 if (!Chain)7609 return;7610 Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) {7611 DeclUpdates[D].push_back(7612 DeclUpdate(DeclUpdateKind::CXXResolvedDtorGlobDelete, GlobDelete));7613 });7614}7615 7616void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {7617 if (Chain && Chain->isProcessingUpdateRecords()) return;7618 assert(!WritingAST && "Already writing the AST!");7619 if (!D->isFromASTFile())7620 return; // Declaration not imported from PCH.7621 7622 // The function definition may not have a body due to parsing errors.7623 if (!D->doesThisDeclarationHaveABody())7624 return;7625 7626 // Implicit function decl from a PCH was defined.7627 DeclUpdates[D].push_back(7628 DeclUpdate(DeclUpdateKind::CXXAddedFunctionDefinition));7629}7630 7631void ASTWriter::VariableDefinitionInstantiated(const VarDecl *D) {7632 if (Chain && Chain->isProcessingUpdateRecords()) return;7633 assert(!WritingAST && "Already writing the AST!");7634 if (!D->isFromASTFile())7635 return;7636 7637 DeclUpdates[D].push_back(DeclUpdate(DeclUpdateKind::CXXAddedVarDefinition));7638}7639 7640void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {7641 if (Chain && Chain->isProcessingUpdateRecords()) return;7642 assert(!WritingAST && "Already writing the AST!");7643 if (!D->isFromASTFile())7644 return;7645 7646 // The function definition may not have a body due to parsing errors.7647 if (!D->doesThisDeclarationHaveABody())7648 return;7649 7650 DeclUpdates[D].push_back(7651 DeclUpdate(DeclUpdateKind::CXXAddedFunctionDefinition));7652}7653 7654void ASTWriter::InstantiationRequested(const ValueDecl *D) {7655 if (Chain && Chain->isProcessingUpdateRecords()) return;7656 assert(!WritingAST && "Already writing the AST!");7657 if (!D->isFromASTFile())7658 return;7659 7660 // Since the actual instantiation is delayed, this really means that we need7661 // to update the instantiation location.7662 SourceLocation POI;7663 if (auto *VD = dyn_cast<VarDecl>(D))7664 POI = VD->getPointOfInstantiation();7665 else7666 POI = cast<FunctionDecl>(D)->getPointOfInstantiation();7667 DeclUpdates[D].push_back(7668 DeclUpdate(DeclUpdateKind::CXXPointOfInstantiation, POI));7669}7670 7671void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) {7672 if (Chain && Chain->isProcessingUpdateRecords()) return;7673 assert(!WritingAST && "Already writing the AST!");7674 if (!D->isFromASTFile())7675 return;7676 7677 DeclUpdates[D].push_back(7678 DeclUpdate(DeclUpdateKind::CXXInstantiatedDefaultArgument, D));7679}7680 7681void ASTWriter::DefaultMemberInitializerInstantiated(const FieldDecl *D) {7682 assert(!WritingAST && "Already writing the AST!");7683 if (!D->isFromASTFile())7684 return;7685 7686 DeclUpdates[D].push_back(7687 DeclUpdate(DeclUpdateKind::CXXInstantiatedDefaultMemberInitializer, D));7688}7689 7690void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,7691 const ObjCInterfaceDecl *IFD) {7692 if (Chain && Chain->isProcessingUpdateRecords()) return;7693 assert(!WritingAST && "Already writing the AST!");7694 if (!IFD->isFromASTFile())7695 return; // Declaration not imported from PCH.7696 7697 assert(IFD->getDefinition() && "Category on a class without a definition?");7698 ObjCClassesWithCategories.insert(7699 const_cast<ObjCInterfaceDecl *>(IFD->getDefinition()));7700}7701 7702void ASTWriter::DeclarationMarkedUsed(const Decl *D) {7703 if (Chain && Chain->isProcessingUpdateRecords()) return;7704 assert(!WritingAST && "Already writing the AST!");7705 7706 // If there is *any* declaration of the entity that's not from an AST file,7707 // we can skip writing the update record. We make sure that isUsed() triggers7708 // completion of the redeclaration chain of the entity.7709 for (auto Prev = D->getMostRecentDecl(); Prev; Prev = Prev->getPreviousDecl())7710 if (IsLocalDecl(Prev))7711 return;7712 7713 DeclUpdates[D].push_back(DeclUpdate(DeclUpdateKind::DeclMarkedUsed));7714}7715 7716void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {7717 if (Chain && Chain->isProcessingUpdateRecords()) return;7718 assert(!WritingAST && "Already writing the AST!");7719 if (!D->isFromASTFile())7720 return;7721 7722 DeclUpdates[D].push_back(7723 DeclUpdate(DeclUpdateKind::DeclMarkedOpenMPThreadPrivate));7724}7725 7726void ASTWriter::DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) {7727 if (Chain && Chain->isProcessingUpdateRecords()) return;7728 assert(!WritingAST && "Already writing the AST!");7729 if (!D->isFromASTFile())7730 return;7731 7732 DeclUpdates[D].push_back(7733 DeclUpdate(DeclUpdateKind::DeclMarkedOpenMPAllocate, A));7734}7735 7736void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D,7737 const Attr *Attr) {7738 if (Chain && Chain->isProcessingUpdateRecords()) return;7739 assert(!WritingAST && "Already writing the AST!");7740 if (!D->isFromASTFile())7741 return;7742 7743 DeclUpdates[D].push_back(7744 DeclUpdate(DeclUpdateKind::DeclMarkedOpenMPDeclareTarget, Attr));7745}7746 7747void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {7748 if (Chain && Chain->isProcessingUpdateRecords()) return;7749 assert(!WritingAST && "Already writing the AST!");7750 assert(!D->isUnconditionallyVisible() && "expected a hidden declaration");7751 DeclUpdates[D].push_back(DeclUpdate(DeclUpdateKind::DeclExported, M));7752}7753 7754void ASTWriter::AddedAttributeToRecord(const Attr *Attr,7755 const RecordDecl *Record) {7756 if (Chain && Chain->isProcessingUpdateRecords()) return;7757 assert(!WritingAST && "Already writing the AST!");7758 if (!Record->isFromASTFile())7759 return;7760 DeclUpdates[Record].push_back(7761 DeclUpdate(DeclUpdateKind::AddedAttrToRecord, Attr));7762}7763 7764void ASTWriter::AddedCXXTemplateSpecialization(7765 const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) {7766 assert(!WritingAST && "Already writing the AST!");7767 7768 if (!TD->getFirstDecl()->isFromASTFile())7769 return;7770 if (Chain && Chain->isProcessingUpdateRecords())7771 return;7772 7773 DeclsToEmitEvenIfUnreferenced.push_back(D);7774}7775 7776void ASTWriter::AddedCXXTemplateSpecialization(7777 const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) {7778 assert(!WritingAST && "Already writing the AST!");7779 7780 if (!TD->getFirstDecl()->isFromASTFile())7781 return;7782 if (Chain && Chain->isProcessingUpdateRecords())7783 return;7784 7785 DeclsToEmitEvenIfUnreferenced.push_back(D);7786}7787 7788void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,7789 const FunctionDecl *D) {7790 assert(!WritingAST && "Already writing the AST!");7791 7792 if (!TD->getFirstDecl()->isFromASTFile())7793 return;7794 if (Chain && Chain->isProcessingUpdateRecords())7795 return;7796 7797 DeclsToEmitEvenIfUnreferenced.push_back(D);7798}7799 7800//===----------------------------------------------------------------------===//7801//// OMPClause Serialization7802////===----------------------------------------------------------------------===//7803 7804namespace {7805 7806class OMPClauseWriter : public OMPClauseVisitor<OMPClauseWriter> {7807 ASTRecordWriter &Record;7808 7809public:7810 OMPClauseWriter(ASTRecordWriter &Record) : Record(Record) {}7811#define GEN_CLANG_CLAUSE_CLASS7812#define CLAUSE_CLASS(Enum, Str, Class) void Visit##Class(Class *S);7813#include "llvm/Frontend/OpenMP/OMP.inc"7814 void writeClause(OMPClause *C);7815 void VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C);7816 void VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C);7817};7818 7819}7820 7821void ASTRecordWriter::writeOMPClause(OMPClause *C) {7822 OMPClauseWriter(*this).writeClause(C);7823}7824 7825void OMPClauseWriter::writeClause(OMPClause *C) {7826 Record.push_back(unsigned(C->getClauseKind()));7827 Visit(C);7828 Record.AddSourceLocation(C->getBeginLoc());7829 Record.AddSourceLocation(C->getEndLoc());7830}7831 7832void OMPClauseWriter::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) {7833 Record.push_back(uint64_t(C->getCaptureRegion()));7834 Record.AddStmt(C->getPreInitStmt());7835}7836 7837void OMPClauseWriter::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) {7838 VisitOMPClauseWithPreInit(C);7839 Record.AddStmt(C->getPostUpdateExpr());7840}7841 7842void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) {7843 VisitOMPClauseWithPreInit(C);7844 Record.push_back(uint64_t(C->getNameModifier()));7845 Record.AddSourceLocation(C->getNameModifierLoc());7846 Record.AddSourceLocation(C->getColonLoc());7847 Record.AddStmt(C->getCondition());7848 Record.AddSourceLocation(C->getLParenLoc());7849}7850 7851void OMPClauseWriter::VisitOMPFinalClause(OMPFinalClause *C) {7852 VisitOMPClauseWithPreInit(C);7853 Record.AddStmt(C->getCondition());7854 Record.AddSourceLocation(C->getLParenLoc());7855}7856 7857void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {7858 VisitOMPClauseWithPreInit(C);7859 Record.writeEnum(C->getModifier());7860 Record.AddStmt(C->getNumThreads());7861 Record.AddSourceLocation(C->getModifierLoc());7862 Record.AddSourceLocation(C->getLParenLoc());7863}7864 7865void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) {7866 Record.AddStmt(C->getSafelen());7867 Record.AddSourceLocation(C->getLParenLoc());7868}7869 7870void OMPClauseWriter::VisitOMPSimdlenClause(OMPSimdlenClause *C) {7871 Record.AddStmt(C->getSimdlen());7872 Record.AddSourceLocation(C->getLParenLoc());7873}7874 7875void OMPClauseWriter::VisitOMPSizesClause(OMPSizesClause *C) {7876 Record.push_back(C->getNumSizes());7877 for (Expr *Size : C->getSizesRefs())7878 Record.AddStmt(Size);7879 Record.AddSourceLocation(C->getLParenLoc());7880}7881 7882void OMPClauseWriter::VisitOMPPermutationClause(OMPPermutationClause *C) {7883 Record.push_back(C->getNumLoops());7884 for (Expr *Size : C->getArgsRefs())7885 Record.AddStmt(Size);7886 Record.AddSourceLocation(C->getLParenLoc());7887}7888 7889void OMPClauseWriter::VisitOMPFullClause(OMPFullClause *C) {}7890 7891void OMPClauseWriter::VisitOMPPartialClause(OMPPartialClause *C) {7892 Record.AddStmt(C->getFactor());7893 Record.AddSourceLocation(C->getLParenLoc());7894}7895 7896void OMPClauseWriter::VisitOMPLoopRangeClause(OMPLoopRangeClause *C) {7897 Record.AddStmt(C->getFirst());7898 Record.AddStmt(C->getCount());7899 Record.AddSourceLocation(C->getLParenLoc());7900 Record.AddSourceLocation(C->getFirstLoc());7901 Record.AddSourceLocation(C->getCountLoc());7902}7903 7904void OMPClauseWriter::VisitOMPAllocatorClause(OMPAllocatorClause *C) {7905 Record.AddStmt(C->getAllocator());7906 Record.AddSourceLocation(C->getLParenLoc());7907}7908 7909void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) {7910 Record.AddStmt(C->getNumForLoops());7911 Record.AddSourceLocation(C->getLParenLoc());7912}7913 7914void OMPClauseWriter::VisitOMPDetachClause(OMPDetachClause *C) {7915 Record.AddStmt(C->getEventHandler());7916 Record.AddSourceLocation(C->getLParenLoc());7917}7918 7919void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {7920 Record.push_back(unsigned(C->getDefaultKind()));7921 Record.AddSourceLocation(C->getLParenLoc());7922 Record.AddSourceLocation(C->getDefaultKindKwLoc());7923 Record.push_back(unsigned(C->getDefaultVC()));7924 Record.AddSourceLocation(C->getDefaultVCLoc());7925}7926 7927void OMPClauseWriter::VisitOMPThreadsetClause(OMPThreadsetClause *C) {7928 Record.AddSourceLocation(C->getLParenLoc());7929 Record.AddSourceLocation(C->getThreadsetKindLoc());7930 Record.writeEnum(C->getThreadsetKind());7931}7932 7933void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) {7934 Record.push_back(unsigned(C->getProcBindKind()));7935 Record.AddSourceLocation(C->getLParenLoc());7936 Record.AddSourceLocation(C->getProcBindKindKwLoc());7937}7938 7939void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) {7940 VisitOMPClauseWithPreInit(C);7941 Record.push_back(C->getScheduleKind());7942 Record.push_back(C->getFirstScheduleModifier());7943 Record.push_back(C->getSecondScheduleModifier());7944 Record.AddStmt(C->getChunkSize());7945 Record.AddSourceLocation(C->getLParenLoc());7946 Record.AddSourceLocation(C->getFirstScheduleModifierLoc());7947 Record.AddSourceLocation(C->getSecondScheduleModifierLoc());7948 Record.AddSourceLocation(C->getScheduleKindLoc());7949 Record.AddSourceLocation(C->getCommaLoc());7950}7951 7952void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *C) {7953 Record.push_back(C->getLoopNumIterations().size());7954 Record.AddStmt(C->getNumForLoops());7955 for (Expr *NumIter : C->getLoopNumIterations())7956 Record.AddStmt(NumIter);7957 for (unsigned I = 0, E = C->getLoopNumIterations().size(); I <E; ++I)7958 Record.AddStmt(C->getLoopCounter(I));7959 Record.AddSourceLocation(C->getLParenLoc());7960}7961 7962void OMPClauseWriter::VisitOMPNowaitClause(OMPNowaitClause *C) {7963 Record.AddStmt(C->getCondition());7964 Record.AddSourceLocation(C->getLParenLoc());7965}7966 7967void OMPClauseWriter::VisitOMPUntiedClause(OMPUntiedClause *) {}7968 7969void OMPClauseWriter::VisitOMPMergeableClause(OMPMergeableClause *) {}7970 7971void OMPClauseWriter::VisitOMPReadClause(OMPReadClause *) {}7972 7973void OMPClauseWriter::VisitOMPWriteClause(OMPWriteClause *) {}7974 7975void OMPClauseWriter::VisitOMPUpdateClause(OMPUpdateClause *C) {7976 Record.push_back(C->isExtended() ? 1 : 0);7977 if (C->isExtended()) {7978 Record.AddSourceLocation(C->getLParenLoc());7979 Record.AddSourceLocation(C->getArgumentLoc());7980 Record.writeEnum(C->getDependencyKind());7981 }7982}7983 7984void OMPClauseWriter::VisitOMPCaptureClause(OMPCaptureClause *) {}7985 7986void OMPClauseWriter::VisitOMPCompareClause(OMPCompareClause *) {}7987 7988// Save the parameter of fail clause.7989void OMPClauseWriter::VisitOMPFailClause(OMPFailClause *C) {7990 Record.AddSourceLocation(C->getLParenLoc());7991 Record.AddSourceLocation(C->getFailParameterLoc());7992 Record.writeEnum(C->getFailParameter());7993}7994 7995void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {}7996 7997void OMPClauseWriter::VisitOMPAcqRelClause(OMPAcqRelClause *) {}7998 7999void OMPClauseWriter::VisitOMPAbsentClause(OMPAbsentClause *C) {8000 Record.push_back(static_cast<uint64_t>(C->getDirectiveKinds().size()));8001 Record.AddSourceLocation(C->getLParenLoc());8002 for (auto K : C->getDirectiveKinds()) {8003 Record.writeEnum(K);8004 }8005}8006 8007void OMPClauseWriter::VisitOMPHoldsClause(OMPHoldsClause *C) {8008 Record.AddStmt(C->getExpr());8009 Record.AddSourceLocation(C->getLParenLoc());8010}8011 8012void OMPClauseWriter::VisitOMPContainsClause(OMPContainsClause *C) {8013 Record.push_back(static_cast<uint64_t>(C->getDirectiveKinds().size()));8014 Record.AddSourceLocation(C->getLParenLoc());8015 for (auto K : C->getDirectiveKinds()) {8016 Record.writeEnum(K);8017 }8018}8019 8020void OMPClauseWriter::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {}8021 8022void OMPClauseWriter::VisitOMPNoOpenMPRoutinesClause(8023 OMPNoOpenMPRoutinesClause *) {}8024 8025void OMPClauseWriter::VisitOMPNoOpenMPConstructsClause(8026 OMPNoOpenMPConstructsClause *) {}8027 8028void OMPClauseWriter::VisitOMPNoParallelismClause(OMPNoParallelismClause *) {}8029 8030void OMPClauseWriter::VisitOMPAcquireClause(OMPAcquireClause *) {}8031 8032void OMPClauseWriter::VisitOMPReleaseClause(OMPReleaseClause *) {}8033 8034void OMPClauseWriter::VisitOMPRelaxedClause(OMPRelaxedClause *) {}8035 8036void OMPClauseWriter::VisitOMPWeakClause(OMPWeakClause *) {}8037 8038void OMPClauseWriter::VisitOMPThreadsClause(OMPThreadsClause *) {}8039 8040void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {}8041 8042void OMPClauseWriter::VisitOMPNogroupClause(OMPNogroupClause *) {}8043 8044void OMPClauseWriter::VisitOMPInitClause(OMPInitClause *C) {8045 Record.push_back(C->varlist_size());8046 for (Expr *VE : C->varlist())8047 Record.AddStmt(VE);8048 Record.writeBool(C->getIsTarget());8049 Record.writeBool(C->getIsTargetSync());8050 Record.AddSourceLocation(C->getLParenLoc());8051 Record.AddSourceLocation(C->getVarLoc());8052}8053 8054void OMPClauseWriter::VisitOMPUseClause(OMPUseClause *C) {8055 Record.AddStmt(C->getInteropVar());8056 Record.AddSourceLocation(C->getLParenLoc());8057 Record.AddSourceLocation(C->getVarLoc());8058}8059 8060void OMPClauseWriter::VisitOMPDestroyClause(OMPDestroyClause *C) {8061 Record.AddStmt(C->getInteropVar());8062 Record.AddSourceLocation(C->getLParenLoc());8063 Record.AddSourceLocation(C->getVarLoc());8064}8065 8066void OMPClauseWriter::VisitOMPNovariantsClause(OMPNovariantsClause *C) {8067 VisitOMPClauseWithPreInit(C);8068 Record.AddStmt(C->getCondition());8069 Record.AddSourceLocation(C->getLParenLoc());8070}8071 8072void OMPClauseWriter::VisitOMPNocontextClause(OMPNocontextClause *C) {8073 VisitOMPClauseWithPreInit(C);8074 Record.AddStmt(C->getCondition());8075 Record.AddSourceLocation(C->getLParenLoc());8076}8077 8078void OMPClauseWriter::VisitOMPFilterClause(OMPFilterClause *C) {8079 VisitOMPClauseWithPreInit(C);8080 Record.AddStmt(C->getThreadID());8081 Record.AddSourceLocation(C->getLParenLoc());8082}8083 8084void OMPClauseWriter::VisitOMPAlignClause(OMPAlignClause *C) {8085 Record.AddStmt(C->getAlignment());8086 Record.AddSourceLocation(C->getLParenLoc());8087}8088 8089void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {8090 Record.push_back(C->varlist_size());8091 Record.AddSourceLocation(C->getLParenLoc());8092 for (auto *VE : C->varlist()) {8093 Record.AddStmt(VE);8094 }8095 for (auto *VE : C->private_copies()) {8096 Record.AddStmt(VE);8097 }8098}8099 8100void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) {8101 Record.push_back(C->varlist_size());8102 VisitOMPClauseWithPreInit(C);8103 Record.AddSourceLocation(C->getLParenLoc());8104 for (auto *VE : C->varlist()) {8105 Record.AddStmt(VE);8106 }8107 for (auto *VE : C->private_copies()) {8108 Record.AddStmt(VE);8109 }8110 for (auto *VE : C->inits()) {8111 Record.AddStmt(VE);8112 }8113}8114 8115void OMPClauseWriter::VisitOMPLastprivateClause(OMPLastprivateClause *C) {8116 Record.push_back(C->varlist_size());8117 VisitOMPClauseWithPostUpdate(C);8118 Record.AddSourceLocation(C->getLParenLoc());8119 Record.writeEnum(C->getKind());8120 Record.AddSourceLocation(C->getKindLoc());8121 Record.AddSourceLocation(C->getColonLoc());8122 for (auto *VE : C->varlist())8123 Record.AddStmt(VE);8124 for (auto *E : C->private_copies())8125 Record.AddStmt(E);8126 for (auto *E : C->source_exprs())8127 Record.AddStmt(E);8128 for (auto *E : C->destination_exprs())8129 Record.AddStmt(E);8130 for (auto *E : C->assignment_ops())8131 Record.AddStmt(E);8132}8133 8134void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {8135 Record.push_back(C->varlist_size());8136 Record.AddSourceLocation(C->getLParenLoc());8137 for (auto *VE : C->varlist())8138 Record.AddStmt(VE);8139}8140 8141void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) {8142 Record.push_back(C->varlist_size());8143 Record.writeEnum(C->getModifier());8144 VisitOMPClauseWithPostUpdate(C);8145 Record.AddSourceLocation(C->getLParenLoc());8146 Record.AddSourceLocation(C->getModifierLoc());8147 Record.AddSourceLocation(C->getColonLoc());8148 Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());8149 Record.AddDeclarationNameInfo(C->getNameInfo());8150 for (auto *VE : C->varlist())8151 Record.AddStmt(VE);8152 for (auto *VE : C->privates())8153 Record.AddStmt(VE);8154 for (auto *E : C->lhs_exprs())8155 Record.AddStmt(E);8156 for (auto *E : C->rhs_exprs())8157 Record.AddStmt(E);8158 for (auto *E : C->reduction_ops())8159 Record.AddStmt(E);8160 if (C->getModifier() == clang::OMPC_REDUCTION_inscan) {8161 for (auto *E : C->copy_ops())8162 Record.AddStmt(E);8163 for (auto *E : C->copy_array_temps())8164 Record.AddStmt(E);8165 for (auto *E : C->copy_array_elems())8166 Record.AddStmt(E);8167 }8168 auto PrivateFlags = C->private_var_reduction_flags();8169 Record.push_back(std::distance(PrivateFlags.begin(), PrivateFlags.end()));8170 for (bool Flag : PrivateFlags)8171 Record.push_back(Flag);8172}8173 8174void OMPClauseWriter::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {8175 Record.push_back(C->varlist_size());8176 VisitOMPClauseWithPostUpdate(C);8177 Record.AddSourceLocation(C->getLParenLoc());8178 Record.AddSourceLocation(C->getColonLoc());8179 Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());8180 Record.AddDeclarationNameInfo(C->getNameInfo());8181 for (auto *VE : C->varlist())8182 Record.AddStmt(VE);8183 for (auto *VE : C->privates())8184 Record.AddStmt(VE);8185 for (auto *E : C->lhs_exprs())8186 Record.AddStmt(E);8187 for (auto *E : C->rhs_exprs())8188 Record.AddStmt(E);8189 for (auto *E : C->reduction_ops())8190 Record.AddStmt(E);8191}8192 8193void OMPClauseWriter::VisitOMPInReductionClause(OMPInReductionClause *C) {8194 Record.push_back(C->varlist_size());8195 VisitOMPClauseWithPostUpdate(C);8196 Record.AddSourceLocation(C->getLParenLoc());8197 Record.AddSourceLocation(C->getColonLoc());8198 Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());8199 Record.AddDeclarationNameInfo(C->getNameInfo());8200 for (auto *VE : C->varlist())8201 Record.AddStmt(VE);8202 for (auto *VE : C->privates())8203 Record.AddStmt(VE);8204 for (auto *E : C->lhs_exprs())8205 Record.AddStmt(E);8206 for (auto *E : C->rhs_exprs())8207 Record.AddStmt(E);8208 for (auto *E : C->reduction_ops())8209 Record.AddStmt(E);8210 for (auto *E : C->taskgroup_descriptors())8211 Record.AddStmt(E);8212}8213 8214void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {8215 Record.push_back(C->varlist_size());8216 VisitOMPClauseWithPostUpdate(C);8217 Record.AddSourceLocation(C->getLParenLoc());8218 Record.AddSourceLocation(C->getColonLoc());8219 Record.push_back(C->getModifier());8220 Record.AddSourceLocation(C->getModifierLoc());8221 for (auto *VE : C->varlist()) {8222 Record.AddStmt(VE);8223 }8224 for (auto *VE : C->privates()) {8225 Record.AddStmt(VE);8226 }8227 for (auto *VE : C->inits()) {8228 Record.AddStmt(VE);8229 }8230 for (auto *VE : C->updates()) {8231 Record.AddStmt(VE);8232 }8233 for (auto *VE : C->finals()) {8234 Record.AddStmt(VE);8235 }8236 Record.AddStmt(C->getStep());8237 Record.AddStmt(C->getCalcStep());8238 for (auto *VE : C->used_expressions())8239 Record.AddStmt(VE);8240}8241 8242void OMPClauseWriter::VisitOMPAlignedClause(OMPAlignedClause *C) {8243 Record.push_back(C->varlist_size());8244 Record.AddSourceLocation(C->getLParenLoc());8245 Record.AddSourceLocation(C->getColonLoc());8246 for (auto *VE : C->varlist())8247 Record.AddStmt(VE);8248 Record.AddStmt(C->getAlignment());8249}8250 8251void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {8252 Record.push_back(C->varlist_size());8253 Record.AddSourceLocation(C->getLParenLoc());8254 for (auto *VE : C->varlist())8255 Record.AddStmt(VE);8256 for (auto *E : C->source_exprs())8257 Record.AddStmt(E);8258 for (auto *E : C->destination_exprs())8259 Record.AddStmt(E);8260 for (auto *E : C->assignment_ops())8261 Record.AddStmt(E);8262}8263 8264void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {8265 Record.push_back(C->varlist_size());8266 Record.AddSourceLocation(C->getLParenLoc());8267 for (auto *VE : C->varlist())8268 Record.AddStmt(VE);8269 for (auto *E : C->source_exprs())8270 Record.AddStmt(E);8271 for (auto *E : C->destination_exprs())8272 Record.AddStmt(E);8273 for (auto *E : C->assignment_ops())8274 Record.AddStmt(E);8275}8276 8277void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) {8278 Record.push_back(C->varlist_size());8279 Record.AddSourceLocation(C->getLParenLoc());8280 for (auto *VE : C->varlist())8281 Record.AddStmt(VE);8282}8283 8284void OMPClauseWriter::VisitOMPDepobjClause(OMPDepobjClause *C) {8285 Record.AddStmt(C->getDepobj());8286 Record.AddSourceLocation(C->getLParenLoc());8287}8288 8289void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {8290 Record.push_back(C->varlist_size());8291 Record.push_back(C->getNumLoops());8292 Record.AddSourceLocation(C->getLParenLoc());8293 Record.AddStmt(C->getModifier());8294 Record.push_back(C->getDependencyKind());8295 Record.AddSourceLocation(C->getDependencyLoc());8296 Record.AddSourceLocation(C->getColonLoc());8297 Record.AddSourceLocation(C->getOmpAllMemoryLoc());8298 for (auto *VE : C->varlist())8299 Record.AddStmt(VE);8300 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)8301 Record.AddStmt(C->getLoopData(I));8302}8303 8304void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) {8305 VisitOMPClauseWithPreInit(C);8306 Record.writeEnum(C->getModifier());8307 Record.AddStmt(C->getDevice());8308 Record.AddSourceLocation(C->getModifierLoc());8309 Record.AddSourceLocation(C->getLParenLoc());8310}8311 8312void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) {8313 Record.push_back(C->varlist_size());8314 Record.push_back(C->getUniqueDeclarationsNum());8315 Record.push_back(C->getTotalComponentListNum());8316 Record.push_back(C->getTotalComponentsNum());8317 Record.AddSourceLocation(C->getLParenLoc());8318 bool HasIteratorModifier = false;8319 for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) {8320 Record.push_back(C->getMapTypeModifier(I));8321 Record.AddSourceLocation(C->getMapTypeModifierLoc(I));8322 if (C->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_iterator)8323 HasIteratorModifier = true;8324 }8325 Record.AddNestedNameSpecifierLoc(C->getMapperQualifierLoc());8326 Record.AddDeclarationNameInfo(C->getMapperIdInfo());8327 Record.push_back(C->getMapType());8328 Record.AddSourceLocation(C->getMapLoc());8329 Record.AddSourceLocation(C->getColonLoc());8330 for (auto *E : C->varlist())8331 Record.AddStmt(E);8332 for (auto *E : C->mapperlists())8333 Record.AddStmt(E);8334 if (HasIteratorModifier)8335 Record.AddStmt(C->getIteratorModifier());8336 for (auto *D : C->all_decls())8337 Record.AddDeclRef(D);8338 for (auto N : C->all_num_lists())8339 Record.push_back(N);8340 for (auto N : C->all_lists_sizes())8341 Record.push_back(N);8342 for (auto &M : C->all_components()) {8343 Record.AddStmt(M.getAssociatedExpression());8344 Record.AddDeclRef(M.getAssociatedDeclaration());8345 }8346}8347 8348void OMPClauseWriter::VisitOMPAllocateClause(OMPAllocateClause *C) {8349 Record.push_back(C->varlist_size());8350 Record.writeEnum(C->getFirstAllocateModifier());8351 Record.writeEnum(C->getSecondAllocateModifier());8352 Record.AddSourceLocation(C->getLParenLoc());8353 Record.AddSourceLocation(C->getColonLoc());8354 Record.AddStmt(C->getAllocator());8355 Record.AddStmt(C->getAlignment());8356 for (auto *VE : C->varlist())8357 Record.AddStmt(VE);8358}8359 8360void OMPClauseWriter::VisitOMPNumTeamsClause(OMPNumTeamsClause *C) {8361 Record.push_back(C->varlist_size());8362 VisitOMPClauseWithPreInit(C);8363 Record.AddSourceLocation(C->getLParenLoc());8364 for (auto *VE : C->varlist())8365 Record.AddStmt(VE);8366}8367 8368void OMPClauseWriter::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) {8369 Record.push_back(C->varlist_size());8370 VisitOMPClauseWithPreInit(C);8371 Record.AddSourceLocation(C->getLParenLoc());8372 for (auto *VE : C->varlist())8373 Record.AddStmt(VE);8374}8375 8376void OMPClauseWriter::VisitOMPPriorityClause(OMPPriorityClause *C) {8377 VisitOMPClauseWithPreInit(C);8378 Record.AddStmt(C->getPriority());8379 Record.AddSourceLocation(C->getLParenLoc());8380}8381 8382void OMPClauseWriter::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {8383 VisitOMPClauseWithPreInit(C);8384 Record.writeEnum(C->getModifier());8385 Record.AddStmt(C->getGrainsize());8386 Record.AddSourceLocation(C->getModifierLoc());8387 Record.AddSourceLocation(C->getLParenLoc());8388}8389 8390void OMPClauseWriter::VisitOMPNumTasksClause(OMPNumTasksClause *C) {8391 VisitOMPClauseWithPreInit(C);8392 Record.writeEnum(C->getModifier());8393 Record.AddStmt(C->getNumTasks());8394 Record.AddSourceLocation(C->getModifierLoc());8395 Record.AddSourceLocation(C->getLParenLoc());8396}8397 8398void OMPClauseWriter::VisitOMPHintClause(OMPHintClause *C) {8399 Record.AddStmt(C->getHint());8400 Record.AddSourceLocation(C->getLParenLoc());8401}8402 8403void OMPClauseWriter::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {8404 VisitOMPClauseWithPreInit(C);8405 Record.push_back(C->getDistScheduleKind());8406 Record.AddStmt(C->getChunkSize());8407 Record.AddSourceLocation(C->getLParenLoc());8408 Record.AddSourceLocation(C->getDistScheduleKindLoc());8409 Record.AddSourceLocation(C->getCommaLoc());8410}8411 8412void OMPClauseWriter::VisitOMPDefaultmapClause(OMPDefaultmapClause *C) {8413 Record.push_back(C->getDefaultmapKind());8414 Record.push_back(C->getDefaultmapModifier());8415 Record.AddSourceLocation(C->getLParenLoc());8416 Record.AddSourceLocation(C->getDefaultmapModifierLoc());8417 Record.AddSourceLocation(C->getDefaultmapKindLoc());8418}8419 8420void OMPClauseWriter::VisitOMPToClause(OMPToClause *C) {8421 Record.push_back(C->varlist_size());8422 Record.push_back(C->getUniqueDeclarationsNum());8423 Record.push_back(C->getTotalComponentListNum());8424 Record.push_back(C->getTotalComponentsNum());8425 Record.AddSourceLocation(C->getLParenLoc());8426 for (unsigned I = 0; I < NumberOfOMPMotionModifiers; ++I) {8427 Record.push_back(C->getMotionModifier(I));8428 Record.AddSourceLocation(C->getMotionModifierLoc(I));8429 if (C->getMotionModifier(I) == OMPC_MOTION_MODIFIER_iterator)8430 Record.AddStmt(C->getIteratorModifier());8431 }8432 Record.AddNestedNameSpecifierLoc(C->getMapperQualifierLoc());8433 Record.AddDeclarationNameInfo(C->getMapperIdInfo());8434 Record.AddSourceLocation(C->getColonLoc());8435 for (auto *E : C->varlist())8436 Record.AddStmt(E);8437 for (auto *E : C->mapperlists())8438 Record.AddStmt(E);8439 for (auto *D : C->all_decls())8440 Record.AddDeclRef(D);8441 for (auto N : C->all_num_lists())8442 Record.push_back(N);8443 for (auto N : C->all_lists_sizes())8444 Record.push_back(N);8445 for (auto &M : C->all_components()) {8446 Record.AddStmt(M.getAssociatedExpression());8447 Record.writeBool(M.isNonContiguous());8448 Record.AddDeclRef(M.getAssociatedDeclaration());8449 }8450}8451 8452void OMPClauseWriter::VisitOMPFromClause(OMPFromClause *C) {8453 Record.push_back(C->varlist_size());8454 Record.push_back(C->getUniqueDeclarationsNum());8455 Record.push_back(C->getTotalComponentListNum());8456 Record.push_back(C->getTotalComponentsNum());8457 Record.AddSourceLocation(C->getLParenLoc());8458 for (unsigned I = 0; I < NumberOfOMPMotionModifiers; ++I) {8459 Record.push_back(C->getMotionModifier(I));8460 Record.AddSourceLocation(C->getMotionModifierLoc(I));8461 if (C->getMotionModifier(I) == OMPC_MOTION_MODIFIER_iterator)8462 Record.AddStmt(C->getIteratorModifier());8463 }8464 Record.AddNestedNameSpecifierLoc(C->getMapperQualifierLoc());8465 Record.AddDeclarationNameInfo(C->getMapperIdInfo());8466 Record.AddSourceLocation(C->getColonLoc());8467 for (auto *E : C->varlist())8468 Record.AddStmt(E);8469 for (auto *E : C->mapperlists())8470 Record.AddStmt(E);8471 for (auto *D : C->all_decls())8472 Record.AddDeclRef(D);8473 for (auto N : C->all_num_lists())8474 Record.push_back(N);8475 for (auto N : C->all_lists_sizes())8476 Record.push_back(N);8477 for (auto &M : C->all_components()) {8478 Record.AddStmt(M.getAssociatedExpression());8479 Record.writeBool(M.isNonContiguous());8480 Record.AddDeclRef(M.getAssociatedDeclaration());8481 }8482}8483 8484void OMPClauseWriter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) {8485 Record.push_back(C->varlist_size());8486 Record.push_back(C->getUniqueDeclarationsNum());8487 Record.push_back(C->getTotalComponentListNum());8488 Record.push_back(C->getTotalComponentsNum());8489 Record.AddSourceLocation(C->getLParenLoc());8490 for (auto *E : C->varlist())8491 Record.AddStmt(E);8492 for (auto *VE : C->private_copies())8493 Record.AddStmt(VE);8494 for (auto *VE : C->inits())8495 Record.AddStmt(VE);8496 for (auto *D : C->all_decls())8497 Record.AddDeclRef(D);8498 for (auto N : C->all_num_lists())8499 Record.push_back(N);8500 for (auto N : C->all_lists_sizes())8501 Record.push_back(N);8502 for (auto &M : C->all_components()) {8503 Record.AddStmt(M.getAssociatedExpression());8504 Record.AddDeclRef(M.getAssociatedDeclaration());8505 }8506}8507 8508void OMPClauseWriter::VisitOMPUseDeviceAddrClause(OMPUseDeviceAddrClause *C) {8509 Record.push_back(C->varlist_size());8510 Record.push_back(C->getUniqueDeclarationsNum());8511 Record.push_back(C->getTotalComponentListNum());8512 Record.push_back(C->getTotalComponentsNum());8513 Record.AddSourceLocation(C->getLParenLoc());8514 for (auto *E : C->varlist())8515 Record.AddStmt(E);8516 for (auto *D : C->all_decls())8517 Record.AddDeclRef(D);8518 for (auto N : C->all_num_lists())8519 Record.push_back(N);8520 for (auto N : C->all_lists_sizes())8521 Record.push_back(N);8522 for (auto &M : C->all_components()) {8523 Record.AddStmt(M.getAssociatedExpression());8524 Record.AddDeclRef(M.getAssociatedDeclaration());8525 }8526}8527 8528void OMPClauseWriter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {8529 Record.push_back(C->varlist_size());8530 Record.push_back(C->getUniqueDeclarationsNum());8531 Record.push_back(C->getTotalComponentListNum());8532 Record.push_back(C->getTotalComponentsNum());8533 Record.AddSourceLocation(C->getLParenLoc());8534 for (auto *E : C->varlist())8535 Record.AddStmt(E);8536 for (auto *D : C->all_decls())8537 Record.AddDeclRef(D);8538 for (auto N : C->all_num_lists())8539 Record.push_back(N);8540 for (auto N : C->all_lists_sizes())8541 Record.push_back(N);8542 for (auto &M : C->all_components()) {8543 Record.AddStmt(M.getAssociatedExpression());8544 Record.AddDeclRef(M.getAssociatedDeclaration());8545 }8546}8547 8548void OMPClauseWriter::VisitOMPHasDeviceAddrClause(OMPHasDeviceAddrClause *C) {8549 Record.push_back(C->varlist_size());8550 Record.push_back(C->getUniqueDeclarationsNum());8551 Record.push_back(C->getTotalComponentListNum());8552 Record.push_back(C->getTotalComponentsNum());8553 Record.AddSourceLocation(C->getLParenLoc());8554 for (auto *E : C->varlist())8555 Record.AddStmt(E);8556 for (auto *D : C->all_decls())8557 Record.AddDeclRef(D);8558 for (auto N : C->all_num_lists())8559 Record.push_back(N);8560 for (auto N : C->all_lists_sizes())8561 Record.push_back(N);8562 for (auto &M : C->all_components()) {8563 Record.AddStmt(M.getAssociatedExpression());8564 Record.AddDeclRef(M.getAssociatedDeclaration());8565 }8566}8567 8568void OMPClauseWriter::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {}8569 8570void OMPClauseWriter::VisitOMPUnifiedSharedMemoryClause(8571 OMPUnifiedSharedMemoryClause *) {}8572 8573void OMPClauseWriter::VisitOMPReverseOffloadClause(OMPReverseOffloadClause *) {}8574 8575void8576OMPClauseWriter::VisitOMPDynamicAllocatorsClause(OMPDynamicAllocatorsClause *) {8577}8578 8579void OMPClauseWriter::VisitOMPAtomicDefaultMemOrderClause(8580 OMPAtomicDefaultMemOrderClause *C) {8581 Record.push_back(C->getAtomicDefaultMemOrderKind());8582 Record.AddSourceLocation(C->getLParenLoc());8583 Record.AddSourceLocation(C->getAtomicDefaultMemOrderKindKwLoc());8584}8585 8586void OMPClauseWriter::VisitOMPSelfMapsClause(OMPSelfMapsClause *) {}8587 8588void OMPClauseWriter::VisitOMPAtClause(OMPAtClause *C) {8589 Record.push_back(C->getAtKind());8590 Record.AddSourceLocation(C->getLParenLoc());8591 Record.AddSourceLocation(C->getAtKindKwLoc());8592}8593 8594void OMPClauseWriter::VisitOMPSeverityClause(OMPSeverityClause *C) {8595 Record.push_back(C->getSeverityKind());8596 Record.AddSourceLocation(C->getLParenLoc());8597 Record.AddSourceLocation(C->getSeverityKindKwLoc());8598}8599 8600void OMPClauseWriter::VisitOMPMessageClause(OMPMessageClause *C) {8601 VisitOMPClauseWithPreInit(C);8602 Record.AddStmt(C->getMessageString());8603 Record.AddSourceLocation(C->getLParenLoc());8604}8605 8606void OMPClauseWriter::VisitOMPNontemporalClause(OMPNontemporalClause *C) {8607 Record.push_back(C->varlist_size());8608 Record.AddSourceLocation(C->getLParenLoc());8609 for (auto *VE : C->varlist())8610 Record.AddStmt(VE);8611 for (auto *E : C->private_refs())8612 Record.AddStmt(E);8613}8614 8615void OMPClauseWriter::VisitOMPInclusiveClause(OMPInclusiveClause *C) {8616 Record.push_back(C->varlist_size());8617 Record.AddSourceLocation(C->getLParenLoc());8618 for (auto *VE : C->varlist())8619 Record.AddStmt(VE);8620}8621 8622void OMPClauseWriter::VisitOMPExclusiveClause(OMPExclusiveClause *C) {8623 Record.push_back(C->varlist_size());8624 Record.AddSourceLocation(C->getLParenLoc());8625 for (auto *VE : C->varlist())8626 Record.AddStmt(VE);8627}8628 8629void OMPClauseWriter::VisitOMPOrderClause(OMPOrderClause *C) {8630 Record.writeEnum(C->getKind());8631 Record.writeEnum(C->getModifier());8632 Record.AddSourceLocation(C->getLParenLoc());8633 Record.AddSourceLocation(C->getKindKwLoc());8634 Record.AddSourceLocation(C->getModifierKwLoc());8635}8636 8637void OMPClauseWriter::VisitOMPUsesAllocatorsClause(OMPUsesAllocatorsClause *C) {8638 Record.push_back(C->getNumberOfAllocators());8639 Record.AddSourceLocation(C->getLParenLoc());8640 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {8641 OMPUsesAllocatorsClause::Data Data = C->getAllocatorData(I);8642 Record.AddStmt(Data.Allocator);8643 Record.AddStmt(Data.AllocatorTraits);8644 Record.AddSourceLocation(Data.LParenLoc);8645 Record.AddSourceLocation(Data.RParenLoc);8646 }8647}8648 8649void OMPClauseWriter::VisitOMPAffinityClause(OMPAffinityClause *C) {8650 Record.push_back(C->varlist_size());8651 Record.AddSourceLocation(C->getLParenLoc());8652 Record.AddStmt(C->getModifier());8653 Record.AddSourceLocation(C->getColonLoc());8654 for (Expr *E : C->varlist())8655 Record.AddStmt(E);8656}8657 8658void OMPClauseWriter::VisitOMPBindClause(OMPBindClause *C) {8659 Record.writeEnum(C->getBindKind());8660 Record.AddSourceLocation(C->getLParenLoc());8661 Record.AddSourceLocation(C->getBindKindLoc());8662}8663 8664void OMPClauseWriter::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) {8665 VisitOMPClauseWithPreInit(C);8666 Record.AddStmt(C->getSize());8667 Record.AddSourceLocation(C->getLParenLoc());8668}8669 8670void OMPClauseWriter::VisitOMPDynGroupprivateClause(8671 OMPDynGroupprivateClause *C) {8672 VisitOMPClauseWithPreInit(C);8673 Record.push_back(C->getDynGroupprivateModifier());8674 Record.push_back(C->getDynGroupprivateFallbackModifier());8675 Record.AddStmt(C->getSize());8676 Record.AddSourceLocation(C->getLParenLoc());8677 Record.AddSourceLocation(C->getDynGroupprivateModifierLoc());8678 Record.AddSourceLocation(C->getDynGroupprivateFallbackModifierLoc());8679}8680 8681void OMPClauseWriter::VisitOMPDoacrossClause(OMPDoacrossClause *C) {8682 Record.push_back(C->varlist_size());8683 Record.push_back(C->getNumLoops());8684 Record.AddSourceLocation(C->getLParenLoc());8685 Record.push_back(C->getDependenceType());8686 Record.AddSourceLocation(C->getDependenceLoc());8687 Record.AddSourceLocation(C->getColonLoc());8688 for (auto *VE : C->varlist())8689 Record.AddStmt(VE);8690 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)8691 Record.AddStmt(C->getLoopData(I));8692}8693 8694void OMPClauseWriter::VisitOMPXAttributeClause(OMPXAttributeClause *C) {8695 Record.AddAttributes(C->getAttrs());8696 Record.AddSourceLocation(C->getBeginLoc());8697 Record.AddSourceLocation(C->getLParenLoc());8698 Record.AddSourceLocation(C->getEndLoc());8699}8700 8701void OMPClauseWriter::VisitOMPXBareClause(OMPXBareClause *C) {}8702 8703void ASTRecordWriter::writeOMPTraitInfo(const OMPTraitInfo *TI) {8704 writeUInt32(TI->Sets.size());8705 for (const auto &Set : TI->Sets) {8706 writeEnum(Set.Kind);8707 writeUInt32(Set.Selectors.size());8708 for (const auto &Selector : Set.Selectors) {8709 writeEnum(Selector.Kind);8710 writeBool(Selector.ScoreOrCondition);8711 if (Selector.ScoreOrCondition)8712 writeExprRef(Selector.ScoreOrCondition);8713 writeUInt32(Selector.Properties.size());8714 for (const auto &Property : Selector.Properties)8715 writeEnum(Property.Kind);8716 }8717 }8718}8719 8720void ASTRecordWriter::writeOMPChildren(OMPChildren *Data) {8721 if (!Data)8722 return;8723 writeUInt32(Data->getNumClauses());8724 writeUInt32(Data->getNumChildren());8725 writeBool(Data->hasAssociatedStmt());8726 for (unsigned I = 0, E = Data->getNumClauses(); I < E; ++I)8727 writeOMPClause(Data->getClauses()[I]);8728 if (Data->hasAssociatedStmt())8729 AddStmt(Data->getAssociatedStmt());8730 for (unsigned I = 0, E = Data->getNumChildren(); I < E; ++I)8731 AddStmt(Data->getChildren()[I]);8732}8733 8734void ASTRecordWriter::writeOpenACCVarList(const OpenACCClauseWithVarList *C) {8735 writeUInt32(C->getVarList().size());8736 for (Expr *E : C->getVarList())8737 AddStmt(E);8738}8739 8740void ASTRecordWriter::writeOpenACCIntExprList(ArrayRef<Expr *> Exprs) {8741 writeUInt32(Exprs.size());8742 for (Expr *E : Exprs)8743 AddStmt(E);8744}8745 8746void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {8747 writeEnum(C->getClauseKind());8748 writeSourceLocation(C->getBeginLoc());8749 writeSourceLocation(C->getEndLoc());8750 8751 switch (C->getClauseKind()) {8752 case OpenACCClauseKind::Default: {8753 const auto *DC = cast<OpenACCDefaultClause>(C);8754 writeSourceLocation(DC->getLParenLoc());8755 writeEnum(DC->getDefaultClauseKind());8756 return;8757 }8758 case OpenACCClauseKind::If: {8759 const auto *IC = cast<OpenACCIfClause>(C);8760 writeSourceLocation(IC->getLParenLoc());8761 AddStmt(const_cast<Expr*>(IC->getConditionExpr()));8762 return;8763 }8764 case OpenACCClauseKind::Self: {8765 const auto *SC = cast<OpenACCSelfClause>(C);8766 writeSourceLocation(SC->getLParenLoc());8767 writeBool(SC->isConditionExprClause());8768 if (SC->isConditionExprClause()) {8769 writeBool(SC->hasConditionExpr());8770 if (SC->hasConditionExpr())8771 AddStmt(const_cast<Expr *>(SC->getConditionExpr()));8772 } else {8773 writeUInt32(SC->getVarList().size());8774 for (Expr *E : SC->getVarList())8775 AddStmt(E);8776 }8777 return;8778 }8779 case OpenACCClauseKind::NumGangs: {8780 const auto *NGC = cast<OpenACCNumGangsClause>(C);8781 writeSourceLocation(NGC->getLParenLoc());8782 writeUInt32(NGC->getIntExprs().size());8783 for (Expr *E : NGC->getIntExprs())8784 AddStmt(E);8785 return;8786 }8787 case OpenACCClauseKind::DeviceNum: {8788 const auto *DNC = cast<OpenACCDeviceNumClause>(C);8789 writeSourceLocation(DNC->getLParenLoc());8790 AddStmt(const_cast<Expr*>(DNC->getIntExpr()));8791 return;8792 }8793 case OpenACCClauseKind::DefaultAsync: {8794 const auto *DAC = cast<OpenACCDefaultAsyncClause>(C);8795 writeSourceLocation(DAC->getLParenLoc());8796 AddStmt(const_cast<Expr *>(DAC->getIntExpr()));8797 return;8798 }8799 case OpenACCClauseKind::NumWorkers: {8800 const auto *NWC = cast<OpenACCNumWorkersClause>(C);8801 writeSourceLocation(NWC->getLParenLoc());8802 AddStmt(const_cast<Expr*>(NWC->getIntExpr()));8803 return;8804 }8805 case OpenACCClauseKind::VectorLength: {8806 const auto *NWC = cast<OpenACCVectorLengthClause>(C);8807 writeSourceLocation(NWC->getLParenLoc());8808 AddStmt(const_cast<Expr*>(NWC->getIntExpr()));8809 return;8810 }8811 case OpenACCClauseKind::Private: {8812 const auto *PC = cast<OpenACCPrivateClause>(C);8813 writeSourceLocation(PC->getLParenLoc());8814 writeOpenACCVarList(PC);8815 8816 for (const OpenACCPrivateRecipe &R : PC->getInitRecipes()) {8817 static_assert(sizeof(R) == 1 * sizeof(int *));8818 AddDeclRef(R.AllocaDecl);8819 }8820 return;8821 }8822 case OpenACCClauseKind::Host: {8823 const auto *HC = cast<OpenACCHostClause>(C);8824 writeSourceLocation(HC->getLParenLoc());8825 writeOpenACCVarList(HC);8826 return;8827 }8828 case OpenACCClauseKind::Device: {8829 const auto *DC = cast<OpenACCDeviceClause>(C);8830 writeSourceLocation(DC->getLParenLoc());8831 writeOpenACCVarList(DC);8832 return;8833 }8834 case OpenACCClauseKind::FirstPrivate: {8835 const auto *FPC = cast<OpenACCFirstPrivateClause>(C);8836 writeSourceLocation(FPC->getLParenLoc());8837 writeOpenACCVarList(FPC);8838 8839 for (const OpenACCFirstPrivateRecipe &R : FPC->getInitRecipes()) {8840 static_assert(sizeof(R) == 2 * sizeof(int *));8841 AddDeclRef(R.AllocaDecl);8842 AddDeclRef(R.InitFromTemporary);8843 }8844 return;8845 }8846 case OpenACCClauseKind::Attach: {8847 const auto *AC = cast<OpenACCAttachClause>(C);8848 writeSourceLocation(AC->getLParenLoc());8849 writeOpenACCVarList(AC);8850 return;8851 }8852 case OpenACCClauseKind::Detach: {8853 const auto *DC = cast<OpenACCDetachClause>(C);8854 writeSourceLocation(DC->getLParenLoc());8855 writeOpenACCVarList(DC);8856 return;8857 }8858 case OpenACCClauseKind::Delete: {8859 const auto *DC = cast<OpenACCDeleteClause>(C);8860 writeSourceLocation(DC->getLParenLoc());8861 writeOpenACCVarList(DC);8862 return;8863 }8864 case OpenACCClauseKind::UseDevice: {8865 const auto *UDC = cast<OpenACCUseDeviceClause>(C);8866 writeSourceLocation(UDC->getLParenLoc());8867 writeOpenACCVarList(UDC);8868 return;8869 }8870 case OpenACCClauseKind::DevicePtr: {8871 const auto *DPC = cast<OpenACCDevicePtrClause>(C);8872 writeSourceLocation(DPC->getLParenLoc());8873 writeOpenACCVarList(DPC);8874 return;8875 }8876 case OpenACCClauseKind::NoCreate: {8877 const auto *NCC = cast<OpenACCNoCreateClause>(C);8878 writeSourceLocation(NCC->getLParenLoc());8879 writeOpenACCVarList(NCC);8880 return;8881 }8882 case OpenACCClauseKind::Present: {8883 const auto *PC = cast<OpenACCPresentClause>(C);8884 writeSourceLocation(PC->getLParenLoc());8885 writeOpenACCVarList(PC);8886 return;8887 }8888 case OpenACCClauseKind::Copy:8889 case OpenACCClauseKind::PCopy:8890 case OpenACCClauseKind::PresentOrCopy: {8891 const auto *CC = cast<OpenACCCopyClause>(C);8892 writeSourceLocation(CC->getLParenLoc());8893 writeEnum(CC->getModifierList());8894 writeOpenACCVarList(CC);8895 return;8896 }8897 case OpenACCClauseKind::CopyIn:8898 case OpenACCClauseKind::PCopyIn:8899 case OpenACCClauseKind::PresentOrCopyIn: {8900 const auto *CIC = cast<OpenACCCopyInClause>(C);8901 writeSourceLocation(CIC->getLParenLoc());8902 writeEnum(CIC->getModifierList());8903 writeOpenACCVarList(CIC);8904 return;8905 }8906 case OpenACCClauseKind::CopyOut:8907 case OpenACCClauseKind::PCopyOut:8908 case OpenACCClauseKind::PresentOrCopyOut: {8909 const auto *COC = cast<OpenACCCopyOutClause>(C);8910 writeSourceLocation(COC->getLParenLoc());8911 writeEnum(COC->getModifierList());8912 writeOpenACCVarList(COC);8913 return;8914 }8915 case OpenACCClauseKind::Create:8916 case OpenACCClauseKind::PCreate:8917 case OpenACCClauseKind::PresentOrCreate: {8918 const auto *CC = cast<OpenACCCreateClause>(C);8919 writeSourceLocation(CC->getLParenLoc());8920 writeEnum(CC->getModifierList());8921 writeOpenACCVarList(CC);8922 return;8923 }8924 case OpenACCClauseKind::Async: {8925 const auto *AC = cast<OpenACCAsyncClause>(C);8926 writeSourceLocation(AC->getLParenLoc());8927 writeBool(AC->hasIntExpr());8928 if (AC->hasIntExpr())8929 AddStmt(const_cast<Expr*>(AC->getIntExpr()));8930 return;8931 }8932 case OpenACCClauseKind::Wait: {8933 const auto *WC = cast<OpenACCWaitClause>(C);8934 writeSourceLocation(WC->getLParenLoc());8935 writeBool(WC->getDevNumExpr());8936 if (Expr *DNE = WC->getDevNumExpr())8937 AddStmt(DNE);8938 writeSourceLocation(WC->getQueuesLoc());8939 8940 writeOpenACCIntExprList(WC->getQueueIdExprs());8941 return;8942 }8943 case OpenACCClauseKind::DeviceType:8944 case OpenACCClauseKind::DType: {8945 const auto *DTC = cast<OpenACCDeviceTypeClause>(C);8946 writeSourceLocation(DTC->getLParenLoc());8947 writeUInt32(DTC->getArchitectures().size());8948 for (const DeviceTypeArgument &Arg : DTC->getArchitectures()) {8949 writeBool(Arg.getIdentifierInfo());8950 if (Arg.getIdentifierInfo())8951 AddIdentifierRef(Arg.getIdentifierInfo());8952 writeSourceLocation(Arg.getLoc());8953 }8954 return;8955 }8956 case OpenACCClauseKind::Reduction: {8957 const auto *RC = cast<OpenACCReductionClause>(C);8958 writeSourceLocation(RC->getLParenLoc());8959 writeEnum(RC->getReductionOp());8960 writeOpenACCVarList(RC);8961 8962 for (const OpenACCReductionRecipe &R : RC->getRecipes()) {8963 AddDeclRef(R.AllocaDecl);8964 8965 static_assert(sizeof(OpenACCReductionRecipe::CombinerRecipe) ==8966 3 * sizeof(int *));8967 writeUInt32(R.CombinerRecipes.size());8968 8969 for (auto &CombinerRecipe : R.CombinerRecipes) {8970 AddDeclRef(CombinerRecipe.LHS);8971 AddDeclRef(CombinerRecipe.RHS);8972 AddStmt(CombinerRecipe.Op);8973 }8974 }8975 return;8976 }8977 case OpenACCClauseKind::Seq:8978 case OpenACCClauseKind::Independent:8979 case OpenACCClauseKind::NoHost:8980 case OpenACCClauseKind::Auto:8981 case OpenACCClauseKind::Finalize:8982 case OpenACCClauseKind::IfPresent:8983 // Nothing to do here, there is no additional information beyond the8984 // begin/end loc and clause kind.8985 return;8986 case OpenACCClauseKind::Collapse: {8987 const auto *CC = cast<OpenACCCollapseClause>(C);8988 writeSourceLocation(CC->getLParenLoc());8989 writeBool(CC->hasForce());8990 AddStmt(const_cast<Expr *>(CC->getLoopCount()));8991 return;8992 }8993 case OpenACCClauseKind::Tile: {8994 const auto *TC = cast<OpenACCTileClause>(C);8995 writeSourceLocation(TC->getLParenLoc());8996 writeUInt32(TC->getSizeExprs().size());8997 for (Expr *E : TC->getSizeExprs())8998 AddStmt(E);8999 return;9000 }9001 case OpenACCClauseKind::Gang: {9002 const auto *GC = cast<OpenACCGangClause>(C);9003 writeSourceLocation(GC->getLParenLoc());9004 writeUInt32(GC->getNumExprs());9005 for (unsigned I = 0; I < GC->getNumExprs(); ++I) {9006 writeEnum(GC->getExpr(I).first);9007 AddStmt(const_cast<Expr *>(GC->getExpr(I).second));9008 }9009 return;9010 }9011 case OpenACCClauseKind::Worker: {9012 const auto *WC = cast<OpenACCWorkerClause>(C);9013 writeSourceLocation(WC->getLParenLoc());9014 writeBool(WC->hasIntExpr());9015 if (WC->hasIntExpr())9016 AddStmt(const_cast<Expr *>(WC->getIntExpr()));9017 return;9018 }9019 case OpenACCClauseKind::Vector: {9020 const auto *VC = cast<OpenACCVectorClause>(C);9021 writeSourceLocation(VC->getLParenLoc());9022 writeBool(VC->hasIntExpr());9023 if (VC->hasIntExpr())9024 AddStmt(const_cast<Expr *>(VC->getIntExpr()));9025 return;9026 }9027 case OpenACCClauseKind::Link: {9028 const auto *LC = cast<OpenACCLinkClause>(C);9029 writeSourceLocation(LC->getLParenLoc());9030 writeOpenACCVarList(LC);9031 return;9032 }9033 case OpenACCClauseKind::DeviceResident: {9034 const auto *DRC = cast<OpenACCDeviceResidentClause>(C);9035 writeSourceLocation(DRC->getLParenLoc());9036 writeOpenACCVarList(DRC);9037 return;9038 }9039 9040 case OpenACCClauseKind::Bind: {9041 const auto *BC = cast<OpenACCBindClause>(C);9042 writeSourceLocation(BC->getLParenLoc());9043 writeBool(BC->isStringArgument());9044 if (BC->isStringArgument())9045 AddStmt(const_cast<StringLiteral *>(BC->getStringArgument()));9046 else9047 AddIdentifierRef(BC->getIdentifierArgument());9048 9049 return;9050 }9051 case OpenACCClauseKind::Invalid:9052 case OpenACCClauseKind::Shortloop:9053 llvm_unreachable("Clause serialization not yet implemented");9054 }9055 llvm_unreachable("Invalid Clause Kind");9056}9057 9058void ASTRecordWriter::writeOpenACCClauseList(9059 ArrayRef<const OpenACCClause *> Clauses) {9060 for (const OpenACCClause *Clause : Clauses)9061 writeOpenACCClause(Clause);9062}9063void ASTRecordWriter::AddOpenACCRoutineDeclAttr(9064 const OpenACCRoutineDeclAttr *A) {9065 // We have to write the size so that the reader can do a resize. Unlike the9066 // Decl version of this, we can't count on trailing storage to get this right.9067 writeUInt32(A->Clauses.size());9068 writeOpenACCClauseList(A->Clauses);9069}9070