When my llvm code calls certain function, either it receives a wrong result or the application ends on what it seems a corrupt stack. The function is a C++ static method that returns a class with just a `double' data member: class Foo { double data; }; My compiler abstracts this as a [8 x i8] array. This is the llvm code: 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 ) bitcast [8 x i8]* %1 to i8* ; <i8*>:3 [#uses=1] tail call void @Addr_004DDA18( i8* inttoptr (i32 14545104 to i8*), i8* %3 ) store i1 true, i1* %2 load i1* %2 ; <i1>:4 [#uses=1] ret i1 %4 } It is a function that just calls the above mentioned C++ static method, calls another external function which is known to be "safe" (as it does nothing and is called thousands of times everywhere without problems) and returns bool. This is the generated machine code, obtained with gdb: 0x0e8d9370: push %esi 0x0e8d9371: sub $0x18,%esp 0x0e8d9374: lea 0x10(%esp),%esi 0x0e8d9378: mov %esi,(%esp) 0x0e8d937b: call 0x5053b0 <_ZN3lp04OpF0IN5IncDB9TDateTimeEXadL_ZNS2_3NowEvEEE1wEv> 0x0e8d9380: sub $0x4,%esp 0x0e8d9383: mov %esi,0x4(%esp) 0x0e8d9387: movl $0x8def210,(%esp) 0x0e8d938e: call 0x4b3ca0 <_ZN3lp015BasicDestructorIN5IncDB9TDateTimeEEEvRNS_8TipoInfoEPv> 0x0e8d9393: movb $0x1,0x8(%esp) 0x0e8d9398: movzbl 0x8(%esp),%eax 0x0e8d939d: add $0x18,%esp 0x0e8d93a0: pop %esi 0x0e8d93a1: ret I'm using setCallingConv(CallingConv::C). After hours and hours of debugging, I'm lost. Do you see something wrong here? My setup is llvm 2.1 on Windows XPSP2. Everything is compiled with MinGW g++.exe (GCC) 4.2.1-dw2 (mingw32-2) -- Oscar
Hi,> 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,%espHere you see the sret stack adjustment. Ciao, Duncan.
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