Hi all, As previously mentioned on this list the Haskell compiler GHC has a new LLVM based back-end. The back-end needs a new calling convention to efficiently use LLVM and that is what this patch does, just for X86 at the moment. Breakdown: 1) Need actual calling convention Touches: - include/llvm/CallingConv.h - lib/Target/X86/X86CallingConv.td 2) Handling new calling convention (including allowing it to be used in tail call optimisation). Touches: - lib/Target/X86/X86ISelLowering.cpp - lib/Target/X86/X86FastISel.cpp 3) New calling convention needs different callee save register list. Touches: - lib/Target/X86/X86RegisterInfo.cpp The GHC developers would love to get this included in LLVM so that we don't need to carry around our own version of LLVM. If this patch isn't something that you would want to include in LLVM can you suggest an alternative way to do this that you would consider including? Cheers, David -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: llvm-ghc-callconv.patch URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20100303/5ef61ebc/attachment.ksh>
Chris Lattner
2010-Mar-03 21:19 UTC
[LLVMdev] [PATCH] New calling convention for use by GHC
On Mar 2, 2010, at 5:33 PM, David Terei wrote:> Hi all, > > As previously mentioned on this list the Haskell compiler GHC has a new LLVM based back-end. The back-end needs a new calling convention to efficiently use LLVM and that is what this patch does, just for X86 at the moment.Nice,> The GHC developers would love to get this included in LLVM so that we don't need to carry around our own version of LLVM. If this patch isn't something that you would want to include in LLVM can you suggest an alternative way to do this that you would consider including?Yes, I'd like to get this in, preferably before 2.7 branches in a couple days. A couple questions: 1) is the GHC calling conv intended to be target specific? If it is x86 specific, it should get an X86 prefix. If not, it should move up to be #10 after Cold. 2) In either case, please document the new calling convention in docs/LangRef.html#callingconv 3) IN X86RegisterInfo.cpp, this patch: if (Is64Bit) { if (IsWin64) - return CalleeSavedRegsWin64; + return (ghcCall ? GhcCalleeSavedRegsWin64 : CalleeSavedRegsWin64); else - return (callsEHReturn ? CalleeSavedRegs64EHRet : CalleeSavedRegs64Bit); + if (ghcCall) + return (callsEHReturn ? + GhcCalleeSavedRegs64EHRet : GhcCalleeSavedRegs64Bit); + else + return (callsEHReturn ? CalleeSavedRegs64EHRet : CalleeSavedRegs64Bit); Seems like it could be simplified. Have you tested the Win64 support? It isn't clear why your patch needs to depend on the host ABI here. Also, does EHRet matter for your calling conv? 4) In X86ISelLowering.cpp: - if (!Is64Bit && CallConv != CallingConv::Fast && ArgsAreStructReturn(Ins)) + if (!Is64Bit && CallConv != CallingConv::Fast && + CallConv != CallingConv::GHC && ArgsAreStructReturn(Ins)) This should probably use !IsTailCallConvention(CallConv) instead of duplicating the two conventions assert(!(isVarArg && CallConv == CallingConv::Fast) && "Var args not supported with calling convention fastcc"); + assert(!(isVarArg && CallConv == CallingConv::GHC) && + "Var args not supported with calling convention ghc"); Likewise. @@ -2151,7 +2168,8 @@ unsigned NumBytesForCalleeToPush; if (IsCalleePop(isVarArg, CallConv)) NumBytesForCalleeToPush = NumBytes; // Callee pops everything - else if (!Is64Bit && CallConv != CallingConv::Fast && IsStructRet) + else if (!Is64Bit && CallConv != CallingConv::Fast && + CallConv != CallingConv::GHC && IsStructRet) Likewise. 5) Please include a .ll testcase that uses the new calling conv and shows that the arguments are getting passed right. For example it could take two ints add them together and return it, the generated code should show the assigned registers. Otherwise the patch looks great, please resend a new spin of it and I'll commit it. Thanks! Also, congrats on the great work on LLVM+GHC, -Chris
OK, new patch attached. Hopefully in time for 2.7. Chris Lattner wrote:> 1) is the GHC calling conv intended to be target specific? If it is x86 specific, it should get an X86 prefix. If not, it should move up to be #10 after Cold.No its intended to be supported on any platforms that GHC is supported on, which is just x86 and SPARC at the moment. At the moment I've just done X86, will try to work on getting it implemented on SPARC next.> 2) In either case, please document the new calling convention in docs/LangRef.html#callingconvDone.> 3) IN X86RegisterInfo.cpp, this patch: > > if (Is64Bit) { > if (IsWin64) > - return CalleeSavedRegsWin64; > + return (ghcCall ? GhcCalleeSavedRegsWin64 : CalleeSavedRegsWin64); > else > - return (callsEHReturn ? CalleeSavedRegs64EHRet : CalleeSavedRegs64Bit); > + if (ghcCall) > + return (callsEHReturn ? > + GhcCalleeSavedRegs64EHRet : GhcCalleeSavedRegs64Bit); > + else > + return (callsEHReturn ? CalleeSavedRegs64EHRet : CalleeSavedRegs64Bit); > > Seems like it could be simplified. Have you tested the Win64 support?> It isn't clear why your patch needs to depend on the host ABI here. > Also, does EHRet matter for your calling conv? This is true. The GHC call convention is only ever used as a tail call by GHC, so really all of this could be changed so that it just returns no callee saves regardless of ABI. Also, I assume EH = Exception Handling? If so, no EHRet doesn't matter. The new patch takes this approach.> > > 4) In X86ISelLowering.cpp: > > - if (!Is64Bit&& CallConv != CallingConv::Fast&& ArgsAreStructReturn(Ins)) > + if (!Is64Bit&& CallConv != CallingConv::Fast&& > + CallConv != CallingConv::GHC&& ArgsAreStructReturn(Ins)) > > This should probably use !IsTailCallConvention(CallConv) instead of duplicating the two conventions > > assert(!(isVarArg&& CallConv == CallingConv::Fast)&& > "Var args not supported with calling convention fastcc"); > + assert(!(isVarArg&& CallConv == CallingConv::GHC)&& > + "Var args not supported with calling convention ghc"); > > Likewise. > > @@ -2151,7 +2168,8 @@ > unsigned NumBytesForCalleeToPush; > if (IsCalleePop(isVarArg, CallConv)) > NumBytesForCalleeToPush = NumBytes; // Callee pops everything > - else if (!Is64Bit&& CallConv != CallingConv::Fast&& IsStructRet) > + else if (!Is64Bit&& CallConv != CallingConv::Fast&& > + CallConv != CallingConv::GHC&& IsStructRet) > > Likewise.Done.> > 5) Please include a .ll testcase that uses the new calling conv and shows that the arguments are getting passed right. For example it could take two ints add them together and return it, the generated code should show the assigned registers. >Done.> Otherwise the patch looks great, please resend a new spin of it and I'll commit it. Thanks! Also, congrats on the great work on LLVM+GHC,Thanks. ~ David -------------- next part -------------- A non-text attachment was scrubbed... Name: llvm-ghc-callconv.patch Type: application/octet-stream Size: 16063 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20100307/714e5c37/attachment.obj>