[comp.lang.misc] setjmp

pmk@craycos.com (Peter Klausler) (03/23/90)

>> Unrestrained pointers are the data structures equivalent of
>> uncontrolled GOTOs. A language like C that lets you do anything
>> in the world that you please with pointers is very similar to a
>> language like BASIC that lets you arbitrarily jump to anyplace you
>> want to in your code.
>C *is* a language that allows you to jump anywhere you want in your code.
>By using longjmp and goto you have nearly as much freedom as you do in
>Basic (or, more, assembler). If only you could assign gotos, it'd be
>perfect [1]. Think of it as a very portable very high-level assembler [2].

It's this kind of freedom of expression, though, that severely constricts many
analyses an optimizing compiler must perform. Setjmp is particularly messy,
since it allows flow of control in a function that isn't explicit. As an
example, consider:

	#include <setjmp.h>
	f (void) {
		jmp_buf jb;
		if (setjmp (jb))		/*1*/
			goto dijkstra;
		while (1)
			g ();
		j ();				/*2*/
	dijkstra: ;
	}

Ordinarily, I could throw line /*2*/ away, since there's no normal flow of
control in f() that could arrive there. In order to process this program
correctly, my compiler needs to know that setjmp() is special, and assume
that control-flow arcs exist from every other function call to the point of
return from setjmp at /*1*/. This yields a very messy flow-graph and prevents
common optimizing transformations.

The ANSI C standard attempts to simplify the situation with its proviso that
only volatile objects will survive a longjmp, but this doesn't help much in
the case of flow-graph construction, and volatile variables completely cripple
optimization anyway.

Fortran has similar problems, with its ASSIGN and assigned GOTO statements,
but the '78 standard has nice rules that restrict ASSIGNs to scalar variables,
and prohibit the copying of ASSIGNed variables to one another. Although we must
assume flow-of-control from each assigned GOTO to every ASSIGNed label, this
tends to be less messy. The programmer even has the ability to restrict the
range of potential targets of the GOTO. I'm not saying the Fortran is superior
to C in any aesthetic sense (sheath your swords), but it's sure nicer to
optimize and parallelize. This is just one example, and not a particularly
good one, since ASSIGNs and setjmps are pretty rare; pointer arguments and
their aliasing problems are nastier by far.

So, if you're using an optimizing compiler, keep your setjmp calls out of
time-critical routines; we'll both be happier.

-Peter Klausler, writing compilers at Cray Computer Corp. in Colorado Springs

pmk@craycos.com (Peter Klausler) (03/23/90)

OOPS! My C code example in a previous posting was quite incorrect; the call
to j() is dead in f() irrespective of the presence of the setjmp. SORRY!

What I MEANT to show was that the presence of setjmp()s and function calls
in a C function implies flow-of-control that isn't explicit in the syntax of
the program. But my example in which this could cause problems in an optimizer
was wrong.

My apologies to all confused by this.

-Peter Klausler @ Cray Computer

jamiller@hpcupt1.HP.COM (Jim Miller) (03/24/90)

>Which is a quite reasonable argument. Pointer-safe languages generally
>require garbage-collected heaps, which means size. So I can see that
>a language like C which is required to run on Machines With Tiny
>Brains will not be "safe" in that respect.
>
>But, this leaves two issues open: (i) why C has such an idiotic
>syntax, arbitrary type-checking, lax compile-time checks and so on,
>and (ii) why people think that C's features provide "power" in
>general-purpose programming. Point (i) is an accident of history.
>Point (ii) still intrigues me.
>
>		Nick.

IMHO, IMHO, IMHO, . . .

("~>" means "approximately said")

~>(i) why C has such:
~>   1) idiotic syntax
in general, I don't think it does (IMHO).  If you are regarding
the crypticness, then I think it is less cryptic than APL, and
a whole lot more useful than most of the alternatives.  I really love
"+=" and "++".  Some "problems" (my favorites are "==" and switch's "break"),
but in the whole I'm a C lover (but don't tell by wife, pardon, significant
other).

~>   2) arbitrary type-checking
Ok, Ok, I think that lint should to a better job.  Especially with
typedefs.

~>   3) lax compile-time checks
I define the compiler as "cc" + "lint".  If you want checks, use lint, if
you want code, use cc.  Among other things, this makes cc FAST.  It
is not unusual for all the code on a machine to be re-make'd overnight
when a new version of the OS comes out (at least we had to do it
sometimes with BSD).  With most languages it might have been a week long
effort.  I know of customers which *will not* recompile, due to the
impact on the time their operation -- one just better find a better way.
They are not using C.

~>   4) and so on.
~>(ii) why people think that C's features provide "power"
IMHO,  C is not a high level language, but a powerful, & semi portable,
assembler.  With C one can usually get more direct access to OS and
machine features than are available with most alternates.
Speed freaks like having a good understanding of the code that
is emitted, and C seems to fit the bill better than many other languages,
though this statement could easily start a religious war (nix nix IMHO IMHO)


    jim - i'm not even sure these are my opinions - miller