Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / utils / gdb-scripts / prettyprinters.py
blob1016467fc097478e6409c715ffae6109d3b4ccad
1 from __future__ import print_function
2 import struct
3 import sys
5 import gdb.printing
6 import gdb.types
9 class Iterator:
10 def __iter__(self):
11 return self
13 if sys.version_info.major == 2:
15 def next(self):
16 return self.__next__()
18 def children(self):
19 return self
22 class SmallStringPrinter:
23 """Print an llvm::SmallString object."""
25 def __init__(self, val):
26 self.val = val
28 def to_string(self):
29 data = self.val["BeginX"].cast(gdb.lookup_type("char").pointer())
30 length = self.val["Size"]
31 return data.lazy_string(length=length)
33 def display_hint(self):
34 return "string"
37 class StringRefPrinter:
38 """Print an llvm::StringRef object."""
40 def __init__(self, val):
41 self.val = val
43 def to_string(self):
44 data = self.val["Data"]
45 length = self.val["Length"]
46 return data.lazy_string(length=length)
48 def display_hint(self):
49 return "string"
52 class SmallVectorPrinter(Iterator):
53 """Print an llvm::SmallVector object."""
55 def __init__(self, val):
56 self.val = val
57 t = val.type.template_argument(0).pointer()
58 self.begin = val["BeginX"].cast(t)
59 self.size = val["Size"]
60 self.i = 0
62 def __next__(self):
63 if self.i == self.size:
64 raise StopIteration
65 ret = "[{}]".format(self.i), (self.begin + self.i).dereference()
66 self.i += 1
67 return ret
69 def to_string(self):
70 return "llvm::SmallVector of Size {}, Capacity {}".format(
71 self.size, self.val["Capacity"]
74 def display_hint(self):
75 return "array"
78 class ArrayRefPrinter:
79 """Print an llvm::ArrayRef object."""
81 class _iterator:
82 def __init__(self, begin, end):
83 self.cur = begin
84 self.end = end
85 self.count = 0
87 def __iter__(self):
88 return self
90 def __next__(self):
91 if self.cur == self.end:
92 raise StopIteration
93 count = self.count
94 self.count = self.count + 1
95 cur = self.cur
96 self.cur = self.cur + 1
97 return "[%d]" % count, cur.dereference()
99 if sys.version_info.major == 2:
100 next = __next__
102 def __init__(self, val):
103 self.val = val
105 def children(self):
106 data = self.val["Data"]
107 return self._iterator(data, data + self.val["Length"])
109 def to_string(self):
110 return "llvm::ArrayRef of length %d" % (self.val["Length"])
112 def display_hint(self):
113 return "array"
116 class ExpectedPrinter(Iterator):
117 """Print an llvm::Expected object."""
119 def __init__(self, val):
120 self.val = val
122 def __next__(self):
123 val = self.val
124 if val is None:
125 raise StopIteration
126 self.val = None
127 if val["HasError"]:
128 return (
129 "error",
130 val["ErrorStorage"]
131 .address.cast(gdb.lookup_type("llvm::ErrorInfoBase").pointer())
132 .dereference(),
134 return (
135 "value",
136 val["TStorage"]
137 .address.cast(val.type.template_argument(0).pointer())
138 .dereference(),
141 def to_string(self):
142 return "llvm::Expected{}".format(" is error" if self.val["HasError"] else "")
145 class OptionalPrinter(Iterator):
146 """Print an llvm::Optional object."""
148 def __init__(self, val):
149 self.val = val
151 def __next__(self):
152 val = self.val
153 if val is None:
154 raise StopIteration
155 self.val = None
156 if not val["Storage"]["hasVal"]:
157 raise StopIteration
158 return ("value", val["Storage"]["val"])
160 def to_string(self):
161 return "llvm::Optional{}".format(
162 "" if self.val["Storage"]["hasVal"] else " is not initialized"
166 class DenseMapPrinter:
167 "Print a DenseMap"
169 class _iterator:
170 def __init__(self, key_info_t, begin, end):
171 self.key_info_t = key_info_t
172 self.cur = begin
173 self.end = end
174 self.advancePastEmptyBuckets()
175 self.first = True
177 def __iter__(self):
178 return self
180 def advancePastEmptyBuckets(self):
181 # disabled until the comments below can be addressed
182 # keeping as notes/posterity/hints for future contributors
183 return
184 n = self.key_info_t.name
185 is_equal = gdb.parse_and_eval(n + "::isEqual")
186 empty = gdb.parse_and_eval(n + "::getEmptyKey()")
187 tombstone = gdb.parse_and_eval(n + "::getTombstoneKey()")
188 # the following is invalid, GDB fails with:
189 # Python Exception <class 'gdb.error'> Attempt to take address of value
190 # not located in memory.
191 # because isEqual took parameter (for the unsigned long key I was testing)
192 # by const ref, and GDB
193 # It's also not entirely general - we should be accessing the "getFirst()"
194 # member function, not the 'first' member variable, but I've yet to figure
195 # out how to find/call member functions (especially (const) overloaded
196 # ones) on a gdb.Value.
197 while self.cur != self.end and (
198 is_equal(self.cur.dereference()["first"], empty)
199 or is_equal(self.cur.dereference()["first"], tombstone)
201 self.cur = self.cur + 1
203 def __next__(self):
204 if self.cur == self.end:
205 raise StopIteration
206 cur = self.cur
207 v = cur.dereference()["first" if self.first else "second"]
208 if not self.first:
209 self.cur = self.cur + 1
210 self.advancePastEmptyBuckets()
211 self.first = True
212 else:
213 self.first = False
214 return "x", v
216 if sys.version_info.major == 2:
217 next = __next__
219 def __init__(self, val):
220 self.val = val
222 def children(self):
223 t = self.val.type.template_argument(3).pointer()
224 begin = self.val["Buckets"].cast(t)
225 end = (begin + self.val["NumBuckets"]).cast(t)
226 return self._iterator(self.val.type.template_argument(2), begin, end)
228 def to_string(self):
229 return "llvm::DenseMap with %d elements" % (self.val["NumEntries"])
231 def display_hint(self):
232 return "map"
235 class StringMapPrinter:
236 "Print a StringMap"
238 def __init__(self, val):
239 self.val = val
241 def children(self):
242 it = self.val["TheTable"]
243 end = it + self.val["NumBuckets"]
244 value_ty = self.val.type.template_argument(0)
245 entry_base_ty = gdb.lookup_type("llvm::StringMapEntryBase")
246 tombstone = gdb.parse_and_eval("llvm::StringMapImpl::TombstoneIntVal")
248 while it != end:
249 it_deref = it.dereference()
250 if it_deref == 0 or it_deref == tombstone:
251 it = it + 1
252 continue
254 entry_ptr = it_deref.cast(entry_base_ty.pointer())
255 entry = entry_ptr.dereference()
257 str_len = entry["keyLength"]
258 value_ptr = (entry_ptr + 1).cast(value_ty.pointer())
259 str_data = (entry_ptr + 1).cast(gdb.lookup_type("uintptr_t")) + max(
260 value_ty.sizeof, entry_base_ty.alignof
262 str_data = str_data.cast(gdb.lookup_type("char").const().pointer())
263 string_ref = gdb.Value(
264 struct.pack("PN", int(str_data), int(str_len)),
265 gdb.lookup_type("llvm::StringRef"),
267 yield "key", string_ref
269 value = value_ptr.dereference()
270 yield "value", value
272 it = it + 1
274 def to_string(self):
275 return "llvm::StringMap with %d elements" % (self.val["NumItems"])
277 def display_hint(self):
278 return "map"
281 class TwinePrinter:
282 "Print a Twine"
284 def __init__(self, val):
285 self._val = val
287 def display_hint(self):
288 return "string"
290 def string_from_pretty_printer_lookup(self, val):
291 """Lookup the default pretty-printer for val and use it.
293 If no pretty-printer is defined for the type of val, print an error and
294 return a placeholder string."""
296 pp = gdb.default_visualizer(val)
297 if pp:
298 s = pp.to_string()
300 # The pretty-printer may return a LazyString instead of an actual Python
301 # string. Convert it to a Python string. However, GDB doesn't seem to
302 # register the LazyString type, so we can't check
303 # "type(s) == gdb.LazyString".
304 if "LazyString" in type(s).__name__:
305 s = s.value().string()
307 else:
308 print(
310 "No pretty printer for {} found. The resulting Twine "
311 + "representation will be incomplete."
312 ).format(val.type.name)
314 s = "(missing {})".format(val.type.name)
316 return s
318 def is_twine_kind(self, kind, expected):
319 if not kind.endswith(expected):
320 return False
321 # apparently some GDB versions add the NodeKind:: namespace
322 # (happens for me on GDB 7.11)
323 return kind in (
324 "llvm::Twine::" + expected,
325 "llvm::Twine::NodeKind::" + expected,
328 def string_from_child(self, child, kind):
329 """Return the string representation of the Twine::Child child."""
331 if self.is_twine_kind(kind, "EmptyKind") or self.is_twine_kind(
332 kind, "NullKind"
334 return ""
336 if self.is_twine_kind(kind, "TwineKind"):
337 return self.string_from_twine_object(child["twine"].dereference())
339 if self.is_twine_kind(kind, "CStringKind"):
340 return child["cString"].string()
342 if self.is_twine_kind(kind, "StdStringKind"):
343 val = child["stdString"].dereference()
344 return self.string_from_pretty_printer_lookup(val)
346 if self.is_twine_kind(kind, "PtrAndLengthKind"):
347 val = child["ptrAndLength"]
348 data = val["ptr"]
349 length = val["length"]
350 return data.string(length=length)
352 if self.is_twine_kind(kind, "CharKind"):
353 return chr(child["character"])
355 if self.is_twine_kind(kind, "DecUIKind"):
356 return str(child["decUI"])
358 if self.is_twine_kind(kind, "DecIKind"):
359 return str(child["decI"])
361 if self.is_twine_kind(kind, "DecULKind"):
362 return str(child["decUL"].dereference())
364 if self.is_twine_kind(kind, "DecLKind"):
365 return str(child["decL"].dereference())
367 if self.is_twine_kind(kind, "DecULLKind"):
368 return str(child["decULL"].dereference())
370 if self.is_twine_kind(kind, "DecLLKind"):
371 return str(child["decLL"].dereference())
373 if self.is_twine_kind(kind, "UHexKind"):
374 val = child["uHex"].dereference()
375 return hex(int(val))
377 print(
379 "Unhandled NodeKind {} in Twine pretty-printer. The result will be "
380 "incomplete."
381 ).format(kind)
384 return "(unhandled {})".format(kind)
386 def string_from_twine_object(self, twine):
387 """Return the string representation of the Twine object twine."""
389 lhs = twine["LHS"]
390 rhs = twine["RHS"]
392 lhs_kind = str(twine["LHSKind"])
393 rhs_kind = str(twine["RHSKind"])
395 lhs_str = self.string_from_child(lhs, lhs_kind)
396 rhs_str = self.string_from_child(rhs, rhs_kind)
398 return lhs_str + rhs_str
400 def to_string(self):
401 return self.string_from_twine_object(self._val)
403 def display_hint(self):
404 return "string"
407 def get_pointer_int_pair(val):
408 """Get tuple from llvm::PointerIntPair."""
409 info_name = val.type.template_argument(4).strip_typedefs().name
410 # Note: this throws a gdb.error if the info type is not used (by means of a
411 # call to getPointer() or similar) in the current translation unit.
412 enum_type = gdb.lookup_type(info_name + "::MaskAndShiftConstants")
413 enum_dict = gdb.types.make_enum_dict(enum_type)
414 ptr_mask = enum_dict[info_name + "::PointerBitMask"]
415 int_shift = enum_dict[info_name + "::IntShift"]
416 int_mask = enum_dict[info_name + "::IntMask"]
417 pair_union = val["Value"]
418 pointer = pair_union & ptr_mask
419 value = (pair_union >> int_shift) & int_mask
420 return (pointer, value)
423 class PointerIntPairPrinter:
424 """Print a PointerIntPair."""
426 def __init__(self, pointer, value):
427 self.pointer = pointer
428 self.value = value
430 def children(self):
431 yield ("pointer", self.pointer)
432 yield ("value", self.value)
434 def to_string(self):
435 return "(%s, %s)" % (self.pointer.type, self.value.type)
438 def make_pointer_int_pair_printer(val):
439 """Factory for an llvm::PointerIntPair printer."""
440 try:
441 pointer, value = get_pointer_int_pair(val)
442 except gdb.error:
443 return None # If PointerIntPair cannot be analyzed, print as raw value.
444 pointer_type = val.type.template_argument(0)
445 value_type = val.type.template_argument(2)
446 return PointerIntPairPrinter(pointer.cast(pointer_type), value.cast(value_type))
449 class PointerUnionPrinter:
450 """Print a PointerUnion."""
452 def __init__(self, pointer):
453 self.pointer = pointer
455 def children(self):
456 yield ("pointer", self.pointer)
458 def to_string(self):
459 return "Containing %s" % self.pointer.type
462 def make_pointer_union_printer(val):
463 """Factory for an llvm::PointerUnion printer."""
464 try:
465 pointer, value = get_pointer_int_pair(val["Val"])
466 except gdb.error:
467 return None # If PointerIntPair cannot be analyzed, print as raw value.
468 pointer_type = val.type.template_argument(int(value))
469 return PointerUnionPrinter(pointer.cast(pointer_type))
472 class IlistNodePrinter:
473 """Print an llvm::ilist_node object."""
475 def __init__(self, val):
476 impl_type = val.type.fields()[0].type
477 base_type = impl_type.fields()[0].type
478 derived_type = val.type.template_argument(0)
480 def get_prev_and_sentinel(base):
481 # One of Prev and PrevAndSentinel exists. Depending on #defines used to
482 # compile LLVM, the base_type's template argument is either true of false.
483 if base_type.template_argument(0):
484 return get_pointer_int_pair(base["PrevAndSentinel"])
485 return base["Prev"], None
487 # Casts a base_type pointer to the appropriate derived type.
488 def cast_pointer(pointer):
489 sentinel = get_prev_and_sentinel(pointer.dereference())[1]
490 pointer = pointer.cast(impl_type.pointer())
491 if sentinel:
492 return pointer
493 return pointer.cast(derived_type.pointer())
495 # Repeated cast becaue val.type's base_type is ambiguous when using tags.
496 base = val.cast(impl_type).cast(base_type)
497 (prev, sentinel) = get_prev_and_sentinel(base)
498 prev = prev.cast(base_type.pointer())
499 self.prev = cast_pointer(prev)
500 self.next = cast_pointer(val["Next"])
501 self.sentinel = sentinel
503 def children(self):
504 if self.sentinel:
505 yield "sentinel", "yes"
506 yield "prev", self.prev
507 yield "next", self.next
510 class IlistPrinter:
511 """Print an llvm::simple_ilist or llvm::iplist object."""
513 def __init__(self, val):
514 self.node_type = val.type.template_argument(0)
515 sentinel = val["Sentinel"]
516 # First field is common base type of sentinel and ilist_node.
517 base_type = sentinel.type.fields()[0].type
518 self.sentinel = sentinel.address.cast(base_type.pointer())
520 def _pointers(self):
521 pointer = self.sentinel
522 while True:
523 pointer = pointer["Next"].cast(pointer.type)
524 if pointer == self.sentinel:
525 return
526 yield pointer.cast(self.node_type.pointer())
528 def children(self):
529 for k, v in enumerate(self._pointers()):
530 yield ("[%d]" % k, v.dereference())
533 pp = gdb.printing.RegexpCollectionPrettyPrinter("LLVMSupport")
534 pp.add_printer("llvm::SmallString", "^llvm::SmallString<.*>$", SmallStringPrinter)
535 pp.add_printer("llvm::StringRef", "^llvm::StringRef$", StringRefPrinter)
536 pp.add_printer(
537 "llvm::SmallVectorImpl", "^llvm::SmallVector(Impl)?<.*>$", SmallVectorPrinter
539 pp.add_printer("llvm::ArrayRef", "^llvm::(Mutable)?ArrayRef<.*>$", ArrayRefPrinter)
540 pp.add_printer("llvm::Expected", "^llvm::Expected<.*>$", ExpectedPrinter)
541 pp.add_printer("llvm::Optional", "^llvm::Optional<.*>$", OptionalPrinter)
542 pp.add_printer("llvm::DenseMap", "^llvm::DenseMap<.*>$", DenseMapPrinter)
543 pp.add_printer("llvm::StringMap", "^llvm::StringMap<.*>$", StringMapPrinter)
544 pp.add_printer("llvm::Twine", "^llvm::Twine$", TwinePrinter)
545 pp.add_printer(
546 "llvm::PointerIntPair", "^llvm::PointerIntPair<.*>$", make_pointer_int_pair_printer
548 pp.add_printer(
549 "llvm::PointerUnion", "^llvm::PointerUnion<.*>$", make_pointer_union_printer
551 pp.add_printer("llvm::ilist_node", "^llvm::ilist_node<.*>$", IlistNodePrinter)
552 pp.add_printer("llvm::iplist", "^llvm::iplist<.*>$", IlistPrinter)
553 pp.add_printer("llvm::simple_ilist", "^llvm::simple_ilist<.*>$", IlistPrinter)
554 gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)