diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index 2f83eaaa3cd..584cb199390 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -167,7 +167,15 @@ public: MarkAllocated(Reg); return Reg; } - + + /// Version of AllocateReg with extra register to be shadowed. + unsigned AllocateReg(unsigned Reg, unsigned ShadowReg) { + if (isAllocated(Reg)) return 0; + MarkAllocated(Reg); + MarkAllocated(ShadowReg); + return Reg; + } + /// 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. @@ -175,13 +183,27 @@ public: 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); return Reg; } - + + /// Version of AllocateReg with list of registers to be shadowed. + unsigned AllocateReg(const unsigned *Regs, const unsigned *ShadowRegs, + 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], ShadowReg = ShadowRegs[FirstUnalloc]; + MarkAllocated(Reg); + MarkAllocated(ShadowReg); + return Reg; + } + /// AllocateStack - Allocate a chunk of stack space with the specified size /// and alignment. unsigned AllocateStack(unsigned Size, unsigned Align) { diff --git a/lib/Target/TargetCallingConv.td b/lib/Target/TargetCallingConv.td index 05d505a88d3..908e16ed5e7 100644 --- a/lib/Target/TargetCallingConv.td +++ b/lib/Target/TargetCallingConv.td @@ -59,6 +59,14 @@ class CCAssignToReg regList> : CCAction { list RegList = regList; } +/// CCAssignToRegWithShadow - Same as CCAssignToReg, but with list of registers +/// which became shadowed, when some register is used. +class CCAssignToRegWithShadow regList, + list shadowList> : CCAction { + list RegList = regList; + list ShadowRegList = shadowList; +} + /// CCAssignToStack - This action always matches: it assigns the value to a /// stack slot of the specified size and alignment on the stack. If size is /// zero then the ABI size is used; if align is zero then the ABI alignment diff --git a/lib/Target/X86/X86CallingConv.td b/lib/Target/X86/X86CallingConv.td index 310dbb7671b..c60611d065e 100644 --- a/lib/Target/X86/X86CallingConv.td +++ b/lib/Target/X86/X86CallingConv.td @@ -158,22 +158,29 @@ def CC_X86_64_C : CallingConv<[ def CC_X86_Win64_C : CallingConv<[ // FIXME: Handle byval stuff. // FIXME: Handle fp80. - // FIXME: Handle shadowed arguments. - // FIXME: Handle nested functions. + // FIXME: Handle varargs. // Promote i8/i16 arguments to i32. CCIfType<[i8, i16], CCPromoteToType>, + // The 'nest' parameter, if any, is passed in R10. + CCIfNest>, + // The first 4 integer arguments are passed in integer registers. - CCIfType<[i32], CCAssignToReg<[ECX, EDX, R8D, R9D]>>, - CCIfType<[i64], CCAssignToReg<[RCX, RDX, R8 , R9 ]>>, + CCIfType<[i32], CCAssignToRegWithShadow<[ECX , EDX , R8D , R9D ], + [XMM0, XMM1, XMM2, XMM3]>>, + CCIfType<[i64], CCAssignToRegWithShadow<[RCX , RDX , R8 , R9 ], + [XMM0, XMM1, XMM2, XMM3]>>, // The first 4 FP/Vector arguments are passed in XMM registers. CCIfType<[f32, f64, v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], - CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>, + CCAssignToRegWithShadow<[XMM0, XMM1, XMM2, XMM3], + [RCX , RDX , R8 , R9 ]>>, // The first 4 MMX vector arguments are passed in GPRs. - CCIfType<[v8i8, v4i16, v2i32, v1i64], CCAssignToReg<[RCX, RDX, R8, R9]>>, + CCIfType<[v8i8, v4i16, v2i32, v1i64], + CCAssignToRegWithShadow<[RCX , RDX , R8 , R9 ], + [XMM0, XMM1, XMM2, XMM3]>>, // Integer/FP values get stored in stack slots that are 8 bytes in size and // 16-byte aligned if there are no more registers to hold them. diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index 192bba5ee31..a211b6aecca 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -111,6 +111,48 @@ void CallingConvEmitter::EmitAction(Record *Action, << "Reg, LocVT, LocInfo));\n"; O << IndentStr << " return false;\n"; O << IndentStr << "}\n"; + } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) { + ListInit *RegList = Action->getValueAsListInit("RegList"); + ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); + if (ShadowRegList->getSize() >0 && + ShadowRegList->getSize() != RegList->getSize()) + throw "Invalid length of list of shadowed registers"; + + if (RegList->getSize() == 1) { + O << IndentStr << "if (unsigned Reg = State.AllocateReg("; + O << getQualifiedName(RegList->getElementAsRecord(0)); + O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0)); + O << ")) {\n"; + } else { + unsigned RegListNumber = ++Counter; + unsigned ShadowRegListNumber = ++Counter; + + O << IndentStr << "static const unsigned RegList" << RegListNumber + << "[] = {\n"; + O << IndentStr << " "; + for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) { + if (i != 0) O << ", "; + O << getQualifiedName(RegList->getElementAsRecord(i)); + } + O << "\n" << IndentStr << "};\n"; + + O << IndentStr << "static const unsigned RegList" + << ShadowRegListNumber << "[] = {\n"; + O << IndentStr << " "; + for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) { + if (i != 0) O << ", "; + O << getQualifiedName(ShadowRegList->getElementAsRecord(i)); + } + O << "\n" << IndentStr << "};\n"; + + O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" + << RegListNumber << ", " << "RegList" << ShadowRegListNumber + << ", " << RegList->getSize() << ")) {\n"; + } + O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " + << "Reg, LocVT, LocInfo));\n"; + O << IndentStr << " return false;\n"; + O << IndentStr << "}\n"; } else if (Action->isSubClassOf("CCAssignToStack")) { int Size = Action->getValueAsInt("Size"); int Align = Action->getValueAsInt("Align");