The following example C code and disassembly is compiled by gcc 3.4.3, for i686. It uses two different invariants for what the value of a static link is. Everywhere inside P, static link values are consistently the same as base pointer (%ebp) register values for the same activation record. A static link value is generated at 4c: in P, and used at 22: in PInner2 and c: in PInner1.
Everywhere inside similar function Q, static link values consistently point 8 bytes higher than where the base register points. A value is generated at d9: in Q and used at 7a: in Qinner2 and 64: in QInner1. From the examples I have looked at, it looks like it is correct translation, and, expect for seeming strangeness, is not a problem for execution. However, I am working on an extended gdb-derived debugger that works, in part, with code produced by a gcc-derived code generator for Modula-3. So far, I can't find out, in the debugger, which invariant is in use. I have the debugger correctly both generating and using static links when evaluating user-typed expressions, using the first invariant. I could easily change it to use the second invariant, but obviously, that would fix some cases and break others. Is there a compelling reason for this difference? If not, I would like to make it all use invariant one. Also, does anybody know where in gcc this difference is happening? I poked around in the source for a couple of hours, but didn't see anything obvious. BTW, this is using stabs. I know that is not very complete, but it would be a lot more work than I want to do to change it. ----------------------------------------------------------------------------- typedef int ( * PFuncT ) ( int F ); int G2; int P ( int PF ) { int PInner1 ( int PInner1F ) { return PF + PInner1F; } /* PInner1 */ int PInner2 ( int PInner2F ) { G2 = PF; return PInner1 ( PInner2F ); } /* PInner2 */ return PInner2 ( PF + 3 ); } /* P */ int Q ( int QF ) { int QInner1 ( int QInner1F ) { return QF + QInner1F; } /* QInner1 */ int QInner2 ( int QInner2F, PFuncT QInner2FProc ) { G2 = QF; return QInner2FProc ( QInner2F ); } /* QInner2 */ return QInner2 ( QF + 3 , QInner1 ); } /* Q */ int main ( ) { P ( 33 ); Q ( 13 ); } /* main */ ------------------------------------------------------------------------------ StaticStrange2.o: file format elf32-i386 Disassembly of section .text: 00000000 <PInner1.0>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 83 ec 04 sub $0x4,%esp 6: 89 4d fc mov %ecx,0xfffffffc(%ebp) 9: 8b 4d fc mov 0xfffffffc(%ebp),%ecx c: 8b 51 fc mov 0xfffffffc(%ecx),%edx f: 8b 45 08 mov 0x8(%ebp),%eax 12: 03 02 add (%edx),%eax 14: c9 leave 15: c3 ret 00000016 <PInner2.1>: 16: 55 push %ebp 17: 89 e5 mov %esp,%ebp 19: 83 ec 04 sub $0x4,%esp 1c: 89 4d fc mov %ecx,0xfffffffc(%ebp) 1f: 8b 4d fc mov 0xfffffffc(%ebp),%ecx 22: 8b 41 fc mov 0xfffffffc(%ecx),%eax 25: 8b 00 mov (%eax),%eax 27: a3 00 00 00 00 mov %eax,0x0 2c: ff 75 08 pushl 0x8(%ebp) 2f: e8 cc ff ff ff call 0 <PInner1.0> 34: 83 c4 04 add $0x4,%esp 37: c9 leave 38: c3 ret 00000039 <P>: 39: 55 push %ebp 3a: 89 e5 mov %esp,%ebp 3c: 83 ec 04 sub $0x4,%esp 3f: 8d 45 08 lea 0x8(%ebp),%eax 42: 89 45 fc mov %eax,0xfffffffc(%ebp) 45: 8b 45 08 mov 0x8(%ebp),%eax 48: 83 c0 03 add $0x3,%eax 4b: 50 push %eax 4c: 89 e9 mov %ebp,%ecx 4e: e8 c3 ff ff ff call 16 <PInner2.1> 53: 83 c4 04 add $0x4,%esp 56: c9 leave 57: c3 ret 00000058 <QInner1.2>: 58: 55 push %ebp 59: 89 e5 mov %esp,%ebp 5b: 83 ec 04 sub $0x4,%esp 5e: 89 4d fc mov %ecx,0xfffffffc(%ebp) 61: 8b 4d fc mov 0xfffffffc(%ebp),%ecx 64: 8b 51 fc mov 0xfffffffc(%ecx),%edx 67: 8b 45 08 mov 0x8(%ebp),%eax 6a: 03 02 add (%edx),%eax 6c: c9 leave 6d: c3 ret 0000006e <QInner2.3>: 6e: 55 push %ebp 6f: 89 e5 mov %esp,%ebp 71: 83 ec 08 sub $0x8,%esp 74: 89 4d fc mov %ecx,0xfffffffc(%ebp) 77: 8b 4d fc mov 0xfffffffc(%ebp),%ecx 7a: 8b 41 fc mov 0xfffffffc(%ecx),%eax 7d: 8b 00 mov (%eax),%eax 7f: a3 00 00 00 00 mov %eax,0x0 84: 83 ec 0c sub $0xc,%esp 87: ff 75 08 pushl 0x8(%ebp) 8a: 8b 45 0c mov 0xc(%ebp),%eax 8d: ff d0 call *%eax 8f: 83 c4 10 add $0x10,%esp 92: c9 leave 93: c3 ret 00000094 <Q>: 94: 55 push %ebp 95: 89 e5 mov %esp,%ebp 97: 83 ec 18 sub $0x18,%esp 9a: 8d 45 08 lea 0x8(%ebp),%eax 9d: 89 45 f4 mov %eax,0xfffffff4(%ebp) a0: 8d 45 e8 lea 0xffffffe8(%ebp),%eax a3: 83 c0 00 add $0x0,%eax a6: 80 e4 ff and $0xff,%ah a9: b9 58 00 00 00 mov $0x58,%ecx ae: 8d 50 0a lea 0xa(%eax),%edx b1: 29 d1 sub %edx,%ecx b3: 89 ca mov %ecx,%edx b5: c6 00 b9 movb $0xb9,(%eax) b8: 8d 4d f8 lea 0xfffffff8(%ebp),%ecx bb: 89 48 01 mov %ecx,0x1(%eax) be: c6 40 05 e9 movb $0xe9,0x5(%eax) c2: 89 50 06 mov %edx,0x6(%eax) c5: 83 ec 08 sub $0x8,%esp c8: 8d 45 e8 lea 0xffffffe8(%ebp),%eax cb: 83 c0 00 add $0x0,%eax ce: 80 e4 ff and $0xff,%ah d1: 50 push %eax d2: 8b 45 08 mov 0x8(%ebp),%eax d5: 83 c0 03 add $0x3,%eax d8: 50 push %eax d9: 8d 4d f8 lea 0xfffffff8(%ebp),%ecx dc: e8 8d ff ff ff call 6e <QInner2.3> e1: 83 c4 10 add $0x10,%esp e4: c9 leave e5: c3 ret 000000e6 <main>: e6: 55 push %ebp e7: 89 e5 mov %esp,%ebp e9: 83 ec 08 sub $0x8,%esp ec: 83 e4 f0 and $0xfffffff0,%esp ef: b8 00 00 00 00 mov $0x0,%eax f4: 83 c0 0f add $0xf,%eax f7: 83 c0 0f add $0xf,%eax fa: c1 e8 04 shr $0x4,%eax fd: c1 e0 04 shl $0x4,%eax 100: 29 c4 sub %eax,%esp 102: 6a 21 push $0x21 104: e8 fc ff ff ff call 105 <main+0x1f> 109: 83 c4 04 add $0x4,%esp 10c: 83 ec 0c sub $0xc,%esp 10f: 6a 0d push $0xd 111: e8 fc ff ff ff call 112 <main+0x2c> 116: 83 c4 10 add $0x10,%esp 119: c9 leave 11a: c3 ret ------------------------------------------------------------------------- -- Rodney M. Bates