1 from __future__
import print_function
13 if sys
.version_info
.major
== 2:
16 return self
.__next
__()
22 class SmallStringPrinter
:
23 """Print an llvm::SmallString object."""
25 def __init__(self
, val
):
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
):
37 class StringRefPrinter
:
38 """Print an llvm::StringRef object."""
40 def __init__(self
, val
):
44 data
= self
.val
["Data"]
45 length
= self
.val
["Length"]
46 return data
.lazy_string(length
=length
)
48 def display_hint(self
):
52 class SmallVectorPrinter(Iterator
):
53 """Print an llvm::SmallVector object."""
55 def __init__(self
, val
):
57 t
= val
.type.template_argument(0).pointer()
58 self
.begin
= val
["BeginX"].cast(t
)
59 self
.size
= val
["Size"]
63 if self
.i
== self
.size
:
65 ret
= "[{}]".format(self
.i
), (self
.begin
+ self
.i
).dereference()
70 return "llvm::SmallVector of Size {}, Capacity {}".format(
71 self
.size
, self
.val
["Capacity"]
74 def display_hint(self
):
78 class ArrayRefPrinter
:
79 """Print an llvm::ArrayRef object."""
82 def __init__(self
, begin
, end
):
91 if self
.cur
== self
.end
:
94 self
.count
= self
.count
+ 1
96 self
.cur
= self
.cur
+ 1
97 return "[%d]" % count
, cur
.dereference()
99 if sys
.version_info
.major
== 2:
102 def __init__(self
, val
):
106 data
= self
.val
["Data"]
107 return self
._iterator
(data
, data
+ self
.val
["Length"])
110 return "llvm::ArrayRef of length %d" % (self
.val
["Length"])
112 def display_hint(self
):
116 class ExpectedPrinter(Iterator
):
117 """Print an llvm::Expected object."""
119 def __init__(self
, val
):
131 .address
.cast(gdb
.lookup_type("llvm::ErrorInfoBase").pointer())
137 .address
.cast(val
.type.template_argument(0).pointer())
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
):
156 if not val
["Storage"]["hasVal"]:
158 return ("value", val
["Storage"]["val"])
161 return "llvm::Optional{}".format(
162 "" if self
.val
["Storage"]["hasVal"] else " is not initialized"
166 class DenseMapPrinter
:
170 def __init__(self
, key_info_t
, begin
, end
):
171 self
.key_info_t
= key_info_t
174 self
.advancePastEmptyBuckets()
180 def advancePastEmptyBuckets(self
):
181 # disabled until the comments below can be addressed
182 # keeping as notes/posterity/hints for future contributors
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
204 if self
.cur
== self
.end
:
207 v
= cur
.dereference()["first" if self
.first
else "second"]
209 self
.cur
= self
.cur
+ 1
210 self
.advancePastEmptyBuckets()
216 if sys
.version_info
.major
== 2:
219 def __init__(self
, val
):
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
)
229 return "llvm::DenseMap with %d elements" % (self
.val
["NumEntries"])
231 def display_hint(self
):
235 class StringMapPrinter
:
238 def __init__(self
, val
):
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")
249 it_deref
= it
.dereference()
250 if it_deref
== 0 or it_deref
== tombstone
:
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()
275 return "llvm::StringMap with %d elements" % (self
.val
["NumItems"])
277 def display_hint(self
):
284 def __init__(self
, val
):
287 def display_hint(self
):
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
)
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()
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
)
318 def is_twine_kind(self
, kind
, expected
):
319 if not kind
.endswith(expected
):
321 # apparently some GDB versions add the NodeKind:: namespace
322 # (happens for me on GDB 7.11)
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(
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"]
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()
379 "Unhandled NodeKind {} in Twine pretty-printer. The result will be "
384 return "(unhandled {})".format(kind
)
386 def string_from_twine_object(self
, twine
):
387 """Return the string representation of the Twine object twine."""
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
401 return self
.string_from_twine_object(self
._val
)
403 def display_hint(self
):
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 value_type
= pair_union
.type.template_argument(0)
419 value_type_ptr
= value_type
.pointer()
420 pair_union
= pair_union
.address
.cast(value_type_ptr
).dereference()
421 pair_union
= pair_union
.cast(gdb
.lookup_type("intptr_t"))
422 pointer
= pair_union
& ptr_mask
423 pointer
= pointer
.cast(value_type
)
424 value
= (pair_union
>> int_shift
) & int_mask
425 return (pointer
, value
)
428 class PointerIntPairPrinter
:
429 """Print a PointerIntPair."""
431 def __init__(self
, pointer
, value
):
432 self
.pointer
= pointer
436 yield ("pointer", self
.pointer
)
437 yield ("value", self
.value
)
440 return "(%s, %s)" % (self
.pointer
.type, self
.value
.type)
443 def make_pointer_int_pair_printer(val
):
444 """Factory for an llvm::PointerIntPair printer."""
446 pointer
, value
= get_pointer_int_pair(val
)
448 return None # If PointerIntPair cannot be analyzed, print as raw value.
449 pointer_type
= val
.type.template_argument(0)
450 value_type
= val
.type.template_argument(2)
451 return PointerIntPairPrinter(pointer
.cast(pointer_type
), value
.cast(value_type
))
454 class PointerUnionPrinter
:
455 """Print a PointerUnion."""
457 def __init__(self
, pointer
):
458 self
.pointer
= pointer
461 yield ("pointer", self
.pointer
)
464 return "Containing %s" % self
.pointer
.type
467 def make_pointer_union_printer(val
):
468 """Factory for an llvm::PointerUnion printer."""
470 pointer
, value
= get_pointer_int_pair(val
["Val"])
472 return None # If PointerIntPair cannot be analyzed, print as raw value.
473 pointer_type
= val
.type.template_argument(int(value
))
474 return PointerUnionPrinter(pointer
.cast(pointer_type
))
477 class IlistNodePrinter
:
478 """Print an llvm::ilist_node object."""
480 def __init__(self
, val
):
481 impl_type
= val
.type.fields()[0].type
482 base_type
= impl_type
.fields()[0].type
483 derived_type
= val
.type.template_argument(0)
485 def get_prev_and_sentinel(base
):
486 # One of Prev and PrevAndSentinel exists. Depending on #defines used to
487 # compile LLVM, the base_type's template argument is either true of false.
488 if base_type
.template_argument(0):
489 return get_pointer_int_pair(base
["PrevAndSentinel"])
490 return base
["Prev"], None
492 # Casts a base_type pointer to the appropriate derived type.
493 def cast_pointer(pointer
):
494 sentinel
= get_prev_and_sentinel(pointer
.dereference())[1]
495 pointer
= pointer
.cast(impl_type
.pointer())
498 return pointer
.cast(derived_type
.pointer())
500 # Repeated cast becaue val.type's base_type is ambiguous when using tags.
501 base
= val
.cast(impl_type
).cast(base_type
)
502 (prev
, sentinel
) = get_prev_and_sentinel(base
)
503 prev
= prev
.cast(base_type
.pointer())
504 self
.prev
= cast_pointer(prev
)
505 self
.next
= cast_pointer(val
["Next"])
506 self
.sentinel
= sentinel
510 yield "sentinel", "yes"
511 yield "prev", self
.prev
512 yield "next", self
.next
516 """Print an llvm::simple_ilist or llvm::iplist object."""
518 def __init__(self
, val
):
519 self
.node_type
= val
.type.template_argument(0)
520 sentinel
= val
["Sentinel"]
521 # First field is common base type of sentinel and ilist_node.
522 base_type
= sentinel
.type.fields()[0].type
523 self
.sentinel
= sentinel
.address
.cast(base_type
.pointer())
526 pointer
= self
.sentinel
528 pointer
= pointer
["Next"].cast(pointer
.type)
529 if pointer
== self
.sentinel
:
531 yield pointer
.cast(self
.node_type
.pointer())
534 for k
, v
in enumerate(self
._pointers
()):
535 yield ("[%d]" % k
, v
.dereference())
538 pp
= gdb
.printing
.RegexpCollectionPrettyPrinter("LLVMSupport")
539 pp
.add_printer("llvm::SmallString", "^llvm::SmallString<.*>$", SmallStringPrinter
)
540 pp
.add_printer("llvm::StringRef", "^llvm::StringRef$", StringRefPrinter
)
542 "llvm::SmallVectorImpl", "^llvm::SmallVector(Impl)?<.*>$", SmallVectorPrinter
544 pp
.add_printer("llvm::ArrayRef", "^llvm::(Mutable)?ArrayRef<.*>$", ArrayRefPrinter
)
545 pp
.add_printer("llvm::Expected", "^llvm::Expected<.*>$", ExpectedPrinter
)
546 pp
.add_printer("llvm::Optional", "^llvm::Optional<.*>$", OptionalPrinter
)
547 pp
.add_printer("llvm::DenseMap", "^llvm::DenseMap<.*>$", DenseMapPrinter
)
548 pp
.add_printer("llvm::StringMap", "^llvm::StringMap<.*>$", StringMapPrinter
)
549 pp
.add_printer("llvm::Twine", "^llvm::Twine$", TwinePrinter
)
551 "llvm::PointerIntPair", "^llvm::PointerIntPair<.*>$", make_pointer_int_pair_printer
554 "llvm::PointerUnion", "^llvm::PointerUnion<.*>$", make_pointer_union_printer
556 pp
.add_printer("llvm::ilist_node", "^llvm::ilist_node<.*>$", IlistNodePrinter
)
557 pp
.add_printer("llvm::iplist", "^llvm::iplist<.*>$", IlistPrinter
)
558 pp
.add_printer("llvm::simple_ilist", "^llvm::simple_ilist<.*>$", IlistPrinter
)
559 gdb
.printing
.register_pretty_printer(gdb
.current_objfile(), pp
)