forked from OSchip/llvm-project
[modules] Further simplification and speedup of redeclaration chain loading.
Instead of eagerly deserializing a list of DeclIDs when we load a module file and doing a binary search to find the redeclarations of a decl, store a list of redeclarations of each chain before the first declaration and load it directly. llvm-svn: 245789
This commit is contained in:
parent
b17bb06914
commit
d61d4acd70
|
@ -433,10 +433,7 @@ namespace clang {
|
|||
/// declarations.
|
||||
TU_UPDATE_LEXICAL = 22,
|
||||
|
||||
/// \brief Record code for the array describing the locations (in the
|
||||
/// LOCAL_REDECLARATIONS record) of the redeclaration chains, indexed by
|
||||
/// the first known ID.
|
||||
LOCAL_REDECLARATIONS_MAP = 23,
|
||||
// ID 23 used to be for a list of local redeclarations.
|
||||
|
||||
/// \brief Record code for declarations that Sema keeps references of.
|
||||
SEMA_DECL_REFS = 24,
|
||||
|
@ -514,13 +511,8 @@ namespace clang {
|
|||
/// imported by the AST file.
|
||||
IMPORTED_MODULES = 43,
|
||||
|
||||
// ID 40 used to be a table of merged canonical declarations.
|
||||
|
||||
/// \brief Record code for the array of redeclaration chains.
|
||||
///
|
||||
/// This array can only be interpreted properly using the local
|
||||
/// redeclarations map.
|
||||
LOCAL_REDECLARATIONS = 45,
|
||||
// ID 44 used to be a table of merged canonical declarations.
|
||||
// ID 45 used to be a list of declaration IDs of local redeclarations.
|
||||
|
||||
/// \brief Record code for the array of Objective-C categories (including
|
||||
/// extensions).
|
||||
|
@ -948,6 +940,9 @@ namespace clang {
|
|||
/// For more information about predefined declarations, see the
|
||||
/// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
|
||||
const unsigned int NUM_PREDEF_DECL_IDS = 12;
|
||||
|
||||
/// \brief Record code for a list of local redeclarations of a declaration.
|
||||
const unsigned int LOCAL_REDECLARATIONS = 50;
|
||||
|
||||
/// \brief Record codes for each kind of declaration.
|
||||
///
|
||||
|
|
|
@ -933,12 +933,9 @@ private:
|
|||
std::deque<Decl *> InterestingDecls;
|
||||
|
||||
/// \brief The list of redeclaration chains that still need to be
|
||||
/// reconstructed.
|
||||
///
|
||||
/// Each element is the canonical declaration of the chain.
|
||||
/// Elements in this vector should be unique; use
|
||||
/// PendingDeclChainsKnown to ensure uniqueness.
|
||||
SmallVector<Decl *, 16> PendingDeclChains;
|
||||
/// reconstructed, and the local offset to the corresponding list
|
||||
/// of redeclarations.
|
||||
SmallVector<std::pair<Decl *, uint64_t>, 16> PendingDeclChains;
|
||||
|
||||
/// \brief The list of canonical declarations whose redeclaration chains
|
||||
/// need to be marked as incomplete once we're done deserializing things.
|
||||
|
@ -1165,7 +1162,7 @@ private:
|
|||
RecordLocation DeclCursorForID(serialization::DeclID ID,
|
||||
unsigned &RawLocation);
|
||||
void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D);
|
||||
void loadPendingDeclChain(Decl *D);
|
||||
void loadPendingDeclChain(Decl *D, uint64_t LocalOffset);
|
||||
void loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D,
|
||||
unsigned PreviousGeneration = 0);
|
||||
|
||||
|
|
|
@ -547,7 +547,6 @@ private:
|
|||
void WriteFPPragmaOptions(const FPOptions &Opts);
|
||||
void WriteOpenCLExtensions(Sema &SemaRef);
|
||||
void WriteObjCCategories();
|
||||
void WriteRedeclarations();
|
||||
void WriteLateParsedTemplates(Sema &SemaRef);
|
||||
void WriteOptimizePragmaOptions(Sema &SemaRef);
|
||||
|
||||
|
|
|
@ -427,17 +427,6 @@ public:
|
|||
const serialization::DeclID *FileSortedDecls;
|
||||
unsigned NumFileSortedDecls;
|
||||
|
||||
/// \brief Array of redeclaration chain location information within this
|
||||
/// module file, sorted by the first declaration ID.
|
||||
const serialization::LocalRedeclarationsInfo *RedeclarationsMap;
|
||||
|
||||
/// \brief The number of redeclaration info entries in RedeclarationsMap.
|
||||
unsigned LocalNumRedeclarationsInMap;
|
||||
|
||||
/// \brief The redeclaration chains for declarations local to this
|
||||
/// module file.
|
||||
SmallVector<uint64_t, 1> RedeclarationChains;
|
||||
|
||||
/// \brief Array of category list location information within this
|
||||
/// module file, sorted by the definition ID.
|
||||
const serialization::ObjCCategoriesInfo *ObjCCategoriesMap;
|
||||
|
|
|
@ -3100,22 +3100,6 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
|
|||
break;
|
||||
}
|
||||
|
||||
case LOCAL_REDECLARATIONS: {
|
||||
F.RedeclarationChains.swap(Record);
|
||||
break;
|
||||
}
|
||||
|
||||
case LOCAL_REDECLARATIONS_MAP: {
|
||||
if (F.LocalNumRedeclarationsInMap != 0) {
|
||||
Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file");
|
||||
return Failure;
|
||||
}
|
||||
|
||||
F.LocalNumRedeclarationsInMap = Record[0];
|
||||
F.RedeclarationsMap = (const LocalRedeclarationsInfo *)Blob.data();
|
||||
break;
|
||||
}
|
||||
|
||||
case MACRO_OFFSET: {
|
||||
if (F.LocalNumMacros != 0) {
|
||||
Error("duplicate MACRO_OFFSET record in AST file");
|
||||
|
@ -8124,7 +8108,7 @@ void ASTReader::finishPendingActions() {
|
|||
|
||||
// Load pending declaration chains.
|
||||
for (unsigned I = 0; I != PendingDeclChains.size(); ++I)
|
||||
loadPendingDeclChain(PendingDeclChains[I]);
|
||||
loadPendingDeclChain(PendingDeclChains[I].first, PendingDeclChains[I].second);
|
||||
PendingDeclChains.clear();
|
||||
|
||||
// Make the most recent of the top-level declarations visible.
|
||||
|
|
|
@ -2156,6 +2156,8 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
|
|||
bool IsKeyDecl = ThisDeclID == FirstDeclID;
|
||||
bool IsFirstLocalDecl = false;
|
||||
|
||||
uint64_t RedeclOffset = 0;
|
||||
|
||||
// 0 indicates that this declaration was the only declaration of its entity,
|
||||
// and is used for space optimization.
|
||||
if (FirstDeclID == 0) {
|
||||
|
@ -2175,6 +2177,8 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
|
|||
// declaration.
|
||||
for (unsigned I = 0; I != N - 1; ++I)
|
||||
MergeWith = ReadDecl(Record, Idx/*, MergeWith*/);
|
||||
|
||||
RedeclOffset = Record[Idx++];
|
||||
} else {
|
||||
// This declaration was not the first local declaration. Read the first
|
||||
// local declaration now, to trigger the import of other redeclarations.
|
||||
|
@ -2198,7 +2202,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
|
|||
// above; this ensures that the redeclaration chain is built in the correct
|
||||
// order.
|
||||
if (IsFirstLocalDecl)
|
||||
Reader.PendingDeclChains.push_back(DAsT);
|
||||
Reader.PendingDeclChains.push_back(std::make_pair(DAsT, RedeclOffset));
|
||||
|
||||
return RedeclarableResult(FirstDeclID, MergeWith, IsKeyDecl);
|
||||
}
|
||||
|
@ -3393,43 +3397,40 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) {
|
|||
}
|
||||
}
|
||||
|
||||
void ASTReader::loadPendingDeclChain(Decl *FirstLocal) {
|
||||
ModuleFile &M = *getOwningModuleFile(FirstLocal);
|
||||
DeclID LocalID =
|
||||
mapGlobalIDToModuleFileGlobalID(M, FirstLocal->getGlobalID());
|
||||
assert(LocalID && "looking for redecl chain in wrong module file");
|
||||
|
||||
// Perform a binary search to find the local redeclarations for this
|
||||
// declaration (if any).
|
||||
// FIXME: Just store an offset with the first declaration.
|
||||
const LocalRedeclarationsInfo Compare = {LocalID, 0};
|
||||
const LocalRedeclarationsInfo *Result = std::lower_bound(
|
||||
M.RedeclarationsMap,
|
||||
M.RedeclarationsMap + M.LocalNumRedeclarationsInMap, Compare);
|
||||
|
||||
// Pull out the list of redeclarations.
|
||||
SmallVector<Decl*, 4> Chain;
|
||||
if (Result != M.RedeclarationsMap + M.LocalNumRedeclarationsInMap &&
|
||||
Result->FirstID == LocalID) {
|
||||
unsigned Offset = Result->Offset;
|
||||
unsigned N = M.RedeclarationChains[Offset++];
|
||||
for (unsigned I = 0; I != N; ++I)
|
||||
Chain.push_back(GetLocalDecl(M, M.RedeclarationChains[Offset++]));
|
||||
}
|
||||
Chain.push_back(FirstLocal);
|
||||
|
||||
// Hook up the chain.
|
||||
//
|
||||
// FIXME: We have three different dispatches on decl kind here; maybe
|
||||
// we should instead generate one loop per kind and dispatch up-front?
|
||||
void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) {
|
||||
// Attach FirstLocal to the end of the decl chain.
|
||||
Decl *CanonDecl = FirstLocal->getCanonicalDecl();
|
||||
Decl *MostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl);
|
||||
if (!MostRecent)
|
||||
MostRecent = CanonDecl;
|
||||
for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
|
||||
auto *D = Chain[N - I - 1];
|
||||
if (D == CanonDecl)
|
||||
continue;
|
||||
if (FirstLocal != CanonDecl) {
|
||||
Decl *PrevMostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl);
|
||||
ASTDeclReader::attachPreviousDecl(
|
||||
*this, FirstLocal, PrevMostRecent ? PrevMostRecent : CanonDecl,
|
||||
CanonDecl);
|
||||
}
|
||||
|
||||
if (!LocalOffset) {
|
||||
ASTDeclReader::attachLatestDecl(CanonDecl, FirstLocal);
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the list of other redeclarations from this module file.
|
||||
ModuleFile *M = getOwningModuleFile(FirstLocal);
|
||||
assert(M && "imported decl from no module file");
|
||||
|
||||
llvm::BitstreamCursor &Cursor = M->DeclsCursor;
|
||||
SavedStreamPosition SavedPosition(Cursor);
|
||||
Cursor.JumpToBit(LocalOffset);
|
||||
|
||||
RecordData Record;
|
||||
unsigned Code = Cursor.ReadCode();
|
||||
unsigned RecCode = Cursor.readRecord(Code, Record);
|
||||
(void)RecCode;
|
||||
assert(RecCode == LOCAL_REDECLARATIONS && "expected LOCAL_REDECLARATIONS record!");
|
||||
|
||||
// FIXME: We have several different dispatches on decl kind here; maybe
|
||||
// we should instead generate one loop per kind and dispatch up-front?
|
||||
Decl *MostRecent = FirstLocal;
|
||||
for (unsigned I = 0, N = Record.size(); I != N; ++I) {
|
||||
auto *D = GetLocalDecl(*M, Record[N - I - 1]);
|
||||
ASTDeclReader::attachPreviousDecl(*this, D, MostRecent, CanonDecl);
|
||||
MostRecent = D;
|
||||
}
|
||||
|
|
|
@ -911,7 +911,6 @@ void ASTWriter::WriteBlockInfoBlock() {
|
|||
RECORD(PPD_ENTITIES_OFFSETS);
|
||||
RECORD(REFERENCED_SELECTOR_POOL);
|
||||
RECORD(TU_UPDATE_LEXICAL);
|
||||
RECORD(LOCAL_REDECLARATIONS_MAP);
|
||||
RECORD(SEMA_DECL_REFS);
|
||||
RECORD(WEAK_UNDECLARED_IDENTIFIERS);
|
||||
RECORD(PENDING_IMPLICIT_INSTANTIATIONS);
|
||||
|
@ -933,7 +932,6 @@ void ASTWriter::WriteBlockInfoBlock() {
|
|||
RECORD(OBJC_CATEGORIES_MAP);
|
||||
RECORD(FILE_SORTED_DECLS);
|
||||
RECORD(IMPORTED_MODULES);
|
||||
RECORD(LOCAL_REDECLARATIONS);
|
||||
RECORD(OBJC_CATEGORIES);
|
||||
RECORD(MACRO_OFFSET);
|
||||
RECORD(LATE_PARSED_TEMPLATE);
|
||||
|
@ -997,6 +995,7 @@ void ASTWriter::WriteBlockInfoBlock() {
|
|||
RECORD(TYPE_ATOMIC);
|
||||
RECORD(TYPE_DECAYED);
|
||||
RECORD(TYPE_ADJUSTED);
|
||||
RECORD(LOCAL_REDECLARATIONS);
|
||||
RECORD(DECL_TYPEDEF);
|
||||
RECORD(DECL_TYPEALIAS);
|
||||
RECORD(DECL_ENUM);
|
||||
|
@ -3794,76 +3793,6 @@ void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {
|
|||
Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
|
||||
}
|
||||
|
||||
void ASTWriter::WriteRedeclarations() {
|
||||
RecordData LocalRedeclChains;
|
||||
SmallVector<serialization::LocalRedeclarationsInfo, 2> LocalRedeclsMap;
|
||||
|
||||
for (unsigned I = 0, N = Redeclarations.size(); I != N; ++I) {
|
||||
const Decl *FirstLocal = Redeclarations[I];
|
||||
assert(!FirstLocal->isFromASTFile() &&
|
||||
(!FirstLocal->getPreviousDecl() ||
|
||||
FirstLocal->getPreviousDecl()->isFromASTFile() ||
|
||||
getDeclID(FirstLocal->getPreviousDecl()) < NUM_PREDEF_DECL_IDS) &&
|
||||
"not the first local declaration");
|
||||
assert(getDeclID(FirstLocal) >= NUM_PREDEF_DECL_IDS &&
|
||||
"should not have predefined decl as first decl");
|
||||
|
||||
unsigned Offset = LocalRedeclChains.size();
|
||||
unsigned Size = 0;
|
||||
LocalRedeclChains.push_back(0); // Placeholder for the size.
|
||||
|
||||
// Collect the set of local redeclarations of this declaration, from newest
|
||||
// to oldest.
|
||||
for (const Decl *Prev = FirstLocal->getMostRecentDecl(); Prev != FirstLocal;
|
||||
Prev = Prev->getPreviousDecl()) {
|
||||
if (!Prev->isFromASTFile()) {
|
||||
AddDeclRef(Prev, LocalRedeclChains);
|
||||
++Size;
|
||||
}
|
||||
}
|
||||
|
||||
// If we only have a single local declaration, there is no point in storing
|
||||
// a redeclaration chain.
|
||||
if (LocalRedeclChains.size() == 1)
|
||||
continue;
|
||||
|
||||
LocalRedeclChains[Offset] = Size;
|
||||
|
||||
// Add the mapping from the first ID from the AST to the set of local
|
||||
// declarations.
|
||||
LocalRedeclarationsInfo Info = { getDeclID(FirstLocal), Offset };
|
||||
LocalRedeclsMap.push_back(Info);
|
||||
|
||||
assert(N == Redeclarations.size() &&
|
||||
"Deserialized a declaration we shouldn't have");
|
||||
}
|
||||
|
||||
if (LocalRedeclChains.empty())
|
||||
return;
|
||||
|
||||
// Sort the local redeclarations map by the first declaration ID,
|
||||
// since the reader will be performing binary searches on this information.
|
||||
llvm::array_pod_sort(LocalRedeclsMap.begin(), LocalRedeclsMap.end());
|
||||
|
||||
// Emit the local redeclarations map.
|
||||
using namespace llvm;
|
||||
llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
|
||||
Abbrev->Add(BitCodeAbbrevOp(LOCAL_REDECLARATIONS_MAP));
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
|
||||
unsigned AbbrevID = Stream.EmitAbbrev(Abbrev);
|
||||
|
||||
RecordData Record;
|
||||
Record.push_back(LOCAL_REDECLARATIONS_MAP);
|
||||
Record.push_back(LocalRedeclsMap.size());
|
||||
Stream.EmitRecordWithBlob(AbbrevID, Record,
|
||||
reinterpret_cast<char*>(LocalRedeclsMap.data()),
|
||||
LocalRedeclsMap.size() * sizeof(LocalRedeclarationsInfo));
|
||||
|
||||
// Emit the redeclaration chains.
|
||||
Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedeclChains);
|
||||
}
|
||||
|
||||
void ASTWriter::WriteObjCCategories() {
|
||||
SmallVector<ObjCCategoriesInfo, 2> CategoriesMap;
|
||||
RecordData Categories;
|
||||
|
@ -4589,7 +4518,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
|
|||
}
|
||||
|
||||
WriteDeclReplacementsBlock();
|
||||
WriteRedeclarations();
|
||||
WriteObjCCategories();
|
||||
if(!WritingModule)
|
||||
WriteOptimizePragmaOptions(SemaRef);
|
||||
|
|
|
@ -1565,8 +1565,6 @@ void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
|
|||
// first local declaration in the chain.
|
||||
const Decl *FirstLocal = Writer.getFirstLocalDecl(DAsT);
|
||||
if (DAsT == FirstLocal) {
|
||||
Writer.Redeclarations.push_back(DAsT);
|
||||
|
||||
// Emit a list of all imported first declarations so that we can be sure
|
||||
// that all redeclarations visible to this module are before D in the
|
||||
// redecl chain.
|
||||
|
@ -1576,6 +1574,23 @@ void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
|
|||
AddFirstDeclFromEachModule(DAsT, /*IncludeLocal*/false);
|
||||
// This is the number of imported first declarations + 1.
|
||||
Record[I] = Record.size() - I;
|
||||
|
||||
// Collect the set of local redeclarations of this declaration, from
|
||||
// newest to oldest.
|
||||
RecordData LocalRedecls;
|
||||
for (const Decl *Prev = FirstLocal->getMostRecentDecl();
|
||||
Prev != FirstLocal; Prev = Prev->getPreviousDecl())
|
||||
if (!Prev->isFromASTFile())
|
||||
Writer.AddDeclRef(Prev, LocalRedecls);
|
||||
|
||||
// If we have any redecls, write them now as a separate record preceding
|
||||
// the declaration itself.
|
||||
if (LocalRedecls.empty())
|
||||
Record.push_back(0);
|
||||
else {
|
||||
Record.push_back(Writer.Stream.GetCurrentBitNo());
|
||||
Writer.Stream.EmitRecord(LOCAL_REDECLARATIONS, LocalRedecls);
|
||||
}
|
||||
} else {
|
||||
Record.push_back(0);
|
||||
Writer.AddDeclRef(FirstLocal, Record);
|
||||
|
@ -2114,6 +2129,13 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
|
|||
VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
|
||||
}
|
||||
|
||||
// Build a record for this declaration
|
||||
Record.clear();
|
||||
W.Code = (serialization::DeclCode)0;
|
||||
W.AbbrevToUse = 0;
|
||||
W.Visit(D);
|
||||
if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
|
||||
|
||||
if (isReplacingADecl) {
|
||||
// We're replacing a decl in a previous file.
|
||||
ReplacedDecls.push_back(ReplacedDeclInfo(ID, Stream.GetCurrentBitNo(),
|
||||
|
@ -2130,19 +2152,12 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
|
|||
DeclOffsets[Index].setLocation(Loc);
|
||||
DeclOffsets[Index].BitOffset = Stream.GetCurrentBitNo();
|
||||
}
|
||||
|
||||
|
||||
SourceManager &SM = Context.getSourceManager();
|
||||
if (Loc.isValid() && SM.isLocalSourceLocation(Loc))
|
||||
associateDeclWithFile(D, ID);
|
||||
}
|
||||
|
||||
// Build and emit a record for this declaration
|
||||
Record.clear();
|
||||
W.Code = (serialization::DeclCode)0;
|
||||
W.AbbrevToUse = 0;
|
||||
W.Visit(D);
|
||||
if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
|
||||
|
||||
if (!W.Code)
|
||||
llvm::report_fatal_error(StringRef("unexpected declaration kind '") +
|
||||
D->getDeclKindName() + "'");
|
||||
|
|
|
@ -40,7 +40,6 @@ ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation)
|
|||
LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(nullptr),
|
||||
LocalNumCXXCtorInitializers(0), CXXCtorInitializersOffsets(nullptr),
|
||||
FileSortedDecls(nullptr), NumFileSortedDecls(0),
|
||||
RedeclarationsMap(nullptr), LocalNumRedeclarationsInMap(0),
|
||||
ObjCCategoriesMap(nullptr), LocalNumObjCCategoriesInMap(0),
|
||||
LocalNumTypes(0), TypeOffsets(nullptr), BaseTypeIndex(0)
|
||||
{}
|
||||
|
|
Loading…
Reference in New Issue