Hi all,
Just a generic question about debugging in GDB. Is there a good way to find the proper type of an "object"
in GDB?
What I mean by that is, say there is an AddNode
passed to a function as a PrimExpr
and while debugging this function, is there way to find that it actually belongs to an AddNode
. Trying whatis object
or ptype object
just prints that it’s a PrimExpr
.
I found a rather hacky way to do this by printing
the object.deleter_
if it’s a subclass of tvm::runtime::Object
, and
object.get().deleter_
if it’s a subclass of tvm::runtime::ObjectRef
This prints the type of the Deleter_
for that object and the template argument to the Handler contains the proper type (a sample output for AddNode
is as shown below:)
$65 = (tvm::runtime::Object::FDeleter) 0x7fffaf6c9300 <tvm::runtime::SimpleObjAllocator::Handler<tvm::tir::AddNode>::Deleter_(tvm::runtime::Object*)>
I was just wondering whether there’s a stable/reliable way to get this info.
1 Like
I use the same way, and when I need inspect more details of the class object, I will use p PrettyPrint(xxx).c_str()
, in addition if I want a more clear display(do the real line break instead of just print it as “\n”), the gdb command call (size_t)puts(PrettyPrint(xxx).c_str())
will be used.
for the last command, it is better to set the standard output of the process to another terminal.
1 Like
Thanks for the reply, atleast I’m not the only one who is using the deleter_ hack to find the types of nodes.
And thanks for the ideas with PrettyPrint, I haven’t used it too much in gdb, I normally use the p tvm::Dump(xxx)
for printing Objects and ObjectRefs.
So, out of curiosity, is there a difference between what’s printed by tvm::Dump
vs what’s printed by call (size_t)puts(PrettyPrint(xxx).c_str())
. I tried it on a couple of simple examples and did not see any major differences.
I haven’t used tvm::Dump(xxx)
, I use call (size_t)puts(PrettyPrint(xxx).c_str())
when the xxx
is a large node, e.g., the whole of PrimFunc, you can try with these large node.
Right, I think tvm::Dump(xxx)
also supports printing entire PrimFunc. The main question I had was, is there a clean way to find the underlying type of an Object
/ObjectRef
. Basically, if I have a PrimFunc
is there a way to find that the underlying type is say an AddNode
.
I am using GetTypeKey()
function to query the type information in a gdb session. It seems to be able to print a string representation of the underlying type of an Object/ObjectRef
.
relay_module->GetTypeKey()
"IRModule"
2 Likes
Thanks for the info. Yes, I did realize that we can use GetTypeKey()
sometime after I had created this initial thread. I thought of using that in my extension, but I realized that GetTypeKey()
returns the type as a string that matches the python types mostly, and to be able to recursively access attributes of Stmts or Exprs it was good to get the exact type of the class in c++, which we did get from the deleter_ node, so I decided not to make any changes.
For example, if we have a StmtNode
which is actually a BufferStoreNode
, the _type_key
assigned is tir.BufferStore
, whereas the deleter would give us tvm::tir::BufferStoreNode
. The second version turns out to be more useful to recursively access the attributes of the BufferStoreNode
like buffer
, value
and indices
(In the extension I access value attribute as tvat stmt.value
).