diff options
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/Sparc/SparcCallingConv.td | 5 | ||||
-rw-r--r-- | lib/Target/Sparc/SparcISelLowering.cpp | 38 | ||||
-rw-r--r-- | lib/Target/Sparc/SparcRegisterInfo.cpp | 5 | ||||
-rw-r--r-- | lib/Target/Sparc/SparcRegisterInfo.h | 2 |
4 files changed, 46 insertions, 4 deletions
diff --git a/lib/Target/Sparc/SparcCallingConv.td b/lib/Target/Sparc/SparcCallingConv.td index 181165d..acd4ec2 100644 --- a/lib/Target/Sparc/SparcCallingConv.td +++ b/lib/Target/Sparc/SparcCallingConv.td @@ -123,3 +123,8 @@ def CSR : CalleeSavedRegs<(add)> { let OtherPreserved = (add (sequence "I%u", 0, 7), (sequence "L%u", 0, 7)); } + +// Callee-saved registers for calls with ReturnsTwice attribute. +def RTCSR : CalleeSavedRegs<(add)> { + let OtherPreserved = (add I6, I7); +} diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index e646521..641ab6c 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -14,6 +14,7 @@ #include "SparcISelLowering.h" #include "SparcMachineFunctionInfo.h" +#include "SparcRegisterInfo.h" #include "SparcTargetMachine.h" #include "MCTargetDesc/SparcBaseInfo.h" #include "llvm/CodeGen/CallingConvLower.h" @@ -648,6 +649,27 @@ SparcTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, return LowerCall_32(CLI, InVals); } +static bool hasReturnsTwiceAttr(SelectionDAG &DAG, SDValue Callee, + ImmutableCallSite *CS) { + if (CS) + return CS->hasFnAttr(Attribute::ReturnsTwice); + + const Function *CalleeFn = 0; + if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { + CalleeFn = dyn_cast<Function>(G->getGlobal()); + } else if (ExternalSymbolSDNode *E = + dyn_cast<ExternalSymbolSDNode>(Callee)) { + const Function *Fn = DAG.getMachineFunction().getFunction(); + const Module *M = Fn->getParent(); + const char *CalleeName = E->getSymbol(); + CalleeFn = M->getFunction(CalleeName); + } + + if (!CalleeFn) + return false; + return CalleeFn->hasFnAttribute(Attribute::ReturnsTwice); +} + // Lower a call for the 32-bit ABI. SDValue SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, @@ -861,6 +883,7 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, } unsigned SRetArgSize = (hasStructRetAttr)? getSRetArgSize(DAG, Callee):0; + bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS); // If the callee is a GlobalAddress node (quite common, every direct call is) // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. @@ -882,8 +905,11 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI, RegsToPass[i].second.getValueType())); // Add a register mask operand representing the call-preserved registers. - const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo(); - const uint32_t *Mask = TRI->getCallPreservedMask(CallConv); + const SparcRegisterInfo *TRI = + ((const SparcTargetMachine&)getTargetMachine()).getRegisterInfo(); + const uint32_t *Mask = ((hasReturnsTwice) + ? TRI->getRTCallPreservedMask(CallConv) + : TRI->getCallPreservedMask(CallConv)); assert(Mask && "Missing call preserved mask for calling convention"); Ops.push_back(DAG.getRegisterMask(Mask)); @@ -1125,6 +1151,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. // Likewise ExternalSymbol -> TargetExternalSymbol. SDValue Callee = CLI.Callee; + bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS); if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy()); else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) @@ -1139,8 +1166,11 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI, RegsToPass[i].second.getValueType())); // Add a register mask operand representing the call-preserved registers. - const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo(); - const uint32_t *Mask = TRI->getCallPreservedMask(CLI.CallConv); + const SparcRegisterInfo *TRI = + ((const SparcTargetMachine&)getTargetMachine()).getRegisterInfo(); + const uint32_t *Mask = ((hasReturnsTwice) + ? TRI->getRTCallPreservedMask(CLI.CallConv) + : TRI->getCallPreservedMask(CLI.CallConv)); assert(Mask && "Missing call preserved mask for calling convention"); Ops.push_back(DAG.getRegisterMask(Mask)); diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp index 09f52fb..8e14dd9 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -48,6 +48,11 @@ SparcRegisterInfo::getCallPreservedMask(CallingConv::ID CC) const { return CSR_RegMask; } +const uint32_t* +SparcRegisterInfo::getRTCallPreservedMask(CallingConv::ID CC) const { + return RTCSR_RegMask; +} + BitVector SparcRegisterInfo::getReservedRegs(const MachineFunction &MF) const { BitVector Reserved(getNumRegs()); // FIXME: G1 reserved for now for large imm generation by frame code. diff --git a/lib/Target/Sparc/SparcRegisterInfo.h b/lib/Target/Sparc/SparcRegisterInfo.h index ae056cd..503229d 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.h +++ b/lib/Target/Sparc/SparcRegisterInfo.h @@ -34,6 +34,8 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo { const uint16_t *getCalleeSavedRegs(const MachineFunction *MF = 0) const; const uint32_t* getCallPreservedMask(CallingConv::ID CC) const; + const uint32_t* getRTCallPreservedMask(CallingConv::ID CC) const; + BitVector getReservedRegs(const MachineFunction &MF) const; const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF, |