Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!tut.cis.ohio-state.edu!zaphod.mps.ohio-state.edu!uakari.primate.wisc.edu!uflorida!travis!tom From: tom@ssd.csd.harris.com (Tom Horsley) Newsgroups: comp.lang.c Subject: Re: Ambiguity in definition of setjmp/longjmp makes them much less useful Message-ID: Date: 8 Oct 90 11:18:02 GMT References: <1597@redsox.bsw.com> <1990Oct8.031745.28651@zoo.toronto.edu> Sender: news@travis.csd.harris.com Organization: Harris Computer Systems Division Lines: 59 In-reply-to: henry@zoo.toronto.edu's message of 8 Oct 90 03:17:45 GMT >>>>> Regarding Re: Ambiguity in definition of setjmp/longjmp makes them much less useful; henry@zoo.toronto.edu (Henry Spencer) adds: henry> Some implementations restore all the registers to the way they were henry> when the *setjmp* was called, but this is often unsatisfactory in henry> general and can be very unsatisfactory when compilers really start henry> playing games with register usage. Wrong! With compilers that play register games restoring the registers as they were at the time of the setjmp is the ONLY implementation that works at all (unless setjmp is recognized as a special construct by the compiler, which I agree is the best way). In any optimizing compiler which is likely to do things like keep common sub-expressions in registers, the following simple example shows the requirement for restoring the registers as of the setjmp() call: { ... /* compiler computes a CSE and keeps it in register 47 */ if (setjmp(...) != 0) { /* compiler references the CSE in register 47 */ } /* compiler makes last reference to CSE in register 47 */ ... /* compiler now has something totally different in register 47 */ longjmp(...) } (In the above example register 47 is assumed to be a register that is not normally destroyed by a function call). If you were to unwind the stack and restore the registers as of the longjmp() call, you would get back to the setjmp() with random gibberish in the register the code generator expected to contain a CSE value. Personally, I believe that compilers should support setjmp() as a special construct - simply making might-goto arcs from every other function call to a point immediately following any setjmp() calls would add enough information to the flow graph for an optimizing compiler to recognize the funny lifetimes that registers might have and volatile would only be needed for variables that interact with signal handling code (since a signal can happen anywhere in the program, not just at a function call). Until the day that compilers properly support setjmp() however, the only implementation of setjmp() that stands a chance of interacting correctly with an optimizing compiler is one that restores the registers as of the setjmp() call. Unfortunately, this also means that the only user code that stands a chance of interacting correctly with an optimizing compiler is code that correctly declares all variables volatile where necessary. Since the phrase "where necessary" is difficult (if not impossible) for an ordinary mortal to figure out, the obviously best solution is to fix compilers to special case setjmp(). -- ====================================================================== domain: tahorsley@csd.harris.com USMail: Tom Horsley uucp: ...!uunet!hcx1!tahorsley 511 Kingbird Circle Delray Beach, FL 33444 +==== Censorship is the only form of Obscenity ======================+ | (Wait, I forgot government tobacco subsidies...) | +====================================================================+