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