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