Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!burl!ulysses!bellcore!decvax!decwrl!pyramid!pesnta!hplabs!qantel!lll-lcc!lll-crg!topaz!harvard!seismo!umcp-cs!chris From: chris@umcp-cs.UUCP Newsgroups: net.lang.c,net.unix-wizards Subject: arguments in registers Message-ID: <1205@umcp-cs.UUCP> Date: Sat, 26-Apr-86 23:41:39 EDT Article-I.D.: umcp-cs.1205 Posted: Sat Apr 26 23:41:39 1986 Date-Received: Thu, 1-May-86 03:31:28 EDT References: <272@vecpyr.UUCP> <5302@alice.uUCp> <792@ccird2.UUCP> <155@cbmvax.cbmvax.cbm.UUCP> Reply-To: chris@maryland.UUCP (Chris Torek) Organization: University of Maryland, Dept. of Computer Sci. Lines: 104 Xref: watmath net.lang.c:8756 net.unix-wizards:17839 In article <155@cbmvax.cbmvax.cbm.UUCP> grr@cbmvax.UUCP (George Robbins) writes: >[Passing arguments in registers] would be fine if C had nested >procedures or inlines or something, but a disaster otherwise. In fact, a compiler is free to optimise any function into inline code, so long as it provides a `regular' version of those that can be called from external modules. For example, given the following as a complete C module, the compiler can eliminate the routine `local1' completely, but not `local2' nor `global': static int local1() { static int count; return (++count); } static void local2() { void ext0(), ext1(); switch (local1()) { case 0: ext0(); break; case 1: ext1(); break; } } void global(ppfv) void (**pfv)(); { *pfv = local2; } [Aside to Joe Yao: Hello! I just used `M' in vi again.] Here the routine `local1' is not accessible outside this module, so a compiler may elide it completely and replace the call in `local2' with a direct reference to an unnamed static variable. However, `local2' is externally accessible, since global() (which is itself reachable) sets the supplied pointer to point at local2. (A really clever compiler will discover unreachable local functions and remove them, which may reveal more unreachable locals.) One can also come up with examples wherein a good compiler might provide a function externally yet also expand calls to it in line within that module: int do_the_obvious(a, b) int a, b; { return (a > b ? a : b); } void something() { register int *p, *q; ... otherproc(do_the_obvious(*p++, *q++)); ... } There is no reason a compiler cannot pretend the call to `do_the_obvious' was a built-in `max' function, and generate something like this Vax code: _do_the_obvious: .globl _do_the_obvious .word 0 # only scratch regs used movq 4(ap),r0 # get a and b into r0 and r1 # assume return a cmpl r0,r1 # if a > b, skip this: bgtr 0f movl r1,r0 # return b 0: ret _something: .globl _something ... movl (r11)+,r0 # get *p++ movl (r10)+,r1 # get *q++ cmpl r0,r1 # if the value from *p is greater bgtr 0f # than that from *q, skip this: movl r1,r0 # move the from-*q value to r0 0: pushl r0 # result onto stack calls $1,_otherproc # go run otherproc ... Incidentally, I have not seen any optimising C compilers myself; are there any available that would have done what I did above? (Just curious.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu