SerializedDiagnosticPrinter.cpp revision 069f9c29802f650a793877fa4c9a34853de9ed98
17800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//===--- SerializedDiagnosticPrinter.cpp - Serializer for diagnostics -----===// 27800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek// 37800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek// The LLVM Compiler Infrastructure 47800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek// 57800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek// This file is distributed under the University of Illinois Open Source 67800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek// License. See LICENSE.TXT for details. 77800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek// 87800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//===----------------------------------------------------------------------===// 97800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 107800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include <vector> 117800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include "llvm/Bitcode/BitstreamWriter.h" 127800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include "llvm/Support/raw_ostream.h" 137800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include "llvm/ADT/StringRef.h" 147800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include "llvm/ADT/SmallString.h" 157800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include "llvm/ADT/DenseSet.h" 167800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include "clang/Basic/SourceManager.h" 177800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include "clang/Basic/FileManager.h" 187800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include "clang/Basic/Diagnostic.h" 197800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include "clang/Basic/Version.h" 207800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek#include "clang/Frontend/SerializedDiagnosticPrinter.h" 217800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 227800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekusing namespace clang; 237800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 247800212ef29be314d55814e8dcc568ff8beed106Ted Kremeneknamespace { 257800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 267800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek/// \brief A utility class for entering and exiting bitstream blocks. 277800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekclass BlockEnterExit { 287800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::BitstreamWriter &Stream; 297800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekpublic: 307800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek BlockEnterExit(llvm::BitstreamWriter &stream, unsigned blockID, 317800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek unsigned codelen = 3) 327800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek : Stream(stream) { 337800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EnterSubblock(blockID, codelen); 347800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 357800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek ~BlockEnterExit() { 367800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.ExitBlock(); 377800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 387800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek}; 397800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 407800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekclass AbbreviationMap { 417800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::DenseMap<unsigned, unsigned> Abbrevs; 427800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekpublic: 437800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek AbbreviationMap() {} 447800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 457800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek void set(unsigned recordID, unsigned abbrevID) { 467800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek assert(Abbrevs.find(recordID) == Abbrevs.end() 477800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek && "Abbreviation already set."); 487800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrevs[recordID] = abbrevID; 497800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 507800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 517800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek unsigned get(unsigned recordID) { 527800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek assert(Abbrevs.find(recordID) != Abbrevs.end() && 537800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek "Abbreviation not set."); 547800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek return Abbrevs[recordID]; 557800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 567800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek}; 577800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 587800212ef29be314d55814e8dcc568ff8beed106Ted Kremenektypedef llvm::SmallVector<uint64_t, 64> RecordData; 597800212ef29be314d55814e8dcc568ff8beed106Ted Kremenektypedef llvm::SmallVectorImpl<uint64_t> RecordDataImpl; 607800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 617800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekclass SDiagsWriter : public DiagnosticConsumer { 627800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekpublic: 637800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek SDiagsWriter(DiagnosticsEngine &diags, llvm::raw_ostream *os) 6459b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek : Stream(Buffer), OS(os), Diags(diags), inNonNoteDiagnostic(false) 657800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek { 667800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitPreamble(); 677800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek }; 687800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 697800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek ~SDiagsWriter() {} 707800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 717800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 727800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek const Diagnostic &Info); 737800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 747800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek void EndSourceFile(); 757800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 767800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { 777800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // It makes no sense to clone this. 787800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek return 0; 797800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 807800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 817800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekprivate: 827800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief Emit the preamble for the serialized diagnostics. 837800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek void EmitPreamble(); 847800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 857800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief Emit the BLOCKINFO block. 867800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek void EmitBlockInfoBlock(); 877800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 887800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief Emit the raw characters of the provided string. 897800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek void EmitRawStringContents(StringRef str); 907800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 917800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief Emit the block containing categories and file names. 927800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek void EmitCategoriesAndFileNames(); 937800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 947800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief The version of the diagnostics file. 957800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek enum { Version = 1 }; 967800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 977800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief The byte buffer for the serialized content. 987800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek std::vector<unsigned char> Buffer; 997800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1007800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief The BitStreamWriter for the serialized diagnostics. 1017800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::BitstreamWriter Stream; 1027800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1037800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief The name of the diagnostics file. 1047800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::OwningPtr<llvm::raw_ostream> OS; 1057800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1067800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief The DiagnosticsEngine tied to all diagnostic locations. 1077800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek DiagnosticsEngine &Diags; 1087800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1097800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief The set of constructed record abbreviations. 1107800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek AbbreviationMap Abbrevs; 1117800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1127800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief A utility buffer for constructing record content. 1137800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RecordData Record; 1147800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1157800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief A text buffer for rendering diagnostic text. 1167800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::SmallString<256> diagBuf; 1177800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1187800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief The collection of diagnostic categories used. 1197800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::DenseSet<unsigned> Categories; 1207800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1217800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief The collection of files used. 1227800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::DenseSet<FileID> Files; 12345d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek 12445d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek typedef llvm::DenseMap<const void *, std::pair<unsigned, llvm::StringRef> > 12545d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek DiagFlagsTy; 12645d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek 12745d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek /// \brief Map for uniquing strings. 12845d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek DiagFlagsTy DiagFlags; 1297800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 13059b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek /// \brief Flag indicating whether or not we are in the process of 13159b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek /// emitting a non-note diagnostic. 13259b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek bool inNonNoteDiagnostic; 13359b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek 1347800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek enum BlockIDs { 1357800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief The DIAG block, which acts as a container around a diagnostic. 1367800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek BLOCK_DIAG = llvm::bitc::FIRST_APPLICATION_BLOCKID, 1377800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief The STRINGS block, which contains strings 1387800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// from multiple diagnostics. 1397800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek BLOCK_STRINGS 1407800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek }; 1417800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1427800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek enum RecordIDs { 1437800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RECORD_DIAG = 1, 1447800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RECORD_DIAG_FLAG, 1457800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RECORD_CATEGORY, 1467800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RECORD_FILENAME 1477800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek }; 1487800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek}; 1497800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} // end anonymous namespace 1507800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1517800212ef29be314d55814e8dcc568ff8beed106Ted Kremeneknamespace clang { 1527800212ef29be314d55814e8dcc568ff8beed106Ted Kremeneknamespace serialized_diags { 1537800212ef29be314d55814e8dcc568ff8beed106Ted KremenekDiagnosticConsumer *create(llvm::raw_ostream *OS, DiagnosticsEngine &Diags) { 1547800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek return new SDiagsWriter(Diags, OS); 1557800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 1567800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} // end namespace serialized_diags 1577800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} // end namespace clang 1587800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1597800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//===----------------------------------------------------------------------===// 1607800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek// Serialization methods. 1617800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//===----------------------------------------------------------------------===// 1627800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1637800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek/// \brief Emits a block ID in the BLOCKINFO block. 1647800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekstatic void EmitBlockID(unsigned ID, const char *Name, 1657800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::BitstreamWriter &Stream, 1667800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RecordDataImpl &Record) { 1677800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 1687800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(ID); 1697800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); 1707800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1717800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit the block name if present. 1727800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek if (Name == 0 || Name[0] == 0) 1737800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek return; 1747800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1757800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 1767800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1777800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek while (*Name) 1787800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(*Name++); 1797800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1807800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); 1817800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 1827800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1837800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek/// \brief Emits a record ID in the BLOCKINFO block. 1847800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekstatic void EmitRecordID(unsigned ID, const char *Name, 1857800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::BitstreamWriter &Stream, 1867800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RecordDataImpl &Record){ 1877800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 1887800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(ID); 1897800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1907800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek while (*Name) 1917800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(*Name++); 1927800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1937800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); 1947800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 1957800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1967800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek/// \brief Emits the preamble of the diagnostics file. 1977800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::EmitPreamble() { 1987800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // EmitRawStringContents("CLANG_DIAGS"); 1997800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Stream.Emit(Version, 32); 2007800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2017800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit the file header. 2027800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.Emit((unsigned)'D', 8); 203069f9c29802f650a793877fa4c9a34853de9ed98Ted Kremenek Stream.Emit((unsigned) Version, 32 - 8); 204069f9c29802f650a793877fa4c9a34853de9ed98Ted Kremenek 2057800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitBlockInfoBlock(); 2067800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 2077800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2087800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::EmitBlockInfoBlock() { 2097800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EnterBlockInfoBlock(3); 2107800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2117800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // ==---------------------------------------------------------------------==// 2127800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // The subsequent records and Abbrevs are for the "Diagnostic" block. 2137800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // ==---------------------------------------------------------------------==// 2147800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 21545d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek EmitBlockID(BLOCK_DIAG, "Diag", Stream, Record); 21645d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek EmitRecordID(RECORD_DIAG, "DiagInfo", Stream, Record); 2177800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2187800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit Abbrevs. 2197800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek using namespace llvm; 2207800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2217800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit abbreviation for RECORD_DIAG. 2227800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); 2237800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG)); 22445d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Diag level. 22545d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category. 22645d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID. 2277800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 2287800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text. 2297800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 2307800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2317800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // ==---------------------------------------------------------------------==// 2327800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // The subsequent records and Abbrevs are for the "Strings" block. 2337800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // ==---------------------------------------------------------------------==// 2347800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2357800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitBlockID(BLOCK_STRINGS, "Strings", Stream, Record); 23645d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek EmitRecordID(RECORD_CATEGORY, "CatName", Stream, Record); 23745d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek EmitRecordID(RECORD_FILENAME, "FileName", Stream, Record); 23845d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek EmitRecordID(RECORD_DIAG_FLAG, "DiagFlag", Stream, Record); 2397800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2407800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev = new BitCodeAbbrev(); 2417800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY)); 2427800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); // Text size. 2437800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Category text. 2447800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_STRINGS, 2457800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev)); 2467800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2477800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev = new BitCodeAbbrev(); 24828eac520cf4f95e81cb8d85ff34b96d96046d50dTed Kremenek Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME)); 24928eac520cf4f95e81cb8d85ff34b96d96046d50dTed Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 64)); // Size. 25028eac520cf4f95e81cb8d85ff34b96d96046d50dTed Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 64)); // Modifcation time. 2517800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 2527800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text. 2537800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_STRINGS, 2547800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev)); 25545d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek 25645d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek // Emit the abbreviation for RECORD_DIAG_FLAG. 25745d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Abbrev = new BitCodeAbbrev(); 25845d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG)); 25945d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID. 26045d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 26145d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text. 26245d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_STRINGS, 26345d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Abbrev)); 2647800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2657800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.ExitBlock(); 2667800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 2677800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2687800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::EmitRawStringContents(llvm::StringRef str) { 2697800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek for (StringRef::const_iterator I = str.begin(), E = str.end(); I!=E; ++I) 2707800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.Emit(*I, 8); 2717800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 2727800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2737800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 2747800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek const Diagnostic &Info) { 2757800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 27659b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek if (DiagLevel != DiagnosticsEngine::Note) { 27759b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek if (inNonNoteDiagnostic) { 27859b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek // We have encountered a non-note diagnostic. Finish up the previous 27959b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek // diagnostic block before starting a new one. 28059b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek Stream.ExitBlock(); 28159b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek } 28259b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek inNonNoteDiagnostic = true; 28359b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek } 28459b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek 28559b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek Stream.EnterSubblock(BLOCK_DIAG, 3); 2867800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2877800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit the RECORD_DIAG record. 2887800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 2897800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(RECORD_DIAG); 2907800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(DiagLevel); 2917800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek unsigned category = DiagnosticIDs::getCategoryNumberForDiag(Info.getID()); 2927800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(category); 2937800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Categories.insert(category); 29445d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek if (DiagLevel == DiagnosticsEngine::Note) 29545d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Record.push_back(0); // No flag for notes. 29645d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek else { 29745d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(Info.getID()); 29845d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek if (FlagName.empty()) 29945d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Record.push_back(0); 30045d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek else { 30145d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek // Here we assume that FlagName points to static data whose pointer 30245d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek // value is fixed. 30345d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek const void *data = FlagName.data(); 30445d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek std::pair<unsigned, StringRef> &entry = DiagFlags[data]; 30545d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek if (entry.first == 0) { 30645d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek entry.first = DiagFlags.size(); 30745d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek entry.second = FlagName; 30845d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek } 30945d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Record.push_back(entry.first); 31045d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek } 31145d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek } 31245d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek 3137800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek diagBuf.clear(); 3147800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Info.FormatDiagnostic(diagBuf); // Compute the diagnostic text. 3157800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(diagBuf.str().size()); 3167800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, diagBuf.str()); 3177800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3187800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // FIXME: emit location 3197800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // FIXME: emit ranges 3207800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // FIXME: emit fixits 32159b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek 32259b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek if (DiagLevel == DiagnosticsEngine::Note) { 32359b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek // Notes currently cannot have child diagnostics. Complete the 32459b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek // diagnostic now. 32559b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek Stream.ExitBlock(); 32659b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek } 3277800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 3287800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3297800212ef29be314d55814e8dcc568ff8beed106Ted Kremenektemplate <typename T> 3307800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekstatic void populateAndSort(std::vector<T> &scribble, 3317800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::DenseSet<T> &set) { 3327800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek scribble.clear(); 3337800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3347800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek for (typename llvm::DenseSet<T>::iterator it = set.begin(), ei = set.end(); 3357800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek it != ei; ++it) 3367800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek scribble.push_back(*it); 3377800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3387800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Sort 'scribble' so we always have a deterministic ordering in the 3397800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // serialized file. 3407800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek std::sort(scribble.begin(), scribble.end()); 3417800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 3427800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3437800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::EmitCategoriesAndFileNames() { 3447800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3457800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek if (Categories.empty() && Files.empty()) 3467800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek return; 3477800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3487800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek BlockEnterExit BlockEnter(Stream, BLOCK_STRINGS); 3497800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3507800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit the category names. 3517800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek { 3527800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek std::vector<unsigned> scribble; 3537800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek populateAndSort(scribble, Categories); 3547800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek for (std::vector<unsigned>::iterator it = scribble.begin(), 3557800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek ei = scribble.end(); it != ei ; ++it) { 3567800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 3577800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(RECORD_CATEGORY); 3587800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek StringRef catName = DiagnosticIDs::getCategoryNameFromID(*it); 3597800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(catName.size()); 3607800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_CATEGORY), Record, catName); 3617800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 3627800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 3637800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3647800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit the file names. 3657800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek { 3667800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek std::vector<FileID> scribble; 3677800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek populateAndSort(scribble, Files); 3687800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek for (std::vector<FileID>::iterator it = scribble.begin(), 3697800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek ei = scribble.end(); it != ei; ++it) { 3707800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek SourceManager &SM = Diags.getSourceManager(); 3717800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek const FileEntry *FE = SM.getFileEntryForID(*it); 3727800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek StringRef Name = FE->getName(); 3737800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3747800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 37528eac520cf4f95e81cb8d85ff34b96d96046d50dTed Kremenek Record.push_back(FE->getSize()); 37628eac520cf4f95e81cb8d85ff34b96d96046d50dTed Kremenek Record.push_back(FE->getModificationTime()); 3777800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(Name.size()); 3787800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FILENAME), Record, Name); 3797800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 3807800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 3817800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 38245d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek // Emit the flag strings. 38345d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek { 38445d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek std::vector<StringRef> scribble; 38545d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek scribble.resize(DiagFlags.size()); 38645d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek 38745d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek for (DiagFlagsTy::iterator it = DiagFlags.begin(), ei = DiagFlags.end(); 38845d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek it != ei; ++it) { 38945d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek scribble[it->second.first - 1] = it->second.second; 39045d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek } 39145d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek for (unsigned i = 0, n = scribble.size(); i != n; ++i) { 39245d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Record.clear(); 39345d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Record.push_back(RECORD_DIAG_FLAG); 39445d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Record.push_back(i+1); 39545d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek StringRef FlagName = scribble[i]; 39645d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Record.push_back(FlagName.size()); 39745d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG_FLAG), 39845d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek Record, FlagName); 39945d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek } 40045d92757f84bbf0fe2d996f482821628fd9cb016Ted Kremenek } 4017800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 4027800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 4037800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::EndSourceFile() { 40459b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek if (inNonNoteDiagnostic) { 40559b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek // Finish off any diagnostics we were in the process of emitting. 40659b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek Stream.ExitBlock(); 40759b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek inNonNoteDiagnostic = false; 40859b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek } 40959b61613ed3b835f869b0f6fa1db52b8c963c5e5Ted Kremenek 4107800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitCategoriesAndFileNames(); 4117800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 4127800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Write the generated bitstream to "Out". 4137800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek OS->write((char *)&Buffer.front(), Buffer.size()); 4147800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek OS->flush(); 4157800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 4167800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek OS.reset(0); 4177800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 4187800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 419