Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83 (MC830713); site tjalk.UUCP Path: utzoo!linus!decvax!genrad!wjh12!harvard!seismo!mcvax!vu44!botter!tjalk!sater From: sater@tjalk.UUCP (Hans van Staveren) Newsgroups: net.lang.c Subject: Re: setjmp: read the manual(long article) Message-ID: <363@tjalk.UUCP> Date: Mon, 22-Oct-84 11:35:39 EDT Article-I.D.: tjalk.363 Posted: Mon Oct 22 11:35:39 1984 Date-Received: Tue, 23-Oct-84 06:02:31 EDT References: <1045@research.UUCP> <1735@sun.uucp> <914@opus.UUCP> Reply-To: sater@tjalk.UUCP (Hans van Staveren) Organization: VU Informatica, Amsterdam Lines: 189 Summary: In article <914@opus.UUCP> rcd@opus.UUCP (Dick Dunn) writes: >Regarding the setjmp/longjmp interaction with register variables... >dmr gave one approach and justified it on the basis of "correct" behavior. >A response... >> There's a good reason for doing it the other way: efficiency... > >Did I really miss something, or did someone just tell us that it is >reasonable to compromise correctness for efficiency? I have a tough time >with such compromises. > >>... >> We looked hard at this and decided to change the meaning of >> setjmp/longjmp (to the above) rather than having EVERY function save... > >The parent article goes on to describe problems with saving all the >registers on a 68000. In fact, there is a "whizzo" (his words) instruction >on the 68000 to save whatever set of registers you need, and you clearly >won't need to save all of them. Setjmp/longjmp and register variables Hans van Staveren Vrije Universiteit Amsterdam, Holland There has been some discussion going on in net.lang.c about the semantics of setjmp/longjmp in combination with register variables. Let me first give a short introduction to the problem for those of you caught napping during the start of the discussion: #include jmp_buf env; main() { register foo; int bar; foo=1;bar=2; if (setjmp(env)!=0) { printf("Foo=%d,bar=%d\n",foo,bar); exit(0); } foo=3;bar=4; subr(); abort(); /* cannot happen */ } subr() { longjmp(env,1); } The preceeding program when executed on our 4.1BSD Sys- tem gave as output: Foo=1,bar=4 How come? The setjmp routine on our system saves *all* registers, and the longjmp call reloads them all. This includes all register variables with the effect that stackvariables after the longjmp have values as of the time longjmp was called, while register variables have values as of the time setjmp was called. - 2 - Obviously this is incorrect behaviour. Whatever the motive may be for this implementation, it will give strange results when porting software. So as a user I will give cries from outrage when I encounter this: "Those %$##'&'(& compiler writers, ...." Now the problem as seen from the compiler writer's point of view: In general the word register in front of a declaration is a hint to the compiler that there may be some advantage in putting the variable in a register. Now an optimizing compiler might have different ideas, it might see other variables more fit to put in registers, it might notice that the overhead cost of saving and restoring the register is more than the saving in its use, etc. So the general problem boils down to this: Suppose there is a number of registers, of different sizes and pro- perties, and a number of variables with different sizes and usage statistics, what is per procedure/function the best assignment of variables to registers. This is already a hard problem to solve. The best solution to this problem will usually use a different set of registers per procedure, and it is most efficient to save only those registers that are actually used in this procedure. At the beginning of the procedure the registers are saved, at the end they are restored. After the compiler writer has finished his task, he will start implementing the library procedures, and what does he see in chapter III? "Those %$&%%('' language designers, ...." they put the non-local goto in the library instead of the language, horrors! Now to implement setjmp/longjmp as the users want it, there must be some way to put the registers back to their proper values, if possi- ble without changing all those closely thought out optimum decisions for those functions that don't use that devilish pair. Solution 1, PDP 11, Unix V7: Save exactly the same registers every function call, csv/cret style. This is not optimum, but what the heck, there are only three usable registers anyhow. At longjmp time, just walk the stack and put them back. (Rhyme) Solution 2, VAX 11, 4.1BSD: Save all registers at setjmp time, put them back at longjmp time. Just slightly incorrect, but what the heck, who cares about the value of some locals. Solution 3, VAX 11, 4.xBSD (don't know really): Walk the stack at longjmp time, finding all those fancy masks between the dozens of longwords in each stackframe, and restore the right value. Lucky to have such a luxury - 3 - call mechanism he? It just costs more, but what the heck, just upgrade to a 785 :-) General solution, all machines, Amsterdam Compiler Kit: Hold on to your chair, under 18 stop reading, compiler writer's porno coming up. All those youngsters gone? Hey, you there kid, hiding in the back, out with you!! Well here it is. Have the C-frontend recognize the word setjmp. In a function containing a call to setjmp save all registers, use none, and at the end restore them all. At longjmp time just close your eyes and jump, no registers need be restored except the frame pointer, stack pointer and program counter. This means that functions not using setjmp/longjmp are not bothered, in general the compiler can continue its fancy register optimizations and all programs will run correct. We would be glad if some magician out there would find a way to do it without having the compiler know the word setjmp, and without having extra cost for those functions not using it. However, we don't think it is possible. C is a language that has evolved, unfortunately the non-local goto has never been tackled by the designers, and we feel our solution is the best that can be done under the cir- cumstances. Hope I have been a help to the discussion, if you disagree with our views do not hesitate to reply, flames reduce the costs of heating :-) !! -- Hans van Staveren, Vrije Universiteit Amsterdam ..!mcvax!vu44!sater