diff --git a/lib/Target/X86/X86ISelPattern.cpp b/lib/Target/X86/X86ISelPattern.cpp index eb6babf6280..3345afcc485 100644 --- a/lib/Target/X86/X86ISelPattern.cpp +++ b/lib/Target/X86/X86ISelPattern.cpp @@ -109,6 +109,11 @@ namespace { addLegalFPImmediate(-1.0); // FLD1/FCHS } + // Return the number of bytes that a function should pop when it returns (in + // addition to the space used by the return address). + // + unsigned getBytesToPopOnReturn() const { return BytesToPopOnReturn; } + /// LowerArguments - This hook must be implemented to indicate how we should /// lower the arguments for the specified function, into the specified DAG. virtual std::vector @@ -228,7 +233,8 @@ X86TargetLowering::LowerCCCArguments(Function &F, SelectionDAG &DAG) { // the start of the first vararg value... for expansion of llvm.va_start. if (F.isVarArg()) VarArgsFrameIndex = MFI->CreateFixedObject(1, ArgOffset); - ReturnAddrIndex = 0; // No return address slot generated yet. + ReturnAddrIndex = 0; // No return address slot generated yet. + BytesToPopOnReturn = 0; // Callee pops nothing. // Finally, inform the code generator which regs we return values in. switch (getValueType(F.getReturnType())) { @@ -527,11 +533,9 @@ X86TargetLowering::LowerFastCCArguments(Function &F, SelectionDAG &DAG) { ArgOffset += ArgIncrement; // Move on to the next argument. } - // If the function takes variable number of arguments, make a frame index for - // the start of the first vararg value... for expansion of llvm.va_start. - if (F.isVarArg()) - VarArgsFrameIndex = MFI->CreateFixedObject(1, ArgOffset); - ReturnAddrIndex = 0; // No return address slot generated yet. + VarArgsFrameIndex = 0xAAAAAAA; // fastcc functions can't have varargs. + ReturnAddrIndex = 0; // No return address slot generated yet. + BytesToPopOnReturn = ArgOffset; // Callee pops all stack arguments. // Finally, inform the code generator which regs we return values in. switch (getValueType(F.getReturnType())) { @@ -3518,7 +3522,10 @@ void ISel::Select(SDOperand N) { Select(N.getOperand(0)); break; } - BuildMI(BB, X86::RET, 0); // Just emit a 'ret' instruction + if (X86Lowering.getBytesToPopOnReturn() == 0) + BuildMI(BB, X86::RET, 0); // Just emit a 'ret' instruction + else + BuildMI(BB, X86::RETI, 1).addImm(X86Lowering.getBytesToPopOnReturn()); return; case ISD::BR: { Select(N.getOperand(0)); @@ -3721,13 +3728,19 @@ void ISel::Select(SDOperand N) { return; } case ISD::CALLSEQ_START: + Select(N.getOperand(0)); + // Stack amount + Tmp1 = cast(N.getOperand(1))->getValue(); + BuildMI(BB, X86::ADJCALLSTACKDOWN, 1).addImm(Tmp1); + return; case ISD::CALLSEQ_END: Select(N.getOperand(0)); + // Stack amount Tmp1 = cast(N.getOperand(1))->getValue(); - Opc = N.getOpcode() == ISD::CALLSEQ_START ? X86::ADJCALLSTACKDOWN : - X86::ADJCALLSTACKUP; - BuildMI(BB, Opc, 1).addImm(Tmp1); + // Amount the callee added to the stack pointer. + Tmp2 = cast(N.getOperand(2))->getValue(); + BuildMI(BB, X86::ADJCALLSTACKUP, 2).addImm(Tmp1).addImm(Tmp2); return; case ISD::MEMSET: { Select(N.getOperand(0)); // Select the chain. diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp index f27784b7f7c..ea5520fbf88 100644 --- a/lib/Target/X86/X86ISelSimple.cpp +++ b/lib/Target/X86/X86ISelSimple.cpp @@ -1695,7 +1695,7 @@ void X86ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI, BB->push_back(CallMI); - BuildMI(BB, X86::ADJCALLSTACKUP, 1).addImm(NumBytes); + BuildMI(BB, X86::ADJCALLSTACKUP, 2).addImm(NumBytes).addImm(0); // If there is a return value, scavenge the result from the location the call // leaves it in... diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 5ef4862d39b..4fb5ccf5b50 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -375,17 +375,31 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); Amount = (Amount+Align-1)/Align*Align; - MachineInstr *New; + MachineInstr *New = 0; if (Old->getOpcode() == X86::ADJCALLSTACKDOWN) { New=BuildMI(X86::SUB32ri, 1, X86::ESP, MachineOperand::UseAndDef) .addZImm(Amount); } else { assert(Old->getOpcode() == X86::ADJCALLSTACKUP); - New=BuildMI(X86::ADD32ri, 1, X86::ESP, MachineOperand::UseAndDef) - .addZImm(Amount); + // factor out the amount the callee already popped. + unsigned CalleeAmt = Old->getOperand(1).getImmedValue(); + Amount -= CalleeAmt; + if (Amount) + New = BuildMI(X86::ADD32ri, 1, X86::ESP, + MachineOperand::UseAndDef).addZImm(Amount); } // Replace the pseudo instruction with a new instruction... + if (New) MBB.insert(I, New); + } + } else if (I->getOpcode() == X86::ADJCALLSTACKUP) { + // If we are performing frame pointer elimination and if the callee pops + // something off the stack pointer, add it back. We do this until we have + // more advanced stack pointer tracking ability. + if (unsigned CalleeAmt = I->getOperand(1).getImmedValue()) { + MachineInstr *New = + BuildMI(X86::SUB32ri, 1, X86::ESP, + MachineOperand::UseAndDef).addZImm(CalleeAmt); MBB.insert(I, New); } } @@ -513,8 +527,8 @@ void X86RegisterInfo::emitEpilogue(MachineFunction &MF, unsigned NumBytes = MFI->getStackSize(); if (NumBytes) { // adjust stack pointer back: ESP += numbytes - MI =BuildMI(X86::ADD32ri, 1, X86::ESP, MachineOperand::UseAndDef) - .addZImm(NumBytes); + MI = BuildMI(X86::ADD32ri, 1, X86::ESP, MachineOperand::UseAndDef) + .addZImm(NumBytes); MBB.insert(MBBI, MI); } }