1254721Semaste//===-- ObjCLanguageRuntime.h ---------------------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#ifndef liblldb_ObjCLanguageRuntime_h_
11254721Semaste#define liblldb_ObjCLanguageRuntime_h_
12254721Semaste
13254721Semaste// C Includes
14254721Semaste// C++ Includes
15254721Semaste#include <functional>
16254721Semaste#include <map>
17254721Semaste#include <unordered_set>
18254721Semaste
19254721Semaste// Other libraries and framework includes
20254721Semaste// Project includes
21254721Semaste#include "lldb/lldb-private.h"
22254721Semaste#include "lldb/Core/PluginInterface.h"
23254721Semaste#include "lldb/Symbol/Type.h"
24254721Semaste#include "lldb/Symbol/TypeVendor.h"
25254721Semaste#include "lldb/Target/LanguageRuntime.h"
26254721Semaste
27254721Semastenamespace lldb_private {
28254721Semaste
29254721Semasteclass ClangUtilityFunction;
30254721Semaste
31254721Semasteclass ObjCLanguageRuntime :
32254721Semaste    public LanguageRuntime
33254721Semaste{
34254721Semastepublic:
35254721Semaste    class MethodName
36254721Semaste    {
37254721Semaste    public:
38254721Semaste        enum Type
39254721Semaste        {
40254721Semaste            eTypeUnspecified,
41254721Semaste            eTypeClassMethod,
42254721Semaste            eTypeInstanceMethod
43254721Semaste        };
44254721Semaste
45254721Semaste        MethodName () :
46254721Semaste            m_full(),
47254721Semaste            m_class(),
48254721Semaste            m_category(),
49254721Semaste            m_selector(),
50254721Semaste            m_type (eTypeUnspecified),
51254721Semaste            m_category_is_valid (false)
52254721Semaste        {
53254721Semaste        }
54254721Semaste
55254721Semaste        MethodName (const char *name, bool strict) :
56254721Semaste            m_full(),
57254721Semaste            m_class(),
58254721Semaste            m_category(),
59254721Semaste            m_selector(),
60254721Semaste            m_type (eTypeUnspecified),
61254721Semaste            m_category_is_valid (false)
62254721Semaste        {
63254721Semaste            SetName (name, strict);
64254721Semaste        }
65254721Semaste
66254721Semaste        void
67254721Semaste        Clear();
68254721Semaste
69254721Semaste        bool
70254721Semaste        IsValid (bool strict) const
71254721Semaste        {
72254721Semaste            // If "strict" is true, the name must have everything specified including
73254721Semaste            // the leading "+" or "-" on the method name
74254721Semaste            if (strict && m_type == eTypeUnspecified)
75254721Semaste                return false;
76254721Semaste            // Other than that, m_full will only be filled in if the objective C
77254721Semaste            // name is valid.
78254721Semaste            return (bool)m_full;
79254721Semaste        }
80254721Semaste
81254721Semaste        bool
82254721Semaste        HasCategory()
83254721Semaste        {
84254721Semaste            return (bool)GetCategory();
85254721Semaste        }
86254721Semaste
87254721Semaste        Type
88254721Semaste        GetType () const
89254721Semaste        {
90254721Semaste            return m_type;
91254721Semaste        }
92254721Semaste
93254721Semaste        const ConstString &
94254721Semaste        GetFullName () const
95254721Semaste        {
96254721Semaste            return m_full;
97254721Semaste        }
98254721Semaste
99254721Semaste        ConstString
100254721Semaste        GetFullNameWithoutCategory (bool empty_if_no_category);
101254721Semaste
102254721Semaste        bool
103254721Semaste        SetName (const char *name, bool strict);
104254721Semaste
105254721Semaste        const ConstString &
106254721Semaste        GetClassName ();
107254721Semaste
108254721Semaste        const ConstString &
109254721Semaste        GetClassNameWithCategory ();
110254721Semaste
111254721Semaste        const ConstString &
112254721Semaste        GetCategory ();
113254721Semaste
114254721Semaste        const ConstString &
115254721Semaste        GetSelector ();
116254721Semaste
117254721Semaste        // Get all possible names for a method. Examples:
118254721Semaste        // If name is "+[NSString(my_additions) myStringWithCString:]"
119254721Semaste        //  names[0] => "+[NSString(my_additions) myStringWithCString:]"
120254721Semaste        //  names[1] => "+[NSString myStringWithCString:]"
121254721Semaste        // If name is specified without the leading '+' or '-' like "[NSString(my_additions) myStringWithCString:]"
122254721Semaste        //  names[0] => "+[NSString(my_additions) myStringWithCString:]"
123254721Semaste        //  names[1] => "-[NSString(my_additions) myStringWithCString:]"
124254721Semaste        //  names[2] => "+[NSString myStringWithCString:]"
125254721Semaste        //  names[3] => "-[NSString myStringWithCString:]"
126254721Semaste        size_t
127254721Semaste        GetFullNames (std::vector<ConstString> &names, bool append);
128254721Semaste    protected:
129254721Semaste        ConstString m_full;     // Full name:   "+[NSString(my_additions) myStringWithCString:]"
130254721Semaste        ConstString m_class;    // Class name:  "NSString"
131254721Semaste        ConstString m_class_category; // Class with category: "NSString(my_additions)"
132254721Semaste        ConstString m_category; // Category:    "my_additions"
133254721Semaste        ConstString m_selector; // Selector:    "myStringWithCString:"
134254721Semaste        Type m_type;
135254721Semaste        bool m_category_is_valid;
136254721Semaste
137254721Semaste    };
138254721Semaste    typedef lldb::addr_t ObjCISA;
139254721Semaste
140254721Semaste    class ClassDescriptor;
141254721Semaste    typedef std::shared_ptr<ClassDescriptor> ClassDescriptorSP;
142254721Semaste
143254721Semaste    // the information that we want to support retrieving from an ObjC class
144254721Semaste    // this needs to be pure virtual since there are at least 2 different implementations
145254721Semaste    // of the runtime, and more might come
146254721Semaste    class ClassDescriptor
147254721Semaste    {
148254721Semaste    public:
149254721Semaste
150254721Semaste        ClassDescriptor() :
151254721Semaste            m_is_kvo (eLazyBoolCalculate),
152254721Semaste            m_is_cf (eLazyBoolCalculate),
153254721Semaste            m_type_wp ()
154254721Semaste        {
155254721Semaste        }
156254721Semaste
157254721Semaste        virtual
158254721Semaste        ~ClassDescriptor ()
159254721Semaste        {
160254721Semaste        }
161254721Semaste
162254721Semaste        virtual ConstString
163254721Semaste        GetClassName () = 0;
164254721Semaste
165254721Semaste        virtual ClassDescriptorSP
166254721Semaste        GetSuperclass () = 0;
167254721Semaste
168254721Semaste        // virtual if any implementation has some other version-specific rules
169254721Semaste        // but for the known v1/v2 this is all that needs to be done
170254721Semaste        virtual bool
171254721Semaste        IsKVO ()
172254721Semaste        {
173254721Semaste            if (m_is_kvo == eLazyBoolCalculate)
174254721Semaste            {
175254721Semaste                const char* class_name = GetClassName().AsCString();
176254721Semaste                if (class_name && *class_name)
177254721Semaste                    m_is_kvo = (LazyBool)(strstr(class_name,"NSKVONotifying_") == class_name);
178254721Semaste            }
179254721Semaste            return (m_is_kvo == eLazyBoolYes);
180254721Semaste        }
181254721Semaste
182254721Semaste        // virtual if any implementation has some other version-specific rules
183254721Semaste        // but for the known v1/v2 this is all that needs to be done
184254721Semaste        virtual bool
185254721Semaste        IsCFType ()
186254721Semaste        {
187254721Semaste            if (m_is_cf == eLazyBoolCalculate)
188254721Semaste            {
189254721Semaste                const char* class_name = GetClassName().AsCString();
190254721Semaste                if (class_name && *class_name)
191254721Semaste                    m_is_cf = (LazyBool)(strcmp(class_name,"__NSCFType") == 0 ||
192254721Semaste                                         strcmp(class_name,"NSCFType") == 0);
193254721Semaste            }
194254721Semaste            return (m_is_cf == eLazyBoolYes);
195254721Semaste        }
196254721Semaste
197254721Semaste        virtual bool
198254721Semaste        IsValid () = 0;
199254721Semaste
200254721Semaste        virtual bool
201254721Semaste        GetTaggedPointerInfo (uint64_t* info_bits = NULL,
202254721Semaste                              uint64_t* value_bits = NULL,
203254721Semaste                              uint64_t* payload = NULL) = 0;
204254721Semaste
205254721Semaste        virtual uint64_t
206254721Semaste        GetInstanceSize () = 0;
207254721Semaste
208254721Semaste        // use to implement version-specific additional constraints on pointers
209254721Semaste        virtual bool
210254721Semaste        CheckPointer (lldb::addr_t value,
211254721Semaste                      uint32_t ptr_size) const
212254721Semaste        {
213254721Semaste            return true;
214254721Semaste        }
215254721Semaste
216254721Semaste        virtual ObjCISA
217254721Semaste        GetISA () = 0;
218254721Semaste
219254721Semaste        // This should return true iff the interface could be completed
220254721Semaste        virtual bool
221254721Semaste        Describe (std::function <void (ObjCISA)> const &superclass_func,
222254721Semaste                  std::function <bool (const char*, const char*)> const &instance_method_func,
223254721Semaste                  std::function <bool (const char*, const char*)> const &class_method_func,
224254721Semaste                  std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func)
225254721Semaste        {
226254721Semaste            return false;
227254721Semaste        }
228254721Semaste
229254721Semaste        lldb::TypeSP
230254721Semaste        GetType ()
231254721Semaste        {
232254721Semaste            return m_type_wp.lock();
233254721Semaste        }
234254721Semaste
235254721Semaste        void
236254721Semaste        SetType (const lldb::TypeSP &type_sp)
237254721Semaste        {
238254721Semaste            m_type_wp = type_sp;
239254721Semaste        }
240254721Semaste
241254721Semaste    protected:
242254721Semaste        bool
243254721Semaste        IsPointerValid (lldb::addr_t value,
244254721Semaste                        uint32_t ptr_size,
245254721Semaste                        bool allow_NULLs = false,
246254721Semaste                        bool allow_tagged = false,
247254721Semaste                        bool check_version_specific = false) const;
248254721Semaste
249254721Semaste    private:
250254721Semaste        LazyBool m_is_kvo;
251254721Semaste        LazyBool m_is_cf;
252254721Semaste        lldb::TypeWP m_type_wp;
253254721Semaste    };
254254721Semaste
255254721Semaste    virtual ClassDescriptorSP
256254721Semaste    GetClassDescriptor (ValueObject& in_value);
257254721Semaste
258254721Semaste    ClassDescriptorSP
259254721Semaste    GetNonKVOClassDescriptor (ValueObject& in_value);
260254721Semaste
261254721Semaste    virtual ClassDescriptorSP
262254721Semaste    GetClassDescriptorFromClassName (const ConstString &class_name);
263254721Semaste
264254721Semaste    virtual ClassDescriptorSP
265254721Semaste    GetClassDescriptorFromISA (ObjCISA isa);
266254721Semaste
267254721Semaste    ClassDescriptorSP
268254721Semaste    GetNonKVOClassDescriptor (ObjCISA isa);
269254721Semaste
270254721Semaste    virtual
271254721Semaste    ~ObjCLanguageRuntime();
272254721Semaste
273254721Semaste    virtual lldb::LanguageType
274254721Semaste    GetLanguageType () const
275254721Semaste    {
276254721Semaste        return lldb::eLanguageTypeObjC;
277254721Semaste    }
278254721Semaste
279254721Semaste    virtual bool
280254721Semaste    IsModuleObjCLibrary (const lldb::ModuleSP &module_sp) = 0;
281254721Semaste
282254721Semaste    virtual bool
283254721Semaste    ReadObjCLibrary (const lldb::ModuleSP &module_sp) = 0;
284254721Semaste
285254721Semaste    virtual bool
286254721Semaste    HasReadObjCLibrary () = 0;
287254721Semaste
288254721Semaste    virtual lldb::ThreadPlanSP
289254721Semaste    GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0;
290254721Semaste
291254721Semaste    lldb::addr_t
292254721Semaste    LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t sel);
293254721Semaste
294254721Semaste    void
295254721Semaste    AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t sel, lldb::addr_t impl_addr);
296254721Semaste
297254721Semaste    TypeAndOrName
298254721Semaste    LookupInClassNameCache (lldb::addr_t class_addr);
299254721Semaste
300254721Semaste    void
301254721Semaste    AddToClassNameCache (lldb::addr_t class_addr, const char *name, lldb::TypeSP type_sp);
302254721Semaste
303254721Semaste    void
304254721Semaste    AddToClassNameCache (lldb::addr_t class_addr, const TypeAndOrName &class_or_type_name);
305254721Semaste
306254721Semaste    lldb::TypeSP
307254721Semaste    LookupInCompleteClassCache (ConstString &name);
308254721Semaste
309254721Semaste    virtual ClangUtilityFunction *
310254721Semaste    CreateObjectChecker (const char *) = 0;
311254721Semaste
312254721Semaste    virtual ObjCRuntimeVersions
313254721Semaste    GetRuntimeVersion ()
314254721Semaste    {
315254721Semaste        return eObjC_VersionUnknown;
316254721Semaste    }
317254721Semaste
318254721Semaste    bool
319254721Semaste    IsValidISA(ObjCISA isa)
320254721Semaste    {
321254721Semaste        UpdateISAToDescriptorMap();
322254721Semaste        return m_isa_to_descriptor.count(isa) > 0;
323254721Semaste    }
324254721Semaste
325254721Semaste    virtual void
326254721Semaste    UpdateISAToDescriptorMapIfNeeded() = 0;
327254721Semaste
328254721Semaste    void
329254721Semaste    UpdateISAToDescriptorMap()
330254721Semaste    {
331254721Semaste        if (m_process && m_process->GetStopID() != m_isa_to_descriptor_stop_id)
332254721Semaste        {
333254721Semaste            UpdateISAToDescriptorMapIfNeeded ();
334254721Semaste        }
335254721Semaste    }
336254721Semaste
337254721Semaste    virtual ObjCISA
338254721Semaste    GetISA(const ConstString &name);
339254721Semaste
340254721Semaste    virtual ConstString
341254721Semaste    GetActualTypeName(ObjCISA isa);
342254721Semaste
343254721Semaste    virtual ObjCISA
344254721Semaste    GetParentClass(ObjCISA isa);
345254721Semaste
346254721Semaste    virtual TypeVendor *
347254721Semaste    GetTypeVendor()
348254721Semaste    {
349254721Semaste        return NULL;
350254721Semaste    }
351254721Semaste
352254721Semaste    // Finds the byte offset of the child_type ivar in parent_type.  If it can't find the
353254721Semaste    // offset, returns LLDB_INVALID_IVAR_OFFSET.
354254721Semaste
355254721Semaste    virtual size_t
356254721Semaste    GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name);
357254721Semaste
358254721Semaste    // Given the name of an Objective-C runtime symbol (e.g., ivar offset symbol),
359254721Semaste    // try to determine from the runtime what the value of that symbol would be.
360254721Semaste    // Useful when the underlying binary is stripped.
361254721Semaste    virtual lldb::addr_t
362254721Semaste    LookupRuntimeSymbol (const ConstString &name)
363254721Semaste    {
364254721Semaste        return LLDB_INVALID_ADDRESS;
365254721Semaste    }
366254721Semaste
367254721Semaste    //------------------------------------------------------------------
368254721Semaste    /// Chop up an objective C function prototype.
369254721Semaste    ///
370254721Semaste    /// Chop up an objective C function fullname and optionally fill in
371254721Semaste    /// any non-NULL ConstString objects. If a ConstString * is NULL,
372254721Semaste    /// then this name doesn't get filled in
373254721Semaste    ///
374254721Semaste    /// @param[in] name
375254721Semaste    ///     A fully specified objective C function name. The string might
376254721Semaste    ///     contain a category and it includes the leading "+" or "-" and
377254721Semaste    ///     the square brackets, no types for the arguments, just the plain
378254721Semaste    ///     selector. A few examples:
379254721Semaste    ///         "-[NSStringDrawingContext init]"
380254721Semaste    ///         "-[NSStringDrawingContext addString:inRect:]"
381254721Semaste    ///         "-[NSString(NSStringDrawing) sizeWithAttributes:]"
382254721Semaste    ///         "+[NSString(NSStringDrawing) usesFontLeading]"
383254721Semaste    ///
384254721Semaste    /// @param[out] class_name
385254721Semaste    ///     If non-NULL, this string will be filled in with the class
386254721Semaste    ///     name including the category. The examples above would return:
387254721Semaste    ///         "NSStringDrawingContext"
388254721Semaste    ///         "NSStringDrawingContext"
389254721Semaste    ///         "NSString(NSStringDrawing)"
390254721Semaste    ///         "NSString(NSStringDrawing)"
391254721Semaste    ///
392254721Semaste    /// @param[out] selector_name
393254721Semaste    ///     If non-NULL, this string will be filled in with the selector
394254721Semaste    ///     name. The examples above would return:
395254721Semaste    ///         "init"
396254721Semaste    ///         "addString:inRect:"
397254721Semaste    ///         "sizeWithAttributes:"
398254721Semaste    ///         "usesFontLeading"
399254721Semaste    ///
400254721Semaste    /// @param[out] name_sans_category
401254721Semaste    ///     If non-NULL, this string will be filled in with the class
402254721Semaste    ///     name _without_ the category. If there is no category, and empty
403254721Semaste    ///     string will be returned (as the result would be normally returned
404254721Semaste    ///     in the "class_name" argument). The examples above would return:
405254721Semaste    ///         <empty>
406254721Semaste    ///         <empty>
407254721Semaste    ///         "-[NSString sizeWithAttributes:]"
408254721Semaste    ///         "+[NSString usesFontLeading]"
409254721Semaste    ///
410254721Semaste    /// @param[out] class_name_sans_category
411254721Semaste    ///     If non-NULL, this string will be filled in with the prototype
412254721Semaste    ///     name _without_ the category. If there is no category, and empty
413254721Semaste    ///     string will be returned (as this is already the value that was
414254721Semaste    ///     passed in). The examples above would return:
415254721Semaste    ///         <empty>
416254721Semaste    ///         <empty>
417254721Semaste    ///         "NSString"
418254721Semaste    ///         "NSString"
419254721Semaste    ///
420254721Semaste    /// @return
421254721Semaste    ///     Returns the number of strings that were successfully filled
422254721Semaste    ///     in.
423254721Semaste    //------------------------------------------------------------------
424254721Semaste//    static uint32_t
425254721Semaste//    ParseMethodName (const char *name,
426254721Semaste//                     ConstString *class_name,               // Class name (with category if there is one)
427254721Semaste//                     ConstString *selector_name,            // selector only
428254721Semaste//                     ConstString *name_sans_category,       // full function name with no category (empty if no category)
429254721Semaste//                     ConstString *class_name_sans_category);// Class name without category (empty if no category)
430254721Semaste
431254721Semaste    static bool
432254721Semaste    IsPossibleObjCMethodName (const char *name)
433254721Semaste    {
434254721Semaste        if (!name)
435254721Semaste            return false;
436254721Semaste        bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '[';
437254721Semaste        bool ends_right = (name[strlen(name) - 1] == ']');
438254721Semaste        return (starts_right && ends_right);
439254721Semaste    }
440254721Semaste
441254721Semaste    static bool
442254721Semaste    IsPossibleObjCSelector (const char *name)
443254721Semaste    {
444254721Semaste        if (!name)
445254721Semaste            return false;
446254721Semaste
447254721Semaste        if (strchr(name, ':') == NULL)
448254721Semaste            return true;
449254721Semaste        else if (name[strlen(name) - 1] == ':')
450254721Semaste            return true;
451254721Semaste        else
452254721Semaste            return false;
453254721Semaste    }
454254721Semaste
455254721Semaste    bool
456254721Semaste    HasNewLiteralsAndIndexing ()
457254721Semaste    {
458254721Semaste        if (m_has_new_literals_and_indexing == eLazyBoolCalculate)
459254721Semaste        {
460254721Semaste            if (CalculateHasNewLiteralsAndIndexing())
461254721Semaste                m_has_new_literals_and_indexing = eLazyBoolYes;
462254721Semaste            else
463254721Semaste                m_has_new_literals_and_indexing = eLazyBoolNo;
464254721Semaste        }
465254721Semaste
466254721Semaste        return (m_has_new_literals_and_indexing == eLazyBoolYes);
467254721Semaste    }
468254721Semaste
469254721Semaste    virtual void
470254721Semaste    SymbolsDidLoad (const ModuleList& module_list)
471254721Semaste    {
472254721Semaste        m_negative_complete_class_cache.clear();
473254721Semaste    }
474254721Semaste
475254721Semasteprotected:
476254721Semaste    //------------------------------------------------------------------
477254721Semaste    // Classes that inherit from ObjCLanguageRuntime can see and modify these
478254721Semaste    //------------------------------------------------------------------
479254721Semaste    ObjCLanguageRuntime(Process *process);
480254721Semaste
481254721Semaste    virtual bool CalculateHasNewLiteralsAndIndexing()
482254721Semaste    {
483254721Semaste        return false;
484254721Semaste    }
485254721Semaste
486254721Semaste
487254721Semaste    bool
488254721Semaste    ISAIsCached (ObjCISA isa) const
489254721Semaste    {
490254721Semaste        return m_isa_to_descriptor.find(isa) != m_isa_to_descriptor.end();
491254721Semaste    }
492254721Semaste
493254721Semaste    bool
494254721Semaste    AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp)
495254721Semaste    {
496254721Semaste        if (isa != 0)
497254721Semaste        {
498254721Semaste            m_isa_to_descriptor[isa] = descriptor_sp;
499254721Semaste            return true;
500254721Semaste        }
501254721Semaste        return false;
502254721Semaste    }
503254721Semaste
504254721Semaste    bool
505254721Semaste    AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name);
506254721Semaste
507254721Semaste    bool
508254721Semaste    AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, uint32_t class_name_hash)
509254721Semaste    {
510254721Semaste        if (isa != 0)
511254721Semaste        {
512254721Semaste            m_isa_to_descriptor[isa] = descriptor_sp;
513254721Semaste            m_hash_to_isa_map.insert(std::make_pair(class_name_hash, isa));
514254721Semaste            return true;
515254721Semaste        }
516254721Semaste        return false;
517254721Semaste    }
518254721Semaste
519254721Semasteprivate:
520254721Semaste    // We keep a map of <Class,Selector>->Implementation so we don't have to call the resolver
521254721Semaste    // function over and over.
522254721Semaste
523254721Semaste    // FIXME: We need to watch for the loading of Protocols, and flush the cache for any
524254721Semaste    // class that we see so changed.
525254721Semaste
526254721Semaste    struct ClassAndSel
527254721Semaste    {
528254721Semaste        ClassAndSel()
529254721Semaste        {
530254721Semaste            sel_addr = LLDB_INVALID_ADDRESS;
531254721Semaste            class_addr = LLDB_INVALID_ADDRESS;
532254721Semaste        }
533254721Semaste        ClassAndSel (lldb::addr_t in_sel_addr, lldb::addr_t in_class_addr) :
534254721Semaste            class_addr (in_class_addr),
535254721Semaste            sel_addr(in_sel_addr)
536254721Semaste        {
537254721Semaste        }
538254721Semaste        bool operator== (const ClassAndSel &rhs)
539254721Semaste        {
540254721Semaste            if (class_addr == rhs.class_addr
541254721Semaste                && sel_addr == rhs.sel_addr)
542254721Semaste                return true;
543254721Semaste            else
544254721Semaste                return false;
545254721Semaste        }
546254721Semaste
547254721Semaste        bool operator< (const ClassAndSel &rhs) const
548254721Semaste        {
549254721Semaste            if (class_addr < rhs.class_addr)
550254721Semaste                return true;
551254721Semaste            else if (class_addr > rhs.class_addr)
552254721Semaste                return false;
553254721Semaste            else
554254721Semaste            {
555254721Semaste                if (sel_addr < rhs.sel_addr)
556254721Semaste                    return true;
557254721Semaste                else
558254721Semaste                    return false;
559254721Semaste            }
560254721Semaste        }
561254721Semaste
562254721Semaste        lldb::addr_t class_addr;
563254721Semaste        lldb::addr_t sel_addr;
564254721Semaste    };
565254721Semaste
566254721Semaste    typedef std::map<ClassAndSel,lldb::addr_t> MsgImplMap;
567254721Semaste    typedef std::map<ObjCISA, ClassDescriptorSP> ISAToDescriptorMap;
568254721Semaste    typedef std::multimap<uint32_t, ObjCISA> HashToISAMap;
569254721Semaste    typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator;
570254721Semaste    typedef HashToISAMap::iterator HashToISAIterator;
571254721Semaste
572254721Semaste    MsgImplMap m_impl_cache;
573254721Semaste    LazyBool m_has_new_literals_and_indexing;
574254721Semaste    ISAToDescriptorMap m_isa_to_descriptor;
575254721Semaste    HashToISAMap m_hash_to_isa_map;
576254721Semaste
577254721Semasteprotected:
578254721Semaste    uint32_t m_isa_to_descriptor_stop_id;
579254721Semaste
580254721Semaste    typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap;
581254721Semaste    CompleteClassMap m_complete_class_cache;
582254721Semaste
583254721Semaste    struct ConstStringSetHelpers {
584254721Semaste        size_t operator () (const ConstString& arg) const // for hashing
585254721Semaste        {
586254721Semaste            return (size_t)arg.GetCString();
587254721Semaste        }
588254721Semaste        bool operator () (const ConstString& arg1, const ConstString& arg2) const // for equality
589254721Semaste        {
590254721Semaste            return arg1.operator==(arg2);
591254721Semaste        }
592254721Semaste    };
593254721Semaste    typedef std::unordered_set<ConstString, ConstStringSetHelpers, ConstStringSetHelpers> CompleteClassSet;
594254721Semaste    CompleteClassSet m_negative_complete_class_cache;
595254721Semaste
596254721Semaste    ISAToDescriptorIterator
597254721Semaste    GetDescriptorIterator (const ConstString &name);
598254721Semaste
599254721Semaste    DISALLOW_COPY_AND_ASSIGN (ObjCLanguageRuntime);
600254721Semaste};
601254721Semaste
602254721Semaste} // namespace lldb_private
603254721Semaste
604254721Semaste#endif  // liblldb_ObjCLanguageRuntime_h_
605