diff --git a/lib/DebugInfo/CMakeLists.txt b/lib/DebugInfo/CMakeLists.txt index 81fc84d4a80..4cce35b5ca1 100644 --- a/lib/DebugInfo/CMakeLists.txt +++ b/lib/DebugInfo/CMakeLists.txt @@ -15,4 +15,5 @@ add_llvm_library(LLVMDebugInfo DWARFFormValue.cpp DWARFTypeUnit.cpp DWARFUnit.cpp + SyntaxHighlighting.cpp ) diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp index 22c27c72dab..a91262f5d3e 100644 --- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ b/lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "SyntaxHighlighting.h" #include "llvm/DebugInfo/DWARFDebugInfoEntry.h" #include "llvm/DebugInfo/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARFContext.h" @@ -19,6 +20,7 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace dwarf; +using namespace syntax; // Small helper to extract a DIE pointed by a reference // attribute. It looks up the Unit containing the DIE and calls @@ -39,15 +41,17 @@ void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, DWARFUnit *u, if (debug_info_data.isValidOffset(offset)) { uint32_t abbrCode = debug_info_data.getULEB128(&offset); + WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset); - OS << format("\n0x%8.8x: ", Offset); if (abbrCode) { if (AbbrevDecl) { - const char *tagString = TagString(getTag()); - if (tagString) - OS.indent(indent) << tagString; - else - OS.indent(indent) << format("DW_TAG_Unknown_%x", getTag()); + const char *tagString = TagString(getTag()); + if (tagString) + WithColor(OS, syntax::Tag).get().indent(indent) << tagString; + else + WithColor(OS, syntax::Tag).get().indent(indent) << + format("DW_TAG_Unknown_%x", getTag()); + OS << format(" [%u] %c\n", abbrCode, AbbrevDecl->hasChildren() ? '*' : ' '); @@ -114,9 +118,10 @@ void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS, OS.indent(indent+2); const char *attrString = AttributeString(attr); if (attrString) - OS << attrString; + WithColor(OS, syntax::Attribute) << attrString; else - OS << format("DW_AT_Unknown_%x", attr); + WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", attr); + const char *formString = FormEncodingString(form); if (formString) OS << " [" << formString << ']'; @@ -132,7 +137,9 @@ void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS, const char *Name = nullptr; std::string File; + auto Color = syntax::Enumerator; if (attr == DW_AT_decl_file || attr == DW_AT_call_file) { + Color = syntax::String; if (const auto *LT = u->getContext().getLineTableForUnit(u)) if (LT->getFileNameByIndex( formValue.getAsUnsignedConstant().getValue(), @@ -144,13 +151,12 @@ void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS, } else if (Optional Val = formValue.getAsUnsignedConstant()) Name = AttributeValueString(attr, *Val); - if (Name) { - OS << Name; - } else if (attr == DW_AT_decl_line || attr == DW_AT_call_line) { + if (Name) + WithColor(OS, Color) << Name; + else if (attr == DW_AT_decl_line || attr == DW_AT_call_line) OS << *formValue.getAsUnsignedConstant(); - } else { + else formValue.dump(OS, u); - } // We have dumped the attribute raw value. For some attributes // having both the raw value and the pretty-printed value is diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp index 0ff8f2c58cb..31b1ce7237d 100644 --- a/lib/DebugInfo/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARFFormValue.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "SyntaxHighlighting.h" #include "llvm/DebugInfo/DWARFFormValue.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" @@ -19,6 +20,7 @@ #include using namespace llvm; using namespace dwarf; +using namespace syntax; namespace { uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) { @@ -423,9 +425,10 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); Optional DbgStr = getAsCString(cu); if (DbgStr.hasValue()) { - OS << '"'; - OS.write_escaped(DbgStr.getValue()); - OS << '"'; + raw_ostream &COS = WithColor(OS, syntax::String); + COS << '"'; + COS.write_escaped(DbgStr.getValue()); + COS << '"'; } break; } @@ -433,9 +436,10 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); Optional DbgStr = getAsCString(cu); if (DbgStr.hasValue()) { - OS << '"'; - OS.write_escaped(DbgStr.getValue()); - OS << '"'; + raw_ostream &COS = WithColor(OS, syntax::String); + COS << '"'; + COS.write_escaped(DbgStr.getValue()); + COS << '"'; } break; } @@ -479,8 +483,12 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { break; } - if (cu_relative_offset) - OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0)); + if (cu_relative_offset) { + OS << " => {"; + WithColor(OS, syntax::Address).get() + << format("0x%8.8" PRIx64, uvalue + (cu ? cu->getOffset() : 0)); + OS << "}"; + } } Optional DWARFFormValue::getAsCString(const DWARFUnit *U) const { diff --git a/lib/DebugInfo/SyntaxHighlighting.cpp b/lib/DebugInfo/SyntaxHighlighting.cpp new file mode 100644 index 00000000000..a6b4c6549ca --- /dev/null +++ b/lib/DebugInfo/SyntaxHighlighting.cpp @@ -0,0 +1,37 @@ +//===-- SyntaxHighlighting.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SyntaxHighlighting.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; +using namespace dwarf; +using namespace syntax; + +static cl::opt + UseColor("color", + cl::desc("use colored syntax highlighting (default=autodetect)"), + cl::init(cl::BOU_UNSET)); + +WithColor::WithColor(llvm::raw_ostream &OS, enum HighlightColor Type) : OS(OS) { + // Detect color from terminal type unless the user passed the --color option. + if (UseColor == cl::BOU_UNSET ? OS.has_colors() : UseColor == cl::BOU_TRUE) { + switch (Type) { + case Address: OS.changeColor(llvm::raw_ostream::YELLOW); break; + case String: OS.changeColor(llvm::raw_ostream::GREEN); break; + case Tag: OS.changeColor(llvm::raw_ostream::BLUE); break; + case Attribute: OS.changeColor(llvm::raw_ostream::CYAN); break; + case Enumerator: OS.changeColor(llvm::raw_ostream::MAGENTA); break; + } + } +} + +WithColor::~WithColor() { + if (UseColor == cl::BOU_UNSET ? OS.has_colors() : UseColor == cl::BOU_TRUE) + OS.resetColor(); +} diff --git a/lib/DebugInfo/SyntaxHighlighting.h b/lib/DebugInfo/SyntaxHighlighting.h new file mode 100644 index 00000000000..946a31308aa --- /dev/null +++ b/lib/DebugInfo/SyntaxHighlighting.h @@ -0,0 +1,39 @@ +//===-- SyntaxHighlighting.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_SYNTAXHIGHLIGHTING_H +#define LLVM_LIB_DEBUGINFO_SYNTAXHIGHLIGHTING_H + +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +namespace dwarf { +namespace syntax { + +// Symbolic names for various syntax elements. +enum HighlightColor { Address, String, Tag, Attribute, Enumerator }; + +/// An RAII object that temporarily switches an output stream to a +/// specific color. +class WithColor { + llvm::raw_ostream &OS; + +public: + /// To be used like this: WithColor(OS, syntax::String) << "text"; + WithColor(llvm::raw_ostream &OS, enum HighlightColor Type); + ~WithColor(); + + llvm::raw_ostream& get() { return OS; } + operator llvm::raw_ostream& () { return OS; } +}; +} +} +} + +#endif