使用 GraphViz 理解 -fdump-tree 输出 gcc

fun*_*man 6 c gcc dot abstract-syntax-tree graphviz

我已经创建了一个树转储如何在这里描述:如何将 gcc 生成的抽象语法树转储到 .dot 文件中?对于这个虚拟脚本:

int fact(int n) {
    if (n<=1) {
        return 1;
    }
    return n * fact(n-1);
}

int main(void) {
    int a = 4;
    int res = fact(a);
    return res;
}
Run Code Online (Sandbox Code Playgroud)

以及我所拥有的图像:

通过 GraphViz 生成的图表

据我所知,gcc 不是学习 AST 表示的最佳方式。但无论如何,了解图像内容的含义会很好。

特别是%这里的符号和FREQ:0声明是什么意思?

Flo*_*mer 5

您链接的答案显示了如何从 GCC 调试转储获取控制流图。所以你的图像实际上并没有显示语法树。

GCC C 前端没有经典意义上的抽象语法树。许多句法结构在解析过程中被降低,通常是一堆gotos。例如,c_finish_loop有这样的:

  /* If we have an exit condition, then we build an IF with gotos either
     out of the loop, or to the top of it.  If there's no exit condition,
     then we just build a jump back to the top.  */
  exit = build_and_jump (&LABEL_EXPR_LABEL (top));
Run Code Online (Sandbox Code Playgroud)

if语句变成COND_EXPR节点。您可以在转储中看到这一点.original(其中COND_EXPR节点像 C 语句一样打印if)。但该过程中没有.dot生成任何文件。一旦编译过程进入中端,就是 GIMPLE,而 GIMPLE(作为 SSA 变体)根本不代表使用高级语言结构(例如for和if语句)的控制流。

Clang 有一个更传统的 AST,由clang -Xclang -ast-dump. 它仍然不适合 Graphviz 的输入,但至少数据在那里。如果您的目标是了解 GCC,请查看 C++ 前端,它在解析器中保留了更丰富的结构。