//===-- IRInterpreter.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/Expression/IRInterpreter.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Policy.h"
#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/ValueObject/ValueObject.h"

#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/Support/raw_ostream.h"

#include <map>

using namespace llvm;
using lldb_private::LLDBLog;

static std::string PrintValue(const Value *value, bool truncate = false) {
  std::string s;
  raw_string_ostream rso(s);
  value->print(rso);
  if (truncate)
    s.resize(s.length() - 1);

  size_t offset;
  while ((offset = s.find('\n')) != s.npos)
    s.erase(offset, 1);
  while (s[0] == ' ' || s[0] == '\t')
    s.erase(0, 1);

  return s;
}

static std::string PrintType(const Type *type, bool truncate = false) {
  std::string s;
  raw_string_ostream rso(s);
  type->print(rso);
  if (truncate)
    s.resize(s.length() - 1);
  return s;
}

static bool CanIgnoreCall(const CallInst *call) {
  const llvm::Function *called_function = call->getCalledFunction();

  if (!called_function)
    return false;

  if (called_function->isIntrinsic()) {
    switch (called_function->getIntrinsicID()) {
    default:
      break;
    case llvm::Intrinsic::dbg_declare:
    case llvm::Intrinsic::dbg_value:
      return true;
    }
  }

  return false;
}

class InterpreterStackFrame {
public:
  typedef std::map<const Value *, lldb::addr_t> ValueMap;

  ValueMap m_values;
  const DataLayout &m_target_data;
  lldb_private::IRExecutionUnit &m_execution_unit;
  const BasicBlock *m_bb = nullptr;
  const BasicBlock *m_prev_bb = nullptr;
  BasicBlock::const_iterator m_ii;
  BasicBlock::const_iterator m_ie;

  lldb::addr_t m_frame_process_address;
  size_t m_frame_size;
  lldb::addr_t m_stack_pointer;

  lldb::ByteOrder m_byte_order;
  size_t m_addr_byte_size;

  InterpreterStackFrame(const DataLayout &target_data,
                        lldb_private::IRExecutionUnit &execution_unit,
                        lldb::addr_t stack_frame_bottom,
                        lldb::addr_t stack_frame_top)
      : m_target_data(target_data), m_execution_unit(execution_unit) {
    m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle
                                                 : lldb::eByteOrderBig);
    m_addr_byte_size = (target_data.getPointerSize(0));

    m_frame_process_address = stack_frame_bottom;
    m_frame_size = stack_frame_top - stack_frame_bottom;
    m_stack_pointer = stack_frame_top;
  }

  ~InterpreterStackFrame() = default;

  void Jump(const BasicBlock *bb) {
    m_prev_bb = m_bb;
    m_bb = bb;
    m_ii = m_bb->begin();
    m_ie = m_bb->end();
  }

  std::string SummarizeValue(const Value *value) {
    lldb_private::StreamString ss;

    ss.PutCString(PrintValue(value).c_str());

    ValueMap::iterator i = m_values.find(value);

    if (i != m_values.end()) {
      lldb::addr_t addr = i->second;

      ss.Printf(" 0x%llx", (unsigned long long)addr);
    }

    return std::string(ss.GetString());
  }

  bool AssignToMatchType(lldb_private::Scalar &scalar, llvm::APInt value,
                         Type *type) {
    size_t type_size = m_target_data.getTypeStoreSize(type);

    if (type_size > 8)
      return false;

    if (type_size != 1)
      type_size = PowerOf2Ceil(type_size);

    scalar = value.zextOrTrunc(type_size * 8);
    return true;
  }

  bool EvaluateValue(lldb_private::Scalar &scalar, const Value *value,
                     Module &module) {
    const Constant *constant = dyn_cast<Constant>(value);

    if (constant) {
      if (constant->getValueID() == Value::ConstantFPVal) {
        if (auto *cfp = dyn_cast<ConstantFP>(constant)) {
          if (cfp->getType()->isDoubleTy())
            scalar = cfp->getValueAPF().convertToDouble();
          else if (cfp->getType()->isFloatTy())
            scalar = cfp->getValueAPF().convertToFloat();
          else
            return false;
          return true;
        }
        return false;
      }
      APInt value_apint;

      if (!ResolveConstantValue(value_apint, constant))
        return false;

      return AssignToMatchType(scalar, value_apint, value->getType());
    }

    lldb::addr_t process_address = ResolveValue(value, module);
    size_t value_size = m_target_data.getTypeStoreSize(value->getType());

    lldb_private::DataExtractor value_extractor;
    lldb_private::Status extract_error;

    m_execution_unit.GetMemoryData(value_extractor, process_address,
                                   value_size, extract_error);

    if (!extract_error.Success())
      return false;

    lldb::offset_t offset = 0;
    if (value_size <= 8) {
      Type *ty = value->getType();
      if (ty->isDoubleTy()) {
        scalar = value_extractor.GetDouble(&offset);
        return true;
      } else if (ty->isFloatTy()) {
        scalar = value_extractor.GetFloat(&offset);
        return true;
      } else {
        uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size);
        return AssignToMatchType(scalar, llvm::APInt(64, u64value),
                                 value->getType());
      }
    }

    return false;
  }

  bool AssignValue(const Value *value, lldb_private::Scalar scalar,
                   Module &module) {
    lldb::addr_t process_address = ResolveValue(value, module);

    if (process_address == LLDB_INVALID_ADDRESS)
      return false;

    lldb_private::Scalar cast_scalar;
    Type *vty = value->getType();
    if (vty->isFloatTy() || vty->isDoubleTy()) {
      cast_scalar = scalar;
    } else {
      scalar.MakeUnsigned();
      if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()),
                             value->getType()))
        return false;
    }

    size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType());

    lldb_private::DataBufferHeap buf(value_byte_size, 0);

    lldb_private::Status get_data_error;

    if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(),
                                     m_byte_order, get_data_error))
      return false;

    lldb_private::Status write_error;

    m_execution_unit.WriteMemory(process_address, buf.GetBytes(),
                                 buf.GetByteSize(), write_error);

    return write_error.Success();
  }

  bool ResolveConstantValue(APInt &value, const Constant *constant) {
    switch (constant->getValueID()) {
    default:
      break;
    case Value::FunctionVal:
      if (const Function *constant_func = dyn_cast<Function>(constant)) {
        lldb_private::ConstString name(
            llvm::GlobalValue::dropLLVMManglingEscape(
                constant_func->getName()));
        bool missing_weak = false;
        lldb::addr_t addr = m_execution_unit.FindSymbol(name, missing_weak);
        if (addr == LLDB_INVALID_ADDRESS)
          return false;
        // A resolved symbol address may be wider than a target pointer when we
        // store extra information in the high bits, such as an address-space
        // tag. Truncate to the pointer width rather than asserting. When the
        // address already fits this is a no-op.
        value = APInt(m_target_data.getPointerSizeInBits(), addr,
                      /*isSigned=*/false, /*implicitTrunc=*/true);
        return true;
      }
      break;
    case Value::ConstantIntVal:
      if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant)) {
        value = constant_int->getValue();
        return true;
      }
      break;
    case Value::ConstantFPVal:
      if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant)) {
        value = constant_fp->getValueAPF().bitcastToAPInt();
        return true;
      }
      break;
    case Value::ConstantExprVal:
      if (const ConstantExpr *constant_expr =
              dyn_cast<ConstantExpr>(constant)) {
        switch (constant_expr->getOpcode()) {
        default:
          return false;
        case Instruction::IntToPtr:
        case Instruction::PtrToInt:
        case Instruction::BitCast:
          return ResolveConstantValue(value, constant_expr->getOperand(0));
        case Instruction::GetElementPtr: {
          ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
          ConstantExpr::const_op_iterator op_end = constant_expr->op_end();

          Constant *base = dyn_cast<Constant>(*op_cursor);

          if (!base)
            return false;

          if (!ResolveConstantValue(value, base))
            return false;

          op_cursor++;

          if (op_cursor == op_end)
            return true; // no offset to apply!

          SmallVector<Value *, 8> indices(op_cursor, op_end);
          Type *src_elem_ty =
              cast<GEPOperator>(constant_expr)->getSourceElementType();

          // DataLayout::getIndexedOffsetInType assumes the indices are
          // instances of ConstantInt.
          uint64_t offset =
              m_target_data.getIndexedOffsetInType(src_elem_ty, indices);

          const bool is_signed = true;
          value += APInt(value.getBitWidth(), offset, is_signed);

          return true;
        }
        }
      }
      break;
    case Value::ConstantPointerNullVal:
      if (isa<ConstantPointerNull>(constant)) {
        value = APInt(m_target_data.getPointerSizeInBits(), 0);
        return true;
      }
      break;
    }
    return false;
  }

  bool MakeArgument(const Argument *value, uint64_t address) {
    lldb::addr_t data_address = Malloc(value->getType());

    if (data_address == LLDB_INVALID_ADDRESS)
      return false;

    lldb_private::Status write_error;

    m_execution_unit.WritePointerToMemory(data_address, address, write_error);

    if (!write_error.Success()) {
      lldb_private::Status free_error;
      m_execution_unit.Free(data_address, free_error);
      return false;
    }

    m_values[value] = data_address;

    lldb_private::Log *log(GetLog(LLDBLog::Expressions));

    LLDB_LOGF(log, "Made an allocation for argument %s",
              PrintValue(value).c_str());
    LLDB_LOGF(log, "  Data region    : %llx", (unsigned long long)address);
    LLDB_LOGF(log, "  Ref region     : %llx", (unsigned long long)data_address);

    return true;
  }

  bool ResolveConstant(lldb::addr_t process_address, const Constant *constant) {
    APInt resolved_value;

    if (!ResolveConstantValue(resolved_value, constant))
      return false;

    size_t constant_size = m_target_data.getTypeStoreSize(constant->getType());
    lldb_private::DataBufferHeap buf(constant_size, 0);

    lldb_private::Status get_data_error;

    lldb_private::Scalar resolved_scalar(
        resolved_value.zextOrTrunc(llvm::NextPowerOf2(constant_size) * 8));
    if (!resolved_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(),
                                         m_byte_order, get_data_error))
      return false;

    lldb_private::Status write_error;

    m_execution_unit.WriteMemory(process_address, buf.GetBytes(),
                                 buf.GetByteSize(), write_error);

    return write_error.Success();
  }

  lldb::addr_t Malloc(size_t size, uint8_t byte_alignment) {
    lldb::addr_t ret = m_stack_pointer;

    ret -= size;
    ret -= (ret % byte_alignment);

    if (ret < m_frame_process_address)
      return LLDB_INVALID_ADDRESS;

    m_stack_pointer = ret;
    return ret;
  }

  lldb::addr_t Malloc(llvm::Type *type) {
    lldb_private::Status alloc_error;

    return Malloc(m_target_data.getTypeAllocSize(type),
                  m_target_data.getPrefTypeAlign(type).value());
  }

  std::string PrintData(lldb::addr_t addr, llvm::Type *type) {
    size_t length = m_target_data.getTypeStoreSize(type);

    lldb_private::DataBufferHeap buf(length, 0);

    lldb_private::Status read_error;

    m_execution_unit.ReadMemory(buf.GetBytes(), addr, length, read_error);

    if (!read_error.Success())
      return std::string("<couldn't read data>");

    lldb_private::StreamString ss;

    for (size_t i = 0; i < length; i++) {
      if ((!(i & 0xf)) && i)
        ss.Printf("%02hhx - ", buf.GetBytes()[i]);
      else
        ss.Printf("%02hhx ", buf.GetBytes()[i]);
    }

    return std::string(ss.GetString());
  }

  lldb::addr_t ResolveValue(const Value *value, Module &module) {
    ValueMap::iterator i = m_values.find(value);

    if (i != m_values.end())
      return i->second;

    // Fall back and allocate space [allocation type Alloca]

    lldb::addr_t data_address = Malloc(value->getType());

    if (const Constant *constant = dyn_cast<Constant>(value)) {
      if (!ResolveConstant(data_address, constant)) {
        lldb_private::Status free_error;
        m_execution_unit.Free(data_address, free_error);
        return LLDB_INVALID_ADDRESS;
      }
    }

    m_values[value] = data_address;
    return data_address;
  }
};

static const char *unsupported_opcode_error =
    "Interpreter doesn't handle one of the expression's opcodes";
static const char *unsupported_operand_error =
    "Interpreter doesn't handle one of the expression's operands";
static const char *interpreter_internal_error =
    "Interpreter encountered an internal error";
static const char *interrupt_error =
    "Interrupted while interpreting expression";
static const char *bad_value_error =
    "Interpreter couldn't resolve a value during execution";
static const char *memory_allocation_error =
    "Interpreter couldn't allocate memory";
static const char *memory_write_error = "Interpreter couldn't write to memory";
static const char *memory_read_error = "Interpreter couldn't read from memory";
static const char *timeout_error =
    "Reached timeout while interpreting expression";
static const char *too_many_functions_error =
    "Interpreter doesn't handle modules with multiple function bodies.";

static bool CanResolveConstant(llvm::Constant *constant) {
  switch (constant->getValueID()) {
  default:
    return false;
  case Value::ConstantIntVal:
  case Value::ConstantFPVal:
  case Value::FunctionVal:
    return true;
  case Value::ConstantExprVal:
    if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) {
      switch (constant_expr->getOpcode()) {
      default:
        return false;
      case Instruction::IntToPtr:
      case Instruction::PtrToInt:
      case Instruction::BitCast:
        return CanResolveConstant(constant_expr->getOperand(0));
      case Instruction::GetElementPtr: {
        // Check that the base can be constant-resolved.
        ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
        Constant *base = dyn_cast<Constant>(*op_cursor);
        if (!base || !CanResolveConstant(base))
          return false;

        // Check that all other operands are just ConstantInt.
        for (Value *op : make_range(constant_expr->op_begin() + 1,
                                    constant_expr->op_end())) {
          ConstantInt *constant_int = dyn_cast<ConstantInt>(op);
          if (!constant_int)
            return false;
        }
        return true;
      }
      }
    } else {
      return false;
    }
  case Value::ConstantPointerNullVal:
    return true;
  }
}

bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
                                 lldb_private::Status &error,
                                 const bool support_function_calls) {
  lldb_private::Log *log(GetLog(LLDBLog::Expressions));

  bool saw_function_with_body = false;
  for (Function &f : module) {
    if (f.begin() != f.end()) {
      if (saw_function_with_body) {
        LLDB_LOGF(log, "More than one function in the module has a body");
        error = lldb_private::Status::FromErrorString(too_many_functions_error);
        return false;
      }
      saw_function_with_body = true;
      LLDB_LOGF(log, "Saw function with body: %s", f.getName().str().c_str());
    }
  }

  for (BasicBlock &bb : function) {
    for (Instruction &ii : bb) {
      switch (ii.getOpcode()) {
      default: {
        LLDB_LOGF(log, "Unsupported instruction: %s", PrintValue(&ii).c_str());
        error = lldb_private::Status::FromErrorString(unsupported_opcode_error);
        return false;
      }
      case Instruction::Add:
      case Instruction::Alloca:
      case Instruction::BitCast:
      case Instruction::UncondBr:
      case Instruction::CondBr:
      case Instruction::PHI:
        break;
      case Instruction::Call: {
        CallInst *call_inst = dyn_cast<CallInst>(&ii);

        if (!call_inst) {
          error =
              lldb_private::Status::FromErrorString(interpreter_internal_error);
          return false;
        }

        if (!CanIgnoreCall(call_inst) && !support_function_calls) {
          LLDB_LOGF(log, "Unsupported instruction: %s",
                    PrintValue(&ii).c_str());
          error =
              lldb_private::Status::FromErrorString(unsupported_opcode_error);
          return false;
        }
      } break;
      case Instruction::GetElementPtr:
        break;
      case Instruction::FCmp:
      case Instruction::ICmp: {
        CmpInst *cmp_inst = dyn_cast<CmpInst>(&ii);

        if (!cmp_inst) {
          error =
              lldb_private::Status::FromErrorString(interpreter_internal_error);
          return false;
        }

        switch (cmp_inst->getPredicate()) {
        default: {
          LLDB_LOGF(log, "Unsupported ICmp predicate: %s",
                    PrintValue(&ii).c_str());

          error =
              lldb_private::Status::FromErrorString(unsupported_opcode_error);
          return false;
        }
        case CmpInst::FCMP_OEQ:
        case CmpInst::ICMP_EQ:
        case CmpInst::FCMP_UNE:
        case CmpInst::ICMP_NE:
        case CmpInst::FCMP_OGT:
        case CmpInst::ICMP_UGT:
        case CmpInst::FCMP_OGE:
        case CmpInst::ICMP_UGE:
        case CmpInst::FCMP_OLT:
        case CmpInst::ICMP_ULT:
        case CmpInst::FCMP_OLE:
        case CmpInst::ICMP_ULE:
        case CmpInst::ICMP_SGT:
        case CmpInst::ICMP_SGE:
        case CmpInst::ICMP_SLT:
        case CmpInst::ICMP_SLE:
          break;
        }
      } break;
      case Instruction::And:
      case Instruction::AShr:
      case Instruction::FPToUI:
      case Instruction::FPToSI:
      case Instruction::IntToPtr:
      case Instruction::PtrToInt:
      case Instruction::Load:
      case Instruction::LShr:
      case Instruction::Mul:
      case Instruction::Or:
      case Instruction::Ret:
      case Instruction::SDiv:
      case Instruction::SExt:
      case Instruction::Shl:
      case Instruction::SRem:
      case Instruction::Store:
      case Instruction::Sub:
      case Instruction::Trunc:
      case Instruction::UDiv:
      case Instruction::URem:
      case Instruction::Xor:
      case Instruction::ZExt:
        break;
      case Instruction::FAdd:
      case Instruction::FSub:
      case Instruction::FMul:
      case Instruction::FDiv:
        break;
      case Instruction::UIToFP:
      case Instruction::SIToFP:
      case Instruction::FPTrunc:
      case Instruction::FPExt:
        if (!ii.getType()->isFloatTy() && !ii.getType()->isDoubleTy()) {
          LLDB_LOGF(log, "Unsupported instruction: %s",
                    PrintValue(&ii).c_str());
          error =
              lldb_private::Status::FromErrorString(unsupported_opcode_error);
          return false;
        }
        break;
      }

      for (unsigned oi = 0, oe = ii.getNumOperands(); oi != oe; ++oi) {
        Value *operand = ii.getOperand(oi);
        Type *operand_type = operand->getType();

        switch (operand_type->getTypeID()) {
        default:
          break;
        case Type::FixedVectorTyID:
        case Type::ScalableVectorTyID: {
          LLDB_LOGF(log, "Unsupported operand type: %s",
                    PrintType(operand_type).c_str());
          error =
              lldb_private::Status::FromErrorString(unsupported_operand_error);
          return false;
        }
        }

        // The IR interpreter currently doesn't know about
        // 128-bit integers. As they're not that frequent,
        // we can just fall back to the JIT rather than
        // choking.
        if (operand_type->getPrimitiveSizeInBits() > 64) {
          LLDB_LOGF(log, "Unsupported operand type: %s",
                    PrintType(operand_type).c_str());
          error =
              lldb_private::Status::FromErrorString(unsupported_operand_error);
          return false;
        }

        if (Constant *constant = llvm::dyn_cast<Constant>(operand)) {
          if (!CanResolveConstant(constant)) {
            LLDB_LOGF(log, "Unsupported constant: %s",
                      PrintValue(constant).c_str());
            error = lldb_private::Status::FromErrorString(
                unsupported_operand_error);
            return false;
          }
        }
      }
    }
  }

  return true;
}

bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
                              llvm::ArrayRef<lldb::addr_t> args,
                              lldb_private::IRExecutionUnit &execution_unit,
                              lldb_private::Status &error,
                              lldb::addr_t stack_frame_bottom,
                              lldb::addr_t stack_frame_top,
                              lldb_private::ExecutionContext &exe_ctx,
                              lldb_private::Timeout<std::micro> timeout) {
  lldb_private::Log *log(GetLog(LLDBLog::Expressions));

  if (log) {
    std::string s;
    raw_string_ostream oss(s);

    module.print(oss, nullptr);

    LLDB_LOGF(log, "Module as passed in to IRInterpreter::Interpret: \n\"%s\"",
              s.c_str());
  }

  const DataLayout &data_layout = module.getDataLayout();

  InterpreterStackFrame frame(data_layout, execution_unit, stack_frame_bottom,
                              stack_frame_top);

  if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS) {
    error =
        lldb_private::Status::FromErrorString("Couldn't allocate stack frame");
  }

  int arg_index = 0;

  for (llvm::Function::arg_iterator ai = function.arg_begin(),
                                    ae = function.arg_end();
       ai != ae; ++ai, ++arg_index) {
    if (args.size() <= static_cast<size_t>(arg_index)) {
      error = lldb_private::Status::FromErrorString(
          "Not enough arguments passed in to function");
      return false;
    }

    lldb::addr_t ptr = args[arg_index];

    frame.MakeArgument(&*ai, ptr);
  }

  frame.Jump(&function.front());

  lldb_private::Process *process = exe_ctx.GetProcessPtr();
  lldb_private::Target *target = exe_ctx.GetTargetPtr();

  using clock = std::chrono::steady_clock;

  // Compute the time at which the timeout has been exceeded.
  std::optional<clock::time_point> end_time;
  if (timeout && timeout->count() > 0)
    end_time = clock::now() + *timeout;

  while (frame.m_ii != frame.m_ie) {
    // Timeout reached: stop interpreting.
    if (end_time && clock::now() >= *end_time) {
      error = lldb_private::Status::FromErrorString(timeout_error);
      return false;
    }

    // If we have access to the debugger we can honor an interrupt request.
    if (target) {
      if (INTERRUPT_REQUESTED(target->GetDebugger(),
                              "Interrupted in IR interpreting.")) {
        error = lldb_private::Status::FromErrorString(interrupt_error);
        return false;
      }
    }

    const Instruction *inst = &*frame.m_ii;

    LLDB_LOGF(log, "Interpreting %s", PrintValue(inst).c_str());

    switch (inst->getOpcode()) {
    default:
      break;

    case Instruction::Add:
    case Instruction::Sub:
    case Instruction::Mul:
    case Instruction::SDiv:
    case Instruction::UDiv:
    case Instruction::SRem:
    case Instruction::URem:
    case Instruction::Shl:
    case Instruction::LShr:
    case Instruction::AShr:
    case Instruction::And:
    case Instruction::Or:
    case Instruction::Xor:
    case Instruction::FAdd:
    case Instruction::FSub:
    case Instruction::FMul:
    case Instruction::FDiv: {
      const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst);

      if (!bin_op) {
        LLDB_LOGF(
            log,
            "getOpcode() returns %s, but instruction is not a BinaryOperator",
            inst->getOpcodeName());
        error =
            lldb_private::Status::FromErrorString(interpreter_internal_error);
        return false;
      }

      Value *lhs = inst->getOperand(0);
      Value *rhs = inst->getOperand(1);

      lldb_private::Scalar L;
      lldb_private::Scalar R;

      if (!frame.EvaluateValue(L, lhs, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(lhs).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      if (!frame.EvaluateValue(R, rhs, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(rhs).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      lldb_private::Scalar result;

      switch (inst->getOpcode()) {
      default:
        break;
      case Instruction::Add:
      case Instruction::FAdd:
        result = L + R;
        break;
      case Instruction::Mul:
      case Instruction::FMul:
        result = L * R;
        break;
      case Instruction::Sub:
      case Instruction::FSub:
        result = L - R;
        break;
      case Instruction::SDiv:
        L.MakeSigned();
        R.MakeSigned();
        result = L / R;
        break;
      case Instruction::UDiv:
        L.MakeUnsigned();
        R.MakeUnsigned();
        result = L / R;
        break;
      case Instruction::FDiv:
        result = L / R;
        break;
      case Instruction::SRem:
        L.MakeSigned();
        R.MakeSigned();
        result = L % R;
        break;
      case Instruction::URem:
        L.MakeUnsigned();
        R.MakeUnsigned();
        result = L % R;
        break;
      case Instruction::Shl:
        result = L << R;
        break;
      case Instruction::AShr:
        result = L >> R;
        break;
      case Instruction::LShr:
        result = L;
        result.ShiftRightLogical(R);
        break;
      case Instruction::And:
        result = L & R;
        break;
      case Instruction::Or:
        result = L | R;
        break;
      case Instruction::Xor:
        result = L ^ R;
        break;
      }

      frame.AssignValue(inst, result, module);

      LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName());
      LLDB_LOGF(log, "  L : %s", frame.SummarizeValue(lhs).c_str());
      LLDB_LOGF(log, "  R : %s", frame.SummarizeValue(rhs).c_str());
      LLDB_LOGF(log, "  = : %s", frame.SummarizeValue(inst).c_str());
    } break;
    case Instruction::Alloca: {
      const AllocaInst *alloca_inst = cast<AllocaInst>(inst);

      std::optional<TypeSize> alloca_size =
          alloca_inst->getAllocationSize(frame.m_target_data);
      if (!alloca_size || alloca_size->isScalable()) {
        LLDB_LOGF(log, "AllocaInsts are not handled if size is not computable");
        error = lldb_private::Status::FromErrorString(unsupported_opcode_error);
        return false;
      }

      // The semantics of Alloca are:
      //   Create a region R of virtual memory of type T, backed by a data
      //   buffer
      //   Create a region P of virtual memory of type T*, backed by a data
      //   buffer
      //   Write the virtual address of R into P

      Type *Tptr = alloca_inst->getType();

      lldb::addr_t R = frame.Malloc(alloca_size->getFixedValue(),
                                    alloca_inst->getAlign().value());

      if (R == LLDB_INVALID_ADDRESS) {
        LLDB_LOGF(log, "Couldn't allocate memory for an AllocaInst");
        error = lldb_private::Status::FromErrorString(memory_allocation_error);
        return false;
      }

      lldb::addr_t P = frame.Malloc(Tptr);

      if (P == LLDB_INVALID_ADDRESS) {
        LLDB_LOGF(log,
                  "Couldn't allocate the result pointer for an AllocaInst");
        error = lldb_private::Status::FromErrorString(memory_allocation_error);
        return false;
      }

      lldb_private::Status write_error;

      execution_unit.WritePointerToMemory(P, R, write_error);

      if (!write_error.Success()) {
        LLDB_LOGF(log, "Couldn't write the result pointer for an AllocaInst");
        error = lldb_private::Status::FromErrorString(memory_write_error);
        lldb_private::Status free_error;
        execution_unit.Free(P, free_error);
        execution_unit.Free(R, free_error);
        return false;
      }

      frame.m_values[alloca_inst] = P;

      LLDB_LOGF(log, "Interpreted an AllocaInst");
      LLDB_LOGF(log, "  R : 0x%" PRIx64, R);
      LLDB_LOGF(log, "  P : 0x%" PRIx64, P);
    } break;
    case Instruction::BitCast:
    case Instruction::ZExt: {
      const CastInst *cast_inst = cast<CastInst>(inst);

      Value *source = cast_inst->getOperand(0);

      lldb_private::Scalar S;

      if (!frame.EvaluateValue(S, source, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(source).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      frame.AssignValue(inst, S, module);
    } break;
    case Instruction::SExt: {
      const CastInst *cast_inst = cast<CastInst>(inst);

      Value *source = cast_inst->getOperand(0);

      lldb_private::Scalar S;

      if (!frame.EvaluateValue(S, source, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(source).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      S.MakeSigned();

      lldb_private::Scalar S_signextend(S.SLongLong());

      frame.AssignValue(inst, S_signextend, module);
    } break;
    case Instruction::UncondBr:
      frame.Jump(cast<UncondBrInst>(inst)->getSuccessor());
      LLDB_LOGF(log, "Interpreted an UncondBrInst");
      continue;
    case Instruction::CondBr: {
      const CondBrInst *br_inst = cast<CondBrInst>(inst);

      Value *condition = br_inst->getCondition();

      lldb_private::Scalar C;

      if (!frame.EvaluateValue(C, condition, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(condition).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      if (!C.IsZero())
        frame.Jump(br_inst->getSuccessor(0));
      else
        frame.Jump(br_inst->getSuccessor(1));

      LLDB_LOGF(log, "Interpreted a CondBrInst");
      LLDB_LOGF(log, "  cond : %s", frame.SummarizeValue(condition).c_str());
    }
      continue;
    case Instruction::PHI: {
      const PHINode *phi_inst = cast<PHINode>(inst);
      if (!frame.m_prev_bb) {
        LLDB_LOGF(log,
                  "Encountered PHI node without having jumped from another "
                  "basic block");
        error =
            lldb_private::Status::FromErrorString(interpreter_internal_error);
        return false;
      }

      Value *value = phi_inst->getIncomingValueForBlock(frame.m_prev_bb);
      lldb_private::Scalar result;
      if (!frame.EvaluateValue(result, value, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(value).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }
      frame.AssignValue(inst, result, module);

      LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName());
      LLDB_LOGF(log, "  Incoming value : %s",
                frame.SummarizeValue(value).c_str());
    } break;
    case Instruction::GetElementPtr: {
      const GetElementPtrInst *gep_inst = cast<GetElementPtrInst>(inst);

      const Value *pointer_operand = gep_inst->getPointerOperand();
      Type *src_elem_ty = gep_inst->getSourceElementType();

      lldb_private::Scalar P;

      if (!frame.EvaluateValue(P, pointer_operand, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s",
                  PrintValue(pointer_operand).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      typedef SmallVector<Value *, 8> IndexVector;
      typedef IndexVector::iterator IndexIterator;

      SmallVector<Value *, 8> indices(gep_inst->idx_begin(),
                                      gep_inst->idx_end());

      SmallVector<Value *, 8> const_indices;

      for (IndexIterator ii = indices.begin(), ie = indices.end(); ii != ie;
           ++ii) {
        ConstantInt *constant_index = dyn_cast<ConstantInt>(*ii);

        if (!constant_index) {
          lldb_private::Scalar I;

          if (!frame.EvaluateValue(I, *ii, module)) {
            LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(*ii).c_str());
            error = lldb_private::Status::FromErrorString(bad_value_error);
            return false;
          }

          LLDB_LOGF(log, "Evaluated constant index %s as %llu",
                    PrintValue(*ii).c_str(), I.ULongLong(LLDB_INVALID_ADDRESS));

          constant_index = cast<ConstantInt>(ConstantInt::get(
              (*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS)));
        }

        const_indices.push_back(constant_index);
      }

      uint64_t offset =
          data_layout.getIndexedOffsetInType(src_elem_ty, const_indices);

      lldb_private::Scalar Poffset = P + offset;

      frame.AssignValue(inst, Poffset, module);

      LLDB_LOGF(log, "Interpreted a GetElementPtrInst");
      LLDB_LOGF(log, "  P       : %s",
                frame.SummarizeValue(pointer_operand).c_str());
      LLDB_LOGF(log, "  Poffset : %s", frame.SummarizeValue(inst).c_str());
    } break;
    case Instruction::FCmp:
    case Instruction::ICmp: {
      const CmpInst *icmp_inst = cast<CmpInst>(inst);

      CmpInst::Predicate predicate = icmp_inst->getPredicate();

      Value *lhs = inst->getOperand(0);
      Value *rhs = inst->getOperand(1);

      lldb_private::Scalar L;
      lldb_private::Scalar R;

      if (!frame.EvaluateValue(L, lhs, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(lhs).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      if (!frame.EvaluateValue(R, rhs, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(rhs).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      lldb_private::Scalar result;

      switch (predicate) {
      default:
        return false;
      case CmpInst::ICMP_EQ:
      case CmpInst::FCMP_OEQ:
        result = (L == R);
        break;
      case CmpInst::ICMP_NE:
      case CmpInst::FCMP_UNE:
        result = (L != R);
        break;
      case CmpInst::ICMP_UGT:
        L.MakeUnsigned();
        R.MakeUnsigned();
        result = (L > R);
        break;
      case CmpInst::ICMP_UGE:
        L.MakeUnsigned();
        R.MakeUnsigned();
        result = (L >= R);
        break;
      case CmpInst::FCMP_OGE:
        result = (L >= R);
        break;
      case CmpInst::FCMP_OGT:
        result = (L > R);
        break;
      case CmpInst::ICMP_ULT:
        L.MakeUnsigned();
        R.MakeUnsigned();
        result = (L < R);
        break;
      case CmpInst::FCMP_OLT:
        result = (L < R);
        break;
      case CmpInst::ICMP_ULE:
        L.MakeUnsigned();
        R.MakeUnsigned();
        result = (L <= R);
        break;
      case CmpInst::FCMP_OLE:
        result = (L <= R);
        break;
      case CmpInst::ICMP_SGT:
        L.MakeSigned();
        R.MakeSigned();
        result = (L > R);
        break;
      case CmpInst::ICMP_SGE:
        L.MakeSigned();
        R.MakeSigned();
        result = (L >= R);
        break;
      case CmpInst::ICMP_SLT:
        L.MakeSigned();
        R.MakeSigned();
        result = (L < R);
        break;
      case CmpInst::ICMP_SLE:
        L.MakeSigned();
        R.MakeSigned();
        result = (L <= R);
        break;
      }

      frame.AssignValue(inst, result, module);

      LLDB_LOGF(log, "Interpreted an ICmpInst");
      LLDB_LOGF(log, "  L : %s", frame.SummarizeValue(lhs).c_str());
      LLDB_LOGF(log, "  R : %s", frame.SummarizeValue(rhs).c_str());
      LLDB_LOGF(log, "  = : %s", frame.SummarizeValue(inst).c_str());
    } break;
    case Instruction::IntToPtr: {
      const IntToPtrInst *int_to_ptr_inst = cast<IntToPtrInst>(inst);

      Value *src_operand = int_to_ptr_inst->getOperand(0);

      lldb_private::Scalar I;

      if (!frame.EvaluateValue(I, src_operand, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      frame.AssignValue(inst, I, module);

      LLDB_LOGF(log, "Interpreted an IntToPtr");
      LLDB_LOGF(log, "  Src : %s", frame.SummarizeValue(src_operand).c_str());
      LLDB_LOGF(log, "  =   : %s", frame.SummarizeValue(inst).c_str());
    } break;
    case Instruction::PtrToInt: {
      const PtrToIntInst *ptr_to_int_inst = cast<PtrToIntInst>(inst);

      Value *src_operand = ptr_to_int_inst->getOperand(0);

      lldb_private::Scalar I;

      if (!frame.EvaluateValue(I, src_operand, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      frame.AssignValue(inst, I, module);

      LLDB_LOGF(log, "Interpreted a PtrToInt");
      LLDB_LOGF(log, "  Src : %s", frame.SummarizeValue(src_operand).c_str());
      LLDB_LOGF(log, "  =   : %s", frame.SummarizeValue(inst).c_str());
    } break;
    case Instruction::Trunc: {
      const TruncInst *trunc_inst = cast<TruncInst>(inst);

      Value *src_operand = trunc_inst->getOperand(0);

      lldb_private::Scalar I;

      if (!frame.EvaluateValue(I, src_operand, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      frame.AssignValue(inst, I, module);

      LLDB_LOGF(log, "Interpreted a Trunc");
      LLDB_LOGF(log, "  Src : %s", frame.SummarizeValue(src_operand).c_str());
      LLDB_LOGF(log, "  =   : %s", frame.SummarizeValue(inst).c_str());
    } break;
    case Instruction::FPToUI:
    case Instruction::FPToSI: {
      Value *src_operand = inst->getOperand(0);

      lldb_private::Scalar S;
      if (!frame.EvaluateValue(S, src_operand, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      assert(inst->getType()->isIntegerTy() && "Unexpected target type");
      llvm::APSInt result(inst->getType()->getIntegerBitWidth(),
                          /*isUnsigned=*/inst->getOpcode() ==
                              Instruction::FPToUI);
      assert(S.GetType() == lldb_private::Scalar::e_float &&
             "Unexpected source type");
      bool isExact;
      llvm::APFloatBase::opStatus status = S.GetAPFloat().convertToInteger(
          result, llvm::APFloat::rmTowardZero, &isExact);
      // Casting floating point values that are out of bounds of the target type
      // is undefined behaviour.
      if (status & llvm::APFloatBase::opInvalidOp) {
        std::string s;
        raw_string_ostream rso(s);
        rso << "Conversion error: " << S << " cannot be converted to ";
        if (inst->getOpcode() == Instruction::FPToUI)
          rso << "unsigned ";
        rso << *inst->getType();
        LLDB_LOGF(log, "%s", s.c_str());
        error = lldb_private::Status::FromErrorString(s.c_str());
        return false;
      }
      lldb_private::Scalar R(result);

      frame.AssignValue(inst, R, module);
      LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName());
      LLDB_LOGF(log, "  Src : %s", frame.SummarizeValue(src_operand).c_str());
      LLDB_LOGF(log, "  =   : %s", frame.SummarizeValue(inst).c_str());
    } break;
    case Instruction::UIToFP:
    case Instruction::SIToFP:
    case Instruction::FPTrunc:
    case Instruction::FPExt: {
      Value *src_operand = inst->getOperand(0);

      lldb_private::Scalar S;
      if (!frame.EvaluateValue(S, src_operand, module)) {
        LLDB_LOGF(log, "Couldn't evaluate %s", PrintValue(src_operand).c_str());
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }
      lldb_private::Scalar R;

      Type *result_type = inst->getType();
      assert(
          (result_type->isFloatTy() || result_type->isDoubleTy()) &&
          "Unsupported result type; CanInterpret() should have checked that");
      if (result_type->isFloatTy())
        R = S.Float();
      else
        R = S.Double();

      frame.AssignValue(inst, R, module);
      LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName());
      LLDB_LOGF(log, "  Src : %s", frame.SummarizeValue(src_operand).c_str());
      LLDB_LOGF(log, "  =   : %s", frame.SummarizeValue(inst).c_str());
    } break;
    case Instruction::Load: {
      const LoadInst *load_inst = cast<LoadInst>(inst);

      // The semantics of Load are:
      //   Create a region D that will contain the loaded data
      //   Resolve the region P containing a pointer
      //   Dereference P to get the region R that the data should be loaded from
      //   Transfer a unit of type type(D) from R to D

      const Value *pointer_operand = load_inst->getPointerOperand();

      lldb::addr_t D = frame.ResolveValue(load_inst, module);
      lldb::addr_t P = frame.ResolveValue(pointer_operand, module);

      if (D == LLDB_INVALID_ADDRESS) {
        LLDB_LOGF(log, "LoadInst's value doesn't resolve to anything");
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      if (P == LLDB_INVALID_ADDRESS) {
        LLDB_LOGF(log, "LoadInst's pointer doesn't resolve to anything");
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      lldb::addr_t R;
      lldb_private::Status read_error;
      execution_unit.ReadPointerFromMemory(&R, P, read_error);

      if (!read_error.Success()) {
        LLDB_LOGF(log, "Couldn't read the address to be loaded for a LoadInst");
        error = lldb_private::Status::FromErrorString(memory_read_error);
        return false;
      }

      Type *target_ty = load_inst->getType();
      size_t target_size = data_layout.getTypeStoreSize(target_ty);
      lldb_private::DataBufferHeap buffer(target_size, 0);

      read_error.Clear();
      execution_unit.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(),
                                read_error);
      if (!read_error.Success()) {
        LLDB_LOGF(log, "Couldn't read from a region on behalf of a LoadInst");
        error = lldb_private::Status::FromErrorString(memory_read_error);
        return false;
      }

      lldb_private::Status write_error;
      execution_unit.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(),
                                 write_error);
      if (!write_error.Success()) {
        LLDB_LOGF(log, "Couldn't write to a region on behalf of a LoadInst");
        error = lldb_private::Status::FromErrorString(memory_write_error);
        return false;
      }

      LLDB_LOGF(log, "Interpreted a LoadInst");
      LLDB_LOGF(log, "  P : 0x%" PRIx64, P);
      LLDB_LOGF(log, "  R : 0x%" PRIx64, R);
      LLDB_LOGF(log, "  D : 0x%" PRIx64, D);
    } break;
    case Instruction::Ret: {
      return true;
    }
    case Instruction::Store: {
      const StoreInst *store_inst = cast<StoreInst>(inst);

      // The semantics of Store are:
      //   Resolve the region D containing the data to be stored
      //   Resolve the region P containing a pointer
      //   Dereference P to get the region R that the data should be stored in
      //   Transfer a unit of type type(D) from D to R

      const Value *value_operand = store_inst->getValueOperand();
      const Value *pointer_operand = store_inst->getPointerOperand();

      lldb::addr_t D = frame.ResolveValue(value_operand, module);
      lldb::addr_t P = frame.ResolveValue(pointer_operand, module);

      if (D == LLDB_INVALID_ADDRESS) {
        LLDB_LOGF(log, "StoreInst's value doesn't resolve to anything");
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      if (P == LLDB_INVALID_ADDRESS) {
        LLDB_LOGF(log, "StoreInst's pointer doesn't resolve to anything");
        error = lldb_private::Status::FromErrorString(bad_value_error);
        return false;
      }

      lldb::addr_t R;
      lldb_private::Status read_error;
      execution_unit.ReadPointerFromMemory(&R, P, read_error);

      if (!read_error.Success()) {
        LLDB_LOGF(log, "Couldn't read the address to be loaded for a LoadInst");
        error = lldb_private::Status::FromErrorString(memory_read_error);
        return false;
      }

      Type *target_ty = value_operand->getType();
      size_t target_size = data_layout.getTypeStoreSize(target_ty);
      lldb_private::DataBufferHeap buffer(target_size, 0);

      read_error.Clear();
      execution_unit.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(),
                                read_error);
      if (!read_error.Success()) {
        LLDB_LOGF(log, "Couldn't read from a region on behalf of a StoreInst");
        error = lldb_private::Status::FromErrorString(memory_read_error);
        return false;
      }

      lldb_private::Status write_error;
      execution_unit.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(),
                                 write_error);
      if (!write_error.Success()) {
        LLDB_LOGF(log, "Couldn't write to a region on behalf of a StoreInst");
        error = lldb_private::Status::FromErrorString(memory_write_error);
        return false;
      }

      LLDB_LOGF(log, "Interpreted a StoreInst");
      LLDB_LOGF(log, "  D : 0x%" PRIx64, D);
      LLDB_LOGF(log, "  P : 0x%" PRIx64, P);
      LLDB_LOGF(log, "  R : 0x%" PRIx64, R);
    } break;
    case Instruction::Call: {
      const CallInst *call_inst = cast<CallInst>(inst);

      if (CanIgnoreCall(call_inst))
        break;

      // Get the return type
      llvm::Type *returnType = call_inst->getType();
      if (returnType == nullptr) {
        error = lldb_private::Status::FromErrorString(
            "unable to access return type");
        return false;
      }

      // Work with void, integer and pointer return types
      if (!returnType->isVoidTy() && !returnType->isIntegerTy() &&
          !returnType->isPointerTy()) {
        error = lldb_private::Status::FromErrorString(
            "return type is not supported");
        return false;
      }

      // Check we can actually get a thread
      if (exe_ctx.GetThreadPtr() == nullptr) {
        error =
            lldb_private::Status::FromErrorString("unable to acquire thread");
        return false;
      }

      // Make sure we have a valid process
      if (!process) {
        error =
            lldb_private::Status::FromErrorString("unable to get the process");
        return false;
      }

      // Find the address of the callee function
      lldb_private::Scalar I;
      const llvm::Value *val = call_inst->getCalledOperand();

      if (!frame.EvaluateValue(I, val, module)) {
        error = lldb_private::Status::FromErrorString(
            "unable to get address of function");
        return false;
      }
      lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS));

      lldb_private::DiagnosticManager diagnostics;
      lldb_private::EvaluateExpressionOptions options;

      llvm::FunctionType *prototype = call_inst->getFunctionType();

      // Find number of arguments
      const int numArgs = call_inst->arg_size();

      // We work with a fixed array of 16 arguments which is our upper limit
      static lldb_private::ABI::CallArgument rawArgs[16];
      if (numArgs >= 16) {
        error = lldb_private::Status::FromErrorString(
            "function takes too many arguments");
        return false;
      }

      // Push all function arguments to the argument list that will be passed
      // to the call function thread plan
      for (int i = 0; i < numArgs; i++) {
        // Get details of this argument
        llvm::Value *arg_op = call_inst->getArgOperand(i);
        llvm::Type *arg_ty = arg_op->getType();

        // Ensure that this argument is an supported type
        if (!arg_ty->isIntegerTy() && !arg_ty->isPointerTy()) {
          error = lldb_private::Status::FromErrorStringWithFormat(
              "argument %d must be integer type", i);
          return false;
        }

        // Extract the arguments value
        lldb_private::Scalar tmp_op = 0;
        if (!frame.EvaluateValue(tmp_op, arg_op, module)) {
          error = lldb_private::Status::FromErrorStringWithFormat(
              "unable to evaluate argument %d", i);
          return false;
        }

        // Check if this is a string literal or constant string pointer
        if (arg_ty->isPointerTy()) {
          lldb::addr_t addr = tmp_op.ULongLong();
          size_t dataSize = 0;

          bool Success = execution_unit.GetAllocSize(addr, dataSize);
          UNUSED_IF_ASSERT_DISABLED(Success);
          assert(Success &&
                 "unable to locate host data for transfer to device");
          // Create the required buffer
          rawArgs[i].size = dataSize;
          rawArgs[i].data_up.reset(new uint8_t[dataSize + 1]);

          // Read string from host memory
          execution_unit.ReadMemory(rawArgs[i].data_up.get(), addr, dataSize,
                                    error);
          assert(!error.Fail() &&
                 "we have failed to read the string from memory");

          // Add null terminator
          rawArgs[i].data_up[dataSize] = '\0';
          rawArgs[i].type = lldb_private::ABI::CallArgument::HostPointer;
        } else /* if ( arg_ty->isPointerTy() ) */
        {
          rawArgs[i].type = lldb_private::ABI::CallArgument::TargetValue;
          // Get argument size in bytes
          rawArgs[i].size = arg_ty->getIntegerBitWidth() / 8;
          // Push value into argument list for thread plan
          rawArgs[i].value = tmp_op.ULongLong();
        }
      }

      // Pack the arguments into an llvm::array
      llvm::ArrayRef<lldb_private::ABI::CallArgument> args(rawArgs, numArgs);

      // Setup a thread plan to call the target function
      lldb::ThreadPlanSP call_plan_sp(
          new lldb_private::ThreadPlanCallFunctionUsingABI(
              exe_ctx.GetThreadRef(), funcAddr, *prototype, *returnType, args,
              options));

      // Check if the plan is valid
      lldb_private::StreamString ss;
      if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) {
        error = lldb_private::Status::FromErrorStringWithFormat(
            "unable to make ThreadPlanCallFunctionUsingABI for 0x%llx",
            I.ULongLong());
        return false;
      }

      process->SetRunningUserExpression(true);

      lldb_private::PolicyStack::Guard expr_policy_guard =
          lldb_private::PolicyStack::Get().PushPublicStateRunningExpression();

      // Execute the actual function call thread plan
      lldb::ExpressionResults res =
          process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics);

      // Check that the thread plan completed successfully
      if (res != lldb::ExpressionResults::eExpressionCompleted) {
        error = lldb_private::Status::FromErrorString(
            "ThreadPlanCallFunctionUsingABI failed");
        return false;
      }

      process->SetRunningUserExpression(false);

      // Void return type
      if (returnType->isVoidTy()) {
        // Cant assign to void types, so we leave the frame untouched
      } else
          // Integer or pointer return type
          if (returnType->isIntegerTy() || returnType->isPointerTy()) {
        // Get the encapsulated return value
        lldb::ValueObjectSP retVal = call_plan_sp.get()->GetReturnValueObject();

        lldb_private::Scalar returnVal = -1;
        lldb_private::ValueObject *vobj = retVal.get();

        // Check if the return value is valid
        if (vobj == nullptr || !retVal) {
          error = lldb_private::Status::FromErrorString(
              "unable to get the return value");
          return false;
        }

        // Extract the return value as a integer
        lldb_private::Value &value = vobj->GetValue();
        returnVal = value.GetScalar();

        // Push the return value as the result
        frame.AssignValue(inst, returnVal, module);
      }
    } break;
    }

    ++frame.m_ii;
  }

  return false;
}
