xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- ObjCLanguageRuntime.cpp -------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric #include "clang/AST/Type.h"
90b57cec5SDimitry Andric 
100b57cec5SDimitry Andric #include "ObjCLanguageRuntime.h"
110b57cec5SDimitry Andric 
125ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
130b57cec5SDimitry Andric #include "lldb/Core/Module.h"
140b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h"
150b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
160b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
170b57cec5SDimitry Andric #include "lldb/Symbol/SymbolFile.h"
180b57cec5SDimitry Andric #include "lldb/Symbol/Type.h"
190b57cec5SDimitry Andric #include "lldb/Symbol/TypeList.h"
200b57cec5SDimitry Andric #include "lldb/Symbol/Variable.h"
21349cc55cSDimitry Andric #include "lldb/Target/ABI.h"
2281ad6265SDimitry Andric #include "lldb/Target/Target.h"
2381ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
240b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
250b57cec5SDimitry Andric #include "lldb/Utility/Timer.h"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
280b57cec5SDimitry Andric #include "llvm/Support/DJB.h"
29bdd1243dSDimitry Andric #include <optional>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace lldb;
320b57cec5SDimitry Andric using namespace lldb_private;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric char ObjCLanguageRuntime::ID = 0;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric // Destructor
37fe6060f1SDimitry Andric ObjCLanguageRuntime::~ObjCLanguageRuntime() = default;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process)
4081ad6265SDimitry Andric     : LanguageRuntime(process), m_impl_cache(), m_impl_str_cache(),
410b57cec5SDimitry Andric       m_has_new_literals_and_indexing(eLazyBoolCalculate),
420b57cec5SDimitry Andric       m_isa_to_descriptor(), m_hash_to_isa_map(), m_type_size_cache(),
430b57cec5SDimitry Andric       m_isa_to_descriptor_stop_id(UINT32_MAX), m_complete_class_cache(),
440b57cec5SDimitry Andric       m_negative_complete_class_cache() {}
450b57cec5SDimitry Andric 
465ffd83dbSDimitry Andric bool ObjCLanguageRuntime::IsAllowedRuntimeValue(ConstString name) {
470b57cec5SDimitry Andric   static ConstString g_self = ConstString("self");
480b57cec5SDimitry Andric   static ConstString g_cmd = ConstString("_cmd");
490b57cec5SDimitry Andric   return name == g_self || name == g_cmd;
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric bool ObjCLanguageRuntime::AddClass(ObjCISA isa,
530b57cec5SDimitry Andric                                    const ClassDescriptorSP &descriptor_sp,
540b57cec5SDimitry Andric                                    const char *class_name) {
550b57cec5SDimitry Andric   if (isa != 0) {
560b57cec5SDimitry Andric     m_isa_to_descriptor[isa] = descriptor_sp;
570b57cec5SDimitry Andric     // class_name is assumed to be valid
580b57cec5SDimitry Andric     m_hash_to_isa_map.insert(std::make_pair(llvm::djbHash(class_name), isa));
590b57cec5SDimitry Andric     return true;
600b57cec5SDimitry Andric   }
610b57cec5SDimitry Andric   return false;
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric void ObjCLanguageRuntime::AddToMethodCache(lldb::addr_t class_addr,
650b57cec5SDimitry Andric                                            lldb::addr_t selector,
660b57cec5SDimitry Andric                                            lldb::addr_t impl_addr) {
6781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
680b57cec5SDimitry Andric   if (log) {
699dba64beSDimitry Andric     LLDB_LOGF(log,
709dba64beSDimitry Andric               "Caching: class 0x%" PRIx64 " selector 0x%" PRIx64
710b57cec5SDimitry Andric               " implementation 0x%" PRIx64 ".",
720b57cec5SDimitry Andric               class_addr, selector, impl_addr);
730b57cec5SDimitry Andric   }
740b57cec5SDimitry Andric   m_impl_cache.insert(std::pair<ClassAndSel, lldb::addr_t>(
750b57cec5SDimitry Andric       ClassAndSel(class_addr, selector), impl_addr));
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
7881ad6265SDimitry Andric void ObjCLanguageRuntime::AddToMethodCache(lldb::addr_t class_addr,
7981ad6265SDimitry Andric                                            llvm::StringRef sel_str,
8081ad6265SDimitry Andric                                            lldb::addr_t impl_addr) {
8181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
8281ad6265SDimitry Andric 
8381ad6265SDimitry Andric   LLDB_LOG(log, "Caching: class {0} selector {1} implementation {2}.",
8481ad6265SDimitry Andric            class_addr, sel_str, impl_addr);
8581ad6265SDimitry Andric 
8681ad6265SDimitry Andric   m_impl_str_cache.insert(std::pair<ClassAndSelStr, lldb::addr_t>(
8781ad6265SDimitry Andric       ClassAndSelStr(class_addr, sel_str), impl_addr));
8881ad6265SDimitry Andric }
8981ad6265SDimitry Andric 
900b57cec5SDimitry Andric lldb::addr_t ObjCLanguageRuntime::LookupInMethodCache(lldb::addr_t class_addr,
910b57cec5SDimitry Andric                                                       lldb::addr_t selector) {
920b57cec5SDimitry Andric   MsgImplMap::iterator pos, end = m_impl_cache.end();
930b57cec5SDimitry Andric   pos = m_impl_cache.find(ClassAndSel(class_addr, selector));
940b57cec5SDimitry Andric   if (pos != end)
950b57cec5SDimitry Andric     return (*pos).second;
960b57cec5SDimitry Andric   return LLDB_INVALID_ADDRESS;
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric 
9981ad6265SDimitry Andric lldb::addr_t ObjCLanguageRuntime::LookupInMethodCache(lldb::addr_t class_addr,
10081ad6265SDimitry Andric                                                       llvm::StringRef sel_str) {
10181ad6265SDimitry Andric   MsgImplStrMap::iterator pos, end = m_impl_str_cache.end();
10281ad6265SDimitry Andric   pos = m_impl_str_cache.find(ClassAndSelStr(class_addr, sel_str));
10381ad6265SDimitry Andric   if (pos != end)
10481ad6265SDimitry Andric     return (*pos).second;
10581ad6265SDimitry Andric   return LLDB_INVALID_ADDRESS;
10681ad6265SDimitry Andric }
10781ad6265SDimitry Andric 
1080b57cec5SDimitry Andric lldb::TypeSP
1090b57cec5SDimitry Andric ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) {
1100b57cec5SDimitry Andric   CompleteClassMap::iterator complete_class_iter =
1110b57cec5SDimitry Andric       m_complete_class_cache.find(name);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   if (complete_class_iter != m_complete_class_cache.end()) {
1140b57cec5SDimitry Andric     // Check the weak pointer to make sure the type hasn't been unloaded
1150b57cec5SDimitry Andric     TypeSP complete_type_sp(complete_class_iter->second.lock());
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric     if (complete_type_sp)
1180b57cec5SDimitry Andric       return complete_type_sp;
1190b57cec5SDimitry Andric     else
1200b57cec5SDimitry Andric       m_complete_class_cache.erase(name);
1210b57cec5SDimitry Andric   }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   if (m_negative_complete_class_cache.count(name) > 0)
1240b57cec5SDimitry Andric     return TypeSP();
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   const ModuleList &modules = m_process->GetTarget().GetImages();
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   SymbolContextList sc_list;
1290b57cec5SDimitry Andric   modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list);
1309dba64beSDimitry Andric   const size_t matching_symbols = sc_list.GetSize();
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   if (matching_symbols) {
1330b57cec5SDimitry Andric     SymbolContext sc;
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric     sc_list.GetContextAtIndex(0, sc);
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric     ModuleSP module_sp(sc.module_sp);
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric     if (!module_sp)
1400b57cec5SDimitry Andric       return TypeSP();
1410b57cec5SDimitry Andric 
1425f757f3fSDimitry Andric     TypeQuery query(name.GetStringRef(), TypeQueryOptions::e_exact_match);
1435f757f3fSDimitry Andric     TypeResults results;
1445f757f3fSDimitry Andric     module_sp->FindTypes(query, results);
1455f757f3fSDimitry Andric     for (const TypeSP &type_sp : results.GetTypeMap().Types()) {
1465ffd83dbSDimitry Andric       if (TypeSystemClang::IsObjCObjectOrInterfaceType(
1470b57cec5SDimitry Andric               type_sp->GetForwardCompilerType())) {
1485ffd83dbSDimitry Andric         if (TypePayloadClang(type_sp->GetPayload()).IsCompleteObjCClass()) {
1490b57cec5SDimitry Andric           m_complete_class_cache[name] = type_sp;
1500b57cec5SDimitry Andric           return type_sp;
1510b57cec5SDimitry Andric         }
1520b57cec5SDimitry Andric       }
1530b57cec5SDimitry Andric     }
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric   m_negative_complete_class_cache.insert(name);
1560b57cec5SDimitry Andric   return TypeSP();
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric size_t ObjCLanguageRuntime::GetByteOffsetForIvar(CompilerType &parent_qual_type,
1600b57cec5SDimitry Andric                                                  const char *ivar_name) {
1610b57cec5SDimitry Andric   return LLDB_INVALID_IVAR_OFFSET;
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric bool ObjCLanguageRuntime::ClassDescriptor::IsPointerValid(
1650b57cec5SDimitry Andric     lldb::addr_t value, uint32_t ptr_size, bool allow_NULLs, bool allow_tagged,
1660b57cec5SDimitry Andric     bool check_version_specific) const {
1670b57cec5SDimitry Andric   if (!value)
1680b57cec5SDimitry Andric     return allow_NULLs;
1690b57cec5SDimitry Andric   if ((value % 2) == 1 && allow_tagged)
1700b57cec5SDimitry Andric     return true;
1710b57cec5SDimitry Andric   if ((value % ptr_size) == 0)
1720b57cec5SDimitry Andric     return (check_version_specific ? CheckPointer(value, ptr_size) : true);
1730b57cec5SDimitry Andric   else
1740b57cec5SDimitry Andric     return false;
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric ObjCLanguageRuntime::ObjCISA
1780b57cec5SDimitry Andric ObjCLanguageRuntime::GetISA(ConstString name) {
1790b57cec5SDimitry Andric   ISAToDescriptorIterator pos = GetDescriptorIterator(name);
1800b57cec5SDimitry Andric   if (pos != m_isa_to_descriptor.end())
1810b57cec5SDimitry Andric     return pos->first;
1820b57cec5SDimitry Andric   return 0;
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric ObjCLanguageRuntime::ISAToDescriptorIterator
1860b57cec5SDimitry Andric ObjCLanguageRuntime::GetDescriptorIterator(ConstString name) {
1870b57cec5SDimitry Andric   ISAToDescriptorIterator end = m_isa_to_descriptor.end();
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   if (name) {
1900b57cec5SDimitry Andric     UpdateISAToDescriptorMap();
1910b57cec5SDimitry Andric     if (m_hash_to_isa_map.empty()) {
1920b57cec5SDimitry Andric       // No name hashes were provided, we need to just linearly power through
1930b57cec5SDimitry Andric       // the names and find a match
1940b57cec5SDimitry Andric       for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin();
1950b57cec5SDimitry Andric            pos != end; ++pos) {
1960b57cec5SDimitry Andric         if (pos->second->GetClassName() == name)
1970b57cec5SDimitry Andric           return pos;
1980b57cec5SDimitry Andric       }
1990b57cec5SDimitry Andric     } else {
2000b57cec5SDimitry Andric       // Name hashes were provided, so use them to efficiently lookup name to
2010b57cec5SDimitry Andric       // isa/descriptor
2020b57cec5SDimitry Andric       const uint32_t name_hash = llvm::djbHash(name.GetStringRef());
2030b57cec5SDimitry Andric       std::pair<HashToISAIterator, HashToISAIterator> range =
2040b57cec5SDimitry Andric           m_hash_to_isa_map.equal_range(name_hash);
2050b57cec5SDimitry Andric       for (HashToISAIterator range_pos = range.first; range_pos != range.second;
2060b57cec5SDimitry Andric            ++range_pos) {
2070b57cec5SDimitry Andric         ISAToDescriptorIterator pos =
2080b57cec5SDimitry Andric             m_isa_to_descriptor.find(range_pos->second);
2090b57cec5SDimitry Andric         if (pos != m_isa_to_descriptor.end()) {
2100b57cec5SDimitry Andric           if (pos->second->GetClassName() == name)
2110b57cec5SDimitry Andric             return pos;
2120b57cec5SDimitry Andric         }
2130b57cec5SDimitry Andric       }
2140b57cec5SDimitry Andric     }
2150b57cec5SDimitry Andric   }
2160b57cec5SDimitry Andric   return end;
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
2200b57cec5SDimitry Andric           ObjCLanguageRuntime::ISAToDescriptorIterator>
2210b57cec5SDimitry Andric ObjCLanguageRuntime::GetDescriptorIteratorPair(bool update_if_needed) {
2220b57cec5SDimitry Andric   if (update_if_needed)
2230b57cec5SDimitry Andric     UpdateISAToDescriptorMapIfNeeded();
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   return std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
2260b57cec5SDimitry Andric                    ObjCLanguageRuntime::ISAToDescriptorIterator>(
2270b57cec5SDimitry Andric       m_isa_to_descriptor.begin(), m_isa_to_descriptor.end());
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric 
23006c3fb27SDimitry Andric void ObjCLanguageRuntime::ReadObjCLibraryIfNeeded(
23106c3fb27SDimitry Andric     const ModuleList &module_list) {
23206c3fb27SDimitry Andric   if (!HasReadObjCLibrary()) {
23306c3fb27SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
23406c3fb27SDimitry Andric 
23506c3fb27SDimitry Andric     size_t num_modules = module_list.GetSize();
23606c3fb27SDimitry Andric     for (size_t i = 0; i < num_modules; i++) {
23706c3fb27SDimitry Andric       auto mod = module_list.GetModuleAtIndex(i);
23806c3fb27SDimitry Andric       if (IsModuleObjCLibrary(mod)) {
23906c3fb27SDimitry Andric         ReadObjCLibrary(mod);
24006c3fb27SDimitry Andric         break;
24106c3fb27SDimitry Andric       }
24206c3fb27SDimitry Andric     }
24306c3fb27SDimitry Andric   }
24406c3fb27SDimitry Andric }
24506c3fb27SDimitry Andric 
2460b57cec5SDimitry Andric ObjCLanguageRuntime::ObjCISA
2470b57cec5SDimitry Andric ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) {
2480b57cec5SDimitry Andric   ClassDescriptorSP objc_class_sp(GetClassDescriptorFromISA(isa));
2490b57cec5SDimitry Andric   if (objc_class_sp) {
2500b57cec5SDimitry Andric     ClassDescriptorSP objc_super_class_sp(objc_class_sp->GetSuperclass());
2510b57cec5SDimitry Andric     if (objc_super_class_sp)
2520b57cec5SDimitry Andric       return objc_super_class_sp->GetISA();
2530b57cec5SDimitry Andric   }
2540b57cec5SDimitry Andric   return 0;
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP
2580b57cec5SDimitry Andric ObjCLanguageRuntime::GetClassDescriptorFromClassName(
2590b57cec5SDimitry Andric     ConstString class_name) {
2600b57cec5SDimitry Andric   ISAToDescriptorIterator pos = GetDescriptorIterator(class_name);
2610b57cec5SDimitry Andric   if (pos != m_isa_to_descriptor.end())
2620b57cec5SDimitry Andric     return pos->second;
2630b57cec5SDimitry Andric   return ClassDescriptorSP();
2640b57cec5SDimitry Andric }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP
2670b57cec5SDimitry Andric ObjCLanguageRuntime::GetClassDescriptor(ValueObject &valobj) {
2680b57cec5SDimitry Andric   ClassDescriptorSP objc_class_sp;
2690b57cec5SDimitry Andric   // if we get an invalid VO (which might still happen when playing around with
2700b57cec5SDimitry Andric   // pointers returned by the expression parser, don't consider this a valid
2710b57cec5SDimitry Andric   // ObjC object)
2720b57cec5SDimitry Andric   if (valobj.GetCompilerType().IsValid()) {
2730b57cec5SDimitry Andric     addr_t isa_pointer = valobj.GetPointerValue();
2740b57cec5SDimitry Andric     if (isa_pointer != LLDB_INVALID_ADDRESS) {
2750b57cec5SDimitry Andric       ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric       Process *process = exe_ctx.GetProcessPtr();
2780b57cec5SDimitry Andric       if (process) {
2790b57cec5SDimitry Andric         Status error;
2800b57cec5SDimitry Andric         ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
2810b57cec5SDimitry Andric         if (isa != LLDB_INVALID_ADDRESS)
2820b57cec5SDimitry Andric           objc_class_sp = GetClassDescriptorFromISA(isa);
2830b57cec5SDimitry Andric       }
2840b57cec5SDimitry Andric     }
2850b57cec5SDimitry Andric   }
2860b57cec5SDimitry Andric   return objc_class_sp;
2870b57cec5SDimitry Andric }
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP
2900b57cec5SDimitry Andric ObjCLanguageRuntime::GetNonKVOClassDescriptor(ValueObject &valobj) {
2910b57cec5SDimitry Andric   ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp(
2920b57cec5SDimitry Andric       GetClassDescriptor(valobj));
2930b57cec5SDimitry Andric   if (objc_class_sp) {
2940b57cec5SDimitry Andric     if (!objc_class_sp->IsKVO())
2950b57cec5SDimitry Andric       return objc_class_sp;
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric     ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
2980b57cec5SDimitry Andric     if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
2990b57cec5SDimitry Andric       return non_kvo_objc_class_sp;
3000b57cec5SDimitry Andric   }
3010b57cec5SDimitry Andric   return ClassDescriptorSP();
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP
3050b57cec5SDimitry Andric ObjCLanguageRuntime::GetClassDescriptorFromISA(ObjCISA isa) {
3060b57cec5SDimitry Andric   if (isa) {
3070b57cec5SDimitry Andric     UpdateISAToDescriptorMap();
308349cc55cSDimitry Andric 
3090b57cec5SDimitry Andric     ObjCLanguageRuntime::ISAToDescriptorIterator pos =
3100b57cec5SDimitry Andric         m_isa_to_descriptor.find(isa);
3110b57cec5SDimitry Andric     if (pos != m_isa_to_descriptor.end())
3120b57cec5SDimitry Andric       return pos->second;
313349cc55cSDimitry Andric 
314349cc55cSDimitry Andric     if (ABISP abi_sp = m_process->GetABI()) {
315349cc55cSDimitry Andric       pos = m_isa_to_descriptor.find(abi_sp->FixCodeAddress(isa));
316349cc55cSDimitry Andric       if (pos != m_isa_to_descriptor.end())
317349cc55cSDimitry Andric         return pos->second;
318349cc55cSDimitry Andric     }
3190b57cec5SDimitry Andric   }
3200b57cec5SDimitry Andric   return ClassDescriptorSP();
3210b57cec5SDimitry Andric }
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP
3240b57cec5SDimitry Andric ObjCLanguageRuntime::GetNonKVOClassDescriptor(ObjCISA isa) {
3250b57cec5SDimitry Andric   if (isa) {
3260b57cec5SDimitry Andric     ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA(isa);
3270b57cec5SDimitry Andric     if (objc_class_sp && objc_class_sp->IsValid()) {
3280b57cec5SDimitry Andric       if (!objc_class_sp->IsKVO())
3290b57cec5SDimitry Andric         return objc_class_sp;
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric       ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
3320b57cec5SDimitry Andric       if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
3330b57cec5SDimitry Andric         return non_kvo_objc_class_sp;
3340b57cec5SDimitry Andric     }
3350b57cec5SDimitry Andric   }
3360b57cec5SDimitry Andric   return ClassDescriptorSP();
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric CompilerType
3400b57cec5SDimitry Andric ObjCLanguageRuntime::EncodingToType::RealizeType(const char *name,
3410b57cec5SDimitry Andric                                                  bool for_expression) {
342bdd1243dSDimitry Andric   if (m_scratch_ast_ctx_sp)
343bdd1243dSDimitry Andric     return RealizeType(*m_scratch_ast_ctx_sp, name, for_expression);
3440b57cec5SDimitry Andric   return CompilerType();
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric 
347fe6060f1SDimitry Andric ObjCLanguageRuntime::EncodingToType::~EncodingToType() = default;
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric ObjCLanguageRuntime::EncodingToTypeSP ObjCLanguageRuntime::GetEncodingToType() {
3500b57cec5SDimitry Andric   return nullptr;
3510b57cec5SDimitry Andric }
3520b57cec5SDimitry Andric 
353*0fca6ea1SDimitry Andric std::optional<uint64_t>
354*0fca6ea1SDimitry Andric ObjCLanguageRuntime::GetTypeBitSize(const CompilerType &compiler_type) {
3550b57cec5SDimitry Andric   void *opaque_ptr = compiler_type.GetOpaqueQualType();
356*0fca6ea1SDimitry Andric   uint64_t cached_size = m_type_size_cache.Lookup(opaque_ptr);
357*0fca6ea1SDimitry Andric   if (cached_size > 0)
358*0fca6ea1SDimitry Andric     return cached_size;
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   ClassDescriptorSP class_descriptor_sp =
3610b57cec5SDimitry Andric       GetClassDescriptorFromClassName(compiler_type.GetTypeName());
3620b57cec5SDimitry Andric   if (!class_descriptor_sp)
363*0fca6ea1SDimitry Andric     return {};
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   int32_t max_offset = INT32_MIN;
3660b57cec5SDimitry Andric   uint64_t sizeof_max = 0;
3670b57cec5SDimitry Andric   bool found = false;
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   for (size_t idx = 0; idx < class_descriptor_sp->GetNumIVars(); idx++) {
3700b57cec5SDimitry Andric     const auto &ivar = class_descriptor_sp->GetIVarAtIndex(idx);
3710b57cec5SDimitry Andric     int32_t cur_offset = ivar.m_offset;
3720b57cec5SDimitry Andric     if (cur_offset > max_offset) {
3730b57cec5SDimitry Andric       max_offset = cur_offset;
3740b57cec5SDimitry Andric       sizeof_max = ivar.m_size;
3750b57cec5SDimitry Andric       found = true;
3760b57cec5SDimitry Andric     }
3770b57cec5SDimitry Andric   }
3780b57cec5SDimitry Andric 
379*0fca6ea1SDimitry Andric   uint64_t size = 8 * (max_offset + sizeof_max);
380*0fca6ea1SDimitry Andric   if (found && size > 0) {
3810b57cec5SDimitry Andric     m_type_size_cache.Insert(opaque_ptr, size);
382*0fca6ea1SDimitry Andric     return size;
383*0fca6ea1SDimitry Andric   }
3840b57cec5SDimitry Andric 
385*0fca6ea1SDimitry Andric   return {};
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric lldb::BreakpointPreconditionSP
3890b57cec5SDimitry Andric ObjCLanguageRuntime::GetBreakpointExceptionPrecondition(LanguageType language,
3900b57cec5SDimitry Andric                                                         bool throw_bp) {
3910b57cec5SDimitry Andric   if (language != eLanguageTypeObjC)
3920b57cec5SDimitry Andric     return lldb::BreakpointPreconditionSP();
3930b57cec5SDimitry Andric   if (!throw_bp)
3940b57cec5SDimitry Andric     return lldb::BreakpointPreconditionSP();
3950b57cec5SDimitry Andric   BreakpointPreconditionSP precondition_sp(
3960b57cec5SDimitry Andric       new ObjCLanguageRuntime::ObjCExceptionPrecondition());
3970b57cec5SDimitry Andric   return precondition_sp;
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric // Exception breakpoint Precondition class for ObjC:
4010b57cec5SDimitry Andric void ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName(
4020b57cec5SDimitry Andric     const char *class_name) {
4030b57cec5SDimitry Andric   m_class_names.insert(class_name);
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric 
406fe6060f1SDimitry Andric ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() =
407fe6060f1SDimitry Andric     default;
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric bool ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition(
4100b57cec5SDimitry Andric     StoppointCallbackContext &context) {
4110b57cec5SDimitry Andric   return true;
4120b57cec5SDimitry Andric }
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric void ObjCLanguageRuntime::ObjCExceptionPrecondition::GetDescription(
4150b57cec5SDimitry Andric     Stream &stream, lldb::DescriptionLevel level) {}
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric Status ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition(
4180b57cec5SDimitry Andric     Args &args) {
4190b57cec5SDimitry Andric   Status error;
4200b57cec5SDimitry Andric   if (args.GetArgumentCount() > 0)
4210b57cec5SDimitry Andric     error.SetErrorString(
4220b57cec5SDimitry Andric         "The ObjC Exception breakpoint doesn't support extra options.");
4230b57cec5SDimitry Andric   return error;
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric 
426bdd1243dSDimitry Andric std::optional<CompilerType>
4270b57cec5SDimitry Andric ObjCLanguageRuntime::GetRuntimeType(CompilerType base_type) {
4280b57cec5SDimitry Andric   CompilerType class_type;
4290b57cec5SDimitry Andric   bool is_pointer_type = false;
4300b57cec5SDimitry Andric 
4315ffd83dbSDimitry Andric   if (TypeSystemClang::IsObjCObjectPointerType(base_type, &class_type))
4320b57cec5SDimitry Andric     is_pointer_type = true;
4335ffd83dbSDimitry Andric   else if (TypeSystemClang::IsObjCObjectOrInterfaceType(base_type))
4340b57cec5SDimitry Andric     class_type = base_type;
4350b57cec5SDimitry Andric   else
436bdd1243dSDimitry Andric     return std::nullopt;
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric   if (!class_type)
439bdd1243dSDimitry Andric     return std::nullopt;
4400b57cec5SDimitry Andric 
4415ffd83dbSDimitry Andric   ConstString class_name(class_type.GetTypeName());
4420b57cec5SDimitry Andric   if (!class_name)
443bdd1243dSDimitry Andric     return std::nullopt;
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   TypeSP complete_objc_class_type_sp = LookupInCompleteClassCache(class_name);
4460b57cec5SDimitry Andric   if (!complete_objc_class_type_sp)
447bdd1243dSDimitry Andric     return std::nullopt;
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   CompilerType complete_class(
4500b57cec5SDimitry Andric       complete_objc_class_type_sp->GetFullCompilerType());
4510b57cec5SDimitry Andric   if (complete_class.GetCompleteType()) {
4520b57cec5SDimitry Andric     if (is_pointer_type)
4530b57cec5SDimitry Andric       return complete_class.GetPointerType();
4540b57cec5SDimitry Andric     else
4550b57cec5SDimitry Andric       return complete_class;
4560b57cec5SDimitry Andric   }
4570b57cec5SDimitry Andric 
458bdd1243dSDimitry Andric   return std::nullopt;
4590b57cec5SDimitry Andric }
460