将控制流图扁平化为结构化代码

发布于 2024-12-26 21:26:56 字数 630 浏览 7 评论 0原文

我想将控制流图(CFG)渲染为高级代码。通常这很容易;遍历树,依次渲染每个基本块,然后用 goto 将它们粘合在一起。

不幸的是,现在 goto 已经过时了,大多数现代语言都不支持它们。因此,我需要某种方法将基本块粘合在一起,仅使用语言中存在的控制流语句:forwhiledo。 ..whileifbreakContinue。 (我不愿意考虑使用变量构建状态机。)

看来,虽然有算法可以做到这一点,但它们并非在所有情况下都有效。也就是说,仅使用上述有限的一组控制流结构就可以构造出无法扁平化为结构化代码的CFG。

这对我来说直观上似乎是显而易见的,但我无法证明这一点(并且我发现的算法的文档没有详细介绍)。我还没有找到一个不能像这样展平的 CFG 的例子。

我想确切地知道这是否可能。

选项 (a):有没有人有一个不能按上述方式展平的 CFG 的示例? (这会告诉我这是不可能的。)

选项(b):是否有人有证据证明CFG可以如上所述被展平? (这将告诉我这是可能的。)也非常需要一种算法来做到这一点,因为我必须让它工作......

I would like to render a control flow graph (CFG) out to high-level code. Normally this is very easy; walk the tree, render each basic block in turn, glue it all together with gotos.

Unfortunately, gotos are out of fashion these days, and most modern languages don't support them. So I need some way to glue my basic blocks together using only those control flow statements that exist in the language: for, while, do...while, if, break and continue. (I'm not willing to consider building a state machine using variables.)

It would appear that while there are algorithms to do this, they will not work in every case. That is, it's possible to construct a CFG that cannot be flattened to structured code using only the above limited set of control flow structures.

This seems intuitively obvious to me, but I can't prove it (and the documentation for the algorithms I've found don't go into more detail). And I haven't been able to find an example of a CFG which can't be flattened like this.

I would like to know, definitively, if this is possible or not.

Option (a): does anyone have a example of a CFG which cannot be flattened as described above? (Which will tell me that it's not possible.)

Option (b): does anyone have a proof that CFGs can be flattened as described above? (Which will tell me that it is possible.) An algorithm to do it would be highly desirable, too, as I would then have to make it work...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

暮年慕年 2025-01-02 21:26:56

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

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

这个想法是以 Relooper 算法为蓝本的2011。有证据表明,任何控制流都可以以结构化方式表示,只需使用 JavaScript 中可用的控制流构造,并使用 Tilt 语义中提到的辅助变量(如标签),无需任何代码重复(其他方法分割节点,并且有最坏情况下的代码大小情况)。 relooper 也在 Emscripten 中实现,在过去的 4 年里,我们获得了大量的实践经验,表明它在实践中给出了良好的结果,通常很少使用辅助变量。

although this question was asked a long time ago this actually seems to be possible. Mozilla had a similar problem when compiling LLVM to JS (or now WebAssembly). JS and WebAssembly only allow structured control flow, while LLVM allows arbitrary control flow.

They'v written a paper about this which is also used for WebAssembly:

This idea is modeled on the Relooper algorithm from 2011. There is a proof there that any control flow can be represented in a structured way, using just the available control flow constructs in JavaScript, and using a helper variable like label mentioned in the Tilt semantics, without any code duplication (other approaches split nodes, and have bad worst-case code size situations). The relooper has also been implemented in Emscripten, and over the last 4 years we have gotten a lot of practical experience with it, showing that it gives good results in practice, typically with little usage of the helper variable.

你好,陌生人 2025-01-02 21:26:56

我想我已经有结果了。

答案似乎是:不可能。这是来自朱塞佩·雅科皮尼 (Giuseppe Jacopini) 于 1966 年发表的一篇名为“只有两种形成规则的流程图、图灵机和语言”的论文中的Communications of the ACM,第 9 卷,第 366 至 371 页。 CiteSeer 链接。(有趣的是,我发现引用了摘自高德纳 (Knuth) 的开创性著作(从我的角度来看,这非常烦人)转到被认为有害的声明。)

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

好消息是,该论文确实描述了一种策略,以高效的方式仅使用有限的控制流机制,使用尽可能少的状态,将任意 CFG 转换为 CFG。这篇论文相当困难,但看起来很有希望。

I think I have a result.

The answer seems to be: it is not possible. This is from Communications of the ACM, volume 9, pages 366 to 371 in a paper from 1966 called "Flow Diagrams, Turing Machines and Languages with only Two Formation Rules" by Giuseppe Jacopini. CiteSeer link. (Which, amusingly, I found referenced from Knuth's seminal (and, from my point of view, incredibly annoying) Go To Statement Considered Harmful.)

Disappointingly, they don't have a proof, saying they were unable to find one.

The good news is that the paper does describe a strategy for converting an arbitrary CFG into a CFG using only limited control-flow mechanisms in an efficient fashion, using as little state as possible. The paper is pretty hard going but it looks promising.

偏闹i 2025-01-02 21:26:56

如果控制流图不是可简化,那么它就不能像您所描述的那样“扁平化”为结构化控制流。任何不可约 CFG 都包含以下内容的某些变体

Irreducable Control Flow Graph

这里 yz 都是相互进入的循环,这是不可能创建的正常的结构化控制流程。

但是,大多数控制流图都可以进行转换。您可以使用辅助数据结构 Dominator Tree 来执行此操作。例如,请参阅 Haskell 中的此实现

If the Control Flow Graph is not reducible, then it cannot be "flattened" to structured control flow as you describe. Any irreducable CFG contains some variant of the following

Irreducable Control Flow Graph

Here both y and z are loops that enter each other, which would be impossible to create with normal structured control flow.

However, most Control Flow Graphs can be converted. You can use the auxiliary data structure the Dominator Tree to do this. See this implementation in Haskell for example.

醉态萌生 2025-01-02 21:26:56

不可约图

上图虽然不可简化,但可以通过添加辅助变量(例如“jump”)的结构化控制流来实现。我们在 x 上方添加一个块 w,它设置 Jump=false 并转到 x。然后我们创建一个新的块 v,设置 Jump=true,并将从 x 出来的右边缘指向 v 而不是 z。然后我们将 v、x 和 z 定向到一个新块 u,条件是 if Jump=true, z else y。然后添加 z 的第一条语句来设置 Jump = false。这添加了最少的代码,没有重复,并将该结构变成具有单个条目的循环。

减少不可约控制流:

减少不可约流

irreducible graph

The above graph, while irreducible, can be implemented with structured control flow with the addition of a helper variable, say "jump". We add a block w above x which sets jump=false and goes to x. Then we create a new block v that sets jump=true, and direct the right edge coming out of x to v instead of to z. Then we direct v, x, and z to a new block u, with a condition if jump=true, z else y. Then the first statement of z added to set jump = false. This adds a minimum of code with no duplication and turns this structure into a loop with a single entry.

Reducing irreducible control flow:

reducing irreducible flow

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文