Wrong calling convention?

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)

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,%esp

Here you see the sret stack adjustment.

Ciao,

Duncan.

Hi Duncan.

Duncan Sands <baldrick@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.

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@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.

Hello, Oscar

This is C++ land, so there is no "platform ABI",

Well, here is g++ ABI :slight_smile:

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.

Óscar Fuentes <ofv@wanadoo.es> writes:

BTW, -fpcc-struct-return solves the case that motivated this thread.

-fpcc-struct-return is an ABI change, hence it requires "compiling the
world". Not acceptable.

I'll be interested on hearing ideas about how to determine how a
function returns a small struct, without knowing the internals of the
struct.

Óscar Fuentes <ofv@wanadoo.es> writes:

BTW, -fpcc-struct-return solves the case that motivated this thread.

-fpcc-struct-return is an ABI change, hence it requires "compiling the
world". Not acceptable.

I'll be interested on hearing ideas about how to determine how a
function returns a small struct, without knowing the internals of the
struct.

You need to know _something_ about the internals. GCC approximately implements the IA-64 C++ ABI; which is fairly conventional in this particular aspect of a C++ ABI. See
  http://www.codesourcery.com/cxx-abi/abi.html#calls

In that ABI, if there is a "nontrivial" (that's a precise term) copy-constructor or destructor, the caller is responsible for allocation.

  Daveed

Take a look at llvm-gcc. Look for HandleAggregateShadowArgument.

Evan

I should note this how we do it today but it may not be the solution long term.

In an ideal world the llvm frontend will not need to know anything about the target since llvm is intended as a virtual instruction set.

Evan

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

Evan Cheng <evan.cheng@apple.com> writes:

I'll be interested on hearing ideas about how to determine how a
function returns a small struct, without knowing the internals of the
struct.

Take a look at llvm-gcc. Look for HandleAggregateShadowArgument.

This does not qualify as "without knowing the internals of the struct"
:slight_smile:

DefaultABI::HandleReturnType made an interesting reading, although it
uses information which is unaccessible to my compiler.

Which calling convention to use depends on the contents of the struct. You cannot make all cases work without that information.

David Vandevoorde <daveed@vandevoorde.com> writes:

I'll be interested on hearing ideas about how to determine how a
function returns a small struct, without knowing the internals of the
struct.

You need to know _something_ about the internals.

[snip]

Well, as AFAIK there is no way of gathering that information, putting
some checks to ensure that the manually provided type info is correct
would be nice, but I'm afraid that there is no way to achieve that
either (except for the most simple checks, like the struct size not
being large than `double', etc). Boost type_traits does not mention g++
on the list of compilers that has the necessary intrinsics for
supporting has_trivial_copier et al.

I guess this is off-topic, so thank you all guys for your suggestions.