Fix fastcc structure return with fast-isel on x86-32

On x86-32, structure return via sret lets the callee pop the hidden
pointer argument off the stack, which the caller then re-pushes.
However if the calling convention is fastcc, then a register is used
instead, and the caller should not adjust the stack. This is
implemented with a check of IsTailCallConvention
X86TargetLowering::LowerCall but is now checked properly in
X86FastISel::DoSelectCall.

(this time, actually commit what was reviewed!)

llvm-svn: 155825
This commit is contained in:
Derek Schuff 2012-04-30 16:57:15 +00:00
parent 9245c93656
commit b051adf263
2 changed files with 16 additions and 0 deletions

View File

@ -1858,6 +1858,8 @@ bool X86FastISel::DoSelectCall(const Instruction *I, const char *MemIntName) {
unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
unsigned NumBytesCallee = 0;
if (!Subtarget->is64Bit() && !Subtarget->isTargetWindows() &&
!(CS.getCallingConv() == CallingConv::Fast ||
CS.getCallingConv() == CallingConv::GHC) &&
CS.paramHasAttr(1, Attribute::StructRet))
NumBytesCallee = 4;
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(AdjStackUp))

View File

@ -46,3 +46,17 @@ entry:
; CHECK: addl $40
}
declare void @test3sret(%struct.a* sret)
; Check that fast-isel sret works with fastcc (and does not callee-pop)
define void @test4() nounwind ssp {
entry:
%tmp = alloca %struct.a, align 8
call fastcc void @test4fastccsret(%struct.a* sret %tmp)
ret void
; CHECK: test4:
; CHECK: subl $28
; CHECK: leal (%esp), %ecx
; CHECK: calll _test4fastccsret
; CHECK addl $28
}
declare fastcc void @test4fastccsret(%struct.a* sret)