//===-- ObjCLanguageRuntime.cpp ---------------------------------*- C++ -*-===//
//
// 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 "clang/AST/Type.h"

#include "ObjCLanguageRuntime.h"

#include "lldb/Core/MappedHash.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Timer.h"

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DJB.h"

using namespace lldb;
using namespace lldb_private;

char ObjCLanguageRuntime::ID = 0;

// Destructor
ObjCLanguageRuntime::~ObjCLanguageRuntime() {}

ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process)
    : LanguageRuntime(process), m_impl_cache(),
      m_has_new_literals_and_indexing(eLazyBoolCalculate),
      m_isa_to_descriptor(), m_hash_to_isa_map(), m_type_size_cache(),
      m_isa_to_descriptor_stop_id(UINT32_MAX), m_complete_class_cache(),
      m_negative_complete_class_cache() {}

bool ObjCLanguageRuntime::IsWhitelistedRuntimeValue(ConstString name) {
  static ConstString g_self = ConstString("self");
  static ConstString g_cmd = ConstString("_cmd");
  return name == g_self || name == g_cmd;
}

bool ObjCLanguageRuntime::AddClass(ObjCISA isa,
                                   const ClassDescriptorSP &descriptor_sp,
                                   const char *class_name) {
  if (isa != 0) {
    m_isa_to_descriptor[isa] = descriptor_sp;
    // class_name is assumed to be valid
    m_hash_to_isa_map.insert(std::make_pair(llvm::djbHash(class_name), isa));
    return true;
  }
  return false;
}

void ObjCLanguageRuntime::AddToMethodCache(lldb::addr_t class_addr,
                                           lldb::addr_t selector,
                                           lldb::addr_t impl_addr) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
  if (log) {
    LLDB_LOGF(log,
              "Caching: class 0x%" PRIx64 " selector 0x%" PRIx64
              " implementation 0x%" PRIx64 ".",
              class_addr, selector, impl_addr);
  }
  m_impl_cache.insert(std::pair<ClassAndSel, lldb::addr_t>(
      ClassAndSel(class_addr, selector), impl_addr));
}

lldb::addr_t ObjCLanguageRuntime::LookupInMethodCache(lldb::addr_t class_addr,
                                                      lldb::addr_t selector) {
  MsgImplMap::iterator pos, end = m_impl_cache.end();
  pos = m_impl_cache.find(ClassAndSel(class_addr, selector));
  if (pos != end)
    return (*pos).second;
  return LLDB_INVALID_ADDRESS;
}

lldb::TypeSP
ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) {
  CompleteClassMap::iterator complete_class_iter =
      m_complete_class_cache.find(name);

  if (complete_class_iter != m_complete_class_cache.end()) {
    // Check the weak pointer to make sure the type hasn't been unloaded
    TypeSP complete_type_sp(complete_class_iter->second.lock());

    if (complete_type_sp)
      return complete_type_sp;
    else
      m_complete_class_cache.erase(name);
  }

  if (m_negative_complete_class_cache.count(name) > 0)
    return TypeSP();

  const ModuleList &modules = m_process->GetTarget().GetImages();

  SymbolContextList sc_list;
  modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list);
  const size_t matching_symbols = sc_list.GetSize();

  if (matching_symbols) {
    SymbolContext sc;

    sc_list.GetContextAtIndex(0, sc);

    ModuleSP module_sp(sc.module_sp);

    if (!module_sp)
      return TypeSP();

    const bool exact_match = true;
    const uint32_t max_matches = UINT32_MAX;
    TypeList types;

    llvm::DenseSet<SymbolFile *> searched_symbol_files;
    module_sp->FindTypes(name, exact_match, max_matches, searched_symbol_files,
                         types);

    for (uint32_t i = 0; i < types.GetSize(); ++i) {
      TypeSP type_sp(types.GetTypeAtIndex(i));

      if (ClangASTContext::IsObjCObjectOrInterfaceType(
              type_sp->GetForwardCompilerType())) {
        if (type_sp->IsCompleteObjCClass()) {
          m_complete_class_cache[name] = type_sp;
          return type_sp;
        }
      }
    }
  }
  m_negative_complete_class_cache.insert(name);
  return TypeSP();
}

size_t ObjCLanguageRuntime::GetByteOffsetForIvar(CompilerType &parent_qual_type,
                                                 const char *ivar_name) {
  return LLDB_INVALID_IVAR_OFFSET;
}

bool ObjCLanguageRuntime::ClassDescriptor::IsPointerValid(
    lldb::addr_t value, uint32_t ptr_size, bool allow_NULLs, bool allow_tagged,
    bool check_version_specific) const {
  if (!value)
    return allow_NULLs;
  if ((value % 2) == 1 && allow_tagged)
    return true;
  if ((value % ptr_size) == 0)
    return (check_version_specific ? CheckPointer(value, ptr_size) : true);
  else
    return false;
}

ObjCLanguageRuntime::ObjCISA
ObjCLanguageRuntime::GetISA(ConstString name) {
  ISAToDescriptorIterator pos = GetDescriptorIterator(name);
  if (pos != m_isa_to_descriptor.end())
    return pos->first;
  return 0;
}

ObjCLanguageRuntime::ISAToDescriptorIterator
ObjCLanguageRuntime::GetDescriptorIterator(ConstString name) {
  ISAToDescriptorIterator end = m_isa_to_descriptor.end();

  if (name) {
    UpdateISAToDescriptorMap();
    if (m_hash_to_isa_map.empty()) {
      // No name hashes were provided, we need to just linearly power through
      // the names and find a match
      for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin();
           pos != end; ++pos) {
        if (pos->second->GetClassName() == name)
          return pos;
      }
    } else {
      // Name hashes were provided, so use them to efficiently lookup name to
      // isa/descriptor
      const uint32_t name_hash = llvm::djbHash(name.GetStringRef());
      std::pair<HashToISAIterator, HashToISAIterator> range =
          m_hash_to_isa_map.equal_range(name_hash);
      for (HashToISAIterator range_pos = range.first; range_pos != range.second;
           ++range_pos) {
        ISAToDescriptorIterator pos =
            m_isa_to_descriptor.find(range_pos->second);
        if (pos != m_isa_to_descriptor.end()) {
          if (pos->second->GetClassName() == name)
            return pos;
        }
      }
    }
  }
  return end;
}

std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
          ObjCLanguageRuntime::ISAToDescriptorIterator>
ObjCLanguageRuntime::GetDescriptorIteratorPair(bool update_if_needed) {
  if (update_if_needed)
    UpdateISAToDescriptorMapIfNeeded();

  return std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
                   ObjCLanguageRuntime::ISAToDescriptorIterator>(
      m_isa_to_descriptor.begin(), m_isa_to_descriptor.end());
}

ObjCLanguageRuntime::ObjCISA
ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) {
  ClassDescriptorSP objc_class_sp(GetClassDescriptorFromISA(isa));
  if (objc_class_sp) {
    ClassDescriptorSP objc_super_class_sp(objc_class_sp->GetSuperclass());
    if (objc_super_class_sp)
      return objc_super_class_sp->GetISA();
  }
  return 0;
}

ConstString
ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) {
  ClassDescriptorSP objc_class_sp(GetNonKVOClassDescriptor(isa));
  if (objc_class_sp)
    return objc_class_sp->GetClassName();
  return ConstString();
}

ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetClassDescriptorFromClassName(
    ConstString class_name) {
  ISAToDescriptorIterator pos = GetDescriptorIterator(class_name);
  if (pos != m_isa_to_descriptor.end())
    return pos->second;
  return ClassDescriptorSP();
}

ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetClassDescriptor(ValueObject &valobj) {
  ClassDescriptorSP objc_class_sp;
  // if we get an invalid VO (which might still happen when playing around with
  // pointers returned by the expression parser, don't consider this a valid
  // ObjC object)
  if (valobj.GetCompilerType().IsValid()) {
    addr_t isa_pointer = valobj.GetPointerValue();
    if (isa_pointer != LLDB_INVALID_ADDRESS) {
      ExecutionContext exe_ctx(valobj.GetExecutionContextRef());

      Process *process = exe_ctx.GetProcessPtr();
      if (process) {
        Status error;
        ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
        if (isa != LLDB_INVALID_ADDRESS)
          objc_class_sp = GetClassDescriptorFromISA(isa);
      }
    }
  }
  return objc_class_sp;
}

ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetNonKVOClassDescriptor(ValueObject &valobj) {
  ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp(
      GetClassDescriptor(valobj));
  if (objc_class_sp) {
    if (!objc_class_sp->IsKVO())
      return objc_class_sp;

    ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
    if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
      return non_kvo_objc_class_sp;
  }
  return ClassDescriptorSP();
}

ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetClassDescriptorFromISA(ObjCISA isa) {
  if (isa) {
    UpdateISAToDescriptorMap();
    ObjCLanguageRuntime::ISAToDescriptorIterator pos =
        m_isa_to_descriptor.find(isa);
    if (pos != m_isa_to_descriptor.end())
      return pos->second;
  }
  return ClassDescriptorSP();
}

ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetNonKVOClassDescriptor(ObjCISA isa) {
  if (isa) {
    ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA(isa);
    if (objc_class_sp && objc_class_sp->IsValid()) {
      if (!objc_class_sp->IsKVO())
        return objc_class_sp;

      ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
      if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
        return non_kvo_objc_class_sp;
    }
  }
  return ClassDescriptorSP();
}

CompilerType
ObjCLanguageRuntime::EncodingToType::RealizeType(const char *name,
                                                 bool for_expression) {
  if (m_scratch_ast_ctx_up)
    return RealizeType(*m_scratch_ast_ctx_up, name, for_expression);
  return CompilerType();
}

CompilerType ObjCLanguageRuntime::EncodingToType::RealizeType(
    ClangASTContext &ast_ctx, const char *name, bool for_expression) {
  clang::ASTContext *clang_ast = ast_ctx.getASTContext();
  if (!clang_ast)
    return CompilerType();
  return RealizeType(*clang_ast, name, for_expression);
}

ObjCLanguageRuntime::EncodingToType::~EncodingToType() {}

ObjCLanguageRuntime::EncodingToTypeSP ObjCLanguageRuntime::GetEncodingToType() {
  return nullptr;
}

bool ObjCLanguageRuntime::GetTypeBitSize(const CompilerType &compiler_type,
                                         uint64_t &size) {
  void *opaque_ptr = compiler_type.GetOpaqueQualType();
  size = m_type_size_cache.Lookup(opaque_ptr);
  // an ObjC object will at least have an ISA, so 0 is definitely not OK
  if (size > 0)
    return true;

  ClassDescriptorSP class_descriptor_sp =
      GetClassDescriptorFromClassName(compiler_type.GetTypeName());
  if (!class_descriptor_sp)
    return false;

  int32_t max_offset = INT32_MIN;
  uint64_t sizeof_max = 0;
  bool found = false;

  for (size_t idx = 0; idx < class_descriptor_sp->GetNumIVars(); idx++) {
    const auto &ivar = class_descriptor_sp->GetIVarAtIndex(idx);
    int32_t cur_offset = ivar.m_offset;
    if (cur_offset > max_offset) {
      max_offset = cur_offset;
      sizeof_max = ivar.m_size;
      found = true;
    }
  }

  size = 8 * (max_offset + sizeof_max);
  if (found)
    m_type_size_cache.Insert(opaque_ptr, size);

  return found;
}

lldb::BreakpointPreconditionSP
ObjCLanguageRuntime::GetBreakpointExceptionPrecondition(LanguageType language,
                                                        bool throw_bp) {
  if (language != eLanguageTypeObjC)
    return lldb::BreakpointPreconditionSP();
  if (!throw_bp)
    return lldb::BreakpointPreconditionSP();
  BreakpointPreconditionSP precondition_sp(
      new ObjCLanguageRuntime::ObjCExceptionPrecondition());
  return precondition_sp;
}

// Exception breakpoint Precondition class for ObjC:
void ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName(
    const char *class_name) {
  m_class_names.insert(class_name);
}

ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() {}

bool ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition(
    StoppointCallbackContext &context) {
  return true;
}

void ObjCLanguageRuntime::ObjCExceptionPrecondition::GetDescription(
    Stream &stream, lldb::DescriptionLevel level) {}

Status ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition(
    Args &args) {
  Status error;
  if (args.GetArgumentCount() > 0)
    error.SetErrorString(
        "The ObjC Exception breakpoint doesn't support extra options.");
  return error;
}

llvm::Optional<CompilerType>
ObjCLanguageRuntime::GetRuntimeType(CompilerType base_type) {
  CompilerType class_type;
  bool is_pointer_type = false;

  if (ClangASTContext::IsObjCObjectPointerType(base_type, &class_type))
    is_pointer_type = true;
  else if (ClangASTContext::IsObjCObjectOrInterfaceType(base_type))
    class_type = base_type;
  else
    return llvm::None;

  if (!class_type)
    return llvm::None;

  ConstString class_name(class_type.GetConstTypeName());
  if (!class_name)
    return llvm::None;

  TypeSP complete_objc_class_type_sp = LookupInCompleteClassCache(class_name);
  if (!complete_objc_class_type_sp)
    return llvm::None;

  CompilerType complete_class(
      complete_objc_class_type_sp->GetFullCompilerType());
  if (complete_class.GetCompleteType()) {
    if (is_pointer_type)
      return complete_class.GetPointerType();
    else
      return complete_class;
  }

  return llvm::None;
}
