First baby steps towards PCHReader being able to keep track of multiple PCH files. WIP

llvm-svn: 108537
This commit is contained in:
Sebastian Redl 2010-07-16 17:50:48 +00:00
parent c30b4ddc58
commit 34522813e7
4 changed files with 109 additions and 58 deletions

View File

@ -147,14 +147,14 @@ private:
void Error(const char *Msg); void Error(const char *Msg);
}; };
/// \brief Reads a precompiled head containing the contents of a /// \brief Reads a precompiled header chain containing the contents of a
/// translation unit. /// translation unit.
/// ///
/// The PCHReader class reads a bitstream (produced by the PCHWriter /// The PCHReader class reads bitstreams (produced by the PCHWriter
/// class) containing the serialized representation of a given /// class) containing the serialized representation of a given
/// abstract syntax tree and its supporting data structures. An /// abstract syntax tree and its supporting data structures. An
/// instance of the PCHReader can be attached to an ASTContext object, /// instance of the PCHReader can be attached to an ASTContext object,
/// which will provide access to the contents of the PCH file. /// which will provide access to the contents of the PCH files.
/// ///
/// The PCH reader provides lazy de-serialization of declarations, as /// The PCH reader provides lazy de-serialization of declarations, as
/// required when traversing the AST. Only those AST nodes that are /// required when traversing the AST. Only those AST nodes that are
@ -181,65 +181,86 @@ private:
Diagnostic &Diags; Diagnostic &Diags;
/// \brief The semantic analysis object that will be processing the /// \brief The semantic analysis object that will be processing the
/// PCH file and the translation unit that uses it. /// PCH files and the translation unit that uses it.
Sema *SemaObj; Sema *SemaObj;
/// \brief The preprocessor that will be loading the source file. /// \brief The preprocessor that will be loading the source file.
Preprocessor *PP; Preprocessor *PP;
/// \brief The AST context into which we'll read the PCH file. /// \brief The AST context into which we'll read the PCH files.
ASTContext *Context; ASTContext *Context;
/// \brief The PCH stat cache installed by this PCHReader, if any.
///
/// The dynamic type of this stat cache is always PCHStatCache
void *StatCache;
/// \brief The AST consumer. /// \brief The AST consumer.
ASTConsumer *Consumer; ASTConsumer *Consumer;
/// \brief The bitstream reader from which we'll read the PCH file. /// \brief Information that is needed for every file in the chain.
llvm::BitstreamReader StreamFile; struct PerFileData {
llvm::BitstreamCursor Stream; PerFileData();
/// \brief The cursor to the start of the preprocessor block, which stores /// \brief The PCH stat cache installed for this file, if any.
/// all of the macro definitions. ///
llvm::BitstreamCursor MacroCursor; /// The dynamic type of this stat cache is always PCHStatCache
void *StatCache;
/// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It /// \brief The bitstream reader from which we'll read the PCH file.
/// has read all the abbreviations at the start of the block and is ready to llvm::BitstreamReader StreamFile;
/// jump around with these in context. llvm::BitstreamCursor Stream;
llvm::BitstreamCursor DeclsCursor;
/// \brief The file name of the PCH file. /// \brief The cursor to the start of the preprocessor block, which stores
std::string FileName; /// all of the macro definitions.
llvm::BitstreamCursor MacroCursor;
/// \brief The memory buffer that stores the data associated with /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It
/// this PCH file. /// has read all the abbreviations at the start of the block and is ready to
llvm::OwningPtr<llvm::MemoryBuffer> Buffer; /// jump around with these in context.
llvm::BitstreamCursor DeclsCursor;
/// \brief Offset type for all of the source location entries in the /// \brief The file name of the PCH file.
/// PCH file. std::string FileName;
/// \brief The memory buffer that stores the data associated with
/// this PCH file.
llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
/// \brief Cursor used to read source location entries.
llvm::BitstreamCursor SLocEntryCursor;
/// \brief The number of source location entries in this PCH file.
unsigned LocalNumSLocEntries;
/// \brief The number of types in this PCH file.
unsigned LocalNumTypes;
/// \brief The number of declarations in this PCH file.
unsigned LocalNumDecls;
};
/// \brief The chain of PCH files. The first entry is the one named by the
/// user, the last one is the one that doesn't depend on anything further.
llvm::SmallVector<PerFileData*, 2> Chain;
/// \brief Offsets for all of the source location entries in the
/// PCH files. The offsets are relative to a particular file; the correct
/// file is chosen using their IDs.
const uint32_t *SLocOffsets; const uint32_t *SLocOffsets;
/// \brief The number of source location entries in the PCH file. /// \brief The number of source location entries in all PCH files.
unsigned TotalNumSLocEntries; unsigned TotalNumSLocEntries;
/// \brief Cursor used to read source location entries.
llvm::BitstreamCursor SLocEntryCursor;
/// \brief Offset of each type within the bitstream, indexed by the /// \brief Offset of each type within the bitstream, indexed by the
/// type ID, or the representation of a Type*. /// type ID, or the representation of a Type*. The offset is local to the
/// containing file; the file is chosen using the ID.
const uint32_t *TypeOffsets; const uint32_t *TypeOffsets;
/// \brief Types that have already been loaded from the PCH file. /// \brief Types that have already been loaded from the PCH file.
/// ///
/// When the pointer at index I is non-NULL, the type with /// When the pointer at index I is non-NULL, the type with
/// ID = (I + 1) << 3 has already been loaded from the PCH file. /// ID = (I + 1) << FastQual::Width has already been loaded from the PCH chain
std::vector<QualType> TypesLoaded; std::vector<QualType> TypesLoaded;
/// \brief Offset of each declaration within the bitstream, indexed /// \brief Offset of each declaration within the bitstream, indexed
/// by the declaration ID (-1). /// by the declaration ID (-1). The offset is local to the containing file;
/// the file is chosen using the ID.
const uint32_t *DeclOffsets; const uint32_t *DeclOffsets;
/// \brief Declarations that have already been loaded from the PCH file. /// \brief Declarations that have already been loaded from the PCH file.
@ -588,8 +609,8 @@ public:
/// \brief Sets and initializes the given Context. /// \brief Sets and initializes the given Context.
void InitializeContext(ASTContext &Context); void InitializeContext(ASTContext &Context);
/// \brief Retrieve the name of the PCH file /// \brief Retrieve the name of the named (primary) PCH file
const std::string &getFileName() const { return FileName; } const std::string &getFileName() const { return Chain[0]->FileName; }
/// \brief Retrieve the name of the original source file name /// \brief Retrieve the name of the original source file name
const std::string &getOriginalSourceFile() { return OriginalFileName; } const std::string &getOriginalSourceFile() { return OriginalFileName; }
@ -844,8 +865,8 @@ public:
Sema *getSema() { return SemaObj; } Sema *getSema() { return SemaObj; }
/// \brief Retrieve the stream that this PCH reader is reading from. /// \brief Retrieve the stream that this PCH reader is reading from.
llvm::BitstreamCursor &getStream() { return Stream; } llvm::BitstreamCursor &getStream() { return Chain[0]->Stream; }
llvm::BitstreamCursor &getDeclsCursor() { return DeclsCursor; } llvm::BitstreamCursor &getDeclsCursor() { return Chain[0]->DeclsCursor; }
/// \brief Retrieve the identifier table associated with the /// \brief Retrieve the identifier table associated with the
/// preprocessor. /// preprocessor.

View File

@ -418,7 +418,7 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
: Listener(new PCHValidator(PP, *this)), DeserializationListener(0), : Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context), Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context),
StatCache(0), Consumer(0), IdentifierTableData(0), IdentifierLookupTable(0), Consumer(0), IdentifierTableData(0), IdentifierLookupTable(0),
IdentifierOffsets(0), IdentifierOffsets(0),
MethodPoolLookupTable(0), MethodPoolLookupTableData(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
TotalSelectorsInMethodPool(0), SelectorOffsets(0), TotalSelectorsInMethodPool(0), SelectorOffsets(0),
@ -435,7 +435,7 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
Diagnostic &Diags, const char *isysroot) Diagnostic &Diags, const char *isysroot)
: DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr), : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr),
Diags(Diags), SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0), Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0),
IdentifierTableData(0), IdentifierLookupTable(0), IdentifierTableData(0), IdentifierLookupTable(0),
IdentifierOffsets(0), IdentifierOffsets(0),
MethodPoolLookupTable(0), MethodPoolLookupTableData(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
@ -450,7 +450,14 @@ PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
RelocatablePCH = false; RelocatablePCH = false;
} }
PCHReader::~PCHReader() {} PCHReader::~PCHReader() {
for (unsigned i = 0, e = Chain.size(); i != e; ++i)
delete Chain[e - i - 1];
}
PCHReader::PerFileData::PerFileData()
: StatCache(0)
{}
namespace { namespace {
@ -878,14 +885,16 @@ public:
PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
using namespace SrcMgr; using namespace SrcMgr;
llvm::BitstreamCursor &SLocEntryCursor = Chain[0]->SLocEntryCursor;
// Set the source-location entry cursor to the current position in // Set the source-location entry cursor to the current position in
// the stream. This cursor will be used to read the contents of the // the stream. This cursor will be used to read the contents of the
// source manager block initially, and then lazily read // source manager block initially, and then lazily read
// source-location entries as needed. // source-location entries as needed.
SLocEntryCursor = Stream; SLocEntryCursor = Chain[0]->Stream;
// The stream itself is going to skip over the source manager block. // The stream itself is going to skip over the source manager block.
if (Stream.SkipBlock()) { if (Chain[0]->Stream.SkipBlock()) {
Error("malformed block record in PCH file"); Error("malformed block record in PCH file");
return Failure; return Failure;
} }
@ -954,6 +963,8 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
return Failure; return Failure;
} }
llvm::BitstreamCursor &SLocEntryCursor = Chain[0]->SLocEntryCursor;
++NumSLocEntriesRead; ++NumSLocEntriesRead;
SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]); SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]);
unsigned Code = SLocEntryCursor.ReadCode(); unsigned Code = SLocEntryCursor.ReadCode();
@ -1089,6 +1100,8 @@ bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
void PCHReader::ReadMacroRecord(uint64_t Offset) { void PCHReader::ReadMacroRecord(uint64_t Offset) {
assert(PP && "Forgot to set Preprocessor ?"); assert(PP && "Forgot to set Preprocessor ?");
llvm::BitstreamCursor &Stream = Chain[0]->Stream;
// Keep track of where we are in the stream, then jump back there // Keep track of where we are in the stream, then jump back there
// after reading this macro. // after reading this macro.
SavedStreamPosition SavedPosition(Stream); SavedStreamPosition SavedPosition(Stream);
@ -1258,6 +1271,8 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
} }
void PCHReader::ReadDefinedMacros() { void PCHReader::ReadDefinedMacros() {
llvm::BitstreamCursor &MacroCursor = Chain[0]->MacroCursor;
// If there was no preprocessor block, do nothing. // If there was no preprocessor block, do nothing.
if (!MacroCursor.getBitStreamReader()) if (!MacroCursor.getBitStreamReader())
return; return;
@ -1354,6 +1369,9 @@ void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) {
PCHReader::PCHReadResult PCHReader::PCHReadResult
PCHReader::ReadPCHBlock() { PCHReader::ReadPCHBlock() {
PerFileData &F = *Chain[0];
llvm::BitstreamCursor &Stream = F.Stream;
if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) { if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
Error("malformed block record in PCH file"); Error("malformed block record in PCH file");
return Failure; return Failure;
@ -1379,17 +1397,17 @@ PCHReader::ReadPCHBlock() {
// DeclsCursor cursor to point into it. Clone our current bitcode // DeclsCursor cursor to point into it. Clone our current bitcode
// cursor to it, enter the block and read the abbrevs in that block. // cursor to it, enter the block and read the abbrevs in that block.
// With the main cursor, we just skip over it. // With the main cursor, we just skip over it.
DeclsCursor = Stream; F.DeclsCursor = Stream;
if (Stream.SkipBlock() || // Skip with the main cursor. if (Stream.SkipBlock() || // Skip with the main cursor.
// Read the abbrevs. // Read the abbrevs.
ReadBlockAbbrevs(DeclsCursor, pch::DECLTYPES_BLOCK_ID)) { ReadBlockAbbrevs(F.DeclsCursor, pch::DECLTYPES_BLOCK_ID)) {
Error("malformed block record in PCH file"); Error("malformed block record in PCH file");
return Failure; return Failure;
} }
break; break;
case pch::PREPROCESSOR_BLOCK_ID: case pch::PREPROCESSOR_BLOCK_ID:
MacroCursor = Stream; F.MacroCursor = Stream;
if (PP) if (PP)
PP->setExternalSource(this); PP->setExternalSource(this);
@ -1578,7 +1596,7 @@ PCHReader::ReadPCHBlock() {
(const unsigned char *)BlobStart, (const unsigned char *)BlobStart,
NumStatHits, NumStatMisses); NumStatHits, NumStatMisses);
FileMgr.addStatCache(MyStatCache); FileMgr.addStatCache(MyStatCache);
StatCache = MyStatCache; F.StatCache = MyStatCache;
break; break;
} }
@ -1641,23 +1659,27 @@ PCHReader::ReadPCHBlock() {
} }
PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
Chain.push_back(new PerFileData());
PerFileData &F = *Chain.back();
// Set the PCH file name. // Set the PCH file name.
this->FileName = FileName; F.FileName = FileName;
// Open the PCH file. // Open the PCH file.
// //
// FIXME: This shouldn't be here, we should just take a raw_ostream. // FIXME: This shouldn't be here, we should just take a raw_ostream.
std::string ErrStr; std::string ErrStr;
Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr)); F.Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
if (!Buffer) { if (!F.Buffer) {
Error(ErrStr.c_str()); Error(ErrStr.c_str());
return IgnorePCH; return IgnorePCH;
} }
// Initialize the stream // Initialize the stream
StreamFile.init((const unsigned char *)Buffer->getBufferStart(), F.StreamFile.init((const unsigned char *)F.Buffer->getBufferStart(),
(const unsigned char *)Buffer->getBufferEnd()); (const unsigned char *)F.Buffer->getBufferEnd());
Stream.init(StreamFile); llvm::BitstreamCursor &Stream = F.Stream;
Stream.init(F.StreamFile);
// Sniff for the signature. // Sniff for the signature.
if (Stream.Read(8) != 'C' || if (Stream.Read(8) != 'C' ||
@ -1704,8 +1726,8 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
SourceMgr.ClearPreallocatedSLocEntries(); SourceMgr.ClearPreallocatedSLocEntries();
// Remove the stat cache. // Remove the stat cache.
if (StatCache) if (F.StatCache)
FileMgr.removeStatCache((PCHStatCache*)StatCache); FileMgr.removeStatCache((PCHStatCache*)F.StatCache);
return IgnorePCH; return IgnorePCH;
} }
@ -2049,6 +2071,8 @@ void PCHReader::ReadPreprocessedEntities() {
/// at the given offset in the bitstream. It is a helper routine for /// at the given offset in the bitstream. It is a helper routine for
/// GetType, which deals with reading type IDs. /// GetType, which deals with reading type IDs.
QualType PCHReader::ReadTypeRecord(uint64_t Offset) { QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
llvm::BitstreamCursor &DeclsCursor = Chain[0]->DeclsCursor;
// Keep track of where we are in the stream, then jump back there // Keep track of where we are in the stream, then jump back there
// after reading this type. // after reading this type.
SavedStreamPosition SavedPosition(DeclsCursor); SavedStreamPosition SavedPosition(DeclsCursor);
@ -2716,8 +2740,8 @@ Decl *PCHReader::GetDecl(pch::DeclID ID) {
Stmt *PCHReader::GetExternalDeclStmt(uint64_t Offset) { Stmt *PCHReader::GetExternalDeclStmt(uint64_t Offset) {
// Since we know tha this statement is part of a decl, make sure to use the // Since we know tha this statement is part of a decl, make sure to use the
// decl cursor to read it. // decl cursor to read it.
DeclsCursor.JumpToBit(Offset); Chain[0]->DeclsCursor.JumpToBit(Offset);
return ReadStmtFromStream(DeclsCursor); return ReadStmtFromStream(Chain[0]->DeclsCursor);
} }
bool PCHReader::FindExternalLexicalDecls(const DeclContext *DC, bool PCHReader::FindExternalLexicalDecls(const DeclContext *DC,
@ -2731,6 +2755,8 @@ bool PCHReader::FindExternalLexicalDecls(const DeclContext *DC,
return true; return true;
} }
llvm::BitstreamCursor &DeclsCursor = Chain[0]->DeclsCursor;
// Keep track of where we are in the stream, then jump back there // Keep track of where we are in the stream, then jump back there
// after reading this context. // after reading this context.
SavedStreamPosition SavedPosition(DeclsCursor); SavedStreamPosition SavedPosition(DeclsCursor);
@ -2765,6 +2791,8 @@ PCHReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclContext::lookup_iterator()); DeclContext::lookup_iterator());
} }
llvm::BitstreamCursor &DeclsCursor = Chain[0]->DeclsCursor;
// Keep track of where we are in the stream, then jump back there // Keep track of where we are in the stream, then jump back there
// after reading this context. // after reading this context.
SavedStreamPosition SavedPosition(DeclsCursor); SavedStreamPosition SavedPosition(DeclsCursor);

View File

@ -1038,6 +1038,7 @@ PCHDeclReader::VisitDeclContext(DeclContext *DC) {
/// \brief Reads attributes from the current stream position. /// \brief Reads attributes from the current stream position.
Attr *PCHReader::ReadAttributes() { Attr *PCHReader::ReadAttributes() {
llvm::BitstreamCursor &DeclsCursor = Chain[0]->DeclsCursor;
unsigned Code = DeclsCursor.ReadCode(); unsigned Code = DeclsCursor.ReadCode();
assert(Code == llvm::bitc::UNABBREV_RECORD && assert(Code == llvm::bitc::UNABBREV_RECORD &&
"Expected unabbreviated record"); (void)Code; "Expected unabbreviated record"); (void)Code;
@ -1252,6 +1253,7 @@ static bool isConsumerInterestedIn(Decl *D) {
/// \brief Read the declaration at the given offset from the PCH file. /// \brief Read the declaration at the given offset from the PCH file.
Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
llvm::BitstreamCursor &DeclsCursor = Chain[0]->DeclsCursor;
// Keep track of where we are in the stream, then jump back there // Keep track of where we are in the stream, then jump back there
// after reading this declaration. // after reading this declaration.
SavedStreamPosition SavedPosition(DeclsCursor); SavedStreamPosition SavedPosition(DeclsCursor);

View File

@ -1215,7 +1215,7 @@ Stmt *PCHReader::ReadStmt() {
case Read_Decl: case Read_Decl:
case Read_Type: case Read_Type:
// Read a statement from the current DeclCursor. // Read a statement from the current DeclCursor.
return ReadStmtFromStream(DeclsCursor); return ReadStmtFromStream(Chain[0]->DeclsCursor);
case Read_Stmt: case Read_Stmt:
return ReadSubStmt(); return ReadSubStmt();
} }