Kaleidoscope control flow

学习内容

完成对 https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/LangImpl05.html 的学习。

练习

看懂原网页后,实现同样的功能。

扩展

原示例中for引入了循环变量,但是仍然没有引入scope之类的概念,而是直接将所有变量名称放到function的NamedValues map(我们的实现是cur_func_args)中。这个是否会产生命名冲突,是否一定需要建立分级的命名查找表?

进展

完成了原示例的if和for添加。
实现过程中发现原示例的for逻辑有问题,参考if的写法做了重写。

实现

大部分语言使用’,’ 作为顺序求值的符号,后续Kaleidoscope也会增加多语句的支持。因此实现时将原示例中的for表达式中的分隔符从”,” 改为了”:”,将”,”预留出来。

实现时的主要变更是改写了for的语义,具体情况如下:
原示例中的for循环展开时,是先执行完成loop后再做结束检查,这和通常语言的for定义都冲突。
使用原示例的代码,如下循环仍然会打印出数字1

1
2
3
def forWrong()
for x = 1: x < 1: 1 in
print(x)

这很明显不是多数人理解的for语义。

实现for的IR生成代码时,重写了其逻辑,修改后的逻辑框架如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
preheader_bb:
计算induction var(指示变量)的初始值
goto to end_check
end_check:
计算end expr的值end_val是否为true
if (end_val)
goto loop
else
goto afterloop

loop:
计算循环体body expr的值
induction var += step
goto end_check

after_loop:
xxxx后续指令

修改后的for工作逻辑与c等语言保持了一致。

扩展问题

在展开for表达式时,原示例代码先保存了for指示变量可能会覆盖的变量名,离开for展开流程时,再恢复原始值(如果没有重名,那就把for定义的指示变量从名称查找map named_var中移除)。这样看来,遵循底层覆盖上层的原则,并且不提供访问上层被覆盖值的机制,那么确实无需专门定义scope的概念。
如下示例:

1
2
3
def xt(i)
for i = 0 : i < 5 : 1 in
print(i)

即使在for表达式后,还可以添加其他语句。那么其他语句也可以正常访问到入参i的值。