diff options
Diffstat (limited to 'lib/Target/X86')
-rw-r--r-- | lib/Target/X86/X86CallingConv.td | 22 | ||||
-rw-r--r-- | lib/Target/X86/X86FastISel.cpp | 6 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 34 | ||||
-rw-r--r-- | lib/Target/X86/X86RegisterInfo.cpp | 11 |
4 files changed, 60 insertions, 13 deletions
diff --git a/lib/Target/X86/X86CallingConv.td b/lib/Target/X86/X86CallingConv.td index 12d3d04..fd15efd 100644 --- a/lib/Target/X86/X86CallingConv.td +++ b/lib/Target/X86/X86CallingConv.td @@ -221,6 +221,20 @@ def CC_X86_Win64_C : CallingConv<[ CCIfType<[v8i8, v4i16, v2i32, v1i64], CCAssignToStack<8, 8>> ]>; +def CC_X86_64_GHC : CallingConv<[ + // Promote i8/i16/i32 arguments to i64. + CCIfType<[i8, i16, i32], CCPromoteToType<i64>>, + + // Pass in STG registers: Base, Sp, Hp, R1, R2, R3, R4, R5, R6, SpLim + CCIfType<[i64], + CCAssignToReg<[R13, RBP, R12, RBX, R14, RSI, RDI, R8, R9, R15]>>, + + // Pass in STG registers: F1, F2, F3, F4, D1, D2 + CCIfType<[f32, f64, v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], + CCIfSubtarget<"hasSSE1()", + CCAssignToReg<[XMM1, XMM2, XMM3, XMM4, XMM5, XMM6]>>> +]>; + //===----------------------------------------------------------------------===// // X86 C Calling Convention //===----------------------------------------------------------------------===// @@ -320,3 +334,11 @@ def CC_X86_32_FastCC : CallingConv<[ // Otherwise, same as everything else. CCDelegateTo<CC_X86_32_Common> ]>; + +def CC_X86_32_GHC : CallingConv<[ + // Promote i8/i16 arguments to i32. + CCIfType<[i8, i16], CCPromoteToType<i32>>, + + // Pass in STG registers: Base, Sp, Hp, R1 + CCIfType<[i32], CCAssignToReg<[EBX, EBP, EDI, ESI]>> +]>; diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 98e3f4e..27807f2 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -172,7 +172,9 @@ bool X86FastISel::isTypeLegal(const Type *Ty, EVT &VT, bool AllowI1) { CCAssignFn *X86FastISel::CCAssignFnForCall(CallingConv::ID CC, bool isTaillCall) { if (Subtarget->is64Bit()) { - if (Subtarget->isTargetWin64()) + if (CC == CallingConv::GHC) + return CC_X86_64_GHC; + else if (Subtarget->isTargetWin64()) return CC_X86_Win64_C; else return CC_X86_64_C; @@ -182,6 +184,8 @@ CCAssignFn *X86FastISel::CCAssignFnForCall(CallingConv::ID CC, return CC_X86_32_FastCall; else if (CC == CallingConv::Fast) return CC_X86_32_FastCC; + else if (CC == CallingConv::GHC) + return CC_X86_32_GHC; else return CC_X86_32_C; } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 1416a6d..9b7f6fc 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1378,6 +1378,8 @@ bool X86TargetLowering::IsCalleePop(bool IsVarArg, CallingConv::ID CallingConv){ return !Subtarget->is64Bit(); case CallingConv::Fast: return GuaranteedTailCallOpt; + case CallingConv::GHC: + return GuaranteedTailCallOpt; } } @@ -1385,7 +1387,9 @@ bool X86TargetLowering::IsCalleePop(bool IsVarArg, CallingConv::ID CallingConv){ /// given CallingConvention value. CCAssignFn *X86TargetLowering::CCAssignFnForNode(CallingConv::ID CC) const { if (Subtarget->is64Bit()) { - if (Subtarget->isTargetWin64()) + if (CC == CallingConv::GHC) + return CC_X86_64_GHC; + else if (Subtarget->isTargetWin64()) return CC_X86_Win64_C; else return CC_X86_64_C; @@ -1395,6 +1399,8 @@ CCAssignFn *X86TargetLowering::CCAssignFnForNode(CallingConv::ID CC) const { return CC_X86_32_FastCall; else if (CC == CallingConv::Fast) return CC_X86_32_FastCC; + else if (CC == CallingConv::GHC) + return CC_X86_32_GHC; else return CC_X86_32_C; } @@ -1412,10 +1418,16 @@ CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, /*AlwaysInline=*/true, NULL, 0, NULL, 0); } +/// IsTailCallConvention - Return true if the calling convention is one that +/// supports tail call optimization. +static bool IsTailCallConvention(CallingConv::ID CC) { + return (CC == CallingConv::Fast || CC == CallingConv::GHC); +} + /// FuncIsMadeTailCallSafe - Return true if the function is being made into /// a tailcall target by changing its ABI. static bool FuncIsMadeTailCallSafe(CallingConv::ID CC) { - return GuaranteedTailCallOpt && CC == CallingConv::Fast; + return GuaranteedTailCallOpt && IsTailCallConvention(CC); } SDValue @@ -1479,8 +1491,8 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, bool Is64Bit = Subtarget->is64Bit(); bool IsWin64 = Subtarget->isTargetWin64(); - assert(!(isVarArg && CallConv == CallingConv::Fast) && - "Var args not supported with calling convention fastcc"); + assert(!(isVarArg && IsTailCallConvention(CallConv)) && + "Var args not supported with calling convention fastcc or ghc"); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; @@ -1683,7 +1695,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, } else { BytesToPopOnReturn = 0; // Callee pops nothing. // If this is an sret function, the return should pop the hidden pointer. - if (!Is64Bit && CallConv != CallingConv::Fast && ArgsAreStructReturn(Ins)) + if (!Is64Bit && !IsTailCallConvention(CallConv) && ArgsAreStructReturn(Ins)) BytesToPopOnReturn = 4; } @@ -1779,8 +1791,8 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, ++NumTailCalls; } - assert(!(isVarArg && CallConv == CallingConv::Fast) && - "Var args not supported with calling convention fastcc"); + assert(!(isVarArg && IsTailCallConvention(CallConv)) && + "Var args not supported with calling convention fastcc or ghc"); // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; @@ -1794,7 +1806,7 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, // This is a sibcall. The memory operands are available in caller's // own caller's stack. NumBytes = 0; - else if (GuaranteedTailCallOpt && CallConv == CallingConv::Fast) + else if (GuaranteedTailCallOpt && IsTailCallConvention(CallConv)) NumBytes = GetAlignedArgumentStackSize(NumBytes, DAG); int FPDiff = 0; @@ -2150,7 +2162,7 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, unsigned NumBytesForCalleeToPush; if (IsCalleePop(isVarArg, CallConv)) NumBytesForCalleeToPush = NumBytes; // Callee pops everything - else if (!Is64Bit && CallConv != CallingConv::Fast && IsStructRet) + else if (!Is64Bit && !IsTailCallConvention(CallConv) && IsStructRet) // If this 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. @@ -2288,14 +2300,14 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<ISD::InputArg> &Ins, SelectionDAG& DAG) const { - if (CalleeCC != CallingConv::Fast && + if (!IsTailCallConvention(CalleeCC) && CalleeCC != CallingConv::C) return false; // If -tailcallopt is specified, make fastcc functions tail-callable. const Function *CallerF = DAG.getMachineFunction().getFunction(); if (GuaranteedTailCallOpt) { - if (CalleeCC == CallingConv::Fast && + if (IsTailCallConvention(CalleeCC) && CallerF->getCallingConv() == CalleeCC) return true; return false; diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index cdb579c..3c087bd 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -294,13 +294,20 @@ X86RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const { const unsigned * X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { bool callsEHReturn = false; + bool ghcCall = false; if (MF) { const MachineFrameInfo *MFI = MF->getFrameInfo(); const MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); callsEHReturn = (MMI ? MMI->callsEHReturn() : false); + const Function *F = MF->getFunction(); + ghcCall = (F ? F->getCallingConv() == CallingConv::GHC : false); } + static const unsigned GhcCalleeSavedRegs[] = { + 0 + }; + static const unsigned CalleeSavedRegs32Bit[] = { X86::ESI, X86::EDI, X86::EBX, X86::EBP, 0 }; @@ -326,7 +333,9 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { X86::XMM14, X86::XMM15, 0 }; - if (Is64Bit) { + if (ghcCall) { + return GhcCalleeSavedRegs; + } else if (Is64Bit) { if (IsWin64) return CalleeSavedRegsWin64; else |