forked from OSchip/llvm-project
[PCH] Keep track of file-level declarations that are contained by files.
Introduce a FILE_SORTED_DECLS [de]serialization record that contains a file sorted array of file-level DeclIDs in a PCH/Module. The rationale is to allow "targeted" deserialization of decls inside a range of a source file. Cocoa PCH increased by 0.8% Difference of creation time for Cocoa PCH is below the noise level. llvm-svn: 143238
This commit is contained in:
parent
3d785edee2
commit
5fc727a0c2
|
@ -436,7 +436,10 @@ namespace clang {
|
|||
|
||||
/// \brief Record code for ObjC categories in a module that are chained to
|
||||
/// an interface.
|
||||
OBJC_CHAINED_CATEGORIES
|
||||
OBJC_CHAINED_CATEGORIES,
|
||||
|
||||
/// \brief Record code for a file sorted array of DeclIDs in a module.
|
||||
FILE_SORTED_DECLS
|
||||
};
|
||||
|
||||
/// \brief Record types used within a source manager block.
|
||||
|
|
|
@ -296,6 +296,9 @@ private:
|
|||
/// \brief Declarations that have been replaced in a later file in the chain.
|
||||
DeclReplacementMap ReplacedDecls;
|
||||
|
||||
/// \brief Map from a FileID to the file-level declarations that it contains.
|
||||
llvm::DenseMap<FileID, ArrayRef<serialization::DeclID> > FileDeclIDs;
|
||||
|
||||
// Updates for visible decls can occur for other contexts than just the
|
||||
// TU, and when we read those update records, the actual context will not
|
||||
// be available yet (unless it's the TU), so have this pending map using the
|
||||
|
|
|
@ -59,6 +59,8 @@ class SwitchCase;
|
|||
class TargetInfo;
|
||||
class VersionTuple;
|
||||
|
||||
namespace SrcMgr { class SLocEntry; }
|
||||
|
||||
/// \brief Writes an AST file containing the contents of a translation unit.
|
||||
///
|
||||
/// The ASTWriter class produces a bitstream containing the serialized
|
||||
|
@ -144,6 +146,25 @@ private:
|
|||
/// the declaration's ID.
|
||||
std::vector<serialization::DeclOffset> DeclOffsets;
|
||||
|
||||
/// \brief Vector of pairs of raw location/DeclID.
|
||||
typedef SmallVector<std::pair<unsigned, serialization::DeclID>, 64>
|
||||
LocDeclIDsTy;
|
||||
struct DeclIDInFileInfo {
|
||||
LocDeclIDsTy DeclIDs;
|
||||
/// \brief Set when the DeclIDs vectors from all files are joined, this
|
||||
/// indicates the index that this particular vector has in the global one.
|
||||
unsigned FirstDeclIndex;
|
||||
};
|
||||
typedef llvm::DenseMap<const SrcMgr::SLocEntry *,
|
||||
DeclIDInFileInfo *> FileDeclIDsTy;
|
||||
|
||||
/// \brief Map from file SLocEntries to info about the file-level declarations
|
||||
/// that it contains.
|
||||
FileDeclIDsTy FileDeclIDs;
|
||||
|
||||
void associateDeclWithFile(const Decl *D, serialization::DeclID,
|
||||
SourceLocation FileLoc);
|
||||
|
||||
/// \brief The first ID number we can use for our own types.
|
||||
serialization::TypeID FirstTypeID;
|
||||
|
||||
|
@ -354,6 +375,7 @@ private:
|
|||
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
|
||||
uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
|
||||
void WriteTypeDeclOffsets();
|
||||
void WriteFileDeclIDsMap();
|
||||
void WriteSelectors(Sema &SemaRef);
|
||||
void WriteReferencedSelectorsPool(Sema &SemaRef);
|
||||
void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,
|
||||
|
@ -393,6 +415,7 @@ public:
|
|||
/// \brief Create a new precompiled header writer that outputs to
|
||||
/// the given bitstream.
|
||||
ASTWriter(llvm::BitstreamWriter &Stream);
|
||||
~ASTWriter();
|
||||
|
||||
/// \brief Write a precompiled header for the given semantic analysis.
|
||||
///
|
||||
|
|
|
@ -271,6 +271,9 @@ public:
|
|||
/// Key is the ID of the interface.
|
||||
/// Value is a pair of linked category DeclIDs (head category, tail category).
|
||||
ChainedObjCCategoriesMap ChainedObjCCategories;
|
||||
|
||||
/// \brief Array of file-level DeclIDs sorted by file.
|
||||
const serialization::DeclID *FileSortedDecls;
|
||||
|
||||
// === Types ===
|
||||
|
||||
|
|
|
@ -1134,6 +1134,13 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(int ID) {
|
|||
FileInfo.NumCreatedFIDs = Record[6];
|
||||
if (Record[3])
|
||||
FileInfo.setHasLineDirectives();
|
||||
|
||||
const DeclID *FirstDecl = F->FileSortedDecls + Record[7];
|
||||
unsigned NumFileDecls = Record[8];
|
||||
if (NumFileDecls) {
|
||||
assert(F->FileSortedDecls && "FILE_SORTED_DECLS not encountered yet ?");
|
||||
FileDeclIDs[FID] = llvm::makeArrayRef(FirstDecl, NumFileDecls);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -1960,6 +1967,10 @@ ASTReader::ReadASTBlock(Module &F) {
|
|||
if (!Record.empty() && Listener)
|
||||
Listener->ReadCounter(Record[0]);
|
||||
break;
|
||||
|
||||
case FILE_SORTED_DECLS:
|
||||
F.FileSortedDecls = (const DeclID *)BlobStart;
|
||||
break;
|
||||
|
||||
case SOURCE_LOCATION_OFFSETS: {
|
||||
F.SLocEntryOffsets = (const uint32_t *)BlobStart;
|
||||
|
|
|
@ -1172,6 +1172,8 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
|
|||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumCreatedFIDs
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 24)); // FirstDeclIndex
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumDecls
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
|
||||
return Stream.EmitAbbrev(Abbrev);
|
||||
}
|
||||
|
@ -1445,6 +1447,15 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
|
|||
Record.push_back(Content->OrigEntry->getModificationTime());
|
||||
|
||||
Record.push_back(File.NumCreatedFIDs);
|
||||
|
||||
FileDeclIDsTy::iterator FDI = FileDeclIDs.find(SLoc);
|
||||
if (FDI != FileDeclIDs.end()) {
|
||||
Record.push_back(FDI->second->FirstDeclIndex);
|
||||
Record.push_back(FDI->second->DeclIDs.size());
|
||||
} else {
|
||||
Record.push_back(0);
|
||||
Record.push_back(0);
|
||||
}
|
||||
|
||||
// Turn the file name into an absolute path, if it isn't already.
|
||||
const char *Filename = Content->OrigEntry->getName();
|
||||
|
@ -1972,6 +1983,29 @@ void ASTWriter::WriteTypeDeclOffsets() {
|
|||
Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, data(DeclOffsets));
|
||||
}
|
||||
|
||||
void ASTWriter::WriteFileDeclIDsMap() {
|
||||
using namespace llvm;
|
||||
RecordData Record;
|
||||
|
||||
// Join the vectors of DeclIDs from all files.
|
||||
SmallVector<DeclID, 256> FileSortedIDs;
|
||||
for (FileDeclIDsTy::iterator
|
||||
FI = FileDeclIDs.begin(), FE = FileDeclIDs.end(); FI != FE; ++FI) {
|
||||
DeclIDInFileInfo &Info = *FI->second;
|
||||
Info.FirstDeclIndex = FileSortedIDs.size();
|
||||
for (LocDeclIDsTy::iterator
|
||||
DI = Info.DeclIDs.begin(), DE = Info.DeclIDs.end(); DI != DE; ++DI)
|
||||
FileSortedIDs.push_back(DI->second);
|
||||
}
|
||||
|
||||
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
|
||||
Abbrev->Add(BitCodeAbbrevOp(FILE_SORTED_DECLS));
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
|
||||
unsigned AbbrevCode = Stream.EmitAbbrev(Abbrev);
|
||||
Record.push_back(FILE_SORTED_DECLS);
|
||||
Stream.EmitRecordWithBlob(AbbrevCode, Record, data(FileSortedIDs));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Global Method Pool and Selector Serialization
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -2732,6 +2766,12 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream)
|
|||
{
|
||||
}
|
||||
|
||||
ASTWriter::~ASTWriter() {
|
||||
for (FileDeclIDsTy::iterator
|
||||
I = FileDeclIDs.begin(), E = FileDeclIDs.end(); I != E; ++I)
|
||||
delete I->second;
|
||||
}
|
||||
|
||||
void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
||||
const std::string &OutputFile,
|
||||
bool IsModule, StringRef isysroot) {
|
||||
|
@ -2910,49 +2950,6 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
|||
WriteLanguageOptions(Context.getLangOptions());
|
||||
if (StatCalls && isysroot.empty())
|
||||
WriteStatCache(*StatCalls);
|
||||
WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
|
||||
|
||||
if (Chain) {
|
||||
// Write the mapping information describing our module dependencies and how
|
||||
// each of those modules were mapped into our own offset/ID space, so that
|
||||
// the reader can build the appropriate mapping to its own offset/ID space.
|
||||
// The map consists solely of a blob with the following format:
|
||||
// *(module-name-len:i16 module-name:len*i8
|
||||
// source-location-offset:i32
|
||||
// identifier-id:i32
|
||||
// preprocessed-entity-id:i32
|
||||
// macro-definition-id:i32
|
||||
// selector-id:i32
|
||||
// declaration-id:i32
|
||||
// c++-base-specifiers-id:i32
|
||||
// type-id:i32)
|
||||
//
|
||||
llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
|
||||
Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP));
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
|
||||
unsigned ModuleOffsetMapAbbrev = Stream.EmitAbbrev(Abbrev);
|
||||
llvm::SmallString<2048> Buffer;
|
||||
{
|
||||
llvm::raw_svector_ostream Out(Buffer);
|
||||
for (ModuleManager::ModuleConstIterator M = Chain->ModuleMgr.begin(),
|
||||
MEnd = Chain->ModuleMgr.end();
|
||||
M != MEnd; ++M) {
|
||||
StringRef FileName = (*M)->FileName;
|
||||
io::Emit16(Out, FileName.size());
|
||||
Out.write(FileName.data(), FileName.size());
|
||||
io::Emit32(Out, (*M)->SLocEntryBaseOffset);
|
||||
io::Emit32(Out, (*M)->BaseIdentifierID);
|
||||
io::Emit32(Out, (*M)->BasePreprocessedEntityID);
|
||||
io::Emit32(Out, (*M)->BaseSelectorID);
|
||||
io::Emit32(Out, (*M)->BaseDeclID);
|
||||
io::Emit32(Out, (*M)->BaseTypeIndex);
|
||||
}
|
||||
}
|
||||
Record.clear();
|
||||
Record.push_back(MODULE_OFFSET_MAP);
|
||||
Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record,
|
||||
Buffer.data(), Buffer.size());
|
||||
}
|
||||
|
||||
// Create a lexical update block containing all of the declarations in the
|
||||
// translation unit that do not come from other AST files.
|
||||
|
@ -3030,6 +3027,51 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
|
|||
}
|
||||
Stream.ExitBlock();
|
||||
|
||||
WriteFileDeclIDsMap();
|
||||
WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
|
||||
|
||||
if (Chain) {
|
||||
// Write the mapping information describing our module dependencies and how
|
||||
// each of those modules were mapped into our own offset/ID space, so that
|
||||
// the reader can build the appropriate mapping to its own offset/ID space.
|
||||
// The map consists solely of a blob with the following format:
|
||||
// *(module-name-len:i16 module-name:len*i8
|
||||
// source-location-offset:i32
|
||||
// identifier-id:i32
|
||||
// preprocessed-entity-id:i32
|
||||
// macro-definition-id:i32
|
||||
// selector-id:i32
|
||||
// declaration-id:i32
|
||||
// c++-base-specifiers-id:i32
|
||||
// type-id:i32)
|
||||
//
|
||||
llvm::BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
|
||||
Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP));
|
||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
|
||||
unsigned ModuleOffsetMapAbbrev = Stream.EmitAbbrev(Abbrev);
|
||||
llvm::SmallString<2048> Buffer;
|
||||
{
|
||||
llvm::raw_svector_ostream Out(Buffer);
|
||||
for (ModuleManager::ModuleConstIterator M = Chain->ModuleMgr.begin(),
|
||||
MEnd = Chain->ModuleMgr.end();
|
||||
M != MEnd; ++M) {
|
||||
StringRef FileName = (*M)->FileName;
|
||||
io::Emit16(Out, FileName.size());
|
||||
Out.write(FileName.data(), FileName.size());
|
||||
io::Emit32(Out, (*M)->SLocEntryBaseOffset);
|
||||
io::Emit32(Out, (*M)->BaseIdentifierID);
|
||||
io::Emit32(Out, (*M)->BasePreprocessedEntityID);
|
||||
io::Emit32(Out, (*M)->BaseSelectorID);
|
||||
io::Emit32(Out, (*M)->BaseDeclID);
|
||||
io::Emit32(Out, (*M)->BaseTypeIndex);
|
||||
}
|
||||
}
|
||||
Record.clear();
|
||||
Record.push_back(MODULE_OFFSET_MAP);
|
||||
Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record,
|
||||
Buffer.data(), Buffer.size());
|
||||
}
|
||||
|
||||
WritePreprocessor(PP, IsModule);
|
||||
WriteHeaderSearch(PP.getHeaderSearchInfo(), isysroot);
|
||||
WriteSelectors(SemaRef);
|
||||
|
@ -3439,6 +3481,48 @@ DeclID ASTWriter::getDeclID(const Decl *D) {
|
|||
return DeclIDs[D];
|
||||
}
|
||||
|
||||
static inline bool compLocDecl(std::pair<unsigned, serialization::DeclID> L,
|
||||
std::pair<unsigned, serialization::DeclID> R) {
|
||||
return L.first < R.first;
|
||||
}
|
||||
|
||||
void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID,
|
||||
SourceLocation FileLoc) {
|
||||
assert(ID);
|
||||
assert(FileLoc.isValid());
|
||||
assert(FileLoc.isFileID());
|
||||
|
||||
// We only keep track of the file-level declarations of each file.
|
||||
if (!D->getLexicalDeclContext()->isFileContext())
|
||||
return;
|
||||
|
||||
SourceManager &SM = Context->getSourceManager();
|
||||
assert(SM.isLocalSourceLocation(FileLoc));
|
||||
FileID FID = SM.getFileID(FileLoc);
|
||||
if (FID.isInvalid())
|
||||
return;
|
||||
const SrcMgr::SLocEntry *Entry = &SM.getSLocEntry(FID);
|
||||
assert(Entry->isFile());
|
||||
|
||||
DeclIDInFileInfo *&Info = FileDeclIDs[Entry];
|
||||
if (!Info)
|
||||
Info = new DeclIDInFileInfo();
|
||||
|
||||
unsigned RawLoc = FileLoc.getRawEncoding();
|
||||
std::pair<unsigned, serialization::DeclID> LocDecl(RawLoc, ID);
|
||||
LocDeclIDsTy &Decls = Info->DeclIDs;
|
||||
|
||||
if (Decls.empty() || Decls.back().first <= RawLoc) {
|
||||
Decls.push_back(LocDecl);
|
||||
return;
|
||||
}
|
||||
|
||||
LocDeclIDsTy::iterator
|
||||
I = std::upper_bound(Decls.begin(), Decls.end(), LocDecl, compLocDecl);
|
||||
|
||||
Decls.insert(I, LocDecl);
|
||||
}
|
||||
|
||||
void ASTWriter::AddDeclarationName(DeclarationName Name, RecordDataImpl &Record) {
|
||||
// FIXME: Emit a stable enum for NameKind. 0 = Identifier etc.
|
||||
Record.push_back(Name.getNameKind());
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/DeclContextInternals.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Bitcode/BitstreamWriter.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
@ -1651,14 +1652,20 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
|
|||
unsigned Index = ID - FirstDeclID;
|
||||
|
||||
// Record the offset for this declaration
|
||||
SourceLocation Loc = D->getLocation();
|
||||
if (DeclOffsets.size() == Index)
|
||||
DeclOffsets.push_back(DeclOffset(D->getLocation(),
|
||||
Stream.GetCurrentBitNo()));
|
||||
DeclOffsets.push_back(DeclOffset(Loc, Stream.GetCurrentBitNo()));
|
||||
else if (DeclOffsets.size() < Index) {
|
||||
DeclOffsets.resize(Index+1);
|
||||
DeclOffsets[Index].setLocation(D->getLocation());
|
||||
DeclOffsets[Index].setLocation(Loc);
|
||||
DeclOffsets[Index].BitOffset = Stream.GetCurrentBitNo();
|
||||
}
|
||||
|
||||
SourceManager &SM = Context.getSourceManager();
|
||||
if (Loc.isValid() && SM.isLocalSourceLocation(Loc)) {
|
||||
SourceLocation FileLoc = SM.getFileLoc(Loc);
|
||||
associateDeclWithFile(D, ID, FileLoc);
|
||||
}
|
||||
}
|
||||
|
||||
// Build and emit a record for this declaration
|
||||
|
|
|
@ -35,6 +35,7 @@ Module::Module(ModuleKind Kind)
|
|||
SelectorLookupTableData(0), SelectorLookupTable(0), LocalNumDecls(0),
|
||||
DeclOffsets(0), BaseDeclID(0),
|
||||
LocalNumCXXBaseSpecifiers(0), CXXBaseSpecifiersOffsets(0),
|
||||
FileSortedDecls(0),
|
||||
LocalNumTypes(0), TypeOffsets(0), BaseTypeIndex(0), StatCache(0)
|
||||
{}
|
||||
|
||||
|
|
Loading…
Reference in New Issue