Hi Duncan. Duncan Sands <baldrick at free.fr> writes:>> define internal i1 @Addr_045442A0() { >> alloca [8 x i8], align 4 ; <[8 x i8]*>:1 [#uses=2] >> alloca i1, align 4 ; <i1*>:2 [#uses=2] >> tail call void @F95478DA5_FFI_FN( [8 x i8]* %1 sret ) > > this call uses the "struct-return" convention (due to the sret attribute). > On x86 this means that the caller is responsible for adjusting the stack > pointer after the call for the sret parameter. If the callee is not following > the sret convention then the stack pointer will be adjusted wrongly and your > program will die horribly. > >> 0x0e8d937b: call 0x5053b0 <_ZN3lp04OpF0IN5IncDB9TDateTimeEXadL_ZNS2_3NowEvEEE1wEv> >> 0x0e8d9380: sub $0x4,%esp > > Here you see the sret stack adjustment.This looks like the opposite: it is making room for passing a parameter to the next call (the stack grows downwards). But you put me on the right track. The problem is that the class is returned on the stack. This is the class: class Foo { public: Foo() : data(113.5) {} static Foo GetFoo() { return Foo(); } private: double data; }; This is the assembler code for Foo::GetFoo: Dump of assembler code for function _ZN3Foo6GetFooEv: 0x6e08b5a4 <_ZN3Foo6GetFooEv+0>: push %ebp 0x6e08b5a5 <_ZN3Foo6GetFooEv+1>: mov %esp,%ebp 0x6e08b5a7 <_ZN3Foo6GetFooEv+3>: sub $0x14,%esp 0x6e08b5aa <_ZN3Foo6GetFooEv+6>: lea -0x8(%ebp),%eax 0x6e08b5ad <_ZN3Foo6GetFooEv+9>: mov %eax,(%esp) 0x6e08b5b0 <_ZN3Foo6GetFooEv+12>: call 0x6e08b5bc <Foo> 0x6e08b5b5 <_ZN3Foo6GetFooEv+17>: fldl -0x8(%ebp) 0x6e08b5b8 <_ZN3Foo6GetFooEv+20>: leave 0x6e08b5b9 <_ZN3Foo6GetFooEv+21>: ret End of assembler dump. I guess that g++ exploits its knowledge of Foo's internals for deciding how to return the class. But my compiler knows nothing about Foo, so I must disable this "feature" of g++. Suggestions welcome. -- Oscar
Hi Óscar,> >> define internal i1 @Addr_045442A0() { > >> alloca [8 x i8], align 4 ; <[8 x i8]*>:1 [#uses=2] > >> alloca i1, align 4 ; <i1*>:2 [#uses=2] > >> tail call void @F95478DA5_FFI_FN( [8 x i8]* %1 sret ) > > > > this call uses the "struct-return" convention (due to the sret attribute). > > On x86 this means that the caller is responsible for adjusting the stack > > pointer after the call for the sret parameter. If the callee is not following > > the sret convention then the stack pointer will be adjusted wrongly and your > > program will die horribly. > > > >> 0x0e8d937b: call 0x5053b0 <_ZN3lp04OpF0IN5IncDB9TDateTimeEXadL_ZNS2_3NowEvEEE1wEv> > >> 0x0e8d9380: sub $0x4,%esp > > > > Here you see the sret stack adjustment. > > This looks like the opposite: it is making room for passing a parameter > to the next call (the stack grows downwards).yes I said it the wrong way round: with sret the callee pops the sret parameter, so the caller needs to correct for that. I'm pretty sure that's exactly what this sub is doing.> But you put me on the right track. The problem is that the class is > returned on the stack. > > This is the class: > > class Foo { > public: > Foo() : data(113.5) {} > static Foo GetFoo() { return Foo(); } > private: > double data; > }; > > This is the assembler code for Foo::GetFoo: > > Dump of assembler code for function _ZN3Foo6GetFooEv: > 0x6e08b5a4 <_ZN3Foo6GetFooEv+0>: push %ebp > 0x6e08b5a5 <_ZN3Foo6GetFooEv+1>: mov %esp,%ebp > 0x6e08b5a7 <_ZN3Foo6GetFooEv+3>: sub $0x14,%esp > 0x6e08b5aa <_ZN3Foo6GetFooEv+6>: lea -0x8(%ebp),%eax > 0x6e08b5ad <_ZN3Foo6GetFooEv+9>: mov %eax,(%esp) > 0x6e08b5b0 <_ZN3Foo6GetFooEv+12>: call 0x6e08b5bc <Foo> > 0x6e08b5b5 <_ZN3Foo6GetFooEv+17>: fldl -0x8(%ebp) > 0x6e08b5b8 <_ZN3Foo6GetFooEv+20>: leave > 0x6e08b5b9 <_ZN3Foo6GetFooEv+21>: ret > End of assembler dump. > > I guess that g++ exploits its knowledge of Foo's internals for deciding > how to return the class.How Foo is returned is specified by the platform ABI. It is not really a feature of g++.> But my compiler knows nothing about Foo, so I > must disable this "feature" of g++. Suggestions welcome.It is not possible to correctly codegen parameter passing/result returning without knowing the type (though not all details of the type are relevant). Your compiler needs to know something about Foo. Ciao, Duncan.
Duncan Sands <baldrick at free.fr> writes:>> But you put me on the right track. The problem is that the class is >> returned on the stack.Correction: The class is returned on the FP stack:>> 0x6e08b5b5 <_ZN3Foo6GetFooEv+17>: fldl -0x8(%ebp) >> 0x6e08b5b8 <_ZN3Foo6GetFooEv+20>: leave >> 0x6e08b5b9 <_ZN3Foo6GetFooEv+21>: ret >> End of assembler dump. >> >> I guess that g++ exploits its knowledge of Foo's internals for deciding >> how to return the class. > > How Foo is returned is specified by the platform ABI. It is not really a > feature of g++.This is C++ land, so there is no "platform ABI", although static methods usually follow C calling convention. I've checked that wrapping the class definition with extern "C" changes nothing, so maybe it is following the platform ABI, after all. BTW, -fpcc-struct-return solves the case that motivated this thread.>> But my compiler knows nothing about Foo, so I >> must disable this "feature" of g++. Suggestions welcome. > > It is not possible to correctly codegen parameter passing/result returning > without knowing the type (though not all details of the type are relevant). > Your compiler needs to know something about Foo.I'm afraid you are right. Current available information includes the specific type (if it is fundamental), and type size (if it is derived). It also knows the default constructor, copier and destructor of each type. I hope that this, together with -fpcc-struct-return, is enough to complete my C++ <-> LLVM interface, which only has to deal with static methods. -- Oscar
Hello, Oscar> This is C++ land, so there is no "platform ABI",Well, here is g++ ABI :)> following the platform ABI, after all. > > BTW, -fpcc-struct-return solves the case that motivated this thread.Usually, special rules are applied for returning struct, if its size is small enough. So you can definitely find something small returned via registers. This is frontend job to select how to pass such object. -- With best regards, Anton Korobeynikov. Faculty of Mathematics & Mechanics, Saint Petersburg State University.
On Wed, 2008-03-26 at 19:56 +0300, Anton Korobeynikov wrote:> Usually, special rules are applied for returning struct, if its size is > small enough. So you can definitely find something small returned via > registers. This is frontend job to select how to pass such object.It is true that many calling conventions optimize small structure return. It is the front end's job to *implement* this. It is the responsibility of the calling convention to *specify* this. The front end must comply with the calling convention, or separate compilation is compromised. shap