diff --git a/debuginfo-tests/llvm-prettyprinters/gdb/prettyprinters.cpp b/debuginfo-tests/llvm-prettyprinters/gdb/prettyprinters.cpp --- a/debuginfo-tests/llvm-prettyprinters/gdb/prettyprinters.cpp +++ b/debuginfo-tests/llvm-prettyprinters/gdb/prettyprinters.cpp @@ -6,6 +6,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/ilist.h" #include "llvm/Support/Error.h" int Array[] = {1, 2, 3}; @@ -25,4 +26,25 @@ llvm::PointerIntPair PointerIntPair(IntPtr, 1); llvm::PointerUnion PointerUnion(IntPtr); +using IlistTag = llvm::ilist_tag; +using SimpleIlistTag = llvm::ilist_tag; +struct IlistNode : llvm::ilist_node, + llvm::ilist_node { + int Value; +}; +auto Ilist = [] { + llvm::ilist Result; + for (int I : {13, 14, 15}) { + Result.push_back(new IlistNode); + Result.back().Value = I; + } + return Result; +}(); +auto SimpleIlist = [&]() { + llvm::simple_ilist Result; + for (auto &Node : Ilist) + Result.push_front(Node); + return Result; +}(); + int main() { return 0; } diff --git a/debuginfo-tests/llvm-prettyprinters/gdb/prettyprinters.gdb b/debuginfo-tests/llvm-prettyprinters/gdb/prettyprinters.gdb --- a/debuginfo-tests/llvm-prettyprinters/gdb/prettyprinters.gdb +++ b/debuginfo-tests/llvm-prettyprinters/gdb/prettyprinters.gdb @@ -45,4 +45,14 @@ # CHECK: llvm::PointerUnion containing int * = {pointer = 0xabc} p PointerUnion - +# CHECK-NOT: ilist_node_impl +# CHECK: Value = 13 +# CHECK: Value = 14 +# CHECK: Value = 15 +p Ilist + +# CHECK-NOT: ilist_node_impl +# CHECK: Value = 15 +# CHECK: Value = 14 +# CHECK: Value = 13 +p SimpleIlist diff --git a/llvm/utils/gdb-scripts/prettyprinters.py b/llvm/utils/gdb-scripts/prettyprinters.py --- a/llvm/utils/gdb-scripts/prettyprinters.py +++ b/llvm/utils/gdb-scripts/prettyprinters.py @@ -365,6 +365,62 @@ string = 'llvm::PointerUnion containing %s' % pointer_type return make_printer(string, [('pointer', pointer.cast(pointer_type))]) +def make_ilist_node_printer(val): + """Factory for an llvm::ilist_node printer.""" + + impl_type = gdb.lookup_type(val.type.fields()[0].name) + base_type = gdb.lookup_type(impl_type.fields()[0].name) + derived_type = val.type.template_argument(0) + + def get_prev_and_sentinel(base): + # One of Prev and PrevAndSentinel exists. Depending on #defines used to + # compile LLVM, the base_type's template argument is either true of false. + if base_type.template_argument(0): + return get_pointer_int_pair(base['PrevAndSentinel']) + else: + return base['Prev'], None + + def cast_pointer(pointer): + """Casts a base_type pointer to the appropriate derived type.""" + sentinel = get_prev_and_sentinel(pointer.dereference())[1] + pointer = pointer.cast(impl_type.pointer()) + if sentinel: + return pointer + return pointer.cast(derived_type.pointer()) + + # Repeated cast becaue val.type's base_type is ambiguous when using tags. + base = val.cast(impl_type).cast(base_type) + (prev, sentinel) = get_prev_and_sentinel(base) + prev = prev.cast(base_type.pointer()) + prev, next = map(cast_pointer, (prev, val['Next'])) + children = [('prev', prev), ('next', next)] + if sentinel: + children = [('sentinel', 'yes')] + children + return make_printer(children=children) + +class IlistPrinter: + """Print an llvm::simple_ilist or llvm::iplist object.""" + + def __init__(self, val): + self.node_type = val.type.template_argument(0) + sentinel = val['Sentinel'] + # First field is common base type of sentinel and ilist_node. + base_type = sentinel.type.fields()[0].type + self.sentinel = sentinel.address.cast(base_type.pointer()) + + def _pointers(self): + pointer = self.sentinel + while True: + pointer = pointer['Next'].cast(pointer.type) + if pointer == self.sentinel: + return + yield pointer.cast(self.node_type.pointer()) + + def children(self): + for k, v in enumerate(self._pointers()): + yield ('[%d]' % k, v.dereference()) + + pp = gdb.printing.RegexpCollectionPrettyPrinter("LLVMSupport") pp.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter) pp.add_printer('llvm::StringRef', '^llvm::StringRef$', StringRefPrinter) @@ -376,4 +432,7 @@ pp.add_printer('llvm::Twine', '^llvm::Twine$', TwinePrinter) pp.add_printer('llvm::PointerIntPair', '^llvm::PointerIntPair<.*>$', make_pointer_int_pair_printer) pp.add_printer('llvm::PointerUnion', '^llvm::PointerUnion<.*>$', make_pointer_union_printer) +pp.add_printer('llvm::ilist_node', '^llvm::ilist_node<.*>$', make_ilist_node_printer) +pp.add_printer('llvm::iplist', '^llvm::iplist<.*>$', IlistPrinter) +pp.add_printer('llvm::simple_ilist', '^llvm::simple_ilist<.*>$', IlistPrinter) gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)