编译总结感想

Posted by Steel Shadow on December 25, 2023

BUAA 2023 编译总结感想

课程收获

实践独立开发了一个 C 语言子集的简单编译器。

学习了编译器优化知识,提升综合工程能力。

Cpp 学习经验

本项目使用 Cpp 编写,目标代码生成 MIPS。共写 6000 余行。

我选择使用 Cpp 而不是 Java 开发编译器有以下几个原因:

  1. 之前选修了面向对象先导课,课程讲授了 Cpp,但作业是 Java,为 OO 课开路。我希望提高自己的 Cpp 编程水平。
  2. 编译器作为基础设施,对性能要求较高,Cpp 比 Java 运行效率更高,符合直觉。

编译器选择 g++ vs clang++ vs MSVC

Visual Studio 的 MSVC 编译器的调试很方便,调试信息十分符合直觉。

在编译报错信息方面,MSVC 和 Clang++ 都远好于 g++。

单例模式 Singleton

Singleton 中,单例变量初始化要放在源文件(放在头文件可能导致多次初始化错误)

Union 中 gcc clang 编译器实现“错误” union 的 C++标准没说清楚,编译器厂商实现不一样! c++ 17 应该使用 variant 替代 union。

include 原则

头文件应当尽可能少地 include,以减少编译时间。 区分头文件和源代码的 include。 必要时使用前置声明避免循环include。(使用module即可避免,可惜课程组要求的 C++17 不支持)

Cmake

学习 Cmake 构建 cpp 工程。makefile 过于原始,不够现代。

课程建议

在学习了实验教程和专题报告后,我认为部分内容可以作进一步的补充。

符号表

在实验教程部分和专题报告中,可以明确指出栈式符号表和树型符号表的适用范围:

  • 栈式符号表要求语义分析和代码生成在同一遍完成。
  • 树型符号表允许语义分析和代码生成在不同遍完成。

$sp 和 $fp

MIPS 的访存指令中,支持使用常数偏移量,因此 $sp 的偏移量计算可以在编译期完成。 在实际生成的代码中,只有在函数调用时,生成加减 $sp 的指令才是必要的。

由于可以使用常数偏移量访问栈上的内存,因此 $fp 使用栈帧是没有必要的。

实验教程网站中,没有明确指出 $sp 和 $fp 的作用,示例代码给出的例子使用 $fp,效率不如只使用 $sp。