aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/X86
diff options
context:
space:
mode:
authorGordon Henriksen <gordonhenriksen@mac.com>2008-01-05 16:56:59 +0000
committerGordon Henriksen <gordonhenriksen@mac.com>2008-01-05 16:56:59 +0000
commit86737665b81550fdb575f7d8cc5decc801a7813d (patch)
tree62a8f209ca1a7856c7637f298f837a704053a923 /lib/Target/X86
parentdf303bd7f2c15d6c5fcbee951bd8c21dde3f2718 (diff)
Refactoring the x86 and x86-64 calling convention implementations,
unifying the copied algorithms and saving over 500 LOC. There should be no functionality change, but please test on your favorite x86 target. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45627 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/X86')
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp1231
-rw-r--r--lib/Target/X86/X86ISelLowering.h20
2 files changed, 372 insertions, 879 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 7b683e3ee3..2f629aca28 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -938,6 +938,75 @@ static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
return VReg;
}
+// Determines whether a CALL node uses struct return semantics.
+static bool CallIsStructReturn(SDOperand Op) {
+ unsigned NumOps = (Op.getNumOperands() - 5) / 2;
+ if (!NumOps)
+ return false;
+
+ ConstantSDNode *Flags = cast<ConstantSDNode>(Op.getOperand(6));
+ return Flags->getValue() & ISD::ParamFlags::StructReturn;
+}
+
+// Determines whether a FORMAL_ARGUMENTS node uses struct return semantics.
+static bool ArgsAreStructReturn(SDOperand Op) {
+ unsigned NumArgs = Op.Val->getNumValues() - 1;
+ if (!NumArgs)
+ return false;
+
+ ConstantSDNode *Flags = cast<ConstantSDNode>(Op.getOperand(3));
+ return Flags->getValue() & ISD::ParamFlags::StructReturn;
+}
+
+// Determines whether a CALL or FORMAL_ARGUMENTS node requires the callee to pop
+// its own arguments. Callee pop is necessary to support tail calls.
+bool X86TargetLowering::IsCalleePop(SDOperand Op) {
+ bool IsVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
+ if (IsVarArg)
+ return false;
+
+ switch (cast<ConstantSDNode>(Op.getOperand(1))->getValue()) {
+ default:
+ return false;
+ case CallingConv::X86_StdCall:
+ return !Subtarget->is64Bit();
+ case CallingConv::X86_FastCall:
+ return !Subtarget->is64Bit();
+ case CallingConv::Fast:
+ return PerformTailCallOpt;
+ }
+}
+
+// Selects the correct CCAssignFn for a CALL or FORMAL_ARGUMENTS node.
+CCAssignFn *X86TargetLowering::CCAssignFnForNode(SDOperand Op) const {
+ unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
+
+ if (Subtarget->is64Bit())
+ if (CC == CallingConv::Fast && PerformTailCallOpt)
+ return CC_X86_64_TailCall;
+ else
+ return CC_X86_64_C;
+
+ if (CC == CallingConv::X86_FastCall)
+ return CC_X86_32_FastCall;
+ else if (CC == CallingConv::Fast && PerformTailCallOpt)
+ return CC_X86_32_TailCall;
+ else
+ return CC_X86_32_C;
+}
+
+// Selects the appropriate decoration to apply to a MachineFunction containing a
+// given FORMAL_ARGUMENTS node.
+NameDecorationStyle
+X86TargetLowering::NameDecorationForFORMAL_ARGUMENTS(SDOperand Op) {
+ unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
+ if (CC == CallingConv::X86_FastCall)
+ return FastCall;
+ else if (CC == CallingConv::X86_StdCall)
+ return StdCall;
+ return None;
+}
+
SDOperand X86TargetLowering::LowerMemArgument(SDOperand Op, SelectionDAG &DAG,
const CCValAssign &VA,
MachineFrameInfo *MFI,
@@ -955,13 +1024,25 @@ SDOperand X86TargetLowering::LowerMemArgument(SDOperand Op, SelectionDAG &DAG,
return DAG.getLoad(VA.getValVT(), Root, FIN, NULL, 0);
}
-SDOperand X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG,
- bool isStdCall) {
+SDOperand
+X86TargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) {
MachineFunction &MF = DAG.getMachineFunction();
+ X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
+
+ const Function* Fn = MF.getFunction();
+ if (Fn->hasExternalLinkage() &&
+ Subtarget->isTargetCygMing() &&
+ Fn->getName() == "main")
+ FuncInfo->setForceFramePointer(true);
+
+ // Decorate the function name.
+ FuncInfo->setDecorationStyle(NameDecorationForFORMAL_ARGUMENTS(Op));
+
MachineFrameInfo *MFI = MF.getFrameInfo();
SDOperand Root = Op.getOperand(0);
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
unsigned CC = MF.getFunction()->getCallingConv();
+ bool Is64Bit = Subtarget->is64Bit();
assert(!(isVarArg && CC == CallingConv::Fast) &&
"Var args not supported with calling convention fastcc");
@@ -969,11 +1050,7 @@ SDOperand X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG,
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
- // Check for possible tail call calling convention.
- if (CC == CallingConv::Fast && PerformTailCallOpt)
- CCInfo.AnalyzeFormalArguments(Op.Val, CC_X86_32_TailCall);
- else
- CCInfo.AnalyzeFormalArguments(Op.Val, CC_X86_32_C);
+ CCInfo.AnalyzeFormalArguments(Op.Val, CCAssignFnForNode(Op));
SmallVector<SDOperand, 8> ArgValues;
unsigned LastVal = ~0U;
@@ -990,9 +1067,19 @@ SDOperand X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG,
TargetRegisterClass *RC;
if (RegVT == MVT::i32)
RC = X86::GR32RegisterClass;
+ else if (Is64Bit && RegVT == MVT::i64)
+ RC = X86::GR64RegisterClass;
+ else if (Is64Bit && RegVT == MVT::f32)
+ RC = X86::FR32RegisterClass;
+ else if (Is64Bit && RegVT == MVT::f64)
+ RC = X86::FR64RegisterClass;
else {
assert(MVT::isVector(RegVT));
- RC = X86::VR128RegisterClass;
+ if (Is64Bit && MVT::getSizeInBits(RegVT) == 64) {
+ RC = X86::GR64RegisterClass; // MMX values are passed in GPRs.
+ RegVT = MVT::i64;
+ } else
+ RC = X86::VR128RegisterClass;
}
unsigned Reg = AddLiveIn(DAG.getMachineFunction(), VA.getLocReg(), RC);
@@ -1011,6 +1098,11 @@ SDOperand X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG,
if (VA.getLocInfo() != CCValAssign::Full)
ArgValue = DAG.getNode(ISD::TRUNCATE, VA.getValVT(), ArgValue);
+ // Handle MMX values passed in GPRs.
+ if (Is64Bit && RegVT != VA.getLocVT() && RC == X86::GR64RegisterClass &&
+ MVT::getSizeInBits(RegVT) == 64)
+ ArgValue = DAG.getNode(ISD::BIT_CONVERT, VA.getLocVT(), ArgValue);
+
ArgValues.push_back(ArgValue);
} else {
assert(VA.isMemLoc());
@@ -1026,32 +1118,90 @@ SDOperand X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG,
// 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 (isVarArg) {
- VarArgsFrameIndex = MFI->CreateFixedObject(1, StackSize);
+ if (Is64Bit || CC != CallingConv::X86_FastCall) {
+ VarArgsFrameIndex = MFI->CreateFixedObject(1, StackSize);
+ }
+ if (Is64Bit) {
+ static const unsigned GPR64ArgRegs[] = {
+ X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8, X86::R9
+ };
+ static const unsigned XMMArgRegs[] = {
+ X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
+ X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
+ };
+
+ unsigned NumIntRegs = CCInfo.getFirstUnallocated(GPR64ArgRegs, 6);
+ unsigned NumXMMRegs = CCInfo.getFirstUnallocated(XMMArgRegs, 8);
+
+ // For X86-64, if there are vararg parameters that are passed via
+ // registers, then we must store them to their spots on the stack so they
+ // may be loaded by deferencing the result of va_next.
+ VarArgsGPOffset = NumIntRegs * 8;
+ VarArgsFPOffset = 6 * 8 + NumXMMRegs * 16;
+ RegSaveFrameIndex = MFI->CreateStackObject(6 * 8 + 8 * 16, 16);
+
+ // Store the integer parameter registers.
+ SmallVector<SDOperand, 8> MemOps;
+ SDOperand RSFIN = DAG.getFrameIndex(RegSaveFrameIndex, getPointerTy());
+ SDOperand FIN = DAG.getNode(ISD::ADD, getPointerTy(), RSFIN,
+ DAG.getConstant(VarArgsGPOffset,
+ getPointerTy()));
+ for (; NumIntRegs != 6; ++NumIntRegs) {
+ unsigned VReg = AddLiveIn(MF, GPR64ArgRegs[NumIntRegs],
+ X86::GR64RegisterClass);
+ SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::i64);
+ SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
+ MemOps.push_back(Store);
+ FIN = DAG.getNode(ISD::ADD, getPointerTy(), FIN,
+ DAG.getConstant(8, getPointerTy()));
+ }
+
+ // Now store the XMM (fp + vector) parameter registers.
+ FIN = DAG.getNode(ISD::ADD, getPointerTy(), RSFIN,
+ DAG.getConstant(VarArgsFPOffset, getPointerTy()));
+ for (; NumXMMRegs != 8; ++NumXMMRegs) {
+ unsigned VReg = AddLiveIn(MF, XMMArgRegs[NumXMMRegs],
+ X86::VR128RegisterClass);
+ SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::v4f32);
+ SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
+ MemOps.push_back(Store);
+ FIN = DAG.getNode(ISD::ADD, getPointerTy(), FIN,
+ DAG.getConstant(16, getPointerTy()));
+ }
+ if (!MemOps.empty())
+ Root = DAG.getNode(ISD::TokenFactor, MVT::Other,
+ &MemOps[0], MemOps.size());
+ }
}
+
+ // Make sure the instruction takes 8n+4 bytes to make sure the start of the
+ // arguments and the arguments after the retaddr has been pushed are
+ // aligned.
+ if (!Is64Bit && CC == CallingConv::X86_FastCall &&
+ !Subtarget->isTargetCygMing() && !Subtarget->isTargetWindows() &&
+ (StackSize & 7) == 0)
+ StackSize += 4;
ArgValues.push_back(Root);
- // Tail call convention (fastcc) needs callee pop.
- if (isStdCall && !isVarArg &&
- (CC==CallingConv::Fast && PerformTailCallOpt || CC!=CallingConv::Fast)) {
- BytesToPopOnReturn = StackSize; // Callee pops everything..
+ // Some CCs need callee pop.
+ if (IsCalleePop(Op)) {
+ BytesToPopOnReturn = StackSize; // Callee pops everything.
BytesCallerReserves = 0;
} else {
BytesToPopOnReturn = 0; // Callee pops nothing.
-
// If this is an sret function, the return should pop the hidden pointer.
- unsigned NumArgs = Op.Val->getNumValues() - 1;
- if (NumArgs &&
- (cast<ConstantSDNode>(Op.getOperand(3))->getValue() &
- ISD::ParamFlags::StructReturn))
+ if (!Is64Bit && ArgsAreStructReturn(Op))
BytesToPopOnReturn = 4;
-
BytesCallerReserves = StackSize;
}
- RegSaveFrameIndex = 0xAAAAAAA; // X86-64 only.
+ if (!Is64Bit) {
+ RegSaveFrameIndex = 0xAAAAAAA; // RegSaveFrameIndex is X86-64 only.
+ if (CC == CallingConv::X86_FastCall)
+ VarArgsFrameIndex = 0xAAAAAAA; // fastcc functions can't have varargs.
+ }
- X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
FuncInfo->setBytesToPopOnReturn(BytesToPopOnReturn);
// Return the new list of results.
@@ -1059,12 +1209,15 @@ SDOperand X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG,
&ArgValues[0], ArgValues.size()).getValue(Op.ResNo);
}
-SDOperand
-X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG,
- unsigned CC) {
+SDOperand X86TargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
+ MachineFunction &MF = DAG.getMachineFunction();
SDOperand Chain = Op.getOperand(0);
+ unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
+ bool IsTailCall = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0
+ && CC == CallingConv::Fast && PerformTailCallOpt;
SDOperand Callee = Op.getOperand(4);
+ bool Is64Bit = Subtarget->is64Bit();
assert(!(isVarArg && CC == CallingConv::Fast) &&
"Var args not supported with calling convention fastcc");
@@ -1072,24 +1225,61 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG,
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
- if (CC==CallingConv::Fast && PerformTailCallOpt)
- CCInfo.AnalyzeCallOperands(Op.Val, CC_X86_32_TailCall);
- else
- CCInfo.AnalyzeCallOperands(Op.Val, CC_X86_32_C);
+ CCInfo.AnalyzeCallOperands(Op.Val, CCAssignFnForNode(Op));
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
if (CC == CallingConv::Fast)
NumBytes = GetAlignedArgumentStackSize(NumBytes, DAG);
+ // Make sure the instruction takes 8n+4 bytes to make sure the start of the
+ // arguments and the arguments after the retaddr has been pushed are aligned.
+ if (!Is64Bit && CC == CallingConv::X86_FastCall &&
+ !Subtarget->isTargetCygMing() && !Subtarget->isTargetWindows() &&
+ (NumBytes & 7) == 0)
+ NumBytes += 4;
+
+ int FPDiff = 0;
+ if (IsTailCall) {
+ // Lower arguments at fp - stackoffset + fpdiff.
+ unsigned NumBytesCallerPushed =
+ MF.getInfo<X86MachineFunctionInfo>()->getBytesToPopOnReturn();
+ FPDiff = NumBytesCallerPushed - NumBytes;
+
+ // Set the delta of movement of the returnaddr stackslot.
+ // But only set if delta is greater than previous delta.
+ if (FPDiff < (MF.getInfo<X86MachineFunctionInfo>()->getTCReturnAddrDelta()))
+ MF.getInfo<X86MachineFunctionInfo>()->setTCReturnAddrDelta(FPDiff);
+ }
+
Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, getPointerTy()));
+ SDOperand RetAddrFrIdx, NewRetAddrFrIdx;
+ if (IsTailCall) {
+ // Adjust the Return address stack slot.
+ if (FPDiff) {
+ MVT::ValueType VT = Is64Bit ? MVT::i64 : MVT::i32;
+ RetAddrFrIdx = getReturnAddressFrameIndex(DAG);
+ // Load the "old" Return address.
+ RetAddrFrIdx =
+ 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);
+ NewRetAddrFrIdx = DAG.getFrameIndex(NewReturnAddrFI, VT);
+ Chain = SDOperand(RetAddrFrIdx.Val, 1);
+ }
+ }
+
SmallVector<std::pair<unsigned, SDOperand>, 8> RegsToPass;
SmallVector<SDOperand, 8> MemOpChains;
SDOperand StackPtr;
// Walk the register/memloc assignments, inserting copies/loads.
+ // For tail calls, lower arguments first to the stack slot where they would
+ // normally - in case of a normal function call - be.
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
SDOperand Arg = Op.getOperand(5+2*VA.getValNo());
@@ -1120,12 +1310,6 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG,
Arg));
}
}
-
- // If the first argument is an sret pointer, remember it.
- unsigned NumOps = (Op.getNumOperands() - 5) / 2;
- bool isSRet = NumOps &&
- (cast<ConstantSDNode>(Op.getOperand(6))->getValue() &
- ISD::ParamFlags::StructReturn);
if (!MemOpChains.empty())
Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
@@ -1139,10 +1323,16 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG,
InFlag);
InFlag = Chain.getValue(1);
}
-
+
+ if (IsTailCall)
+ InFlag = SDOperand(); // ??? Isn't this nuking the preceding loop's output?
+
// ELF / PIC requires GOT in the EBX register before function calls via PLT
// GOT pointer.
- if (getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
+ // Does not work with tail call since ebx is not restored correctly by
+ // tailcaller. TODO: at least for x86 - verify for x86-64
+ if (!IsTailCall && !Is64Bit &&
+ getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
Subtarget->isPICStyleGOT()) {
Chain = DAG.getCopyToReg(Chain, X86::EBX,
DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()),
@@ -1150,55 +1340,176 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG,
InFlag = Chain.getValue(1);
}
+ if (Is64Bit && isVarArg) {
+ // From AMD64 ABI document:
+ // For calls that may call functions that use varargs or stdargs
+ // (prototype-less calls or calls to functions containing ellipsis (...) in
+ // the declaration) %al is used as hidden argument to specify the number
+ // of SSE registers used. The contents of %al do not need to match exactly
+ // the number of registers, but must be an ubound on the number of SSE
+ // registers used and is in the range 0 - 8 inclusive.
+
+ // Count the number of XMM registers allocated.
+ static const unsigned XMMArgRegs[] = {
+ X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
+ X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
+ };
+ unsigned NumXMMRegs = CCInfo.getFirstUnallocated(XMMArgRegs, 8);
+
+ Chain = DAG.getCopyToReg(Chain, X86::AL,
+ DAG.getConstant(NumXMMRegs, MVT::i8), InFlag);
+ InFlag = Chain.getValue(1);
+ }
+
+ // 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.
+ // TODO: To make this more efficient (sometimes saving a store/load) we could
+ // analyse the arguments and emit this store/load/store sequence only for
+ // arguments which would be overwritten otherwise.
+ if (IsTailCall) {
+ SmallVector<SDOperand, 8> MemOpChains2;
+ SDOperand PtrOff;
+ SDOperand FIN;
+ int FI = 0;
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ CCValAssign &VA = ArgLocs[i];
+ if (!VA.isRegLoc()) {
+ SDOperand FlagsOp = Op.getOperand(6+2*VA.getValNo());
+ unsigned Flags = cast<ConstantSDNode>(FlagsOp)->getValue();
+
+ // Get source stack slot.
+ SDOperand PtrOff = DAG.getConstant(VA.getLocMemOffset(),
+ getPointerTy());
+ PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
+ // Create frame index.
+ int32_t Offset = VA.getLocMemOffset()+FPDiff;
+ uint32_t OpSize = (MVT::getSizeInBits(VA.getLocVT())+7)/8;
+ FI = MF.getFrameInfo()->CreateFixedObject(OpSize, Offset);
+ FIN = DAG.getFrameIndex(FI, MVT::i32);
+ if (Flags & ISD::ParamFlags::ByVal) {
+ // Copy relative to framepointer.
+ unsigned Align = 1 << ((Flags & ISD::ParamFlags::ByValAlign) >>
+ ISD::ParamFlags::ByValAlignOffs);
+
+ unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >>
+ ISD::ParamFlags::ByValSizeOffs;
+
+ SDOperand AlignNode = DAG.getConstant(Align, MVT::i32);
+ SDOperand SizeNode = DAG.getConstant(Size, MVT::i32);
+ SDOperand AlwaysInline = DAG.getConstant(1, MVT::i1);
+
+ MemOpChains2.push_back(DAG.getMemcpy(Chain, FIN, PtrOff, SizeNode,
+ AlignNode,AlwaysInline));
+ } else {
+ SDOperand LoadedArg = DAG.getLoad(VA.getValVT(), Chain, PtrOff,
+ NULL, 0);
+ // Store relative to framepointer.
+ MemOpChains2.push_back(DAG.getStore(Chain, LoadedArg, FIN, NULL, 0));
+ }
+ }
+ }
+
+ if (!MemOpChains2.empty())
+ 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);
+ }
+
// If the callee is a GlobalAddress node (quite common, every direct call is)
// turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
// We should use extra load for direct calls to dllimported functions in
// non-JIT mode.
- if (!Subtarget->GVRequiresExtraLoad(G->getGlobal(),
- getTargetMachine(), true))
+ if ((IsTailCall || !Is64Bit ||
+ getTargetMachine().getCodeModel() != CodeModel::Large)
+ && !Subtarget->GVRequiresExtraLoad(G->getGlobal(),
+ getTargetMachine(), true))
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
} else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
- Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
+ if (IsTailCall || !Is64Bit ||
+ getTargetMachine().getCodeModel() != CodeModel::Large)
+ Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
+ } else if (IsTailCall) {
+ assert(Callee.getOpcode() == ISD::LOAD &&
+ "Function destination must be loaded into virtual register");
+ unsigned Opc = Is64Bit ? X86::R9 : X86::ECX;
+
+ Chain = DAG.getCopyToReg(Chain,
+ DAG.getRegister(Opc, getPointerTy()) ,
+ Callee,InFlag);
+ Callee = DAG.getRegister(Opc, getPointerTy());
+ // Add register as live out.
+ DAG.getMachineFunction().getRegInfo().addLiveOut(Opc);
}
// Returns a chain & a flag for retval copy to use.
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
SmallVector<SDOperand, 8> Ops;
+
+ if (IsTailCall) {
+ Ops.push_back(Chain);
+ Ops.push_back(DAG.getConstant(NumBytes, getPointerTy()));
+ Ops.push_back(DAG.getConstant(0, getPointerTy()));
+ if (InFlag.Val)
+ Ops.push_back(InFlag);
+ Chain = DAG.getNode(ISD::CALLSEQ_END, NodeTys, &Ops[0], Ops.size());
+ InFlag = Chain.getValue(1);
+
+ // Returns a chain & a flag for retval copy to use.
+ NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
+ Ops.clear();
+ }
+
Ops.push_back(Chain);
Ops.push_back(Callee);
- // Add argument registers to the end of the list so that they are known live
- // into the call.
- for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
- Ops.push_back(DAG.getRegister(RegsToPass[i].first,
- RegsToPass[i].second.getValueType()));
+ if (IsTailCall)
+ Ops.push_back(DAG.getConstant(FPDiff, MVT::i32));
// Add an implicit use GOT pointer in EBX.
- if (getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
+ if (!IsTailCall && !Is64Bit &&
+ getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
Subtarget->isPICStyleGOT())
Ops.push_back(DAG.getRegister(X86::EBX, getPointerTy()));
+ // Add argument registers to the end of the list so that they are known live
+ // into the call.
+ if (IsTailCall)
+ for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
+ Ops.push_back(DAG.getRegister(RegsToPass[i].first,
+ RegsToPass[i].second.getValueType()));
+
if (InFlag.Val)
Ops.push_back(InFlag);
+ if (IsTailCall) {
+ assert(InFlag.Val &&
+ "Flag must be set. Depend on flag being set in LowerRET");
+ Chain = DAG.getNode(X86ISD::TAILCALL,
+ Op.Val->getVTList(), &Ops[0], Ops.size());
+
+ return SDOperand(Chain.Val, Op.ResNo);
+ }
+
Chain = DAG.getNode(X86ISD::CALL, NodeTys, &Ops[0], Ops.size());
InFlag = Chain.getValue(1);
// Create the CALLSEQ_END node.
- unsigned NumBytesForCalleeToPush = 0;
- if (!isVarArg && (CC == CallingConv::X86_StdCall
- || CC == CallingConv::Fast && PerformTailCallOpt)) {
- NumBytesForCalleeToPush = NumBytes; // Callee pops everything
- } else if (isSRet) {
+ unsigned NumBytesForCalleeToPush;
+ if (IsCalleePop(Op))
+ NumBytesForCalleeToPush = NumBytes; // Callee pops everything
+ else if (!Is64Bit && CallIsStructReturn(Op))
// If this is is a call to a struct-return function, the callee
// pops the hidden struct pointer, so we have to push it back.
// This is common for Darwin/X86, Linux & Mingw32 targets.
NumBytesForCalleeToPush = 4;
- } else {
+ else
NumBytesForCalleeToPush = 0; // Callee pops nothing.
- }
-
+
// Returns a flag for retval copy to use.
Chain = DAG.getCALLSEQ_END(Chain,
DAG.getConstant(NumBytes, getPointerTy()),
@@ -1227,90 +1538,6 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG,
// reasons.
SDOperand
-X86TargetLowering::LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG) {
- MachineFunction &MF = DAG.getMachineFunction();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- SDOperand Root = Op.getOperand(0);
- bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
- unsigned CC = MF.getFunction()->getCallingConv();
-
- assert(!(isVarArg && CC == CallingConv::Fast) &&
- "Var args not supported with calling convention fastcc");
-
- // Assign locations to all of the incoming arguments.
- SmallVector<CCValAssign, 16> ArgLocs;
- CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
- CCInfo.AnalyzeFormalArguments(Op.Val, CC_X86_32_FastCall);
-
- SmallVector<SDOperand, 8> ArgValues;
- unsigned LastVal = ~0U;
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
- CCValAssign &VA = ArgLocs[i];
- // TODO: If an arg is passed in two places (e.g. reg and stack), skip later
- // places.
- assert(VA.getValNo() != LastVal &&
- "Don't support value assigned to multiple locs yet");
- LastVal = VA.getValNo();
-
- if (VA.isRegLoc()) {
- MVT::ValueType RegVT = VA.getLocVT();
- TargetRegisterClass *RC;
- if (RegVT == MVT::i32)
- RC = X86::GR32RegisterClass;
- else {
- assert(MVT::isVector(RegVT));
- RC = X86::VR128RegisterClass;
- }
-
- unsigned Reg = AddLiveIn(DAG.getMachineFunction(), VA.getLocReg(), RC);
- SDOperand ArgValue = DAG.getCopyFromReg(Root, Reg, RegVT);
-
- // If this is an 8 or 16-bit value, it is really passed promoted to 32
- // bits. Insert an assert[sz]ext to capture this, then truncate to the
- // right size.
- if (VA.getLocInfo() == CCValAssign::SExt)
- ArgValue = DAG.getNode(ISD::AssertSext, RegVT, ArgValue,
- DAG.getValueType(VA.getValVT()));
- else if (VA.getLocInfo() == CCValAssign::ZExt)
- ArgValue = DAG.getNode(ISD::AssertZext, RegVT, ArgValue,
- DAG.getValueType(VA.getValVT()));
-
- if (VA.getLocInfo() != CCValAssign::Full)
- ArgValue = DAG.getNode(ISD::TRUNCATE, VA.getValVT(), ArgValue);
-
- ArgValues.push_back(ArgValue);
- } else {
- assert(VA.isMemLoc());
- ArgValues.push_back(LowerMemArgument(Op, DAG, VA, MFI, Root, i));
- }
- }
-
- unsigned StackSize = CCInfo.getNextStackOffset();
-
- if (!Subtarget->isTargetCygMing() && !Subtarget->isTargetWindows()) {
- // Make sure the instruction takes 8n+4 bytes to make sure the start of the
- // arguments and the arguments after the retaddr has been pushed are
- // aligned.
- if ((StackSize & 7) == 0)
- StackSize += 4;
- }
-
- ArgValues.push_back(Root);
-
- RegSaveFrameIndex = 0xAAAAAAA; // X86-64 only.
- VarArgsFrameIndex = 0xAAAAAAA; // fastcc functions can't have varargs.
- BytesToPopOnReturn = StackSize; // Callee pops all stack arguments.
- BytesCallerReserves = 0;
-
- X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
- FuncInfo->setBytesToPopOnReturn(BytesToPopOnReturn);
-
- // Return the new list of results.
- return DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(),
- &ArgValues[0], ArgValues.size()).getValue(Op.ResNo);
-}
-
-SDOperand
X86TargetLowering::LowerMemOpCallTo(SDOperand Op, SelectionDAG &DAG,
const SDOperand &StackPtr,
const CCValAssign &VA,
@@ -1338,144 +1565,6 @@ X86TargetLowering::LowerMemOpCallTo(SDOperand Op, SelectionDAG &DAG,
}
}
-SDOperand
-X86TargetLowering::LowerFastCCCallTo(SDOperand Op, SelectionDAG &DAG,
- unsigned CC) {
- SDOperand Chain = Op.getOperand(0);
- bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
- SDOperand Callee = Op.getOperand(4);
-
- assert(!cast<ConstantSDNode>(Op.getOperand(3))->getValue() &&
- "Tail calls should not reach here.");
-
- // Analyze operands of the call, assigning locations to each operand.
- SmallVector<CCValAssign, 16> ArgLocs;
- CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
- CCInfo.AnalyzeCallOperands(Op.Val, CC_X86_32_FastCall);
-
- // Get a count of how many bytes are to be pushed on the stack.
- unsigned NumBytes = CCInfo.getNextStackOffset();
- if (!Subtarget->isTargetCygMing() && !Subtarget->isTargetWindows()) {
- // Make sure the instruction takes 8n+4 bytes to make sure the start of the
- // arguments and the arguments after the retaddr has been pushed are
- // aligned.
- if ((NumBytes & 7) == 0)
- NumBytes += 4;
- }
-
- Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, getPointerTy()));
-
- SmallVector<std::pair<unsigned, SDOperand>, 8> RegsToPass;
- SmallVector<SDOperand, 8> MemOpChains;
-
- SDOperand StackPtr;
-
- // Walk the register/memloc assignments, inserting copies/loads.
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
- CCValAssign &VA = ArgLocs[i];
- SDOperand Arg = Op.getOperand(5+2*VA.getValNo());
-
- // Promote the value if needed.
- switch (VA.getLocInfo()) {
- default: assert(0 && "Unknown loc info!");
- case CCValAssign::Full: break;
- case CCValAssign::SExt:
- Arg = DAG.getNode(ISD::SIGN_EXTEND, VA.getLocVT(), Arg);
- break;
- case CCValAssign::ZExt:
- Arg = DAG.getNode(ISD::ZERO_EXTEND, VA.getLocVT(), Arg);
- break;
- case CCValAssign::AExt:
- Arg = DAG.getNode(ISD::ANY_EXTEND, VA.getLocVT(), Arg);
- break;
- }
-
- if (VA.isRegLoc()) {
- RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
- } else {
- assert(VA.isMemLoc());
- if (StackPtr.Val == 0)
- StackPtr = DAG.getRegister(getStackPtrReg(), getPointerTy());
-
- MemOpChains.push_back(LowerMemOpCallTo(Op, DAG, StackPtr, VA, Chain,
- Arg));
- }
- }
-
- if (!MemOpChains.empty())
- Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
- &MemOpChains[0], MemOpChains.size());
-
- // Build a sequence of copy-to-reg nodes chained together with token chain
- // and flag operands which copy the outgoing args into registers.
- SDOperand InFlag;
- for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
- Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
- InFlag);
- InFlag = Chain.getValue(1);
- }
-
- // If the callee is a GlobalAddress node (quite common, every direct call is)
- // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
- if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- // We should use extra load for direct calls to dllimported functions in
- // non-JIT mode.
- if (!Subtarget->GVRequiresExtraLoad(G->getGlobal(),
- getTargetMachine(), true))
- Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
- } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
- Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
- }
-
- // ELF / PIC requires GOT in the EBX register before function calls via PLT
- // GOT pointer.
- if (getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
- Subtarget->isPICStyleGOT()) {
- Chain = DAG.getCopyToReg(Chain, X86::EBX,
- DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()),
- InFlag);
- InFlag = Chain.getValue(1);
- }
-
- // Returns a chain & a flag for retval copy to use.
- SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
- SmallVector<SDOperand, 8> Ops;
- Ops.push_back(Chain);
- Ops.push_back(Callee);
-
- // Add argument registers to the end of the list so that they are known live
- // into the call.
- for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
- Ops.push_back(DAG.getRegister(RegsToPass[i].first,
- RegsToPass[i].second.getValueType()));
-
- // Add an implicit use GOT pointer in EBX.
- if (getTargetMachine().getRelocationModel() == Reloc::PIC_ &&
- Subtarget->isPICStyleGOT())
- Ops.push_back(DAG.getRegister(X86::EBX, getPointerTy()));
-
- if (InFlag.Val)
- Ops.push_back(InFlag);
-
- Chain = DAG.getNode(X86ISD::CALL, NodeTys, &Ops[0], Ops.size());
- InFlag = Chain.getValue(1);
-
- // Create the CALLSEQ_END node.
- unsigned NumBytesForCalleeToPush = NumBytes;
-
- // Returns a flag for retval copy to use.
- Chain = DAG.getCALLSEQ_END(Chain,
- DAG.getConstant(NumBytes, getPointerTy()),
- DAG.getConstant(NumBytesForCalleeToPush,
- getPointerTy()),
- InFlag);
- InFlag = Chain.getValue(1);
-
- // Handle result values, copying them out of physregs into vregs that we
- // return.
- return SDOperand(LowerCallResult(Chain, InFlag, Op.Val, CC, DAG), Op.ResNo);
-}
-
//===----------------------------------------------------------------------===//
// Fast Calling Convention (tail call) implementation
//===----------------------------------------------------------------------===//
@@ -1563,546 +1652,15 @@ bool X86TargetLowering::IsEligibleForTailCallOptimization(SDOperand Call,
return true;
// Can only do local tail calls with PIC.
- GlobalValue * GV = 0;
- GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee);
- if(G != 0 &&
- (GV = G->getGlobal()) &&
- (GV->hasHiddenVisibility() || GV->hasProtectedVisibility()))
- return true;
+ if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
+ return G->getGlobal()->hasHiddenVisibility()
+ || G->getGlobal()->hasProtectedVisibility();
}
}
return false;
}
-SDOperand
-X86TargetLowering::LowerX86_TailCallTo(SDOperand Op, SelectionDAG &DAG,
- unsigned CC) {
- SDOperand Chain = Op.getOperand(0);
- bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
- SDOperand Callee = Op.getOperand(4);
- bool is64Bit = Subtarget->is64Bit();
-
- assert(cast<ConstantSDNode>(Op.getOperand(3))->getValue() &&PerformTailCallOpt
- && "Should only emit tail calls.");
-
- // Analyze operands of the call, assigning locations to each operand.
- SmallVector<CCValAssign, 16> ArgLocs;
- CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
- if (is64Bit)
- CCInfo.AnalyzeCallOperands(Op.Val, CC_X86_64_TailCall);
- else
- CCInfo.AnalyzeCallOperands(Op.Val, CC_X86_32_TailCall);
-
- // Lower arguments at fp - stackoffset + fpdiff.
- MachineFunction &MF = DAG.getMachineFunction();
-
- unsigned NumBytesToBePushed =
- GetAlignedArgumentStackSize(CCInfo.getNextStackOffset(), DAG);
-
- unsigned NumBytesCallerPushed =
- MF.getInfo<X86MachineFunctionInfo>()->getBytesToPopOnReturn();
- int FPDiff = NumBytesCallerPushed - NumBytesToBePushed;
-
- // Set the delta of movement of the returnaddr stackslot.
- // But only set if delta is greater than previous delta.
- if (FPDiff < (MF.getInfo<X86MachineFunctionInfo>()->getTCReturnAddrDelta()))
- MF.getInfo<X86MachineFunctionInfo>()->setTCReturnAddrDelta(FPDiff);
-
- 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;
- RetAddrFrIdx = getReturnAddressFrameIndex(DAG);
- // Load the "old" Return address.
- RetAddrFrIdx =
- 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);
- NewRetAddrFrIdx = DAG.getFrameIndex(NewReturnAddrFI, VT);
- Chain = SDOperand(RetAddrFrIdx.Val, 1);
- }
-
- SmallVector<std::pair<unsigned, SDOperand>, 8> RegsToPass;
- SmallVector<SDOperand, 8> MemOpChains;
- SmallVector<SDOperand, 8> MemOpChains2;
- SDOperand FramePtr, StackPtr;
- SDOperand PtrOff;
- SDOperand FIN;
- int FI = 0;
-
- // Walk the register/memloc assignments, inserting copies/loads. Lower
- // arguments first to the stack slot where they would normally - in case of a
- // normal function call - be.
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
- CCValAssign &VA = ArgLocs[i];
- SDOperand Arg = Op.getOperand(5+2*VA.getValNo());
-
- // Promote the value if needed.
- switch (VA.getLocInfo()) {
- default: assert(0 && "Unknown loc info!");
- case CCValAssign::Full: break;
- case CCValAssign::SExt:
- Arg = DAG.getNode(ISD::SIGN_EXTEND, VA.getLocVT(), Arg);
- break;
- case CCValAssign::ZExt:
- Arg = DAG.getNode(ISD::ZERO_EXTEND, VA.getLocVT(), Arg);
- break;
- case CCValAssign::AExt:
- Arg = DAG.getNode(ISD::ANY_EXTEND, VA.getLocVT(), Arg);
- break;
- }
-
- if (VA.isRegLoc()) {
- RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
- } else {
- assert(VA.isMemLoc());
- if (StackPtr.Val == 0)
- StackPtr = DAG.getRegister(getStackPtrReg(), getPointerTy());
-
- MemOpChains.push_back(LowerMemOpCallTo(Op, DAG, StackPtr, VA, Chain,
- Arg));
- }
- }
-
- if (!MemOpChains.empty())
- Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
- &MemOpChains[0], MemOpChains.size());
-
- // Build a sequence of copy-to-reg nodes chained together with token chain
- // and flag operands which copy the outgoing args into registers.
- SDOperand InFlag;
- for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
- Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
- InFlag);
- 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.
- // TODO: To make this more efficient (sometimes saving a store/load) we could
- // analyse the arguments and emit this store/load/store sequence only for
- // arguments which would be overwritten otherwise.
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
- CCValAssign &VA = ArgLocs[i];
- if (!VA.isRegLoc()) {
- SDOperand FlagsOp = Op.getOperand(6+2*VA.getValNo());
- unsigned Flags = cast<ConstantSDNode>(FlagsOp)->getValue();
-
- // Get source stack slot.
- SDOperand PtrOff = DAG.getConstant(VA.getLocMemOffset(), getPointerTy());
- PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
- // Create frame index.
- int32_t Offset = VA.getLocMemOffset()+FPDiff;
- uint32_t OpSize = (MVT::getSizeInBits(VA.getLocVT())+7)/8;
- FI = MF.getFrameInfo()->CreateFixedObject(OpSize, Offset);
- FIN = DAG.getFrameIndex(FI, MVT::i32);
- if (Flags & ISD::ParamFlags::ByVal) {
- // Copy relative to framepointer.
- unsigned Align = 1 << ((Flags & ISD::ParamFlags::ByValAlign) >>
- ISD::ParamFlags::ByValAlignOffs);
-
- unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >>
- ISD::ParamFlags::ByValSizeOffs;
-
- SDOperand AlignNode = DAG.getConstant(Align, MVT::i32);
- SDOperand SizeNode = DAG.getConstant(Size, MVT::i32);
- SDOperand AlwaysInline = DAG.getConstant(1, MVT::i1);
-
- MemOpChains2.push_back(DAG.getMemcpy(Chain, FIN, PtrOff, SizeNode,
- AlignNode,AlwaysInline));
- } else {
- SDOperand LoadedArg = DAG.getLoad(VA.getValVT(), Chain, PtrOff, NULL,0);
- // Store relative to framepointer.
- MemOpChains2.push_back(DAG.getStore(Chain, LoadedArg, FIN, NULL, 0));
- }
- }
- }
-
- if (!MemOpChains2.empty())
- 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
- // tailcaller. TODO: at least for x86 - verify for x86-64
-
- // If the callee is a GlobalAddress node (quite common, every direct call is)
- // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
- if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- // We should use extra load for direct calls to dllimported functions in
- // non-JIT mode.
- if (!Subtarget->GVRequiresExtraLoad(G->getGlobal(),
- getTargetMachine(), true))
- Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
- } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
- Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
- else {
- assert(Callee.getOpcode() == ISD::LOAD &&
- "Function destination must be loaded into virtual register");
- unsigned Opc = is64Bit ? X86::R9 : X86::ECX;
-
- Chain = DAG.getCopyToReg(Chain,
- DAG.getRegister(Opc, getPointerTy()) ,
- Callee,InFlag);
- Callee = DAG.getRegister(Opc, getPointerTy());
- // Add register as live out.
- DAG.getMachineFunction().getRegInfo().addLiveOut(Opc);
- }
-
- SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
- SmallVector<SDOperand, 8> Ops;
-
- Ops.push_back(Chain);
- Ops.push_back(DAG.getConstant(NumBytesToBePushed, getPointerTy()));
- Ops.push_back(DAG.getConstant(0, getPointerTy()));
- if (InFlag.Val)
- Ops.push_back(InFlag);
- Chain = DAG.getNode(ISD::CALLSEQ_END, NodeTys, &Ops[0], Ops.size());
- InFlag = Chain.getValue(1);
-
- // Returns a chain & a flag for retval copy to use.
- NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
- Ops.clear();
- Ops.push_back(Chain);
- Ops.push_back(Callee);
- Ops.push_back(DAG.getConstant(FPDiff, MVT::i32));
- // Add argument registers to the end of the list so that they are known live
- // into the call.
- for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
- Ops.push_back(DAG.getRegister(RegsToPass[i].first,
- RegsToPass[i].second.getValueType()));
- if (InFlag.Val)
- Ops.push_back(InFlag);
- assert(InFlag.Val &&
- "Flag must be set. Depend on flag being set in LowerRET");
- Chain = DAG.getNode(X86ISD::TAILCALL,
- Op.Val->getVTList(), &Ops[0], Ops.size());
-
- return SDOperand(Chain.Val, Op.ResNo);
-}
-
-//===----------------------------------------------------------------------===//
-// X86-64 C Calling Convention implementation
-//===----------------------------------------------------------------------===//
-
-SDOperand
-X86TargetLowering::LowerX86_64CCCArguments(SDOperand Op, SelectionDAG &DAG) {
- MachineFunction &MF = DAG.getMachineFunction();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- SDOperand Root = Op.getOperand(0);
- bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
- unsigned CC = MF.getFunction()->getCallingConv();
-
- assert(!(isVarArg && CC == CallingConv::Fast) &&
- "Var args not supported with calling convention fastcc");
-
- static const unsigned GPR64ArgRegs[] = {
- X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8, X86::R9
- };
- static const unsigned XMMArgRegs[] = {
- X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
- X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
- };
-
- // Assign locations to all of the incoming arguments.
- SmallVector<CCValAssign, 16> ArgLocs;
- CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
- // Check for possible tail call calling convention.
- if (CC == CallingConv::Fast && PerformTailCallOpt)
- CCInfo.AnalyzeFormalArguments(Op.Val, CC_X86_64_TailCall);
- else
- CCInfo.AnalyzeFormalArguments(Op.Val, CC_X86_64_C);
-
- SmallVector<SDOperand, 8> ArgValues;
- unsigned LastVal = ~0U;
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
- CCValAssign &VA = ArgLocs[i];
- // TODO: If an arg is passed in two places (e.g. reg and stack), skip later
- // places.
- assert(VA.getValNo() != LastVal &&
- "Don't support value assigned to multiple locs yet");
- LastVal = VA.getValNo();
-
- if (VA.isRegLoc()) {
- MVT::ValueType RegVT = VA.getLocVT();
- TargetRegisterClass *RC;
- if (RegVT == MVT::i32)
- RC = X86::GR32RegisterClass;
- else if (RegVT == MVT::i64)
- RC = X86::GR64RegisterClass;
- else if (RegVT == MVT::f32)
- RC = X86::FR32RegisterClass;
- else if (RegVT == MVT::f64)
- RC = X86::FR64RegisterClass;
- else {
- assert(MVT::isVector(RegVT));
- if (MVT::getSizeInBits(RegVT) == 64) {
- RC = X86::GR64RegisterClass; // MMX values are passed in GPRs.
- RegVT = MVT::i64;
- } else
- RC = X86::VR128RegisterClass;
- }
-
- unsigned Reg = AddLiveIn(DAG.getMachineFunction(), VA.getLocReg(), RC);
- SDOperand ArgValue = DAG.getCopyFromReg(Root, Reg, RegVT);
-
- // If this is an 8 or 16-bit value, it is really passed promoted to 32
- // bits. Insert an assert[sz]ext to capture this, then truncate to the
- // right size.
- if (VA.getLocInfo() == CCValAssign::SExt)
- ArgValue = DAG.getNode(ISD::AssertSext, RegVT, ArgValue,
- DAG.getValueType(VA.getValVT()));
- else if (VA.getLocInfo() == CCValAssign::ZExt)
- ArgValue = DAG.getNode(ISD::AssertZext, RegVT, ArgValue,
- DAG.getValueType(VA.getValVT()));
-
- if (VA.getLocInfo() != CCValAssign::Full)
- ArgValue = DAG.getNode(ISD::TRUNCATE, VA.getValVT(), ArgValue);
-
- // Handle MMX values passed in GPRs.
- if (RegVT != VA.getLocVT() && RC == X86::GR64RegisterClass &&
- MVT::getSizeInBits(RegVT) == 64)
- ArgValue = DAG.getNode(ISD::BIT_CONVERT, VA.getLocVT(), ArgValue);
-
- ArgValues.push_back(ArgValue);
- } else {
- assert(VA.isMemLoc());
- ArgValues.push_back(LowerMemArgument(Op, DAG, VA, MFI, Root, i));
- }
- }
-
- unsigned StackSize = CCInfo.getNextStackOffset();
- // align stack specially for tail calls
- if (CC == CallingConv::Fast)
- StackSize = GetAlignedArgumentStackSize(StackSize, DAG);
-
- // 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 (isVarArg) {
- unsigned NumIntRegs = CCInfo.getFirstUnallocated(GPR64ArgRegs, 6);
- unsigned NumXMMRegs = CCInfo.getFirstUnallocated(XMMArgRegs, 8);
-
- // For X86-64, if there are vararg parameters that are passed via
- // registers, then we must store them to their spots on the stack so they
- // may be loaded by deferencing the result of va_next.
- VarArgsGPOffset = NumIntRegs * 8;
- VarArgsFPOffset = 6 * 8 + NumXMMRegs * 16;
- VarArgsFrameIndex = MFI->CreateFixedObject(1, StackSize);
- RegSaveFrameIndex = MFI->CreateStackObject(6 * 8 + 8 * 16, 16);
-
- // Store the integer parameter registers.
- SmallVector<SDOperand, 8> MemOps;
- SDOperand RSFIN = DAG.getFrameIndex(RegSaveFrameIndex, getPointerTy());
- SDOperand FIN = DAG.getNode(ISD::ADD, getPointerTy(), RSFIN,
- DAG.getConstant(VarArgsGPOffset, getPointerTy()));
- for (; NumIntRegs != 6; ++NumIntRegs) {
- unsigned VReg = AddLiveIn(MF, GPR64ArgRegs[NumIntRegs],
- X86::GR64RegisterClass);
- SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::i64);
- SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
- MemOps.push_back(Store);
- FIN = DAG.getNode(ISD::ADD, getPointerTy(), FIN,
- DAG.getConstant(8, getPointerTy()));
- }
-
- // Now store the XMM (fp + vector) parameter registers.
- FIN = DAG.getNode(ISD::ADD, getPointerTy(), RSFIN,
- DAG.getConstant(VarArgsFPOffset, getPointerTy()));
- for (; NumXMMRegs != 8; ++NumXMMRegs) {
- unsigned VReg = AddLiveIn(MF, XMMArgRegs[NumXMMRegs],
- X86::VR128RegisterClass);
- SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::v4f32);
- SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
- MemOps.push_back(Store);
- FIN = DAG.getNode(ISD::ADD, getPointerTy(), FIN,
- DAG.getConstant(16, getPointerTy()));
- }
- if (!MemOps.empty())
- Root = DAG.getNode(ISD::TokenFactor, MVT::Other,
- &MemOps[0], MemOps.size());
- }
-
- ArgValues.push_back(Root);
-
- // Tail call convention (fastcc) needs callee pop.
- if (CC == CallingConv::Fast && PerformTailCallOpt) {
- BytesToPopOnReturn = StackSize; // Callee pops everything.
- BytesCallerReserves = 0;
- } else {
- BytesToPopOnReturn = 0; // Callee pops nothing.
- BytesCallerReserves = StackSize;
- }
- X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
- FuncInfo->setBytesToPopOnReturn(BytesToPopOnReturn);
-
- // Return the new list of results.
- return DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(),
- &ArgValues[0], ArgValues.size()).getValue(Op.ResNo);
-}
-
-SDOperand
-X86TargetLowering::LowerX86_64CCCCallTo(SDOperand Op, SelectionDAG &DAG,
- unsigned CC) {
- SDOperand Chain = Op.getOperand(0);
- bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
- SDOperand Callee = Op.getOperand(4);
-
- assert(!(isVarArg && CC == CallingConv::Fast) &&
- "Var args not supported with calling convention fastcc");
-
- // Analyze operands of the call, assigning locations to each operand.
- SmallVector<CCValAssign, 16> ArgLocs;
- CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
- if (CC==CallingConv::Fast && PerformTailCallOpt)
- CCInfo.AnalyzeCallOperands(Op.Val, CC_X86_64_TailCall);
- else
- CCInfo.AnalyzeCallOperands(Op.Val, CC_X86_64_C);
-
- // Get a count of how many bytes are to be pushed on the stack.
- unsigned NumBytes = CCInfo.getNextStackOffset();
- if (CC == CallingConv::Fast)
- NumBytes = GetAlignedArgumentStackSize(NumBytes, DAG);
-
- Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, getPointerTy()));
-
- SmallVector<std::pair<unsigned, SDOperand>, 8> RegsToPass;
- SmallVector<SDOperand, 8> MemOpChains;
-
- SDOperand StackPtr;
-
- // Walk the register/memloc assignments, inserting copies/loads.
- for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
- CCValAssign &VA = ArgLocs[i];
- SDOperand Arg = Op.getOperand(5+2*VA.getValNo());
-
- // Promote the value if needed.
- switch (VA.getLocInfo()) {
- default: assert(0 && "Unknown loc info!");
- case CCValAssign::Full: break;
- case CCValAssign::SExt:
- Arg = DAG.getNode(ISD::SIGN_EXTEND, VA.getLocVT(), Arg);
- break;
- case CCValAssign::ZExt:
- Arg = DAG.getNode(ISD::ZERO_EXTEND, VA.getLocVT(), Arg);
- break;
- case CCValAssign::AExt:
- Arg = DAG.getNode(ISD::ANY_EXTEND, VA.getLocVT(), Arg);
- break;
- }
-
- if (VA.isRegLoc()) {
- RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
- } else {
- assert(VA.isMemLoc());
- if (StackPtr.Val == 0)
- StackPtr = DAG.getRegister(getStackPtrReg(), getPointerTy());
-
- MemOpChains.push_back(LowerMemOpCallTo(Op, DAG, StackPtr, VA, Chain,
- Arg));
- }
- }
-
- if (!MemOpChains.empty())
- Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
- &MemOpChains[0], MemOpChains.size());
-
- // Build a sequence of copy-to-reg nodes chained together with token chain
- // and flag operands which copy the outgoing args into registers.
- SDOperand InFlag;
- for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
- Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
- InFlag);
- InFlag = Chain.getValue(1);
- }
-
- if (isVarArg) {
- // From AMD64 ABI document:
- // For calls that may call functions that use varargs or stdargs
- // (prototype-less calls or calls to functions containing ellipsis (...) in
- // the declaration) %al is used as hidden argument to specify the number
- // of SSE registers used. The contents of %al do not need to match exactly
- // the number of registers, but must be an ubound on the number of SSE
- // registers used and is in the range 0 - 8 inclusive.
-
- // Count the number of XMM registers allocated.
- static const unsigned XMMArgRegs[] = {
- X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
- X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
- };
- unsigned NumXMMRegs = CCInfo.getFirstUnallocated(XMMArgRegs, 8);
-
- Chain = DAG.getCopyToReg(Chain, X86::AL,
- DAG.getConstant(NumXMMRegs, MVT::i8), InFlag);
- InFlag = Chain.getValue(1);
- }
-
- // If the callee is a GlobalAddress node (quite common, every direct call is)
- // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
- if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- // We should use extra load for direct calls to dllimported functions in
- // non-JIT mode.
- if (getTargetMachine().getCodeModel() != CodeModel::Large
- && !Subtarget->GVRequiresExtraLoad(G->getGlobal(),
- getTargetMachine(), true))
- Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
- } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
- if (getTargetMachine().getCodeModel() != CodeModel::Large)
- Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
- }
-
- // Returns a chain & a flag for retval copy to use.
- SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
- SmallVector<SDOperand, 8> Ops;
- Ops.push_back(Chain);
- Ops.push_back(Callee);
-
- // Add argument registers to the end of the list so that they are known live
- // into the call.
- for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
- Ops.push_back(DAG.getRegister(RegsToPass[i].first,
- RegsToPass[i].second.getValueType()));
-
- if (InFlag.Val)
- Ops.push_back(InFlag);
-
- Chain = DAG.getNode(X86ISD::CALL, NodeTys, &Ops[0], Ops.size());
- InFlag = Chain.getValue(1);
-
- // Create the CALLSEQ_END node.
- unsigned NumBytesForCalleeToPush = 0;
- if (CC == CallingConv::Fast && PerformTailCallOpt) {
- NumBytesForCalleeToPush = NumBytes; // Callee pops everything
- } else {
- NumBytesForCalleeToPush = 0; // Callee pops nothing.
- }
-
- // Returns a flag for retval copy to use.
- Chain = DAG.getCALLSEQ_END(Chain,
- DAG.getConstant(NumBytes, getPointerTy()),
- DAG.getConstant(NumBytesForCalleeToPush,
- getPointerTy()),
- InFlag);
- InFlag = Chain.getValue(1);
-
- // Handle result values, copying them out of physregs into vregs that we
- // return.
- return SDOperand(LowerCallResult(Chain, InFlag, Op.Val, CC, DAG), Op.ResNo);
-}
-
-
//===----------------------------------------------------------------------===//
// Other Lowering Hooks
//===----------------------------------------------------------------------===//
@@ -4680,32 +4238,6 @@ SDOperand X86TargetLowering::LowerBRCOND(SDOperand Op, SelectionDAG &DAG) {
Chain, Op.getOperand(2), CC, Cond);
}
-SDOperand X86TargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
- unsigned CallingConv = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
- bool isTailCall = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0;
-
- if (Subtarget->is64Bit())
- if(CallingConv==CallingConv::Fast && isTailCall && PerformTailCallOpt)
- return LowerX86_TailCallTo(Op, DAG, CallingConv);
- else
- return LowerX86_64CCCCallTo(Op, DAG, CallingConv);
- else
- switch (CallingConv) {
- default:
- assert(0 && "Unsupported calling convention");
- case CallingConv::Fast:
- if (isTailCall && PerformTailCallOpt)
- return LowerX86_TailCallTo(Op, DAG, CallingConv);
- else
- return LowerCCCCallTo(Op,DAG, CallingConv);
- case CallingConv::C:
- case CallingConv::X86_StdCall:
- return LowerCCCCallTo(Op, DAG, CallingConv);
- case CallingConv::X86_FastCall:
- return LowerFastCCCallTo(Op, DAG, CallingConv);
- }
-}
-
// Lower dynamic stack allocation to _alloca call for Cygwin/Mingw targets.
// Calls to _alloca is needed to probe the stack when allocating more than 4k
@@ -4748,35 +4280,6 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDOperand Op,
return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops1, 2);
}
-SDOperand
-X86TargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) {
- MachineFunction &MF = DAG.getMachineFunction();
- const Function* Fn = MF.getFunction();
- if (Fn->hasExternalLinkage() &&
- Subtarget->isTargetCygMing() &&
- Fn->getName() == "main")
- MF.getInfo<X86MachineFunctionInfo>()->setForceFramePointer(true);
-
- unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
- if (Subtarget->is64Bit())
- return LowerX86_64CCCArguments(Op, DAG);
- else
- switch(CC) {
- default:
- assert(0 && "Unsupported calling convention");
- case CallingConv::Fast:
- return LowerCCCArguments(Op, DAG, true);
- case CallingConv::C:
- return LowerCCCArguments(Op, DAG);
- case CallingConv::X86_StdCall:
- MF.getInfo<X86MachineFunctionInfo>()->setDecorationStyle(StdCall);
- return LowerCCCArguments(Op, DAG, true);
- case CallingConv::X86_FastCall:
- MF.getInfo<X86MachineFunctionInfo>()->setDecorationStyle(FastCall);
- return LowerFastCCArguments(Op, DAG);
- }
-}
-
SDOperand X86TargetLowering::LowerMEMSET(SDOperand Op, SelectionDAG &DAG) {
SDOperand InFlag(0, 0);
SDOperand Chain = Op.getOperand(0);
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index bcfab641fd..64324f3dc5 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -17,6 +17,7 @@
#include "X86Subtarget.h"
#include "X86RegisterInfo.h"
+#include "X86MachineFunctionInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/CallingConvLower.h"
@@ -438,22 +439,11 @@ namespace llvm {
const CCValAssign &VA, SDOperand Chain,
SDOperand Arg);
- // C and StdCall Calling Convention implementation.
- SDOperand LowerCCCArguments(SDOperand Op, SelectionDAG &DAG,
- bool isStdCall = false);
- SDOperand LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC);
-
- // X86-64 C Calling Convention implementation.
- SDOperand LowerX86_64CCCArguments(SDOperand Op, SelectionDAG &DAG);
- SDOperand LowerX86_64CCCCallTo(SDOperand Op, SelectionDAG &DAG,unsigned CC);
-
- // fast calling convention (tail call) implementation for 32/64bit
- SDOperand LowerX86_TailCallTo(SDOperand Op,
- SelectionDAG & DAG, unsigned CC);
+ // Call lowering helpers.
+ bool IsCalleePop(SDOperand Op);
+ CCAssignFn *CCAssignFnForNode(SDOperand Op) const;
+ NameDecorationStyle NameDecorationForFORMAL_ARGUMENTS(SDOperand Op);
unsigned GetAlignedArgumentStackSize(unsigned StackSize, SelectionDAG &DAG);
- // Fast and FastCall Calling Convention implementation.
- SDOperand LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG);
- SDOperand LowerFastCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC);
std::pair<SDOperand,SDOperand> FP_TO_SINTHelper(SDOperand Op,
SelectionDAG &DAG);