<div dir="ltr">On Mon, Jul 29, 2013 at 10:45 AM, Duncan Sands <span dir="ltr"><<a href="mailto:baldrick@free.fr" target="_blank">baldrick@free.fr</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Reid,<div class="im"><br>
<br>
On 29/07/13 16:36, Reid Kleckner wrote:<br>
</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">
On Mon, Jul 29, 2013 at 9:40 AM, Duncan Sands <<a href="mailto:baldrick@free.fr" target="_blank">baldrick@free.fr</a><br></div><div><div class="h5">
<mailto:<a href="mailto:baldrick@free.fr" target="_blank">baldrick@free.fr</a>>> wrote:<br>
<br>
On 29/07/13 15:30, Anton Korobeynikov wrote:<br>
<br>
object in place on the stack or at least call its copy constructor.<br>
<br>
<br>
<br>
what does GCC do?<br>
<br>
Nothing. It does not support MSVC ABI.<br>
<br>
<br>
Maybe we shouldn't either :) So the ABI requires the struct to be pushed on the<br>
stack by the caller along with the other parameters, and what's more it requires<br>
the caller to execute some code on that copy, in place on the stack, before<br>
performing the call. Is that right?<br>
<br>
<br>
Just calling the copy ctor is the bare minimum needed to support the ABI.<br>
cl.exe uses a more efficient lowering that evaluates the arguments right to<br>
left directly into the outgoing argument stack slots. It lowers following call<br>
to bar to something like:<br>
<br>
struct A {int x; int y;};<br>
A foo();<br>
void bar(int, A, int);<br>
...<br>
bar(0xdead, foo(), 0xbeef);<br>
<br>
x86_32 pseudo intel asm:<br>
<br>
push 0xdead<br>
sub esp, 8<br>
push esp # sret arg for foo<br>
call foo<br>
add esp, 4 # clear sret arg<br>
push 0xbeef<br>
call bar<br>
</div></div></blockquote>
<br>
I got confused by your example. Is the struct passed on the stack, amongst the<br>
other parameters, or can it be allocated somewhere else and a pointer to it<br>
passed? Because in your example it isn't clear to me how the return value of<br>
foo() is being passed to bar().<br></blockquote><div><br></div><div>Yes, the struct is passed amongst the other parameters. LLVM already supports passing C structs this way using byval, but it emits a memcpy in the backend, which breaks C++ objects.</div>
<div><br></div><div>foo() is returning an A struct via the usual hidden sret parameter. The "push esp" is taking the address of the struct's outgoing arg slot and passing it to foo().</div></div></div></div>