Path: utzoo!attcan!uunet!zephyr.ens.tek.com!uw-beaver!mit-eddie!bloom-beacon!daemon From: scs@adam.mit.edu (Steve Summit) Newsgroups: comp.std.c Subject: Re: Reality check (Was Re: prototypes required ?) Message-ID: <1990Oct19.222246.23253@athena.mit.edu> Date: 19 Oct 90 22:22:46 GMT References: <1061@dg.dg.com> <1171@dms.UUCP> Sender: daemon@athena.mit.edu (Mr Background) Reply-To: scs@adam.mit.edu (Steve Summit) Organization: Thermal Technologies, Inc. Lines: 51 In article <1171@dms.UUCP> albaugh@dms.UUCP (Mike Albaugh) writes: >From article <1061@dg.dg.com>, by lewine@dg-rtp.dg.com (Donald Lewine): >> Well, if the implementation uses one calling sequence (say, with >> arguments in registers) for functions with a known number of arguments >> and uses a different calling sequence (say, with arguments on the >> stack) for functions with a variable number of arguments, the >> generated code will not call the library correctly unless the function >> is correctly declared. > >In practice I believe a compiler >writer will do as I did (in a re-target of GCC) > a) Have the means for detecting "varargsish" stuff, like taking > the address of a parameter. > b) "forcing" that parameter and any following out of the regs > and onto the stack in the "prologue" of the called routine. > It is darn hard (not impossible) to "fool" this approach, and >not too hard to implement it (I hacked my prologue generation in GCC >for a machine with the first five params passed in regs). Note that another optimization which the standard now allows, which I expect compiler writers to begin taking advantage of, is to use a calling sequence which pops arguments in the callee for non-varargs functions. A frequent complaint about C by the blizzard-efficiency aficionados is that the former implicit requirement that all functions might be varargs (so that printf could exist at all) meant that the caller had to pop arguments (since it knew how many there were). This approach bloated code size a bit (the stack adjustment to pop the arguments happened at each point of call, rather than once in the function implementation) and precluded the use of special-purpose pop-and-return instructions provided by some architectures. A congenial implementation that tries to use this optimization but still allow old, now-incorrect code (that calls varargs functions without prototypes in scope) to work cannot do so, because even if it "recognizes" a varargs function implementation and decides not to pop the arguments within it, there is still no way for each call to be recognized (without, of course, prototypes in scope) so that the arguments can be popped there. I'm all for backwards compatibility when I can get away with it, and it's too bad that old code that calls printf without #including is now not-strictly-conforming, but (as none other than Dennis Ritchie has pointed out) a large former wart in the language was that variadic functions were not allowed, yet printf existed. The standard fixes this, at the cost of requiring prototyopes for variadic functions. (Fortunately for us old-style aficionados, they are nowhere else required, yet.) Steve Summit scs@adam.mit.edu