从 AST 构建 CFG

Building CFGs from the AST

据我所知,在解析器构建 AST 之后,此结构被转换为 'intermediate level' IR,例如三个地址代码或任何其他。然后,为了执行一些分析,这个 IR 被转换成一个控制流图。我的问题是,是否有可能在不经过另一个 IR 的情况下从 AST 表示到 CFG,然后通过 CFG 执行数据流分析并获得成功的结果?

如果不先进行作用域再进行名称解析,就无法构建 CFG。

您需要范围解析来确定隐式控制传输的 "scope",例如,if-then-else 的边界、try 语句、带有 "break statements"、[=44 的块=] 语句等。这通常相当容易,因为作用域倾向于遵循语言的语法结构,您已经使用 AST 了。

如果您的语言允许控制转移到命名实体 ("goto "),"call ",您还需要范围解析来确定标识符的定义位置。如果不知道哪个范围包含 goto 以及范围如何控制命名标签的查找,则无法知道 goto 的目标。

通过范围解析,您可以实现名称解析;这允许您将名称分配给包含它们的定义范围,并附加名称的定义(例如,知道 "goto x" 指的是特定范围内的 x,因此指向第 750 行,其中 x 被定义为范围。

一旦你有了名称解析(这样你就可以在 "goto x" 中查找 x 的定义),现在你可以构建一个控制流图。

您可以使用属性语法完成所有这三项操作,属性语法本质上是直接在 AST 上进行的计算。所以,不,除了 AST 之外你不需要任何东西来实现这些。 {您可以了解有关属性计算的更多信息 at my SO answer describing them。当然,任何你可以用形式化的属性计算做的事情,你也可以通过简单地编写大量遍历树并计算等效结果的递归过程来做;这就是在实践中编译属性语法的内容。

在这里你可以找到some details on how to extract the control flow graph by attribute computation

一个混乱的故障是像 "goto @" 这样的计算(GCC 允许这样做)。为此 right,您需要计算标签变量的数据流(从技术上讲,这要求您首先构建一个 CFG :-( )。您可以通过构建一个保守的来避免数据流answer: "goto @" 可以跳转到找到goto的函数中取地址的任何标签。你也可以用属性文法来计算这个。

对于只有结构化控制流的语言,实际上可以直接通过属性语法实现数据流分析。