Index: lib/Target/X86/X86CallingConv.h =================================================================== --- lib/Target/X86/X86CallingConv.h +++ lib/Target/X86/X86CallingConv.h @@ -42,6 +42,9 @@ return false; } +bool CC_X86_HWReg(unsigned &, MVT &, MVT &, + CCValAssign::LocInfo &, ISD::ArgFlagsTy &, + CCState &); } // End llvm namespace #endif Index: lib/Target/X86/X86CallingConv.td =================================================================== --- lib/Target/X86/X86CallingConv.td +++ lib/Target/X86/X86CallingConv.td @@ -191,6 +191,10 @@ CCCustom<"CC_X86_AnyReg_Error"> ]>; +def RetCC_X86_64_Explicit : CallingConv<[ + CCCustom<"CC_X86_AnyReg_Error"> +]>; + // This is the root return-value convention for the X86-32 backend. def RetCC_X86_32 : CallingConv<[ // If FastCC, use RetCC_X86_32_Fast. @@ -212,6 +216,10 @@ CCIfCC<"CallingConv::WebKit_JS", CCDelegateTo>, CCIfCC<"CallingConv::AnyReg", CCDelegateTo>, + // Handle ExplicitCC calls. + CCIfCC<"CallingConv::Explicit", + CCDelegateTo>, + // Handle explicit CC selection CCIfCC<"CallingConv::X86_64_Win64", CCDelegateTo>, CCIfCC<"CallingConv::X86_64_SysV", CCDelegateTo>, @@ -420,6 +428,10 @@ CCCustom<"CC_X86_AnyReg_Error"> ]>; +def CC_X86_64_Explicit : CallingConv<[ + CCCustom<"CC_X86_HWReg"> +]>; + //===----------------------------------------------------------------------===// // X86 C Calling Convention //===----------------------------------------------------------------------===// @@ -665,6 +677,7 @@ CCIfCC<"CallingConv::HiPE", CCDelegateTo>, CCIfCC<"CallingConv::WebKit_JS", CCDelegateTo>, CCIfCC<"CallingConv::AnyReg", CCDelegateTo>, + CCIfCC<"CallingConv::Explicit", CCDelegateTo>, CCIfCC<"CallingConv::X86_64_Win64", CCDelegateTo>, CCIfCC<"CallingConv::X86_64_SysV", CCDelegateTo>, CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo>, @@ -689,6 +702,9 @@ def CSR_NoRegs : CalleeSavedRegs<(add)>; +def CSR_32_Explicit : CalleeSavedRegs<(add EBP)>; +def CSR_64_Explicit : CalleeSavedRegs<(add RBP)>; + def CSR_32 : CalleeSavedRegs<(add ESI, EDI, EBX, EBP)>; def CSR_64 : CalleeSavedRegs<(add RBX, R12, R13, R14, R15, RBP)>; Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -1842,6 +1842,33 @@ return SrcAS < 256 && DestAS < 256; } +bool llvm::CC_X86_HWReg(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + + assert(ArgFlags.isHWReg() && + "A hw-register must be associated with each argument"); + + if (LocVT == MVT::i8 || LocVT == MVT::i16) { + LocVT = MVT::i32; + if (ArgFlags.isSExt()) + LocInfo = CCValAssign::SExt; + else if (ArgFlags.isZExt()) + LocInfo = CCValAssign::ZExt; + else + LocInfo = CCValAssign::AExt; + } + + if (unsigned Reg = State.AllocateReg(ArgFlags.getHWReg())) { + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + return true; + } + llvm_unreachable("Failed to allocate a register which is assigned by the" + " hw-reg attribute"); + return false; +} + //===----------------------------------------------------------------------===// // Return Value Calling Convention Implementation //===----------------------------------------------------------------------===// Index: lib/Target/X86/X86RegisterInfo.cpp =================================================================== --- lib/Target/X86/X86RegisterInfo.cpp +++ lib/Target/X86/X86RegisterInfo.cpp @@ -235,6 +235,11 @@ if (HasAVX) return CSR_64_AllRegs_AVX_SaveList; return CSR_64_AllRegs_SaveList; + case CallingConv::Explicit: + if (Is64Bit) + return CSR_64_Explicit_SaveList; + else + return CSR_32_Explicit_SaveList; case CallingConv::PreserveMost: return CSR_64_RT_MostRegs_SaveList; case CallingConv::PreserveAll: @@ -295,6 +300,11 @@ if (HasAVX) return CSR_64_AllRegs_AVX_RegMask; return CSR_64_AllRegs_RegMask; + case CallingConv::Explicit: + if (Is64Bit) + return CSR_64_Explicit_RegMask; + else + return CSR_32_Explicit_RegMask; case CallingConv::PreserveMost: return CSR_64_RT_MostRegs_RegMask; case CallingConv::PreserveAll: