编译原理之中间代码生成

中间代码定义

源程序的一种内部表示,不依赖目标机的结构,易于机械生成目标代码的中间表示。
如果不生成中间代码而是直接生成机器语言或者汇编语言形式的目标代码,优点是编译时间短,缺点是目标代码执行效率和质量都比较低,移植性差。

为什么不直接翻译成机器码呢,而多此一举生成中间代码再转换?(代码的鲁棒性)

是为了提高编译器的可移植性,因为不同的cpu的指令集是不一样的,假如直接翻译成机器代码,那么当你换了一块cpu之后,可能你的编译器就完全不能运行了,所以为了鲁棒性,将代码先翻译成中间代码,然后在能在多个不同的cpu上做出相应的改变并且运行了。
在这里插入图片描述

使用中间代码的好处:

1)一是便于编译器程序的开发和移植(鲁棒性)
2)二是代码进行优化处理

常见的中间代码表示形式

逆波兰式(后缀式)、三地址码(三元式、四元式)、抽象语法树、有向无环图。

逆波兰式 运算量(操作数)写在前面,把运算符写在后面,因此又称为后缀表示法
在这里插入图片描述

三地址码——最常用的中间代码形式是三地址码,它的实现形式常采用四元式形式。
指每条代码包含一个运算和三个地址,两个地址用于存放运算对象,一个地址用于存放运算结果。其一般形式为x=y op z。
四元式
一个四元式具有四个域的记录结构,表示为:(op,arg1,arg2,result)。op为运算符;result存放运算结果;arg为运算对象,如果为空,则使用空格,留出位置。
四元式与三元式的唯一区别:
将由序号所表示的运算结果改为:用(临时)变量来表示。
此改变使得四元式的运算结果与其在四元式序列中的位置无关.为代码的优化提供了极大方便,因为这样可以删除或移动四元式而不会影响运算结果.
在这里插入图片描述

例:将 a=b*c+b*d用三元形式
(1) (*,b,c)
(2) (*,b,d)
(3) (+,(1),(2))
(4) (=,(3),a)

例:将 a=b*c+b*d用四元式形式
写成三地址码的赋值语句形式如下:
    1) t1 = b*c
    2) t2 = b*d
    3) t3 =t1+t2
    4) a = t3
写成四元形式如下:
    1) (*,b,c,t1)
    2) (*,b,d,t2)
    3) (+,t1,t2,t3)
    4) (=,t3, ,a)

抽象语法树
抽象语法树(Abstract SyntaxCode,AST)是语法树的一种简化形式,是源程序的抽象语法结构的树状表示,树的每个节点都表示源代码中的一种结构。

有向无环图
有向无环图(Directed Acyclic Graph,简称DAG)对表达式中的每个子表达式都有一个结点,内部结点表示运算符,它的孩子代表运算分量。DAG中代表公共子表达式的结点只出现一次,具有多个父结点。

一个例子

声明语句的翻译之变量的声明 一个变量的声明应该由两部分来完成:类型的定义和变量的声明
类型定义:为编译器提供存储空间大小的信息
变量声明:为变量分配存储空间
组合数据的类型定义和变量声明:定义与声明在一起,定义与声明分离.

引用于介篇文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章