digitalmars.D.bugs - [Issue 2318] New: flaw code generation building a function pointer table
- d-bugmail puremagic.com (124/124) Aug 27 2008 http://d.puremagic.com/issues/show_bug.cgi?id=2318
- Sivo Schilling (4/147) Sep 03 2008 If you declare FnPtr as void delegate() then these issues are gone.
- d-bugmail puremagic.com (8/8) Apr 08 2009 http://d.puremagic.com/issues/show_bug.cgi?id=2318
- d-bugmail puremagic.com (17/17) Feb 01 2010 http://d.puremagic.com/issues/show_bug.cgi?id=2318
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 digitalmars.com ReportedBy: enzo.petrelli 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) pTst.apFnc[iIdx]); pTst.apFnc[1](); pTst.apFnc[3](); pTst.apFnc[4](); } /* execution produces: 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 */ --
Aug 27 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 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 digitalmars.com ReportedBy: enzo.petrelli 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) pTst.apFnc[iIdx]); pTst.apFnc[1](); pTst.apFnc[3](); pTst.apFnc[4](); } /* execution produces: 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 */ --
Sep 03 2008
http://d.puremagic.com/issues/show_bug.cgi?id=2318 clugdbug yahoo.com.au changed: What |Removed |Added ---------------------------------------------------------------------------- Severity|normal |critical This also applies to D2.(DMD2.028). --
Apr 08 2009
http://d.puremagic.com/issues/show_bug.cgi?id=2318 Don <clugdbug yahoo.com.au> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED CC| |clugdbug yahoo.com.au Resolution| |INVALID This is invalid: the code creates delegates, then casts them to function pointers. To create the desired effect, this line: pTst.apFnc[0] = cast(FnPtr) &pTst.func0; should be changed to: pTst.apFnc[0] = &TTest.func0; -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 01 2010