基本块和流图 Baic Block and Flow Graph
介绍一种表示中间代码的方式—流图(Flow Graph)。先把中间代码划分成基本块(Baisc Block),载由基本块形成流图的节点,流图的边指明了哪些基本块可能跟随一个基本块之后执行。
基本块 Baic Block
(鲸书)非正式地说,基本块是一段只能从它的第一条指令进入,并从它的最后一条指令离开的最长指令序列。
(龙书)以三地址指令作为中间代码的表示。基本块为满足下列条件的最大连续指令序列:
- 控制流只能从基本块的第一条指令进入该基本块。
- 除了基本块最后一条指令,控制流在离开基本块之前不会停机或者跳转。
基本块的划分算法(龙书):
输入:三地址指令序列。
输出:输入指令序列对应的基本块列表,每个指令恰好被分给一个基本块。
方法:首先,确定指令序列中的首指令,即每个基本块的第一条指令。选择首指令的原则:
1)输入指令序列的第一条指令是一个首指令。
2)任何一个跳转指令的目标指令是一个首指令。
3)紧跟在一个跳转指令之后的指令是一个首指令。
然后,每个首指令对应的基本块包括了从它自己开始,直到下一个首指令(不包含)或者程序结尾指令之间的所有指令。
上图的这个例子中,根据首指令的规则,很容易判断1、2、3、10、12和13是首指令。
流图 Flow Graph
中间代码程序转换成基本块后,可以使用一个流图表示它们之间的控制流。流图的节点就是基本块。基本块B到基本块C之间有一条边当且仅当C的第一条指令紧跟在B最后一条指令之后执行。有以下两种原因:
- 存在一个从B结尾跳转到C开头的条件或无条件跳转语句。
- 按照原来指令序列中的顺序,C紧跟在B之后,且B结尾不存在跳转语句。
称B是C的前驱(predecessor),而C是B的后继(successor)。通常还为流图增加一个入口(entry)和出口(exit)节点,方便程序分析。
下图就是上面指令序列的流图。
参考
- [1] 龙书
- [2] 鲸书