Hi all. I am working on constructors implementation for MS ABI. Itanium ABI has 2 constructor types - base & complete. MS ABI has only 1 type. How it works I'll show on example. class first { public: virtual void g(){} }; class second : public virtual first { public : virtual void g(){} }; When construct instance of second we will have next code push 1 lea ecx,[f] call second::second ; ctor call And in ctor ................................................................................ 012B19E0 mov dword ptr [ebp-8],ecx 012B19E3 cmp dword ptr [ebp+8],0 012B19E7 je second::second+3Dh (12B19FDh) 012B19E9 mov eax,dword ptr [this] 012B19EC mov dword ptr [eax],offset second::`vbtable' (12B7744h) 012B19F2 mov ecx,dword ptr [this] 012B19F5 add ecx,4 012B19F8 call first::asdf (12B10FAh) 012B19FD mov eax,dword ptr [this] 012B1A00 mov ecx,dword ptr [eax] 012B1A02 mov edx,dword ptr [ecx+4] 012B1A05 mov eax,dword ptr [this] 012B1A08 mov dword ptr [eax+edx],offset second::`vftable' (12B77F4h) 012B1A0F mov eax,dword ptr [this] ................................................................................ As you can see 'push 1' for MS ABI is like ctor_base & ctor_complete for Itanium ABI. If second ctor was called from another ctor(for example child that inherits second) on stack will be pushed 0, and ctor in second will not initialize vbtable and call first::ctor. Add new class. class third : public second, public first {}; ................................................................................ 002519FE push 0 00251A00 mov ecx,dword ptr [this] 00251A03 add ecx,4 ; this adjustment 00251A06 call second::second (2510F0h) ................................................................................ This is part of code from third ctor. Before second::ctor call 0 was pushed on the stack, this value tell to second::ctor that vbtable initialization and first::ctor call not need. So my question is: How can I tell llvm that I need push 1 on the stack? Thx in advance. - Dmitry Sokolov.
Eli Friedman
2012-Feb-27 17:00 UTC
[LLVMdev] Microsoft constructors implementation problem.
On Mon, Feb 27, 2012 at 3:42 AM, r4start <r4start at gmail.com> wrote:> Hi all. > > I am working on constructors implementation for MS ABI. Itanium ABI has > 2 constructor types - base & complete. MS ABI has only 1 type. > How it works I'll show on example. > class first { > public: > virtual void g(){} > }; > > class second : public virtual first { > public : > virtual void g(){} > }; > When construct instance of second we will have next code > push 1 > lea ecx,[f] > call second::second ; ctor call > > And in ctor > ................................................................................ > 012B19E0 mov dword ptr [ebp-8],ecx > 012B19E3 cmp dword ptr [ebp+8],0 > 012B19E7 je second::second+3Dh (12B19FDh) > 012B19E9 mov eax,dword ptr [this] > 012B19EC mov dword ptr [eax],offset second::`vbtable' (12B7744h) > 012B19F2 mov ecx,dword ptr [this] > 012B19F5 add ecx,4 > 012B19F8 call first::asdf (12B10FAh) > 012B19FD mov eax,dword ptr [this] > 012B1A00 mov ecx,dword ptr [eax] > 012B1A02 mov edx,dword ptr [ecx+4] > 012B1A05 mov eax,dword ptr [this] > 012B1A08 mov dword ptr [eax+edx],offset second::`vftable' > (12B77F4h) > 012B1A0F mov eax,dword ptr [this] > ................................................................................ > As you can see 'push 1' for MS ABI is like ctor_base & ctor_complete for > Itanium ABI. > If second ctor was called from another ctor(for example child that > inherits second) on stack will be pushed 0, > and ctor in second will not initialize vbtable and call first::ctor. > > Add new class. > > class third : public second, public first {}; > > ................................................................................ > 002519FE push 0 > 00251A00 mov ecx,dword ptr [this] > 00251A03 add ecx,4 ; this adjustment > 00251A06 call second::second (2510F0h) > ................................................................................ > This is part of code from third ctor. Before second::ctor call 0 was > pushed on the stack, > this value tell to second::ctor that vbtable initialization and > first::ctor call not need. > > So my question is: How can I tell llvm that I need push 1 on the stack?Make the signature of the constructor something like "void (%second*, i32)"? The "thiscall" calling convention should handle this case correctly. -Eli
On 27/02/2012 21:00, Eli Friedman wrote:> On Mon, Feb 27, 2012 at 3:42 AM, r4start<r4start at gmail.com> wrote: >> Hi all. >> >> I am working on constructors implementation for MS ABI. Itanium ABI has >> 2 constructor types - base& complete. MS ABI has only 1 type. >> How it works I'll show on example. >> class first { >> public: >> virtual void g(){} >> }; >> >> class second : public virtual first { >> public : >> virtual void g(){} >> }; >> When construct instance of second we will have next code >> push 1 >> lea ecx,[f] >> call second::second ; ctor call >> >> And in ctor >> ................................................................................ >> 012B19E0 mov dword ptr [ebp-8],ecx >> 012B19E3 cmp dword ptr [ebp+8],0 >> 012B19E7 je second::second+3Dh (12B19FDh) >> 012B19E9 mov eax,dword ptr [this] >> 012B19EC mov dword ptr [eax],offset second::`vbtable' (12B7744h) >> 012B19F2 mov ecx,dword ptr [this] >> 012B19F5 add ecx,4 >> 012B19F8 call first::asdf (12B10FAh) >> 012B19FD mov eax,dword ptr [this] >> 012B1A00 mov ecx,dword ptr [eax] >> 012B1A02 mov edx,dword ptr [ecx+4] >> 012B1A05 mov eax,dword ptr [this] >> 012B1A08 mov dword ptr [eax+edx],offset second::`vftable' >> (12B77F4h) >> 012B1A0F mov eax,dword ptr [this] >> ................................................................................ >> As you can see 'push 1' for MS ABI is like ctor_base& ctor_complete for >> Itanium ABI. >> If second ctor was called from another ctor(for example child that >> inherits second) on stack will be pushed 0, >> and ctor in second will not initialize vbtable and call first::ctor. >> >> Add new class. >> >> class third : public second, public first {}; >> >> ................................................................................ >> 002519FE push 0 >> 00251A00 mov ecx,dword ptr [this] >> 00251A03 add ecx,4 ; this adjustment >> 00251A06 call second::second (2510F0h) >> ................................................................................ >> This is part of code from third ctor. Before second::ctor call 0 was >> pushed on the stack, >> this value tell to second::ctor that vbtable initialization and >> first::ctor call not need. >> >> So my question is: How can I tell llvm that I need push 1 on the stack? > Make the signature of the constructor something like "void (%second*, > i32)"? The "thiscall" calling convention should handle this case > correctly. > > -EliThanks. - Dmitry.