将CFG展平为结构化代码

时间:2012-01-14 22:51:22

标签: compiler-construction compilation theory control-flow control-flow-graph

我想将CFG呈现给高级代码。通常这很容易;走树,依次渲染每个基本块,将它们与gotos粘合在一起。

不幸的是,这些日子已经过时了,大多数现代语言都不支持它们。所以我需要一些方法将我的基本块粘合在一起,只使用语言中存在的那些控制流语句:forwhiledo ... while,{ {1}},ifbreak。 (我不愿意考虑使用变量构建状态机。)

虽然有算法可以做到这一点,但它们在每种情况下都能正常工作。也就是说,可以使用上述有限的控制流结构来构造一个不能扁平化为结构化代码的CFG。

这对我来说似乎很直观,但我无法证明它(我发现的算法文档没有详细说明)。而且我还没有找到一个不能像这样平整的CFG的例子。

我想明确知道,如果这是可能的话。

选项(a):是否有人有一个如上所述无法展平的CFG示例? (这会告诉我这是不可能的。)

选项(b):是否有人证明CFG 可以如上所述被夷为平地? (这会告诉我它可能。)这样做的算法也非常可取,因为我必须让它工作......

3 个答案:

答案 0 :(得分:1)

我想我有结果。

答案似乎是:这是不可能的。这是来自1966年的一篇名为“流程图,图灵机和只有两种形成规则的语言”的文章,第9卷,第366至371页的通信ACM ,第9卷,第366至371页,作者是Giuseppe Jacopini。 CiteSeer link.(有趣的是,我发现从Knuth的开创性中引用了(并且,从我的观点来看,令人难以置信的烦恼)转到认为有害的陈述。)

令人失望的是,他们没有证据,说他们找不到证据。

好消息是,本文确实描述了使用有限的控制流机制将任意CFG转换为CFG的策略,使用尽可能少的状态。这篇论文很难,但看起来很有希望。

答案 1 :(得分:1)

尽管很久以前就提出过这个问题,但实际上这似乎是可能的。在将LLVM编译为JS(或现在的WebAssembly)时,Mozilla也遇到了类似的问题。 JS和WebAssembly只允许结构化控制流,而LLVM允许任意控制流。

他们写了一篇关于此的论文,也用于WebAssembly

  

这个想法是基于Relooper2011算法建模的。有证据表明,任何控制流都可以用结构化的方式表示,只使用JavaScript中可用的控制流结构,并使用Tilt语义中提到的标签之类的辅助变量,而不需要任何代码重复(其他方法分割节点,并且具有糟糕的最坏情况代码大小情况)。 relooper也已在Emscripten中实现,在过去的4年中,我们已经获得了很多实践经验,表明它在实践中给出了很好的结果,通常很少使用辅助变量。

答案 2 :(得分:0)

一般情况下,您不能通过走树来展平CFG。如果你有k个预测标记,这将适用于LL(k)语法。但是,对于更复杂的语法,如LR(k)语法,需要更复杂的技术。例如,请参阅http://en.wikipedia.org/wiki/LR_parser

一般来说,没有已知的解析任何CFG的算法,尽管大多数有用的CFG都可以写成LR(k)语法。更多的研究改进了这一点,并且可以解析大类的CFG。我不认为这个问题是不可判定的(虽然我不确定),所以它总是可以做到这一点 - 但我认为这是一个研究问题,而不是在这里你会回答是/否。

我还应该补充一点,今天所有有价值的语言都是图灵完备的,这意味着你可以用if / while / for / ...类型结构来完成你可以用GOTO做的任何事情。新语言不是限制,它是需要帮助的理论构建块。

但在实践中,您无法解析任何您想要的CFG。但这并不意味着我们不知道将来怎么样......