1 from __future__
import print_function
12 if sys
.version_info
.major
== 2:
14 return self
.__next
__()
19 def escape_bytes(val
, l
):
20 return '"' + val
.string(encoding
='Latin-1', length
=l
).encode('unicode_escape').decode() + '"'
22 class SmallStringPrinter
:
23 """Print an llvm::SmallString object."""
25 def __init__(self
, val
):
29 begin
= self
.val
['BeginX']
30 return escape_bytes(begin
.cast(gdb
.lookup_type('char').pointer()), self
.val
['Size'])
32 class StringRefPrinter
:
33 """Print an llvm::StringRef object."""
35 def __init__(self
, val
):
39 return escape_bytes(self
.val
['Data'], self
.val
['Length'])
41 class SmallVectorPrinter(Iterator
):
42 """Print an llvm::SmallVector object."""
44 def __init__(self
, val
):
46 t
= val
.type.template_argument(0).pointer()
47 self
.begin
= val
['BeginX'].cast(t
)
48 self
.size
= val
['Size']
52 if self
.i
== self
.size
:
54 ret
= '[{}]'.format(self
.i
), (self
.begin
+self
.i
).dereference()
59 return 'llvm::SmallVector of Size {}, Capacity {}'.format(self
.size
, self
.val
['Capacity'])
61 def display_hint (self
):
64 class ArrayRefPrinter
:
65 """Print an llvm::ArrayRef object."""
68 def __init__(self
, begin
, end
):
77 if self
.cur
== self
.end
:
80 self
.count
= self
.count
+ 1
82 self
.cur
= self
.cur
+ 1
83 return '[%d]' % count
, cur
.dereference()
85 if sys
.version_info
.major
== 2:
88 def __init__(self
, val
):
92 data
= self
.val
['Data']
93 return self
._iterator
(data
, data
+ self
.val
['Length'])
96 return 'llvm::ArrayRef of length %d' % (self
.val
['Length'])
98 def display_hint (self
):
101 class ExpectedPrinter(Iterator
):
102 """Print an llvm::Expected object."""
104 def __init__(self
, val
):
113 return ('error', val
['ErrorStorage'].address
.cast(
114 gdb
.lookup_type('llvm::ErrorInfoBase').pointer()).dereference())
115 return ('value', val
['TStorage'].address
.cast(
116 val
.type.template_argument(0).pointer()).dereference())
119 return 'llvm::Expected{}'.format(' is error' if self
.val
['HasError'] else '')
121 class OptionalPrinter(Iterator
):
122 """Print an llvm::Optional object."""
124 def __init__(self
, val
):
132 if not val
['Storage']['hasVal']:
134 return ('value', val
['Storage']['value'])
137 return 'llvm::Optional{}'.format('' if self
.val
['Storage']['hasVal'] else ' is not initialized')
139 class DenseMapPrinter
:
143 def __init__(self
, key_info_t
, begin
, end
):
144 self
.key_info_t
= key_info_t
147 self
.advancePastEmptyBuckets()
153 def advancePastEmptyBuckets(self
):
154 # disabled until the comments below can be addressed
155 # keeping as notes/posterity/hints for future contributors
157 n
= self
.key_info_t
.name
158 is_equal
= gdb
.parse_and_eval(n
+ '::isEqual')
159 empty
= gdb
.parse_and_eval(n
+ '::getEmptyKey()')
160 tombstone
= gdb
.parse_and_eval(n
+ '::getTombstoneKey()')
161 # the following is invalid, GDB fails with:
162 # Python Exception <class 'gdb.error'> Attempt to take address of value
163 # not located in memory.
164 # because isEqual took parameter (for the unsigned long key I was testing)
165 # by const ref, and GDB
166 # It's also not entirely general - we should be accessing the "getFirst()"
167 # member function, not the 'first' member variable, but I've yet to figure
168 # out how to find/call member functions (especially (const) overloaded
169 # ones) on a gdb.Value.
170 while self
.cur
!= self
.end
and (is_equal(self
.cur
.dereference()['first'], empty
) or is_equal(self
.cur
.dereference()['first'], tombstone
)):
171 self
.cur
= self
.cur
+ 1
174 if self
.cur
== self
.end
:
177 v
= cur
.dereference()['first' if self
.first
else 'second']
179 self
.cur
= self
.cur
+ 1
180 self
.advancePastEmptyBuckets()
186 if sys
.version_info
.major
== 2:
189 def __init__(self
, val
):
193 t
= self
.val
.type.template_argument(3).pointer()
194 begin
= self
.val
['Buckets'].cast(t
)
195 end
= (begin
+ self
.val
['NumBuckets']).cast(t
)
196 return self
._iterator
(self
.val
.type.template_argument(2), begin
, end
)
199 return 'llvm::DenseMap with %d elements' % (self
.val
['NumEntries'])
201 def display_hint(self
):
204 class StringMapPrinter
:
207 def __init__(self
, val
):
211 it
= self
.val
['TheTable']
212 end
= (it
+ self
.val
['NumBuckets'])
213 value_ty
= self
.val
.type.template_argument(0)
214 entry_base_ty
= gdb
.lookup_type('llvm::StringMapEntryBase')
215 tombstone
= gdb
.parse_and_eval('llvm::StringMapImpl::TombstoneIntVal');
218 it_deref
= it
.dereference()
219 if it_deref
== 0 or it_deref
== tombstone
:
223 entry_ptr
= it_deref
.cast(entry_base_ty
.pointer())
224 entry
= entry_ptr
.dereference()
226 str_len
= entry
['keyLength']
227 value_ptr
= (entry_ptr
+ 1).cast(value_ty
.pointer())
228 str_data
= (entry_ptr
+ 1).cast(gdb
.lookup_type('uintptr_t')) + max(value_ty
.sizeof
, entry_base_ty
.alignof
)
229 str_data
= str_data
.cast(gdb
.lookup_type('char').const().pointer())
230 string_ref
= gdb
.Value(struct
.pack('PN', int(str_data
), int(str_len
)), gdb
.lookup_type('llvm::StringRef'))
231 yield 'key', string_ref
233 value
= value_ptr
.dereference()
239 return 'llvm::StringMap with %d elements' % (self
.val
['NumItems'])
241 def display_hint(self
):
247 def __init__(self
, val
):
250 def display_hint(self
):
253 def string_from_pretty_printer_lookup(self
, val
):
254 '''Lookup the default pretty-printer for val and use it.
256 If no pretty-printer is defined for the type of val, print an error and
257 return a placeholder string.'''
259 pp
= gdb
.default_visualizer(val
)
263 # The pretty-printer may return a LazyString instead of an actual Python
264 # string. Convert it to a Python string. However, GDB doesn't seem to
265 # register the LazyString type, so we can't check
266 # "type(s) == gdb.LazyString".
267 if 'LazyString' in type(s
).__name
__:
268 s
= s
.value().address
.string()
271 print(('No pretty printer for {} found. The resulting Twine ' +
272 'representation will be incomplete.').format(val
.type.name
))
273 s
= '(missing {})'.format(val
.type.name
)
277 def is_twine_kind(self
, kind
, expected
):
278 if not kind
.endswith(expected
):
280 # apparently some GDB versions add the NodeKind:: namespace
281 # (happens for me on GDB 7.11)
282 return kind
in ('llvm::Twine::' + expected
,
283 'llvm::Twine::NodeKind::' + expected
)
285 def string_from_child(self
, child
, kind
):
286 '''Return the string representation of the Twine::Child child.'''
288 if self
.is_twine_kind(kind
, 'EmptyKind') or self
.is_twine_kind(kind
, 'NullKind'):
291 if self
.is_twine_kind(kind
, 'TwineKind'):
292 return self
.string_from_twine_object(child
['twine'].dereference())
294 if self
.is_twine_kind(kind
, 'CStringKind'):
295 return child
['cString'].string()
297 if self
.is_twine_kind(kind
, 'StdStringKind'):
298 val
= child
['stdString'].dereference()
299 return self
.string_from_pretty_printer_lookup(val
)
301 if self
.is_twine_kind(kind
, 'StringRefKind'):
302 val
= child
['stringRef'].dereference()
303 pp
= StringRefPrinter(val
)
304 return pp
.to_string()
306 if self
.is_twine_kind(kind
, 'SmallStringKind'):
307 val
= child
['smallString'].dereference()
308 pp
= SmallStringPrinter(val
)
309 return pp
.to_string()
311 if self
.is_twine_kind(kind
, 'CharKind'):
312 return chr(child
['character'])
314 if self
.is_twine_kind(kind
, 'DecUIKind'):
315 return str(child
['decUI'])
317 if self
.is_twine_kind(kind
, 'DecIKind'):
318 return str(child
['decI'])
320 if self
.is_twine_kind(kind
, 'DecULKind'):
321 return str(child
['decUL'].dereference())
323 if self
.is_twine_kind(kind
, 'DecLKind'):
324 return str(child
['decL'].dereference())
326 if self
.is_twine_kind(kind
, 'DecULLKind'):
327 return str(child
['decULL'].dereference())
329 if self
.is_twine_kind(kind
, 'DecLLKind'):
330 return str(child
['decLL'].dereference())
332 if self
.is_twine_kind(kind
, 'UHexKind'):
333 val
= child
['uHex'].dereference()
336 print(('Unhandled NodeKind {} in Twine pretty-printer. The result will be '
337 'incomplete.').format(kind
))
339 return '(unhandled {})'.format(kind
)
341 def string_from_twine_object(self
, twine
):
342 '''Return the string representation of the Twine object twine.'''
349 lhs_kind
= str(twine
['LHSKind'])
350 rhs_kind
= str(twine
['RHSKind'])
352 lhs_str
= self
.string_from_child(lhs
, lhs_kind
)
353 rhs_str
= self
.string_from_child(rhs
, rhs_kind
)
355 return lhs_str
+ rhs_str
358 return self
.string_from_twine_object(self
._val
)
360 def get_pointer_int_pair(val
):
361 """Get tuple from llvm::PointerIntPair."""
362 info_name
= val
.type.template_argument(4).strip_typedefs().name
363 # Note: this throws a gdb.error if the info type is not used (by means of a
364 # call to getPointer() or similar) in the current translation unit.
365 enum_type
= gdb
.lookup_type(info_name
+ '::MaskAndShiftConstants')
366 enum_dict
= gdb
.types
.make_enum_dict(enum_type
)
367 ptr_mask
= enum_dict
[info_name
+ '::PointerBitMask']
368 int_shift
= enum_dict
[info_name
+ '::IntShift']
369 int_mask
= enum_dict
[info_name
+ '::IntMask']
370 pair_union
= val
['Value']
371 pointer
= (pair_union
& ptr_mask
)
372 value
= ((pair_union
>> int_shift
) & int_mask
)
373 return (pointer
, value
)
375 class PointerIntPairPrinter
:
376 """Print a PointerIntPair."""
378 def __init__(self
, pointer
, value
):
379 self
.pointer
= pointer
383 yield ('pointer', self
.pointer
)
384 yield ('value', self
.value
)
386 def make_pointer_int_pair_printer(val
):
387 """Factory for an llvm::PointerIntPair printer."""
389 pointer
, value
= get_pointer_int_pair(val
)
391 return None # If PointerIntPair cannot be analyzed, print as raw value.
392 pointer_type
= val
.type.template_argument(0)
393 value_type
= val
.type.template_argument(2)
394 return PointerIntPairPrinter(pointer
.cast(pointer_type
),
395 value
.cast(value_type
))
397 class PointerUnionPrinter
:
398 """Print a PointerUnion."""
400 def __init__(self
, pointer
):
401 self
.pointer
= pointer
404 yield ('pointer', self
.pointer
)
407 return "Containing %s" % self
.pointer
.type
409 def make_pointer_union_printer(val
):
410 """Factory for an llvm::PointerUnion printer."""
412 pointer
, value
= get_pointer_int_pair(val
['Val'])
414 return None # If PointerIntPair cannot be analyzed, print as raw value.
415 pointer_type
= val
.type.template_argument(int(value
))
416 return PointerUnionPrinter(pointer
.cast(pointer_type
))
418 class IlistNodePrinter
:
419 """Print an llvm::ilist_node object."""
421 def __init__(self
, val
):
422 impl_type
= val
.type.fields()[0].type
423 base_type
= impl_type
.fields()[0].type
424 derived_type
= val
.type.template_argument(0)
426 def get_prev_and_sentinel(base
):
427 # One of Prev and PrevAndSentinel exists. Depending on #defines used to
428 # compile LLVM, the base_type's template argument is either true of false.
429 if base_type
.template_argument(0):
430 return get_pointer_int_pair(base
['PrevAndSentinel'])
431 return base
['Prev'], None
433 # Casts a base_type pointer to the appropriate derived type.
434 def cast_pointer(pointer
):
435 sentinel
= get_prev_and_sentinel(pointer
.dereference())[1]
436 pointer
= pointer
.cast(impl_type
.pointer())
439 return pointer
.cast(derived_type
.pointer())
441 # Repeated cast becaue val.type's base_type is ambiguous when using tags.
442 base
= val
.cast(impl_type
).cast(base_type
)
443 (prev
, sentinel
) = get_prev_and_sentinel(base
)
444 prev
= prev
.cast(base_type
.pointer())
445 self
.prev
= cast_pointer(prev
)
446 self
.next
= cast_pointer(val
['Next'])
447 self
.sentinel
= sentinel
451 yield 'sentinel', 'yes'
452 yield 'prev', self
.prev
453 yield 'next', self
.next
456 """Print an llvm::simple_ilist or llvm::iplist object."""
458 def __init__(self
, val
):
459 self
.node_type
= val
.type.template_argument(0)
460 sentinel
= val
['Sentinel']
461 # First field is common base type of sentinel and ilist_node.
462 base_type
= sentinel
.type.fields()[0].type
463 self
.sentinel
= sentinel
.address
.cast(base_type
.pointer())
466 pointer
= self
.sentinel
468 pointer
= pointer
['Next'].cast(pointer
.type)
469 if pointer
== self
.sentinel
:
471 yield pointer
.cast(self
.node_type
.pointer())
474 for k
, v
in enumerate(self
._pointers
()):
475 yield ('[%d]' % k
, v
.dereference())
478 pp
= gdb
.printing
.RegexpCollectionPrettyPrinter("LLVMSupport")
479 pp
.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter
)
480 pp
.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter
)
481 pp
.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter
)
482 pp
.add_printer('llvm::ArrayRef', '^llvm::(Mutable)?ArrayRef<.*>$', ArrayRefPrinter
)
483 pp
.add_printer('llvm::Expected', '^llvm::Expected<.*>$', ExpectedPrinter
)
484 pp
.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter
)
485 pp
.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter
)
486 pp
.add_printer('llvm::StringMap', '^llvm::StringMap<.*>$', StringMapPrinter
)
487 pp
.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter
)
488 pp
.add_printer('llvm::PointerIntPair', '^llvm::PointerIntPair<.*>$', make_pointer_int_pair_printer
)
489 pp
.add_printer('llvm::PointerUnion', '^llvm::PointerUnion<.*>$', make_pointer_union_printer
)
490 pp
.add_printer('llvm::ilist_node', '^llvm::ilist_node<.*>$', IlistNodePrinter
)
491 pp
.add_printer('llvm::iplist', '^llvm::iplist<.*>$', IlistPrinter
)
492 pp
.add_printer('llvm::simple_ilist', '^llvm::simple_ilist<.*>$', IlistPrinter
)
493 gdb
.printing
.register_pretty_printer(gdb
.current_objfile(), pp
)