学习内容
完成对 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 | def forWrong() |
这很明显不是多数人理解的for语义。
实现for的IR生成代码时,重写了其逻辑,修改后的逻辑框架如下:
1 | preheader_bb: |
修改后的for工作逻辑与c等语言保持了一致。
扩展问题
在展开for表达式时,原示例代码先保存了for指示变量可能会覆盖的变量名,离开for展开流程时,再恢复原始值(如果没有重名,那就把for定义的指示变量从名称查找map named_var中移除)。这样看来,遵循底层覆盖上层的原则,并且不提供访问上层被覆盖值的机制,那么确实无需专门定义scope的概念。
如下示例:
1 | def xt(i) |
即使在for表达式后,还可以添加其他语句。那么其他语句也可以正常访问到入参i的值。