<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jan 6, 2015 at 9:11 AM, Adrian Prantl <span dir="ltr"><<a href="mailto:aprantl@apple.com" target="_blank">aprantl@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><div><div class="h5"><blockquote type="cite"><div>On Jan 6, 2015, at 9:05 AM, David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>> wrote:</div><br><div><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jan 6, 2015 at 8:50 AM, Adrian Prantl <span dir="ltr"><<a href="mailto:aprantl@apple.com" target="_blank">aprantl@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: adrian<br>
Date: Tue Jan  6 10:50:25 2015<br>
New Revision: 225269<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=225269&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=225269&view=rev</a><br>
Log:<br>
Implement a very basic colored syntax highlighting for llvm-dwarfdump.<br>
The color scheme is the same as the one used by the colorize dwarfdump<br>
script on Darwin.<br>
A new --color option can be used to forcibly turn color on or off.<br>
<br>
<a href="http://reviews.llvm.org/D6852" target="_blank">http://reviews.llvm.org/D6852</a><br>
<br>
Added:<br>
    llvm/trunk/lib/DebugInfo/SyntaxHighlighting.cpp<br>
    llvm/trunk/lib/DebugInfo/SyntaxHighlighting.h<br>
Modified:<br>
    llvm/trunk/lib/DebugInfo/CMakeLists.txt<br>
    llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.cpp<br>
    llvm/trunk/lib/DebugInfo/DWARFFormValue.cpp<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CMakeLists.txt?rev=225269&r1=225268&r2=225269&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CMakeLists.txt?rev=225269&r1=225268&r2=225269&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/DebugInfo/CMakeLists.txt Tue Jan  6 10:50:25 2015<br>
@@ -15,4 +15,5 @@ add_llvm_library(LLVMDebugInfo<br>
   DWARFFormValue.cpp<br>
   DWARFTypeUnit.cpp<br>
   DWARFUnit.cpp<br>
+  SyntaxHighlighting.cpp<br>
   )<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.cpp?rev=225269&r1=225268&r2=225269&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.cpp?rev=225269&r1=225268&r2=225269&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/DWARFDebugInfoEntry.cpp Tue Jan  6 10:50:25 2015<br>
@@ -7,6 +7,7 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
<br>
+#include "SyntaxHighlighting.h"<br>
 #include "llvm/DebugInfo/DWARFDebugInfoEntry.h"<br>
 #include "llvm/DebugInfo/DWARFCompileUnit.h"<br>
 #include "llvm/DebugInfo/DWARFContext.h"<br>
@@ -19,6 +20,7 @@<br>
 #include "llvm/Support/raw_ostream.h"<br>
 using namespace llvm;<br>
 using namespace dwarf;<br>
+using namespace syntax;<br>
<br>
 // Small helper to extract a DIE pointed by a reference<br>
 // attribute. It looks up the Unit containing the DIE and calls<br>
@@ -39,15 +41,17 @@ void DWARFDebugInfoEntryMinimal::dump(ra<br>
<br>
   if (debug_info_data.isValidOffset(offset)) {<br>
     uint32_t abbrCode = debug_info_data.getULEB128(&offset);<br>
+    WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset);<br>
<br>
-    OS << format("\n0x%8.8x: ", Offset);<br>
     if (abbrCode) {<br>
       if (AbbrevDecl) {<br>
-        const char *tagString = TagString(getTag());<br>
-        if (tagString)<br>
-          OS.indent(indent) << tagString;<br>
-        else<br>
-          OS.indent(indent) << format("DW_TAG_Unknown_%x", getTag());<br>
+          const char *tagString = TagString(getTag());<br>
+          if (tagString)<br>
+            WithColor(OS, syntax::Tag).get().indent(indent) << tagString;<br>
+          else<br>
+            WithColor(OS, syntax::Tag).get().indent(indent) <<<br>
+              format("DW_TAG_Unknown_%x", getTag());<br></blockquote><div><br>Perhaps we could/should introduce a non-member form of indent something like:<br><br>stream << indent(2) << ...<br></div></div></div></div></div></blockquote><div><br></div></div></div><div>I think that would be nice. Thinking of it, it might be even better to have something like</div><div><br></div><div>OS << indent(2) << color(syntax::Attribute) << text << color_reset;</div><div><br></div><div>where color and color_reset are the identity if color support is not enabled.</div></div></div></blockquote><div><br>I rather like the scoped solution that ensures we don't have to remember to 'reset' all the time - though that could still be done with the syntax you're suggesting. It'd be a bit tricky.<br><br>color(syntax::Attribute) would be (or return) an object that, when passed to the relevant op<<, would apply the color and store a reference to the stream in a mutable member. In color's dtor, it would then undo the color application.<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><span class=""><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br>?<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
         OS << format(" [%u] %c\n", abbrCode,<br>
                      AbbrevDecl->hasChildren() ? '*' : ' ');<br>
<br>
@@ -114,9 +118,10 @@ void DWARFDebugInfoEntryMinimal::dumpAtt<br>
   OS.indent(indent+2);<br>
   const char *attrString = AttributeString(attr);<br>
   if (attrString)<br>
-    OS << attrString;<br>
+    WithColor(OS, syntax::Attribute) << attrString;<br>
   else<br>
-    OS << format("DW_AT_Unknown_%x", attr);<br>
+    WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", attr);<br></blockquote><div><br>Why do some calls have get, and some not?<br></div></div></div></div></div></blockquote><div><br></div></span><div>The C++ type system cannot infer that we want the llvm::ostream &operator() if the format template is involved. </div></div></div></blockquote><div><br>Ah. I believe this is the problem I alluded to in the review. The way the format() is implemented is that it returns a format_object<...> (a subclass of format_object_base) and raw_ostream has an op<< overload for const format_object_base&. The problem is that this op<< is implemented as a member function which means you don't get the free implicit conversions on the LHS of the << usage. If this (and related) op<< are moved out to be non-members, I believe this should work.<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div>Maybe having both forms is even worse compared to having calls to get() everywhere?</div><span class="HOEnZb"><font color="#888888"><div><br></div><div>-- adrian</div></font></span></div><div><div class="h5"><div><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
   const char *formString = FormEncodingString(form);<br>
   if (formString)<br>
     OS << " [" << formString << ']';<br>
@@ -132,7 +137,9 @@ void DWARFDebugInfoEntryMinimal::dumpAtt<br>
<br>
   const char *Name = nullptr;<br>
   std::string File;<br>
+  auto Color = syntax::Enumerator;<br>
   if (attr == DW_AT_decl_file || attr == DW_AT_call_file) {<br>
+  Color = syntax::String;<br>
     if (const auto *LT = u->getContext().getLineTableForUnit(u))<br>
       if (LT->getFileNameByIndex(<br>
              formValue.getAsUnsignedConstant().getValue(),<br>
@@ -144,13 +151,12 @@ void DWARFDebugInfoEntryMinimal::dumpAtt<br>
   } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())<br>
     Name = AttributeValueString(attr, *Val);<br>
<br>
-  if (Name) {<br>
-    OS << Name;<br>
-  } else if (attr == DW_AT_decl_line || attr == DW_AT_call_line) {<br>
+  if (Name)<br>
+    WithColor(OS, Color) << Name;<br>
+  else if (attr == DW_AT_decl_line || attr == DW_AT_call_line)<br>
     OS << *formValue.getAsUnsignedConstant();<br>
-  } else {<br>
+  else<br>
     formValue.dump(OS, u);<br>
-  }<br>
<br>
   // We have dumped the attribute raw value. For some attributes<br>
   // having both the raw value and the pretty-printed value is<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/DWARFFormValue.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFFormValue.cpp?rev=225269&r1=225268&r2=225269&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARFFormValue.cpp?rev=225269&r1=225268&r2=225269&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/DWARFFormValue.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/DWARFFormValue.cpp Tue Jan  6 10:50:25 2015<br>
@@ -7,6 +7,7 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
<br>
+#include "SyntaxHighlighting.h"<br>
 #include "llvm/DebugInfo/DWARFFormValue.h"<br>
 #include "llvm/ADT/ArrayRef.h"<br>
 #include "llvm/ADT/StringRef.h"<br>
@@ -19,6 +20,7 @@<br>
 #include <cassert><br>
 using namespace llvm;<br>
 using namespace dwarf;<br>
+using namespace syntax;<br>
<br>
 namespace {<br>
 uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {<br>
@@ -423,9 +425,10 @@ DWARFFormValue::dump(raw_ostream &OS, co<br>
     OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);<br>
     Optional<const char *> DbgStr = getAsCString(cu);<br>
     if (DbgStr.hasValue()) {<br>
-      OS << '"';<br>
-      OS.write_escaped(DbgStr.getValue());<br>
-      OS << '"';<br>
+      raw_ostream &COS = WithColor(OS, syntax::String);<br>
+      COS << '"';<br>
+      COS.write_escaped(DbgStr.getValue());<br>
+      COS << '"';<br>
     }<br>
     break;<br>
   }<br>
@@ -433,9 +436,10 @@ DWARFFormValue::dump(raw_ostream &OS, co<br>
     OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);<br>
     Optional<const char *> DbgStr = getAsCString(cu);<br>
     if (DbgStr.hasValue()) {<br>
-      OS << '"';<br>
-      OS.write_escaped(DbgStr.getValue());<br>
-      OS << '"';<br>
+      raw_ostream &COS = WithColor(OS, syntax::String);<br>
+      COS << '"';<br>
+      COS.write_escaped(DbgStr.getValue());<br>
+      COS << '"';<br>
     }<br>
     break;<br>
   }<br>
@@ -479,8 +483,12 @@ DWARFFormValue::dump(raw_ostream &OS, co<br>
     break;<br>
   }<br>
<br>
-  if (cu_relative_offset)<br>
-    OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0));<br>
+  if (cu_relative_offset) {<br>
+    OS << " => {";<br>
+    WithColor(OS, syntax::Address).get()<br>
+      << format("0x%8.8" PRIx64, uvalue + (cu ? cu->getOffset() : 0));<br>
+    OS << "}";<br>
+  }<br>
 }<br>
<br>
 Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const {<br>
<br>
Added: llvm/trunk/lib/DebugInfo/SyntaxHighlighting.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/SyntaxHighlighting.cpp?rev=225269&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/SyntaxHighlighting.cpp?rev=225269&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/SyntaxHighlighting.cpp (added)<br>
+++ llvm/trunk/lib/DebugInfo/SyntaxHighlighting.cpp Tue Jan  6 10:50:25 2015<br>
@@ -0,0 +1,37 @@<br>
+//===-- SyntaxHighlighting.cpp ----------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "SyntaxHighlighting.h"<br>
+#include "llvm/Support/CommandLine.h"<br>
+using namespace llvm;<br>
+using namespace dwarf;<br>
+using namespace syntax;<br>
+<br>
+static cl::opt<cl::boolOrDefault><br>
+    UseColor("color",<br>
+             cl::desc("use colored syntax highlighting (default=autodetect)"),<br>
+             cl::init(cl::BOU_UNSET));<br>
+<br>
+WithColor::WithColor(llvm::raw_ostream &OS, enum HighlightColor Type) : OS(OS) {<br>
+  // Detect color from terminal type unless the user passed the --color option.<br>
+  if (UseColor == cl::BOU_UNSET ? OS.has_colors() : UseColor == cl::BOU_TRUE) {<br>
+    switch (Type) {<br>
+    case Address:    OS.changeColor(llvm::raw_ostream::YELLOW);  break;<br>
+    case String:     OS.changeColor(llvm::raw_ostream::GREEN);   break;<br>
+    case Tag:        OS.changeColor(llvm::raw_ostream::BLUE);    break;<br>
+    case Attribute:  OS.changeColor(llvm::raw_ostream::CYAN);    break;<br>
+    case Enumerator: OS.changeColor(llvm::raw_ostream::MAGENTA); break;<br>
+    }<br>
+  }<br>
+}<br>
+<br>
+WithColor::~WithColor() {<br>
+  if (UseColor == cl::BOU_UNSET ? OS.has_colors() : UseColor == cl::BOU_TRUE)<br>
+    OS.resetColor();<br>
+}<br>
<br>
Added: llvm/trunk/lib/DebugInfo/SyntaxHighlighting.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/SyntaxHighlighting.h?rev=225269&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/SyntaxHighlighting.h?rev=225269&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/SyntaxHighlighting.h (added)<br>
+++ llvm/trunk/lib/DebugInfo/SyntaxHighlighting.h Tue Jan  6 10:50:25 2015<br>
@@ -0,0 +1,39 @@<br>
+//===-- SyntaxHighlighting.h ------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_LIB_DEBUGINFO_SYNTAXHIGHLIGHTING_H<br>
+#define LLVM_LIB_DEBUGINFO_SYNTAXHIGHLIGHTING_H<br>
+<br>
+#include "llvm/Support/raw_ostream.h"<br>
+<br>
+namespace llvm {<br>
+namespace dwarf {<br>
+namespace syntax {<br>
+<br>
+// Symbolic names for various syntax elements.<br>
+enum HighlightColor { Address, String, Tag, Attribute, Enumerator };<br>
+<br>
+/// An RAII object that temporarily switches an output stream to a<br>
+/// specific color.<br>
+class WithColor {<br>
+  llvm::raw_ostream &OS;<br>
+<br>
+public:<br>
+  /// To be used like this: WithColor(OS, syntax::String) << "text";<br>
+  WithColor(llvm::raw_ostream &OS, enum HighlightColor Type);<br>
+  ~WithColor();<br>
+<br>
+  llvm::raw_ostream& get() { return OS; }<br>
+  operator llvm::raw_ostream& () { return OS; }<br>
+};<br>
+}<br>
+}<br>
+}<br>
+<br>
+#endif<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>
</div></blockquote></div><br></div></div></div></blockquote></div><br></div></div>