Index: llvm/tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- llvm/tools/llvm-objdump/llvm-objdump.cpp +++ llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -332,6 +332,10 @@ cl::cat(ObjdumpCat)); static cl::alias WideShort("w", cl::Grouping, cl::aliasopt(Wide)); +static cl::opt Highlight("highlight", + cl::desc("Enable syntax highlighting"), + cl::cat(ObjdumpCat)); + static cl::extrahelp HelpResponse("\nPass @FILE as argument to read options from FILE.\n"); @@ -1072,6 +1076,68 @@ } } +// Parses given rich disassembly output (see https://llvm.org/docs/MarkedUpDisassembly.html) +// and prints colored output. +static void printMarkedUpInst(StringRef Text) { + if (!Highlight) { + outs() << Text; + return; + } + + size_t Pos = 0; + while (Pos < Text.size()) { + size_t OpenBracket, Colon; + if ((OpenBracket = Text.find('<', Pos)) == StringRef::npos) + break; + if ((Colon = Text.find(':', OpenBracket)) == StringRef::npos) + break; + + // Look for the corresponding closing bracket. + size_t NestedLevel = 1; + size_t CloseBracket = Colon + 1; + while (CloseBracket < Text.size()) { + if (Text[CloseBracket] == '<') + NestedLevel++; + if (Text[CloseBracket] == '>') { + NestedLevel--; + if (NestedLevel == 0) + break; + } + + CloseBracket++; + } + + if (CloseBracket == Text.size()) + break; + + // It looks a valid rich dissassembly format. Parse it as follows: + // + // leaq )>, + // ^----- ^-- ^-------------- + // BeforeText Tag InnerText + // + StringRef BeforeText = Text.substr(Pos, OpenBracket - Pos); + StringRef Tag = Text.substr(OpenBracket + 1, Colon - OpenBracket - 1); + StringRef InnerText = Text.substr(Colon + 1, CloseBracket - Colon - 1); + + outs() << BeforeText; + + // WIP: Hghlight only register names for now. + // TODO: tag may contain multiple values (e.g. ""). + if (Tag == "reg") + outs().changeColor(raw_ostream::RED); + + // Print innter text recursively. + printMarkedUpInst(InnerText); + + outs().resetColor(); + Pos = CloseBracket + 1; + } + + // Print the remaining part. + outs() << Text.substr(Pos); +} + static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj, MCContext &Ctx, MCDisassembler *PrimaryDisAsm, MCDisassembler *SecondaryDisAsm, @@ -1378,10 +1444,13 @@ if (Size == 0) Size = 1; + std::string InstText; + raw_string_ostream InstTextStream(InstText); PIP.printInst( *IP, Disassembled ? &Inst : nullptr, Bytes.slice(Index, Size), - {SectionAddr + Index + VMAAdjustment, Section.getIndex()}, outs(), + {SectionAddr + Index + VMAAdjustment, Section.getIndex()}, InstTextStream, "", *STI, &SP, &Rels); + printMarkedUpInst(StringRef(InstTextStream.str())); outs() << CommentStream.str(); Comments.clear(); @@ -1549,6 +1618,7 @@ report_error(Obj->getFileName(), "no instruction printer for target " + TripleName); IP->setPrintImmHex(PrintImmHex); + IP->setUseMarkup(Highlight); PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName)); SourcePrinter SP(Obj, TheTarget->getName());