Next: Gimplification pass, Up: Passes
语言前端只被调用一次,通过lang_hooks.parse_file
,用来解析整个输入。语言前端可以使用任何被认为合适的中间语言表示。C前端使用了GENERIC树,以及在c-common.def中定义的(double handful of)语言特定的树代码。Fortran前端使用了完全不同的私有表示。
在某个地方,前端必须将其使用的表示转换为编译器中语言独立的部分能够理解的表示。目前的实现采用了两种形式。C前端在函数编译完之前,手动的对每个函数调用gimplifier,并且使用gimplifier回调函数将语言特定的树代码直接转换为GIMPLE。Fortran前端将私有表示转换为 GENERIC,之后当函数编译完时,再降低为GIMPLE。选择哪种途径可能取决于GENERIC(及其扩展)是否能够很好的匹配源语言,以及是否需要解析数据结构。
BUG:Gimplification必须在nested function lowering之前进行,并且nested function lowering必须在将数据传给cgraph之前,由前端完成。
TODO:Cgraph应该控制nested function lowering。并且只会在确定最外层函数被使用时才调用。
TODO:Cgraph需要一个gimplify_function回调函数。并且在下列情况下会被调用:(1)确定函数被使用,(2)为了兑现用户指定的警告选项,需要多次的编译,(3)语言本身表明了在gimplification进行前,语义分析会不完整。嗯。。。听起来有点过度复杂。或许我们应该总是进行前端的gimplify;大多数情况,这只是一个函数调用。
前端需要将所有函数的定义和顶层的声明传给中端,以至于它们能被编译和生成目标文件。对于一个简单的程序语言,顶层的每个声明和定义都能找到,因此这样做非常方便。另外,对于生成函数代码和生成完全的调试信息,也有差别。对于函数代码,唯一必须的是将函数和数据定义传给中端。对于完全的调试信息,函数,数据和类型的声明也都需要被传递。
任何情况下,如果前端需要每个完全的顶层函数或数据声明,则每个数据定义应该传给rest_of_decl_compilation
。每个完全的类型定义应该传给rest_of_type_compilation
。每个函数定义应给传给cgraph_finalize_function
。
TODO: I know rest_of_compilation currently has all sorts of RTL generation semantics. I plan to move all code generation bits (both Tree and RTL) to compile_function. Should we hide cgraph from the front ends and move back to rest_of_compilation as the official interface? Possibly we should rename all three interfaces such that the names match in some meaningful way and that is more descriptive than "rest_of".
中端根据自己的选择,将会立即生成函数和数据的定义,或者放入队列中以便后面的处理。