我的一个项目是decompiler,它将本机代码转换为LLVM IR,简化了它并输出伪C。程序过程的一个重要阶段是pattern-independent control flow structuring,它在程序中查找区域并将它们转换为结构化控制流程语句(即不是结果)。
我不得不推出自己的代码来寻找区域,因为LLVM的区域并不完全符合论文的预期。但是,找到区域需要你有一个后支配树,并且事实证明LLVM的后支配树构建算法不能为没有结束块的函数创建一个,就像&#的函数一样34;端"无限循环。
这似乎是因为树构建算法需要一个起点。通常,起点是函数的返回块,因为它后控制其他每个块;但由于它们没有任何return
或unreachable
终止符,因此没有任何函数可以旋转到无限循环中。 (此时,值得注意的是LLVM的区域代码也依赖于后统治树,对于无法构建它的函数也没用。)
在我看来,即使这个算法失败了,一个函数没有返回的事实并不意味着你不能为它做一个后支配树。 1 事实上,如果无限循环具有单个后沿(这是我可以确保的),那么具有该后沿的节点必然会支配图中的每个其他节点,因此它应该是可能的制作一个后统治者树。
如果我能找到那个节点,我可以将它提供给LLVM的后dom基础设施,并从中获得一个合理的后支配树。不幸的是,我并不是很富有想象力,而且我能想到的唯一直截了当的方法就是确定那个关键节点是"它是那个后来主宰一切的那个"它当然赢了& #39; t帮助我引导一个后支配者树。
寻找后缘并不是特别困难。正如Doug Currie所说,你可以用一个简单的DFS,事实上,我的项目does exactly that的另一部分。然而,在具有无限循环和嵌套的终止循环的函数的情况下,我不知道如何在没有支配信息的情况下从外后边缘告诉内后边缘。 (如果它可以提供帮助,在此过程的这个阶段,每个循环都保证有一个入口节点和最多一个出口节点。)
那么如何构建一个没有任何返回基本块的函数的后支配树?
1。我的编译器和图论背景完全是自学成才。这可能不准确。
答案 0 :(得分:6)
严格来说,当有一个无限循环(不仅仅是一个无界循环 - 一个没有退出的严格无限循环)时,没有后支配者,就像循环中的每个节点一样,下一个节点在循环中将执行它,所以没有"最后"节点到循环。
处理它的一种方法是执行正常的后支配者查找,除非在从出口执行初始深度优先遍历之后,检查未访问的节点。如果有的话,退出是无法从它们到达的(没有从节点到出口的路径),所以你随机选择一个并将其添加为psuedo-exit(就好像节点包含一个条件分支到出口,只是条件总是假的)并重新启动。这为你提供了一个后支配者树,但不一定是唯一的(因为你可以随意选择不同的节点来添加退出分支),但通常这并不重要。