wallace updated this revision to Diff 350652.
wallace added a comment.

I tried to use a ConstString instead of a const char *, but that's not trivial 
because
the compilers wants a safe destructor all the way down, and it seems that this 
is non-standard
across compilers, except for C++17 and onwards, which has the std::variant type.

So I'm just adding a comment as suggested.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103588/new/

https://reviews.llvm.org/D103588

Files:
  lldb/include/lldb/Target/Trace.h
  lldb/include/lldb/lldb-enumerations.h
  lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
  lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
  lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
  lldb/source/Target/Trace.cpp

Index: lldb/source/Target/Trace.cpp
===================================================================
--- lldb/source/Target/Trace.cpp
+++ lldb/source/Target/Trace.cpp
@@ -52,6 +52,23 @@
 } // namespace json
 } // namespace llvm
 
+TraceInstruction::TraceInstruction() : m_is_error(true) {
+  m_data.m_error = "invalid instruction";
+}
+
+TraceInstruction::TraceInstruction(lldb::addr_t load_address, uint8_t byte_size,
+                                   lldb::TraceInstructionType instruction_type)
+    : m_is_error(false), m_byte_size(byte_size),
+      m_instruction_type(instruction_type) {
+  m_data.m_load_address = load_address;
+}
+
+TraceInstruction::TraceInstruction(Error error) : m_is_error(true) {
+  // We are assuming that errors will be rare, so using the ConstrString pool
+  // helps us make this class smaller.
+  m_data.m_error = ConstString(toString(std::move(error))).GetCString();
+}
+
 static Error createInvalidPlugInError(StringRef plugin_name) {
   return createStringError(
       std::errc::invalid_argument,
@@ -124,9 +141,9 @@
 struct InstructionSymbolInfo {
   SymbolContext sc;
   Address address;
-  lldb::addr_t load_address;
+  TraceInstruction instruction;
   lldb::DisassemblerSP disassembler;
-  lldb::InstructionSP instruction;
+  lldb::InstructionSP instruction_sp;
   lldb_private::ExecutionContext exe_ctx;
 };
 
@@ -144,7 +161,7 @@
     Trace &trace, Thread &thread, size_t position,
     Trace::TraceDirection direction, SymbolContextItem symbol_scope,
     bool include_disassembler,
-    std::function<bool(size_t index, Expected<InstructionSymbolInfo> insn)>
+    std::function<bool(size_t index, const InstructionSymbolInfo &insn)>
         callback) {
   InstructionSymbolInfo prev_insn;
 
@@ -199,18 +216,18 @@
 
   trace.TraverseInstructions(
       thread, position, direction,
-      [&](size_t index, Expected<lldb::addr_t> load_address) -> bool {
-        if (!load_address)
-          return callback(index, load_address.takeError());
-
+      [&](size_t index, const TraceInstruction &instruction) -> bool {
         InstructionSymbolInfo insn;
-        insn.load_address = *load_address;
+        insn.instruction = instruction;
+        if (instruction.IsError())
+          return callback(index, insn);
+
         insn.exe_ctx = exe_ctx;
-        insn.address.SetLoadAddress(*load_address, &target);
+        insn.address.SetLoadAddress(instruction.GetLoadAddress(), &target);
         if (symbol_scope != 0)
           insn.sc = calculate_symbol_context(insn.address);
         if (include_disassembler)
-          std::tie(insn.disassembler, insn.instruction) =
+          std::tie(insn.disassembler, insn.instruction_sp) =
               calculate_disass(insn.address, insn.sc);
         prev_insn = insn;
         return callback(index, insn);
@@ -268,7 +285,7 @@
 static void
 DumpInstructionSymbolContext(Stream &s,
                              Optional<InstructionSymbolInfo> prev_insn,
-                             InstructionSymbolInfo &insn) {
+                             const InstructionSymbolInfo &insn) {
   if (prev_insn && IsSameInstructionSymbolContext(*prev_insn, insn))
     return;
 
@@ -288,15 +305,16 @@
   s.Printf("\n");
 }
 
-static void DumpInstructionDisassembly(Stream &s, InstructionSymbolInfo &insn) {
-  if (!insn.instruction)
+static void DumpInstructionDisassembly(Stream &s,
+                                       const InstructionSymbolInfo &insn) {
+  if (insn.instruction.IsError())
     return;
   s.Printf("    ");
-  insn.instruction->Dump(&s, /*show_address*/ false, /*show_bytes*/ false,
-                         /*max_opcode_byte_size*/ 0, &insn.exe_ctx, &insn.sc,
-                         /*prev_sym_ctx*/ nullptr,
-                         /*disassembly_addr_format*/ nullptr,
-                         /*max_address_text_size*/ 0);
+  insn.instruction_sp->Dump(&s, /*show_address*/ false, /*show_bytes*/ false,
+                            /*max_opcode_byte_size*/ 0, &insn.exe_ctx, &insn.sc,
+                            /*prev_sym_ctx*/ nullptr,
+                            /*disassembly_addr_format*/ nullptr,
+                            /*max_address_text_size*/ 0);
 }
 
 void Trace::DumpTraceInstructions(Thread &thread, Stream &s, size_t count,
@@ -327,10 +345,10 @@
   TraverseInstructionsWithSymbolInfo(
       *this, thread, start_position, TraceDirection::Forwards,
       eSymbolContextEverything, /*disassembler*/ true,
-      [&](size_t index, Expected<InstructionSymbolInfo> insn) -> bool {
-        if (!insn) {
+      [&](size_t index, const InstructionSymbolInfo &insn) -> bool {
+        if (insn.instruction.IsError()) {
           printInstructionIndex(index);
-          s << toString(insn.takeError());
+          s << insn.instruction.GetError();
 
           prev_insn = None;
           was_prev_instruction_an_error = true;
@@ -339,15 +357,15 @@
             s.Printf("    ...missing instructions\n");
 
           if (!raw)
-            DumpInstructionSymbolContext(s, prev_insn, *insn);
+            DumpInstructionSymbolContext(s, prev_insn, insn);
 
           printInstructionIndex(index);
-          s.Printf("0x%016" PRIx64, insn->load_address);
+          s.Printf("0x%016" PRIx64, insn.instruction.GetLoadAddress());
 
           if (!raw)
-            DumpInstructionDisassembly(s, *insn);
+            DumpInstructionDisassembly(s, insn);
 
-          prev_insn = *insn;
+          prev_insn = insn;
           was_prev_instruction_an_error = false;
         }
 
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
@@ -67,7 +67,7 @@
 
   void TraverseInstructions(
       Thread &thread, size_t position, TraceDirection direction,
-      std::function<bool(size_t index, llvm::Expected<lldb::addr_t> load_addr)>
+      std::function<bool(size_t index, const TraceInstruction &instruction)>
           callback) override;
 
   llvm::Optional<size_t> GetInstructionCount(Thread &thread) override;
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
@@ -108,18 +108,18 @@
 
 void TraceIntelPT::TraverseInstructions(
     Thread &thread, size_t position, TraceDirection direction,
-    std::function<bool(size_t index, Expected<lldb::addr_t> load_addr)>
+    std::function<bool(size_t index, const TraceInstruction &load_addr)>
         callback) {
   const DecodedThread *decoded_thread = Decode(thread);
   if (!decoded_thread)
     return;
 
-  ArrayRef<IntelPTInstruction> instructions = decoded_thread->GetInstructions();
+  ArrayRef<TraceInstruction> instructions = decoded_thread->GetInstructions();
 
   ssize_t delta = direction == TraceDirection::Forwards ? 1 : -1;
   for (ssize_t i = position; i < (ssize_t)instructions.size() && i >= 0;
        i += delta)
-    if (!callback(i, instructions[i].GetLoadAddress()))
+    if (!callback(i, instructions[i]))
       break;
 }
 
Index: lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
+++ lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
@@ -8,19 +8,32 @@
 #include "IntelPTDecoder.h"
 
 #include "llvm/Support/MemoryBuffer.h"
+#include <intel-pt.h>
 
 #include "TraceIntelPT.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/ThreadPostMortemTrace.h"
-#include "lldb/Utility/StringExtractor.h"
 
 using namespace lldb;
 using namespace lldb_private;
 using namespace lldb_private::trace_intel_pt;
 using namespace llvm;
 
+static llvm::Error
+CreateIntelPTError(int libipt_error_code,
+                   lldb::addr_t address = LLDB_INVALID_ADDRESS) {
+  const char *libipt_error_message = pt_errstr(pt_errcode(libipt_error_code));
+  if (address != LLDB_INVALID_ADDRESS && address > 0) {
+    return createStringError(inconvertibleErrorCode(),
+                             "0x%16.16" PRIx64 "    error: %s", address,
+                             libipt_error_message);
+  }
+  return createStringError(inconvertibleErrorCode(), "error: %s",
+                           libipt_error_message);
+}
+
 /// Move the decoder forward to the next synchronization point (i.e. next PSB
 /// packet).
 ///
@@ -88,6 +101,31 @@
   return 0;
 }
 
+TraceInstructionType GetTraceInstructionType(const pt_insn &insn) {
+  switch (insn.iclass) {
+  case ptic_other:
+    return lldb::eTraceInstructionOther;
+  case ptic_call:
+    return lldb::eTraceInstructionCall;
+  case ptic_return:
+    return lldb::eTraceInstructionReturn;
+  case ptic_jump:
+    return lldb::eTraceInstructionJump;
+  case ptic_cond_jump:
+    return lldb::eTraceInstructionCondJump;
+  case ptic_far_call:
+    return lldb::eTraceInstructionFarCall;
+  case ptic_far_return:
+    return lldb::eTraceInstructionFarReturn;
+  case ptic_far_jump:
+    return lldb::eTraceInstructionFarJump;
+  case ptic_ptwrite:
+    return lldb::eTraceInstructionTraceWrite;
+  default:
+    return lldb::eTraceInstructionUnknown;
+  }
+}
+
 /// Decode all the instructions from a configured decoder.
 /// The decoding flow is based on
 /// https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#the-instruction-flow-decode-loop
@@ -103,9 +141,9 @@
 ///
 /// \return
 ///   The decoded instructions.
-static std::vector<IntelPTInstruction>
+static std::vector<TraceInstruction>
 DecodeInstructions(pt_insn_decoder &decoder) {
-  std::vector<IntelPTInstruction> instructions;
+  std::vector<TraceInstruction> instructions;
 
   while (true) {
     int errcode = FindNextSynchronizationPoint(decoder);
@@ -113,7 +151,7 @@
       break;
 
     if (errcode < 0) {
-      instructions.emplace_back(make_error<IntelPTError>(errcode));
+      instructions.emplace_back(CreateIntelPTError(errcode));
       break;
     }
 
@@ -122,7 +160,7 @@
     while (true) {
       errcode = ProcessPTEvents(decoder, errcode);
       if (errcode < 0) {
-        instructions.emplace_back(make_error<IntelPTError>(errcode));
+        instructions.emplace_back(CreateIntelPTError(errcode));
         break;
       }
       pt_insn insn;
@@ -132,11 +170,12 @@
         break;
 
       if (errcode < 0) {
-        instructions.emplace_back(make_error<IntelPTError>(errcode, insn.ip));
+        instructions.emplace_back(CreateIntelPTError(errcode, insn.ip));
         break;
       }
 
-      instructions.emplace_back(insn);
+      instructions.emplace_back(insn.ip, insn.size,
+                                GetTraceInstructionType(insn));
     }
   }
 
@@ -159,7 +198,7 @@
   return bytes_read;
 }
 
-static Expected<std::vector<IntelPTInstruction>>
+static Expected<std::vector<TraceInstruction>>
 DecodeInMemoryTrace(Process &process, TraceIntelPT &trace_intel_pt,
                     MutableArrayRef<uint8_t> buffer) {
   Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo();
@@ -171,14 +210,14 @@
   config.cpu = *cpu_info;
 
   if (int errcode = pt_cpu_errata(&config.errata, &config.cpu))
-    return make_error<IntelPTError>(errcode);
+    return CreateIntelPTError(errcode);
 
   config.begin = buffer.data();
   config.end = buffer.data() + buffer.size();
 
   pt_insn_decoder *decoder = pt_insn_alloc_decoder(&config);
   if (!decoder)
-    return make_error<IntelPTError>(-pte_nomem);
+    return CreateIntelPTError(-pte_nomem);
 
   pt_image *image = pt_insn_get_image(decoder);
 
@@ -186,13 +225,13 @@
   assert(errcode == 0);
   (void)errcode;
 
-  std::vector<IntelPTInstruction> instructions = DecodeInstructions(*decoder);
+  std::vector<TraceInstruction> instructions = DecodeInstructions(*decoder);
 
   pt_insn_free_decoder(decoder);
   return instructions;
 }
 
-static Expected<std::vector<IntelPTInstruction>>
+static Expected<std::vector<TraceInstruction>>
 DecodeTraceFile(Process &process, TraceIntelPT &trace_intel_pt,
                 const FileSpec &trace_file) {
   ErrorOr<std::unique_ptr<MemoryBuffer>> trace_or_error =
@@ -209,7 +248,7 @@
   return DecodeInMemoryTrace(process, trace_intel_pt, trace_data);
 }
 
-static Expected<std::vector<IntelPTInstruction>>
+static Expected<std::vector<TraceInstruction>>
 DecodeLiveThread(Thread &thread, TraceIntelPT &trace) {
   Expected<std::vector<uint8_t>> buffer =
       trace.GetLiveThreadBuffer(thread.GetID());
@@ -233,7 +272,7 @@
     : m_trace_thread(trace_thread), m_trace(trace) {}
 
 DecodedThread PostMortemThreadDecoder::DoDecode() {
-  if (Expected<std::vector<IntelPTInstruction>> instructions =
+  if (Expected<std::vector<TraceInstruction>> instructions =
           DecodeTraceFile(*m_trace_thread->GetProcess(), m_trace,
                           m_trace_thread->GetTraceFile()))
     return DecodedThread(std::move(*instructions));
@@ -245,7 +284,7 @@
     : m_thread_sp(thread.shared_from_this()), m_trace(trace) {}
 
 DecodedThread LiveThreadDecoder::DoDecode() {
-  if (Expected<std::vector<IntelPTInstruction>> instructions =
+  if (Expected<std::vector<TraceInstruction>> instructions =
           DecodeLiveThread(*m_thread_sp, m_trace))
     return DecodedThread(std::move(*instructions));
   else
Index: lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
+++ lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
@@ -11,7 +11,6 @@
 
 #include <vector>
 
-#include "llvm/Support/Errc.h"
 #include "llvm/Support/Error.h"
 
 #include "lldb/Target/Trace.h"
@@ -22,83 +21,6 @@
 namespace lldb_private {
 namespace trace_intel_pt {
 
-/// Class for representing a libipt decoding error.
-class IntelPTError : public llvm::ErrorInfo<IntelPTError> {
-public:
-  static char ID;
-
-  /// \param[in] libipt_error_code
-  ///     Negative number returned by libipt when decoding the trace and
-  ///     signaling errors.
-  ///
-  /// \param[in] address
-  ///     Optional instruction address. When decoding an individual instruction,
-  ///     its address might be available in the \a pt_insn object, and should be
-  ///     passed to this constructor. Other errors don't have an associated
-  ///     address.
-  IntelPTError(int libipt_error_code,
-               lldb::addr_t address = LLDB_INVALID_ADDRESS);
-
-  std::error_code convertToErrorCode() const override {
-    return llvm::errc::not_supported;
-  }
-
-  void log(llvm::raw_ostream &OS) const override;
-
-private:
-  int m_libipt_error_code;
-  lldb::addr_t m_address;
-};
-
-/// \class IntelPTInstruction
-/// An instruction obtained from decoding a trace. It is either an actual
-/// instruction or an error indicating a gap in the trace.
-///
-/// Gaps in the trace can come in a few flavors:
-///   - tracing gaps (e.g. tracing was paused and then resumed)
-///   - tracing errors (e.g. buffer overflow)
-///   - decoding errors (e.g. some memory region couldn't be decoded)
-/// As mentioned, any gap is represented as an error in this class.
-class IntelPTInstruction {
-public:
-  IntelPTInstruction(const pt_insn &pt_insn) : m_pt_insn(pt_insn) {}
-
-  /// Error constructor
-  ///
-  /// libipt errors should use the underlying \a IntelPTError class.
-  IntelPTInstruction(llvm::Error err) {
-    llvm::handleAllErrors(std::move(err),
-                          [&](std::unique_ptr<llvm::ErrorInfoBase> info) {
-                            m_error = std::move(info);
-                          });
-  }
-
-  /// Check if this object represents an error (i.e. a gap).
-  ///
-  /// \return
-  ///     Whether this object represents an error.
-  bool IsError() const;
-
-  /// \return
-  ///     The instruction pointer address, or an \a llvm::Error if it is an
-  ///     error.
-  llvm::Expected<lldb::addr_t> GetLoadAddress() const;
-
-  /// \return
-  ///     An \a llvm::Error object if this class corresponds to an Error, or an
-  ///     \a llvm::Error::success otherwise.
-  llvm::Error ToError() const;
-
-  IntelPTInstruction(IntelPTInstruction &&other) = default;
-
-private:
-  IntelPTInstruction(const IntelPTInstruction &other) = delete;
-  const IntelPTInstruction &operator=(const IntelPTInstruction &other) = delete;
-
-  pt_insn m_pt_insn;
-  std::unique_ptr<llvm::ErrorInfoBase> m_error;
-};
-
 /// \class DecodedThread
 /// Class holding the instructions and function call hierarchy obtained from
 /// decoding a trace, as well as a position cursor used when reverse debugging
@@ -108,7 +30,7 @@
 /// stopped at. See \a Trace::GetCursorPosition for more information.
 class DecodedThread {
 public:
-  DecodedThread(std::vector<IntelPTInstruction> &&instructions)
+  DecodedThread(std::vector<TraceInstruction> &&instructions)
       : m_instructions(std::move(instructions)), m_position(GetLastPosition()) {
   }
 
@@ -121,7 +43,7 @@
   ///
   /// \return
   ///   The instructions of the trace.
-  llvm::ArrayRef<IntelPTInstruction> GetInstructions() const;
+  llvm::ArrayRef<TraceInstruction> GetInstructions() const;
 
   /// \return
   ///   The current position of the cursor of this trace, or 0 if there are no
@@ -141,7 +63,7 @@
   ///     The index of the last element of the trace, or 0 if empty.
   size_t GetLastPosition() const;
 
-  std::vector<IntelPTInstruction> m_instructions;
+  std::vector<TraceInstruction> m_instructions;
   size_t m_position;
 };
 
Index: lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
+++ lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
@@ -14,45 +14,11 @@
 using namespace lldb_private::trace_intel_pt;
 using namespace llvm;
 
-char IntelPTError::ID;
-
-IntelPTError::IntelPTError(int libipt_error_code, lldb::addr_t address)
-    : m_libipt_error_code(libipt_error_code), m_address(address) {
-  assert(libipt_error_code < 0);
-}
-
-void IntelPTError::log(llvm::raw_ostream &OS) const {
-  const char *libipt_error_message = pt_errstr(pt_errcode(m_libipt_error_code));
-  if (m_address != LLDB_INVALID_ADDRESS && m_address > 0) {
-    write_hex(OS, m_address, HexPrintStyle::PrefixLower, 18);
-    OS << "    ";
-  }
-  OS << "error: " << libipt_error_message;
-}
-
-bool IntelPTInstruction::IsError() const { return (bool)m_error; }
-
-Expected<lldb::addr_t> IntelPTInstruction::GetLoadAddress() const {
-  if (IsError())
-    return ToError();
-  return m_pt_insn.ip;
-}
-
-Error IntelPTInstruction::ToError() const {
-  if (!IsError())
-    return Error::success();
-
-  if (m_error->isA<IntelPTError>())
-    return make_error<IntelPTError>(static_cast<IntelPTError &>(*m_error));
-  return make_error<StringError>(m_error->message(),
-                                 m_error->convertToErrorCode());
-}
-
 size_t DecodedThread::GetLastPosition() const {
   return m_instructions.empty() ? 0 : m_instructions.size() - 1;
 }
 
-ArrayRef<IntelPTInstruction> DecodedThread::GetInstructions() const {
+ArrayRef<TraceInstruction> DecodedThread::GetInstructions() const {
   return makeArrayRef(m_instructions);
 }
 
Index: lldb/include/lldb/lldb-enumerations.h
===================================================================
--- lldb/include/lldb/lldb-enumerations.h
+++ lldb/include/lldb/lldb-enumerations.h
@@ -9,6 +9,7 @@
 #ifndef LLDB_LLDB_ENUMERATIONS_H
 #define LLDB_LLDB_ENUMERATIONS_H
 
+#include <cstdint>
 #include <type_traits>
 
 #ifndef SWIG
@@ -781,6 +782,34 @@
   eTraceTypeProcessorTrace
 };
 
+/// Architecture-agnostic categorization of instructions. Useful for doing
+/// analysis on traces.
+enum TraceInstructionType : uint8_t {
+  /// The instruction is not recognized by LLDB
+  eTraceInstructionUnknown = 0,
+  /// The instruction is something not listed below
+  eTraceInstructionOther,
+  /// The instruction is a near (function) call
+  eTraceInstructionCall,
+  /// The instruction is a near (function) return
+  eTraceInstructionReturn,
+  /// The instruction is a near unconditional jump
+  eTraceInstructionJump,
+  /// The instruction is a near conditional jump
+  eTraceInstructionCondJump,
+  /// The instruction is a call-like far transfer
+  /// e.g. SYSCALL, SYSENTER, or FAR CALL
+  eTraceInstructionFarCall,
+  /// The instruction is a return-like far transfer
+  /// e.g. SYSRET, SYSEXIT, IRET, or FAR RET
+  eTraceInstructionFarReturn,
+  /// The instruction is a jump-like far transfer
+  /// e.g. FAR JMP
+  eTraceInstructionFarJump,
+  /// The instruction is a PTWRITE or similar
+  eTraceInstructionTraceWrite,
+};
+
 enum StructuredDataType {
   eStructuredDataTypeInvalid = -1,
   eStructuredDataTypeNull = 0,
Index: lldb/include/lldb/Target/Trace.h
===================================================================
--- lldb/include/lldb/Target/Trace.h
+++ lldb/include/lldb/Target/Trace.h
@@ -22,6 +22,62 @@
 
 namespace lldb_private {
 
+/// Class that represents a decoded instruction from a trace. It's supposed to
+/// have a minimal memory footprint as the number of instructions can be in the
+/// order of millions.
+///
+/// For complex operations, \a lldb_private::Instruction can be used sparingly.
+///
+/// This class assumes that errors will be extremely rare compared to the number
+/// of correct instructions and storing them as \a ConstString should be fine.
+class TraceInstruction {
+public:
+  TraceInstruction(lldb::addr_t load_address, uint8_t byte_size,
+                   lldb::TraceInstructionType instruction_type);
+
+  /// Constructor for an instruction that couldn't be decoded
+  TraceInstruction(llvm::Error error);
+
+  /// This constructs a failed instruction, i.e. \a GetError() returns \b true.
+  TraceInstruction();
+
+  /// \return
+  ///     The architecture-agnostic instruction type
+  lldb::TraceInstructionType GetInstructionType() const {
+    return m_instruction_type;
+  }
+
+  /// \return
+  ///     The load adress (aka instruction pointer)
+  lldb::addr_t GetLoadAddress() const { return m_data.m_load_address; }
+
+  /// \return
+  ///     The error message or \b nullptr if not an error.
+  const char *GetError() const {
+    if (m_is_error)
+      return m_data.m_error;
+    return nullptr;
+  }
+
+  /// \return
+  ///     The size in bytes of the instruction.
+  uint8_t GetByteSize() const { return m_byte_size; }
+
+  bool IsError() const { return m_is_error; }
+
+private:
+  uint8_t m_is_error;
+  uint8_t m_byte_size;
+  lldb::TraceInstructionType m_instruction_type;
+
+  union {
+    lldb::addr_t m_load_address;
+    /// This const char * comes from a \a ConstString, and thus doesn't need to
+    /// be freed.
+    const char *m_error;
+  } m_data;
+};
+
 /// \class Trace Trace.h "lldb/Target/Trace.h"
 /// A plug-in interface definition class for trace information.
 ///
@@ -201,7 +257,7 @@
   ///     the iteration stops.
   virtual void TraverseInstructions(
       Thread &thread, size_t position, TraceDirection direction,
-      std::function<bool(size_t index, llvm::Expected<lldb::addr_t> load_addr)>
+      std::function<bool(size_t index, const TraceInstruction &instruction)>
           callback) = 0;
 
   /// Get the number of available instructions in the trace of the given thread.
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to