Count the sret register as well when keeping track of how many integer registers

are available for extern(C) functions on x86-64.
Interestingly, llvm-g++ seems to have a very similar bug: http://llvm.org/pr4242
(So this breaks ABI-compatibility with llvm-gcc for this corner case, but gains
it with gcc...)

To clarify, this is about code like this:
{{{
struct S { void*[3] data; }
struct T { void*[2] data; }

// The T should be passed in memory, and p in the last int register.
extern(C) S fail(int, int, int, int, T t, void* p) {
    S s;
    s.data[0] = t.data[0];
    s.data[1] = t.data[1];
    s.data[2] = p;
    return s;
}
}}}
which should generate code functionally equivalent to this:
{{{
extern(C) S* succeed(S* s, int, int, int, int, T t, void* p) {
    s.data[0] = t.data[0];
    s.data[1] = t.data[1];
    s.data[2] = p;
    return s;
}
}}}
(with the same definitions for S and T)
This commit is contained in:
Frits van Bommel
2009-05-22 13:17:06 +02:00
parent 86e1457dde
commit 59f9b35cea

View File

@@ -562,7 +562,14 @@ bool X86_64TargetABI::returnInArg(TypeFunction* tf) {
return false;
Classification cl = classify(rt);
return cl.isMemory;
if (cl.isMemory) {
assert(state().int_regs > 0
&& "No int registers available when determining sret-ness?");
// An sret parameter takes an integer register.
state().int_regs--;
return true;
}
return false;
}
}