Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / examples / summaries / cocoa / NSNumber.py
blob8812ba45bc9af6bbd62fa14985ff2e18e004353d
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 NSNumber
9 # the real summary is now C++ code built into LLDB
11 import lldb
12 import ctypes
13 import lldb.runtime.objc.objc_runtime
14 import lldb.formatters.metrics
15 import struct
16 import lldb.formatters.Logger
18 statistics = lldb.formatters.metrics.Metrics()
19 statistics.add_metric("invalid_isa")
20 statistics.add_metric("invalid_pointer")
21 statistics.add_metric("unknown_class")
22 statistics.add_metric("code_notrun")
24 # despite the similary to synthetic children providers, these classes are not
25 # trying to provide anything but the port number of an NSNumber, so they need not
26 # obey the interface specification for synthetic children providers
29 class NSTaggedNumber_SummaryProvider:
30 def adjust_for_architecture(self):
31 pass
33 def __init__(self, valobj, info_bits, data, params):
34 logger = lldb.formatters.Logger.Logger()
35 self.valobj = valobj
36 self.sys_params = params
37 self.info_bits = info_bits
38 self.data = data
39 self.update()
41 def update(self):
42 logger = lldb.formatters.Logger.Logger()
43 self.adjust_for_architecture()
45 def value(self):
46 logger = lldb.formatters.Logger.Logger()
47 # in spite of the plenty of types made available by the public NSNumber API
48 # only a bunch of these are actually used in the internal implementation
49 # unfortunately, the original type information appears to be lost
50 # so we try to at least recover the proper magnitude of the data
51 if self.info_bits == 0:
52 return "(char)" + str(ord(ctypes.c_char(chr(self.data % 256)).value))
53 if self.info_bits == 4:
54 return "(short)" + str(ctypes.c_short(self.data % (256 * 256)).value)
55 if self.info_bits == 8:
56 return "(int)" + str(
57 ctypes.c_int(self.data % (256 * 256 * 256 * 256)).value
59 if self.info_bits == 12:
60 return "(long)" + str(ctypes.c_long(self.data).value)
61 else:
62 return (
63 "unexpected value:(info="
64 + str(self.info_bits)
65 + ", value = "
66 + str(self.data)
67 + ")"
71 class NSUntaggedNumber_SummaryProvider:
72 def adjust_for_architecture(self):
73 pass
75 def __init__(self, valobj, params):
76 logger = lldb.formatters.Logger.Logger()
77 self.valobj = valobj
78 self.sys_params = params
79 if not (self.sys_params.types_cache.char):
80 self.sys_params.types_cache.char = self.valobj.GetType().GetBasicType(
81 lldb.eBasicTypeChar
83 if not (self.sys_params.types_cache.short):
84 self.sys_params.types_cache.short = self.valobj.GetType().GetBasicType(
85 lldb.eBasicTypeShort
87 if not (self.sys_params.types_cache.ushort):
88 self.sys_params.types_cache.ushort = self.valobj.GetType().GetBasicType(
89 lldb.eBasicTypeUnsignedShort
91 if not (self.sys_params.types_cache.int):
92 self.sys_params.types_cache.int = self.valobj.GetType().GetBasicType(
93 lldb.eBasicTypeInt
95 if not (self.sys_params.types_cache.long):
96 self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(
97 lldb.eBasicTypeLong
99 if not (self.sys_params.types_cache.ulong):
100 self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(
101 lldb.eBasicTypeUnsignedLong
103 if not (self.sys_params.types_cache.longlong):
104 self.sys_params.types_cache.longlong = self.valobj.GetType().GetBasicType(
105 lldb.eBasicTypeLongLong
107 if not (self.sys_params.types_cache.ulonglong):
108 self.sys_params.types_cache.ulonglong = self.valobj.GetType().GetBasicType(
109 lldb.eBasicTypeUnsignedLongLong
111 if not (self.sys_params.types_cache.float):
112 self.sys_params.types_cache.float = self.valobj.GetType().GetBasicType(
113 lldb.eBasicTypeFloat
115 if not (self.sys_params.types_cache.double):
116 self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(
117 lldb.eBasicTypeDouble
119 self.update()
121 def update(self):
122 logger = lldb.formatters.Logger.Logger()
123 self.adjust_for_architecture()
125 def value(self):
126 logger = lldb.formatters.Logger.Logger()
127 global statistics
128 # we need to skip the ISA, then the next byte tells us what to read
129 # we then skip one other full pointer worth of data and then fetch the contents
130 # if we are fetching an int64 value, one more pointer must be skipped
131 # to get at our data
132 data_type_vo = self.valobj.CreateChildAtOffset(
133 "dt", self.sys_params.pointer_size, self.sys_params.types_cache.char
135 data_type = (data_type_vo.GetValueAsUnsigned(0) % 256) & 0x1F
136 data_offset = 2 * self.sys_params.pointer_size
137 if data_type == 0b00001:
138 data_vo = self.valobj.CreateChildAtOffset(
139 "data", data_offset, self.sys_params.types_cache.char
141 statistics.metric_hit("code_notrun", self.valobj)
142 return "(char)" + str(
143 ord(ctypes.c_char(chr(data_vo.GetValueAsUnsigned(0))).value)
145 elif data_type == 0b0010:
146 data_vo = self.valobj.CreateChildAtOffset(
147 "data", data_offset, self.sys_params.types_cache.short
149 statistics.metric_hit("code_notrun", self.valobj)
150 return "(short)" + str(
151 ctypes.c_short(data_vo.GetValueAsUnsigned(0) % (256 * 256)).value
153 # IF tagged pointers are possible on 32bit+v2 runtime
154 # (of which the only existing instance should be iOS)
155 # then values of this type might be tagged
156 elif data_type == 0b0011:
157 data_vo = self.valobj.CreateChildAtOffset(
158 "data", data_offset, self.sys_params.types_cache.int
160 statistics.metric_hit("code_notrun", self.valobj)
161 return "(int)" + str(
162 ctypes.c_int(
163 data_vo.GetValueAsUnsigned(0) % (256 * 256 * 256 * 256)
164 ).value
166 # apparently, on is_64_bit architectures, these are the only values that will ever
167 # be represented by a non tagged pointers
168 elif data_type == 0b10001:
169 data_offset = data_offset + 8 # 8 is needed even if we are on 32bit
170 data_vo = self.valobj.CreateChildAtOffset(
171 "data", data_offset, self.sys_params.types_cache.longlong
173 statistics.metric_hit("code_notrun", self.valobj)
174 return "(long)" + str(ctypes.c_long(data_vo.GetValueAsUnsigned(0)).value)
175 elif data_type == 0b0100:
176 if self.sys_params.is_64_bit:
177 data_offset = data_offset + self.sys_params.pointer_size
178 data_vo = self.valobj.CreateChildAtOffset(
179 "data", data_offset, self.sys_params.types_cache.longlong
181 statistics.metric_hit("code_notrun", self.valobj)
182 return "(long)" + str(ctypes.c_long(data_vo.GetValueAsUnsigned(0)).value)
183 elif data_type == 0b0101:
184 data_vo = self.valobj.CreateChildAtOffset(
185 "data", data_offset, self.sys_params.types_cache.longlong
187 data_plain = int(str(data_vo.GetValueAsUnsigned(0) & 0x00000000FFFFFFFF))
188 packed = struct.pack("I", data_plain)
189 data_float = struct.unpack("f", packed)[0]
190 statistics.metric_hit("code_notrun", self.valobj)
191 return "(float)" + str(data_float)
192 elif data_type == 0b0110:
193 data_vo = self.valobj.CreateChildAtOffset(
194 "data", data_offset, self.sys_params.types_cache.longlong
196 data_plain = data_vo.GetValueAsUnsigned(0)
197 data_double = struct.unpack("d", struct.pack("Q", data_plain))[0]
198 statistics.metric_hit("code_notrun", self.valobj)
199 return "(double)" + str(data_double)
200 statistics.metric_hit(
201 "unknown_class",
202 str(valobj.GetName()) + " had unknown data_type " + str(data_type),
204 return "unexpected: dt = " + str(data_type)
207 class NSUnknownNumber_SummaryProvider:
208 def adjust_for_architecture(self):
209 pass
211 def __init__(self, valobj, params):
212 logger = lldb.formatters.Logger.Logger()
213 self.valobj = valobj
214 self.sys_params = params
215 self.update()
217 def update(self):
218 logger = lldb.formatters.Logger.Logger()
219 self.adjust_for_architecture()
221 def value(self):
222 logger = lldb.formatters.Logger.Logger()
223 stream = lldb.SBStream()
224 self.valobj.GetExpressionPath(stream)
225 expr = "(NSString*)[" + stream.GetData() + " stringValue]"
226 num_children_vo = self.valobj.CreateValueFromExpression("str", expr)
227 if num_children_vo.IsValid():
228 return num_children_vo.GetSummary()
229 return "<variable is not NSNumber>"
232 def GetSummary_Impl(valobj):
233 logger = lldb.formatters.Logger.Logger()
234 global statistics
236 class_data,
237 wrapper,
238 ) = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
239 valobj, statistics
241 if wrapper:
242 return wrapper
244 name_string = class_data.class_name()
245 logger >> "class name is: " + str(name_string)
247 if name_string == "NSNumber" or name_string == "__NSCFNumber":
248 if class_data.is_tagged():
249 wrapper = NSTaggedNumber_SummaryProvider(
250 valobj,
251 class_data.info_bits(),
252 class_data.value(),
253 class_data.sys_params,
255 statistics.metric_hit("code_notrun", valobj)
256 else:
257 # the wrapper might be unable to decipher what is into the NSNumber
258 # and then have to run code on it
259 wrapper = NSUntaggedNumber_SummaryProvider(valobj, class_data.sys_params)
260 else:
261 wrapper = NSUnknownNumber_SummaryProvider(valobj, class_data.sys_params)
262 statistics.metric_hit(
263 "unknown_class", valobj.GetName() + " seen as " + name_string
265 return wrapper
268 def NSNumber_SummaryProvider(valobj, dict):
269 logger = lldb.formatters.Logger.Logger()
270 provider = GetSummary_Impl(valobj)
271 if provider is not None:
272 if isinstance(
273 provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description
275 return provider.message()
276 try:
277 summary = provider.value()
278 except Exception as foo:
279 print(foo)
280 # except:
281 summary = None
282 logger >> "got summary " + str(summary)
283 if summary is None:
284 summary = "<variable is not NSNumber>"
285 return str(summary)
286 return "Summary Unavailable"
289 def __lldb_init_module(debugger, dict):
290 debugger.HandleCommand(
291 "type summary add -F NSNumber.NSNumber_SummaryProvider NSNumber"
293 debugger.HandleCommand(
294 "type summary add -F NSNumber.NSNumber_SummaryProvider __NSCFBoolean"
296 debugger.HandleCommand(
297 "type summary add -F NSNumber.NSNumber_SummaryProvider __NSCFNumber"