180814287SRaphael Isemann //===-- ObjCLanguageRuntime.cpp -------------------------------------------===//
2b5701710SAlex Langford //
3b5701710SAlex Langford // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b5701710SAlex Langford // See https://llvm.org/LICENSE.txt for license information.
5b5701710SAlex Langford // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b5701710SAlex Langford //
7b5701710SAlex Langford //===----------------------------------------------------------------------===//
8b5701710SAlex Langford #include "clang/AST/Type.h"
9b5701710SAlex Langford 
10b5701710SAlex Langford #include "ObjCLanguageRuntime.h"
11b5701710SAlex Langford 
128be30215SAlex Langford #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
13b5701710SAlex Langford #include "lldb/Core/MappedHash.h"
14b5701710SAlex Langford #include "lldb/Core/Module.h"
15b5701710SAlex Langford #include "lldb/Core/PluginManager.h"
16b5701710SAlex Langford #include "lldb/Core/ValueObject.h"
17b5701710SAlex Langford #include "lldb/Symbol/SymbolContext.h"
18b5701710SAlex Langford #include "lldb/Symbol/SymbolFile.h"
19b5701710SAlex Langford #include "lldb/Symbol/Type.h"
20b5701710SAlex Langford #include "lldb/Symbol/TypeList.h"
21b5701710SAlex Langford #include "lldb/Symbol/Variable.h"
228bac9e36SJonas Devlieghere #include "lldb/Target/ABI.h"
23c34698a8SPavel Labath #include "lldb/Target/Target.h"
24c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
25b5701710SAlex Langford #include "lldb/Utility/Log.h"
26b5701710SAlex Langford #include "lldb/Utility/Timer.h"
27b5701710SAlex Langford 
28b5701710SAlex Langford #include "llvm/ADT/StringRef.h"
29b5701710SAlex Langford #include "llvm/Support/DJB.h"
30b5701710SAlex Langford 
31b5701710SAlex Langford using namespace lldb;
32b5701710SAlex Langford using namespace lldb_private;
33b5701710SAlex Langford 
34b5701710SAlex Langford char ObjCLanguageRuntime::ID = 0;
35b5701710SAlex Langford 
36b5701710SAlex Langford // Destructor
37fd2433e1SJonas Devlieghere ObjCLanguageRuntime::~ObjCLanguageRuntime() = default;
38b5701710SAlex Langford 
ObjCLanguageRuntime(Process * process)39b5701710SAlex Langford ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process)
40*833882b3SJim Ingham     : LanguageRuntime(process), m_impl_cache(), m_impl_str_cache(),
41b5701710SAlex Langford       m_has_new_literals_and_indexing(eLazyBoolCalculate),
42b5701710SAlex Langford       m_isa_to_descriptor(), m_hash_to_isa_map(), m_type_size_cache(),
43b5701710SAlex Langford       m_isa_to_descriptor_stop_id(UINT32_MAX), m_complete_class_cache(),
44b5701710SAlex Langford       m_negative_complete_class_cache() {}
45b5701710SAlex Langford 
IsAllowedRuntimeValue(ConstString name)46efb328f6SEric Christopher bool ObjCLanguageRuntime::IsAllowedRuntimeValue(ConstString name) {
47b5701710SAlex Langford   static ConstString g_self = ConstString("self");
48b5701710SAlex Langford   static ConstString g_cmd = ConstString("_cmd");
49b5701710SAlex Langford   return name == g_self || name == g_cmd;
50b5701710SAlex Langford }
51b5701710SAlex Langford 
AddClass(ObjCISA isa,const ClassDescriptorSP & descriptor_sp,const char * class_name)52b5701710SAlex Langford bool ObjCLanguageRuntime::AddClass(ObjCISA isa,
53b5701710SAlex Langford                                    const ClassDescriptorSP &descriptor_sp,
54b5701710SAlex Langford                                    const char *class_name) {
55b5701710SAlex Langford   if (isa != 0) {
56b5701710SAlex Langford     m_isa_to_descriptor[isa] = descriptor_sp;
57b5701710SAlex Langford     // class_name is assumed to be valid
58b5701710SAlex Langford     m_hash_to_isa_map.insert(std::make_pair(llvm::djbHash(class_name), isa));
59b5701710SAlex Langford     return true;
60b5701710SAlex Langford   }
61b5701710SAlex Langford   return false;
62b5701710SAlex Langford }
63b5701710SAlex Langford 
AddToMethodCache(lldb::addr_t class_addr,lldb::addr_t selector,lldb::addr_t impl_addr)64b5701710SAlex Langford void ObjCLanguageRuntime::AddToMethodCache(lldb::addr_t class_addr,
65b5701710SAlex Langford                                            lldb::addr_t selector,
66b5701710SAlex Langford                                            lldb::addr_t impl_addr) {
67a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::Step);
68b5701710SAlex Langford   if (log) {
6963e5fb76SJonas Devlieghere     LLDB_LOGF(log,
7063e5fb76SJonas Devlieghere               "Caching: class 0x%" PRIx64 " selector 0x%" PRIx64
71b5701710SAlex Langford               " implementation 0x%" PRIx64 ".",
72b5701710SAlex Langford               class_addr, selector, impl_addr);
73b5701710SAlex Langford   }
74b5701710SAlex Langford   m_impl_cache.insert(std::pair<ClassAndSel, lldb::addr_t>(
75b5701710SAlex Langford       ClassAndSel(class_addr, selector), impl_addr));
76b5701710SAlex Langford }
77b5701710SAlex Langford 
AddToMethodCache(lldb::addr_t class_addr,llvm::StringRef sel_str,lldb::addr_t impl_addr)78*833882b3SJim Ingham void ObjCLanguageRuntime::AddToMethodCache(lldb::addr_t class_addr,
79*833882b3SJim Ingham                                            llvm::StringRef sel_str,
80*833882b3SJim Ingham                                            lldb::addr_t impl_addr) {
81*833882b3SJim Ingham   Log *log = GetLog(LLDBLog::Step);
82*833882b3SJim Ingham 
83*833882b3SJim Ingham   LLDB_LOG(log, "Caching: class {0} selector {1} implementation {2}.",
84*833882b3SJim Ingham            class_addr, sel_str, impl_addr);
85*833882b3SJim Ingham 
86*833882b3SJim Ingham   m_impl_str_cache.insert(std::pair<ClassAndSelStr, lldb::addr_t>(
87*833882b3SJim Ingham       ClassAndSelStr(class_addr, sel_str), impl_addr));
88*833882b3SJim Ingham }
89*833882b3SJim Ingham 
LookupInMethodCache(lldb::addr_t class_addr,lldb::addr_t selector)90b5701710SAlex Langford lldb::addr_t ObjCLanguageRuntime::LookupInMethodCache(lldb::addr_t class_addr,
91b5701710SAlex Langford                                                       lldb::addr_t selector) {
92b5701710SAlex Langford   MsgImplMap::iterator pos, end = m_impl_cache.end();
93b5701710SAlex Langford   pos = m_impl_cache.find(ClassAndSel(class_addr, selector));
94b5701710SAlex Langford   if (pos != end)
95b5701710SAlex Langford     return (*pos).second;
96b5701710SAlex Langford   return LLDB_INVALID_ADDRESS;
97b5701710SAlex Langford }
98b5701710SAlex Langford 
LookupInMethodCache(lldb::addr_t class_addr,llvm::StringRef sel_str)99*833882b3SJim Ingham lldb::addr_t ObjCLanguageRuntime::LookupInMethodCache(lldb::addr_t class_addr,
100*833882b3SJim Ingham                                                       llvm::StringRef sel_str) {
101*833882b3SJim Ingham   MsgImplStrMap::iterator pos, end = m_impl_str_cache.end();
102*833882b3SJim Ingham   pos = m_impl_str_cache.find(ClassAndSelStr(class_addr, sel_str));
103*833882b3SJim Ingham   if (pos != end)
104*833882b3SJim Ingham     return (*pos).second;
105*833882b3SJim Ingham   return LLDB_INVALID_ADDRESS;
106*833882b3SJim Ingham }
107*833882b3SJim Ingham 
108b5701710SAlex Langford lldb::TypeSP
LookupInCompleteClassCache(ConstString & name)109b5701710SAlex Langford ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) {
110b5701710SAlex Langford   CompleteClassMap::iterator complete_class_iter =
111b5701710SAlex Langford       m_complete_class_cache.find(name);
112b5701710SAlex Langford 
113b5701710SAlex Langford   if (complete_class_iter != m_complete_class_cache.end()) {
114b5701710SAlex Langford     // Check the weak pointer to make sure the type hasn't been unloaded
115b5701710SAlex Langford     TypeSP complete_type_sp(complete_class_iter->second.lock());
116b5701710SAlex Langford 
117b5701710SAlex Langford     if (complete_type_sp)
118b5701710SAlex Langford       return complete_type_sp;
119b5701710SAlex Langford     else
120b5701710SAlex Langford       m_complete_class_cache.erase(name);
121b5701710SAlex Langford   }
122b5701710SAlex Langford 
123b5701710SAlex Langford   if (m_negative_complete_class_cache.count(name) > 0)
124b5701710SAlex Langford     return TypeSP();
125b5701710SAlex Langford 
126b5701710SAlex Langford   const ModuleList &modules = m_process->GetTarget().GetImages();
127b5701710SAlex Langford 
128b5701710SAlex Langford   SymbolContextList sc_list;
129b5701710SAlex Langford   modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list);
1301ad655e2SAdrian Prantl   const size_t matching_symbols = sc_list.GetSize();
131b5701710SAlex Langford 
132b5701710SAlex Langford   if (matching_symbols) {
133b5701710SAlex Langford     SymbolContext sc;
134b5701710SAlex Langford 
135b5701710SAlex Langford     sc_list.GetContextAtIndex(0, sc);
136b5701710SAlex Langford 
137b5701710SAlex Langford     ModuleSP module_sp(sc.module_sp);
138b5701710SAlex Langford 
139b5701710SAlex Langford     if (!module_sp)
140b5701710SAlex Langford       return TypeSP();
141b5701710SAlex Langford 
142b5701710SAlex Langford     const bool exact_match = true;
143b5701710SAlex Langford     const uint32_t max_matches = UINT32_MAX;
144b5701710SAlex Langford     TypeList types;
145b5701710SAlex Langford 
146b5701710SAlex Langford     llvm::DenseSet<SymbolFile *> searched_symbol_files;
147bf9d84c0SAdrian Prantl     module_sp->FindTypes(name, exact_match, max_matches, searched_symbol_files,
148bf9d84c0SAdrian Prantl                          types);
149b5701710SAlex Langford 
150bf9d84c0SAdrian Prantl     for (uint32_t i = 0; i < types.GetSize(); ++i) {
151b5701710SAlex Langford       TypeSP type_sp(types.GetTypeAtIndex(i));
152b5701710SAlex Langford 
1536e3b0cc2SRaphael Isemann       if (TypeSystemClang::IsObjCObjectOrInterfaceType(
154b5701710SAlex Langford               type_sp->GetForwardCompilerType())) {
1557b06cb45SAdrian Prantl         if (TypePayloadClang(type_sp->GetPayload()).IsCompleteObjCClass()) {
156b5701710SAlex Langford           m_complete_class_cache[name] = type_sp;
157b5701710SAlex Langford           return type_sp;
158b5701710SAlex Langford         }
159b5701710SAlex Langford       }
160b5701710SAlex Langford     }
161b5701710SAlex Langford   }
162b5701710SAlex Langford   m_negative_complete_class_cache.insert(name);
163b5701710SAlex Langford   return TypeSP();
164b5701710SAlex Langford }
165b5701710SAlex Langford 
GetByteOffsetForIvar(CompilerType & parent_qual_type,const char * ivar_name)166b5701710SAlex Langford size_t ObjCLanguageRuntime::GetByteOffsetForIvar(CompilerType &parent_qual_type,
167b5701710SAlex Langford                                                  const char *ivar_name) {
168b5701710SAlex Langford   return LLDB_INVALID_IVAR_OFFSET;
169b5701710SAlex Langford }
170b5701710SAlex Langford 
IsPointerValid(lldb::addr_t value,uint32_t ptr_size,bool allow_NULLs,bool allow_tagged,bool check_version_specific) const171b5701710SAlex Langford bool ObjCLanguageRuntime::ClassDescriptor::IsPointerValid(
172b5701710SAlex Langford     lldb::addr_t value, uint32_t ptr_size, bool allow_NULLs, bool allow_tagged,
173b5701710SAlex Langford     bool check_version_specific) const {
174b5701710SAlex Langford   if (!value)
175b5701710SAlex Langford     return allow_NULLs;
176b5701710SAlex Langford   if ((value % 2) == 1 && allow_tagged)
177b5701710SAlex Langford     return true;
178b5701710SAlex Langford   if ((value % ptr_size) == 0)
179b5701710SAlex Langford     return (check_version_specific ? CheckPointer(value, ptr_size) : true);
180b5701710SAlex Langford   else
181b5701710SAlex Langford     return false;
182b5701710SAlex Langford }
183b5701710SAlex Langford 
184b5701710SAlex Langford ObjCLanguageRuntime::ObjCISA
GetISA(ConstString name)185b5701710SAlex Langford ObjCLanguageRuntime::GetISA(ConstString name) {
186b5701710SAlex Langford   ISAToDescriptorIterator pos = GetDescriptorIterator(name);
187b5701710SAlex Langford   if (pos != m_isa_to_descriptor.end())
188b5701710SAlex Langford     return pos->first;
189b5701710SAlex Langford   return 0;
190b5701710SAlex Langford }
191b5701710SAlex Langford 
192b5701710SAlex Langford ObjCLanguageRuntime::ISAToDescriptorIterator
GetDescriptorIterator(ConstString name)193b5701710SAlex Langford ObjCLanguageRuntime::GetDescriptorIterator(ConstString name) {
194b5701710SAlex Langford   ISAToDescriptorIterator end = m_isa_to_descriptor.end();
195b5701710SAlex Langford 
196b5701710SAlex Langford   if (name) {
197b5701710SAlex Langford     UpdateISAToDescriptorMap();
198b5701710SAlex Langford     if (m_hash_to_isa_map.empty()) {
199b5701710SAlex Langford       // No name hashes were provided, we need to just linearly power through
200b5701710SAlex Langford       // the names and find a match
201b5701710SAlex Langford       for (ISAToDescriptorIterator pos = m_isa_to_descriptor.begin();
202b5701710SAlex Langford            pos != end; ++pos) {
203b5701710SAlex Langford         if (pos->second->GetClassName() == name)
204b5701710SAlex Langford           return pos;
205b5701710SAlex Langford       }
206b5701710SAlex Langford     } else {
207b5701710SAlex Langford       // Name hashes were provided, so use them to efficiently lookup name to
208b5701710SAlex Langford       // isa/descriptor
209b5701710SAlex Langford       const uint32_t name_hash = llvm::djbHash(name.GetStringRef());
210b5701710SAlex Langford       std::pair<HashToISAIterator, HashToISAIterator> range =
211b5701710SAlex Langford           m_hash_to_isa_map.equal_range(name_hash);
212b5701710SAlex Langford       for (HashToISAIterator range_pos = range.first; range_pos != range.second;
213b5701710SAlex Langford            ++range_pos) {
214b5701710SAlex Langford         ISAToDescriptorIterator pos =
215b5701710SAlex Langford             m_isa_to_descriptor.find(range_pos->second);
216b5701710SAlex Langford         if (pos != m_isa_to_descriptor.end()) {
217b5701710SAlex Langford           if (pos->second->GetClassName() == name)
218b5701710SAlex Langford             return pos;
219b5701710SAlex Langford         }
220b5701710SAlex Langford       }
221b5701710SAlex Langford     }
222b5701710SAlex Langford   }
223b5701710SAlex Langford   return end;
224b5701710SAlex Langford }
225b5701710SAlex Langford 
226b5701710SAlex Langford std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
227b5701710SAlex Langford           ObjCLanguageRuntime::ISAToDescriptorIterator>
GetDescriptorIteratorPair(bool update_if_needed)228b5701710SAlex Langford ObjCLanguageRuntime::GetDescriptorIteratorPair(bool update_if_needed) {
229b5701710SAlex Langford   if (update_if_needed)
230b5701710SAlex Langford     UpdateISAToDescriptorMapIfNeeded();
231b5701710SAlex Langford 
232b5701710SAlex Langford   return std::pair<ObjCLanguageRuntime::ISAToDescriptorIterator,
233b5701710SAlex Langford                    ObjCLanguageRuntime::ISAToDescriptorIterator>(
234b5701710SAlex Langford       m_isa_to_descriptor.begin(), m_isa_to_descriptor.end());
235b5701710SAlex Langford }
236b5701710SAlex Langford 
237b5701710SAlex Langford ObjCLanguageRuntime::ObjCISA
GetParentClass(ObjCLanguageRuntime::ObjCISA isa)238b5701710SAlex Langford ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) {
239b5701710SAlex Langford   ClassDescriptorSP objc_class_sp(GetClassDescriptorFromISA(isa));
240b5701710SAlex Langford   if (objc_class_sp) {
241b5701710SAlex Langford     ClassDescriptorSP objc_super_class_sp(objc_class_sp->GetSuperclass());
242b5701710SAlex Langford     if (objc_super_class_sp)
243b5701710SAlex Langford       return objc_super_class_sp->GetISA();
244b5701710SAlex Langford   }
245b5701710SAlex Langford   return 0;
246b5701710SAlex Langford }
247b5701710SAlex Langford 
248b5701710SAlex Langford ObjCLanguageRuntime::ClassDescriptorSP
GetClassDescriptorFromClassName(ConstString class_name)249b5701710SAlex Langford ObjCLanguageRuntime::GetClassDescriptorFromClassName(
250b5701710SAlex Langford     ConstString class_name) {
251b5701710SAlex Langford   ISAToDescriptorIterator pos = GetDescriptorIterator(class_name);
252b5701710SAlex Langford   if (pos != m_isa_to_descriptor.end())
253b5701710SAlex Langford     return pos->second;
254b5701710SAlex Langford   return ClassDescriptorSP();
255b5701710SAlex Langford }
256b5701710SAlex Langford 
257b5701710SAlex Langford ObjCLanguageRuntime::ClassDescriptorSP
GetClassDescriptor(ValueObject & valobj)258b5701710SAlex Langford ObjCLanguageRuntime::GetClassDescriptor(ValueObject &valobj) {
259b5701710SAlex Langford   ClassDescriptorSP objc_class_sp;
260b5701710SAlex Langford   // if we get an invalid VO (which might still happen when playing around with
261b5701710SAlex Langford   // pointers returned by the expression parser, don't consider this a valid
262b5701710SAlex Langford   // ObjC object)
263b5701710SAlex Langford   if (valobj.GetCompilerType().IsValid()) {
264b5701710SAlex Langford     addr_t isa_pointer = valobj.GetPointerValue();
265b5701710SAlex Langford     if (isa_pointer != LLDB_INVALID_ADDRESS) {
266b5701710SAlex Langford       ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
267b5701710SAlex Langford 
268b5701710SAlex Langford       Process *process = exe_ctx.GetProcessPtr();
269b5701710SAlex Langford       if (process) {
270b5701710SAlex Langford         Status error;
271b5701710SAlex Langford         ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
272b5701710SAlex Langford         if (isa != LLDB_INVALID_ADDRESS)
273b5701710SAlex Langford           objc_class_sp = GetClassDescriptorFromISA(isa);
274b5701710SAlex Langford       }
275b5701710SAlex Langford     }
276b5701710SAlex Langford   }
277b5701710SAlex Langford   return objc_class_sp;
278b5701710SAlex Langford }
279b5701710SAlex Langford 
280b5701710SAlex Langford ObjCLanguageRuntime::ClassDescriptorSP
GetNonKVOClassDescriptor(ValueObject & valobj)281b5701710SAlex Langford ObjCLanguageRuntime::GetNonKVOClassDescriptor(ValueObject &valobj) {
282b5701710SAlex Langford   ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp(
283b5701710SAlex Langford       GetClassDescriptor(valobj));
284b5701710SAlex Langford   if (objc_class_sp) {
285b5701710SAlex Langford     if (!objc_class_sp->IsKVO())
286b5701710SAlex Langford       return objc_class_sp;
287b5701710SAlex Langford 
288b5701710SAlex Langford     ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
289b5701710SAlex Langford     if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
290b5701710SAlex Langford       return non_kvo_objc_class_sp;
291b5701710SAlex Langford   }
292b5701710SAlex Langford   return ClassDescriptorSP();
293b5701710SAlex Langford }
294b5701710SAlex Langford 
295b5701710SAlex Langford ObjCLanguageRuntime::ClassDescriptorSP
GetClassDescriptorFromISA(ObjCISA isa)296b5701710SAlex Langford ObjCLanguageRuntime::GetClassDescriptorFromISA(ObjCISA isa) {
297b5701710SAlex Langford   if (isa) {
298b5701710SAlex Langford     UpdateISAToDescriptorMap();
2998bac9e36SJonas Devlieghere 
300b5701710SAlex Langford     ObjCLanguageRuntime::ISAToDescriptorIterator pos =
301b5701710SAlex Langford         m_isa_to_descriptor.find(isa);
302b5701710SAlex Langford     if (pos != m_isa_to_descriptor.end())
303b5701710SAlex Langford       return pos->second;
3048bac9e36SJonas Devlieghere 
3058bac9e36SJonas Devlieghere     if (ABISP abi_sp = m_process->GetABI()) {
3068bac9e36SJonas Devlieghere       pos = m_isa_to_descriptor.find(abi_sp->FixCodeAddress(isa));
3078bac9e36SJonas Devlieghere       if (pos != m_isa_to_descriptor.end())
3088bac9e36SJonas Devlieghere         return pos->second;
3098bac9e36SJonas Devlieghere     }
310b5701710SAlex Langford   }
311b5701710SAlex Langford   return ClassDescriptorSP();
312b5701710SAlex Langford }
313b5701710SAlex Langford 
314b5701710SAlex Langford ObjCLanguageRuntime::ClassDescriptorSP
GetNonKVOClassDescriptor(ObjCISA isa)315b5701710SAlex Langford ObjCLanguageRuntime::GetNonKVOClassDescriptor(ObjCISA isa) {
316b5701710SAlex Langford   if (isa) {
317b5701710SAlex Langford     ClassDescriptorSP objc_class_sp = GetClassDescriptorFromISA(isa);
318b5701710SAlex Langford     if (objc_class_sp && objc_class_sp->IsValid()) {
319b5701710SAlex Langford       if (!objc_class_sp->IsKVO())
320b5701710SAlex Langford         return objc_class_sp;
321b5701710SAlex Langford 
322b5701710SAlex Langford       ClassDescriptorSP non_kvo_objc_class_sp(objc_class_sp->GetSuperclass());
323b5701710SAlex Langford       if (non_kvo_objc_class_sp && non_kvo_objc_class_sp->IsValid())
324b5701710SAlex Langford         return non_kvo_objc_class_sp;
325b5701710SAlex Langford     }
326b5701710SAlex Langford   }
327b5701710SAlex Langford   return ClassDescriptorSP();
328b5701710SAlex Langford }
329b5701710SAlex Langford 
330b5701710SAlex Langford CompilerType
RealizeType(const char * name,bool for_expression)331b5701710SAlex Langford ObjCLanguageRuntime::EncodingToType::RealizeType(const char *name,
332b5701710SAlex Langford                                                  bool for_expression) {
333b5701710SAlex Langford   if (m_scratch_ast_ctx_up)
334b5701710SAlex Langford     return RealizeType(*m_scratch_ast_ctx_up, name, for_expression);
335b5701710SAlex Langford   return CompilerType();
336b5701710SAlex Langford }
337b5701710SAlex Langford 
338fd2433e1SJonas Devlieghere ObjCLanguageRuntime::EncodingToType::~EncodingToType() = default;
339b5701710SAlex Langford 
GetEncodingToType()340b5701710SAlex Langford ObjCLanguageRuntime::EncodingToTypeSP ObjCLanguageRuntime::GetEncodingToType() {
341b5701710SAlex Langford   return nullptr;
342b5701710SAlex Langford }
343b5701710SAlex Langford 
GetTypeBitSize(const CompilerType & compiler_type,uint64_t & size)344b5701710SAlex Langford bool ObjCLanguageRuntime::GetTypeBitSize(const CompilerType &compiler_type,
345b5701710SAlex Langford                                          uint64_t &size) {
346b5701710SAlex Langford   void *opaque_ptr = compiler_type.GetOpaqueQualType();
347b5701710SAlex Langford   size = m_type_size_cache.Lookup(opaque_ptr);
348b5701710SAlex Langford   // an ObjC object will at least have an ISA, so 0 is definitely not OK
349b5701710SAlex Langford   if (size > 0)
350b5701710SAlex Langford     return true;
351b5701710SAlex Langford 
352b5701710SAlex Langford   ClassDescriptorSP class_descriptor_sp =
353b5701710SAlex Langford       GetClassDescriptorFromClassName(compiler_type.GetTypeName());
354b5701710SAlex Langford   if (!class_descriptor_sp)
355b5701710SAlex Langford     return false;
356b5701710SAlex Langford 
357b5701710SAlex Langford   int32_t max_offset = INT32_MIN;
358b5701710SAlex Langford   uint64_t sizeof_max = 0;
359b5701710SAlex Langford   bool found = false;
360b5701710SAlex Langford 
361b5701710SAlex Langford   for (size_t idx = 0; idx < class_descriptor_sp->GetNumIVars(); idx++) {
362b5701710SAlex Langford     const auto &ivar = class_descriptor_sp->GetIVarAtIndex(idx);
363b5701710SAlex Langford     int32_t cur_offset = ivar.m_offset;
364b5701710SAlex Langford     if (cur_offset > max_offset) {
365b5701710SAlex Langford       max_offset = cur_offset;
366b5701710SAlex Langford       sizeof_max = ivar.m_size;
367b5701710SAlex Langford       found = true;
368b5701710SAlex Langford     }
369b5701710SAlex Langford   }
370b5701710SAlex Langford 
371b5701710SAlex Langford   size = 8 * (max_offset + sizeof_max);
372b5701710SAlex Langford   if (found)
373b5701710SAlex Langford     m_type_size_cache.Insert(opaque_ptr, size);
374b5701710SAlex Langford 
375b5701710SAlex Langford   return found;
376b5701710SAlex Langford }
377b5701710SAlex Langford 
378b5701710SAlex Langford lldb::BreakpointPreconditionSP
GetBreakpointExceptionPrecondition(LanguageType language,bool throw_bp)379b5701710SAlex Langford ObjCLanguageRuntime::GetBreakpointExceptionPrecondition(LanguageType language,
380b5701710SAlex Langford                                                         bool throw_bp) {
381b5701710SAlex Langford   if (language != eLanguageTypeObjC)
382b5701710SAlex Langford     return lldb::BreakpointPreconditionSP();
383b5701710SAlex Langford   if (!throw_bp)
384b5701710SAlex Langford     return lldb::BreakpointPreconditionSP();
385b5701710SAlex Langford   BreakpointPreconditionSP precondition_sp(
386b5701710SAlex Langford       new ObjCLanguageRuntime::ObjCExceptionPrecondition());
387b5701710SAlex Langford   return precondition_sp;
388b5701710SAlex Langford }
389b5701710SAlex Langford 
390b5701710SAlex Langford // Exception breakpoint Precondition class for ObjC:
AddClassName(const char * class_name)391b5701710SAlex Langford void ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName(
392b5701710SAlex Langford     const char *class_name) {
393b5701710SAlex Langford   m_class_names.insert(class_name);
394b5701710SAlex Langford }
395b5701710SAlex Langford 
396fd2433e1SJonas Devlieghere ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() =
397fd2433e1SJonas Devlieghere     default;
398b5701710SAlex Langford 
EvaluatePrecondition(StoppointCallbackContext & context)399b5701710SAlex Langford bool ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition(
400b5701710SAlex Langford     StoppointCallbackContext &context) {
401b5701710SAlex Langford   return true;
402b5701710SAlex Langford }
403b5701710SAlex Langford 
GetDescription(Stream & stream,lldb::DescriptionLevel level)404b5701710SAlex Langford void ObjCLanguageRuntime::ObjCExceptionPrecondition::GetDescription(
405b5701710SAlex Langford     Stream &stream, lldb::DescriptionLevel level) {}
406b5701710SAlex Langford 
ConfigurePrecondition(Args & args)407b5701710SAlex Langford Status ObjCLanguageRuntime::ObjCExceptionPrecondition::ConfigurePrecondition(
408b5701710SAlex Langford     Args &args) {
409b5701710SAlex Langford   Status error;
410b5701710SAlex Langford   if (args.GetArgumentCount() > 0)
411b5701710SAlex Langford     error.SetErrorString(
412b5701710SAlex Langford         "The ObjC Exception breakpoint doesn't support extra options.");
413b5701710SAlex Langford   return error;
414b5701710SAlex Langford }
415b5701710SAlex Langford 
416b5701710SAlex Langford llvm::Optional<CompilerType>
GetRuntimeType(CompilerType base_type)417b5701710SAlex Langford ObjCLanguageRuntime::GetRuntimeType(CompilerType base_type) {
418b5701710SAlex Langford   CompilerType class_type;
419b5701710SAlex Langford   bool is_pointer_type = false;
420b5701710SAlex Langford 
4216e3b0cc2SRaphael Isemann   if (TypeSystemClang::IsObjCObjectPointerType(base_type, &class_type))
422b5701710SAlex Langford     is_pointer_type = true;
4236e3b0cc2SRaphael Isemann   else if (TypeSystemClang::IsObjCObjectOrInterfaceType(base_type))
424b5701710SAlex Langford     class_type = base_type;
425b5701710SAlex Langford   else
426b5701710SAlex Langford     return llvm::None;
427b5701710SAlex Langford 
428b5701710SAlex Langford   if (!class_type)
429b5701710SAlex Langford     return llvm::None;
430b5701710SAlex Langford 
43130ce956aSRaphael Isemann   ConstString class_name(class_type.GetTypeName());
432b5701710SAlex Langford   if (!class_name)
433b5701710SAlex Langford     return llvm::None;
434b5701710SAlex Langford 
435b5701710SAlex Langford   TypeSP complete_objc_class_type_sp = LookupInCompleteClassCache(class_name);
436b5701710SAlex Langford   if (!complete_objc_class_type_sp)
437b5701710SAlex Langford     return llvm::None;
438b5701710SAlex Langford 
439b5701710SAlex Langford   CompilerType complete_class(
440b5701710SAlex Langford       complete_objc_class_type_sp->GetFullCompilerType());
441b5701710SAlex Langford   if (complete_class.GetCompleteType()) {
442b5701710SAlex Langford     if (is_pointer_type)
443b5701710SAlex Langford       return complete_class.GetPointerType();
444b5701710SAlex Langford     else
445b5701710SAlex Langford       return complete_class;
446b5701710SAlex Langford   }
447b5701710SAlex Langford 
448b5701710SAlex Langford   return llvm::None;
449b5701710SAlex Langford }
450