From mboxrd@z Thu Jan 1 00:00:00 1970 Message-Id: <200207191809.TAA08184@cthulhu.dircon.co.uk> Subject: Re: [9fans] useful language extension, or no? In-Reply-To: <200207191541.g6JFfXMN025116@ducky.net> from Mike Haertel at "Jul 19, 2002 08:41:33 am" To: 9fans@cse.psu.edu From: Digby Tarvin MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Date: Fri, 19 Jul 2002 19:09:47 +0100 Topicbox-Message-UUID: d2db2c7a-eaca-11e9-9e20-41e7f4b1d025 Ah - I see! It hadn't realised that the scope rules now included that sort of nesting. When did that happen? I guess I am going to have to trade in my much loved, dog eared K&R for a book on standard C one of these days... Presumably I need something along the lines of #include int foo(int (*f)()) { (*f)(); } int main() { int g(){; } foo(g); } To see it used, producing: foo: pushl %ebp movl %esp,%ebp subl $20,%esp pushl %ebx movl 8(%ebp),%ebx call *%ebx .L2: movl -24(%ebp),%ebx movl %ebp,%esp popl %ebp ret Presumably %esp is the stack pointer, %ebp is the frame pointer, and %ebx is the a scratch register used for parameter passing and jumping through to get to the trampoline. Makes me curious about what the 'e' stands for - like I said, I am not an x86 expert... This seems to require the somewhat less than transparent calling sequence: main: pushl %ebp movl %esp,%ebp subl $40,%esp leal -28(%ebp),%edx leal 15(%edx),%eax andb $240,%al movl $g.6,%edx leal 10(%eax),%ecx subl %ecx,%edx movb $185,(%eax) movl %ebp,1(%eax) movb $233,5(%eax) movl %edx,6(%eax) addl $-12,%esp leal -28(%ebp),%edx leal 15(%edx),%eax andb $240,%al pushl %eax call foo addl $16,%esp .L3: movl %ebp,%esp popl %ebp ret Presumably $185 generates the instruction to load the frame pointer, and $233 creates the jump to the actual function. Thanks for the explanation. The level of knowledge on this list never ceases to impress me... Regards, DigbyT > In order to call a lexically scoped nested function, a caller needs > two pieces of information: > > 1. the actual address address of the code > > 2. a pointer to the stack frame for the containing function, > sometimes called the static chain pointer. > > A traditional C "pointer to function" is just (1) since there is no > containing function. > > In order to make "pointer to nested function" have the same > representation as "pointer to top level function", GCC creates a > small bit of trampline code on the stack that sets up (2), then > jumps to (1). Then when a pointer to the nested function is actually > needed, GCC passes out the pointer to the trampoline code. > > The trampoline isn't needed when the call to the nested function is a > direct call within the scope of the parent function--it's only needed > when the nested function is being called via a function pointer from an > unknown scope. So if you never take the address of a nested function, > GCC shouldn't generate any trampoline code. > > The alternative to the trampoline would be for "pointer to function" > to become a two-word object, or a pointer to a two-word object, with a > changed calling sequence in either case. This would be fine, the C > standard would certainly allow it, but it would be binary incompatible > with existing calling conventions in most systems. > -- Digby R. S. Tarvin digbyt@acm.org http://www.cthulhu.dircon.co.uk