MS ABI: Fix __fastcall methods that return structs

The sret paramater consumes the register after the implicit 'this'
parameter, as with other calling conventions.

Fixes PR20278, which turned out to be very easy.

llvm-svn: 212669
This commit is contained in:
Reid Kleckner 2014-07-10 01:58:55 +00:00
parent 2e28edf8e1
commit 677539d0af
2 changed files with 18 additions and 1 deletions

View File

@ -957,8 +957,16 @@ void X86_32ABIInfo::computeInfo(CGFunctionInfo &FI) const {
else
State.FreeRegs = DefaultNumRegisterParameters;
if (!getCXXABI().classifyReturnType(FI))
if (!getCXXABI().classifyReturnType(FI)) {
FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), State);
} else if (FI.getReturnInfo().isIndirect()) {
// The C++ ABI is not aware of register usage, so we have to check if the
// return value was sret and put it in a register ourselves if appropriate.
if (State.FreeRegs) {
--State.FreeRegs; // The sret parameter consumes a register.
FI.getReturnInfo().setInReg(true);
}
}
bool UsedInAlloca = false;
for (auto &I : FI.arguments()) {

View File

@ -33,3 +33,12 @@ int main() {
// CHECK: call void {{.*}} @"\01?variadic_sret@C@@QAA?AUS@@PBDZZ"
// CHECK: call void @"\01?cdecl_sret@C@@QAA?AUS@@XZ"
// CHECK: call void @"\01?byval_and_sret@C@@QAA?AUS@@U2@@Z"
// __fastcall has similar issues.
struct A {
S __fastcall f(int x);
};
S A::f(int x) {
return S();
}
// CHECK-LABEL: define x86_fastcallcc void @"\01?f@A@@QAI?AUS@@H@Z"(%struct.A* inreg %this, %struct.S* inreg noalias sret %agg.result, i32 %x)