Skip to content

Commit 23cbb11

Browse files
committed
GDB pretty printers: Basic DenseMap support
Still prints the empty/tombstone keys (which some people would prefer, but I find pretty noisy) because I haven't yet found a reliable way to skip them (it requires calling into the running process to do so, which isn't ideal for a pretty printer (doesn't work on a core file, for example) - and gdb's ability to do so (or my ability to figure out how to get gdb to do so) is limited) left some breadcrumbs for the next person who might try to address that. llvm-svn: 290011
1 parent a0aec9b commit 23cbb11

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

llvm/utils/gdb-scripts/prettyprinters.py

+64
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,74 @@ def children(self):
131131
def to_string(self):
132132
return 'llvm::Optional is %sinitialized' % ('' if self.value['hasVal'] else 'not ')
133133

134+
class DenseMapPrinter:
135+
"Print a DenseMap"
136+
137+
class _iterator:
138+
def __init__(self, key_info_t, begin, end):
139+
self.key_info_t = key_info_t
140+
self.cur = begin
141+
self.end = end
142+
self.advancePastEmptyBuckets()
143+
self.first = True
144+
145+
def __iter__(self):
146+
return self
147+
148+
def advancePastEmptyBuckets(self):
149+
# disabled until the comments below can be addressed
150+
# keeping as notes/posterity/hints for future contributors
151+
return
152+
n = self.key_info_t.name
153+
is_equal = gdb.parse_and_eval(n + '::isEqual')
154+
empty = gdb.parse_and_eval(n + '::getEmptyKey()')
155+
tombstone = gdb.parse_and_eval(n + '::getTombstoneKey()')
156+
# the following is invalid, GDB fails with:
157+
# Python Exception <class 'gdb.error'> Attempt to take address of value
158+
# not located in memory.
159+
# because isEqual took parameter (for the unsigned long key I was testing)
160+
# by const ref, and GDB
161+
# It's also not entirely general - we should be accessing the "getFirst()"
162+
# member function, not the 'first' member variable, but I've yet to figure
163+
# out how to find/call member functions (especially (const) overloaded
164+
# ones) on a gdb.Value.
165+
while self.cur != self.end and (is_equal(self.cur.dereference()['first'], empty) or is_equal(self.cur.dereference()['first'], tombstone)):
166+
self.cur = self.cur + 1
167+
168+
def next(self):
169+
if self.cur == self.end:
170+
raise StopIteration
171+
cur = self.cur
172+
v = cur.dereference()['first' if self.first else 'second']
173+
if not self.first:
174+
self.cur = self.cur + 1
175+
self.advancePastEmptyBuckets()
176+
self.first = True
177+
else:
178+
self.first = False
179+
return 'x', v
180+
181+
def __init__(self, val):
182+
self.val = val
183+
184+
def children(self):
185+
t = self.val.type.template_argument(3).pointer()
186+
begin = self.val['Buckets'].cast(t)
187+
end = (begin + self.val['NumBuckets']).cast(t)
188+
return self._iterator(self.val.type.template_argument(2), begin, end)
189+
190+
def to_string(self):
191+
return 'llvm::DenseMap with %d elements' % (self.val['NumEntries'])
192+
193+
def display_hint(self):
194+
return 'map'
195+
196+
134197
pp = gdb.printing.RegexpCollectionPrettyPrinter("LLVMSupport")
135198
pp.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter)
136199
pp.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter)
137200
pp.add_printer('llvm::SmallVectorImpl', '^llvm::SmallVector(Impl)?<.*>$', SmallVectorPrinter)
138201
pp.add_printer('llvm::ArrayRef', '^llvm::(Const)?ArrayRef<.*>$', ArrayRefPrinter)
139202
pp.add_printer('llvm::Optional', '^llvm::Optional<.*>$', OptionalPrinter)
203+
pp.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter)
140204
gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)

0 commit comments

Comments
 (0)