1 from __future__
import print_function
12 if sys
.version_info
.major
== 2:
14 return self
.__next
__()
19 class SmallStringPrinter
:
20 """Print an llvm::SmallString object."""
22 def __init__(self
, val
):
26 data
= self
.val
['BeginX'].cast(gdb
.lookup_type('char').pointer())
27 length
= self
.val
['Size']
28 return data
.lazy_string(length
=length
)
30 def display_hint (self
):
33 class StringRefPrinter
:
34 """Print an llvm::StringRef object."""
36 def __init__(self
, val
):
40 data
= self
.val
['Data']
41 length
= self
.val
['Length']
42 return data
.lazy_string(length
=length
)
44 def display_hint(self
):
47 class SmallVectorPrinter(Iterator
):
48 """Print an llvm::SmallVector object."""
50 def __init__(self
, val
):
52 t
= val
.type.template_argument(0).pointer()
53 self
.begin
= val
['BeginX'].cast(t
)
54 self
.size
= val
['Size']
58 if self
.i
== self
.size
:
60 ret
= '[{}]'.format(self
.i
), (self
.begin
+self
.i
).dereference()
65 return 'llvm::SmallVector of Size {}, Capacity {}'.format(self
.size
, self
.val
['Capacity'])
67 def display_hint (self
):
70 class ArrayRefPrinter
:
71 """Print an llvm::ArrayRef object."""
74 def __init__(self
, begin
, end
):
83 if self
.cur
== self
.end
:
86 self
.count
= self
.count
+ 1
88 self
.cur
= self
.cur
+ 1
89 return '[%d]' % count
, cur
.dereference()
91 if sys
.version_info
.major
== 2:
94 def __init__(self
, val
):
98 data
= self
.val
['Data']
99 return self
._iterator
(data
, data
+ self
.val
['Length'])
102 return 'llvm::ArrayRef of length %d' % (self
.val
['Length'])
104 def display_hint (self
):
107 class ExpectedPrinter(Iterator
):
108 """Print an llvm::Expected object."""
110 def __init__(self
, val
):
119 return ('error', val
['ErrorStorage'].address
.cast(
120 gdb
.lookup_type('llvm::ErrorInfoBase').pointer()).dereference())
121 return ('value', val
['TStorage'].address
.cast(
122 val
.type.template_argument(0).pointer()).dereference())
125 return 'llvm::Expected{}'.format(' is error' if self
.val
['HasError'] else '')
127 class OptionalPrinter(Iterator
):
128 """Print an llvm::Optional object."""
130 def __init__(self
, val
):
138 if not val
['Storage']['hasVal']:
140 return ('value', val
['Storage']['val'])
143 return 'llvm::Optional{}'.format('' if self
.val
['Storage']['hasVal'] else ' is not initialized')
145 class DenseMapPrinter
:
149 def __init__(self
, key_info_t
, begin
, end
):
150 self
.key_info_t
= key_info_t
153 self
.advancePastEmptyBuckets()
159 def advancePastEmptyBuckets(self
):
160 # disabled until the comments below can be addressed
161 # keeping as notes/posterity/hints for future contributors
163 n
= self
.key_info_t
.name
164 is_equal
= gdb
.parse_and_eval(n
+ '::isEqual')
165 empty
= gdb
.parse_and_eval(n
+ '::getEmptyKey()')
166 tombstone
= gdb
.parse_and_eval(n
+ '::getTombstoneKey()')
167 # the following is invalid, GDB fails with:
168 # Python Exception <class 'gdb.error'> Attempt to take address of value
169 # not located in memory.
170 # because isEqual took parameter (for the unsigned long key I was testing)
171 # by const ref, and GDB
172 # It's also not entirely general - we should be accessing the "getFirst()"
173 # member function, not the 'first' member variable, but I've yet to figure
174 # out how to find/call member functions (especially (const) overloaded
175 # ones) on a gdb.Value.
176 while self
.cur
!= self
.end
and (is_equal(self
.cur
.dereference()['first'], empty
) or is_equal(self
.cur
.dereference()['first'], tombstone
)):
177 self
.cur
= self
.cur
+ 1
180 if self
.cur
== self
.end
:
183 v
= cur
.dereference()['first' if self
.first
else 'second']
185 self
.cur
= self
.cur
+ 1
186 self
.advancePastEmptyBuckets()
192 if sys
.version_info
.major
== 2:
195 def __init__(self
, val
):
199 t
= self
.val
.type.template_argument(3).pointer()
200 begin
= self
.val
['Buckets'].cast(t
)
201 end
= (begin
+ self
.val
['NumBuckets']).cast(t
)
202 return self
._iterator
(self
.val
.type.template_argument(2), begin
, end
)
205 return 'llvm::DenseMap with %d elements' % (self
.val
['NumEntries'])
207 def display_hint(self
):
210 class StringMapPrinter
:
213 def __init__(self
, val
):
217 it
= self
.val
['TheTable']
218 end
= (it
+ self
.val
['NumBuckets'])
219 value_ty
= self
.val
.type.template_argument(0)
220 entry_base_ty
= gdb
.lookup_type('llvm::StringMapEntryBase')
221 tombstone
= gdb
.parse_and_eval('llvm::StringMapImpl::TombstoneIntVal');
224 it_deref
= it
.dereference()
225 if it_deref
== 0 or it_deref
== tombstone
:
229 entry_ptr
= it_deref
.cast(entry_base_ty
.pointer())
230 entry
= entry_ptr
.dereference()
232 str_len
= entry
['keyLength']
233 value_ptr
= (entry_ptr
+ 1).cast(value_ty
.pointer())
234 str_data
= (entry_ptr
+ 1).cast(gdb
.lookup_type('uintptr_t')) + max(value_ty
.sizeof
, entry_base_ty
.alignof
)
235 str_data
= str_data
.cast(gdb
.lookup_type('char').const().pointer())
236 string_ref
= gdb
.Value(struct
.pack('PN', int(str_data
), int(str_len
)), gdb
.lookup_type('llvm::StringRef'))
237 yield 'key', string_ref
239 value
= value_ptr
.dereference()
245 return 'llvm::StringMap with %d elements' % (self
.val
['NumItems'])
247 def display_hint(self
):
253 def __init__(self
, val
):
256 def display_hint(self
):
259 def string_from_pretty_printer_lookup(self
, val
):
260 '''Lookup the default pretty-printer for val and use it.
262 If no pretty-printer is defined for the type of val, print an error and
263 return a placeholder string.'''
265 pp
= gdb
.default_visualizer(val
)
269 # The pretty-printer may return a LazyString instead of an actual Python
270 # string. Convert it to a Python string. However, GDB doesn't seem to
271 # register the LazyString type, so we can't check
272 # "type(s) == gdb.LazyString".
273 if 'LazyString' in type(s
).__name
__:
274 s
= s
.value().string()
277 print(('No pretty printer for {} found. The resulting Twine ' +
278 'representation will be incomplete.').format(val
.type.name
))
279 s
= '(missing {})'.format(val
.type.name
)
283 def is_twine_kind(self
, kind
, expected
):
284 if not kind
.endswith(expected
):
286 # apparently some GDB versions add the NodeKind:: namespace
287 # (happens for me on GDB 7.11)
288 return kind
in ('llvm::Twine::' + expected
,
289 'llvm::Twine::NodeKind::' + expected
)
291 def string_from_child(self
, child
, kind
):
292 '''Return the string representation of the Twine::Child child.'''
294 if self
.is_twine_kind(kind
, 'EmptyKind') or self
.is_twine_kind(kind
, 'NullKind'):
297 if self
.is_twine_kind(kind
, 'TwineKind'):
298 return self
.string_from_twine_object(child
['twine'].dereference())
300 if self
.is_twine_kind(kind
, 'CStringKind'):
301 return child
['cString'].string()
303 if self
.is_twine_kind(kind
, 'StdStringKind'):
304 val
= child
['stdString'].dereference()
305 return self
.string_from_pretty_printer_lookup(val
)
307 if self
.is_twine_kind(kind
, 'PtrAndLengthKind'):
308 val
= child
['ptrAndLength']
310 length
= val
['length']
311 return data
.string(length
=length
)
313 if self
.is_twine_kind(kind
, 'CharKind'):
314 return chr(child
['character'])
316 if self
.is_twine_kind(kind
, 'DecUIKind'):
317 return str(child
['decUI'])
319 if self
.is_twine_kind(kind
, 'DecIKind'):
320 return str(child
['decI'])
322 if self
.is_twine_kind(kind
, 'DecULKind'):
323 return str(child
['decUL'].dereference())
325 if self
.is_twine_kind(kind
, 'DecLKind'):
326 return str(child
['decL'].dereference())
328 if self
.is_twine_kind(kind
, 'DecULLKind'):
329 return str(child
['decULL'].dereference())
331 if self
.is_twine_kind(kind
, 'DecLLKind'):
332 return str(child
['decLL'].dereference())
334 if self
.is_twine_kind(kind
, 'UHexKind'):
335 val
= child
['uHex'].dereference()
338 print(('Unhandled NodeKind {} in Twine pretty-printer. The result will be '
339 'incomplete.').format(kind
))
341 return '(unhandled {})'.format(kind
)
343 def string_from_twine_object(self
, twine
):
344 '''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 display_hint(self
):
363 def get_pointer_int_pair(val
):
364 """Get tuple from llvm::PointerIntPair."""
365 info_name
= val
.type.template_argument(4).strip_typedefs().name
366 # Note: this throws a gdb.error if the info type is not used (by means of a
367 # call to getPointer() or similar) in the current translation unit.
368 enum_type
= gdb
.lookup_type(info_name
+ '::MaskAndShiftConstants')
369 enum_dict
= gdb
.types
.make_enum_dict(enum_type
)
370 ptr_mask
= enum_dict
[info_name
+ '::PointerBitMask']
371 int_shift
= enum_dict
[info_name
+ '::IntShift']
372 int_mask
= enum_dict
[info_name
+ '::IntMask']
373 pair_union
= val
['Value']
374 pointer
= (pair_union
& ptr_mask
)
375 value
= ((pair_union
>> int_shift
) & int_mask
)
376 return (pointer
, value
)
378 class PointerIntPairPrinter
:
379 """Print a PointerIntPair."""
381 def __init__(self
, pointer
, value
):
382 self
.pointer
= pointer
386 yield ('pointer', self
.pointer
)
387 yield ('value', self
.value
)
390 return '(%s, %s)' % (self
.pointer
.type, self
.value
.type)
392 def make_pointer_int_pair_printer(val
):
393 """Factory for an llvm::PointerIntPair printer."""
395 pointer
, value
= get_pointer_int_pair(val
)
397 return None # If PointerIntPair cannot be analyzed, print as raw value.
398 pointer_type
= val
.type.template_argument(0)
399 value_type
= val
.type.template_argument(2)
400 return PointerIntPairPrinter(pointer
.cast(pointer_type
),
401 value
.cast(value_type
))
403 class PointerUnionPrinter
:
404 """Print a PointerUnion."""
406 def __init__(self
, pointer
):
407 self
.pointer
= pointer
410 yield ('pointer', self
.pointer
)
413 return "Containing %s" % self
.pointer
.type
415 def make_pointer_union_printer(val
):
416 """Factory for an llvm::PointerUnion printer."""
418 pointer
, value
= get_pointer_int_pair(val
['Val'])
420 return None # If PointerIntPair cannot be analyzed, print as raw value.
421 pointer_type
= val
.type.template_argument(int(value
))
422 return PointerUnionPrinter(pointer
.cast(pointer_type
))
424 class IlistNodePrinter
:
425 """Print an llvm::ilist_node object."""
427 def __init__(self
, val
):
428 impl_type
= val
.type.fields()[0].type
429 base_type
= impl_type
.fields()[0].type
430 derived_type
= val
.type.template_argument(0)
432 def get_prev_and_sentinel(base
):
433 # One of Prev and PrevAndSentinel exists. Depending on #defines used to
434 # compile LLVM, the base_type's template argument is either true of false.
435 if base_type
.template_argument(0):
436 return get_pointer_int_pair(base
['PrevAndSentinel'])
437 return base
['Prev'], None
439 # Casts a base_type pointer to the appropriate derived type.
440 def cast_pointer(pointer
):
441 sentinel
= get_prev_and_sentinel(pointer
.dereference())[1]
442 pointer
= pointer
.cast(impl_type
.pointer())
445 return pointer
.cast(derived_type
.pointer())
447 # Repeated cast becaue val.type's base_type is ambiguous when using tags.
448 base
= val
.cast(impl_type
).cast(base_type
)
449 (prev
, sentinel
) = get_prev_and_sentinel(base
)
450 prev
= prev
.cast(base_type
.pointer())
451 self
.prev
= cast_pointer(prev
)
452 self
.next
= cast_pointer(val
['Next'])
453 self
.sentinel
= sentinel
457 yield 'sentinel', 'yes'
458 yield 'prev', self
.prev
459 yield 'next', self
.next
462 """Print an llvm::simple_ilist or llvm::iplist object."""
464 def __init__(self
, val
):
465 self
.node_type
= val
.type.template_argument(0)
466 sentinel
= val
['Sentinel']
467 # First field is common base type of sentinel and ilist_node.
468 base_type
= sentinel
.type.fields()[0].type
469 self
.sentinel
= sentinel
.address
.cast(base_type
.pointer())
472 pointer
= self
.sentinel
474 pointer
= pointer
['Next'].cast(pointer
.type)
475 if pointer
== self
.sentinel
:
477 yield pointer
.cast(self
.node_type
.pointer())
480 for k
, v
in enumerate(self
._pointers
()):
481 yield ('[%d]' % k
, v
.dereference())
484 pp
= gdb
.printing
.RegexpCollectionPrettyPrinter("LLVMSupport")
485 pp
.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter
)
486 pp
.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter
)
487 pp
.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter
)
488 pp
.add_printer('llvm::ArrayRef', '^llvm::(Mutable)?ArrayRef<.*>$', ArrayRefPrinter
)
489 pp
.add_printer('llvm::Expected', '^llvm::Expected<.*>$', ExpectedPrinter
)
490 pp
.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter
)
491 pp
.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter
)
492 pp
.add_printer('llvm::StringMap', '^llvm::StringMap<.*>$', StringMapPrinter
)
493 pp
.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter
)
494 pp
.add_printer('llvm::PointerIntPair', '^llvm::PointerIntPair<.*>$', make_pointer_int_pair_printer
)
495 pp
.add_printer('llvm::PointerUnion', '^llvm::PointerUnion<.*>$', make_pointer_union_printer
)
496 pp
.add_printer('llvm::ilist_node', '^llvm::ilist_node<.*>$', IlistNodePrinter
)
497 pp
.add_printer('llvm::iplist', '^llvm::iplist<.*>$', IlistPrinter
)
498 pp
.add_printer('llvm::simple_ilist', '^llvm::simple_ilist<.*>$', IlistPrinter
)
499 gdb
.printing
.register_pretty_printer(gdb
.current_objfile(), pp
)