Index: lib/DebugInfo/CMakeLists.txt =================================================================== --- lib/DebugInfo/CMakeLists.txt +++ lib/DebugInfo/CMakeLists.txt @@ -15,4 +15,5 @@ DWARFFormValue.cpp DWARFTypeUnit.cpp DWARFUnit.cpp + SyntaxHighlighting.cpp ) Index: lib/DebugInfo/DWARFDebugInfoEntry.cpp =================================================================== --- lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ 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 @@ 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 @@ OS.indent(indent+2); const char *attrString = AttributeString(attr); if (attrString) - OS << attrString; + WithColor(OS, syntax::Attribute).get() << 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 << ']'; @@ -145,7 +150,10 @@ Name = AttributeValueString(attr, *Val); if (Name) { - OS << Name; + if (attr == DW_AT_decl_file || attr == DW_AT_call_file) + WithColor(OS, syntax::String).get() << Name; + else + WithColor(OS, syntax::Enumerator).get() << Name; } else if (attr == DW_AT_decl_line || attr == DW_AT_call_line) { OS << *formValue.getAsUnsignedConstant(); } else { Index: lib/DebugInfo/DWARFFormValue.cpp =================================================================== --- lib/DebugInfo/DWARFFormValue.cpp +++ 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 @@ OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); Optional DbgStr = getAsCString(cu); if (DbgStr.hasValue()) { - OS << '"'; - OS.write_escaped(DbgStr.getValue()); - OS << '"'; + auto &COS = WithColor(OS, syntax::String).get(); + COS << '"'; + COS.write_escaped(DbgStr.getValue()); + COS << '"'; } break; } @@ -433,9 +436,10 @@ OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); Optional DbgStr = getAsCString(cu); if (DbgStr.hasValue()) { - OS << '"'; - OS.write_escaped(DbgStr.getValue()); - OS << '"'; + auto &COS = WithColor(OS, syntax::String).get(); + COS << '"'; + COS.write_escaped(DbgStr.getValue()); + COS << '"'; } break; } @@ -479,8 +483,14 @@ 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 { Index: lib/DebugInfo/SyntaxHighlighting.h =================================================================== --- /dev/null +++ lib/DebugInfo/SyntaxHighlighting.h @@ -0,0 +1,38 @@ +//===-- 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: + WithColor(llvm::raw_ostream &OS, enum HighlightColor Type); + ~WithColor(); + + llvm::raw_ostream& get() { return OS; } + operator llvm::raw_ostream& () { return OS; } +}; +} +} +} + +#endif Index: lib/DebugInfo/SyntaxHighlighting.cpp =================================================================== --- /dev/null +++ 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(); +}