7 # Python 2 compatibility
14 def escape_bytes(val
, l
):
15 return '"' + val
.string(encoding
='Latin-1', length
=l
).encode('unicode_escape').decode() + '"'
17 class SmallStringPrinter
:
18 """Print an llvm::SmallString object."""
20 def __init__(self
, val
):
24 begin
= self
.val
['BeginX']
25 return escape_bytes(begin
.cast(gdb
.lookup_type('char').pointer()), self
.val
['Size'])
27 class StringRefPrinter
:
28 """Print an llvm::StringRef object."""
30 def __init__(self
, val
):
34 return escape_bytes(self
.val
['Data'], self
.val
['Length'])
36 class SmallVectorPrinter(Iterator
):
37 """Print an llvm::SmallVector object."""
39 def __init__(self
, val
):
41 t
= val
.type.template_argument(0).pointer()
42 self
.begin
= val
['BeginX'].cast(t
)
43 self
.size
= val
['Size']
47 if self
.i
== self
.size
:
49 ret
= '[{}]'.format(self
.i
), (self
.begin
+self
.i
).dereference()
54 return 'llvm::SmallVector of Size {}, Capacity {}'.format(self
.size
, self
.val
['Capacity'])
56 def display_hint (self
):
59 class ArrayRefPrinter
:
60 """Print an llvm::ArrayRef object."""
63 def __init__(self
, begin
, end
):
72 if self
.cur
== self
.end
:
75 self
.count
= self
.count
+ 1
77 self
.cur
= self
.cur
+ 1
78 return '[%d]' % count
, cur
.dereference()
82 def __init__(self
, val
):
88 data
= self
.val
['Data']
89 return self
._iterator
(data
, data
+ self
.val
['Length'])
92 return 'llvm::ArrayRef of length %d' % (self
.val
['Length'])
94 def display_hint (self
):
97 class ExpectedPrinter(Iterator
):
98 """Print an llvm::Expected object."""
100 def __init__(self
, val
):
109 return ('error', val
['ErrorStorage'].address
.cast(
110 gdb
.lookup_type('llvm::ErrorInfoBase').pointer()).dereference())
111 return ('value', val
['TStorage'].address
.cast(
112 val
.type.template_argument(0).pointer()).dereference())
115 return 'llvm::Expected{}'.format(' is error' if self
.val
['HasError'] else '')
117 class OptionalPrinter(Iterator
):
118 """Print an llvm::Optional object."""
120 def __init__(self
, val
):
128 if not val
['Storage']['hasVal']:
130 return ('value', val
['Storage']['storage']['buffer'].address
.cast(
131 val
.type.template_argument(0).pointer()).dereference())
134 return 'llvm::Optional{}'.format('' if self
.val
['Storage']['hasVal'] else ' is not initialized')
136 class DenseMapPrinter
:
140 def __init__(self
, key_info_t
, begin
, end
):
141 self
.key_info_t
= key_info_t
144 self
.advancePastEmptyBuckets()
150 def advancePastEmptyBuckets(self
):
151 # disabled until the comments below can be addressed
152 # keeping as notes/posterity/hints for future contributors
154 n
= self
.key_info_t
.name
155 is_equal
= gdb
.parse_and_eval(n
+ '::isEqual')
156 empty
= gdb
.parse_and_eval(n
+ '::getEmptyKey()')
157 tombstone
= gdb
.parse_and_eval(n
+ '::getTombstoneKey()')
158 # the following is invalid, GDB fails with:
159 # Python Exception <class 'gdb.error'> Attempt to take address of value
160 # not located in memory.
161 # because isEqual took parameter (for the unsigned long key I was testing)
162 # by const ref, and GDB
163 # It's also not entirely general - we should be accessing the "getFirst()"
164 # member function, not the 'first' member variable, but I've yet to figure
165 # out how to find/call member functions (especially (const) overloaded
166 # ones) on a gdb.Value.
167 while self
.cur
!= self
.end
and (is_equal(self
.cur
.dereference()['first'], empty
) or is_equal(self
.cur
.dereference()['first'], tombstone
)):
168 self
.cur
= self
.cur
+ 1
171 if self
.cur
== self
.end
:
174 v
= cur
.dereference()['first' if self
.first
else 'second']
176 self
.cur
= self
.cur
+ 1
177 self
.advancePastEmptyBuckets()
185 def __init__(self
, val
):
189 t
= self
.val
.type.template_argument(3).pointer()
190 begin
= self
.val
['Buckets'].cast(t
)
191 end
= (begin
+ self
.val
['NumBuckets']).cast(t
)
192 return self
._iterator
(self
.val
.type.template_argument(2), begin
, end
)
195 return 'llvm::DenseMap with %d elements' % (self
.val
['NumEntries'])
197 def display_hint(self
):
203 def __init__(self
, val
):
206 def display_hint(self
):
209 def string_from_pretty_printer_lookup(self
, val
):
210 '''Lookup the default pretty-printer for val and use it.
212 If no pretty-printer is defined for the type of val, print an error and
213 return a placeholder string.'''
215 pp
= gdb
.default_visualizer(val
)
219 # The pretty-printer may return a LazyString instead of an actual Python
220 # string. Convert it to a Python string. However, GDB doesn't seem to
221 # register the LazyString type, so we can't check
222 # "type(s) == gdb.LazyString".
223 if 'LazyString' in type(s
).__name
__:
224 s
= s
.value().address
.string()
227 print(('No pretty printer for {} found. The resulting Twine ' +
228 'representation will be incomplete.').format(val
.type.name
))
229 s
= '(missing {})'.format(val
.type.name
)
233 def is_twine_kind(self
, kind
, expected
):
234 if not kind
.endswith(expected
):
236 # apparently some GDB versions add the NodeKind:: namespace
237 # (happens for me on GDB 7.11)
238 return kind
in ('llvm::Twine::' + expected
,
239 'llvm::Twine::NodeKind::' + expected
)
241 def string_from_child(self
, child
, kind
):
242 '''Return the string representation of the Twine::Child child.'''
244 if self
.is_twine_kind(kind
, 'EmptyKind') or self
.is_twine_kind(kind
, 'NullKind'):
247 if self
.is_twine_kind(kind
, 'TwineKind'):
248 return self
.string_from_twine_object(child
['twine'].dereference())
250 if self
.is_twine_kind(kind
, 'CStringKind'):
251 return child
['cString'].string()
253 if self
.is_twine_kind(kind
, 'StdStringKind'):
254 val
= child
['stdString'].dereference()
255 return self
.string_from_pretty_printer_lookup(val
)
257 if self
.is_twine_kind(kind
, 'StringRefKind'):
258 val
= child
['stringRef'].dereference()
259 pp
= StringRefPrinter(val
)
260 return pp
.to_string()
262 if self
.is_twine_kind(kind
, 'SmallStringKind'):
263 val
= child
['smallString'].dereference()
264 pp
= SmallStringPrinter(val
)
265 return pp
.to_string()
267 if self
.is_twine_kind(kind
, 'CharKind'):
268 return chr(child
['character'])
270 if self
.is_twine_kind(kind
, 'DecUIKind'):
271 return str(child
['decUI'])
273 if self
.is_twine_kind(kind
, 'DecIKind'):
274 return str(child
['decI'])
276 if self
.is_twine_kind(kind
, 'DecULKind'):
277 return str(child
['decUL'].dereference())
279 if self
.is_twine_kind(kind
, 'DecLKind'):
280 return str(child
['decL'].dereference())
282 if self
.is_twine_kind(kind
, 'DecULLKind'):
283 return str(child
['decULL'].dereference())
285 if self
.is_twine_kind(kind
, 'DecLLKind'):
286 return str(child
['decLL'].dereference())
288 if self
.is_twine_kind(kind
, 'UHexKind'):
289 val
= child
['uHex'].dereference()
292 print(('Unhandled NodeKind {} in Twine pretty-printer. The result will be '
293 'incomplete.').format(kind
))
295 return '(unhandled {})'.format(kind
)
297 def string_from_twine_object(self
, twine
):
298 '''Return the string representation of the Twine object twine.'''
305 lhs_kind
= str(twine
['LHSKind'])
306 rhs_kind
= str(twine
['RHSKind'])
308 lhs_str
= self
.string_from_child(lhs
, lhs_kind
)
309 rhs_str
= self
.string_from_child(rhs
, rhs_kind
)
311 return lhs_str
+ rhs_str
314 return self
.string_from_twine_object(self
._val
)
316 pp
= gdb
.printing
.RegexpCollectionPrettyPrinter("LLVMSupport")
317 pp
.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter
)
318 pp
.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter
)
319 pp
.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter
)
320 pp
.add_printer('llvm::ArrayRef', '^llvm::(Const)?ArrayRef<.*>$', ArrayRefPrinter
)
321 pp
.add_printer('llvm::Expected', '^llvm::Expected<.*>$', ExpectedPrinter
)
322 pp
.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter
)
323 pp
.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter
)
324 pp
.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter
)
325 gdb
.printing
.register_pretty_printer(gdb
.current_objfile(), pp
)