抱歉博客有一阵子没更了,因为生了四五天的病,又因为书上对这一段介绍的顺序奇奇怪怪的,it confuse me for a long time. 不过我现在可以把我前几天写的东西记录一下了。
参考
- 《编译器设计》(《Engineering a Compiler》)
- 龙书
大体思路
AST => 线性IR(三地址代码) => 构建CFG => (future),可能要加SSA(静态单赋值形式)。
线性IR指令的一些要点
- 全局变量用@ name表示,局部变量用%name表示。
- 为了方便起见,在不同scope的变量,即便重名,也实际上是不同的变量,所以干脆起成不同的名字。
- 条件语句支持短路求值。
字符串的连接和比较大小,我暂时没想好怎么写,就先表示成函数形式。
构建CFG的一些要点
把整个IR存成一个数据结构,类似于这样
暂时不知道这样好不好,就觉得会方便一点。
小小的例子
对于这样一份代码:
void func(int a, int b) { println("happy " + toString(a) + " " + toString(b)); } int main() { int i, j, n = 10; for (i = 1; i <= n; ++i) { for (j = 1; j < i; ++j) { func(j, i); } } }
我会生成这样的例子:
Func_def @func (%a0, %b1): BasicBlock @func: @func: param %a0 call %2 @toString 1 param "happy " param %2 call %3 @stringCat 2 param %3 param " " call %4 @stringCat 2 param %b1 call %5 @toString 1 param %4 param %5 call %6 @stringCat 2 param %6 call @println 1 (From:) (To:) Func_def_done Func_def @main (): BasicBlock @main: @main: mov %n9 10 mov %i7 1 leq %14 %i7 %n9 cbr %14 label0 label6 (From:) (To: label0 label6) BasicBlock label6: label6: nop (From: @main label4) (To:) BasicBlock label0: label0: mov %j8 1 les %19 %j8 %i7 cbr %19 label2 label4 (From: @main label4) (To: label2 label4) BasicBlock label4: label4: add %i7 %i7 1 leq %21 %i7 %n9 cbr %21 label0 label6 (From: label0 label2) (To: label0 label6) BasicBlock label2: label2: param %j8 param %i7 call @func 2 add %j8 %j8 1 les %20 %j8 %i7 cbr %20 label2 label4 (From: label0 label2) (To: label2 label4) Func_def_done
Something else
- 哇这篇博客好短啊,你不是说it confuse you for a long time吗,折腾了半天就写了这点东西?态度太不端正了!
- 我承认态度不如(ai)以(cou)前(zi)好(shu)了,但是确实一下想通了就觉得没什么可说的了。
不过还是说一说:
- 什么树IR什么图IR什么线性IR什么CFG什么AR什么OR这都是什么东西啊,什么时候加哪一个啊,到底要不要用LLVM啊?如上所述。
- 现在要不要管内存的东西?我感觉基本不要,除了数组啊类啊什么的,可以稍微表示一下,知道它是数组是类就好了。
- 函数怎么表示啊?如上所述。
- 类怎么表示啊?类的定义怎么写成三地址代码啊?说到底,类和数组也没啥区别嘛,无非就是每个人不一般大而已。所以只要记一下每个人的offset,不管在数据结构里还是三地址代码里,到后面按照内存类似数组的方式访问就可以了。
- 寄存器啥的到底存成字符串还是写个类啊?抱歉,我也不知道,实在不行到时候再转呗,转来转去还挺方便的……
- SSA是什么东西啊?phi函数又是啥啊?怎么加啊?我不知道,所以我暂时还没加……