Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!rice!uw-beaver!zephyr.ens.tek.com!tekfdi!videovax!bart From: bart@videovax.tv.tek.com (Bart Massey) Newsgroups: comp.lang.c++ Subject: cfront and inline (LONG) (Re: Why doesn't inline always work?) Message-ID: <5756@videovax.tv.tek.com> Date: 10 Mar 90 01:20:18 GMT References: <540@janus.Quotron.com> <5041@odin.SGI.COM> Reply-To: bart@videovax.tv.tek.com (Bart Massey) Organization: Tektronix TV Measurement Systems, Beaverton OR Lines: 83 In article <5041@odin.SGI.COM> shap@delrey.sgi.com (Jonathan Shapiro) writes: > The problem is that in order to perform inlining, cfront turns the > function into a single expression (remember that the function needs to > return a result, so it needs to be an expression). The stuff in parentheses above just isn't true. And this is exactly the kind of cfront behavior at the heart of my philosophical disagreement with Andrew Koenig over whether cfront is a "compiler which generates C as its output" (my interpretation of his claim) or a "preprocessor which massages C++ code into still-human-readable C code" (my claim). Take the following example C++ code: ----------------------- inline int il( int x, y ) { int i; for( i = x; i < y; i++ ) x += y; return x; } main() { int i, x, y; /* ... */ x = 3; y = 5; y = il( x, y ); cout << x << " " << y; } ----------------------- A "compiler" such as G++ doesn't normally have the luxury of outputting expressions in its code generator. Nonetheless, it still manages to inline the call to il above, without breaking any semantics anywhere! How can we generate appropriate C code for this case? It might look something like... ----------------------- int main_i, main_x, main_y, il_x, il_y, il_i; /* ... */ main_x = 3; main_y = 5; il_x = main_x; il_y = main_y; il_i = il_x; il_loop: if( il_i >= il_y ) goto il_loop_end; il_x += il_y; goto il_loop; il_loop_end: main_y = il_x; /* lots of calls to functions with funny intermediates to print main_x and main_y */ ----------------------- There are several things to note about this code. For example, it is currently unoptimized -- the GNU optimizer would now proceed to throw most of it away, since main_x and main_y have known constant values at the start of this loop. Also note that the loop construct has been translated to "goto"s, by analogy with the "jump"s of most assembly languages. I know of no reasons not to do this, except possible minor optimizations in the assembly code output by the subsequent C compiler, and human readability. At any rate, it's straightforward for a good optimizer to translate this structure back into "while"s when appropriate. Note that cfront, even if it could inline the above, would presumably miss the optimization in the above case, since it would fail to notice the constant propagation. On the other hand, a good C compiler would catch it during its subsequent compilation -- unfortunately, this means that all the work of compilation and optimization is done twice. The fundamental problem with inlining is one of aliasing -- keeping things in the appropriate namespace. This is clearly a solvable problem, in the sense that C is as powerful a language as assembly language, and compilers to assembly language routinely solve the problem. Bart CAVEAT: I haven't compiled any of the above code -- it's probably all slightly broken! It is intended only to illustrate some ideas.