Index: lldb/include/lldb/Core/Disassembler.h =================================================================== --- lldb/include/lldb/Core/Disassembler.h +++ lldb/include/lldb/Core/Disassembler.h @@ -64,14 +64,16 @@ const Address &GetAddress() const { return m_address; } - const char *GetMnemonic(const ExecutionContext *exe_ctx) { + const char *GetMnemonic(const ExecutionContext *exe_ctx, + bool markup = false) { CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); - return m_opcode_name.c_str(); + return markup ? m_markup_opcode_name.c_str() : m_opcode_name.c_str(); } - const char *GetOperands(const ExecutionContext *exe_ctx) { + const char *GetOperands(const ExecutionContext *exe_ctx, + bool markup = false) { CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); - return m_mnemonics.c_str(); + return markup ? m_markup_mnemonics.c_str() : m_mnemonics.c_str(); } const char *GetComment(const ExecutionContext *exe_ctx) { @@ -244,7 +246,9 @@ protected: Opcode m_opcode; // The opcode for this instruction std::string m_opcode_name; + std::string m_markup_opcode_name; std::string m_mnemonics; + std::string m_markup_mnemonics; std::string m_comment; bool m_calculated_strings; Index: lldb/source/Core/Disassembler.cpp =================================================================== --- lldb/source/Core/Disassembler.cpp +++ lldb/source/Core/Disassembler.cpp @@ -645,18 +645,27 @@ instruction_control_flow_kind)); } + bool show_color = false; + if (exe_ctx) { + if (TargetSP target_sp = exe_ctx->GetTargetSP()) { + show_color = target_sp->GetDebugger().GetUseColor(); + } + } const size_t opcode_pos = ss.GetSizeOfLastLine(); + const std::string &opcode_name = + show_color ? m_markup_opcode_name : m_opcode_name; + const std::string &mnemonics = show_color ? m_markup_mnemonics : m_mnemonics; // The default opcode size of 7 characters is plenty for most architectures // but some like arm can pull out the occasional vqrshrun.s16. We won't get // consistent column spacing in these cases, unfortunately. - if (m_opcode_name.length() >= opcode_column_width) { - opcode_column_width = m_opcode_name.length() + 1; + if (opcode_name.length() >= opcode_column_width) { + opcode_column_width = opcode_name.length() + 1; } - ss.PutCString(m_opcode_name); + ss.PutCString(opcode_name); ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' '); - ss.PutCString(m_mnemonics); + ss.PutCString(mnemonics); if (!m_comment.empty()) { ss.FillLastLineToColumn( Index: lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp =================================================================== --- lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp +++ lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp @@ -63,6 +63,8 @@ void PrintMCInst(llvm::MCInst &mc_inst, lldb::addr_t pc, std::string &inst_string, std::string &comments_string); void SetStyle(bool use_hex_immed, HexImmediateStyle hex_style); + void SetUseColor(bool use_color); + bool GetUseColor() const; bool CanBranch(llvm::MCInst &mc_inst) const; bool HasDelaySlot(llvm::MCInst &mc_inst) const; bool IsCall(llvm::MCInst &mc_inst) const; @@ -565,7 +567,9 @@ if (m_opcode.GetData(data)) { std::string out_string; + std::string markup_out_string; std::string comment_string; + std::string markup_comment_string; DisassemblerScope disasm(*this, exe_ctx); if (disasm) { @@ -607,7 +611,14 @@ if (inst_size > 0) { mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); + + const bool saved_use_color = mc_disasm_ptr->GetUseColor(); + mc_disasm_ptr->SetUseColor(false); mc_disasm_ptr->PrintMCInst(inst, pc, out_string, comment_string); + mc_disasm_ptr->SetUseColor(true); + mc_disasm_ptr->PrintMCInst(inst, pc, markup_out_string, + markup_comment_string); + mc_disasm_ptr->SetUseColor(saved_use_color); if (!comment_string.empty()) { AppendComment(comment_string); @@ -672,6 +683,11 @@ m_opcode_name = matches[1].str(); m_mnemonics = matches[2].str(); } + matches.clear(); + if (s_regex.Execute(markup_out_string, &matches)) { + m_markup_opcode_name = matches[1].str(); + m_markup_mnemonics = matches[2].str(); + } } } } @@ -1344,10 +1360,12 @@ llvm::raw_string_ostream inst_stream(inst_string); llvm::raw_string_ostream comments_stream(comments_string); + inst_stream.enable_colors(m_instr_printer_up->getUseColor()); m_instr_printer_up->setCommentStream(comments_stream); m_instr_printer_up->printInst(&mc_inst, pc, llvm::StringRef(), *m_subtarget_info_up, inst_stream); m_instr_printer_up->setCommentStream(llvm::nulls()); + comments_stream.flush(); static std::string g_newlines("\r\n"); @@ -1374,6 +1392,14 @@ } } +void DisassemblerLLVMC::MCDisasmInstance::SetUseColor(bool use_color) { + m_instr_printer_up->setUseColor(use_color); +} + +bool DisassemblerLLVMC::MCDisasmInstance::GetUseColor() const { + return m_instr_printer_up->getUseColor(); +} + bool DisassemblerLLVMC::MCDisasmInstance::CanBranch( llvm::MCInst &mc_inst) const { if (m_instr_analysis_up) Index: lldb/test/API/python_api/disassemble-raw-data/TestDisassembleRawData.py =================================================================== --- lldb/test/API/python_api/disassemble-raw-data/TestDisassembleRawData.py +++ lldb/test/API/python_api/disassemble-raw-data/TestDisassembleRawData.py @@ -59,9 +59,19 @@ elif arch in ("aarch64", "arm64"): self.assertEqual(inst.GetMnemonic(target), "mov") self.assertEqual(inst.GetOperands(target), "w0, #0x63") + self.assertEqual(inst.GetComment(target), "=99 ") self.assertEqual( inst.GetControlFlowKind(target), lldb.eInstructionControlFlowKindUnknown ) + # Make sure that using colors doesn't affect the output here. + res = lldb.SBCommandReturnObject() + ci = self.dbg.GetCommandInterpreter() + ci.HandleCommand("settings set use-color true", res) + self.assertEqual(inst.GetOperands(target), "w0, #0x63") + self.assertEqual(inst.GetMnemonic(target), "mov") + self.assertEqual(inst.GetComment(target), "=99 ") + ci.HandleCommand("settings set use-color false", res) + elif arch == "arm": self.assertEqual(inst.GetMnemonic(target), "mov") self.assertEqual(inst.GetOperands(target), "r3, #99") Index: lldb/test/Shell/Commands/command-disassemble-aarch64-color.s =================================================================== --- /dev/null +++ lldb/test/Shell/Commands/command-disassemble-aarch64-color.s @@ -0,0 +1,32 @@ +# REQUIRES: aarch64 + +# This checks that lldb's disassembler colors AArch64 disassembly. + +# RUN: llvm-mc -filetype=obj -triple aarch64-linux-gnueabihf %s -o %t --mattr=+all +# RUN: %lldb %t -o "settings set use-color true" -o "disassemble -n fn" -o exit 2>&1 | FileCheck %s + +.globl fn +.type fn, @function +fn: + // These are in alphabetical order by extension name + aesd v0.16b, v0.16b // AEK_AES + bfadd z23.h, p3/m, z23.h, z13.h // AEK_B16B16 + bfdot v2.2s, v3.4h, v4.4h // AEK_BF16 + brb iall // AEK_BRBE + crc32b w0, w0, w0 // AEK_CRC + // AEK_CRYPTO enables a combination of other features + smin x0, x0, #0 // AEK_CSSC + sysp #0, c2, c0, #0, x0, x1 // AEK_D128 + sdot v0.2s, v1.8b, v2.8b // AEK_DOTPROD + fmmla z0.s, z1.s, z2.s // AEK_F32MM + +# CHECK: `fn: +# CHECK-NEXT: [0x0] <+0>: aesd v0.16b, v0.16b +# CHECK-NEXT: [0x4] <+4>: bfadd z23.h, p3/m, z23.h, z13.h +# CHECK-NEXT: [0x8] <+8>: bfdot v2.2s, v3.4h, v4.4h +# CHECK-NEXT: [0xc] <+12>: brb iall +# CHECK-NEXT: [0x10] <+16>: crc32b w0, w0, w0 +# CHECK-NEXT: [0x14] <+20>: smin x0, x0, #0x0 +# CHECK-NEXT: [0x18] <+24>: sysp #0x0, c2, c0, #0x0, x0, x1 +# CHECK-NEXT: [0x1c] <+28>: sdot v0.2s, v1.8b, v2.8b +# CHECK-NEXT: [0x20] <+32>: fmmla z0.s, z1.s, z2.s