Computer science 程序的控制流图

Computer science 程序的控制流图,computer-science,compiler-theory,control-flow,compiler-construction,control-flow-graph,Computer Science,Compiler Theory,Control Flow,Compiler Construction,Control Flow Graph,我现在正在学习一个编译器类,为了实现优化,我们必须构建一个CFG。有一件事我搞不清楚,一个项目有多少CFG?我所看到的每个示例似乎都是一个简单代码段的CGF。所以,如果你有一个有三个功能的程序。每个函数都有一个单独的CFG,还是整个程序都有一个大的CFG?好吧,你可以为每个函数构造一个CFG,然后——如果需要的话——将它们组合成一个完整的CFG。然而,整个程序的CFG可能相当大,因此它们通常不能像示例那样正常工作。每个函数的CFG都是通过调用站点连接的。如果一个函数调用另一个函数,例如: 0

我现在正在学习一个编译器类,为了实现优化,我们必须构建一个CFG。有一件事我搞不清楚,一个项目有多少CFG?我所看到的每个示例似乎都是一个简单代码段的CGF。所以,如果你有一个有三个功能的程序。每个函数都有一个单独的CFG,还是整个程序都有一个大的CFG?

好吧,你可以为每个函数构造一个CFG,然后——如果需要的话——将它们组合成一个完整的CFG。然而,整个程序的CFG可能相当大,因此它们通常不能像示例那样正常工作。

每个函数的CFG都是通过调用站点连接的。如果一个函数调用另一个函数,例如:

0  void foo() { /* do stuff */ }
1  void bar() { /* do stuff */ }
2
3  void baz() {
4     foo();  // Callsite for foo. Control transfers to foo, then foo returns here.
5     bar();  // Callsite for bar. Control transfers to bar, then bar returns here.
6  }
然后,
baz
的控制图将包含一条边,该边指向
foo
的图。同样,由于
foo
最终将返回到
baz
(以及它可能从何处被调用),因此
foo
图形的末尾将有一条边回到
baz
中调用
foo
后的语句。在这里,下一条语句是对第5行上的
bar
的调用。在这一点上,从
bar
调用站点到
bar
的CFG有一条边,从
bar
中的退出点到
baz
的末尾有一条线

基本上,您需要考虑的是“接下来执行什么代码”。这将告诉您边在控制图中的位置。函数调用将控制权转移到函数返回之前,这意味着从调用站点到函数CFG的边缘,然后再返回


注意,并非所有完整程序CFG都是连通图。如果您正在分析的程序中有,那么它将是完整CFG中自己未连接的部分。e、 g.如果在上面的示例中调用
bar
,那么
bar
将有自己的图形在旁边,而
baz
foo
将通过边连接。

这对程序员会更好吗?哼哼。。。我想有一件事让我困惑,那就是在课堂上,教授说基本块应该只有一个入边,最多两个出边(一个到下一个块,第二个到标签,如果有分支的话)。因此,如果我连接不同的图形,那么函数的第一个块可以有多个in边,最后一个黑色块可以有多个out边。有什么想法吗?你会说1边入2边出语句是错误的吗?基本块通常的定义方式是,它们只有一个入口点,但可以有多条边指向入口点。你不能跳到中间,因为BB不是这样定义的。为了便于分析,您需要设置块,以便在执行块中的任何语句时,都会执行块中的所有语句。只要跳转到第一条语句,块中仍可以有多条边。对于可以从多个位置调用的函数和循环条目,都会发生这种情况,如果循环尚未完成,则可以从循环之前的代码或循环末尾的分支输入块。你通常把从循环结束到开始的那条边称为后边。至于出度,你通常只在基本块中有两条边。如果你有一个三向分支指令,我想你可以有更多的外边缘,但我想不出一个架构有这样的想法。也许你的教授现在只是想让事情简单化。在网上找到控制流图的例子相当容易——只需谷歌就可以了。请注意此处的输入边数(>1):