中间代码生成

中间代码生成的任务是将分析之后得到的源程序的中间表示形式翻译成中间代码表示。

image-20231219095859932

使用中间代码的缺点:

  • 便于编译程序的建立和移植,可以将编译程序分离为前端和后端两个部分,针对不同的语言可以复用针对同一个机器的后端,针对不同的机器可以复用针对同一个语言的前端。
  • 便于记性于机器无关的代码优化工作。

但是使用中间代码的表示增加了IO操作的数量,编译程序的效率有所降低。

中间代码形式

图形表示形式

分成两种形式:

  • 语法树:描绘了源程序的自然层次结构
  • DAG图:以更紧凑的形式给出了和语法树相同的信息,公共子表达式也被标示出来

三地址代码

使用三地址语句组成的代码描述中间代码。

三地址语句是一种类似于汇编语句的代码,有赋值语句和空间语句,语句可以有标号。三地址语句的一般形式为: 其中x可以是临时变量或者是名字,yz可以是名字、常数或者是临时变量。op是运算符号,如算数运算符或者是逻辑运算符。语句中最多有三个地址。

三地址语句的种类和形式如下所示:

  1. 简单赋值语句:

    x := y op z

    x := op y

    x := y

  2. 含有变址的赋值语句:

    x := y[i]

  3. 含有地址和指针的赋值语句:

    x := &y

    x := *y

  4. 转移语句:

    goto L

    if x relop y goto L

  5. 过程调用语句:

    param x

    call p, n

  6. 返回语句:

    return y

例如,对于赋值语句x := (-y) * z + (-y) * z

  1. 对应语法树的三地址代码为:

    image-20231219101157463

  2. 对于DAG图的三地址代码为:

    image-20231219101215573

三地址语句的实现

  1. 四元式

    使用四元组(op, arg1, arg2, result) 表示。

    例如对于三地址语句x := y + z,其的四元式表示为:

    ('+', y, z, x)
    
  2. 三元式

    使用三元组(op, arg1, arg2)表示,相对于四元式省略了返回值的临时变量,减少了符号表的空间,用语句的指针代替存放中间结果的临时变量。

    例如,对于赋值语句x := (-y) * z + (-y) * z:

    image-20231219101937767

  3. 间接三元式

    为三元式的序列增加了一个间接码表,其每个元素依次指向三元式序列中的一个元素。

    对于赋值语句x := (-y) * z + (-y) * z:

    image-20231219102157167

赋值语句的翻译

布尔表达式的翻译

控制语句的翻译