Pretty printers for lldb

I have some basic pretty printers for the LLDB debugger that use the tvm::relay::PrettyPrinter implementation and I am wondering what a good place might be to put them (if people think they are useful). Does a new top-level directory /debug/lldb sound ok, or maybe /tools/debug/lldb?
What are people using in general, gcc toolchain or lldb or something else?

1 Like

Can you elaborate a bit about what is the feature of the printer(perhaps an example usage)? Is it used for debugging relay programs or LLVM in general?

I think your proposal /tools/debug/lldb seems to be reasonable, but would be great if there is a bit of context so the community can also learn from your insights :slight_smile:

cc @jroesch

Pretty printers in lldb (and in gdb) are Python functions that are able to display variables that are more complex than say basic integers or strings. These functions are called automatically anywhere in the debugger where the contents of variables are displayed, e.g. the “Locals” display, when evaluating expressions etc. For example. the STL containers are displayed with pretty printers. Normally you get memory pointers only for (subclasses of) Nodes; with these functions you see the contents.

The “Locals” view in my debugger without pretty printers:

func = {const tvm::relay::Function &}
tvm::relay::Expr = {tvm::relay::Expr}
tvm::relay::NodeRef = {tvm::relay::NodeRef}
node_ = {tvm::NodePtr<tvm::Node>}
var = {const tvm::relay::GlobalVar &}

With pretty printers:

func = {const tvm::relay::Function &} "fn (%a: Tensor[(1, 8, 8, 3), uint8], %b: Tensor[(1, 8, 8, 3), uint8], %e: Tensor[(1, 7, 7, 1), uint8]) {\n %0 = multiply(%a, %b);\n %1 = qnn.conv2d(%0, meta[relay.Constant][0], [snip]
var = {const tvm::relay::GlobalVar &} “@main

1 Like

+1 from me. Leo has explained it pretty well above.

The other example references from the GDB world are as below.

libstdc++ for example ships with a whole bunch of pretty printers that can help debugging C++ stl a more pleasant experience.

I understand that the lldb documentation is here but I haven’t yet found a tutorial for this.


Thanks for great explanation. Currently, the optional features could go to src/contrib/lldb

@Leo-arm @ramana-arm

Thanks for introducing this.

I was trying to pretty print using LLDB, but i couldn’t make it work and was getting something like following while trying to print a CallNode. It seems it at least gets the correct indentation.

Do you have ideas why this could be ?

lldb) p call
(const tvm::relay::CallNode *) $0 = 0x0000000002485a40
(lldb) p call->op
(tvm::relay::Expr) $1 = error: error: Couldn't lookup symbols:
  tvm::PrettyPrint(tvm::runtime::ObjectRef const&)
(lldb) p call->args
(const tvm::Array<tvm::RelayExpr>) $2 = {
  tvm::runtime::ObjectRef = {
    data_ = {
      data_ = 0x00000000024587b0
(lldb) p call->attrs
(const tvm::Attrs) $3 = error: error: Couldn't lookup symbols:
  tvm::PrettyPrint(tvm::runtime::ObjectRef const&)

It appears that the object hierarchy has changed and a CallNode is no longer a sub-class of ObjectRef, hence PrettyPrint fails. I am not very familiar with the new structure so I can’t see a quick way to fix that.

Hi, will there be any updates? It seems that it cannot provide pretty printings for many classes like tvm::runtime::Array or tvm::OpNode.

Sorry for the slow reply; I have been away. Sadly, I have not been involved in actual development of TVM in recent times so have not kept track of this. I created the original list by grabbing the derived classes from ObjectRef iirc. Or just add the ones you know are missing manually. I probably won’t have time to update soon, sorry.