[RISCV] Refactor predicates for rvv intrinsic patterns.
[llvm-project.git] / llvm / utils / gdb-scripts / prettyprinters.py
blob1fdf4fe781c742e6fe7895911150ca83825c5f48
1 from __future__ import print_function
2 import struct
3 import sys
5 import gdb.printing
6 import gdb.types
8 class Iterator:
9 def __iter__(self):
10 return self
12 if sys.version_info.major == 2:
13 def next(self):
14 return self.__next__()
16 def children(self):
17 return self
19 class SmallStringPrinter:
20 """Print an llvm::SmallString object."""
22 def __init__(self, val):
23 self.val = val
25 def to_string(self):
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):
31 return 'string'
33 class StringRefPrinter:
34 """Print an llvm::StringRef object."""
36 def __init__(self, val):
37 self.val = val
39 def to_string(self):
40 data = self.val['Data']
41 length = self.val['Length']
42 return data.lazy_string(length=length)
44 def display_hint(self):
45 return 'string'
47 class SmallVectorPrinter(Iterator):
48 """Print an llvm::SmallVector object."""
50 def __init__(self, val):
51 self.val = val
52 t = val.type.template_argument(0).pointer()
53 self.begin = val['BeginX'].cast(t)
54 self.size = val['Size']
55 self.i = 0
57 def __next__(self):
58 if self.i == self.size:
59 raise StopIteration
60 ret = '[{}]'.format(self.i), (self.begin+self.i).dereference()
61 self.i += 1
62 return ret
64 def to_string(self):
65 return 'llvm::SmallVector of Size {}, Capacity {}'.format(self.size, self.val['Capacity'])
67 def display_hint (self):
68 return 'array'
70 class ArrayRefPrinter:
71 """Print an llvm::ArrayRef object."""
73 class _iterator:
74 def __init__(self, begin, end):
75 self.cur = begin
76 self.end = end
77 self.count = 0
79 def __iter__(self):
80 return self
82 def __next__(self):
83 if self.cur == self.end:
84 raise StopIteration
85 count = self.count
86 self.count = self.count + 1
87 cur = self.cur
88 self.cur = self.cur + 1
89 return '[%d]' % count, cur.dereference()
91 if sys.version_info.major == 2:
92 next = __next__
94 def __init__(self, val):
95 self.val = val
97 def children(self):
98 data = self.val['Data']
99 return self._iterator(data, data + self.val['Length'])
101 def to_string(self):
102 return 'llvm::ArrayRef of length %d' % (self.val['Length'])
104 def display_hint (self):
105 return 'array'
107 class ExpectedPrinter(Iterator):
108 """Print an llvm::Expected object."""
110 def __init__(self, val):
111 self.val = val
113 def __next__(self):
114 val = self.val
115 if val is None:
116 raise StopIteration
117 self.val = None
118 if val['HasError']:
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())
124 def to_string(self):
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):
131 self.val = val
133 def __next__(self):
134 val = self.val
135 if val is None:
136 raise StopIteration
137 self.val = None
138 if not val['Storage']['hasVal']:
139 raise StopIteration
140 return ('value', val['Storage']['val'])
142 def to_string(self):
143 return 'llvm::Optional{}'.format('' if self.val['Storage']['hasVal'] else ' is not initialized')
145 class DenseMapPrinter:
146 "Print a DenseMap"
148 class _iterator:
149 def __init__(self, key_info_t, begin, end):
150 self.key_info_t = key_info_t
151 self.cur = begin
152 self.end = end
153 self.advancePastEmptyBuckets()
154 self.first = True
156 def __iter__(self):
157 return self
159 def advancePastEmptyBuckets(self):
160 # disabled until the comments below can be addressed
161 # keeping as notes/posterity/hints for future contributors
162 return
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
179 def __next__(self):
180 if self.cur == self.end:
181 raise StopIteration
182 cur = self.cur
183 v = cur.dereference()['first' if self.first else 'second']
184 if not self.first:
185 self.cur = self.cur + 1
186 self.advancePastEmptyBuckets()
187 self.first = True
188 else:
189 self.first = False
190 return 'x', v
192 if sys.version_info.major == 2:
193 next = __next__
195 def __init__(self, val):
196 self.val = val
198 def children(self):
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)
204 def to_string(self):
205 return 'llvm::DenseMap with %d elements' % (self.val['NumEntries'])
207 def display_hint(self):
208 return 'map'
210 class StringMapPrinter:
211 "Print a StringMap"
213 def __init__(self, val):
214 self.val = val
216 def children(self):
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');
223 while it != end:
224 it_deref = it.dereference()
225 if it_deref == 0 or it_deref == tombstone:
226 it = it + 1
227 continue
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()
240 yield 'value', value
242 it = it + 1
244 def to_string(self):
245 return 'llvm::StringMap with %d elements' % (self.val['NumItems'])
247 def display_hint(self):
248 return 'map'
250 class TwinePrinter:
251 "Print a Twine"
253 def __init__(self, val):
254 self._val = val
256 def display_hint(self):
257 return 'string'
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)
266 if pp:
267 s = pp.to_string()
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()
276 else:
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)
281 return s
283 def is_twine_kind(self, kind, expected):
284 if not kind.endswith(expected):
285 return False
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'):
295 return ''
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']
309 data = val['ptr']
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()
336 return hex(int(val))
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.'''
346 lhs = twine['LHS']
347 rhs = twine['RHS']
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
357 def to_string(self):
358 return self.string_from_twine_object(self._val)
360 def display_hint(self):
361 return 'string'
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
383 self.value = value
385 def children(self):
386 yield ('pointer', self.pointer)
387 yield ('value', self.value)
389 def to_string(self):
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."""
394 try:
395 pointer, value = get_pointer_int_pair(val)
396 except gdb.error:
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
409 def children(self):
410 yield ('pointer', self.pointer)
412 def to_string(self):
413 return "Containing %s" % self.pointer.type
415 def make_pointer_union_printer(val):
416 """Factory for an llvm::PointerUnion printer."""
417 try:
418 pointer, value = get_pointer_int_pair(val['Val'])
419 except gdb.error:
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())
443 if sentinel:
444 return 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
455 def children(self):
456 if self.sentinel:
457 yield 'sentinel', 'yes'
458 yield 'prev', self.prev
459 yield 'next', self.next
461 class IlistPrinter:
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())
471 def _pointers(self):
472 pointer = self.sentinel
473 while True:
474 pointer = pointer['Next'].cast(pointer.type)
475 if pointer == self.sentinel:
476 return
477 yield pointer.cast(self.node_type.pointer())
479 def children(self):
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)