diff --git a/include/llvm/Target/TargetCallingConv.td b/include/llvm/Target/TargetCallingConv.td index a53ed29f1ec..c1bef28652e 100644 --- a/include/llvm/Target/TargetCallingConv.td +++ b/include/llvm/Target/TargetCallingConv.td @@ -143,4 +143,10 @@ class CallingConv actions> { /// returning from getCallPreservedMask(). class CalleeSavedRegs { dag SaveList = saves; + + // Registers that are also preserved across function calls, but should not be + // included in the generated FOO_SaveList array. These registers will be + // included in the FOO_RegMask bit mask. This can be used for registers that + // are saved automatically, like the SPARC register windows. + dag OtherPreserved; } diff --git a/lib/Target/Sparc/SparcCallingConv.td b/lib/Target/Sparc/SparcCallingConv.td index a181bcf3d26..181165d6ddd 100644 --- a/lib/Target/Sparc/SparcCallingConv.td +++ b/lib/Target/Sparc/SparcCallingConv.td @@ -117,3 +117,9 @@ def CC_Sparc64 : CallingConv<[ // arguments whether they are passed in registers or not. CCCustom<"CC_Sparc64_Full"> ]>; + +// Callee-saved registers are handled by the register window mechanism. +def CSR : CalleeSavedRegs<(add)> { + let OtherPreserved = (add (sequence "I%u", 0, 7), + (sequence "L%u", 0, 7)); +} diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp index dc97f06b7ca..0b0fe2d4fe8 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -40,8 +40,12 @@ SparcRegisterInfo::SparcRegisterInfo(SparcSubtarget &st) const uint16_t* SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { - static const uint16_t CalleeSavedRegs[] = { 0 }; - return CalleeSavedRegs; + return CSR_SaveList; +} + +const uint32_t* +SparcRegisterInfo::getCallPreservedMask(CallingConv::ID CC) const { + return CSR_RegMask; } BitVector SparcRegisterInfo::getReservedRegs(const MachineFunction &MF) const { diff --git a/lib/Target/Sparc/SparcRegisterInfo.h b/lib/Target/Sparc/SparcRegisterInfo.h index 6b77d4efa21..ae056cdcf29 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.h +++ b/lib/Target/Sparc/SparcRegisterInfo.h @@ -32,6 +32,7 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo { /// Code Generation virtual methods... const uint16_t *getCalleeSavedRegs(const MachineFunction *MF = 0) const; + const uint32_t* getCallPreservedMask(CallingConv::ID CC) const; BitVector getReservedRegs(const MachineFunction &MF) const; diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 731dccf75e8..9a30e159be4 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -1314,9 +1314,21 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "0 };\n"; // Emit the *_RegMask bit mask of call-preserved registers. + BitVector Covered = RegBank.computeCoveredRegisters(*Regs); + + // Check for an optional OtherPreserved set. + // Add those registers to RegMask, but not to SaveList. + if (DagInit *OPDag = + dyn_cast(CSRSet->getValueInit("OtherPreserved"))) { + SetTheory::RecSet OPSet; + RegBank.getSets().evaluate(OPDag, OPSet, CSRSet->getLoc()); + Covered |= RegBank.computeCoveredRegisters( + ArrayRef(OPSet.begin(), OPSet.end())); + } + OS << "static const uint32_t " << CSRSet->getName() << "_RegMask[] = { "; - printBitVectorAsHex(OS, RegBank.computeCoveredRegisters(*Regs), 32); + printBitVectorAsHex(OS, Covered, 32); OS << "};\n"; } OS << "\n\n";