From 448175fd020acd680c27e61a3aa09d23031a496d Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Tue, 16 Oct 2007 09:05:00 +0000 Subject: [PATCH] Correction to tail call optimization code. The new return address was stored to the acutal stack slot before the parameters were lowered to their stack slot. This could cause arguments to be overwritten by the return address if the called function had less parameters than the caller function. The update should remove the last failing test case of llc-beta: SPASS. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43027 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86ISelLowering.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 8726c587caf..53bb81dd309 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -707,10 +707,11 @@ SDOperand X86TargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG) { Operands.push_back(StackAdjustment); // Copy registers used by the call. Last operand is a flag so it is not // copied. - for(unsigned i=3; i < TailCall.getNumOperands()-1;i++) { + for (unsigned i=3; i < TailCall.getNumOperands()-1; i++) { Operands.push_back(Chain.getOperand(i)); } - return DAG.getNode(X86ISD::TC_RETURN, MVT::Other, &Operands[0], Operands.size()); + return DAG.getNode(X86ISD::TC_RETURN, MVT::Other, &Operands[0], + Operands.size()); } // Regular return. @@ -1520,23 +1521,25 @@ SDOperand X86TargetLowering::LowerX86_TailCallTo(SDOperand Op, if (FPDiff < (MF.getInfo()->getTCReturnAddrDelta())) MF.getInfo()->setTCReturnAddrDelta(FPDiff); - // Adjust the ret address stack slot. + Chain = DAG. + getCALLSEQ_START(Chain, DAG.getConstant(NumBytesToBePushed, getPointerTy())); + + // Adjust the Return address stack slot. + SDOperand RetAddrFrIdx, NewRetAddrFrIdx; if (FPDiff) { MVT::ValueType VT = is64Bit ? MVT::i64 : MVT::i32; - SDOperand RetAddrFrIdx = getReturnAddressFrameIndex(DAG); + RetAddrFrIdx = getReturnAddressFrameIndex(DAG); + // Load the "old" Return address. RetAddrFrIdx = - DAG.getLoad(VT, DAG.getEntryNode(),RetAddrFrIdx, NULL, 0); - // Emit a store of the saved ret value to the new location. + DAG.getLoad(VT, Chain,RetAddrFrIdx, NULL, 0); + // Calculate the new stack slot for the return address. int SlotSize = is64Bit ? 8 : 4; int NewReturnAddrFI = MF.getFrameInfo()->CreateFixedObject(SlotSize, FPDiff-SlotSize); - SDOperand NewRetAddrFrIdx = DAG.getFrameIndex(NewReturnAddrFI, VT); - Chain = DAG.getStore(Chain,RetAddrFrIdx, NewRetAddrFrIdx, NULL, 0); + NewRetAddrFrIdx = DAG.getFrameIndex(NewReturnAddrFI, VT); + Chain = SDOperand(RetAddrFrIdx.Val, 1); } - Chain = DAG. - getCALLSEQ_START(Chain, DAG.getConstant(NumBytesToBePushed, getPointerTy())); - SmallVector, 8> RegsToPass; SmallVector MemOpChains; SmallVector MemOpChains2; @@ -1592,6 +1595,7 @@ SDOperand X86TargetLowering::LowerX86_TailCallTo(SDOperand Op, InFlag = Chain.getValue(1); } InFlag = SDOperand(); + // Copy from stack slots to stack slot of a tail called function. This needs // to be done because if we would lower the arguments directly to their real // stack slot we might end up overwriting each other. @@ -1637,6 +1641,10 @@ SDOperand X86TargetLowering::LowerX86_TailCallTo(SDOperand Op, Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &MemOpChains2[0], MemOpChains.size()); + // Store the return address to the appropriate stack slot. + if (FPDiff) + Chain = DAG.getStore(Chain,RetAddrFrIdx, NewRetAddrFrIdx, NULL, 0); + // ELF / PIC requires GOT in the EBX register before function calls via PLT // GOT pointer. // Does not work with tail call since ebx is not restored correctly by