//===-- DILEval.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/ValueObject/DILEval.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/ValueObject/DILAST.h"
#include "lldb/ValueObject/DILParser.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/ValueObject/ValueObjectRegister.h"
#include "lldb/ValueObject/ValueObjectVariable.h"
#include "llvm/Support/ErrorExtras.h"
#include "llvm/Support/FormatAdapters.h"
#include <memory>

namespace lldb_private::dil {

static CompilerType GetBasicType(lldb::TypeSystemSP type_system,
                                 lldb::BasicType basic_type) {
  if (type_system)
    return type_system.get()->GetBasicTypeFromAST(basic_type);

  return CompilerType();
}

static lldb::ValueObjectSP ArrayToPointerConversion(ValueObject &valobj,
                                                    ExecutionContextScope &ctx,
                                                    llvm::StringRef name) {
  uint64_t addr = valobj.GetLoadAddress();
  ExecutionContext exe_ctx;
  ctx.CalculateExecutionContext(exe_ctx);
  return ValueObject::CreateValueObjectFromAddress(
      name, addr, exe_ctx,
      valobj.GetCompilerType().GetArrayElementType(&ctx).GetPointerType(),
      /* do_deref */ false);
}

static llvm::Expected<lldb::TypeSystemSP> GetTypeSystemFromCU(StackFrame &ctx) {
  SymbolContext symbol_context =
      ctx.GetSymbolContext(lldb::eSymbolContextCompUnit);
  if (!symbol_context.comp_unit)
    return llvm::createStringErrorV("no compile unit for frame: {}",
                                    ctx.GetFunctionName());

  lldb::LanguageType language = symbol_context.comp_unit->GetLanguage();
  symbol_context = ctx.GetSymbolContext(lldb::eSymbolContextModule);
  return symbol_context.module_sp->GetTypeSystemForLanguage(language);
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::UnaryConversion(lldb::ValueObjectSP valobj, uint32_t location) {
  if (!valobj)
    return llvm::make_error<DILDiagnosticError>(m_expr, "invalid value object",
                                                location);
  llvm::Expected<lldb::TypeSystemSP> type_system =
      GetTypeSystemFromCU(m_stack_frame);
  if (!type_system)
    return type_system.takeError();

  CompilerType in_type = valobj->GetCompilerType();
  if (valobj->IsBitfield()) {
    // Promote bitfields. If `int` can represent the bitfield value, it is
    // converted to `int`. Otherwise, if `unsigned int` can represent it, it
    // is converted to `unsigned int`. Otherwise, it is treated as its
    // underlying type.
    uint32_t bitfield_size = valobj->GetBitfieldBitSize();
    // Some bitfields have undefined size (e.g. result of ternary operation).
    // The AST's `bitfield_size` of those is 0, and no promotion takes place.
    if (bitfield_size > 0 && in_type.IsInteger()) {
      CompilerType int_type = GetBasicType(*type_system, lldb::eBasicTypeInt);
      CompilerType uint_type =
          GetBasicType(*type_system, lldb::eBasicTypeUnsignedInt);
      llvm::Expected<uint64_t> int_bit_size =
          int_type.GetBitSize(&m_stack_frame);
      if (!int_bit_size)
        return int_bit_size.takeError();
      llvm::Expected<uint64_t> uint_bit_size =
          uint_type.GetBitSize(&m_stack_frame);
      if (!uint_bit_size)
        return uint_bit_size.takeError();
      if (bitfield_size < *int_bit_size ||
          (in_type.IsSigned() && bitfield_size == *int_bit_size))
        return valobj->CastToBasicType(int_type);
      if (bitfield_size <= *uint_bit_size)
        return valobj->CastToBasicType(uint_type);
      // Re-create as a const value with the same underlying type
      Scalar scalar;
      bool resolved = valobj->ResolveValue(scalar);
      if (!resolved)
        return llvm::createStringError("invalid scalar value");
      return ValueObject::CreateValueObjectFromScalar(m_stack_frame, scalar,
                                                      in_type, "result");
    }
  }

  if (in_type.IsArrayType())
    valobj = ArrayToPointerConversion(*valobj, m_stack_frame, "result");

  CompilerType promoted_type =
      valobj->GetCompilerType().GetPromotedIntegerType();
  if (promoted_type)
    return valobj->CastToBasicType(promoted_type);

  return valobj;
}

/// Basic types with a lower rank are converted to the basic type
/// with a higher rank.
static size_t ConversionRank(CompilerType type) {
  switch (type.GetCanonicalType().GetBasicTypeEnumeration()) {
  case lldb::eBasicTypeBool:
    return 1;
  case lldb::eBasicTypeChar:
  case lldb::eBasicTypeSignedChar:
  case lldb::eBasicTypeUnsignedChar:
    return 2;
  case lldb::eBasicTypeShort:
  case lldb::eBasicTypeUnsignedShort:
    return 3;
  case lldb::eBasicTypeInt:
  case lldb::eBasicTypeUnsignedInt:
    return 4;
  case lldb::eBasicTypeLong:
  case lldb::eBasicTypeUnsignedLong:
    return 5;
  case lldb::eBasicTypeLongLong:
  case lldb::eBasicTypeUnsignedLongLong:
    return 6;
  case lldb::eBasicTypeInt128:
  case lldb::eBasicTypeUnsignedInt128:
    return 7;
  case lldb::eBasicTypeHalf:
    return 8;
  case lldb::eBasicTypeFloat:
    return 9;
  case lldb::eBasicTypeDouble:
    return 10;
  case lldb::eBasicTypeLongDouble:
    return 11;
  default:
    break;
  }
  return 0;
}

static lldb::BasicType BasicTypeToUnsigned(lldb::BasicType basic_type) {
  switch (basic_type) {
  case lldb::eBasicTypeChar:
  case lldb::eBasicTypeSignedChar:
    return lldb::eBasicTypeUnsignedChar;
  case lldb::eBasicTypeShort:
    return lldb::eBasicTypeUnsignedShort;
  case lldb::eBasicTypeInt:
    return lldb::eBasicTypeUnsignedInt;
  case lldb::eBasicTypeLong:
    return lldb::eBasicTypeUnsignedLong;
  case lldb::eBasicTypeLongLong:
    return lldb::eBasicTypeUnsignedLongLong;
  case lldb::eBasicTypeInt128:
    return lldb::eBasicTypeUnsignedInt128;
  default:
    return basic_type;
  }
}

llvm::Expected<CompilerType>
Interpreter::PromoteSignedInteger(CompilerType &lhs_type,
                                  CompilerType &rhs_type) {
  assert(lhs_type.IsInteger() && rhs_type.IsInteger());
  if (!lhs_type.IsSigned() && rhs_type.IsSigned()) {
    llvm::Expected<uint64_t> lhs_size = lhs_type.GetBitSize(&m_stack_frame);
    if (!lhs_size)
      return lhs_size.takeError();
    llvm::Expected<uint64_t> rhs_size = rhs_type.GetBitSize(&m_stack_frame);
    if (!rhs_size)
      return rhs_size.takeError();

    if (*rhs_size == *lhs_size) {
      llvm::Expected<lldb::TypeSystemSP> type_system =
          GetTypeSystemFromCU(m_stack_frame);
      if (!type_system)
        return type_system.takeError();
      CompilerType r_type_unsigned = GetBasicType(
          *type_system,
          BasicTypeToUnsigned(
              rhs_type.GetCanonicalType().GetBasicTypeEnumeration()));
      return r_type_unsigned;
    }
  }
  return rhs_type;
}

llvm::Expected<CompilerType>
Interpreter::ArithmeticConversion(lldb::ValueObjectSP &lhs,
                                  lldb::ValueObjectSP &rhs, uint32_t location) {
  // Apply unary conversion for both operands.
  auto lhs_or_err = UnaryConversion(lhs, location);
  if (!lhs_or_err)
    return lhs_or_err.takeError();
  lhs = *lhs_or_err;
  auto rhs_or_err = UnaryConversion(rhs, location);
  if (!rhs_or_err)
    return rhs_or_err.takeError();
  rhs = *rhs_or_err;

  CompilerType lhs_type = lhs->GetCompilerType();
  CompilerType rhs_type = rhs->GetCompilerType();

  // If types already match, no need for further conversions.
  if (lhs_type.CompareTypes(rhs_type))
    return lhs_type;

  // If either of the operands is not arithmetic (e.g. pointer), we're done.
  if (!lhs_type.IsScalarType() || !rhs_type.IsScalarType())
    return CompilerType();

  size_t l_rank = ConversionRank(lhs_type);
  size_t r_rank = ConversionRank(rhs_type);
  if (l_rank == 0 || r_rank == 0)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "unexpected basic type in arithmetic operation", location);

  // If both operands are integer, check if we need to promote
  // the higher ranked signed type.
  if (lhs_type.IsInteger() && rhs_type.IsInteger()) {
    using Rank = std::tuple<size_t, bool>;
    Rank int_l_rank = {l_rank, !lhs_type.IsSigned()};
    Rank int_r_rank = {r_rank, !rhs_type.IsSigned()};
    if (int_l_rank < int_r_rank) {
      auto type_or_err = PromoteSignedInteger(lhs_type, rhs_type);
      if (!type_or_err)
        return type_or_err.takeError();
      return *type_or_err;
    }
    if (int_l_rank > int_r_rank) {
      auto type_or_err = PromoteSignedInteger(rhs_type, lhs_type);
      if (!type_or_err)
        return type_or_err.takeError();
      return *type_or_err;
    }
    return lhs_type;
  }

  // Handle other combinations of integer and floating point operands.
  if (l_rank < r_rank)
    return rhs_type;
  return lhs_type;
}

static lldb::VariableSP DILFindVariable(ConstString name,
                                        VariableList &variable_list) {
  lldb::VariableSP exact_match;
  std::vector<lldb::VariableSP> possible_matches;

  for (lldb::VariableSP var_sp : variable_list) {
    llvm::StringRef str_ref_name = var_sp->GetName().GetStringRef();

    str_ref_name.consume_front("::");
    // Check for the exact same match
    if (str_ref_name == name.GetStringRef())
      return var_sp;

    // Check for possible matches by base name
    if (var_sp->NameMatches(name))
      possible_matches.push_back(var_sp);
  }

  // If there's a non-exact match, take it.
  if (possible_matches.size() > 0)
    return possible_matches[0];

  return nullptr;
}

lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref,
                                           StackFrame &stack_frame,
                                           lldb::TargetSP target_sp,
                                           lldb::DynamicValueType use_dynamic) {
  // Get a global variables list without the locals from the current frame
  SymbolContext symbol_context =
      stack_frame.GetSymbolContext(lldb::eSymbolContextCompUnit);
  lldb::VariableListSP variable_list;
  if (symbol_context.comp_unit)
    variable_list = symbol_context.comp_unit->GetVariableList(true);

  name_ref.consume_front("::");
  lldb::ValueObjectSP value_sp;
  if (variable_list) {
    lldb::VariableSP var_sp =
        DILFindVariable(ConstString(name_ref), *variable_list);
    if (var_sp)
      value_sp =
          stack_frame.GetValueObjectForFrameVariable(var_sp, use_dynamic);
  }

  if (value_sp)
    return value_sp;

  // Check for match in modules global variables.
  VariableList modules_var_list;
  target_sp->GetImages().FindGlobalVariables(
      ConstString(name_ref), std::numeric_limits<uint32_t>::max(),
      modules_var_list);

  if (!modules_var_list.Empty()) {
    lldb::VariableSP var_sp =
        DILFindVariable(ConstString(name_ref), modules_var_list);
    if (var_sp)
      value_sp = ValueObjectVariable::Create(&stack_frame, var_sp);

    if (value_sp)
      return value_sp;
  }
  return nullptr;
}

lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
                                     StackFrame &stack_frame,
                                     lldb::DynamicValueType use_dynamic) {
  // Support $rax as a special syntax for accessing registers.
  // Will return an invalid value in case the requested register doesn't exist.
  if (name_ref.consume_front("$")) {
    lldb::RegisterContextSP reg_ctx(stack_frame.GetRegisterContext());
    if (!reg_ctx)
      return nullptr;

    if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name_ref))
      return ValueObjectRegister::Create(&stack_frame, reg_ctx, reg_info);

    return nullptr;
  }

  if (!name_ref.contains("::")) {
    // Lookup in the current frame.
    // Try looking for a local variable in current scope.
    lldb::VariableListSP variable_list(
        stack_frame.GetInScopeVariableList(false));

    lldb::ValueObjectSP value_sp;
    if (variable_list) {
      lldb::VariableSP var_sp =
          variable_list->FindVariable(ConstString(name_ref));
      if (var_sp)
        value_sp =
            stack_frame.GetValueObjectForFrameVariable(var_sp, use_dynamic);
    }

    if (value_sp)
      return value_sp;

    // Try looking for an instance variable (class member).
    SymbolContext sc = stack_frame.GetSymbolContext(
        lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
    llvm::StringRef instance_name = sc.GetInstanceName();
    value_sp = stack_frame.FindVariable(ConstString(instance_name));
    if (value_sp)
      value_sp = value_sp->GetChildMemberWithName(name_ref);

    if (value_sp)
      return value_sp;
  }
  return nullptr;
}

lldb::ValueObjectSP LookupEnumValue(llvm::StringRef name_ref,
                                    ExecutionContextScope &ctx_scope) {
  if (name_ref.contains("::")) {
    llvm::StringRef enum_typename, enumerator_name;
    // FIXME: Change this to a structured binding for lambda capturing
    // once we have C++20.
    std::tie(enum_typename, enumerator_name) = name_ref.rsplit("::");
    CompilerType enum_type = ResolveTypeByName(enum_typename.str(), ctx_scope);
    lldb::ValueObjectSP result;
    enum_type.ForEachEnumerator([&](const CompilerType &integer_type,
                                    ConstString name,
                                    const llvm::APSInt &value) -> bool {
      if (name == enumerator_name) {
        Scalar scalar(value);
        result = ValueObject::CreateValueObjectFromScalar(ctx_scope, scalar,
                                                          enum_type, "result");
        return false; // Stop iterating
      }
      return true;
    });
    return result;
  }
  return nullptr;
}

Interpreter::Interpreter(lldb::TargetSP target, llvm::StringRef expr,
                         StackFrame &stack_frame,
                         lldb::DynamicValueType use_dynamic, uint32_t options)
    : m_target(std::move(target)), m_expr(expr), m_stack_frame(stack_frame),
      m_use_dynamic(use_dynamic) {

  const bool check_ptr_vs_member =
      (options & StackFrame::eExpressionPathOptionCheckPtrVsMember) != 0;
  const bool no_synth_child =
      (options & StackFrame::eExpressionPathOptionsNoSyntheticChildren) != 0;
  const bool allow_var_updates =
      (options & StackFrame::eExpressionPathOptionsAllowVarUpdates) != 0;
  const bool disallow_globals =
      (options & StackFrame::eExpressionPathOptionsDisallowGlobals) != 0;

  m_use_synthetic = !no_synth_child;
  m_check_ptr_vs_member = check_ptr_vs_member;
  m_allow_var_updates = allow_var_updates;
  m_allow_globals = !disallow_globals;
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::Evaluate(const ASTNode &node) {
  // Evaluate an AST.
  auto value_or_error = node.Accept(this);
  // Convert SP with a nullptr to an error.
  if (value_or_error && !*value_or_error)
    return llvm::make_error<DILDiagnosticError>(m_expr, "invalid value object",
                                                node.GetLocation());
  // Return the computed value-or-error. The caller is responsible for
  // checking if an error occurred during the evaluation.
  return value_or_error;
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::EvaluateAndDereference(const ASTNode &node) {
  auto valobj_or_err = Evaluate(node);
  if (!valobj_or_err)
    return valobj_or_err;
  lldb::ValueObjectSP valobj = *valobj_or_err;

  Status error;
  if (valobj->GetCompilerType().IsReferenceType()) {
    valobj = valobj->Dereference(error);
    if (error.Fail())
      return error.ToError();
  }
  return valobj;
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const IdentifierNode &node) {
  lldb::DynamicValueType use_dynamic = m_use_dynamic;

  lldb::ValueObjectSP identifier =
      LookupIdentifier(node.GetName(), m_stack_frame, use_dynamic);

  if (!identifier && m_allow_globals)
    identifier = LookupGlobalIdentifier(node.GetName(), m_stack_frame, m_target,
                                        use_dynamic);

  if (!identifier)
    identifier = LookupEnumValue(node.GetName(), m_stack_frame);

  if (!identifier && node.GetName() == "nullptr") {
    // If we got a "nullptr" identifier, and there is no defined variable with
    // this name, resolve it as a null pointer.
    llvm::Expected<lldb::TypeSystemSP> type_system =
        GetTypeSystemFromCU(m_stack_frame);
    if (!type_system)
      return type_system.takeError();
    type_system.get()->GetPointerByteSize();
    llvm::APInt value(type_system.get()->GetPointerByteSize() * CHAR_BIT, 0);
    Scalar scalar(value);
    CompilerType type = GetBasicType(*type_system, lldb::eBasicTypeNullPtr);
    return ValueObject::CreateValueObjectFromScalar(m_stack_frame, scalar, type,
                                                    "result");
  }

  if (!identifier) {
    std::string errMsg =
        llvm::formatv("use of undeclared identifier '{0}'", node.GetName());
    return llvm::make_error<DILDiagnosticError>(
        m_expr, errMsg, node.GetLocation(), node.GetName().size());
  }

  return identifier;
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const UnaryOpNode &node) {
  Status error;
  auto op_or_err = Evaluate(node.GetOperand());
  if (!op_or_err)
    return op_or_err;

  lldb::ValueObjectSP operand = *op_or_err;

  switch (node.GetKind()) {
  case UnaryOpKind::Deref: {
    lldb::ValueObjectSP dynamic_op = operand->GetDynamicValue(m_use_dynamic);
    if (dynamic_op)
      operand = dynamic_op;

    lldb::ValueObjectSP child_sp = operand->Dereference(error);
    if (!child_sp && m_use_synthetic) {
      if (lldb::ValueObjectSP synth_obj_sp = operand->GetSyntheticValue()) {
        error.Clear();
        child_sp = synth_obj_sp->Dereference(error);
      }
    }
    if (error.Fail())
      return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
                                                  node.GetLocation());

    return child_sp;
  }
  case UnaryOpKind::AddrOf: {
    Status error;
    lldb::ValueObjectSP value = operand->AddressOf(error);
    if (error.Fail())
      return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
                                                  node.GetLocation());

    return value;
  }
  case UnaryOpKind::Minus: {
    if (operand->GetCompilerType().IsReferenceType()) {
      operand = operand->Dereference(error);
      if (error.Fail())
        return error.ToError();
    }
    llvm::Expected<lldb::ValueObjectSP> conv_op =
        UnaryConversion(operand, node.GetOperand().GetLocation());
    if (!conv_op)
      return conv_op;
    operand = *conv_op;
    CompilerType operand_type = operand->GetCompilerType();
    if (!operand_type.IsScalarType()) {
      std::string errMsg =
          llvm::formatv("invalid argument type '{0}' to unary expression",
                        operand_type.GetTypeName());
      return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
                                                  node.GetLocation());
    }
    Scalar scalar;
    bool resolved = operand->ResolveValue(scalar);
    if (!resolved)
      break;

    bool negated = scalar.UnaryNegate();
    if (negated)
      return ValueObject::CreateValueObjectFromScalar(
          m_stack_frame, scalar, operand->GetCompilerType(), "result");
    break;
  }
  case UnaryOpKind::Plus: {
    if (operand->GetCompilerType().IsReferenceType()) {
      operand = operand->Dereference(error);
      if (error.Fail())
        return error.ToError();
    }
    llvm::Expected<lldb::ValueObjectSP> conv_op =
        UnaryConversion(operand, node.GetOperand().GetLocation());
    if (!conv_op)
      return conv_op;
    operand = *conv_op;
    CompilerType operand_type = operand->GetCompilerType();
    if (!operand_type.IsScalarType() &&
        // Unary plus is allowed for pointers.
        !operand_type.IsPointerType()) {
      std::string errMsg =
          llvm::formatv("invalid argument type '{0}' to unary expression",
                        operand_type.GetTypeName());
      return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
                                                  node.GetLocation());
    }
    return operand;
  }
  }
  return llvm::make_error<DILDiagnosticError>(m_expr, "invalid unary operation",
                                              node.GetLocation());
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::PointerOffset(lldb::ValueObjectSP ptr, lldb::ValueObjectSP offset,
                           BinaryOpKind operation, uint32_t location) {
  assert(operation == BinaryOpKind::Add || operation == BinaryOpKind::Sub);
  if (ptr->GetCompilerType().IsPointerToVoid())
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "arithmetic on a pointer to void", location);
  if (ptr->GetValueAsUnsigned(0) == 0 && offset != 0)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "arithmetic on a nullptr is undefined", location);

  bool success;
  int64_t offset_int = offset->GetValueAsSigned(0, &success);
  if (!success) {
    std::string errMsg = llvm::formatv("could not get the offset: {0}",
                                       offset->GetError().AsCString());
    return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                                location);
  }

  llvm::Expected<uint64_t> byte_size =
      ptr->GetCompilerType().GetPointeeType().GetByteSize(&m_stack_frame);
  if (!byte_size)
    return byte_size.takeError();
  uint64_t ptr_addr = ptr->GetValueAsUnsigned(0);
  if (operation == BinaryOpKind::Sub)
    ptr_addr -= offset_int * (*byte_size);
  else
    ptr_addr += offset_int * (*byte_size);

  ExecutionContext exe_ctx(m_target.get(), false);
  Scalar scalar(ptr_addr);
  return ValueObject::CreateValueObjectFromScalar(
      m_stack_frame, scalar, ptr->GetCompilerType(), "result");
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::EvaluateScalarOp(BinaryOpKind kind, lldb::ValueObjectSP lhs,
                              lldb::ValueObjectSP rhs, CompilerType result_type,
                              uint32_t location) {
  Scalar l, r;
  bool l_resolved = lhs->ResolveValue(l);
  if (!l_resolved) {
    std::string errMsg =
        llvm::formatv("invalid lhs value: {0}", lhs->GetError().AsCString());
    return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
  }
  bool r_resolved = rhs->ResolveValue(r);
  if (!r_resolved) {
    std::string errMsg =
        llvm::formatv("invalid rhs value: {0}", rhs->GetError().AsCString());
    return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
  }

  auto value_object = [this, result_type](Scalar scalar) {
    return ValueObject::CreateValueObjectFromScalar(m_stack_frame, scalar,
                                                    result_type, "result");
  };

  switch (kind) {
  case BinaryOpKind::Add:
    return value_object(l + r);
  case BinaryOpKind::Sub:
    return value_object(l - r);
  case BinaryOpKind::Mul:
    return value_object(l * r);
  case BinaryOpKind::Div:
    return value_object(l / r);
  case BinaryOpKind::Rem:
    return value_object(l % r);
  case BinaryOpKind::Shl:
    return value_object(l << r);
  case BinaryOpKind::Shr:
    return value_object(l >> r);
  default:
    break;
  }
  return llvm::make_error<DILDiagnosticError>(
      m_expr, "invalid arithmetic operation", location);
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryAddition(
    lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
  // Operation '+' works for:
  //   {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
  //   {integer,unscoped_enum} <-> pointer
  //   pointer <-> {integer,unscoped_enum}
  auto orig_lhs_type = lhs->GetCompilerType();
  auto orig_rhs_type = rhs->GetCompilerType();
  auto type_or_err = ArithmeticConversion(lhs, rhs, location);
  if (!type_or_err)
    return type_or_err.takeError();
  CompilerType result_type = *type_or_err;

  if (result_type.IsScalarType())
    return EvaluateScalarOp(BinaryOpKind::Add, lhs, rhs, result_type, location);

  // Check for pointer arithmetics.
  // One of the operands must be a pointer and the other one an integer.
  lldb::ValueObjectSP ptr, offset;
  if (lhs->GetCompilerType().IsPointerType()) {
    ptr = lhs;
    offset = rhs;
  } else if (rhs->GetCompilerType().IsPointerType()) {
    ptr = rhs;
    offset = lhs;
  }

  if (!ptr || !offset->GetCompilerType().IsInteger()) {
    std::string errMsg =
        llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                      orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
    return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                                location);
  }

  return PointerOffset(ptr, offset, BinaryOpKind::Add, location);
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinarySubtraction(
    lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
  // Operation '-' works for:
  //   {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
  //   pointer <-> {integer,unscoped_enum}
  //   pointer <-> pointer (if pointee types are compatible)
  auto orig_lhs_type = lhs->GetCompilerType();
  auto orig_rhs_type = rhs->GetCompilerType();
  auto type_or_err = ArithmeticConversion(lhs, rhs, location);
  if (!type_or_err)
    return type_or_err.takeError();
  CompilerType result_type = *type_or_err;

  if (result_type.IsScalarType())
    return EvaluateScalarOp(BinaryOpKind::Sub, lhs, rhs, result_type, location);

  auto lhs_type = lhs->GetCompilerType();
  auto rhs_type = rhs->GetCompilerType();

  // "pointer - integer" operation.
  if (lhs_type.IsPointerType() && rhs_type.IsInteger())
    return PointerOffset(lhs, rhs, BinaryOpKind::Sub, location);

  // "pointer - pointer" operation.
  if (lhs_type.IsPointerType() && rhs_type.IsPointerType()) {
    if (lhs_type.IsPointerToVoid() && rhs_type.IsPointerToVoid()) {
      return llvm::make_error<DILDiagnosticError>(
          m_expr, "arithmetic on pointers to void", location);
    }
    // Compare canonical unqualified pointer types.
    CompilerType lhs_unqualified_type = lhs_type.GetCanonicalType();
    CompilerType rhs_unqualified_type = rhs_type.GetCanonicalType();
    if (!lhs_unqualified_type.CompareTypes(rhs_unqualified_type)) {
      std::string errMsg = llvm::formatv(
          "'{0}' and '{1}' are not pointers to compatible types",
          orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
      return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
    }

    llvm::Expected<uint64_t> lhs_byte_size =
        lhs_type.GetPointeeType().GetByteSize(&m_stack_frame);
    if (!lhs_byte_size)
      return lhs_byte_size.takeError();
    // Since pointers have compatible types, both have the same pointee size.
    int64_t item_size = *lhs_byte_size;
    int64_t diff = static_cast<int64_t>(lhs->GetValueAsUnsigned(0) -
                                        rhs->GetValueAsUnsigned(0));
    assert(item_size > 0 && "Pointee size cannot be 0");
    if (diff % item_size != 0) {
      // If address difference isn't divisible by pointee size then performing
      // the operation is undefined behaviour.
      return llvm::make_error<DILDiagnosticError>(
          m_expr, "undefined pointer arithmetic", location);
    }
    diff /= item_size;

    llvm::Expected<lldb::TypeSystemSP> type_system =
        GetTypeSystemFromCU(m_stack_frame);
    if (!type_system)
      return type_system.takeError();
    CompilerType ptrdiff_type = type_system.get()->GetPointerDiffType(true);
    if (!ptrdiff_type)
      return llvm::make_error<DILDiagnosticError>(
          m_expr, "unable to determine pointer diff type", location);

    Scalar scalar(diff);
    return ValueObject::CreateValueObjectFromScalar(m_stack_frame, scalar,
                                                    ptrdiff_type, "result");
  }

  std::string errMsg =
      llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                    orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
  return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                              location);
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryMultiplication(
    lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
  // Operation '*' works for:
  //  {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
  auto orig_lhs_type = lhs->GetCompilerType();
  auto orig_rhs_type = rhs->GetCompilerType();
  auto type_or_err = ArithmeticConversion(lhs, rhs, location);
  if (!type_or_err)
    return type_or_err.takeError();
  CompilerType result_type = *type_or_err;

  if (!result_type.IsScalarType()) {
    std::string errMsg =
        llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                      orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
    return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                                location);
  }

  return EvaluateScalarOp(BinaryOpKind::Mul, lhs, rhs, result_type, location);
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryDivision(
    lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
  // Operation '/' works for:
  //  {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
  auto orig_lhs_type = lhs->GetCompilerType();
  auto orig_rhs_type = rhs->GetCompilerType();
  auto type_or_err = ArithmeticConversion(lhs, rhs, location);
  if (!type_or_err)
    return type_or_err.takeError();
  CompilerType result_type = *type_or_err;

  if (!result_type.IsScalarType()) {
    std::string errMsg =
        llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                      orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
    return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                                location);
  }

  // Check for zero only for integer division.
  if (result_type.IsInteger() && rhs->GetValueAsSigned(-1) == 0) {
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "division by zero is undefined", location);
  }

  return EvaluateScalarOp(BinaryOpKind::Div, lhs, rhs, result_type, location);
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryRemainder(
    lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
  // Operation '%' works for:
  //  {integer,unscoped_enum} <-> {integer,unscoped_enum}
  auto orig_lhs_type = lhs->GetCompilerType();
  auto orig_rhs_type = rhs->GetCompilerType();
  auto type_or_err = ArithmeticConversion(lhs, rhs, location);
  if (!type_or_err)
    return type_or_err.takeError();
  CompilerType result_type = *type_or_err;

  if (!result_type.IsInteger()) {
    std::string errMsg =
        llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                      orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
    return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                                location);
  }

  if (rhs->GetValueAsSigned(-1) == 0) {
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "division by zero is undefined", location);
  }

  return EvaluateScalarOp(BinaryOpKind::Rem, lhs, rhs, result_type, location);
}

static bool HasFloatingRepresentation(CompilerType ct) {
  return ct.GetTypeInfo() & lldb::eTypeIsFloat;
}

static llvm::Expected<bool> VerifyAssignmentTypes(CompilerType lhs_type,
                                                  CompilerType rhs_type) {
  // Make sure lhs is a legal type for DIL assignment.
  if (!lhs_type.IsInteger() && !lhs_type.IsUnscopedEnumerationType() &&
      !HasFloatingRepresentation(lhs_type) && !lhs_type.IsPointerType() &&
      !lhs_type.IsScalarType())
    return llvm::createStringError(
        "Illegal type for lhs of assignment (not scalar numeric type)");

  // Make sure rhs is a legal type for DIL assignment.
  if (!rhs_type.IsInteger() && !rhs_type.IsUnscopedEnumerationType() &&
      !HasFloatingRepresentation(rhs_type) && !rhs_type.IsPointerType())
    return llvm::createStringError(
        "Illegal type for rhs of assignment (not scalar numeric type)");

  // Only allow assigning pointers to pointers.
  if ((lhs_type.IsPointerType() && !rhs_type.IsPointerType()) ||
      (!lhs_type.IsPointerType() && rhs_type.IsPointerType()))
    return llvm::createStringError(
        "Invalid assignment: Can only assign pointers to pointers");

  // For "real numbers", the types must match exactly.
  if ((HasFloatingRepresentation(rhs_type) ||
       HasFloatingRepresentation(lhs_type)) &&
      lhs_type != rhs_type) {
    std::string err_msg =
        llvm::formatv("Incompatible types for assignment: Cannot assign {0} "
                      "to {1}",
                      rhs_type.TypeDescription(), lhs_type.TypeDescription());
    return llvm::createStringError(err_msg);
  }

  return true;
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::EvaluateAssignment(lldb::ValueObjectSP lhs,
                                lldb::ValueObjectSP rhs, uint32_t location) {

  auto all_ok =
      VerifyAssignmentTypes(lhs->GetCompilerType(), rhs->GetCompilerType());
  if (!all_ok)
    return all_ok.takeError();

  if (llvm::Error e = lhs->SetValueFromInteger(rhs, m_allow_var_updates))
    return e;

  return lhs;
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::EvaluateBinaryShift(BinaryOpKind kind, lldb::ValueObjectSP lhs,
                                 lldb::ValueObjectSP rhs, uint32_t location) {
  // Operations {'>>', '<<'} work for:
  //  {integer,unscoped_enum} <-> {integer,unscoped_enum}
  CompilerType orig_lhs_type = lhs->GetCompilerType();
  CompilerType orig_rhs_type = rhs->GetCompilerType();
  auto lhs_or_err = UnaryConversion(lhs, location);
  if (!lhs_or_err)
    return lhs_or_err.takeError();
  lhs = *lhs_or_err;
  auto rhs_or_err = UnaryConversion(rhs, location);
  if (!rhs_or_err)
    return rhs_or_err.takeError();
  rhs = *rhs_or_err;

  CompilerType lhs_type = lhs->GetCompilerType();
  CompilerType rhs_type = rhs->GetCompilerType();
  if (!lhs_type.IsInteger() || !rhs_type.IsInteger()) {
    std::string errMsg =
        llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
                      orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
    return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
  }

  bool success;
  uint64_t amount = rhs->GetValueAsUnsigned(0, &success);
  if (!success)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "could not get the shift amount as an integer", location);
  llvm::Expected<uint64_t> lhs_size = lhs_type.GetBitSize(&m_stack_frame);
  if (!lhs_size)
    return lhs_size.takeError();
  if (amount >= *lhs_size)
    return llvm::make_error<DILDiagnosticError>(m_expr, "invalid shift amount",
                                                location);

  return EvaluateScalarOp(kind, lhs, rhs, lhs_type, location);
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const BinaryOpNode &node) {
  auto lhs_or_err = EvaluateAndDereference(node.GetLHS());
  if (!lhs_or_err)
    return lhs_or_err;
  lldb::ValueObjectSP lhs = *lhs_or_err;
  auto rhs_or_err = EvaluateAndDereference(node.GetRHS());
  if (!rhs_or_err)
    return rhs_or_err;
  lldb::ValueObjectSP rhs = *rhs_or_err;

  lldb::TypeSystemSP lhs_system =
      lhs->GetCompilerType().GetTypeSystem().GetSharedPointer();
  lldb::TypeSystemSP rhs_system =
      rhs->GetCompilerType().GetTypeSystem().GetSharedPointer();
  if (lhs_system->GetPluginName() != rhs_system->GetPluginName()) {
    // TODO: Attempt to convert values to current CU's type system
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "operands have different type systems", node.GetLocation());
  }

  switch (node.GetKind()) {
  case BinaryOpKind::Add:
    return EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
  case BinaryOpKind::AddAssign: {
    auto ret_or_err = EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
    if (!ret_or_err)
      return ret_or_err;
    return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
  }
  case BinaryOpKind::Assign:
    return EvaluateAssignment(lhs, rhs, node.GetLocation());
  case BinaryOpKind::Sub:
    return EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
  case BinaryOpKind::SubAssign: {
    auto ret_or_err = EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
    if (!ret_or_err)
      return ret_or_err;
    return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
  }
  case BinaryOpKind::Mul:
    return EvaluateBinaryMultiplication(lhs, rhs, node.GetLocation());
  case BinaryOpKind::Div:
    return EvaluateBinaryDivision(lhs, rhs, node.GetLocation());
  case BinaryOpKind::Rem:
    return EvaluateBinaryRemainder(lhs, rhs, node.GetLocation());
  case BinaryOpKind::Shl:
  case BinaryOpKind::Shr:
    return EvaluateBinaryShift(node.GetKind(), lhs, rhs, node.GetLocation());
  }

  return llvm::make_error<DILDiagnosticError>(
      m_expr, "unimplemented binary operation", node.GetLocation());
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const MemberOfNode &node) {
  auto base_or_err = Evaluate(node.GetBase());
  if (!base_or_err)
    return base_or_err;
  bool expr_is_ptr = node.GetIsArrow();
  lldb::ValueObjectSP base = *base_or_err;

  // Perform some basic type & correctness checking.
  if (node.GetIsArrow()) {
    // If we have a non-pointer type with a synthetic value then lets check
    // if we have a synthetic dereference specified.
    if (!base->IsPointerType() && base->HasSyntheticValue()) {
      Status deref_error;
      if (lldb::ValueObjectSP synth_deref_sp =
              base->GetSyntheticValue()->Dereference(deref_error);
          synth_deref_sp && deref_error.Success()) {
        base = std::move(synth_deref_sp);
      }
      if (!base || deref_error.Fail()) {
        std::string errMsg = llvm::formatv(
            "Failed to dereference synthetic value: {0}", deref_error);
        return llvm::make_error<DILDiagnosticError>(
            m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
      }

      // Some synthetic plug-ins fail to set the error in Dereference
      if (!base) {
        std::string errMsg = "Failed to dereference synthetic value";
        return llvm::make_error<DILDiagnosticError>(
            m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
      }
      expr_is_ptr = false;
    }
  }

  if (m_check_ptr_vs_member) {
    bool base_is_ptr = base->IsPointerType();

    if (expr_is_ptr != base_is_ptr) {
      if (base_is_ptr) {
        std::string errMsg =
            llvm::formatv("member reference type {0} is a pointer; "
                          "did you mean to use '->'?",
                          base->GetCompilerType().TypeDescription());
        return llvm::make_error<DILDiagnosticError>(
            m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
      } else {
        std::string errMsg =
            llvm::formatv("member reference type {0} is not a pointer; "
                          "did you mean to use '.'?",
                          base->GetCompilerType().TypeDescription());
        return llvm::make_error<DILDiagnosticError>(
            m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
      }
    }
  }

  lldb::ValueObjectSP field_obj =
      base->GetChildMemberWithName(node.GetFieldName());
  if (!field_obj) {
    if (m_use_synthetic) {
      field_obj = base->GetSyntheticValue();
      if (field_obj)
        field_obj = field_obj->GetChildMemberWithName(node.GetFieldName());
    }

    if (!m_use_synthetic || !field_obj) {
      std::string errMsg = llvm::formatv(
          "\"{0}\" is not a member of \"({1}) {2}\"", node.GetFieldName(),
          base->GetTypeName().AsCString("<invalid type>"), base->GetName());
      return llvm::make_error<DILDiagnosticError>(
          m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
    }
  }

  if (field_obj) {
    if (m_use_dynamic != lldb::eNoDynamicValues) {
      lldb::ValueObjectSP dynamic_val_sp =
          field_obj->GetDynamicValue(m_use_dynamic);
      if (dynamic_val_sp)
        field_obj = dynamic_val_sp;
    }
    return field_obj;
  }

  CompilerType base_type = base->GetCompilerType();
  if (node.GetIsArrow() && base->IsPointerType())
    base_type = base_type.GetPointeeType();
  std::string errMsg = llvm::formatv(
      "\"{0}\" is not a member of \"({1}) {2}\"", node.GetFieldName(),
      base->GetTypeName().AsCString("<invalid type>"), base->GetName());
  return llvm::make_error<DILDiagnosticError>(
      m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const ArraySubscriptNode &node) {
  auto idx_or_err = EvaluateAndDereference(node.GetIndex());
  if (!idx_or_err)
    return idx_or_err;
  lldb::ValueObjectSP idx = *idx_or_err;

  if (!idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "array subscript is not an integer", node.GetLocation());
  }

  StreamString var_expr_path_strm;
  uint64_t child_idx = idx->GetValueAsUnsigned(0);
  lldb::ValueObjectSP child_valobj_sp;

  auto base_or_err = Evaluate(node.GetBase());
  if (!base_or_err)
    return base_or_err;
  lldb::ValueObjectSP base = *base_or_err;

  CompilerType base_type = base->GetCompilerType().GetNonReferenceType();
  base->GetExpressionPath(var_expr_path_strm);
  bool is_incomplete_array = false;
  if (base_type.IsPointerType()) {
    bool is_objc_pointer = true;

    if (base->GetCompilerType().GetMinimumLanguage() != lldb::eLanguageTypeObjC)
      is_objc_pointer = false;
    else if (!base->GetCompilerType().IsPointerType())
      is_objc_pointer = false;

    if (!m_use_synthetic && is_objc_pointer) {
      std::string err_msg = llvm::formatv(
          "\"({0}) {1}\" is an Objective-C pointer, and cannot be subscripted",
          base->GetTypeName().AsCString("<invalid type>"),
          var_expr_path_strm.GetData());
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation());
    }
    if (is_objc_pointer) {
      lldb::ValueObjectSP synthetic = base->GetSyntheticValue();
      if (!synthetic || synthetic == base) {
        std::string err_msg =
            llvm::formatv("\"({0}) {1}\" is not an array type",
                          base->GetTypeName().AsCString("<invalid type>"),
                          var_expr_path_strm.GetData());
        return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                    node.GetLocation());
      }
      if (static_cast<uint32_t>(child_idx) >=
          synthetic->GetNumChildrenIgnoringErrors()) {
        std::string err_msg = llvm::formatv(
            "array index {0} is not valid for \"({1}) {2}\"", child_idx,
            base->GetTypeName().AsCString("<invalid type>"),
            var_expr_path_strm.GetData());
        return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                    node.GetLocation());
      }
      child_valobj_sp = synthetic->GetChildAtIndex(child_idx);
      if (!child_valobj_sp) {
        std::string err_msg = llvm::formatv(
            "array index {0} is not valid for \"({1}) {2}\"", child_idx,
            base->GetTypeName().AsCString("<invalid type>"),
            var_expr_path_strm.GetData());
        return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                    node.GetLocation());
      }
      if (m_use_dynamic != lldb::eNoDynamicValues) {
        if (auto dynamic_sp = child_valobj_sp->GetDynamicValue(m_use_dynamic))
          child_valobj_sp = std::move(dynamic_sp);
      }
      return child_valobj_sp;
    }

    child_valobj_sp = base->GetSyntheticArrayMember(child_idx, true);
    if (!child_valobj_sp) {
      std::string err_msg = llvm::formatv(
          "failed to use pointer as array for index {0} for "
          "\"({1}) {2}\"",
          child_idx, base->GetTypeName().AsCString("<invalid type>"),
          var_expr_path_strm.GetData());
      if (base_type.IsPointerToVoid())
        err_msg = "subscript of pointer to incomplete type 'void'";
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation());
    }
  } else if (base_type.IsArrayType(nullptr, nullptr, &is_incomplete_array)) {
    child_valobj_sp = base->GetChildAtIndex(child_idx);
    if (!child_valobj_sp && (is_incomplete_array || m_use_synthetic))
      child_valobj_sp = base->GetSyntheticArrayMember(child_idx, true);
    if (!child_valobj_sp) {
      std::string err_msg = llvm::formatv(
          "array index {0} is not valid for \"({1}) {2}\"", child_idx,
          base->GetTypeName().AsCString("<invalid type>"),
          var_expr_path_strm.GetData());
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation());
    }
  } else if (base_type.IsScalarType()) {
    child_valobj_sp =
        base->GetSyntheticBitFieldChild(child_idx, child_idx, true);
    if (!child_valobj_sp) {
      std::string err_msg = llvm::formatv(
          "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", child_idx,
          child_idx, base->GetTypeName().AsCString("<invalid type>"),
          var_expr_path_strm.GetData());
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation(), 1);
    }
  } else {
    lldb::ValueObjectSP synthetic = base->GetSyntheticValue();
    if (!m_use_synthetic || !synthetic || synthetic == base) {
      std::string err_msg =
          llvm::formatv("\"{0}\" is not an array type",
                        base->GetTypeName().AsCString("<invalid type>"));
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation(), 1);
    }
    if (static_cast<uint32_t>(child_idx) >=
        synthetic->GetNumChildrenIgnoringErrors(child_idx + 1)) {
      std::string err_msg = llvm::formatv(
          "array index {0} is not valid for \"({1}) {2}\"", child_idx,
          base->GetTypeName().AsCString("<invalid type>"),
          var_expr_path_strm.GetData());
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation(), 1);
    }
    child_valobj_sp = synthetic->GetChildAtIndex(child_idx);
    if (!child_valobj_sp) {
      std::string err_msg = llvm::formatv(
          "array index {0} is not valid for \"({1}) {2}\"", child_idx,
          base->GetTypeName().AsCString("<invalid type>"),
          var_expr_path_strm.GetData());
      return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
                                                  node.GetLocation(), 1);
    }
  }

  if (child_valobj_sp) {
    if (m_use_dynamic != lldb::eNoDynamicValues) {
      if (auto dynamic_sp = child_valobj_sp->GetDynamicValue(m_use_dynamic))
        child_valobj_sp = std::move(dynamic_sp);
    }
    return child_valobj_sp;
  }

  bool success;
  int64_t signed_child_idx = idx->GetValueAsSigned(0, &success);
  if (!success)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "could not get the index as an integer",
        node.GetIndex().GetLocation());
  return base->GetSyntheticArrayMember(signed_child_idx, true);
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const BitFieldExtractionNode &node) {
  auto first_idx_or_err = EvaluateAndDereference(node.GetFirstIndex());
  if (!first_idx_or_err)
    return first_idx_or_err;
  lldb::ValueObjectSP first_idx = *first_idx_or_err;
  auto last_idx_or_err = EvaluateAndDereference(node.GetLastIndex());
  if (!last_idx_or_err)
    return last_idx_or_err;
  lldb::ValueObjectSP last_idx = *last_idx_or_err;

  if (!first_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType() ||
      !last_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "bit index is not an integer", node.GetLocation());
  }

  bool success_first, success_last;
  int64_t first_index = first_idx->GetValueAsSigned(0, &success_first);
  int64_t last_index = last_idx->GetValueAsSigned(0, &success_last);
  if (!success_first || !success_last)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "could not get the index as an integer", node.GetLocation());

  // if the format given is [high-low], swap range
  if (first_index > last_index)
    std::swap(first_index, last_index);

  auto base_or_err = EvaluateAndDereference(node.GetBase());
  if (!base_or_err)
    return base_or_err;
  lldb::ValueObjectSP base = *base_or_err;
  lldb::ValueObjectSP child_valobj_sp =
      base->GetSyntheticBitFieldChild(first_index, last_index, true);
  if (!child_valobj_sp) {
    std::string message = llvm::formatv(
        "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", first_index,
        last_index, base->GetTypeName().AsCString("<invalid type>"),
        base->GetName().GetStringRef());
    return llvm::make_error<DILDiagnosticError>(m_expr, message,
                                                node.GetLocation());
  }
  return child_valobj_sp;
}

llvm::Expected<CompilerType>
Interpreter::PickIntegerType(lldb::TypeSystemSP type_system,
                             ExecutionContextScope &ctx,
                             const IntegerLiteralNode &literal) {
  // Binary, Octal, Hexadecimal and literals with a U suffix are allowed to be
  // an unsigned integer.
  bool unsigned_is_allowed = literal.IsUnsigned() || literal.GetRadix() != 10;
  llvm::APInt apint = literal.GetValue();

  llvm::SmallVector<std::pair<lldb::BasicType, lldb::BasicType>, 3> candidates;
  if (literal.GetTypeSuffix() <= IntegerTypeSuffix::None)
    candidates.emplace_back(lldb::eBasicTypeInt,
                            unsigned_is_allowed ? lldb::eBasicTypeUnsignedInt
                                                : lldb::eBasicTypeInvalid);
  if (literal.GetTypeSuffix() <= IntegerTypeSuffix::Long)
    candidates.emplace_back(lldb::eBasicTypeLong,
                            unsigned_is_allowed ? lldb::eBasicTypeUnsignedLong
                                                : lldb::eBasicTypeInvalid);
  candidates.emplace_back(lldb::eBasicTypeLongLong,
                          lldb::eBasicTypeUnsignedLongLong);
  for (auto [signed_, unsigned_] : candidates) {
    CompilerType signed_type = type_system->GetBasicTypeFromAST(signed_);
    if (!signed_type)
      continue;
    llvm::Expected<uint64_t> size = signed_type.GetBitSize(&ctx);
    if (!size)
      return size.takeError();
    if (!literal.IsUnsigned() && apint.isIntN(*size - 1))
      return signed_type;
    if (unsigned_ != lldb::eBasicTypeInvalid && apint.isIntN(*size))
      return type_system->GetBasicTypeFromAST(unsigned_);
  }

  return llvm::make_error<DILDiagnosticError>(
      m_expr,
      "integer literal is too large to be represented in any integer type",
      literal.GetLocation());
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const IntegerLiteralNode &node) {
  llvm::Expected<lldb::TypeSystemSP> type_system =
      GetTypeSystemFromCU(m_stack_frame);
  if (!type_system)
    return type_system.takeError();

  llvm::Expected<CompilerType> type =
      PickIntegerType(*type_system, m_stack_frame, node);
  if (!type)
    return type.takeError();

  Scalar scalar = node.GetValue();
  // APInt from StringRef::getAsInteger comes with just enough bitwidth to
  // hold the value. This adjusts APInt bitwidth to match the compiler type.
  llvm::Expected<uint64_t> type_bitsize = type->GetBitSize(&m_stack_frame);
  if (!type_bitsize)
    return type_bitsize.takeError();
  // Literal itself cannot be a negative value, so we do an unsigned extension.
  scalar.TruncOrExtendTo(*type_bitsize, false);
  // If the picked compiler type is signed, make the scalar signed as well.
  if (type->IsSigned())
    scalar.MakeSigned();
  return ValueObject::CreateValueObjectFromScalar(m_stack_frame, scalar, *type,
                                                  "result");
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const FloatLiteralNode &node) {
  llvm::Expected<lldb::TypeSystemSP> type_system =
      GetTypeSystemFromCU(m_stack_frame);
  if (!type_system)
    return type_system.takeError();

  bool isFloat =
      &node.GetValue().getSemantics() == &llvm::APFloat::IEEEsingle();
  lldb::BasicType basic_type =
      isFloat ? lldb::eBasicTypeFloat : lldb::eBasicTypeDouble;
  CompilerType type = GetBasicType(*type_system, basic_type);

  if (!type)
    return llvm::make_error<DILDiagnosticError>(
        m_expr, "unable to create a const literal", node.GetLocation());

  Scalar scalar = node.GetValue();
  return ValueObject::CreateValueObjectFromScalar(m_stack_frame, scalar, type,
                                                  "result");
}

llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const BooleanLiteralNode &node) {
  bool value = node.GetValue();
  llvm::Expected<lldb::TypeSystemSP> type_system =
      GetTypeSystemFromCU(m_stack_frame);
  if (!type_system)
    return type_system.takeError();
  return ValueObject::CreateValueObjectFromBool(m_stack_frame, *type_system,
                                                value, "result");
}

llvm::Expected<CastKind>
Interpreter::VerifyArithmeticCast(CompilerType source_type,
                                  CompilerType target_type, int location) {
  if (source_type.IsPointerType() || source_type.IsNullPtrType()) {
    // Cast from pointer to float/double is not allowed.
    if (target_type.GetTypeInfo() & lldb::eTypeIsFloat) {
      std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
                                         source_type.TypeDescription(),
                                         target_type.TypeDescription());
      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          source_type.TypeDescription().length());
    }

    // Casting from pointer to bool is always valid.
    if (target_type.IsBoolean())
      return CastKind::eArithmetic;

    // Otherwise check if the result type is at least as big as the pointer
    // size.
    uint64_t type_byte_size = 0;
    uint64_t rhs_type_byte_size = 0;
    if (auto temp = target_type.GetByteSize(&m_stack_frame)) {
      type_byte_size = *temp;
    } else {
      std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
                                         target_type.TypeDescription());
      LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), temp.takeError(),
                     "GetByteSize failed: {0}");
      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          target_type.TypeDescription().length());
    }

    if (auto temp = source_type.GetByteSize(&m_stack_frame)) {
      rhs_type_byte_size = *temp;
    } else {
      std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
                                         source_type.TypeDescription());
      LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), temp.takeError(),
                     "GetByteSize failed: {0}");
      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          source_type.TypeDescription().length());
    }

    if (type_byte_size < rhs_type_byte_size) {
      std::string errMsg = llvm::formatv(
          "cast from pointer to smaller type {0} loses information",
          target_type.TypeDescription());
      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          source_type.TypeDescription().length());
    }
  } else if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
    // Otherwise accept only arithmetic types and enums.
    std::string errMsg = llvm::formatv("cannot convert {0} to {1}",
                                       source_type.TypeDescription(),
                                       target_type.TypeDescription());

    return llvm::make_error<DILDiagnosticError>(
        m_expr, std::move(errMsg), location,
        source_type.TypeDescription().length());
  }
  return CastKind::eArithmetic;
}

llvm::Expected<CastKind>
Interpreter::VerifyCastType(lldb::ValueObjectSP operand,
                            CompilerType source_type, CompilerType target_type,
                            int location) {

  if (target_type.IsScalarType())
    return VerifyArithmeticCast(source_type, target_type, location);

  if (target_type.IsEnumerationType()) {
    // Cast to enum type.
    if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
      std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
                                         source_type.TypeDescription(),
                                         target_type.TypeDescription());

      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          source_type.TypeDescription().length());
    }
    return CastKind::eEnumeration;
  }

  if (target_type.IsPointerType()) {
    if (!source_type.IsInteger() && !source_type.IsEnumerationType() &&
        !source_type.IsArrayType() && !source_type.IsPointerType() &&
        !source_type.IsNullPtrType()) {
      std::string errMsg = llvm::formatv(
          "cannot cast from type {0} to pointer type {1}",
          source_type.TypeDescription(), target_type.TypeDescription());

      return llvm::make_error<DILDiagnosticError>(
          m_expr, std::move(errMsg), location,
          source_type.TypeDescription().length());
    }
    return CastKind::ePointer;
  }

  // Unsupported cast.
  std::string errMsg = llvm::formatv(
      "casting of {0} to {1} is not implemented yet",
      source_type.TypeDescription(), target_type.TypeDescription());
  return llvm::make_error<DILDiagnosticError>(
      m_expr, std::move(errMsg), location,
      source_type.TypeDescription().length());
}

llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const CastNode &node) {
  auto operand_or_err = Evaluate(node.GetOperand());

  if (!operand_or_err)
    return operand_or_err;

  lldb::ValueObjectSP operand = *operand_or_err;
  CompilerType op_type = operand->GetCompilerType();
  CompilerType target_type = node.GetType();

  if (op_type.IsReferenceType())
    op_type = op_type.GetNonReferenceType();
  if (target_type.IsScalarType() && op_type.IsArrayType()) {
    operand = ArrayToPointerConversion(*operand, m_stack_frame,
                                       operand->GetName().GetStringRef());
    op_type = operand->GetCompilerType();
  }
  auto type_or_err =
      VerifyCastType(operand, op_type, target_type, node.GetLocation());
  if (!type_or_err)
    return type_or_err.takeError();

  CastKind cast_kind = *type_or_err;
  if (operand->GetCompilerType().IsReferenceType()) {
    Status error;
    operand = operand->Dereference(error);
    if (error.Fail())
      return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
                                                  node.GetLocation());
  }

  switch (cast_kind) {
  case CastKind::eEnumeration: {
    // FIXME: is this correct for float vector types?
    if (op_type.GetTypeInfo() & lldb::eTypeIsFloat || op_type.IsInteger() ||
        op_type.IsEnumerationType())
      return operand->CastToEnumType(target_type);
    break;
  }
  case CastKind::eArithmetic: {
    if (op_type.IsPointerType() || op_type.IsNullPtrType() ||
        op_type.IsScalarType() || op_type.IsEnumerationType())
      return operand->CastToBasicType(target_type);
    break;
  }
  case CastKind::ePointer: {
    uint64_t addr = op_type.IsArrayType()
                        ? operand->GetLoadAddress()
                        : (op_type.IsSigned() ? operand->GetValueAsSigned(0)
                                              : operand->GetValueAsUnsigned(0));
    llvm::StringRef name = "result";
    ExecutionContext exe_ctx(m_target.get(), false);
    return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx,
                                                     target_type,
                                                     /* do_deref */ false);
  }
  case CastKind::eNone: {
    return lldb::ValueObjectSP();
  }
  } // switch

  std::string errMsg =
      llvm::formatv("unable to cast from '{0}' to '{1}'",
                    op_type.TypeDescription(), target_type.TypeDescription());
  return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
                                              node.GetLocation());
}

} // namespace lldb_private::dil
