SerializedDiagnosticPrinter.cpp revision 239462
1139749Simp//===--- SerializedDiagnosticPrinter.cpp - Serializer for diagnostics -----===// 2119815Smarcel// 3119815Smarcel// The LLVM Compiler Infrastructure 4119815Smarcel// 5119815Smarcel// This file is distributed under the University of Illinois Open Source 6119815Smarcel// License. See LICENSE.TXT for details. 7119815Smarcel// 8119815Smarcel//===----------------------------------------------------------------------===// 9119815Smarcel 10119815Smarcel#include <vector> 11119815Smarcel#include "llvm/Support/raw_ostream.h" 12119815Smarcel#include "llvm/ADT/StringRef.h" 13119815Smarcel#include "llvm/ADT/SmallString.h" 14119815Smarcel#include "llvm/ADT/DenseSet.h" 15119815Smarcel#include "clang/Basic/SourceManager.h" 16119815Smarcel#include "clang/Basic/FileManager.h" 17119815Smarcel#include "clang/Basic/Diagnostic.h" 18119815Smarcel#include "clang/Basic/Version.h" 19119815Smarcel#include "clang/Lex/Lexer.h" 20119815Smarcel#include "clang/Frontend/SerializedDiagnosticPrinter.h" 21119815Smarcel#include "clang/Frontend/DiagnosticRenderer.h" 22119815Smarcel 23119815Smarcelusing namespace clang; 24119815Smarcelusing namespace clang::serialized_diags; 25119815Smarcel 26119815Smarcelnamespace { 27119815Smarcel 28119815Smarcelclass AbbreviationMap { 29119815Smarcel llvm::DenseMap<unsigned, unsigned> Abbrevs; 30119815Smarcelpublic: 31119815Smarcel AbbreviationMap() {} 32119815Smarcel 33119815Smarcel void set(unsigned recordID, unsigned abbrevID) { 34119815Smarcel assert(Abbrevs.find(recordID) == Abbrevs.end() 35119815Smarcel && "Abbreviation already set."); 36119815Smarcel Abbrevs[recordID] = abbrevID; 37119815Smarcel } 38119815Smarcel 39119815Smarcel unsigned get(unsigned recordID) { 40137956Smarcel assert(Abbrevs.find(recordID) != Abbrevs.end() && 41137956Smarcel "Abbreviation not set."); 42119815Smarcel return Abbrevs[recordID]; 43119815Smarcel } 44119815Smarcel}; 45119815Smarcel 46160717Smarceltypedef llvm::SmallVector<uint64_t, 64> RecordData; 47160717Smarceltypedef llvm::SmallVectorImpl<uint64_t> RecordDataImpl; 48160717Smarcel 49160717Smarcelclass SDiagsWriter; 50160717Smarcel 51160717Smarcelclass SDiagsRenderer : public DiagnosticNoteRenderer { 52160717Smarcel SDiagsWriter &Writer; 53119815Smarcel RecordData &Record; 54119815Smarcelpublic: 55119815Smarcel SDiagsRenderer(SDiagsWriter &Writer, RecordData &Record, 56119815Smarcel const LangOptions &LangOpts, 57119815Smarcel const DiagnosticOptions &DiagOpts) 58119815Smarcel : DiagnosticNoteRenderer(LangOpts, DiagOpts), 59119815Smarcel Writer(Writer), Record(Record){} 60119815Smarcel 61119815Smarcel virtual ~SDiagsRenderer() {} 62119815Smarcel 63119815Smarcelprotected: 64119815Smarcel virtual void emitDiagnosticMessage(SourceLocation Loc, 65119815Smarcel PresumedLoc PLoc, 66119815Smarcel DiagnosticsEngine::Level Level, 67119815Smarcel StringRef Message, 68119815Smarcel ArrayRef<CharSourceRange> Ranges, 69119815Smarcel const SourceManager *SM, 70119815Smarcel DiagOrStoredDiag D); 71119815Smarcel 72119815Smarcel virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, 73119815Smarcel DiagnosticsEngine::Level Level, 74119815Smarcel ArrayRef<CharSourceRange> Ranges, 75119815Smarcel const SourceManager &SM) {} 76119815Smarcel 77119815Smarcel void emitNote(SourceLocation Loc, StringRef Message, const SourceManager *SM); 78158504Smarcel 79119815Smarcel virtual void emitCodeContext(SourceLocation Loc, 80119815Smarcel DiagnosticsEngine::Level Level, 81157451Smarcel SmallVectorImpl<CharSourceRange>& Ranges, 82158504Smarcel ArrayRef<FixItHint> Hints, 83119815Smarcel const SourceManager &SM); 84119815Smarcel 85119815Smarcel virtual void beginDiagnostic(DiagOrStoredDiag D, 86119815Smarcel DiagnosticsEngine::Level Level); 87119815Smarcel virtual void endDiagnostic(DiagOrStoredDiag D, 88119815Smarcel DiagnosticsEngine::Level Level); 89119815Smarcel}; 90158504Smarcel 91119815Smarcelclass SDiagsWriter : public DiagnosticConsumer { 92119815Smarcel friend class SDiagsRenderer; 93119815Smarcelpublic: 94119815Smarcel explicit SDiagsWriter(llvm::raw_ostream *os, const DiagnosticOptions &diags) 95119815Smarcel : LangOpts(0), DiagOpts(diags), 96119815Smarcel Stream(Buffer), OS(os), inNonNoteDiagnostic(false) 97119815Smarcel { 98119815Smarcel EmitPreamble(); 99119815Smarcel } 100119815Smarcel 101119815Smarcel ~SDiagsWriter() {} 102119815Smarcel 103119815Smarcel void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 104119815Smarcel const Diagnostic &Info); 105119815Smarcel 106119815Smarcel void BeginSourceFile(const LangOptions &LO, 107119815Smarcel const Preprocessor *PP) { 108119815Smarcel LangOpts = &LO; 109119815Smarcel } 110119815Smarcel 111119815Smarcel virtual void finish(); 112119815Smarcel 113119815Smarcel DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { 114119815Smarcel // It makes no sense to clone this. 115119815Smarcel return 0; 116119815Smarcel } 117119815Smarcel 118119815Smarcelprivate: 119119815Smarcel /// \brief Emit the preamble for the serialized diagnostics. 120119815Smarcel void EmitPreamble(); 121119815Smarcel 122119815Smarcel /// \brief Emit the BLOCKINFO block. 123119815Smarcel void EmitBlockInfoBlock(); 124119815Smarcel 125119815Smarcel /// \brief Emit the META data block. 126119815Smarcel void EmitMetaBlock(); 127119815Smarcel 128119815Smarcel /// \brief Emit a record for a CharSourceRange. 129158504Smarcel void EmitCharSourceRange(CharSourceRange R, const SourceManager &SM); 130119815Smarcel 131158504Smarcel /// \brief Emit the string information for the category. 132158504Smarcel unsigned getEmitCategory(unsigned category = 0); 133158504Smarcel 134160717Smarcel /// \brief Emit the string information for diagnostic flags. 135158504Smarcel unsigned getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel, 136158504Smarcel unsigned DiagID = 0); 137158504Smarcel 138119815Smarcel /// \brief Emit (lazily) the file string and retrieved the file identifier. 139119815Smarcel unsigned getEmitFile(const char *Filename); 140119815Smarcel 141119815Smarcel /// \brief Add SourceLocation information the specified record. 142119815Smarcel void AddLocToRecord(SourceLocation Loc, const SourceManager *SM, 143119815Smarcel PresumedLoc PLoc, RecordDataImpl &Record, 144119815Smarcel unsigned TokSize = 0); 145119815Smarcel 146119815Smarcel /// \brief Add SourceLocation information the specified record. 147119815Smarcel void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record, 148119815Smarcel const SourceManager *SM, 149119815Smarcel unsigned TokSize = 0) { 150160717Smarcel AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(), 151158504Smarcel Record, TokSize); 152119815Smarcel } 153119815Smarcel 154119815Smarcel /// \brief Add CharSourceRange information the specified record. 155119815Smarcel void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record, 156119815Smarcel const SourceManager &SM); 157119815Smarcel 158119815Smarcel /// \brief The version of the diagnostics file. 159119815Smarcel enum { Version = 1 }; 160141032Smarcel 161119815Smarcel const LangOptions *LangOpts; 162119815Smarcel const DiagnosticOptions &DiagOpts; 163119815Smarcel 164119815Smarcel /// \brief The byte buffer for the serialized content. 165119815Smarcel SmallString<1024> Buffer; 166120452Smarcel 167120452Smarcel /// \brief The BitStreamWriter for the serialized diagnostics. 168141032Smarcel llvm::BitstreamWriter Stream; 169120452Smarcel 170120452Smarcel /// \brief The name of the diagnostics file. 171141032Smarcel OwningPtr<llvm::raw_ostream> OS; 172120452Smarcel 173120452Smarcel /// \brief The set of constructed record abbreviations. 174119815Smarcel AbbreviationMap Abbrevs; 175158504Smarcel 176119815Smarcel /// \brief A utility buffer for constructing record content. 177160717Smarcel RecordData Record; 178119815Smarcel 179119815Smarcel /// \brief A text buffer for rendering diagnostic text. 180119815Smarcel SmallString<256> diagBuf; 181119815Smarcel 182119815Smarcel /// \brief The collection of diagnostic categories used. 183119815Smarcel llvm::DenseSet<unsigned> Categories; 184119815Smarcel 185119815Smarcel /// \brief The collection of files used. 186119815Smarcel llvm::DenseMap<const char *, unsigned> Files; 187119815Smarcel 188119815Smarcel typedef llvm::DenseMap<const void *, std::pair<unsigned, llvm::StringRef> > 189119815Smarcel DiagFlagsTy; 190119815Smarcel 191119815Smarcel /// \brief Map for uniquing strings. 192119815Smarcel DiagFlagsTy DiagFlags; 193119815Smarcel 194119815Smarcel /// \brief Flag indicating whether or not we are in the process of 195166100Smarius /// emitting a non-note diagnostic. 196157380Smarcel bool inNonNoteDiagnostic; 197119815Smarcel}; 198168281Smarcel} // end anonymous namespace 199119815Smarcel 200119815Smarcelnamespace clang { 201119815Smarcelnamespace serialized_diags { 202119815SmarcelDiagnosticConsumer *create(llvm::raw_ostream *OS, 203166100Smarius const DiagnosticOptions &diags) { 204119815Smarcel return new SDiagsWriter(OS, diags); 205119815Smarcel} 206119815Smarcel} // end namespace serialized_diags 207119815Smarcel} // end namespace clang 208119815Smarcel 209119815Smarcel//===----------------------------------------------------------------------===// 210119815Smarcel// Serialization methods. 211119815Smarcel//===----------------------------------------------------------------------===// 212119815Smarcel 213119815Smarcel/// \brief Emits a block ID in the BLOCKINFO block. 214119815Smarcelstatic void EmitBlockID(unsigned ID, const char *Name, 215119815Smarcel llvm::BitstreamWriter &Stream, 216119815Smarcel RecordDataImpl &Record) { 217119815Smarcel Record.clear(); 218119815Smarcel Record.push_back(ID); 219119815Smarcel Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); 220119815Smarcel 221119815Smarcel // Emit the block name if present. 222119815Smarcel if (Name == 0 || Name[0] == 0) 223119815Smarcel return; 224119815Smarcel 225119815Smarcel Record.clear(); 226119815Smarcel 227119815Smarcel while (*Name) 228119815Smarcel Record.push_back(*Name++); 229119815Smarcel 230119815Smarcel Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); 231145603Smarcel} 232119815Smarcel 233119815Smarcel/// \brief Emits a record ID in the BLOCKINFO block. 234119815Smarcelstatic void EmitRecordID(unsigned ID, const char *Name, 235119815Smarcel llvm::BitstreamWriter &Stream, 236119815Smarcel RecordDataImpl &Record){ 237119815Smarcel Record.clear(); 238166100Smarius Record.push_back(ID); 239119815Smarcel 240119815Smarcel while (*Name) 241166100Smarius Record.push_back(*Name++); 242119815Smarcel 243119815Smarcel Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); 244119815Smarcel} 245157380Smarcel 246119815Smarcelvoid SDiagsWriter::AddLocToRecord(SourceLocation Loc, 247157380Smarcel const SourceManager *SM, 248119815Smarcel PresumedLoc PLoc, 249157380Smarcel RecordDataImpl &Record, 250157380Smarcel unsigned TokSize) { 251157380Smarcel if (PLoc.isInvalid()) { 252157380Smarcel // Emit a "sentinel" location. 253157380Smarcel Record.push_back((unsigned)0); // File. 254157380Smarcel Record.push_back((unsigned)0); // Line. 255157380Smarcel Record.push_back((unsigned)0); // Column. 256157380Smarcel Record.push_back((unsigned)0); // Offset. 257157380Smarcel return; 258157380Smarcel } 259157380Smarcel 260157380Smarcel Record.push_back(getEmitFile(PLoc.getFilename())); 261157380Smarcel Record.push_back(PLoc.getLine()); 262119815Smarcel Record.push_back(PLoc.getColumn()+TokSize); 263119815Smarcel Record.push_back(SM->getFileOffset(Loc)); 264119815Smarcel} 265119815Smarcel 266119815Smarcelvoid SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range, 267119815Smarcel RecordDataImpl &Record, 268119815Smarcel const SourceManager &SM) { 269119815Smarcel AddLocToRecord(Range.getBegin(), Record, &SM); 270128911Smarcel unsigned TokSize = 0; 271119815Smarcel if (Range.isTokenRange()) 272119815Smarcel TokSize = Lexer::MeasureTokenLength(Range.getEnd(), 273119815Smarcel SM, *LangOpts); 274119815Smarcel 275119815Smarcel AddLocToRecord(Range.getEnd(), Record, &SM, TokSize); 276119815Smarcel} 277119815Smarcel 278119815Smarcelunsigned SDiagsWriter::getEmitFile(const char *FileName){ 279119815Smarcel if (!FileName) 280119815Smarcel return 0; 281119815Smarcel 282119815Smarcel unsigned &entry = Files[FileName]; 283119815Smarcel if (entry) 284262649Simp return entry; 285262649Simp 286119815Smarcel // Lazily generate the record for the file. 287119815Smarcel entry = Files.size(); 288119815Smarcel RecordData Record; 289119815Smarcel Record.push_back(RECORD_FILENAME); 290119815Smarcel Record.push_back(entry); 291119815Smarcel Record.push_back(0); // For legacy. 292119815Smarcel Record.push_back(0); // For legacy. 293119815Smarcel StringRef Name(FileName); 294119815Smarcel Record.push_back(Name.size()); 295119815Smarcel Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FILENAME), Record, Name); 296119815Smarcel 297119815Smarcel return entry; 298119815Smarcel} 299262649Simp 300262649Simpvoid SDiagsWriter::EmitCharSourceRange(CharSourceRange R, 301119815Smarcel const SourceManager &SM) { 302119815Smarcel Record.clear(); 303119815Smarcel Record.push_back(RECORD_SOURCE_RANGE); 304119815Smarcel AddCharSourceRangeToRecord(R, Record, SM); 305168281Smarcel Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_SOURCE_RANGE), Record); 306119815Smarcel} 307119815Smarcel 308168281Smarcel/// \brief Emits the preamble of the diagnostics file. 309119815Smarcelvoid SDiagsWriter::EmitPreamble() { 310119815Smarcel // Emit the file header. 311119815Smarcel Stream.Emit((unsigned)'D', 8); 312119815Smarcel Stream.Emit((unsigned)'I', 8); 313119815Smarcel Stream.Emit((unsigned)'A', 8); 314119815Smarcel Stream.Emit((unsigned)'G', 8); 315119815Smarcel 316119815Smarcel EmitBlockInfoBlock(); 317119815Smarcel EmitMetaBlock(); 318119815Smarcel} 319119815Smarcel 320119815Smarcelstatic void AddSourceLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) { 321119815Smarcel using namespace llvm; 322119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // File ID. 323119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line. 324119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column. 325119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Offset; 326119815Smarcel} 327119815Smarcel 328119815Smarcelstatic void AddRangeLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) { 329119815Smarcel AddSourceLocationAbbrev(Abbrev); 330119815Smarcel AddSourceLocationAbbrev(Abbrev); 331119815Smarcel} 332119815Smarcel 333119815Smarcelvoid SDiagsWriter::EmitBlockInfoBlock() { 334119815Smarcel Stream.EnterBlockInfoBlock(3); 335119815Smarcel 336119815Smarcel using namespace llvm; 337155971Smarcel 338119815Smarcel // ==---------------------------------------------------------------------==// 339119815Smarcel // The subsequent records and Abbrevs are for the "Meta" block. 340119815Smarcel // ==---------------------------------------------------------------------==// 341119815Smarcel 342119815Smarcel EmitBlockID(BLOCK_META, "Meta", Stream, Record); 343141032Smarcel EmitRecordID(RECORD_VERSION, "Version", Stream, Record); 344119815Smarcel BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); 345119815Smarcel Abbrev->Add(BitCodeAbbrevOp(RECORD_VERSION)); 346119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); 347119815Smarcel Abbrevs.set(RECORD_VERSION, Stream.EmitBlockInfoAbbrev(BLOCK_META, Abbrev)); 348119815Smarcel 349141032Smarcel // ==---------------------------------------------------------------------==// 350141032Smarcel // The subsequent records and Abbrevs are for the "Diagnostic" block. 351119815Smarcel // ==---------------------------------------------------------------------==// 352119815Smarcel 353119815Smarcel EmitBlockID(BLOCK_DIAG, "Diag", Stream, Record); 354119815Smarcel EmitRecordID(RECORD_DIAG, "DiagInfo", Stream, Record); 355119815Smarcel EmitRecordID(RECORD_SOURCE_RANGE, "SrcRange", Stream, Record); 356119815Smarcel EmitRecordID(RECORD_CATEGORY, "CatName", Stream, Record); 357119815Smarcel EmitRecordID(RECORD_DIAG_FLAG, "DiagFlag", Stream, Record); 358119815Smarcel EmitRecordID(RECORD_FILENAME, "FileName", Stream, Record); 359119815Smarcel EmitRecordID(RECORD_FIXIT, "FixIt", Stream, Record); 360119815Smarcel 361119815Smarcel // Emit abbreviation for RECORD_DIAG. 362119815Smarcel Abbrev = new BitCodeAbbrev(); 363119815Smarcel Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG)); 364119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Diag level. 365119815Smarcel AddSourceLocationAbbrev(Abbrev); 366119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category. 367119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID. 368119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 369119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text. 370119815Smarcel Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 371119815Smarcel 372119815Smarcel // Emit abbrevation for RECORD_CATEGORY. 373119815Smarcel Abbrev = new BitCodeAbbrev(); 374119815Smarcel Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY)); 375119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Category ID. 376119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); // Text size. 377157300Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Category text. 378120143Smarcel Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 379157300Smarcel 380131043Sphk // Emit abbrevation for RECORD_SOURCE_RANGE. 381131043Sphk Abbrev = new BitCodeAbbrev(); 382141032Smarcel Abbrev->Add(BitCodeAbbrevOp(RECORD_SOURCE_RANGE)); 383155973Smarcel AddRangeLocationAbbrev(Abbrev); 384119815Smarcel Abbrevs.set(RECORD_SOURCE_RANGE, 385119815Smarcel Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 386119815Smarcel 387119815Smarcel // Emit the abbreviation for RECORD_DIAG_FLAG. 388119815Smarcel Abbrev = new BitCodeAbbrev(); 389119815Smarcel Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG)); 390119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID. 391119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 392119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text. 393160716Smarcel Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, 394119815Smarcel Abbrev)); 395119815Smarcel 396120143Smarcel // Emit the abbreviation for RECORD_FILENAME. 397157300Smarcel Abbrev = new BitCodeAbbrev(); 398119815Smarcel Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME)); 399119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped file ID. 400119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Size. 401119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modifcation time. 402119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 403119815Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text. 404119815Smarcel Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, 405119815Smarcel Abbrev)); 406119815Smarcel 407160716Smarcel // Emit the abbreviation for RECORD_FIXIT. 408160716Smarcel Abbrev = new BitCodeAbbrev(); 409160716Smarcel Abbrev->Add(BitCodeAbbrevOp(RECORD_FIXIT)); 410160716Smarcel AddRangeLocationAbbrev(Abbrev); 411160716Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 412160716Smarcel Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // FixIt text. 413119815Smarcel Abbrevs.set(RECORD_FIXIT, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, 414120143Smarcel Abbrev)); 415120143Smarcel 416119815Smarcel Stream.ExitBlock(); 417157300Smarcel} 418120143Smarcel 419119815Smarcelvoid SDiagsWriter::EmitMetaBlock() { 420119815Smarcel Stream.EnterSubblock(BLOCK_META, 3); 421119815Smarcel Record.clear(); 422119815Smarcel Record.push_back(RECORD_VERSION); 423119815Smarcel Record.push_back(Version); 424128911Smarcel Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record); 425119815Smarcel Stream.ExitBlock(); 426119815Smarcel} 427119815Smarcel 428141032Smarcelunsigned SDiagsWriter::getEmitCategory(unsigned int category) { 429119815Smarcel if (Categories.count(category)) 430119815Smarcel return category; 431119815Smarcel 432141032Smarcel Categories.insert(category); 433157300Smarcel 434141032Smarcel // We use a local version of 'Record' so that we can be generating 435141032Smarcel // another record when we lazily generate one for the category entry. 436141032Smarcel RecordData Record; 437141032Smarcel Record.push_back(RECORD_CATEGORY); 438141032Smarcel Record.push_back(category); 439141032Smarcel StringRef catName = DiagnosticIDs::getCategoryNameFromID(category); 440141032Smarcel Record.push_back(catName.size()); 441141032Smarcel Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_CATEGORY), Record, catName); 442141032Smarcel 443141032Smarcel return category; 444141032Smarcel} 445141032Smarcel 446141032Smarcelunsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel, 447141032Smarcel unsigned DiagID) { 448141032Smarcel if (DiagLevel == DiagnosticsEngine::Note) 449141032Smarcel return 0; // No flag for notes. 450119815Smarcel 451141032Smarcel StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(DiagID); 452141032Smarcel if (FlagName.empty()) 453155971Smarcel return 0; 454141032Smarcel 455141032Smarcel // Here we assume that FlagName points to static data whose pointer 456119815Smarcel // value is fixed. This allows us to unique by diagnostic groups. 457141032Smarcel const void *data = FlagName.data(); 458141032Smarcel std::pair<unsigned, StringRef> &entry = DiagFlags[data]; 459155971Smarcel if (entry.first == 0) { 460155971Smarcel entry.first = DiagFlags.size(); 461141032Smarcel entry.second = FlagName; 462119815Smarcel 463141032Smarcel // Lazily emit the string in a separate record. 464141032Smarcel RecordData Record; 465141032Smarcel Record.push_back(RECORD_DIAG_FLAG); 466141032Smarcel Record.push_back(entry.first); 467141032Smarcel Record.push_back(FlagName.size()); 468141032Smarcel Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG_FLAG), 469155971Smarcel Record, FlagName); 470141032Smarcel } 471141032Smarcel 472141032Smarcel return entry.first; 473141032Smarcel} 474155973Smarcel 475155971Smarcelvoid SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 476141032Smarcel const Diagnostic &Info) { 477141032Smarcel if (DiagLevel != DiagnosticsEngine::Note) { 478141032Smarcel if (inNonNoteDiagnostic) { 479141032Smarcel // We have encountered a non-note diagnostic. Finish up the previous 480155971Smarcel // diagnostic block before starting a new one. 481141032Smarcel Stream.ExitBlock(); 482119815Smarcel } 483141032Smarcel inNonNoteDiagnostic = true; 484141032Smarcel } 485141032Smarcel 486141032Smarcel // Compute the diagnostic text. 487141032Smarcel diagBuf.clear(); 488141032Smarcel Info.FormatDiagnostic(diagBuf); 489157300Smarcel 490141032Smarcel const SourceManager * 491119815Smarcel SM = Info.hasSourceManager() ? &Info.getSourceManager() : 0; 492119815Smarcel SDiagsRenderer Renderer(*this, Record, *LangOpts, DiagOpts); 493119815Smarcel Renderer.emitDiagnostic(Info.getLocation(), DiagLevel, 494119815Smarcel diagBuf.str(), 495119815Smarcel Info.getRanges(), 496119815Smarcel llvm::makeArrayRef(Info.getFixItHints(), 497119815Smarcel Info.getNumFixItHints()), 498119815Smarcel SM, 499119815Smarcel &Info); 500119815Smarcel} 501157300Smarcel 502119815Smarcelvoid 503119815SmarcelSDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc, 504157300Smarcel PresumedLoc PLoc, 505119815Smarcel DiagnosticsEngine::Level Level, 506119815Smarcel StringRef Message, 507119815Smarcel ArrayRef<clang::CharSourceRange> Ranges, 508119815Smarcel const SourceManager *SM, 509119815Smarcel DiagOrStoredDiag D) { 510119815Smarcel // Emit the RECORD_DIAG record. 511119815Smarcel Writer.Record.clear(); 512119815Smarcel Writer.Record.push_back(RECORD_DIAG); 513120452Smarcel Writer.Record.push_back(Level); 514119815Smarcel Writer.AddLocToRecord(Loc, SM, PLoc, Record); 515119815Smarcel 516119815Smarcel if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) { 517119815Smarcel // Emit the category string lazily and get the category ID. 518119815Smarcel unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID()); 519248965Sian Writer.Record.push_back(Writer.getEmitCategory(DiagID)); 520248965Sian // Emit the diagnostic flag string lazily and get the mapped ID. 521248965Sian Writer.Record.push_back(Writer.getEmitDiagnosticFlag(Level, Info->getID())); 522120452Smarcel } 523119815Smarcel else { 524120452Smarcel Writer.Record.push_back(Writer.getEmitCategory()); 525119815Smarcel Writer.Record.push_back(Writer.getEmitDiagnosticFlag(Level)); 526119815Smarcel } 527119815Smarcel 528119815Smarcel Writer.Record.push_back(Message.size()); 529119815Smarcel Writer.Stream.EmitRecordWithBlob(Writer.Abbrevs.get(RECORD_DIAG), 530119815Smarcel Writer.Record, Message); 531119815Smarcel} 532119815Smarcel 533119815Smarcelvoid SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D, 534119815Smarcel DiagnosticsEngine::Level Level) { 535119815Smarcel Writer.Stream.EnterSubblock(BLOCK_DIAG, 4); 536119815Smarcel} 537157300Smarcel 538119815Smarcelvoid SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D, 539120146Smarcel DiagnosticsEngine::Level Level) { 540120146Smarcel if (D && Level != DiagnosticsEngine::Note) 541120146Smarcel return; 542120146Smarcel Writer.Stream.ExitBlock(); 543120146Smarcel} 544141032Smarcel 545141032Smarcelvoid SDiagsRenderer::emitCodeContext(SourceLocation Loc, 546119815Smarcel DiagnosticsEngine::Level Level, 547119815Smarcel SmallVectorImpl<CharSourceRange> &Ranges, 548119815Smarcel ArrayRef<FixItHint> Hints, 549119815Smarcel const SourceManager &SM) { 550119815Smarcel // Emit Source Ranges. 551141032Smarcel for (ArrayRef<CharSourceRange>::iterator it=Ranges.begin(), ei=Ranges.end(); 552141032Smarcel it != ei; ++it) { 553119815Smarcel if (it->isValid()) 554141032Smarcel Writer.EmitCharSourceRange(*it, SM); 555119815Smarcel } 556120146Smarcel 557120146Smarcel // Emit FixIts. 558119815Smarcel for (ArrayRef<FixItHint>::iterator it = Hints.begin(), et = Hints.end(); 559119815Smarcel it != et; ++it) { 560120146Smarcel const FixItHint &fix = *it; 561120146Smarcel if (fix.isNull()) 562141032Smarcel continue; 563141032Smarcel Writer.Record.clear(); 564120146Smarcel Writer.Record.push_back(RECORD_FIXIT); 565141032Smarcel Writer.AddCharSourceRangeToRecord(fix.RemoveRange, Record, SM); 566120146Smarcel Writer.Record.push_back(fix.CodeToInsert.size()); 567120146Smarcel Writer.Stream.EmitRecordWithBlob(Writer.Abbrevs.get(RECORD_FIXIT), Record, 568120146Smarcel fix.CodeToInsert); 569120146Smarcel } 570120146Smarcel} 571157300Smarcel 572119815Smarcelvoid SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message, 573119815Smarcel const SourceManager *SM) { 574119815Smarcel Writer.Stream.EnterSubblock(BLOCK_DIAG, 4); 575119815Smarcel RecordData Record; 576119815Smarcel Record.push_back(RECORD_DIAG); 577119815Smarcel Record.push_back(DiagnosticsEngine::Note); 578119815Smarcel Writer.AddLocToRecord(Loc, Record, SM); 579119815Smarcel Record.push_back(Writer.getEmitCategory()); 580119815Smarcel Record.push_back(Writer.getEmitDiagnosticFlag(DiagnosticsEngine::Note)); 581119815Smarcel Record.push_back(Message.size()); 582119815Smarcel Writer.Stream.EmitRecordWithBlob(Writer.Abbrevs.get(RECORD_DIAG), 583119815Smarcel Record, Message); 584119815Smarcel Writer.Stream.ExitBlock(); 585119815Smarcel} 586131043Sphk 587131043Sphkvoid SDiagsWriter::finish() { 588131043Sphk if (inNonNoteDiagnostic) { 589119815Smarcel // Finish off any diagnostics we were in the process of emitting. 590131043Sphk Stream.ExitBlock(); 591131043Sphk inNonNoteDiagnostic = false; 592131043Sphk } 593119815Smarcel 594119815Smarcel // Write the generated bitstream to "Out". 595119815Smarcel OS->write((char *)&Buffer.front(), Buffer.size()); 596157300Smarcel OS->flush(); 597131043Sphk 598119815Smarcel OS.reset(0); 599119815Smarcel} 600119815Smarcel 601131043Sphk