prettyprinters.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. import gdb.printing
  2. class SmallStringPrinter:
  3. """Print an llvm::SmallString object."""
  4. def __init__(self, val):
  5. self.val = val
  6. def to_string(self):
  7. begin = self.val['BeginX']
  8. end = self.val['EndX']
  9. return begin.cast(gdb.lookup_type("char").pointer()).string(length = end - begin)
  10. def display_hint (self):
  11. return 'string'
  12. class StringRefPrinter:
  13. """Print an llvm::StringRef object."""
  14. def __init__(self, val):
  15. self.val = val
  16. def to_string(self):
  17. return self.val['Data'].string(length = self.val['Length'])
  18. def display_hint (self):
  19. return 'string'
  20. class SmallVectorPrinter:
  21. """Print an llvm::SmallVector object."""
  22. class _iterator:
  23. def __init__(self, begin, end):
  24. self.cur = begin
  25. self.end = end
  26. self.count = 0
  27. def __iter__(self):
  28. return self
  29. def next(self):
  30. if self.cur == self.end:
  31. raise StopIteration
  32. count = self.count
  33. self.count = self.count + 1
  34. cur = self.cur
  35. self.cur = self.cur + 1
  36. return '[%d]' % count, cur.dereference()
  37. __next__ = next
  38. def __init__(self, val):
  39. self.val = val
  40. def children(self):
  41. t = self.val.type.template_argument(0).pointer()
  42. begin = self.val['BeginX'].cast(t)
  43. end = self.val['EndX'].cast(t)
  44. return self._iterator(begin, end)
  45. def to_string(self):
  46. t = self.val.type.template_argument(0).pointer()
  47. begin = self.val['BeginX'].cast(t)
  48. end = self.val['EndX'].cast(t)
  49. capacity = self.val['CapacityX'].cast(t)
  50. return 'llvm::SmallVector of length %d, capacity %d' % (end - begin, capacity - begin)
  51. def display_hint (self):
  52. return 'array'
  53. class ArrayRefPrinter:
  54. """Print an llvm::ArrayRef object."""
  55. class _iterator:
  56. def __init__(self, begin, end):
  57. self.cur = begin
  58. self.end = end
  59. self.count = 0
  60. def __iter__(self):
  61. return self
  62. def next(self):
  63. if self.cur == self.end:
  64. raise StopIteration
  65. count = self.count
  66. self.count = self.count + 1
  67. cur = self.cur
  68. self.cur = self.cur + 1
  69. return '[%d]' % count, cur.dereference()
  70. __next__ = next
  71. def __init__(self, val):
  72. self.val = val
  73. def children(self):
  74. data = self.val['Data']
  75. return self._iterator(data, data + self.val['Length'])
  76. def to_string(self):
  77. return 'llvm::ArrayRef of length %d' % (self.val['Length'])
  78. def display_hint (self):
  79. return 'array'
  80. class OptionalPrinter:
  81. """Print an llvm::Optional object."""
  82. def __init__(self, value):
  83. self.value = value
  84. class _iterator:
  85. def __init__(self, member, empty):
  86. self.member = member
  87. self.done = empty
  88. def __iter__(self):
  89. return self
  90. def next(self):
  91. if self.done:
  92. raise StopIteration
  93. self.done = True
  94. return ('value', self.member.dereference())
  95. def children(self):
  96. if not self.value['hasVal']:
  97. return self._iterator('', True)
  98. return self._iterator(self.value['storage']['buffer'].address.cast(self.value.type.template_argument(0).pointer()), False)
  99. def to_string(self):
  100. return 'llvm::Optional is %sinitialized' % ('' if self.value['hasVal'] else 'not ')
  101. class DenseMapPrinter:
  102. "Print a DenseMap"
  103. class _iterator:
  104. def __init__(self, key_info_t, begin, end):
  105. self.key_info_t = key_info_t
  106. self.cur = begin
  107. self.end = end
  108. self.advancePastEmptyBuckets()
  109. self.first = True
  110. def __iter__(self):
  111. return self
  112. def advancePastEmptyBuckets(self):
  113. # disabled until the comments below can be addressed
  114. # keeping as notes/posterity/hints for future contributors
  115. return
  116. n = self.key_info_t.name
  117. is_equal = gdb.parse_and_eval(n + '::isEqual')
  118. empty = gdb.parse_and_eval(n + '::getEmptyKey()')
  119. tombstone = gdb.parse_and_eval(n + '::getTombstoneKey()')
  120. # the following is invalid, GDB fails with:
  121. # Python Exception <class 'gdb.error'> Attempt to take address of value
  122. # not located in memory.
  123. # because isEqual took parameter (for the unsigned long key I was testing)
  124. # by const ref, and GDB
  125. # It's also not entirely general - we should be accessing the "getFirst()"
  126. # member function, not the 'first' member variable, but I've yet to figure
  127. # out how to find/call member functions (especially (const) overloaded
  128. # ones) on a gdb.Value.
  129. while self.cur != self.end and (is_equal(self.cur.dereference()['first'], empty) or is_equal(self.cur.dereference()['first'], tombstone)):
  130. self.cur = self.cur + 1
  131. def next(self):
  132. if self.cur == self.end:
  133. raise StopIteration
  134. cur = self.cur
  135. v = cur.dereference()['first' if self.first else 'second']
  136. if not self.first:
  137. self.cur = self.cur + 1
  138. self.advancePastEmptyBuckets()
  139. self.first = True
  140. else:
  141. self.first = False
  142. return 'x', v
  143. def __init__(self, val):
  144. self.val = val
  145. def children(self):
  146. t = self.val.type.template_argument(3).pointer()
  147. begin = self.val['Buckets'].cast(t)
  148. end = (begin + self.val['NumBuckets']).cast(t)
  149. return self._iterator(self.val.type.template_argument(2), begin, end)
  150. def to_string(self):
  151. return 'llvm::DenseMap with %d elements' % (self.val['NumEntries'])
  152. def display_hint(self):
  153. return 'map'
  154. class TwinePrinter:
  155. "Print a Twine"
  156. def __init__(self, val):
  157. self._val = val
  158. def display_hint(self):
  159. return 'string'
  160. def string_from_pretty_printer_lookup(self, val):
  161. '''Lookup the default pretty-printer for val and use it.
  162. If no pretty-printer is defined for the type of val, print an error and
  163. return a placeholder string.'''
  164. pp = gdb.default_visualizer(val)
  165. if pp:
  166. s = pp.to_string()
  167. # The pretty-printer may return a LazyString instead of an actual Python
  168. # string. Convert it to a Python string. However, GDB doesn't seem to
  169. # register the LazyString type, so we can't check
  170. # "type(s) == gdb.LazyString".
  171. if 'LazyString' in type(s).__name__:
  172. s = s.value().address.string()
  173. else:
  174. print(('No pretty printer for {} found. The resulting Twine ' +
  175. 'representation will be incomplete.').format(val.type.name))
  176. s = '(missing {})'.format(val.type.name)
  177. return s
  178. def string_from_child(self, child, kind):
  179. '''Return the string representation of the Twine::Child child.'''
  180. if kind in ('llvm::Twine::EmptyKind', 'llvm::Twine::NullKind'):
  181. return ''
  182. if kind == 'llvm::Twine::TwineKind':
  183. return self.string_from_twine_object(child['twine'].dereference())
  184. if kind == 'llvm::Twine::CStringKind':
  185. return child['cString'].string()
  186. if kind == 'llvm::Twine::StdStringKind':
  187. val = child['stdString'].dereference()
  188. return self.string_from_pretty_printer_lookup(val)
  189. if kind == 'llvm::Twine::StringRefKind':
  190. val = child['stringRef'].dereference()
  191. pp = StringRefPrinter(val)
  192. return pp.to_string()
  193. if kind == 'llvm::Twine::SmallStringKind':
  194. val = child['smallString'].dereference()
  195. pp = SmallStringPrinter(val)
  196. return pp.to_string()
  197. if kind == 'llvm::Twine::CharKind':
  198. return chr(child['character'])
  199. if kind == 'llvm::Twine::DecUIKind':
  200. return str(child['decUI'])
  201. if kind == 'llvm::Twine::DecIKind':
  202. return str(child['decI'])
  203. if kind == 'llvm::Twine::DecULKind':
  204. return str(child['decUL'].dereference())
  205. if kind == 'llvm::Twine::DecLKind':
  206. return str(child['decL'].dereference())
  207. if kind == 'llvm::Twine::DecULLKind':
  208. return str(child['decULL'].dereference())
  209. if kind == 'llvm::Twine::DecLLKind':
  210. return str(child['decLL'].dereference())
  211. if kind == 'llvm::Twine::UHexKind':
  212. val = child['uHex'].dereference()
  213. return hex(int(val))
  214. print(('Unhandled NodeKind {} in Twine pretty-printer. The result will be '
  215. 'incomplete.').format(kind))
  216. return '(unhandled {})'.format(kind)
  217. def string_from_twine_object(self, twine):
  218. '''Return the string representation of the Twine object twine.'''
  219. lhs_str = ''
  220. rhs_str = ''
  221. lhs = twine['LHS']
  222. rhs = twine['RHS']
  223. lhs_kind = str(twine['LHSKind'])
  224. rhs_kind = str(twine['RHSKind'])
  225. lhs_str = self.string_from_child(lhs, lhs_kind)
  226. rhs_str = self.string_from_child(rhs, rhs_kind)
  227. return lhs_str + rhs_str
  228. def to_string(self):
  229. return self.string_from_twine_object(self._val)
  230. pp = gdb.printing.RegexpCollectionPrettyPrinter("LLVMSupport")
  231. pp.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter)
  232. pp.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter)
  233. pp.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter)
  234. pp.add_printer('llvm::ArrayRef', '^llvm::(Const)?ArrayRef<.*>$', ArrayRefPrinter)
  235. pp.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter)
  236. pp.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter)
  237. pp.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter)
  238. gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)