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']['value'])
135 return 'llvm::Optional{}'.format('' if self
.val
['Storage']['hasVal'] else ' is not initialized')
137 class DenseMapPrinter
:
141 def __init__(self
, key_info_t
, begin
, end
):
142 self
.key_info_t
= key_info_t
145 self
.advancePastEmptyBuckets()
151 def advancePastEmptyBuckets(self
):
152 # disabled until the comments below can be addressed
153 # keeping as notes/posterity/hints for future contributors
155 n
= self
.key_info_t
.name
156 is_equal
= gdb
.parse_and_eval(n
+ '::isEqual')
157 empty
= gdb
.parse_and_eval(n
+ '::getEmptyKey()')
158 tombstone
= gdb
.parse_and_eval(n
+ '::getTombstoneKey()')
159 # the following is invalid, GDB fails with:
160 # Python Exception <class 'gdb.error'> Attempt to take address of value
161 # not located in memory.
162 # because isEqual took parameter (for the unsigned long key I was testing)
163 # by const ref, and GDB
164 # It's also not entirely general - we should be accessing the "getFirst()"
165 # member function, not the 'first' member variable, but I've yet to figure
166 # out how to find/call member functions (especially (const) overloaded
167 # ones) on a gdb.Value.
168 while self
.cur
!= self
.end
and (is_equal(self
.cur
.dereference()['first'], empty
) or is_equal(self
.cur
.dereference()['first'], tombstone
)):
169 self
.cur
= self
.cur
+ 1
172 if self
.cur
== self
.end
:
175 v
= cur
.dereference()['first' if self
.first
else 'second']
177 self
.cur
= self
.cur
+ 1
178 self
.advancePastEmptyBuckets()
184 if sys
.version_info
.major
== 2:
187 def __init__(self
, val
):
191 t
= self
.val
.type.template_argument(3).pointer()
192 begin
= self
.val
['Buckets'].cast(t
)
193 end
= (begin
+ self
.val
['NumBuckets']).cast(t
)
194 return self
._iterator
(self
.val
.type.template_argument(2), begin
, end
)
197 return 'llvm::DenseMap with %d elements' % (self
.val
['NumEntries'])
199 def display_hint(self
):
205 def __init__(self
, val
):
208 def display_hint(self
):
211 def string_from_pretty_printer_lookup(self
, val
):
212 '''Lookup the default pretty-printer for val and use it.
214 If no pretty-printer is defined for the type of val, print an error and
215 return a placeholder string.'''
217 pp
= gdb
.default_visualizer(val
)
221 # The pretty-printer may return a LazyString instead of an actual Python
222 # string. Convert it to a Python string. However, GDB doesn't seem to
223 # register the LazyString type, so we can't check
224 # "type(s) == gdb.LazyString".
225 if 'LazyString' in type(s
).__name
__:
226 s
= s
.value().address
.string()
229 print(('No pretty printer for {} found. The resulting Twine ' +
230 'representation will be incomplete.').format(val
.type.name
))
231 s
= '(missing {})'.format(val
.type.name
)
235 def is_twine_kind(self
, kind
, expected
):
236 if not kind
.endswith(expected
):
238 # apparently some GDB versions add the NodeKind:: namespace
239 # (happens for me on GDB 7.11)
240 return kind
in ('llvm::Twine::' + expected
,
241 'llvm::Twine::NodeKind::' + expected
)
243 def string_from_child(self
, child
, kind
):
244 '''Return the string representation of the Twine::Child child.'''
246 if self
.is_twine_kind(kind
, 'EmptyKind') or self
.is_twine_kind(kind
, 'NullKind'):
249 if self
.is_twine_kind(kind
, 'TwineKind'):
250 return self
.string_from_twine_object(child
['twine'].dereference())
252 if self
.is_twine_kind(kind
, 'CStringKind'):
253 return child
['cString'].string()
255 if self
.is_twine_kind(kind
, 'StdStringKind'):
256 val
= child
['stdString'].dereference()
257 return self
.string_from_pretty_printer_lookup(val
)
259 if self
.is_twine_kind(kind
, 'StringRefKind'):
260 val
= child
['stringRef'].dereference()
261 pp
= StringRefPrinter(val
)
262 return pp
.to_string()
264 if self
.is_twine_kind(kind
, 'SmallStringKind'):
265 val
= child
['smallString'].dereference()
266 pp
= SmallStringPrinter(val
)
267 return pp
.to_string()
269 if self
.is_twine_kind(kind
, 'CharKind'):
270 return chr(child
['character'])
272 if self
.is_twine_kind(kind
, 'DecUIKind'):
273 return str(child
['decUI'])
275 if self
.is_twine_kind(kind
, 'DecIKind'):
276 return str(child
['decI'])
278 if self
.is_twine_kind(kind
, 'DecULKind'):
279 return str(child
['decUL'].dereference())
281 if self
.is_twine_kind(kind
, 'DecLKind'):
282 return str(child
['decL'].dereference())
284 if self
.is_twine_kind(kind
, 'DecULLKind'):
285 return str(child
['decULL'].dereference())
287 if self
.is_twine_kind(kind
, 'DecLLKind'):
288 return str(child
['decLL'].dereference())
290 if self
.is_twine_kind(kind
, 'UHexKind'):
291 val
= child
['uHex'].dereference()
294 print(('Unhandled NodeKind {} in Twine pretty-printer. The result will be '
295 'incomplete.').format(kind
))
297 return '(unhandled {})'.format(kind
)
299 def string_from_twine_object(self
, twine
):
300 '''Return the string representation of the Twine object twine.'''
307 lhs_kind
= str(twine
['LHSKind'])
308 rhs_kind
= str(twine
['RHSKind'])
310 lhs_str
= self
.string_from_child(lhs
, lhs_kind
)
311 rhs_str
= self
.string_from_child(rhs
, rhs_kind
)
313 return lhs_str
+ rhs_str
316 return self
.string_from_twine_object(self
._val
)
318 pp
= gdb
.printing
.RegexpCollectionPrettyPrinter("LLVMSupport")
319 pp
.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter
)
320 pp
.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter
)
321 pp
.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter
)
322 pp
.add_printer('llvm::ArrayRef', '^llvm::(Const)?ArrayRef<.*>$', ArrayRefPrinter
)
323 pp
.add_printer('llvm::Expected', '^llvm::Expected<.*>$', ExpectedPrinter
)
324 pp
.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter
)
325 pp
.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter
)
326 pp
.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter
)
327 gdb
.printing
.register_pretty_printer(gdb
.current_objfile(), pp
)