Kaleidoscope ast

学习内容

完成对https://github.com/zy445566/llvm-guide-zh/tree/master/Chapter02

https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/LangImpl02.html
的学习。

练习

看懂原网页后,实现同样的功能,补充测试。
实现时需要做如下改进:
1 作为纯粹的前端,至少在生成LLVM-IR前不应该依赖llvm的任何代码。将所有的llvm::make_unique 改为 std::make_unique(C++11中没有这个接口所以llvm自己实现了,C++14已经有了;最新的LLVM代码也已经完成了向std的切换)
2 将parser作为class封装起来
3 日志输出的封装
4 基本功能测试

扩展

clang 是如何实现AST的构建
玩具实现和clang的实现之间有没有实质性的区别

进展

完成了示例parser的实现,并添加了对应的测试用例

实现

除了完成了原示例外和前面计划的改进外,实现过程中还新增了一些改进,包括:
1 为每一个ast添加了type类型,便于管理ast指针
2 将每一个全局ast存入了统一的vector中,便于后续读取处理
3 为各个ast的内部接口添加了访问接口,以便读出数据进行测试
4 为所有的prototype提供了全局hash表,为后续call的一致性检查提供了便利
5 改进了原示例对toplevel expr的处理逻辑,将这些expr推入2步提供的vector中管理,不再放入一个匿名函数中(以避免重名等问题)
6 严格分层,parser不直接读取原始的char,其全部输入都来自lexer给出的token
7 小幅改进binary_op的相关解析流程,将原有流程中 op优先级和binary表达式结束 混合判断的情况做了拆分,逻辑上更易理解

clang对比

实现后,查看了clang的代码。
clang的parser基本解析流程和玩具示例的没有实质上的区别(注意到clang的parser也是处理token,不直接读取char),尤其是binary_op的解析。
clang的lib/Parse/ParseExpr.cpp的ParseRHSOfBinaryExpression和示例中的parse_binary_expr基本逻辑是完全一样的。
阅读clang代码,发现了一些clang实现可借鉴的地方:
1 使用 using定义专有类型,可以使得代码更简洁

1
using ExprResult = ActionResult<Expr *>;

2 使用class内的模板函数自动完成指针类型的转换,可以使代码更简洁

1
2
template <typename PtrT> PtrT getPtrAs() const {
return get();

3 定制测试框架设计(dump出文本+模式匹配),测试用例开发效率确实远高于直接使用gtest等通用单元测试框架