《Engineering a Complier》学习笔记(五)

Intermediate Representation (中间表达式)

 

一. 概述

IR是编译器从语义分析到生成机器代码的中间过程。编译器可能有一种IR,也可能有多种。

IR可以分为3类:

  • 图IR
  • 线性IR
  • 混合型IR 

 

二. 图IR

与语法相关的树

1. 语法分析树

第3章中已介绍,不赘述

 

2. 抽象语法树(AST)

在语法树的基础上,省略了表示非终结符的大部分节点

 

 

3. 有向无环图(DAG)

DAG是一种具有共享机制的AST,相同子树只实例化一次,可能有多个父节点。

 

a * 2 + a * 2 * b的DAG:

 

 

4. 抽象层次

AST或DAG简洁的表达了IR技术,但对于底层的实现来说,缺少细节,举例:w ← a - 2 * b, 在不同层次上的AST:

其中,◆是一个运算符,反引用一个值,即:将值作为地址处理,返回内存地址中的内容。

 

 

编译器将具有相同生命周期和可见性的值存储在一起,称为数据区。(Data Area)

1. 控制流图

基本程序块(Basic Block):最大长度的无分支代码序列,开始于一个有标号的操作,结束于一个分支、跳转或条件判断操作。

控制流图(Control-flow Graph,CFG):控制各程序块的模型,是一个有向图G=(N,E),每个节点是一个基本程序块,每个边是一个可能的控制转移。

While和If在CFG中的表示:

 

      

单语句块(Single-Statement Block):对应源代码层次上单一语句的代码块。

2. 依赖关系图

依赖关系图(Data Dependence Graph):表达一个值从创建之处(定义)到使用之处(使用)的流动

示例:

 

 

3. 调用图(Call Graph)

调用图的结点表示每个过程,每个边表示每个不同过程的调用位置。

 

三. 线性IR

包含一个指令序列,其中各个指令按照顺序执行。指令可能包含多个操作,类似汇编代码。

1. 堆栈机代码

一种单地址代码,大部分操作从栈获得一个操作数,并将其结果堆入栈

如 a - 2 * b:

 

2. 三地址代码

包括1个运算符,2个操作数,1个结果,最多需要3个地址:

如 a - 2 * b:

 

3. 线性代码的表示

三地址代码表示为一个四元组,1个运算符,2个操作数,1个结果。

在代码中可以用不同方法实现。

 

4. 从线性代码构建控制流图

 

四. 从值到名字的映射

1.临时值的命名

以下式为例,源代码只包含4个变量,用三地址法处理时,变量的扩展以不同方法数目也不同。

 

从ATS到底层的线性IR,会产生很多临时变量。

 2.静态单赋值形式(Static Single-Assignment Form)

SSA,一种命名规范,基于值的命名系统,由一种称为ϕ函数的伪码操作方法构造。

SSA程序两条约束:(1)每一条定义都有一个独特的名字(2)每一处使用都引用一条定义。

一个ϕ函数会融合不同的命名,并创建一个新的名字。

 ϕ函数不遵守三地址模型,其可以放入多个name作为输入,用来处理诸如Switch...case等情形。

  3.内存模型

 内存模型描述了上述步骤所记录出来的值如何储存。

一般有两种策略:

(1)寄存器到寄存器

(2)内存到内存

 

五. 符号表

参考:https://www.jianshu.com/p/bda60193808d, https://www.cnblogs.com/programnote/p/4729467.html

当编译器将IR重新写入磁盘时,重新计算内容的代价比将其写入磁盘再读取的代价要小。

书中用哈希表来建立符号表。。。

 

posted @   Asp1rant  阅读(166)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示