Skip to content

Commit a03ec58

Browse files
committed
Add GDB pretty printers for llvm::ilist, llvm::simple_ilist, and llvm::ilist_node.
Reviewers: dblaikie Reviewed By: dblaikie Subscribers: merge_guards_bot, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D72589
1 parent 6b9e2be commit a03ec58

File tree

3 files changed

+167
-1
lines changed

3 files changed

+167
-1
lines changed

debuginfo-tests/llvm-prettyprinters/gdb/prettyprinters.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "llvm/ADT/SmallString.h"
77
#include "llvm/ADT/SmallVector.h"
88
#include "llvm/ADT/Twine.h"
9+
#include "llvm/ADT/ilist.h"
910
#include "llvm/Support/Error.h"
1011

1112
int Array[] = {1, 2, 3};
@@ -25,4 +26,25 @@ llvm::Twine Twine = llvm::Twine(SmallString) + StringRef;
2526
llvm::PointerIntPair<int *, 1> PointerIntPair(IntPtr, 1);
2627
llvm::PointerUnion<float *, int *> PointerUnion(IntPtr);
2728

29+
using IlistTag = llvm::ilist_tag<struct A>;
30+
using SimpleIlistTag = llvm::ilist_tag<struct B>;
31+
struct IlistNode : llvm::ilist_node<IlistNode, IlistTag>,
32+
llvm::ilist_node<IlistNode, SimpleIlistTag> {
33+
int Value;
34+
};
35+
auto Ilist = [] {
36+
llvm::ilist<IlistNode, IlistTag> Result;
37+
for (int I : {13, 14, 15}) {
38+
Result.push_back(new IlistNode);
39+
Result.back().Value = I;
40+
}
41+
return Result;
42+
}();
43+
auto SimpleIlist = []() {
44+
llvm::simple_ilist<IlistNode, SimpleIlistTag> Result;
45+
for (auto &Node : Ilist)
46+
Result.push_front(Node);
47+
return Result;
48+
}();
49+
2850
int main() { return 0; }

debuginfo-tests/llvm-prettyprinters/gdb/prettyprinters.gdb

+82-1
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,85 @@ p PointerIntPair
4545
# CHECK: llvm::PointerUnion containing int * = {pointer = 0xabc}
4646
p PointerUnion
4747

48-
48+
# Switch to print pretty adds newlines to the following statements.
49+
set print pretty
50+
51+
# CHECK: {
52+
# CHECK: [0] = {
53+
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<A> >> = {
54+
# CHECK: prev = [[Ilist_Sentinel:0x.*]] <Ilist>,
55+
# CHECK: next = [[Node_14:0x.*]]
56+
# CHECK: },
57+
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<B> >> = {
58+
# CHECK: prev = [[Node_14]],
59+
# CHECK: next = [[SimpleIlist_Sentinel:0x.*]] <SimpleIlist>
60+
# CHECK: },
61+
# CHECK: members of IlistNode:
62+
# CHECK: Value = 13
63+
# CHECK: },
64+
# CHECK: [1] = {
65+
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<A> >> = {
66+
# CHECK: prev = [[Node_13:0x.*]],
67+
# CHECK: next = [[Node_15:0x.*]]
68+
# CHECK: },
69+
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<B> >> = {
70+
# CHECK: prev = [[Node_15]],
71+
# CHECK: next = [[Node_13]]
72+
# CHECK: },
73+
# CHECK: members of IlistNode:
74+
# CHECK: Value = 14
75+
# CHECK: },
76+
# CHECK: [2] = {
77+
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<A> >> = {
78+
# CHECK: prev = [[Node_14]],
79+
# CHECK: next = [[Ilist_Sentinel]] <Ilist>
80+
# CHECK: },
81+
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<B> >> = {
82+
# CHECK: prev = [[SimpleIlist_Sentinel]] <SimpleIlist>,
83+
# CHECK: next = [[Node_14]]
84+
# CHECK: },
85+
# CHECK: members of IlistNode:
86+
# CHECK: Value = 15
87+
# CHECK: }
88+
# CHECK: }
89+
p Ilist
90+
91+
# CHECK: {
92+
# CHECK: [0] = {
93+
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<A> >> = {
94+
# CHECK: prev = [[Node_14]],
95+
# CHECK: next = [[Ilist_Sentinel]] <Ilist>
96+
# CHECK: },
97+
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<B> >> = {
98+
# CHECK: prev = [[SimpleIlist_Sentinel]] <SimpleIlist>,
99+
# CHECK: next = [[Node_14]]
100+
# CHECK: },
101+
# CHECK: members of IlistNode:
102+
# CHECK: Value = 15
103+
# CHECK: },
104+
# CHECK: [1] = {
105+
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<A> >> = {
106+
# CHECK: prev = [[Node_13]],
107+
# CHECK: next = [[Node_15]]
108+
# CHECK: },
109+
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<B> >> = {
110+
# CHECK: prev = [[Node_15]],
111+
# CHECK: next = [[Node_13]]
112+
# CHECK: },
113+
# CHECK: members of IlistNode:
114+
# CHECK: Value = 14
115+
# CHECK: },
116+
# CHECK: [2] = {
117+
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<A> >> = {
118+
# CHECK: prev = [[Ilist_Sentinel]] <Ilist>,
119+
# CHECK: next = [[Node_14]]
120+
# CHECK: },
121+
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<B> >> = {
122+
# CHECK: prev = [[Node_14]],
123+
# CHECK: next = [[SimpleIlist_Sentinel]] <SimpleIlist>
124+
# CHECK: },
125+
# CHECK: members of IlistNode:
126+
# CHECK: Value = 13
127+
# CHECK: }
128+
# CHECK: }
129+
p SimpleIlist

llvm/utils/gdb-scripts/prettyprinters.py

+63
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,66 @@ def make_pointer_union_printer(val):
365365
string = 'llvm::PointerUnion containing %s' % pointer_type
366366
return make_printer(string, [('pointer', pointer.cast(pointer_type))])
367367

368+
class IlistNodePrinter:
369+
"""Print an llvm::ilist_node object."""
370+
371+
def __init__(self, val):
372+
impl_type = val.type.fields()[0].type
373+
base_type = impl_type.fields()[0].type
374+
derived_type = val.type.template_argument(0)
375+
376+
def get_prev_and_sentinel(base):
377+
# One of Prev and PrevAndSentinel exists. Depending on #defines used to
378+
# compile LLVM, the base_type's template argument is either true of false.
379+
if base_type.template_argument(0):
380+
return get_pointer_int_pair(base['PrevAndSentinel'])
381+
return base['Prev'], None
382+
383+
# Casts a base_type pointer to the appropriate derived type.
384+
def cast_pointer(pointer):
385+
sentinel = get_prev_and_sentinel(pointer.dereference())[1]
386+
pointer = pointer.cast(impl_type.pointer())
387+
if sentinel:
388+
return pointer
389+
return pointer.cast(derived_type.pointer())
390+
391+
# Repeated cast becaue val.type's base_type is ambiguous when using tags.
392+
base = val.cast(impl_type).cast(base_type)
393+
(prev, sentinel) = get_prev_and_sentinel(base)
394+
prev = prev.cast(base_type.pointer())
395+
self.prev = cast_pointer(prev)
396+
self.next = cast_pointer(val['Next'])
397+
self.sentinel = sentinel
398+
399+
def children(self):
400+
if self.sentinel:
401+
yield 'sentinel', 'yes'
402+
yield 'prev', self.prev
403+
yield 'next', self.next
404+
405+
class IlistPrinter:
406+
"""Print an llvm::simple_ilist or llvm::iplist object."""
407+
408+
def __init__(self, val):
409+
self.node_type = val.type.template_argument(0)
410+
sentinel = val['Sentinel']
411+
# First field is common base type of sentinel and ilist_node.
412+
base_type = sentinel.type.fields()[0].type
413+
self.sentinel = sentinel.address.cast(base_type.pointer())
414+
415+
def _pointers(self):
416+
pointer = self.sentinel
417+
while True:
418+
pointer = pointer['Next'].cast(pointer.type)
419+
if pointer == self.sentinel:
420+
return
421+
yield pointer.cast(self.node_type.pointer())
422+
423+
def children(self):
424+
for k, v in enumerate(self._pointers()):
425+
yield ('[%d]' % k, v.dereference())
426+
427+
368428
pp = gdb.printing.RegexpCollectionPrettyPrinter("LLVMSupport")
369429
pp.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter)
370430
pp.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter)
@@ -376,4 +436,7 @@ def make_pointer_union_printer(val):
376436
pp.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter)
377437
pp.add_printer('llvm::PointerIntPair', '^llvm::PointerIntPair<.*>$', make_pointer_int_pair_printer)
378438
pp.add_printer('llvm::PointerUnion', '^llvm::PointerUnion<.*>$', make_pointer_union_printer)
439+
pp.add_printer('llvm::ilist_node', '^llvm::ilist_node<.*>$', IlistNodePrinter)
440+
pp.add_printer('llvm::iplist', '^llvm::iplist<.*>$', IlistPrinter)
441+
pp.add_printer('llvm::simple_ilist', '^llvm::simple_ilist<.*>$', IlistPrinter)
379442
gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)

0 commit comments

Comments
 (0)