[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelLowering.cpp
Chris Lattner
sabre at nondot.org
Sun Feb 25 23:50:19 PST 2007
Changes in directory llvm/lib/Target/X86:
X86ISelLowering.cpp updated: 1.339 -> 1.340
---
Log message:
initial hack at splitting the x86-64 calling convention info out from the
mechanics that process it. I'm still not happy with this, but it's a step
in the right direction.
---
Diffs of the changes: (+300 -272)
X86ISelLowering.cpp | 572 +++++++++++++++++++++++++++-------------------------
1 files changed, 300 insertions(+), 272 deletions(-)
Index: llvm/lib/Target/X86/X86ISelLowering.cpp
diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.339 llvm/lib/Target/X86/X86ISelLowering.cpp:1.340
--- llvm/lib/Target/X86/X86ISelLowering.cpp:1.339 Sun Feb 25 23:21:05 2007
+++ llvm/lib/Target/X86/X86ISelLowering.cpp Mon Feb 26 01:50:02 2007
@@ -833,7 +833,7 @@
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(),
- &ArgValues[0], ArgValues.size());
+ &ArgValues[0], ArgValues.size()).getValue(Op.ResNo);
}
SDOperand X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG,
@@ -1058,63 +1058,264 @@
// X86-64 C Calling Convention implementation
//===----------------------------------------------------------------------===//
-/// HowToPassX86_64CCCArgument - Returns how an formal argument of the specified
-/// type should be passed. If it is through stack, returns the size of the stack
-/// slot; if it is through integer or XMM register, returns the number of
-/// integer or XMM registers are needed.
-static void
-HowToPassX86_64CCCArgument(MVT::ValueType ObjectVT,
- unsigned NumIntRegs, unsigned NumXMMRegs,
- unsigned &ObjSize, unsigned &ObjIntRegs,
- unsigned &ObjXMMRegs) {
- ObjSize = 0;
- ObjIntRegs = 0;
- ObjXMMRegs = 0;
+class CallingConvState {
+ uint32_t UsedRegs[(X86::NUM_TARGET_REGS+31)/32];
+ unsigned StackOffset;
+ const MRegisterInfo &MRI;
+public:
+ CallingConvState(const MRegisterInfo &mri) : MRI(mri) {
+ // No stack is used.
+ StackOffset = 0;
+
+ UsedRegs.resize(MRI.getNumRegs());
+ // No registers are used.
+ memset(UsedRegs, 0, sizeof(UsedRegs));
+ }
+
+ unsigned getNextStackOffset() const { return StackOffset; }
- switch (ObjectVT) {
- default: assert(0 && "Unhandled argument type!");
- case MVT::i8:
- case MVT::i16:
- case MVT::i32:
- case MVT::i64:
- if (NumIntRegs < 6)
- ObjIntRegs = 1;
- else {
- switch (ObjectVT) {
- default: break;
- case MVT::i8: ObjSize = 1; break;
- case MVT::i16: ObjSize = 2; break;
- case MVT::i32: ObjSize = 4; break;
- case MVT::i64: ObjSize = 8; break;
- }
+ /// isAllocated - Return true if the specified register (or an alias) is
+ /// allocated.
+ bool isAllocated(unsigned Reg) const {
+ return UsedRegs[Reg/32] & (1 << (Reg&31));
+ }
+
+ /// getFirstUnallocated - Return the first unallocated register in the set, or
+ /// NumRegs if they are all allocated.
+ unsigned getFirstUnallocated(const unsigned *Regs, unsigned NumRegs) const {
+ for (unsigned i = 0; i != NumRegs; ++i)
+ if (!isAllocated(Regs[i]))
+ return i;
+ return NumRegs;
+ }
+
+ /// AllocateReg - Attempt to allocate one of the specified registers. If none
+ /// are available, return zero. Otherwise, return the first one available,
+ /// marking it and any aliases as allocated.
+ unsigned AllocateReg(const unsigned *Regs, unsigned NumRegs) {
+ unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs);
+ if (FirstUnalloc == NumRegs)
+ return 0; // Didn't find the reg.
+
+ // Mark the register and any aliases as allocated.
+ unsigned Reg = Regs[FirstUnalloc];
+ MarkAllocated(Reg);
+ if (const unsigned *RegAliases = MRI.getAliasSet(Reg))
+ for (; *RegAliases; ++RegAliases)
+ MarkAllocated(*RegAliases);
+ return Reg;
+ }
+
+ /// AllocateStack - Allocate a chunk of stack space with the specified size
+ /// and alignment.
+ unsigned AllocateStack(unsigned Size, unsigned Align) {
+ assert(Align && ((Align-1) & Align) == 0); // Align is power of 2.
+ StackOffset = ((StackOffset + Align-1) & ~(Align-1));
+ unsigned Result = StackOffset;
+ StackOffset += Size;
+ return Result;
+ }
+private:
+ void MarkAllocated(unsigned Reg) {
+ UsedRegs[Reg/32] |= 1 << (Reg&31);
+ }
+};
+
+/// X86_64_CCC_AssignArgument - Implement the X86-64 C Calling Convention.
+template<typename Client, typename DataTy>
+static void X86_64_CCC_AssignArgument(Client &C, CallingConvState &State,
+ MVT::ValueType ArgVT, unsigned ArgFlags,
+ DataTy Data) {
+ MVT::ValueType LocVT = ArgVT;
+ unsigned ExtendType = ISD::ANY_EXTEND;
+
+ // Promote the integer to 32 bits. If the input type is signed use a
+ // sign extend, otherwise use a zero extend.
+ if (ArgVT == MVT::i8 || ArgVT == MVT::i16) {
+ LocVT = MVT::i32;
+ ExtendType = (ArgFlags & 1) ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
+ }
+
+ // If this is a 32-bit value, assign to a 32-bit register if any are
+ // available.
+ if (LocVT == MVT::i32) {
+ static const unsigned GPR32ArgRegs[] = {
+ X86::EDI, X86::ESI, X86::EDX, X86::ECX, X86::R8D, X86::R9D
+ };
+ if (unsigned Reg = State.AllocateReg(GPR32ArgRegs, 6)) {
+ C.AssignToReg(Data, Reg, ArgVT, LocVT, ExtendType);
+ return;
}
- break;
- case MVT::f32:
- case MVT::f64:
- case MVT::v16i8:
- case MVT::v8i16:
- case MVT::v4i32:
- case MVT::v2i64:
- case MVT::v4f32:
- case MVT::v2f64:
- if (NumXMMRegs < 8)
- ObjXMMRegs = 1;
+ }
+
+ // If this is a 64-bit value, assign to a 64-bit register if any are
+ // available.
+ if (LocVT == MVT::i64) {
+ static const unsigned GPR64ArgRegs[] = {
+ X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8, X86::R9
+ };
+ if (unsigned Reg = State.AllocateReg(GPR64ArgRegs, 6)) {
+ C.AssignToReg(Data, Reg, ArgVT, LocVT, ExtendType);
+ return;
+ }
+ }
+
+ // If this is a FP or vector type, assign to an XMM reg if any are
+ // available.
+ if (MVT::isVector(LocVT) || MVT::isFloatingPoint(LocVT)) {
+ static const unsigned XMMArgRegs[] = {
+ X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
+ X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
+ };
+ if (unsigned Reg = State.AllocateReg(XMMArgRegs, 8)) {
+ C.AssignToReg(Data, Reg, ArgVT, LocVT, ExtendType);
+ return;
+ }
+ }
+
+ // Integer/FP values get stored in stack slots that are 8 bytes in size and
+ // 8-byte aligned if there are no more registers to hold them.
+ if (LocVT == MVT::i32 || LocVT == MVT::i64 ||
+ LocVT == MVT::f32 || LocVT == MVT::f64) {
+ unsigned Offset = State.AllocateStack(8, 8);
+ C.AssignToStack(Data, Offset, ArgVT, LocVT, ExtendType);
+ return;
+ }
+
+ // Vectors get 16-byte stack slots that are 16-byte aligned.
+ if (MVT::isVector(LocVT)) {
+ unsigned Offset = State.AllocateStack(16, 16);
+ C.AssignToStack(Data, Offset, ArgVT, LocVT, ExtendType);
+ return;
+ }
+ assert(0 && "Unknown argument type!");
+}
+
+class LowerArgumentsClient {
+ SelectionDAG &DAG;
+ X86TargetLowering &TLI;
+ SmallVector<SDOperand, 8> &ArgValues;
+ SDOperand Chain;
+public:
+ LowerArgumentsClient(SelectionDAG &dag, X86TargetLowering &tli,
+ SmallVector<SDOperand, 8> &argvalues,
+ SDOperand chain)
+ : DAG(dag), TLI(tli), ArgValues(argvalues), Chain(chain) {
+
+ }
+
+ void AssignToReg(SDOperand Arg, unsigned RegNo,
+ MVT::ValueType ArgVT, MVT::ValueType RegVT,
+ unsigned ExtendType) {
+ TargetRegisterClass *RC = NULL;
+ 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 {
- switch (ObjectVT) {
- default: break;
- case MVT::f32: ObjSize = 4; break;
- case MVT::f64: ObjSize = 8; break;
- case MVT::v16i8:
- case MVT::v8i16:
- case MVT::v4i32:
- case MVT::v2i64:
- case MVT::v4f32:
- case MVT::v2f64: ObjSize = 16; break;
+ RC = X86::VR128RegisterClass;
}
- break;
+
+ SDOperand ArgValue = DAG.getCopyFromReg(Chain, RegNo, RegVT);
+ AddLiveIn(DAG.getMachineFunction(), RegNo, RC);
+
+ // 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 (ArgVT < RegVT) {
+ if (ExtendType == ISD::SIGN_EXTEND) {
+ ArgValue = DAG.getNode(ISD::AssertSext, RegVT, ArgValue,
+ DAG.getValueType(ArgVT));
+ } else if (ExtendType == ISD::ZERO_EXTEND) {
+ ArgValue = DAG.getNode(ISD::AssertZext, RegVT, ArgValue,
+ DAG.getValueType(ArgVT));
+ }
+ ArgValue = DAG.getNode(ISD::TRUNCATE, ArgVT, ArgValue);
+ }
+
+ ArgValues.push_back(ArgValue);
}
+
+ void AssignToStack(SDOperand Arg, unsigned Offset,
+ MVT::ValueType ArgVT, MVT::ValueType DestVT,
+ unsigned ExtendType) {
+ // Create the SelectionDAG nodes corresponding to a load from this
+ // parameter.
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ int FI = MFI->CreateFixedObject(MVT::getSizeInBits(ArgVT)/8, Offset);
+ SDOperand FIN = DAG.getFrameIndex(FI, TLI.getPointerTy());
+ ArgValues.push_back(DAG.getLoad(ArgVT, Chain, FIN, NULL, 0));
+ }
+};
+
+class LowerCallArgumentsClient {
+ SelectionDAG &DAG;
+ X86TargetLowering &TLI;
+ SmallVector<std::pair<unsigned, SDOperand>, 8> &RegsToPass;
+ SmallVector<SDOperand, 8> &MemOpChains;
+ SDOperand Chain;
+ SDOperand StackPtr;
+public:
+ LowerCallArgumentsClient(SelectionDAG &dag, X86TargetLowering &tli,
+ SmallVector<std::pair<unsigned, SDOperand>, 8> &rtp,
+ SmallVector<SDOperand, 8> &moc,
+ SDOperand chain)
+ : DAG(dag), TLI(tli), RegsToPass(rtp), MemOpChains(moc), Chain(chain) {
+
}
-}
+
+ void AssignToReg(SDOperand Arg, unsigned RegNo,
+ MVT::ValueType ArgVT, MVT::ValueType RegVT,
+ unsigned ExtendType) {
+ // If the argument has to be extended somehow before being passed, do so.
+ if (ArgVT < RegVT)
+ Arg = DAG.getNode(ExtendType, RegVT, Arg);
+
+ RegsToPass.push_back(std::make_pair(RegNo, Arg));
+ }
+
+ void AssignToStack(SDOperand Arg, unsigned Offset,
+ MVT::ValueType ArgVT, MVT::ValueType DestVT,
+ unsigned ExtendType) {
+ // If the argument has to be extended somehow before being stored, do so.
+ if (ArgVT < DestVT)
+ Arg = DAG.getNode(ExtendType, DestVT, Arg);
+
+ SDOperand SP = getSP();
+ SDOperand PtrOff = DAG.getConstant(Offset, SP.getValueType());
+ PtrOff = DAG.getNode(ISD::ADD, SP.getValueType(), SP, PtrOff);
+ MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
+ }
+private:
+ SDOperand getSP() {
+ if (StackPtr.Val == 0) {
+ MVT::ValueType PtrTy = TLI.getPointerTy();
+ StackPtr = DAG.getRegister(TLI.getStackPtrReg(), PtrTy);
+ }
+ return StackPtr;
+ }
+};
+
+class EmptyArgumentsClient {
+public:
+ EmptyArgumentsClient() {}
+
+ void AssignToReg(SDOperand Arg, unsigned RegNo,
+ MVT::ValueType ArgVT, MVT::ValueType RegVT,
+ unsigned ExtendType) {
+ }
+
+ void AssignToStack(SDOperand Arg, unsigned Offset,
+ MVT::ValueType ArgVT, MVT::ValueType DestVT,
+ unsigned ExtendType) {
+ }
+};
+
SDOperand
X86TargetLowering::LowerX86_64CCCArguments(SDOperand Op, SelectionDAG &DAG) {
@@ -1123,23 +1324,7 @@
MachineFrameInfo *MFI = MF.getFrameInfo();
SDOperand Root = Op.getOperand(0);
bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
- SmallVector<SDOperand, 8> ArgValues;
- // Add DAG nodes to load the arguments... On entry to a function on the X86,
- // the stack frame looks like this:
- //
- // [RSP] -- return address
- // [RSP + 8] -- first nonreg argument (leftmost lexically)
- // [RSP +16] -- second nonreg argument, if 1st argument is <= 8 bytes in size
- // ...
- //
- unsigned ArgOffset = 0; // Frame mechanisms handle retaddr slot
- unsigned NumIntRegs = 0; // Int regs used for parameter passing.
- unsigned NumXMMRegs = 0; // XMM regs used for parameter passing.
-
- static const unsigned GPR32ArgRegs[] = {
- X86::EDI, X86::ESI, X86::EDX, X86::ECX, X86::R8D, X86::R9D
- };
static const unsigned GPR64ArgRegs[] = {
X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8, X86::R9
};
@@ -1148,105 +1333,33 @@
X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
};
- for (unsigned i = 0; i < NumArgs; ++i) {
- MVT::ValueType ObjectVT = Op.getValue(i).getValueType();
+ SmallVector<SDOperand, 8> ArgValues;
+
+
+ CallingConvState CCState(*getTargetMachine().getRegisterInfo());
+ LowerArgumentsClient Client(DAG, *this, ArgValues, Root);
+
+ for (unsigned i = 0; i != NumArgs; ++i) {
+ MVT::ValueType ArgVT = Op.getValue(i).getValueType();
unsigned ArgFlags = cast<ConstantSDNode>(Op.getOperand(3+i))->getValue();
- unsigned ArgIncrement = 8;
- unsigned ObjSize = 0;
- unsigned ObjIntRegs = 0;
- unsigned ObjXMMRegs = 0;
- // FIXME: __int128 and long double support?
- HowToPassX86_64CCCArgument(ObjectVT, NumIntRegs, NumXMMRegs,
- ObjSize, ObjIntRegs, ObjXMMRegs);
- if (ObjSize > 8)
- ArgIncrement = ObjSize;
-
- unsigned Reg = 0;
- SDOperand ArgValue;
- if (ObjIntRegs || ObjXMMRegs) {
- switch (ObjectVT) {
- default: assert(0 && "Unhandled argument type!");
- case MVT::i8:
- case MVT::i16:
- case MVT::i32:
- case MVT::i64: {
- TargetRegisterClass *RC = NULL;
- switch (ObjectVT) {
- default: assert(0 && "Unknown integer VT!");
- case MVT::i8:
- case MVT::i16:
- case MVT::i32:
- RC = X86::GR32RegisterClass;
- Reg = GPR32ArgRegs[NumIntRegs];
- ArgValue = DAG.getCopyFromReg(Root, Reg, MVT::i32);
- break;
- case MVT::i64:
- RC = X86::GR64RegisterClass;
- Reg = GPR64ArgRegs[NumIntRegs];
- ArgValue = DAG.getCopyFromReg(Root, Reg, MVT::i64);
- break;
- }
- Reg = AddLiveIn(MF, Reg, RC);
-
- // 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 (ObjectVT == MVT::i8 || ObjectVT == MVT::i16) {
- // FIXME: FORMAL_ARGUMENTS can't currently distinguish between an
- // argument with undefined high bits, so we can't insert a assertzext
- // yet.
- if (ArgFlags & 1) {
- unsigned ExtOpc = (ArgFlags & 1) ? ISD::AssertSext :ISD::AssertZext;
- ArgValue = DAG.getNode(ExtOpc, MVT::i32, ArgValue,
- DAG.getValueType(ObjectVT));
- }
- ArgValue = DAG.getNode(ISD::TRUNCATE, ObjectVT, ArgValue);
- }
- break;
- }
- case MVT::f32:
- case MVT::f64:
- case MVT::v16i8:
- case MVT::v8i16:
- case MVT::v4i32:
- case MVT::v2i64:
- case MVT::v4f32:
- case MVT::v2f64: {
- TargetRegisterClass *RC= (ObjectVT == MVT::f32) ?
- X86::FR32RegisterClass : ((ObjectVT == MVT::f64) ?
- X86::FR64RegisterClass : X86::VR128RegisterClass);
- Reg = AddLiveIn(MF, XMMArgRegs[NumXMMRegs], RC);
- ArgValue = DAG.getCopyFromReg(Root, Reg, ObjectVT);
- break;
- }
- }
- NumIntRegs += ObjIntRegs;
- NumXMMRegs += ObjXMMRegs;
- } else if (ObjSize) {
- // XMM arguments have to be aligned on 16-byte boundary.
- if (ObjSize == 16)
- ArgOffset = ((ArgOffset + 15) / 16) * 16;
- // Create the SelectionDAG nodes corresponding to a load from this
- // parameter.
- int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
- SDOperand FIN = DAG.getFrameIndex(FI, getPointerTy());
- ArgValue = DAG.getLoad(Op.Val->getValueType(i), Root, FIN, NULL, 0);
- ArgOffset += ArgIncrement; // Move on to the next argument.
- }
-
- ArgValues.push_back(ArgValue);
+ X86_64_CCC_AssignArgument(Client, CCState, ArgVT, ArgFlags, SDOperand());
}
+ unsigned StackSize = CCState.getNextStackOffset();
+
// 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 = CCState.getFirstUnallocated(GPR64ArgRegs, 6);
+ unsigned NumXMMRegs = CCState.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, ArgOffset);
+ VarArgsFrameIndex = MFI->CreateFixedObject(1, StackSize);
RegSaveFrameIndex = MFI->CreateStackObject(6 * 8 + 8 * 16, 16);
// Store the integer parameter registers.
@@ -1285,11 +1398,11 @@
ReturnAddrIndex = 0; // No return address slot generated yet.
BytesToPopOnReturn = 0; // Callee pops nothing.
- BytesCallerReserves = ArgOffset;
+ BytesCallerReserves = StackSize;
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(),
- &ArgValues[0], ArgValues.size());
+ &ArgValues[0], ArgValues.size()).getValue(Op.ResNo);
}
SDOperand
@@ -1303,129 +1416,38 @@
// Count how many bytes are to be pushed on the stack.
unsigned NumBytes = 0;
- unsigned NumIntRegs = 0; // Int regs used for parameter passing.
- unsigned NumXMMRegs = 0; // XMM regs used for parameter passing.
-
- static const unsigned GPR32ArgRegs[] = {
- X86::EDI, X86::ESI, X86::EDX, X86::ECX, X86::R8D, X86::R9D
- };
- 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
- };
-
- for (unsigned i = 0; i != NumOps; ++i) {
- SDOperand Arg = Op.getOperand(5+2*i);
- MVT::ValueType ArgVT = Arg.getValueType();
-
- switch (ArgVT) {
- default: assert(0 && "Unknown value type!");
- case MVT::i8:
- case MVT::i16:
- case MVT::i32:
- case MVT::i64:
- if (NumIntRegs < 6)
- ++NumIntRegs;
- else
- NumBytes += 8;
- break;
- case MVT::f32:
- case MVT::f64:
- case MVT::v16i8:
- case MVT::v8i16:
- case MVT::v4i32:
- case MVT::v2i64:
- case MVT::v4f32:
- case MVT::v2f64:
- if (NumXMMRegs < 8)
- NumXMMRegs++;
- else if (ArgVT == MVT::f32 || ArgVT == MVT::f64)
- NumBytes += 8;
- else {
- // XMM arguments have to be aligned on 16-byte boundary.
- NumBytes = ((NumBytes + 15) / 16) * 16;
- NumBytes += 16;
- }
- break;
+ {
+ CallingConvState CCState(*getTargetMachine().getRegisterInfo());
+ EmptyArgumentsClient Client;
+
+ for (unsigned i = 0; i != NumOps; ++i) {
+ SDOperand Arg = Op.getOperand(5+2*i);
+ MVT::ValueType ArgVT = Arg.getValueType();
+ unsigned ArgFlags =
+ cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue();
+ X86_64_CCC_AssignArgument(Client, CCState, ArgVT, ArgFlags, Arg);
}
+
+ NumBytes = CCState.getNextStackOffset();
}
+
Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, getPointerTy()));
- // Arguments go on the stack in reverse order, as specified by the ABI.
- unsigned ArgOffset = 0;
- NumIntRegs = 0;
- NumXMMRegs = 0;
SmallVector<std::pair<unsigned, SDOperand>, 8> RegsToPass;
SmallVector<SDOperand, 8> MemOpChains;
- SDOperand StackPtr = DAG.getRegister(X86StackPtr, getPointerTy());
+
+ CallingConvState CCState(*getTargetMachine().getRegisterInfo());
+ LowerCallArgumentsClient Client(DAG, *this, RegsToPass, MemOpChains, Chain);
+
for (unsigned i = 0; i != NumOps; ++i) {
SDOperand Arg = Op.getOperand(5+2*i);
MVT::ValueType ArgVT = Arg.getValueType();
- unsigned ArgFlags =cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue();
-
- if (MVT::isInteger(ArgVT) && ArgVT < MVT::i32) {
- // Promote the integer to 32 bits. If the input type is signed use a
- // sign extend, otherwise use a zero extend.
- unsigned ExtOpc = (ArgFlags & 1) ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
- Arg = DAG.getNode(ExtOpc, MVT::i32, Arg);
- ArgVT = MVT::i32;
- }
-
- switch (ArgVT) {
- default: assert(0 && "Unexpected ValueType for argument!");
- case MVT::i8:
- case MVT::i16:
- case MVT::i32:
- case MVT::i64:
- if (NumIntRegs < 6) {
- unsigned Reg = 0;
- switch (ArgVT) {
- default: assert(0 && "Unknown integer size!");
- case MVT::i32:
- Reg = GPR32ArgRegs[NumIntRegs];
- break;
- case MVT::i64: Reg = GPR64ArgRegs[NumIntRegs]; break;
- }
- RegsToPass.push_back(std::make_pair(Reg, Arg));
- ++NumIntRegs;
- } else {
- SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
- PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
- MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
- ArgOffset += 8;
- }
- break;
- case MVT::f32:
- case MVT::f64:
- case MVT::v16i8:
- case MVT::v8i16:
- case MVT::v4i32:
- case MVT::v2i64:
- case MVT::v4f32:
- case MVT::v2f64:
- if (NumXMMRegs < 8) {
- RegsToPass.push_back(std::make_pair(XMMArgRegs[NumXMMRegs], Arg));
- NumXMMRegs++;
- } else {
- if (ArgVT != MVT::f32 && ArgVT != MVT::f64) {
- // XMM arguments have to be aligned on 16-byte boundary.
- ArgOffset = ((ArgOffset + 15) / 16) * 16;
- }
- SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
- PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
- MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
- if (ArgVT == MVT::f32 || ArgVT == MVT::f64)
- ArgOffset += 8;
- else
- ArgOffset += 16;
- }
- }
+ unsigned ArgFlags =
+ cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue();
+ X86_64_CCC_AssignArgument(Client, CCState, ArgVT, ArgFlags, Arg);
}
-
+
if (!MemOpChains.empty())
Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
&MemOpChains[0], MemOpChains.size());
@@ -1447,6 +1469,14 @@
// 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 = CCState.getFirstUnallocated(XMMArgRegs, 8);
+
Chain = DAG.getCopyToReg(Chain, X86::AL,
DAG.getConstant(NumXMMRegs, MVT::i8), InFlag);
InFlag = Chain.getValue(1);
@@ -1523,8 +1553,6 @@
// This calling convention always arranges for the callee pop value to be 8n+4
// bytes, which is needed for tail recursion elimination and stack alignment
// reasons.
-
-
SDOperand
X86TargetLowering::LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG,
bool isFastCall) {
@@ -1670,7 +1698,7 @@
// Return the new list of results.
return DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(),
- &ArgValues[0], ArgValues.size());
+ &ArgValues[0], ArgValues.size()).getValue(Op.ResNo);
}
SDOperand X86TargetLowering::LowerFastCCCallTo(SDOperand Op, SelectionDAG &DAG,
More information about the llvm-commits
mailing list