9.5.3 构建数据流有向图
在总体逻辑中我们提到构建数据流有向图总共分为三步,但要做的事情实际上只有两类:创建顶点、创建边。
创建顶点
对于函数中的每个局部变量,都需要为其创建一个顶点,该逻辑由函数 initFunc()
完成:
创建顶点的逻辑由第一个 for 循环完成,其遍历函数所有的局部变量,为其创建一个 location 对象,并将其添加到 b.allLocs
属性中,该逻辑由 e.newLoc()
完成,此处不再贴出代码。第二个 for 循环用来设置返回值变量的索引值,此处不用太关注。
注意此处创建的顶点仅是函数内的命名局部变量,对于通过函数 new
与 make
创建的顶点,以及各种字面量初始化创建的顶点,需要在构造有向图边的时候才能创建。
创建有向边
构造有向边的逻辑更加复杂,因为只有对函数的所有语句进行分析之后,才能够构建出完整的赋值关系,从而构建出完整的数据流有向图。
分析赋值关系的逻辑入口是 batch.walkFunc(ir.Func)
, 该方法对目标函数的所有语句递归遍历并进行分析,如果语句中存在赋值关系,则为其创建有向边。该逻辑涉及到的代码很多,但主体框架可以由如下几个函数体现:
escape.stmt(ir.Node) 对单个语句进行分析的方法,该函数通过一个巨大的
switch...case
对各种类型的语句进行处理。例如对于赋值语句,该函数最终会为赋值语句两边的顶点建立一条有向边。escape.expr(h hole, n ir.Node) 该函数模拟对表达式
n
进行求值,并将求值策略保存在参数h
中,可以将该方法理解为为节点n
所表示的表达式构建对应的hole
实例。batch.flow(h hole, src location) 建立从
src
到h.dst
两个顶点的有向边。
读者可以通过Unit Test部分介绍的方式对总体构建逻辑进行调试。
最后更新于