From: MERC::"uunet!CRVAX.SRI.COM!RELAY-INFO-VAX" 28-JAN-1993 08:28:07.88 To: INFO-VAX@kl.sri.com CC: Subj: Re: VAXC divide problems (V3.2) >>Gruesome details are available in the CRTL portion of the VMS >>listings. This ugly violation of the VMS Procedure Calling Standard > In what way is this a violation of the Procedure Calling Standard? > It is perfectly legitimate for a procedure to reserve space on the > stack for data of local interest; nothing says that that space has > to correspond to variables visible to the user. That won't wash. The violation is in VAXC$ESTABLISH, which will clobber the top of your stack if you haven't allocated the undocumented hidden variable for it. It mungs its _caller's_ stack; that's completely different from extra stack space being used by the current procedure. Alternatively, your own code can clobber the saved handler address, Your own code cannot touch the saved handler address unless it uses and invalid pointer. It could just as easily clobber the handler address at (FP). which in turn can result in an ACCVIO inside VAXCRTL for non-longjmp conditions. The documentation for VAXC$ESTABLISH states that it is only usable from code compiled by VAX C because that particular compiler allocates stack space for its use, but it still violates the procedure calling standard. It is perfectly legitimate for a procedure in a language support RTL to make assumptions about the environment compiled code will set up for it. Try calling one of the routines that implements formatted I/O in FORTRAN without setting up the appropriate environment. LIB$ESTABLISH also modifies its caller's stack frame. In fact, the only difference between LIB$ESTABLISH and VAXC$ESTABLISH is in the addressing mode of one instruction. Do you also claim that LIB$ESTABLISH is in violation of the Standard? In many languages, you NEVER call language support RTL routines directly; the compiler generates all the calls. In C, because of its extreme low level, just about all calls have to be visible to the user. Calling internal FORTRAN support routines is not supported, except in code generated by the FORTRAN compiler. (That's not to say it can't be made to work.) Calling VAXC$ESTABLISH is not supported outside of code generated by the VAX C compiler (although again it can be made to work). I see no signi- ficant difference, and I see no violation of the calling standard. Would it have made you happier if, instead of a documented VAXC$ESTABLISH routine, VAX C had defined a new statement, say establish , which turned into just such a call? > It is perfectly permissible for a condition > handler to make calls to other procedures, basing its choices on > locally available data. That's just what this condition handler is > doing; it's no different, in principle, from having a local variable > that indicates what you were trying to do, and a condition handler > that checks that variable to decide what furtheraction to take. That would be true if such usage didn't interfere with user code. Try calling VAXC$ESTABLISH from code compiled by some other compiler sometime (recent releases of GCC excepted), then tell me that it isn't violating the procedure calling standard. Try calling the Ada RTL routines that manage tasking from some code written in some other language. In fact, I'll bet that if you name any language RTL, I can find some routine in it that, if called from another language, will cause quick failure. So? As for GCC: It's really too damn bad for GCC that, when it tries to make use of the VAX C RTL, it has to play by the rules. The VAX C RTL was written to support the VAX C compiler. It owes absolutely nothing to the writers of GCC. >>is for setjmp/longjmp handling, and is inherited from the Pascal >>compiler of all places! ... > Actually, I think it's the BASIC compiler (which had to pull the > same kind of trick to implement its user error handling). My post was not based on speculation; check the source listings. They took the implementation from Pascal's GOTO handler. Perhaps the Pascal implementation was derived from BASIC's, but if so, the C code doesn't mention it. What can I tell you; my understanding was that the technique of using stack unwinding as it is done in VAX C was first developed for BASIC. Good solutions to hard problems get re-used. BASIC's needs are somewhat different, so I can't say I'm shocked that the actual code came from Pascal. Look, let's back off and look at the bigger picture for a moment. The C language brings with it two features - well, one is just a common abuse of the language - that are in and of themselves incompatible with the VAX Procedure Calling standard: 1. Functions view their arguments as a block of successive values which they can step through - and modify. Without the overhead of copying values around, this results in generated code that modifies the values pointed to by AP, a practice once strictly prohibited by the Calling Standard: That data belongs exclusively to the caller. A field test version of VAX C (I think V3.0) tried to obey the calling standard strictly: When the address of any argument was taken, the argument was re-bound to a new stack location, and the value passed in the argument block was copied on procedure entry. Such an implementation is completely consistent with both K&R and ANSI C, as well as with the Standard. However, so many customers objected that it broke their code that the change was backed out before the final version of the compiler and never tried again. Instead, VAX C was given a waiver from this requirement of the Standard. It causes grief for mixed FORTRAN/C programs to this day. 2. setjmp/longjmp simply cannot be implemented strictly within the Calling Standard. The old "just pop the stack pointer back to where it was" approach is absolutely a violation. Rather than bitch about the "horrible" way this is done, would you like to suggest an implementation that will (a) conform to the ANSI definition; (b) conform to the Procedure Calling Standard; (c) behave rationally in a mixed language environ- ment, where there may be stack frames for code created by several different compilers arbitrarily mixed on the stack between the frame where the longjmp takes place and the frame it will end up in? If you can, I, for one, would be quite interested in seeing it. -- Jerry