forked from OSchip/llvm-project
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
This commit is contained in:
parent
6b9e2be8ec
commit
a03ec58da6
debuginfo-tests/llvm-prettyprinters/gdb
llvm/utils/gdb-scripts
|
@ -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::Twine Twine = llvm::Twine(SmallString) + StringRef;
|
|||
llvm::PointerIntPair<int *, 1> PointerIntPair(IntPtr, 1);
|
||||
llvm::PointerUnion<float *, int *> PointerUnion(IntPtr);
|
||||
|
||||
using IlistTag = llvm::ilist_tag<struct A>;
|
||||
using SimpleIlistTag = llvm::ilist_tag<struct B>;
|
||||
struct IlistNode : llvm::ilist_node<IlistNode, IlistTag>,
|
||||
llvm::ilist_node<IlistNode, SimpleIlistTag> {
|
||||
int Value;
|
||||
};
|
||||
auto Ilist = [] {
|
||||
llvm::ilist<IlistNode, IlistTag> Result;
|
||||
for (int I : {13, 14, 15}) {
|
||||
Result.push_back(new IlistNode);
|
||||
Result.back().Value = I;
|
||||
}
|
||||
return Result;
|
||||
}();
|
||||
auto SimpleIlist = []() {
|
||||
llvm::simple_ilist<IlistNode, SimpleIlistTag> Result;
|
||||
for (auto &Node : Ilist)
|
||||
Result.push_front(Node);
|
||||
return Result;
|
||||
}();
|
||||
|
||||
int main() { return 0; }
|
||||
|
|
|
@ -45,4 +45,85 @@ p PointerIntPair
|
|||
# CHECK: llvm::PointerUnion containing int * = {pointer = 0xabc}
|
||||
p PointerUnion
|
||||
|
||||
# Switch to print pretty adds newlines to the following statements.
|
||||
set print pretty
|
||||
|
||||
# CHECK: {
|
||||
# CHECK: [0] = {
|
||||
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<A> >> = {
|
||||
# CHECK: prev = [[Ilist_Sentinel:0x.*]] <Ilist>,
|
||||
# CHECK: next = [[Node_14:0x.*]]
|
||||
# CHECK: },
|
||||
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<B> >> = {
|
||||
# CHECK: prev = [[Node_14]],
|
||||
# CHECK: next = [[SimpleIlist_Sentinel:0x.*]] <SimpleIlist>
|
||||
# CHECK: },
|
||||
# CHECK: members of IlistNode:
|
||||
# CHECK: Value = 13
|
||||
# CHECK: },
|
||||
# CHECK: [1] = {
|
||||
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<A> >> = {
|
||||
# CHECK: prev = [[Node_13:0x.*]],
|
||||
# CHECK: next = [[Node_15:0x.*]]
|
||||
# CHECK: },
|
||||
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<B> >> = {
|
||||
# CHECK: prev = [[Node_15]],
|
||||
# CHECK: next = [[Node_13]]
|
||||
# CHECK: },
|
||||
# CHECK: members of IlistNode:
|
||||
# CHECK: Value = 14
|
||||
# CHECK: },
|
||||
# CHECK: [2] = {
|
||||
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<A> >> = {
|
||||
# CHECK: prev = [[Node_14]],
|
||||
# CHECK: next = [[Ilist_Sentinel]] <Ilist>
|
||||
# CHECK: },
|
||||
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<B> >> = {
|
||||
# CHECK: prev = [[SimpleIlist_Sentinel]] <SimpleIlist>,
|
||||
# CHECK: next = [[Node_14]]
|
||||
# CHECK: },
|
||||
# CHECK: members of IlistNode:
|
||||
# CHECK: Value = 15
|
||||
# CHECK: }
|
||||
# CHECK: }
|
||||
p Ilist
|
||||
|
||||
# CHECK: {
|
||||
# CHECK: [0] = {
|
||||
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<A> >> = {
|
||||
# CHECK: prev = [[Node_14]],
|
||||
# CHECK: next = [[Ilist_Sentinel]] <Ilist>
|
||||
# CHECK: },
|
||||
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<B> >> = {
|
||||
# CHECK: prev = [[SimpleIlist_Sentinel]] <SimpleIlist>,
|
||||
# CHECK: next = [[Node_14]]
|
||||
# CHECK: },
|
||||
# CHECK: members of IlistNode:
|
||||
# CHECK: Value = 15
|
||||
# CHECK: },
|
||||
# CHECK: [1] = {
|
||||
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<A> >> = {
|
||||
# CHECK: prev = [[Node_13]],
|
||||
# CHECK: next = [[Node_15]]
|
||||
# CHECK: },
|
||||
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<B> >> = {
|
||||
# CHECK: prev = [[Node_15]],
|
||||
# CHECK: next = [[Node_13]]
|
||||
# CHECK: },
|
||||
# CHECK: members of IlistNode:
|
||||
# CHECK: Value = 14
|
||||
# CHECK: },
|
||||
# CHECK: [2] = {
|
||||
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<A> >> = {
|
||||
# CHECK: prev = [[Ilist_Sentinel]] <Ilist>,
|
||||
# CHECK: next = [[Node_14]]
|
||||
# CHECK: },
|
||||
# CHECK: <llvm::ilist_node<IlistNode, llvm::ilist_tag<B> >> = {
|
||||
# CHECK: prev = [[Node_14]],
|
||||
# CHECK: next = [[SimpleIlist_Sentinel]] <SimpleIlist>
|
||||
# CHECK: },
|
||||
# CHECK: members of IlistNode:
|
||||
# CHECK: Value = 13
|
||||
# CHECK: }
|
||||
# CHECK: }
|
||||
p SimpleIlist
|
||||
|
|
|
@ -365,6 +365,66 @@ def make_pointer_union_printer(val):
|
|||
string = 'llvm::PointerUnion containing %s' % pointer_type
|
||||
return make_printer(string, [('pointer', pointer.cast(pointer_type))])
|
||||
|
||||
class IlistNodePrinter:
|
||||
"""Print an llvm::ilist_node object."""
|
||||
|
||||
def __init__(self, val):
|
||||
impl_type = val.type.fields()[0].type
|
||||
base_type = impl_type.fields()[0].type
|
||||
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'])
|
||||
return base['Prev'], None
|
||||
|
||||
# Casts a base_type pointer to the appropriate derived type.
|
||||
def cast_pointer(pointer):
|
||||
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())
|
||||
self.prev = cast_pointer(prev)
|
||||
self.next = cast_pointer(val['Next'])
|
||||
self.sentinel = sentinel
|
||||
|
||||
def children(self):
|
||||
if self.sentinel:
|
||||
yield 'sentinel', 'yes'
|
||||
yield 'prev', self.prev
|
||||
yield 'next', self.next
|
||||
|
||||
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 +436,7 @@ pp.add_printer('llvm::DenseMap', '^llvm::DenseMap<.*>$', DenseMapPrinter)
|
|||
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<.*>$', IlistNodePrinter)
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue