Tree Browser has been removed from GCC,
and this page is no longer up-to-date.
Until recently the only way to debug trees from gdb was to call debug_tree as follows:
(gdb) p debug_tree (current_function_decl)
An alternative for interactively scan tree structures is to use the Tree Browser. You can access Tree Browser from anywhere during a debugging session as follows:
(gdb) p browse_tree (current_function_decl) Tree Browser foo Up/prev expressions updated. TB>
For listing available commands, you could try:
TB> h Possible commands are: x - Exits tree-browser. q - Exits tree-browser. h - Prints this help message. update - Update information about parent expressions. verbose - Sets/unsets verbose mode (default is on). fun - Go to the current function declaration. nx - Go to the next expression in a BIND_EXPR. pr - Go to the previous expression in a BIND_EXPR. up - Go to the parent tree node. last - Go to the last expression in a BIND_EXPR. first - Go to the first expression in a BIND_EXPR. hpr - Go to the previous visited node (history previous). arg0 - Child 0. arg1 - Child 1. arg2 - Child 2. arg3 - Child 3. decl_saved_tree - Body of a function. type - Field accessor. size - Field accessor. unit_size - Field accessor. offset - Field accessor. bit_offset - Field accessor. context - Field accessor. attributes - Field accessor. abstract_origin - Field accessor. arguments - Field accessor. result - Field accessor. initial - Field accessor. arg-type - Field accessor. arg-type-as-written - Field accessor. chain - Field accessor. values - Field accessor. domain - Field accessor. method_basetype - Field accessor. fields - Field accessor. arg-types - Field accessor. basetype - Field accessor. pointer_to_this - Field accessor. reference_to_this - Field accessor. vars - Field accessor. supercontext - Field accessor. body - Field accessor. subblocks - Field accessor. block - Field accessor. real - Field accessor. imag - Field accessor. purpose - Field accessor. value - Field accessor. elt - Field accessor. min - Field accessor. max - Field accessor. sc - Search a node having a TREE_CODE given as a parameter. sn - Search an identifier having a name given as a parameter. pp - Pretty print current node. p - Prints the current node. TB>
Note that this list of commands is susceptible to change, since this is a pretty new tool and is still in development.
Now let's try some of these commands: we're on the declaration of the current function, we can have a look at its body.
TB> decl_saved_tree { int T.1; int T.2; int i; extern koo; extern bar; extern toons; i = 0, i = i + 1, koo (), if (i != 0) { bar (i) } else { T.1 = i * 3, T.2 = i + T.1, toons (T.2) }, return i; } TB>
The above output is a pretty-print of the body of the current function. A call to debug_tree would have printed more things about the structure of the Abstract Syntax Trees (AST), as follows:
TB> p <expr_with_file_location 0x401a2aa0 type <void_type 0x401a089c void VOID align 8 symtab 0 alias set -1 pointer_to_this <pointer_type 0x401a0910>> side-effects public arg 0 <bind_expr 0x401a28e0 type <void_type 0x401a089c void> side-effects vars <var_decl 0x401c3910 T.1 type <integer_type 0x40199414 int> used SI file one.c line 10 size <integer_cst 0x401964e0 constant 32> unit size <integer_cst 0x40196580 constant 4> align 32 context <function_decl 0x401c34fc foo> chain <var_decl 0x401c3984 T.2>> body <compound_expr 0x401a2960 type <void_type 0x401a089c void> side-effects arg 0 <expr_with_file_location 0x401a2ac0 type <void_type 0x401a089c void> side-effects public arg 0 <init_expr 0x401a2900 type <void_type 0x401a089c void> side-effects arg 0 <var_decl 0x401c36cc i> arg 1 <integer_cst 0x401a2780 constant 0>> arg 1 <identifier_node 0x401c6480 one.c> one.c:3:0> arg 1 <compound_expr 0x401a29a0 type <void_type 0x401a089c void> side-effects arg 0 <expr_with_file_location 0x401a2b60 type <integer_type 0x40199414 int> side-effects public arg 0 <modify_expr 0x401a2b20 type <integer_type 0x40199414 int> side-effects arg 0 <var_decl 0x401c36cc i> arg 1 <plus_expr 0x401a2b00 type <integer_type 0x40199414 int> arg 0 <var_decl 0x401c36cc i> arg 1 <integer_cst 0x40196c20 1>>> arg 1 <identifier_node 0x401c6480 one.c> one.c:4:0> arg 1 <compound_expr 0x401a2a40 type <void_type 0x401a089c void> side-effects arg 0 <expr_with_file_location 0x401a2980 type <integer_type 0x40199414 int> side-effects public arg 0 <call_expr 0x401a27c0 type <integer_type 0x40199414 int> side-effects arg 0 <addr_expr 0x401b35d0>> arg 1 <identifier_node 0x401c6480 one.c> one.c:5:0> arg 1 <compound_expr 0x401a2a80 type <void_type 0x401a089c void> side-effects arg 0 <expr_with_file_location 0x401a2a20 type <void_type 0x401a089c void> side-effects public arg 0 <cond_expr 0x401a2a00> arg 1 <identifier_node 0x401c6480 one.c> one.c:7:0> arg 1 <expr_with_file_location 0x401a2a60 type <void_type 0x401a089c void> side-effects public arg 0 <return_expr 0x401b3768> arg 1 <identifier_node 0x401c6480 one.c> one.c:12:0>>>>> block <block 0x40198294 used vars <var_decl 0x401c36cc i> supercontext <block 0x401982c0 used supercontext <function_decl 0x401c34fc foo> subblocks <block 0x40198294>>>> arg 1 <identifier_node 0x401c6480 one.c> one.c:3:0> TB>
An interesting thing to remark in this dumping is that a node is represented as a well parenthesized expression. Each tree node contains several fields that are in general aligned at the same indentation level. For example BIND_EXPR has a child called vars (a set of variabl definitions), a body, and a block. All these fields are accessible from Tree Browser.
Thus if we continue our exploration of the current tree structure,
TB> arg0 { int T.1; int T.2; int i; extern koo; extern bar; extern toons; i = 0, i = i + 1, koo (), if (i != 0) { bar (i) } else { T.1 = i * 3, T.2 = i + T.1, toons (T.2) }, return i; } TB> body i = 0, i = i + 1, koo (), if (i != 0) { bar (i) } else { T.1 = i * 3, T.2 = i + T.1, toons (T.2) }, return i; TB>
Here I have to write some notes on the current chaining of expressions procedure. A compound_expr contains two operands: arg0 the child that contains the expression and arg1 the child that contains the rest of the list of expressions. In arg0 GCC stores an expr_with_file_location node that contains the expression and an information about the position of this expression in the original source code.
For accessing the next expression you can use the next command:
TB> nx i = i + 1, koo (), if (i != 0) { bar (i) } else { T.1 = i * 3, T.2 = i + T.1, toons (T.2) }, return i; TB> nx koo (), if (i != 0) { bar (i) } else { T.1 = i * 3, T.2 = i + T.1, toons (T.2) }, return i; TB> nx if (i != 0) { bar (i) } else { T.1 = i * 3, T.2 = i + T.1, toons (T.2) }, return i; TB>
You can choose to go backwards via the history stack: this pops the last visited node from the stack.
TB> hpr koo (), if (i != 0) { bar (i) } else { T.1 = i * 3, T.2 = i + T.1, toons (T.2) }, return i; TB>
Or via the previous expression command (this information is not yet included in GCC's trees, Tree Browser stores it in a hash table):
TB> pr i = i + 1, koo (), if (i != 0) { bar (i) } else { T.1 = i * 3, T.2 = i + T.1, toons (T.2) }, return i; TB>
Some extensions could be added in the near future, such as including commands that allows you to modify tree structure, apply optimizations locally on a given node.
A more interesting but much more long term project is to write an interactive program editor/optimizer, but for the moment this is only science fiction... :-)
Copyright (C) Free Software Foundation, Inc. Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved.
These pages are maintained by the GCC team. Last modified 2022-11-01.