[Issue 2318] New: flaw code generation building a function pointer table
Sivo Schilling
sivo.schilling at web.de
Wed Sep 3 02:48:37 PDT 2008
If you declare FnPtr as void delegate() then these issues are gone.
This works with both DMD 1.034 and DMD 2.018 on Win XP SP3 but
using phobos instead of Tango/tangobos.
d-bugmail at puremagic.com Wrote:
> http://d.puremagic.com/issues/show_bug.cgi?id=2318
>
> Summary: flaw code generation building a function pointer table
> Product: D
> Version: 1.034
> Platform: PC
> OS/Version: Windows
> Status: NEW
> Severity: normal
> Priority: P2
> Component: DMD
> AssignedTo: bugzilla at digitalmars.com
> ReportedBy: enzo.petrelli at fastwebnet.it
>
>
> /***************************
> OS: Vista SP1
> Compiler/linker: Digital Mars D Compiler v1.034
> Tango/tangobos Lib: tango-0.99.7-bin-win32-dmd.1.033
> Compiled with: dmd -g -debug epfuntbl.d
>
> Debug version:
> Trying to build a table of 5 function pointers out of
> 5 struct members, 1st and 3rd items are uncorrectly
> asssigned values
>
> Release version:
> A similar but slightly different behaviour is shown.
> Further, an "Access violation" is raised
>
> ***************************/
>
> import std.cstream;
>
> alias void function() FnPtr;
>
> void initTTest(TTest * pTst)
> {
> // pTst.pVtbl = cast(void*) pTst.apFnc.ptr;
> pTst.apFnc[0] = cast(FnPtr) &pTst.func0;
> pTst.apFnc[1] = cast(FnPtr) &pTst.func1;
> pTst.apFnc[2] = cast(FnPtr) &pTst.func2;
> pTst.apFnc[3] = cast(FnPtr) &pTst.func3;
> pTst.apFnc[4] = cast(FnPtr) &pTst.func4;
> }
>
> struct TTest
> {
> void * pVtbl;
> FnPtr[5] apFnc;
>
> void func0()
> {
> dout.writefln("func0");
> }
> void func1()
> {
> dout.writefln("func1");
> }
> void func2()
> {
> dout.writefln("func2");
> }
> void func3()
> {
> dout.writefln("func3");
> }
> void func4()
> {
> dout.writefln("func4");
> }
> }
>
> void main()
> {
> TTest * pTst = new TTest;
> initTTest(pTst);
> for (int iIdx = 0; iIdx < pTst.apFnc.length; ++iIdx)
> dout.writefln("item#%d:0x%08X", iIdx, cast(int)
> pTst.apFnc[iIdx]);
> pTst.apFnc[1]();
> pTst.apFnc[3]();
> pTst.apFnc[4]();
> }
>
> /*
> execution produces:
>
> item#0:0x019F3FE0
> item#1:0x004020AC
> item#2:0x019F3FE0
> item#3:0x0040215C
> item#4:0x004021B4
> func1
> func3
> func4
> */
>
> /*
> disassembly shows that wrong code is generated for the 1st and 3rd
> function pointer assignments:
> function address is loaded into a register but the destination is
> written from another one
>
> 5: void initTTest(TTest * pTst)
> 00402010 enter 4,0
> 00402014 push ebx
> 00402015 push esi
> 00402016 mov dword ptr [ebp-4],eax
> 6: {
> 7: // pTst.pVtbl = cast(void*) pTst.apFnc.ptr;
> 8: pTst.apFnc[0] = cast(FnPtr) &pTst.func0;
> 00402019 mov eax,dword ptr [pTst]
> 0040201C mov ecx,offset _D8epfuntbl5TTest5func0MFZv (00402054)
> 00402021 mov edx,dword ptr [pTst]
> 00402024 mov dword ptr [edx+4],eax
> 9: pTst.apFnc[1] = cast(FnPtr) &pTst.func1;
> 00402027 mov ebx,edx
> 00402029 mov ecx,offset _D8epfuntbl5TTest5func1MFZv (004020ac)
> 0040202E mov dword ptr [edx+8],ecx
> 10: pTst.apFnc[2] = cast(FnPtr) &pTst.func2;
> 00402031 mov eax,edx
> 00402033 mov ecx,offset _D8epfuntbl5TTest5func2MFZv (00402104)
> 00402038 mov dword ptr [edx+0Ch],eax
> 11: pTst.apFnc[3] = cast(FnPtr) &pTst.func3;
> 0040203B mov esi,edx
> 0040203D mov ecx,offset _D8epfuntbl5TTest5func3MFZv (0040215c)
> 00402042 mov dword ptr [edx+10h],ecx
> 12: pTst.apFnc[4] = cast(FnPtr) &pTst.func4;
> 00402045 mov ebx,edx
> 00402047 mov ecx,offset _D8epfuntbl5TTest5func4MFZv (004021b4)
> 0040204C mov dword ptr [edx+14h],ecx
> 13: }
> 0040204F pop esi
> 00402050 pop ebx
> 00402051 leave
> 00402052 ret
> 00402053 int 3
> */
>
>
> --
>
More information about the Digitalmars-d-bugs
mailing list