0
点赞
收藏
分享

微信扫一扫

UCC编译器学习笔记16


方案2中,无论a为真还是假,都只需要跳转一次,但是方案1不是,因此UCC编译器选的是第二种中间代码生成方案。这个其实是个模板,就是待判断的表达式为真,则跳转到F2,否则顺序执行块会跳到Next2块。

UCC编译器学习笔记16_中间代码

其实指令的执行,就分为两种,顺序执行,跳转执行(引起了控制流的改变)。顺序执行的最小单元,叫做块bblock。那么生成指令时候,无非就是执行指令(不需要产生有向边),或者跳转到块的指令(由于这个是一个块要到另一个块了,因此同时会产生一条有向边)

UCC编译器学习笔记16_UCC编译器源码学习_02

UCC编译器学习笔记16_UCC编译器源码学习_03

在 C 语言中,对数组元素和结构体成员的访问方式也较为灵活,UCC 编译器为了简单

起见,也认为这些操作数被进行了“取地址”操作,即不再重用含有这些操作数的表达式

图 5.2.8 中的例子对此进行了说明,虽然第 20 行只是对 a 进行取地址,并没有通过*ptr 来改

变 a 的值,但 UCC 编译器保守地认为 a 的值会发生变化,因此对第 21 行的 a+b 进行重新计

算。而含有结构体成员 dt.a 或者数组元素 arr[0]的表达式,也不被当作公共子表达式来处理。

在第 23 行对 dt.a+dt.b 进行了重新计算,与之对应的中间代码在第 48 行,其中的 dt[0]对应

的就是 dt.a,而 dt[4]对应的就是 db.b。在中间代码层次,通过保存在符号表中的类型信息,

我们可以知道 dt.a 在结构体对象 dt 中偏移为 0,而 dt.b 在结构体对象 dt 中的偏移为 4。这

是一种“基地址 base + 偏移 offset”的寻址模式,符号 dt 相当于是基地址,而 0 或 4 为偏

移。在图 5.2.8 第 25 行,我们也对 C 表达式 arr[0]+arr[1]重新计算,与之对应的中间代码在

第 52 行。在中间代码层次,我们已经把 C 程序员编写的第 25 行的 arr[1],改用“基地址 base

+ 偏移 offset”的形式来表示,即表示为第 52 行的 arr[4],其中 arr 相当于基地址,而 4 相

当于偏移。不过,对于第 9 行的数组 int arr2[3][5]来说,由于 C 程序员在第 26 行用 arr2[i][2]

这样的方式来访问数组元素,其中 i 为变量,而 2 为常量,这就意味着对数组元素的寻址要

按“基地址+常量偏移+可变偏移”来进行,其中常量偏移为 2*sizeof(int),即 8;可变偏移

则为 i*sizeof(int)*5,即 i*20,第 54 至 57 行用于计算出 arr2[i][2]的地址并存于临时变量 t12

中。对图 5.2.8 第 58 行的中间代码“*t12 = 30;”而言,若把 t12 的值存于 CPU 的寄存器中,

我们就可以通过寄存器间接寻址来对 arr2[i][2]进行赋值操作。

UCC编译器学习笔记16_UCC编译器源码学习_04

UCC编译器学习笔记16_中间代码_05



举报

相关推荐

0 条评论