Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / examples / summaries / cocoa / NSIndexSet.py
blob559b8ebe425272630eecf3a5eee7710eeb4c7341
1 """
2 LLDB AppKit formatters
4 Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 See https://llvm.org/LICENSE.txt for license information.
6 SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 """
8 # example summary provider for NS(Mutable)IndexSet
9 # the real summary is now C++ code built into LLDB
10 import lldb
11 import ctypes
12 import lldb.runtime.objc.objc_runtime
13 import lldb.formatters.metrics
14 import lldb.formatters.Logger
16 statistics = lldb.formatters.metrics.Metrics()
17 statistics.add_metric("invalid_isa")
18 statistics.add_metric("invalid_pointer")
19 statistics.add_metric("unknown_class")
20 statistics.add_metric("code_notrun")
22 # despite the similary to synthetic children providers, these classes are not
23 # trying to provide anything but the count of values for an NSIndexSet, so they need not
24 # obey the interface specification for synthetic children providers
27 class NSIndexSetClass_SummaryProvider:
28 def adjust_for_architecture(self):
29 pass
31 def __init__(self, valobj, params):
32 logger = lldb.formatters.Logger.Logger()
33 self.valobj = valobj
34 self.sys_params = params
35 if not (self.sys_params.types_cache.NSUInteger):
36 if self.sys_params.is_64_bit:
37 self.sys_params.types_cache.NSUInteger = (
38 self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
40 self.sys_params.types_cache.uint32 = self.valobj.GetType().GetBasicType(
41 lldb.eBasicTypeUnsignedInt
43 else:
44 self.sys_params.types_cache.NSUInteger = (
45 self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
47 self.sys_params.types_cache.uint32 = self.valobj.GetType().GetBasicType(
48 lldb.eBasicTypeUnsignedInt
50 if not (self.sys_params.types_cache.uint32):
51 self.sys_params.types_cache.uint32 = self.valobj.GetType().GetBasicType(
52 lldb.eBasicTypeUnsignedInt
54 self.update()
56 def update(self):
57 logger = lldb.formatters.Logger.Logger()
58 self.adjust_for_architecture()
60 # NS(Mutable)IndexSet works in one of two modes: when having a compact block of data (e.g. a Range)
61 # the count is stored in the set itself, 3 pointers into it
62 # otherwise, it will store a pointer to an additional data structure (2 pointers into itself) and this
63 # additional structure will contain the count two pointers deep
64 # a bunch of flags allow us to detect an empty set, vs. a one-range set,
65 # vs. a multi-range set
66 def count(self):
67 logger = lldb.formatters.Logger.Logger()
68 mode_chooser_vo = self.valobj.CreateChildAtOffset(
69 "mode_chooser",
70 self.sys_params.pointer_size,
71 self.sys_params.types_cache.uint32,
73 mode_chooser = mode_chooser_vo.GetValueAsUnsigned(0)
74 if self.sys_params.is_64_bit:
75 mode_chooser = mode_chooser & 0x00000000FFFFFFFF
76 # empty set
77 if mode_chooser & 0x01 == 1:
78 return 0
79 # single range
80 if mode_chooser & 0x02 == 2:
81 mode = 1
82 # multi range
83 else:
84 mode = 2
85 if mode == 1:
86 count_vo = self.valobj.CreateChildAtOffset(
87 "count",
88 3 * self.sys_params.pointer_size,
89 self.sys_params.types_cache.NSUInteger,
91 else:
92 count_ptr = self.valobj.CreateChildAtOffset(
93 "count_ptr",
94 2 * self.sys_params.pointer_size,
95 self.sys_params.types_cache.NSUInteger,
97 count_vo = self.valobj.CreateValueFromAddress(
98 "count",
99 count_ptr.GetValueAsUnsigned() + 2 * self.sys_params.pointer_size,
100 self.sys_params.types_cache.NSUInteger,
102 return count_vo.GetValueAsUnsigned(0)
105 class NSIndexSetUnknown_SummaryProvider:
106 def adjust_for_architecture(self):
107 pass
109 def __init__(self, valobj, params):
110 logger = lldb.formatters.Logger.Logger()
111 self.valobj = valobj
112 self.sys_params = params
113 self.update()
115 def update(self):
116 logger = lldb.formatters.Logger.Logger()
117 self.adjust_for_architecture()
119 def count(self):
120 logger = lldb.formatters.Logger.Logger()
121 stream = lldb.SBStream()
122 self.valobj.GetExpressionPath(stream)
123 expr = "(int)[" + stream.GetData() + " count]"
124 num_children_vo = self.valobj.CreateValueFromExpression("count", expr)
125 if num_children_vo.IsValid():
126 return num_children_vo.GetValueAsUnsigned(0)
127 return "<variable is not NSIndexSet>"
130 def GetSummary_Impl(valobj):
131 logger = lldb.formatters.Logger.Logger()
132 global statistics
134 class_data,
135 wrapper,
136 ) = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
137 valobj, statistics
139 if wrapper:
140 return wrapper
142 name_string = class_data.class_name()
143 logger >> "class name is: " + str(name_string)
145 if name_string == "NSIndexSet" or name_string == "NSMutableIndexSet":
146 wrapper = NSIndexSetClass_SummaryProvider(valobj, class_data.sys_params)
147 statistics.metric_hit("code_notrun", valobj)
148 else:
149 wrapper = NSIndexSetUnknown_SummaryProvider(valobj, class_data.sys_params)
150 statistics.metric_hit(
151 "unknown_class", valobj.GetName() + " seen as " + name_string
153 return wrapper
156 def NSIndexSet_SummaryProvider(valobj, dict):
157 logger = lldb.formatters.Logger.Logger()
158 provider = GetSummary_Impl(valobj)
159 if provider is not None:
160 if isinstance(
161 provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description
163 return provider.message()
164 try:
165 summary = provider.count()
166 except:
167 summary = None
168 logger >> "got summary " + str(summary)
169 if summary is None:
170 summary = "<variable is not NSIndexSet>"
171 if isinstance(summary, str):
172 return summary
173 else:
174 summary = str(summary) + (" indexes" if summary != 1 else " index")
175 return summary
176 return "Summary Unavailable"
179 def __lldb_init_module(debugger, dict):
180 debugger.HandleCommand(
181 "type summary add -F NSIndexSet.NSIndexSet_SummaryProvider NSIndexSet NSMutableIndexSet"