[comp.lang.c++] cfront and inline

bart@videovax.tv.tek.com (Bart Massey) (03/10/90)

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.

shap@delrey.sgi.com (Jonathan Shapiro) (03/11/90)

In article <5756@videovax.tv.tek.com> bart@videovax.tv.tek.com (Bart Massey) writes:
>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.

Harumph. Andy Koenig was kind enough to point out the error of my
statement.  It isn't that the expressions can't be rewritten - it's
that they cannot be rewritten easily.  In fact, it's rather
complicated.

Embarassing - a moment's thought would have let me figure that out for
myself.

Jon Shapiro