SerializedDiagnosticPrinter.cpp revision 28eac520cf4f95e81cb8d85ff34b96d96046d50d
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) 647800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek : Stream(Buffer), OS(os), Diags(diags) 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; 1237800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1247800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek enum BlockIDs { 1257800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief The DIAG block, which acts as a container around a diagnostic. 1267800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek BLOCK_DIAG = llvm::bitc::FIRST_APPLICATION_BLOCKID, 1277800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// \brief The STRINGS block, which contains strings 1287800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek /// from multiple diagnostics. 1297800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek BLOCK_STRINGS 1307800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek }; 1317800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1327800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek enum RecordIDs { 1337800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RECORD_DIAG = 1, 1347800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RECORD_DIAG_FLAG, 1357800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RECORD_CATEGORY, 1367800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RECORD_FILENAME 1377800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek }; 1387800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1397800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek}; 1407800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} // end anonymous namespace 1417800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1427800212ef29be314d55814e8dcc568ff8beed106Ted Kremeneknamespace clang { 1437800212ef29be314d55814e8dcc568ff8beed106Ted Kremeneknamespace serialized_diags { 1447800212ef29be314d55814e8dcc568ff8beed106Ted KremenekDiagnosticConsumer *create(llvm::raw_ostream *OS, DiagnosticsEngine &Diags) { 1457800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek return new SDiagsWriter(Diags, OS); 1467800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 1477800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} // end namespace serialized_diags 1487800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} // end namespace clang 1497800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1507800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//===----------------------------------------------------------------------===// 1517800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek// Serialization methods. 1527800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek//===----------------------------------------------------------------------===// 1537800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1547800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek/// \brief Emits a block ID in the BLOCKINFO block. 1557800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekstatic void EmitBlockID(unsigned ID, const char *Name, 1567800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::BitstreamWriter &Stream, 1577800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RecordDataImpl &Record) { 1587800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 1597800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(ID); 1607800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); 1617800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1627800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit the block name if present. 1637800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek if (Name == 0 || Name[0] == 0) 1647800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek return; 1657800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1667800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 1677800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1687800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek while (*Name) 1697800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(*Name++); 1707800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1717800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); 1727800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 1737800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1747800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek/// \brief Emits a record ID in the BLOCKINFO block. 1757800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekstatic void EmitRecordID(unsigned ID, const char *Name, 1767800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::BitstreamWriter &Stream, 1777800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek RecordDataImpl &Record){ 1787800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 1797800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(ID); 1807800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1817800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek while (*Name) 1827800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(*Name++); 1837800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1847800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); 1857800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 1867800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1877800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek/// \brief Emits the preamble of the diagnostics file. 1887800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::EmitPreamble() { 1897800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // EmitRawStringContents("CLANG_DIAGS"); 1907800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Stream.Emit(Version, 32); 1917800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1927800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit the file header. 1937800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.Emit((unsigned)'D', 8); 1947800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.Emit((unsigned)'I', 8); 1957800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.Emit((unsigned)'A', 8); 1967800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.Emit((unsigned)'G', 8); 1977800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 1987800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitBlockInfoBlock(); 1997800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 2007800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2017800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::EmitBlockInfoBlock() { 2027800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EnterBlockInfoBlock(3); 2037800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2047800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // ==---------------------------------------------------------------------==// 2057800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // The subsequent records and Abbrevs are for the "Diagnostic" block. 2067800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // ==---------------------------------------------------------------------==// 2077800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2087800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitBlockID(BLOCK_DIAG, "Diagnostic", Stream, Record); 2097800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitRecordID(RECORD_DIAG, "Diagnostic Info", Stream, Record); 2107800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitRecordID(RECORD_DIAG_FLAG, "Diagnostic Flag", Stream, Record); 2117800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2127800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit Abbrevs. 2137800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek using namespace llvm; 2147800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2157800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit abbreviation for RECORD_DIAG. 2167800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); 2177800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG)); 2187800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Diag level. 2197800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16-3)); // Category. 2207800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 2217800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text. 2227800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 2237800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2247800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2257800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit the abbreviation for RECORD_DIAG_FLAG. 2267800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev = new BitCodeAbbrev(); 2277800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG)); 2287800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 2297800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text. 2307800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 2317800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2327800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // ==---------------------------------------------------------------------==// 2337800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // The subsequent records and Abbrevs are for the "Strings" block. 2347800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // ==---------------------------------------------------------------------==// 2357800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2367800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitBlockID(BLOCK_STRINGS, "Strings", Stream, Record); 2377800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitRecordID(RECORD_CATEGORY, "Category Name", Stream, Record); 2387800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitRecordID(RECORD_FILENAME, "File Name", 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)); 2557800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2567800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.ExitBlock(); 2577800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 2587800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2597800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::EmitRawStringContents(llvm::StringRef str) { 2607800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek for (StringRef::const_iterator I = str.begin(), E = str.end(); I!=E; ++I) 2617800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.Emit(*I, 8); 2627800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 2637800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2647800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 2657800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek const Diagnostic &Info) { 2667800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2677800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek BlockEnterExit DiagBlock(Stream, BLOCK_DIAG); 2687800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2697800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit the RECORD_DIAG record. 2707800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 2717800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(RECORD_DIAG); 2727800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(DiagLevel); 2737800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek unsigned category = DiagnosticIDs::getCategoryNumberForDiag(Info.getID()); 2747800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(category); 2757800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Categories.insert(category); 2767800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek diagBuf.clear(); 2777800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Info.FormatDiagnostic(diagBuf); // Compute the diagnostic text. 2787800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(diagBuf.str().size()); 2797800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, diagBuf.str()); 2807800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2817800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit the RECORD_DIAG_FLAG record. 2827800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(Info.getID()); 2837800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek if (!FlagName.empty()) { 2847800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 2857800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(RECORD_DIAG_FLAG); 2867800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(FlagName.size()); 2877800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG_FLAG), 2887800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record, FlagName.str()); 2897800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 2907800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2917800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // FIXME: emit location 2927800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // FIXME: emit ranges 2937800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // FIXME: emit notes 2947800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // FIXME: emit fixits 2957800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 2967800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 2977800212ef29be314d55814e8dcc568ff8beed106Ted Kremenektemplate <typename T> 2987800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekstatic void populateAndSort(std::vector<T> &scribble, 2997800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek llvm::DenseSet<T> &set) { 3007800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek scribble.clear(); 3017800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3027800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek for (typename llvm::DenseSet<T>::iterator it = set.begin(), ei = set.end(); 3037800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek it != ei; ++it) 3047800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek scribble.push_back(*it); 3057800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3067800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Sort 'scribble' so we always have a deterministic ordering in the 3077800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // serialized file. 3087800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek std::sort(scribble.begin(), scribble.end()); 3097800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 3107800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3117800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::EmitCategoriesAndFileNames() { 3127800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3137800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek if (Categories.empty() && Files.empty()) 3147800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek return; 3157800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3167800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek BlockEnterExit BlockEnter(Stream, BLOCK_STRINGS); 3177800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3187800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit the category names. 3197800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek { 3207800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek std::vector<unsigned> scribble; 3217800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek populateAndSort(scribble, Categories); 3227800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek for (std::vector<unsigned>::iterator it = scribble.begin(), 3237800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek ei = scribble.end(); it != ei ; ++it) { 3247800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 3257800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(RECORD_CATEGORY); 3267800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek StringRef catName = DiagnosticIDs::getCategoryNameFromID(*it); 3277800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(catName.size()); 3287800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_CATEGORY), Record, catName); 3297800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 3307800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 3317800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3327800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Emit the file names. 3337800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek { 3347800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek std::vector<FileID> scribble; 3357800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek populateAndSort(scribble, Files); 3367800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek for (std::vector<FileID>::iterator it = scribble.begin(), 3377800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek ei = scribble.end(); it != ei; ++it) { 3387800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek SourceManager &SM = Diags.getSourceManager(); 3397800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek const FileEntry *FE = SM.getFileEntryForID(*it); 3407800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek StringRef Name = FE->getName(); 3417800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3427800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.clear(); 34328eac520cf4f95e81cb8d85ff34b96d96046d50dTed Kremenek Record.push_back(FE->getSize()); 34428eac520cf4f95e81cb8d85ff34b96d96046d50dTed Kremenek Record.push_back(FE->getModificationTime()); 3457800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Record.push_back(Name.size()); 3467800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FILENAME), Record, Name); 3477800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 3487800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek } 3497800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3507800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 3517800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3527800212ef29be314d55814e8dcc568ff8beed106Ted Kremenekvoid SDiagsWriter::EndSourceFile() { 3537800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek EmitCategoriesAndFileNames(); 3547800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3557800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek // Write the generated bitstream to "Out". 3567800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek OS->write((char *)&Buffer.front(), Buffer.size()); 3577800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek OS->flush(); 3587800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 3597800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek OS.reset(0); 3607800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek} 3617800212ef29be314d55814e8dcc568ff8beed106Ted Kremenek 362