DECLTYPES_BLOCK_ID,
/// \brief The block containing DECL_UPDATES records.
- DECL_UPDATES_BLOCK_ID
+ DECL_UPDATES_BLOCK_ID,
+
+ /// \brief The block containing the detailed preprocessing record.
+ PREPROCESSOR_DETAIL_BLOCK_ID
};
/// \brief Record types that occur within the AST block itself.
/// \brief Describes one token.
/// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]
- PP_TOKEN = 3,
+ PP_TOKEN = 3
+ };
+ /// \brief Record types used within a preprocessor detail block.
+ enum PreprocessorDetailRecordTypes {
/// \brief Describes a macro instantiation within the preprocessing
/// record.
- PP_MACRO_INSTANTIATION = 4,
+ PPD_MACRO_INSTANTIATION = 0,
/// \brief Describes a macro definition within the preprocessing record.
- PP_MACRO_DEFINITION = 5,
+ PPD_MACRO_DEFINITION = 1,
- /// \brief Describes am inclusion directive within the preprocessing
+ /// \brief Describes an inclusion directive within the preprocessing
/// record.
- PP_INCLUSION_DIRECTIVE = 6
+ PPD_INCLUSION_DIRECTIVE = 2
};
-
+
/// \defgroup ASTAST AST file AST constants
///
/// The constants in this group describe various components of the
/// \brief The offset of the start of the set of defined macros.
uint64_t MacroStartOffset;
+ // === Detailed PreprocessingRecord ===
+
+ /// \brief The cursor to the start of the (optional) detailed preprocessing
+ /// record block.
+ llvm::BitstreamCursor PreprocessorDetailCursor;
+
+ /// \brief The offset of the start of the preprocessor detail cursor.
+ uint64_t PreprocessorDetailStartOffset;
+
/// \brief The number of macro definitions in this file.
unsigned LocalNumMacroDefinitions;
-
+
/// \brief Offsets of all of the macro definitions in the preprocessing
/// record in the AST file.
const uint32_t *MacroDefinitionOffsets;
/// \brief Reads the macro record located at the given offset.
PreprocessedEntity *ReadMacroRecord(PerFileData &F, uint64_t Offset);
+ /// \brief Reads the preprocessed entity located at the current stream
+ /// position.
+ PreprocessedEntity *LoadPreprocessedEntity(PerFileData &F);
+
/// \brief Note that the identifier is a macro whose record will be loaded
/// from the given AST file at the given (file-local) offset.
void SetIdentifierIsMacro(IdentifierInfo *II, PerFileData &F,
class MemorizeStatCalls;
class ASTReader;
class PreprocessedEntity;
+class PreprocessingRecord;
class Preprocessor;
class Sema;
class SourceManager;
const Preprocessor &PP,
const char* isysroot);
void WritePreprocessor(const Preprocessor &PP);
+ void WritePreprocessorDetail(PreprocessingRecord &PPRec);
void WritePragmaDiagnosticMappings(const Diagnostic &Diag);
void WriteType(QualType T);
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
Macro->AddTokenToBody(Tok);
break;
}
+ }
+ }
+
+ return 0;
+}
- case PP_MACRO_INSTANTIATION: {
- // If we already have a macro, that means that we've hit the end
- // of the definition of the macro we were looking for. We're
- // done.
- if (Macro)
- return 0;
-
- if (!PP->getPreprocessingRecord()) {
- Error("missing preprocessing record in AST file");
- return 0;
- }
+PreprocessedEntity *ASTReader::LoadPreprocessedEntity(PerFileData &F) {
+ assert(PP && "Forgot to set Preprocessor ?");
+ unsigned Code = F.PreprocessorDetailCursor.ReadCode();
+ switch (Code) {
+ case llvm::bitc::END_BLOCK:
+ return 0;
+
+ case llvm::bitc::ENTER_SUBBLOCK:
+ Error("unexpected subblock record in preprocessor detail block");
+ return 0;
+
+ case llvm::bitc::DEFINE_ABBREV:
+ Error("unexpected abbrevation record in preprocessor detail block");
+ return 0;
+
+ default:
+ break;
+ }
- PreprocessingRecord &PPRec = *PP->getPreprocessingRecord();
- if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0]))
- return PE;
-
- MacroInstantiation *MI
- = new (PPRec) MacroInstantiation(DecodeIdentifierInfo(Record[3]),
- SourceRange(ReadSourceLocation(F, Record[1]),
- ReadSourceLocation(F, Record[2])),
- getMacroDefinition(Record[4]));
- PPRec.SetPreallocatedEntity(Record[0], MI);
- return MI;
+ if (!PP->getPreprocessingRecord()) {
+ Error("no preprocessing record");
+ return 0;
+ }
+
+ // Read the record.
+ PreprocessingRecord &PPRec = *PP->getPreprocessingRecord();
+ const char *BlobStart = 0;
+ unsigned BlobLen = 0;
+ RecordData Record;
+ PreprocessorDetailRecordTypes RecType =
+ (PreprocessorDetailRecordTypes)F.PreprocessorDetailCursor.ReadRecord(
+ Code, Record, BlobStart, BlobLen);
+ switch (RecType) {
+ case PPD_MACRO_INSTANTIATION: {
+ if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0]))
+ return PE;
+
+ MacroInstantiation *MI
+ = new (PPRec) MacroInstantiation(DecodeIdentifierInfo(Record[3]),
+ SourceRange(ReadSourceLocation(F, Record[1]),
+ ReadSourceLocation(F, Record[2])),
+ getMacroDefinition(Record[4]));
+ PPRec.SetPreallocatedEntity(Record[0], MI);
+ return MI;
+ }
+
+ case PPD_MACRO_DEFINITION: {
+ if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0]))
+ return PE;
+
+ if (Record[1] > MacroDefinitionsLoaded.size()) {
+ Error("out-of-bounds macro definition record");
+ return 0;
}
-
- case PP_MACRO_DEFINITION: {
- // If we already have a macro, that means that we've hit the end
- // of the definition of the macro we were looking for. We're
- // done.
- if (Macro)
- return 0;
-
- if (!PP->getPreprocessingRecord()) {
- Error("missing preprocessing record in AST file");
- return 0;
- }
-
- PreprocessingRecord &PPRec = *PP->getPreprocessingRecord();
- if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0]))
- return PE;
-
- if (Record[1] > MacroDefinitionsLoaded.size()) {
- Error("out-of-bounds macro definition record");
- return 0;
- }
-
- // Decode the identifier info and then check again; if the macro is
- // still defined and associated with the identifier,
- IdentifierInfo *II = DecodeIdentifierInfo(Record[4]);
- if (!MacroDefinitionsLoaded[Record[1] - 1]) {
- MacroDefinition *MD
- = new (PPRec) MacroDefinition(II,
- ReadSourceLocation(F, Record[5]),
- SourceRange(
- ReadSourceLocation(F, Record[2]),
- ReadSourceLocation(F, Record[3])));
-
- PPRec.SetPreallocatedEntity(Record[0], MD);
- MacroDefinitionsLoaded[Record[1] - 1] = MD;
-
- if (DeserializationListener)
- DeserializationListener->MacroDefinitionRead(Record[1], MD);
- }
-
- return MacroDefinitionsLoaded[Record[1] - 1];
+
+ // Decode the identifier info and then check again; if the macro is
+ // still defined and associated with the identifier,
+ IdentifierInfo *II = DecodeIdentifierInfo(Record[4]);
+ if (!MacroDefinitionsLoaded[Record[1] - 1]) {
+ MacroDefinition *MD
+ = new (PPRec) MacroDefinition(II,
+ ReadSourceLocation(F, Record[5]),
+ SourceRange(
+ ReadSourceLocation(F, Record[2]),
+ ReadSourceLocation(F, Record[3])));
+
+ PPRec.SetPreallocatedEntity(Record[0], MD);
+ MacroDefinitionsLoaded[Record[1] - 1] = MD;
+
+ if (DeserializationListener)
+ DeserializationListener->MacroDefinitionRead(Record[1], MD);
}
-
- case PP_INCLUSION_DIRECTIVE: {
- // If we already have a macro, that means that we've hit the end
- // of the definition of the macro we were looking for. We're
- // done.
- if (Macro)
- return 0;
-
- if (!PP->getPreprocessingRecord()) {
- Error("missing preprocessing record in AST file");
- return 0;
- }
-
- PreprocessingRecord &PPRec = *PP->getPreprocessingRecord();
- if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0]))
- return PE;
-
- const char *FullFileNameStart = BlobStart + Record[3];
- const FileEntry *File
- = PP->getFileManager().getFile(llvm::StringRef(FullFileNameStart,
- BlobLen - Record[3]));
-
- // FIXME: Stable encoding
- InclusionDirective::InclusionKind Kind
- = static_cast<InclusionDirective::InclusionKind>(Record[5]);
- InclusionDirective *ID
- = new (PPRec) InclusionDirective(PPRec, Kind,
- llvm::StringRef(BlobStart, Record[3]),
- Record[4],
- File,
+
+ return MacroDefinitionsLoaded[Record[1] - 1];
+ }
+
+ case PPD_INCLUSION_DIRECTIVE: {
+ if (PreprocessedEntity *PE = PPRec.getPreprocessedEntity(Record[0]))
+ return PE;
+
+ const char *FullFileNameStart = BlobStart + Record[3];
+ const FileEntry *File
+ = PP->getFileManager().getFile(llvm::StringRef(FullFileNameStart,
+ BlobLen - Record[3]));
+
+ // FIXME: Stable encoding
+ InclusionDirective::InclusionKind Kind
+ = static_cast<InclusionDirective::InclusionKind>(Record[5]);
+ InclusionDirective *ID
+ = new (PPRec) InclusionDirective(PPRec, Kind,
+ llvm::StringRef(BlobStart, Record[3]),
+ Record[4],
+ File,
SourceRange(ReadSourceLocation(F, Record[1]),
ReadSourceLocation(F, Record[2])));
- PPRec.SetPreallocatedEntity(Record[0], ID);
- return ID;
- }
- }
+ PPRec.SetPreallocatedEntity(Record[0], ID);
+ return ID;
+ }
}
+ Error("invalid offset in preprocessor detail block");
return 0;
}
RecordData Record;
while (true) {
- uint64_t Offset = Cursor.GetCurrentBitNo();
unsigned Code = Cursor.ReadCode();
if (Code == llvm::bitc::END_BLOCK)
break;
case PP_TOKEN:
// Ignore tokens.
break;
-
- case PP_MACRO_INSTANTIATION:
- case PP_MACRO_DEFINITION:
- case PP_INCLUSION_DIRECTIVE:
- // Read the macro record.
- // FIXME: That's a stupid way to do this. We should reuse this cursor.
- ReadMacroRecord(F, Offset);
- break;
}
}
}
for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
PerFileData &F = *Chain[N - I - 1];
if (Index < F.LocalNumMacroDefinitions) {
- ReadMacroRecord(F, F.MacroDefinitionOffsets[Index]);
+ SavedStreamPosition SavedPosition(F.PreprocessorDetailCursor);
+ F.PreprocessorDetailCursor.JumpToBit(F.MacroDefinitionOffsets[Index]);
+ LoadPreprocessedEntity(F);
break;
}
Index -= F.LocalNumMacroDefinitions;
F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo();
break;
+ case PREPROCESSOR_DETAIL_BLOCK_ID:
+ F.PreprocessorDetailCursor = Stream;
+ if (Stream.SkipBlock() ||
+ ReadBlockAbbrevs(F.PreprocessorDetailCursor,
+ PREPROCESSOR_DETAIL_BLOCK_ID)) {
+ Error("malformed preprocessor detail record in AST file");
+ return Failure;
+ }
+ F.PreprocessorDetailStartOffset
+ = F.PreprocessorDetailCursor.GetCurrentBitNo();
+ break;
+
case SOURCE_MANAGER_BLOCK_ID:
switch (ReadSourceManagerBlock(F)) {
case Success:
}
void ASTReader::ReadPreprocessedEntities() {
- ReadDefinedMacros();
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[I];
+ if (!F.PreprocessorDetailCursor.getBitStreamReader())
+ continue;
+
+ SavedStreamPosition SavedPosition(F.PreprocessorDetailCursor);
+ F.PreprocessorDetailCursor.JumpToBit(F.PreprocessorDetailStartOffset);
+ while (LoadPreprocessedEntity(F)) { }
+ }
}
PreprocessedEntity *ASTReader::ReadPreprocessedEntity(uint64_t Offset) {
return 0;
}
- return ReadMacroRecord(*F, Offset);
+ // Keep track of where we are in the stream, then jump back there
+ // after reading this entity.
+ SavedStreamPosition SavedPosition(F->PreprocessorDetailCursor);
+ F->PreprocessorDetailCursor.JumpToBit(Offset);
+ return LoadPreprocessedEntity(*F);
}
void ASTReader::ReadPragmaDiagnosticMappings(Diagnostic &Diag) {
RECORD(PP_MACRO_OBJECT_LIKE);
RECORD(PP_MACRO_FUNCTION_LIKE);
RECORD(PP_TOKEN);
- RECORD(PP_MACRO_INSTANTIATION);
- RECORD(PP_MACRO_DEFINITION);
- RECORD(PP_INCLUSION_DIRECTIVE);
// Decls and Types block.
BLOCK(DECLTYPES_BLOCK);
RECORD(DECL_INDIRECTFIELD);
RECORD(DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK);
+ BLOCK(PREPROCESSOR_DETAIL_BLOCK);
+ RECORD(PPD_MACRO_INSTANTIATION);
+ RECORD(PPD_MACRO_DEFINITION);
+ RECORD(PPD_INCLUSION_DIRECTIVE);
+
// Statements and Exprs can occur in the Decls and Types block.
AddStmtsExprs(Stream, Record);
#undef RECORD
// Loop over all the macro definitions that are live at the end of the file,
// emitting each to the PP section.
PreprocessingRecord *PPRec = PP.getPreprocessingRecord();
- unsigned InclusionAbbrev = 0;
- if (PPRec) {
- using namespace llvm;
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(PP_INCLUSION_DIRECTIVE));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // start location
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // end location
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
- InclusionAbbrev = Stream.EmitAbbrev(Abbrev);
- }
+ // FIXME: If we are chaining, don't visit all of the macros!
for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
I != E; ++I) {
// FIXME: This emits macros in hash table order, we should do it in a stable
}
++NumMacros;
}
+ Stream.ExitBlock();
+
+ if (PPRec)
+ WritePreprocessorDetail(*PPRec);
+}
+
+void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
+ if (PPRec.begin(Chain) == PPRec.end(Chain))
+ return;
+
+ // Enter the preprocessor block.
+ Stream.EnterSubblock(PREPROCESSOR_DETAIL_BLOCK_ID, 3);
// If the preprocessor has a preprocessing record, emit it.
unsigned NumPreprocessingRecords = 0;
- if (PPRec) {
- unsigned IndexBase = Chain ? PPRec->getNumPreallocatedEntities() : 0;
- for (PreprocessingRecord::iterator E = PPRec->begin(Chain),
- EEnd = PPRec->end(Chain);
- E != EEnd; ++E) {
- Record.clear();
+ using namespace llvm;
+
+ // Set up the abbreviation for
+ unsigned InclusionAbbrev = 0;
+ {
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(PPD_INCLUSION_DIRECTIVE));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // start location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // end location
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ InclusionAbbrev = Stream.EmitAbbrev(Abbrev);
+ }
+
+ unsigned IndexBase = Chain ? PPRec.getNumPreallocatedEntities() : 0;
+ RecordData Record;
+ for (PreprocessingRecord::iterator E = PPRec.begin(Chain),
+ EEnd = PPRec.end(Chain);
+ E != EEnd; ++E) {
+ Record.clear();
- if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
- // Record this macro definition's location.
- MacroID ID = getMacroDefinitionID(MD);
-
- // Don't write the macro definition if it is from another AST file.
- if (ID < FirstMacroID)
- continue;
-
- // Notify the serialization listener that we're serializing this entity.
- if (SerializationListener)
- SerializationListener->SerializedPreprocessedEntity(*E,
- Stream.GetCurrentBitNo());
-
- unsigned Position = ID - FirstMacroID;
- if (Position != MacroDefinitionOffsets.size()) {
- if (Position > MacroDefinitionOffsets.size())
- MacroDefinitionOffsets.resize(Position + 1);
-
- MacroDefinitionOffsets[Position] = Stream.GetCurrentBitNo();
- } else
- MacroDefinitionOffsets.push_back(Stream.GetCurrentBitNo());
-
- Record.push_back(IndexBase + NumPreprocessingRecords++);
- Record.push_back(ID);
- AddSourceLocation(MD->getSourceRange().getBegin(), Record);
- AddSourceLocation(MD->getSourceRange().getEnd(), Record);
- AddIdentifierRef(MD->getName(), Record);
- AddSourceLocation(MD->getLocation(), Record);
- Stream.EmitRecord(PP_MACRO_DEFINITION, Record);
+ if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
+ // Record this macro definition's location.
+ MacroID ID = getMacroDefinitionID(MD);
+
+ // Don't write the macro definition if it is from another AST file.
+ if (ID < FirstMacroID)
continue;
- }
-
+
// Notify the serialization listener that we're serializing this entity.
if (SerializationListener)
SerializationListener->SerializedPreprocessedEntity(*E,
- Stream.GetCurrentBitNo());
-
- if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
- Record.push_back(IndexBase + NumPreprocessingRecords++);
- AddSourceLocation(MI->getSourceRange().getBegin(), Record);
- AddSourceLocation(MI->getSourceRange().getEnd(), Record);
- AddIdentifierRef(MI->getName(), Record);
- Record.push_back(getMacroDefinitionID(MI->getDefinition()));
- Stream.EmitRecord(PP_MACRO_INSTANTIATION, Record);
- continue;
- }
+ Stream.GetCurrentBitNo());
- if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) {
- Record.push_back(PP_INCLUSION_DIRECTIVE);
- Record.push_back(IndexBase + NumPreprocessingRecords++);
- AddSourceLocation(ID->getSourceRange().getBegin(), Record);
- AddSourceLocation(ID->getSourceRange().getEnd(), Record);
- Record.push_back(ID->getFileName().size());
- Record.push_back(ID->wasInQuotes());
- Record.push_back(static_cast<unsigned>(ID->getKind()));
- llvm::SmallString<64> Buffer;
- Buffer += ID->getFileName();
- Buffer += ID->getFile()->getName();
- Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer);
- continue;
- }
+ unsigned Position = ID - FirstMacroID;
+ if (Position != MacroDefinitionOffsets.size()) {
+ if (Position > MacroDefinitionOffsets.size())
+ MacroDefinitionOffsets.resize(Position + 1);
+
+ MacroDefinitionOffsets[Position] = Stream.GetCurrentBitNo();
+ } else
+ MacroDefinitionOffsets.push_back(Stream.GetCurrentBitNo());
- llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter");
+ Record.push_back(IndexBase + NumPreprocessingRecords++);
+ Record.push_back(ID);
+ AddSourceLocation(MD->getSourceRange().getBegin(), Record);
+ AddSourceLocation(MD->getSourceRange().getEnd(), Record);
+ AddIdentifierRef(MD->getName(), Record);
+ AddSourceLocation(MD->getLocation(), Record);
+ Stream.EmitRecord(PPD_MACRO_DEFINITION, Record);
+ continue;
}
- }
+ // Notify the serialization listener that we're serializing this entity.
+ if (SerializationListener)
+ SerializationListener->SerializedPreprocessedEntity(*E,
+ Stream.GetCurrentBitNo());
+
+ if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
+ Record.push_back(IndexBase + NumPreprocessingRecords++);
+ AddSourceLocation(MI->getSourceRange().getBegin(), Record);
+ AddSourceLocation(MI->getSourceRange().getEnd(), Record);
+ AddIdentifierRef(MI->getName(), Record);
+ Record.push_back(getMacroDefinitionID(MI->getDefinition()));
+ Stream.EmitRecord(PPD_MACRO_INSTANTIATION, Record);
+ continue;
+ }
+
+ if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) {
+ Record.push_back(PPD_INCLUSION_DIRECTIVE);
+ Record.push_back(IndexBase + NumPreprocessingRecords++);
+ AddSourceLocation(ID->getSourceRange().getBegin(), Record);
+ AddSourceLocation(ID->getSourceRange().getEnd(), Record);
+ Record.push_back(ID->getFileName().size());
+ Record.push_back(ID->wasInQuotes());
+ Record.push_back(static_cast<unsigned>(ID->getKind()));
+ llvm::SmallString<64> Buffer;
+ Buffer += ID->getFileName();
+ Buffer += ID->getFile()->getName();
+ Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer);
+ continue;
+ }
+
+ llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter");
+ }
Stream.ExitBlock();
// Write the offsets table for the preprocessing record.