1 from __future__
import print_function
10 if sys
.version_info
.major
== 2:
12 return self
.__next
__()
17 def escape_bytes(val
, l
):
18 return '"' + val
.string(encoding
='Latin-1', length
=l
).encode('unicode_escape').decode() + '"'
20 class SmallStringPrinter
:
21 """Print an llvm::SmallString object."""
23 def __init__(self
, val
):
27 begin
= self
.val
['BeginX']
28 return escape_bytes(begin
.cast(gdb
.lookup_type('char').pointer()), self
.val
['Size'])
30 class StringRefPrinter
:
31 """Print an llvm::StringRef object."""
33 def __init__(self
, val
):
37 return escape_bytes(self
.val
['Data'], self
.val
['Length'])
39 class SmallVectorPrinter(Iterator
):
40 """Print an llvm::SmallVector object."""
42 def __init__(self
, val
):
44 t
= val
.type.template_argument(0).pointer()
45 self
.begin
= val
['BeginX'].cast(t
)
46 self
.size
= val
['Size']
50 if self
.i
== self
.size
:
52 ret
= '[{}]'.format(self
.i
), (self
.begin
+self
.i
).dereference()
57 return 'llvm::SmallVector of Size {}, Capacity {}'.format(self
.size
, self
.val
['Capacity'])
59 def display_hint (self
):
62 class ArrayRefPrinter
:
63 """Print an llvm::ArrayRef object."""
66 def __init__(self
, begin
, end
):
75 if self
.cur
== self
.end
:
78 self
.count
= self
.count
+ 1
80 self
.cur
= self
.cur
+ 1
81 return '[%d]' % count
, cur
.dereference()
83 if sys
.version_info
.major
== 2:
86 def __init__(self
, val
):
90 data
= self
.val
['Data']
91 return self
._iterator
(data
, data
+ self
.val
['Length'])
94 return 'llvm::ArrayRef of length %d' % (self
.val
['Length'])
96 def display_hint (self
):
99 class ExpectedPrinter(Iterator
):
100 """Print an llvm::Expected object."""
102 def __init__(self
, val
):
111 return ('error', val
['ErrorStorage'].address
.cast(
112 gdb
.lookup_type('llvm::ErrorInfoBase').pointer()).dereference())
113 return ('value', val
['TStorage'].address
.cast(
114 val
.type.template_argument(0).pointer()).dereference())
117 return 'llvm::Expected{}'.format(' is error' if self
.val
['HasError'] else '')
119 class OptionalPrinter(Iterator
):
120 """Print an llvm::Optional object."""
122 def __init__(self
, val
):
130 if not val
['Storage']['hasVal']:
132 return ('value', val
['Storage']['storage']['buffer'].address
.cast(
133 val
.type.template_argument(0).pointer()).dereference())
136 return 'llvm::Optional{}'.format('' if self
.val
['Storage']['hasVal'] else ' is not initialized')
138 class DenseMapPrinter
:
142 def __init__(self
, key_info_t
, begin
, end
):
143 self
.key_info_t
= key_info_t
146 self
.advancePastEmptyBuckets()
152 def advancePastEmptyBuckets(self
):
153 # disabled until the comments below can be addressed
154 # keeping as notes/posterity/hints for future contributors
156 n
= self
.key_info_t
.name
157 is_equal
= gdb
.parse_and_eval(n
+ '::isEqual')
158 empty
= gdb
.parse_and_eval(n
+ '::getEmptyKey()')
159 tombstone
= gdb
.parse_and_eval(n
+ '::getTombstoneKey()')
160 # the following is invalid, GDB fails with:
161 # Python Exception <class 'gdb.error'> Attempt to take address of value
162 # not located in memory.
163 # because isEqual took parameter (for the unsigned long key I was testing)
164 # by const ref, and GDB
165 # It's also not entirely general - we should be accessing the "getFirst()"
166 # member function, not the 'first' member variable, but I've yet to figure
167 # out how to find/call member functions (especially (const) overloaded
168 # ones) on a gdb.Value.
169 while self
.cur
!= self
.end
and (is_equal(self
.cur
.dereference()['first'], empty
) or is_equal(self
.cur
.dereference()['first'], tombstone
)):
170 self
.cur
= self
.cur
+ 1
173 if self
.cur
== self
.end
:
176 v
= cur
.dereference()['first' if self
.first
else 'second']
178 self
.cur
= self
.cur
+ 1
179 self
.advancePastEmptyBuckets()
185 if sys
.version_info
.major
== 2:
188 def __init__(self
, val
):
192 t
= self
.val
.type.template_argument(3).pointer()
193 begin
= self
.val
['Buckets'].cast(t
)
194 end
= (begin
+ self
.val
['NumBuckets']).cast(t
)
195 return self
._iterator
(self
.val
.type.template_argument(2), begin
, end
)
198 return 'llvm::DenseMap with %d elements' % (self
.val
['NumEntries'])
200 def display_hint(self
):
206 def __init__(self
, val
):
209 def display_hint(self
):
212 def string_from_pretty_printer_lookup(self
, val
):
213 '''Lookup the default pretty-printer for val and use it.
215 If no pretty-printer is defined for the type of val, print an error and
216 return a placeholder string.'''
218 pp
= gdb
.default_visualizer(val
)
222 # The pretty-printer may return a LazyString instead of an actual Python
223 # string. Convert it to a Python string. However, GDB doesn't seem to
224 # register the LazyString type, so we can't check
225 # "type(s) == gdb.LazyString".
226 if 'LazyString' in type(s
).__name
__:
227 s
= s
.value().address
.string()
230 print(('No pretty printer for {} found. The resulting Twine ' +
231 'representation will be incomplete.').format(val
.type.name
))
232 s
= '(missing {})'.format(val
.type.name
)
236 def is_twine_kind(self
, kind
, expected
):
237 if not kind
.endswith(expected
):
239 # apparently some GDB versions add the NodeKind:: namespace
240 # (happens for me on GDB 7.11)
241 return kind
in ('llvm::Twine::' + expected
,
242 'llvm::Twine::NodeKind::' + expected
)
244 def string_from_child(self
, child
, kind
):
245 '''Return the string representation of the Twine::Child child.'''
247 if self
.is_twine_kind(kind
, 'EmptyKind') or self
.is_twine_kind(kind
, 'NullKind'):
250 if self
.is_twine_kind(kind
, 'TwineKind'):
251 return self
.string_from_twine_object(child
['twine'].dereference())
253 if self
.is_twine_kind(kind
, 'CStringKind'):
254 return child
['cString'].string()
256 if self
.is_twine_kind(kind
, 'StdStringKind'):
257 val
= child
['stdString'].dereference()
258 return self
.string_from_pretty_printer_lookup(val
)
260 if self
.is_twine_kind(kind
, 'StringRefKind'):
261 val
= child
['stringRef'].dereference()
262 pp
= StringRefPrinter(val
)
263 return pp
.to_string()
265 if self
.is_twine_kind(kind
, 'SmallStringKind'):
266 val
= child
['smallString'].dereference()
267 pp
= SmallStringPrinter(val
)
268 return pp
.to_string()
270 if self
.is_twine_kind(kind
, 'CharKind'):
271 return chr(child
['character'])
273 if self
.is_twine_kind(kind
, 'DecUIKind'):
274 return str(child
['decUI'])
276 if self
.is_twine_kind(kind
, 'DecIKind'):
277 return str(child
['decI'])
279 if self
.is_twine_kind(kind
, 'DecULKind'):
280 return str(child
['decUL'].dereference())
282 if self
.is_twine_kind(kind
, 'DecLKind'):
283 return str(child
['decL'].dereference())
285 if self
.is_twine_kind(kind
, 'DecULLKind'):
286 return str(child
['decULL'].dereference())
288 if self
.is_twine_kind(kind
, 'DecLLKind'):
289 return str(child
['decLL'].dereference())
291 if self
.is_twine_kind(kind
, 'UHexKind'):
292 val
= child
['uHex'].dereference()
295 print(('Unhandled NodeKind {} in Twine pretty-printer. The result will be '
296 'incomplete.').format(kind
))
298 return '(unhandled {})'.format(kind
)
300 def string_from_twine_object(self
, twine
):
301 '''Return the string representation of the Twine object twine.'''
308 lhs_kind
= str(twine
['LHSKind'])
309 rhs_kind
= str(twine
['RHSKind'])
311 lhs_str
= self
.string_from_child(lhs
, lhs_kind
)
312 rhs_str
= self
.string_from_child(rhs
, rhs_kind
)
314 return lhs_str
+ rhs_str
317 return self
.string_from_twine_object(self
._val
)
319 pp
= gdb
.printing
.RegexpCollectionPrettyPrinter("LLVMSupport")
320 pp
.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter
)
321 pp
.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter
)
322 pp
.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter
)
323 pp
.add_printer('llvm::ArrayRef', '^llvm::(Const)?ArrayRef<.*>$', ArrayRefPrinter
)
324 pp
.add_printer('llvm::Expected', '^llvm::Expected<.*>$', ExpectedPrinter
)
325 pp
.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter
)
326 pp
.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter
)
327 pp
.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter
)
328 gdb
.printing
.register_pretty_printer(gdb
.current_objfile(), pp
)