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