//===-- FormatterBytecode.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/DataFormatters/FormatterBytecode.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/ValueObject/ValueObjectConstResult.h"
#include "lldb/lldb-forward.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorExtras.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadicDetails.h"

using namespace lldb;
namespace lldb_private {

std::string toString(FormatterBytecode::OpCodes op) {
  switch (op) {
#define DEFINE_OPCODE(OP, MNEMONIC, NAME)                                      \
  case OP: {                                                                   \
    const char *s = MNEMONIC;                                                  \
    return s ? s : #NAME;                                                      \
  }
#include "lldb/DataFormatters/FormatterBytecode.def"
#undef DEFINE_OPCODE
  }
  return llvm::utostr(op);
}

std::string toString(FormatterBytecode::Selectors sel) {
  switch (sel) {
#define DEFINE_SELECTOR(ID, NAME)                                              \
  case ID:                                                                     \
    return "@" #NAME;
#include "lldb/DataFormatters/FormatterBytecode.def"
#undef DEFINE_SELECTOR
  }
  return "@" + llvm::utostr(sel);
}

std::string toString(FormatterBytecode::Signatures sig) {
  switch (sig) {
#define DEFINE_SIGNATURE(ID, NAME)                                             \
  case ID:                                                                     \
    return "@" #NAME;
#include "lldb/DataFormatters/FormatterBytecode.def"
#undef DEFINE_SIGNATURE
  }
  return llvm::utostr(sig);
}

std::string toString(const FormatterBytecode::DataStack &data) {
  std::string s;
  llvm::raw_string_ostream os(s);
  os << "[ ";
  for (auto &d : data) {
    if (auto s = std::get_if<std::string>(&d))
      os << '"' << *s << '"';
    else if (auto u = std::get_if<uint64_t>(&d))
      os << *u << 'u';
    else if (auto i = std::get_if<int64_t>(&d))
      os << *i;
    else if (auto ap = std::get_if<llvm::APSInt>(&d))
      os << *ap;
    else if (auto valobj = std::get_if<ValueObjectSP>(&d)) {
      if (!valobj->get())
        os << "null";
      else
        os << "object(" << valobj->get()->GetValueAsCString() << ')';
    } else if (auto type = std::get_if<CompilerType>(&d)) {
      os << '(' << type->GetTypeName(true) << ')';
    } else if (auto sel = std::get_if<FormatterBytecode::Selectors>(&d)) {
      os << toString(*sel);
    }
    os << ' ';
  }
  os << ']';
  return s;
}

namespace FormatterBytecode {

/// Implement the @format function.
static llvm::Error FormatImpl(DataStack &data) {
  auto fmt = data.Pop<std::string>();
  auto replacements =
      llvm::formatv_object_base::parseFormatString(fmt, 0, false);
  std::string s;
  llvm::raw_string_ostream os(s);
  unsigned num_args = 0;
  for (const auto &r : replacements)
    if (r.Type == llvm::ReplacementType::Format)
      num_args = std::max(num_args, r.Index + 1);

  if (data.size() < num_args)
    return llvm::createStringError("not enough arguments");

  for (const auto &r : replacements) {
    if (r.Type == llvm::ReplacementType::Literal) {
      os << r.Spec;
      continue;
    }
    using namespace llvm::support::detail;
    auto arg = data[data.size() - num_args + r.Index];
    auto format = [&](FormatFunctorRef &&adapter) {
      llvm::FmtAlign Align(adapter, r.Where, r.Width, r.Pad);
      Align.format(os, r.Options);
    };

    if (auto s = std::get_if<std::string>(&arg))
      format(FormatFunctor(s->c_str()));
    else if (auto u = std::get_if<uint64_t>(&arg))
      format(FormatFunctor(u));
    else if (auto i = std::get_if<int64_t>(&arg))
      format(FormatFunctor(i));
    else if (auto ap = std::get_if<llvm::APSInt>(&arg))
      format(FormatFunctor(*ap));
    else if (auto valobj = std::get_if<ValueObjectSP>(&arg)) {
      if (!valobj->get())
        format(FormatFunctor("null object"));
      else
        format(FormatFunctor(valobj->get()->GetValueAsCString()));
    } else if (auto type = std::get_if<CompilerType>(&arg))
      format(FormatFunctor(type->GetDisplayTypeName()));
    else if (auto sel = std::get_if<FormatterBytecode::Selectors>(&arg))
      format(FormatFunctor(toString(*sel)));
  }
  data.Push(s);
  return llvm::Error::success();
}

static llvm::Error TypeCheck(llvm::ArrayRef<DataStackElement> data,
                             DataType type) {
  if (data.size() < 1)
    return llvm::createStringError("not enough elements on data stack");

  auto &elem = data.back();
  switch (type) {
  case Any:
    break;
  case String:
    if (!std::holds_alternative<std::string>(elem))
      return llvm::createStringError("expected String");
    break;
  case UInt:
    if (!std::holds_alternative<uint64_t>(elem))
      return llvm::createStringError("expected UInt");
    break;
  case Int:
    if (!std::holds_alternative<int64_t>(elem))
      return llvm::createStringError("expected Int");
    break;
  case Object:
    if (!std::holds_alternative<ValueObjectSP>(elem))
      return llvm::createStringError("expected Object");
    break;
  case Type:
    if (!std::holds_alternative<CompilerType>(elem))
      return llvm::createStringError("expected Type");
    break;
  case Selector:
    if (!std::holds_alternative<Selectors>(elem))
      return llvm::createStringError("expected Selector");
    break;
  case Integer:
    if (!std::holds_alternative<llvm::APSInt>(elem))
      return llvm::createStringError("expected Integer");
    break;
  }
  return llvm::Error::success();
}

static llvm::Error TypeCheck(llvm::ArrayRef<DataStackElement> data,
                             DataType type1, DataType type2) {
  if (auto error = TypeCheck(data, type2))
    return error;
  return TypeCheck(data.drop_back(), type1);
}

static llvm::Error TypeCheck(llvm::ArrayRef<DataStackElement> data,
                             DataType type1, DataType type2, DataType type3) {
  if (auto error = TypeCheck(data, type3))
    return error;
  return TypeCheck(data.drop_back(1), type2, type1);
}

/// Wrap the result of a binary operator applied to two APSInts back into a
/// DataStackElement. Comparison operators yield bool and need bit_width/
/// is_unsigned to construct the boolean's APSInt representation; arithmetic
/// operators already yield a correctly-tagged APSInt and ignore them.
template <typename T>
static DataStackElement WrapAPSIntResult(T result, unsigned bit_width,
                                         bool is_unsigned) {
  if constexpr (std::is_same_v<T, bool>)
    return llvm::APSInt(llvm::APInt(bit_width, result), is_unsigned);
  else
    return DataStackElement(std::move(result));
}

llvm::Error Interpret(ControlStack &control, DataStack &data, Signatures sig) {
  if (control.empty())
    return llvm::Error::success();
  // Since the only data types are single endian and ULEBs, the
  // endianness should not matter.
  llvm::DataExtractor cur_block(control.back(), true);
  llvm::DataExtractor::Cursor pc(0);

  while (!control.empty()) {
    /// Activate the top most block from the control stack.
    auto activate_block = [&]() {
      // Save the return address.
      if (control.size() > 1)
        control[control.size() - 2] = cur_block.getData().drop_front(pc.tell());
      cur_block = llvm::DataExtractor(control.back(), true);
      if (pc)
        pc = llvm::DataExtractor::Cursor(0);
    };

    /// Fetch the next byte in the instruction stream.
    auto next_byte = [&]() -> uint8_t {
      // At the end of the current block?
      while (pc.tell() >= cur_block.size() && !control.empty()) {
        if (control.size() == 1) {
          control.pop_back();
          return 0;
        }
        control.pop_back();
        activate_block();
      }

      // Fetch the next instruction.
      return cur_block.getU8(pc);
    };

    // Fetch the next opcode.
    OpCodes opcode = (OpCodes)next_byte();
    if (control.empty() || !pc)
      return pc.takeError();

    LLDB_LOG_VERBOSE(GetLog(LLDBLog::DataFormatters),
                     "[eval {0}] opcode={1}, control={2}, data={3}",
                     toString(sig), toString(opcode), control.size(),
                     toString(data));

    // Various shorthands to improve the readability of error handling.
#define TYPE_CHECK(...)                                                        \
  if (auto error = TypeCheck(data, __VA_ARGS__))                               \
    return error;

    auto error = [&](llvm::Twine msg) {
      return llvm::createStringError(msg + "(opcode=" + toString(opcode) + ")");
    };

    switch (opcode) {
    // Data stack manipulation.
    case op_dup:
      TYPE_CHECK(Any);
      data.Push(data.back());
      continue;
    case op_drop:
      TYPE_CHECK(Any);
      data.pop_back();
      continue;
    case op_pick: {
      TYPE_CHECK(UInt);
      uint64_t idx = data.Pop<uint64_t>();
      if (idx >= data.size())
        return error("index out of bounds");
      data.Push(data[idx]);
      continue;
    }
    case op_over:
      TYPE_CHECK(Any, Any);
      data.Push(data[data.size() - 2]);
      continue;
    case op_swap: {
      TYPE_CHECK(Any, Any);
      auto x = data.PopAny();
      auto y = data.PopAny();
      data.Push(x);
      data.Push(y);
      continue;
    }
    case op_rot: {
      TYPE_CHECK(Any, Any, Any);
      auto z = data.PopAny();
      auto y = data.PopAny();
      auto x = data.PopAny();
      data.Push(z);
      data.Push(x);
      data.Push(y);
      continue;
    }

    // Control stack manipulation.
    case op_begin: {
      uint64_t length = cur_block.getULEB128(pc);
      if (!pc)
        return pc.takeError();
      llvm::StringRef block = cur_block.getBytes(pc, length);
      if (!pc)
        return pc.takeError();
      control.push_back(block);
      continue;
    }
    case op_if: {
      auto cond = data.PopAny();
      bool truthy;
      if (auto *ap = std::get_if<llvm::APSInt>(&cond))
        truthy = !ap->isZero();
      else if (auto *u = std::get_if<uint64_t>(&cond))
        // Deprecated.
        truthy = *u != 0;
      else
        return error("expected Integer or UInt");
      if (truthy) {
        if (!cur_block.size())
          return error("empty control stack");
        activate_block();
      } else
        control.pop_back();
      continue;
    }
    case op_ifelse: {
      if (cur_block.size() < 2)
        return error("empty control stack");
      auto cond = data.PopAny();
      bool truthy;
      if (auto *ap = std::get_if<llvm::APSInt>(&cond))
        truthy = !ap->isZero();
      else if (auto *u = std::get_if<uint64_t>(&cond))
        // Deprecated.
        truthy = *u != 0;
      else
        return error("expected Integer or UInt");
      if (!truthy)
        control[control.size() - 2] = control.back();
      control.pop_back();
      activate_block();
      continue;
    }
    case op_return:
      control.clear();
      return pc.takeError();

    // Literals.
    case op_lit_uint:
      data.Push(cur_block.getULEB128(pc));
      continue;
    case op_lit_int:
      data.Push(cur_block.getSLEB128(pc));
      continue;
    case op_lit_integer:
      data.Push(cur_block.getSLEB128APSInt(pc));
      continue;
    case op_lit_selector:
      data.Push(Selectors(cur_block.getU8(pc)));
      continue;
    case op_lit_null:
      data.Push(ValueObjectSP());
      continue;
    case op_lit_string: {
      uint64_t length = cur_block.getULEB128(pc);
      llvm::StringRef bytes = cur_block.getBytes(pc, length);
      data.Push(bytes.str());
      continue;
    }
    case op_as_uint: {
      TYPE_CHECK(Int);
      uint64_t casted;
      int64_t val = data.Pop<int64_t>();
      memcpy(&casted, &val, sizeof(val));
      data.Push(casted);
      continue;
    }
    case op_as_int: {
      TYPE_CHECK(UInt);
      int64_t casted;
      uint64_t val = data.Pop<uint64_t>();
      memcpy(&casted, &val, sizeof(val));
      data.Push(casted);
      continue;
    }
    case op_is_null: {
      TYPE_CHECK(Object);
      data.Push(data.Pop<ValueObjectSP>() ? (uint64_t)0 : (uint64_t)1);
      continue;
    }

// Arithmetic operations.
#define BINOP_IMPL(OP, CHECK_ZERO)                                             \
  {                                                                            \
    TYPE_CHECK(Any, Any);                                                      \
    auto y = data.PopAny();                                                    \
    if (std::holds_alternative<uint64_t>(y)) {                                 \
      if (CHECK_ZERO && !std::get<uint64_t>(y))                                \
        return error(#OP " by zero");                                          \
      TYPE_CHECK(UInt);                                                        \
      data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y)));    \
    } else if (std::holds_alternative<int64_t>(y)) {                           \
      if (CHECK_ZERO && !std::get<int64_t>(y))                                 \
        return error(#OP " by zero");                                          \
      TYPE_CHECK(Int);                                                         \
      data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y)));       \
    } else if (std::holds_alternative<llvm::APSInt>(y)) {                      \
      TYPE_CHECK(Integer);                                                     \
      llvm::APSInt rhs = std::get<llvm::APSInt>(y);                            \
      llvm::APSInt lhs = data.Pop<llvm::APSInt>();                             \
      if (lhs.isUnsigned() || rhs.isUnsigned())                                \
        return error("unsupported unsigned value");                            \
      unsigned width = std::max(lhs.getBitWidth(), rhs.getBitWidth());         \
      lhs = lhs.extend(width);                                                 \
      rhs = rhs.extend(width);                                                 \
      if (CHECK_ZERO && rhs.isZero())                                          \
        return error(#OP " by zero");                                          \
      data.Push(WrapAPSIntResult(lhs OP rhs, width, lhs.isUnsigned()));        \
    } else                                                                     \
      return error("unsupported data types");                                  \
  }
#define BINOP(OP) BINOP_IMPL(OP, false)
#define BINOP_CHECKZERO(OP) BINOP_IMPL(OP, true)

// Comparison operations.
#define CMPOP(OP)                                                              \
  {                                                                            \
    TYPE_CHECK(Any, Any);                                                      \
    auto y = data.PopAny();                                                    \
    if (std::holds_alternative<uint64_t>(y)) {                                 \
      TYPE_CHECK(UInt);                                                        \
      data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y)));    \
    } else if (std::holds_alternative<int64_t>(y)) {                           \
      TYPE_CHECK(Int);                                                         \
      data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y)));       \
    } else if (std::holds_alternative<llvm::APSInt>(y)) {                      \
      TYPE_CHECK(Integer);                                                     \
      llvm::APSInt rhs = std::get<llvm::APSInt>(y);                            \
      llvm::APSInt lhs = data.Pop<llvm::APSInt>();                             \
      if (lhs.isUnsigned() || rhs.isUnsigned())                                \
        return error("unsupported unsigned value");                            \
      unsigned width = std::max(lhs.getBitWidth(), rhs.getBitWidth());         \
      lhs = lhs.extend(width);                                                 \
      rhs = rhs.extend(width);                                                 \
      data.Push(WrapAPSIntResult(lhs OP rhs, width, lhs.isUnsigned()));        \
    } else                                                                     \
      return error("unsupported data types");                                  \
  }

// Bitwise operations use an Integer's underlying bit pattern, not its
// mathematical value (ie signed-ness is ignored). This means >> is always a
// logical (zero-filling) shift, never an arithmetic shift. Mismatched bit
// widths are implicitly zero-extended (not sign-extended).
#define BITOP(OP)                                                              \
  {                                                                            \
    TYPE_CHECK(Any, Any);                                                      \
    auto y = data.PopAny();                                                    \
    if (std::holds_alternative<uint64_t>(y)) {                                 \
      TYPE_CHECK(UInt);                                                        \
      data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y)));    \
    } else if (std::holds_alternative<int64_t>(y)) {                           \
      TYPE_CHECK(Int);                                                         \
      data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y)));       \
    } else if (std::holds_alternative<llvm::APSInt>(y)) {                      \
      TYPE_CHECK(Integer);                                                     \
      llvm::APSInt rhs = std::get<llvm::APSInt>(y);                            \
      llvm::APSInt lhs = data.Pop<llvm::APSInt>();                             \
      unsigned width = std::max(lhs.getBitWidth(), rhs.getBitWidth());         \
      llvm::APInt lhs_bits =                                                   \
          static_cast<const llvm::APInt &>(lhs).zext(width);                   \
      llvm::APInt rhs_bits =                                                   \
          static_cast<const llvm::APInt &>(rhs).zext(width);                   \
      llvm::APInt bits = lhs_bits OP rhs_bits;                                 \
      data.Push(llvm::APSInt(std::move(bits), /*isUnsigned=*/false));          \
    } else                                                                     \
      return error("unsupported data types");                                  \
  }

    case op_plus:
      BINOP(+);
      continue;
    case op_minus:
      BINOP(-);
      continue;
    case op_mul:
      BINOP(*);
      continue;
    case op_div:
      BINOP_CHECKZERO(/);
      continue;
    case op_mod:
      BINOP_CHECKZERO(%);
      continue;
    case op_shl:
#define SHIFTOP(OP, LEFT)                                                      \
  {                                                                            \
    TYPE_CHECK(Any, UInt);                                                     \
    uint64_t y = data.Pop<uint64_t>();                                         \
    if (y > 64)                                                                \
      return error("shift out of bounds");                                     \
    if (std::holds_alternative<uint64_t>(data.back())) {                       \
      uint64_t x = data.Pop<uint64_t>();                                       \
      data.Push(x OP y);                                                       \
    } else if (std::holds_alternative<int64_t>(data.back())) {                 \
      int64_t x = data.Pop<int64_t>();                                         \
      if (x < 0 && LEFT)                                                       \
        return error("left shift of negative value");                          \
      if (y > 64)                                                              \
        return error("shift out of bounds");                                   \
      data.Push(x OP y);                                                       \
    } else if (std::holds_alternative<llvm::APSInt>(data.back())) {            \
      llvm::APSInt x = data.Pop<llvm::APSInt>();                               \
      if (y > x.getBitWidth())                                                 \
        return error("shift out of bounds");                                   \
      const llvm::APInt &bits = x;                                             \
      llvm::APInt shifted =                                                    \
          LEFT ? bits.shl((unsigned)y) : bits.lshr((unsigned)y);               \
      data.Push(llvm::APSInt(std::move(shifted), /*isUnsigned=*/false));       \
    } else                                                                     \
      return error("unsupported data types");                                  \
  }
      SHIFTOP(<<, true);
      continue;
    case op_shr:
      SHIFTOP(>>, false);
      continue;
    case op_and:
      BITOP(&);
      continue;
    case op_or:
      BITOP(|);
      continue;
    case op_xor:
      BITOP(^);
      continue;
    case op_not: {
      TYPE_CHECK(Any);
      auto x = data.PopAny();
      if (std::holds_alternative<uint64_t>(x))
        data.Push(~std::get<uint64_t>(x));
      else if (auto *ap = std::get_if<llvm::APSInt>(&x)) {
        llvm::APInt bits = ~static_cast<const llvm::APInt &>(*ap);
        data.Push(llvm::APSInt(std::move(bits), /*isUnsigned=*/false));
      } else
        return error("unsupported data types");
      continue;
    }
    case op_eq:
      CMPOP(==);
      continue;
    case op_neq:
      CMPOP(!=);
      continue;
    case op_lt:
      CMPOP(<);
      continue;
    case op_gt:
      CMPOP(>);
      continue;
    case op_le:
      CMPOP(<=);
      continue;
    case op_ge:
      CMPOP(>=);
      continue;
    case op_call: {
      TYPE_CHECK(Selector);
      Selectors sel = data.Pop<Selectors>();

      // Shorthand to improve readability.
#define POP_VALOBJ(VALOBJ)                                                     \
  auto VALOBJ = data.Pop<ValueObjectSP>();                                     \
  if (!VALOBJ)                                                                 \
    return error("null object");

      auto sel_error = [&](const char *msg) {
        return llvm::createStringErrorV("{0} (opcode={1}, selector={2})", msg,
                                        toString(opcode).c_str(),
                                        toString(sel).c_str());
      };

      switch (sel) {
      case sel_summary: {
        TYPE_CHECK(Object);
        POP_VALOBJ(valobj);
        const char *summary = valobj->GetSummaryAsCString();
        data.Push(summary ? std::string(valobj->GetSummaryAsCString())
                          : std::string());
        break;
      }
      case sel_get_num_children: {
        TYPE_CHECK(Object);
        POP_VALOBJ(valobj);
        auto result = valobj->GetNumChildren();
        if (!result)
          return result.takeError();
        data.Push((uint64_t)*result);
        break;
      }
      case sel_get_child_at_index: {
        TYPE_CHECK(Object, UInt);
        auto index = data.Pop<uint64_t>();
        POP_VALOBJ(valobj);
        data.Push(valobj->GetChildAtIndex(index));
        break;
      }
      case sel_get_child_with_name: {
        TYPE_CHECK(Object, String);
        auto name = data.Pop<std::string>();
        POP_VALOBJ(valobj);
        data.Push(valobj->GetChildMemberWithName(name));
        break;
      }
      case sel_get_child_index: {
        TYPE_CHECK(Object, String);
        auto name = data.Pop<std::string>();
        POP_VALOBJ(valobj);
        if (auto index_or_err = valobj->GetIndexOfChildWithName(name))
          data.Push((uint64_t)*index_or_err);
        else
          return index_or_err.takeError();
        break;
      }
      case sel_get_parent: {
        TYPE_CHECK(Object);
        POP_VALOBJ(valobj);
        auto *parent = valobj->GetParent();
        data.Push(parent ? parent->GetSP() : ValueObjectSP());
        break;
      }
      case sel_get_type: {
        TYPE_CHECK(Object);
        POP_VALOBJ(valobj);
        // FIXME: do we need to control dynamic type resolution?
        data.Push(valobj->GetTypeImpl().GetCompilerType(false));
        break;
      }
      case sel_get_template_argument_type: {
        TYPE_CHECK(Type, UInt);
        auto index = data.Pop<uint64_t>();
        auto type = data.Pop<CompilerType>();
        // FIXME: There is more code in SBType::GetTemplateArgumentType().
        data.Push(type.GetTypeTemplateArgument(index, true));
        break;
      }
      case sel_get_synthetic_value: {
        TYPE_CHECK(Object);
        POP_VALOBJ(valobj);
        data.Push(valobj->GetSyntheticValue());
        break;
      }
      case sel_get_non_synthetic_value: {
        TYPE_CHECK(Object);
        POP_VALOBJ(valobj);
        data.Push(valobj->GetNonSyntheticValue());
        break;
      }
      case sel_get_value: {
        TYPE_CHECK(Object);
        POP_VALOBJ(valobj);
        data.Push(std::string(valobj->GetValueAsCString()));
        break;
      }
      case sel_get_value_as_unsigned: {
        TYPE_CHECK(Object);
        POP_VALOBJ(valobj);
        bool success;
        uint64_t val = valobj->GetValueAsUnsigned(0, &success);
        data.Push(val);
        if (!success)
          return sel_error("failed to get value");
        break;
      }
      case sel_get_value_as_signed: {
        TYPE_CHECK(Object);
        POP_VALOBJ(valobj);
        bool success;
        int64_t val = valobj->GetValueAsSigned(0, &success);
        data.Push(val);
        if (!success)
          return sel_error("failed to get value");
        break;
      }
      case sel_get_value_as_address: {
        TYPE_CHECK(Object);
        POP_VALOBJ(valobj);
        bool success;
        uint64_t addr = valobj->GetValueAsUnsigned(0, &success);
        if (!success)
          return sel_error("failed to get value");
        if (auto process_sp = valobj->GetProcessSP())
          addr = process_sp->FixDataAddress(addr);
        data.Push(addr);
        break;
      }
      case sel_cast: {
        TYPE_CHECK(Object, Type);
        auto type = data.Pop<CompilerType>();
        POP_VALOBJ(valobj);
        data.Push(valobj->Cast(type));
        break;
      }
      case sel_clone: {
        TYPE_CHECK(Object, String);
        auto new_name = data.Pop<std::string>();
        POP_VALOBJ(valobj);
        data.Push(valobj->Clone(new_name));
        break;
      }
      case sel_strlen: {
        TYPE_CHECK(String);
        data.Push((uint64_t)data.Pop<std::string>().size());
        break;
      }
      case sel_fmt: {
        TYPE_CHECK(String);
        if (auto error = FormatImpl(data))
          return error;
        break;
      }
      default:
        return sel_error("selector not implemented");
      }
      continue;
    }
    }
    return error("opcode not implemented");
  }
  return pc.takeError();
}
} // namespace FormatterBytecode

} // namespace lldb_private
