我正在学习编译器课程,程序编译遵循以下步骤
- 词法分析
- 语法分析
- 语义分析
- 中间代码生成
- 代码优化
- 目标代码生成。
如何查看每个步骤的输出,例如我想在语法分析后查看解析树。
我正在使用 GCC 编译器在 Linux 机器上编译程序。
我们可以使用 gcc 中的 -Wa 编译器选项查看程序的汇编代码,同样有查看 Tokens、Parse tree 和 Inetmediate 代码的选项。
我正在学习编译器课程,程序编译遵循以下步骤
如何查看每个步骤的输出,例如我想在语法分析后查看解析树。
我正在使用 GCC 编译器在 Linux 机器上编译程序。
我们可以使用 gcc 中的 -Wa 编译器选项查看程序的汇编代码,同样有查看 Tokens、Parse tree 和 Inetmediate 代码的选项。
虽然您可以在 gcc 中使用-fdump-tree-all
and-fdump-rtl-all
选项,但我不认为它们的输出对编译器学生非常有用。FWIW,我开始研究 gcc 作为我博士研究的一部分,已经完成了两门本科课程,我发现gcc
它的调试文件不透明且难以理解。
此外,gcc 并没有真正遵循编译器的教科书设计。没有人这样做,真的,因为那样做不好。我很确定 gcc 不会产生解析树或抽象语法树。它确实构建了一个 IR(称为 gimple)来执行其高级优化。
我建议改用 LLVM,它以设计良好且易于遵循而闻名。另一种选择是从教科书下载代码,尤其是 Appel 书,假设它可用。
另一个建议,如果我可以推荐一下我自己的,是使用phc。使用 phc,您可以将解析树视为图像,并在编译器的每次传递后查看 AST 和源代码。这是 AST 和解析树的一部分的比较。它们是使用 phc 生成的。您可以看到类型推断和别名分析的编译器 IR、CFG、SSA 表单和调试输出。您还可以打开和关闭优化和传递以查看它们的效果。
我认为这可能对你有用。
你可以看到预处理器的输出-E
。-fdump-tree-*
转储树的内部表示,例如-fdump-tree-all
. 存在各种-d
转储 RTL 中间表示的选项,例如-fdump-rtl-all
(请参阅手册了解您获得转储的各个通行证);此外,-dD
转储所有宏定义。
从编译器的角度来看clang
,您无法看到编译器生成的每一个输出。这是因为与其他编译器相比,clang 的工作方式不同。
词法分析
令牌可以通过以下方式发出:
clang test.c -Xclang -dump-tokens
clang test.c -Xclang -dump-raw-tokens
中间代码生成
字节码可以通过以下方式发出:clang test.c -S -emit-llvm
语义分析
在生成 AST 的同时执行语义分析。AST 可以通过以下方式发出:
clang test.c -Xclang -ast-dump
clang test.c -Xclang -ast-view (this generates a graph for the textual AST)
代码优化
您可以通过打印应用于 c 代码的优化管道来查询代码优化:
clang test.c -S -mllvm -print-after-all
目标代码生成
生成的代码(即汇编输出)可以通过以下方式查看:
clang test.c -S
奖金
您还可以查看 clang 为程序调用的完整管道。例如,可以通过以下方式查看用于发出目标文件的管道:
clang -ccc-print-phases test.c -c
在终端上生成的输出是:
0: input, "test.c", c
1: preprocessor, {0}, cpp-output
2: compiler, {1}, ir
3: backend, {2}, assembler
4: assembler, {3}, object