diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -56,9 +56,9 @@ void SystemZInstrInfo::anchor() {} SystemZInstrInfo::SystemZInstrInfo(SystemZSubtarget &sti) - : SystemZGenInstrInfo(SystemZ::ADJCALLSTACKDOWN, SystemZ::ADJCALLSTACKUP), - RI(), STI(sti) { -} + : SystemZGenInstrInfo(SystemZ::ADJCALLSTACKDOWN, SystemZ::ADJCALLSTACKUP), + RI(sti.getSpecialRegisters()->getReturnFunctionAddressRegister()), + STI(sti) {} // MI is a 128-bit load or store. Split it into two 64-bit loads or stores, // each having the opcode given by NewOpcode. diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h --- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h +++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h @@ -39,9 +39,84 @@ } } // end namespace SystemZ +/// A SystemZ-specific class detailing special use registers +/// particular for calling conventions. +/// It is abstract, all calling conventions must override and +/// define the pure virtual member function defined in this class. +class SystemZCallingConventionRegisters { +public: + /// \returns the register that keeps the + /// return function address. + virtual int getReturnFunctionAddressRegister() = 0; + + /// \returns the register that keeps the + /// stack pointer address. + virtual int getStackPointerRegister() = 0; + + /// \returns the register that keeps the + /// frame pointer address. + virtual int getFramePointerRegister() = 0; + + /// \returns an array of all the callee saved registers. + virtual const MCPhysReg * + getCalleeSavedRegs(const MachineFunction *MF) const = 0; + + /// \returns the mask of all the call preserved registers. + virtual const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID CC) const = 0; + + /// Destroys the object. Bogus destructor allowing derived classes + /// to override it. + virtual ~SystemZCallingConventionRegisters(){}; +}; + +/// XPLINK64 calling convention specific use registers +/// Particular to z/OS when in 64 bit mode +class SystemZXPLINK64Registers : public SystemZCallingConventionRegisters { +public: + int getReturnFunctionAddressRegister() override final { + return SystemZ::R7D; + }; + + int getStackPointerRegister() override final { return SystemZ::R4D; }; + + int getFramePointerRegister() override final { return SystemZ::R8D; }; + + const MCPhysReg * + getCalleeSavedRegs(const MachineFunction *MF) const override final; + + const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID CC) const override final; + + /// Destroys the object. Bogus destructor overriding base class destructor + ~SystemZXPLINK64Registers(){}; +}; + +/// ELF calling convention specific use registers +/// Particular when on zLinux in 64 bit mode +class SystemZELFRegisters : public SystemZCallingConventionRegisters { +public: + int getReturnFunctionAddressRegister() override final { + return SystemZ::R14D; + }; + + int getStackPointerRegister() override final { return SystemZ::R15D; }; + + int getFramePointerRegister() override final { return SystemZ::R11D; }; + + const MCPhysReg * + getCalleeSavedRegs(const MachineFunction *MF) const override final; + + const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID CC) const override final; + + /// Destroys the object. Bogus destructor overriding base class destructor + ~SystemZELFRegisters(){}; +}; + struct SystemZRegisterInfo : public SystemZGenRegisterInfo { public: - SystemZRegisterInfo(); + SystemZRegisterInfo(unsigned int RA); /// getPointerRegClass - Return the register class to use to hold pointers. /// This is currently only used by LOAD_STACK_GUARD, which requires a non-%r0 diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp --- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -22,9 +22,6 @@ #define GET_REGINFO_TARGET_DESC #include "SystemZGenRegisterInfo.inc" -SystemZRegisterInfo::SystemZRegisterInfo() - : SystemZGenRegisterInfo(SystemZ::R14D) {} - // Given that MO is a GRX32 operand, return either GR32 or GRH32 if MO // somehow belongs in it. Otherwise, return GRX32. static const TargetRegisterClass *getRC32(MachineOperand &MO, @@ -192,7 +189,12 @@ } const MCPhysReg * -SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { +SystemZXPLINK64Registers::getCalleeSavedRegs(const MachineFunction *MF) const { + return CSR_SystemZ_XPLINK64_SaveList; +} + +const MCPhysReg * +SystemZELFRegisters::getCalleeSavedRegs(const MachineFunction *MF) const { const SystemZSubtarget &Subtarget = MF->getSubtarget(); if (MF->getFunction().getCallingConv() == CallingConv::GHC) return CSR_SystemZ_NoRegs_SaveList; @@ -207,7 +209,13 @@ } const uint32_t * -SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF, +SystemZXPLINK64Registers::getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID CC) const { + return CSR_SystemZ_XPLINK64_RegMask; +} + +const uint32_t * +SystemZELFRegisters::getCallPreservedMask(const MachineFunction &MF, CallingConv::ID CC) const { const SystemZSubtarget &Subtarget = MF.getSubtarget(); if (CC == CallingConv::GHC) @@ -222,24 +230,43 @@ return CSR_SystemZ_ELF_RegMask; } +SystemZRegisterInfo::SystemZRegisterInfo(unsigned int RA) + : SystemZGenRegisterInfo(RA) {} + +const MCPhysReg * +SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + + const SystemZSubtarget *Subtarget = &MF->getSubtarget(); + SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters(); + + return Regs->getCalleeSavedRegs(MF); +} + +const uint32_t * +SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID CC) const { + + const SystemZSubtarget *Subtarget = &MF.getSubtarget(); + SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters(); + return Regs->getCallPreservedMask(MF, CC); +} + BitVector SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const { BitVector Reserved(getNumRegs()); const SystemZFrameLowering *TFI = getFrameLowering(MF); - - if (TFI->hasFP(MF)) { - // R11D is the frame pointer. Reserve all aliases. - Reserved.set(SystemZ::R11D); - Reserved.set(SystemZ::R11L); - Reserved.set(SystemZ::R11H); - Reserved.set(SystemZ::R10Q); - } - - // R15D is the stack pointer. Reserve all aliases. - Reserved.set(SystemZ::R15D); - Reserved.set(SystemZ::R15L); - Reserved.set(SystemZ::R15H); - Reserved.set(SystemZ::R14Q); + const SystemZSubtarget *Subtarget = &MF.getSubtarget(); + SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters(); + if (TFI->hasFP(MF)) + // The frame pointer. Reserve all aliases. + for (MCRegAliasIterator AI(Regs->getFramePointerRegister(), this, true); + AI.isValid(); ++AI) + Reserved.set(*AI); + + // Reserve all aliases for the stack pointer. + for (MCRegAliasIterator AI(Regs->getStackPointerRegister(), this, true); + AI.isValid(); ++AI) + Reserved.set(*AI); // A0 and A1 hold the thread pointer. Reserved.set(SystemZ::A0); @@ -420,7 +447,11 @@ Register SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const { const SystemZFrameLowering *TFI = getFrameLowering(MF); - return TFI->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D; + const SystemZSubtarget *Subtarget = &MF.getSubtarget(); + SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters(); + + return TFI->hasFP(MF) ? Regs->getFramePointerRegister() + : Regs->getStackPointerRegister(); } const TargetRegisterClass * diff --git a/llvm/lib/Target/SystemZ/SystemZSubtarget.h b/llvm/lib/Target/SystemZ/SystemZSubtarget.h --- a/llvm/lib/Target/SystemZ/SystemZSubtarget.h +++ b/llvm/lib/Target/SystemZ/SystemZSubtarget.h @@ -72,6 +72,7 @@ private: Triple TargetTriple; + SystemZCallingConventionRegisters *SpecialRegisters; SystemZInstrInfo InstrInfo; SystemZTargetLowering TLInfo; SystemZSelectionDAGInfo TSInfo; @@ -79,10 +80,19 @@ SystemZSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); + SystemZCallingConventionRegisters *initializeSpecialRegisters(void); + public: SystemZSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS, const TargetMachine &TM); + ~SystemZSubtarget(); + + SystemZCallingConventionRegisters *getSpecialRegisters() const { + assert(SpecialRegisters && "Unsupported SystemZ calling convention"); + return SpecialRegisters; + } + const TargetFrameLowering *getFrameLowering() const override { return &FrameLowering; } diff --git a/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp b/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp --- a/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp +++ b/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -50,6 +50,18 @@ return *this; } +SystemZCallingConventionRegisters * +SystemZSubtarget::initializeSpecialRegisters() { + if (isTargetXPLINK64()) + return new SystemZXPLINK64Registers; + else if (isTargetELF()) + return new SystemZELFRegisters; + else { + llvm_unreachable("Invalid Calling Convention. Cannot initialize Special " + "Call Registers!"); + } +} + SystemZSubtarget::SystemZSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS, const TargetMachine &TM) @@ -61,20 +73,21 @@ HasInterlockedAccess1(false), HasMiscellaneousExtensions(false), HasExecutionHint(false), HasLoadAndTrap(false), HasTransactionalExecution(false), HasProcessorAssist(false), - HasDFPZonedConversion(false), HasEnhancedDAT2(false), - HasVector(false), HasLoadStoreOnCond2(false), - HasLoadAndZeroRightmostByte(false), HasMessageSecurityAssist5(false), - HasDFPPackedConversion(false), + HasDFPZonedConversion(false), HasEnhancedDAT2(false), HasVector(false), + HasLoadStoreOnCond2(false), HasLoadAndZeroRightmostByte(false), + HasMessageSecurityAssist5(false), HasDFPPackedConversion(false), HasMiscellaneousExtensions2(false), HasGuardedStorage(false), HasMessageSecurityAssist7(false), HasMessageSecurityAssist8(false), HasVectorEnhancements1(false), HasVectorPackedDecimal(false), - HasInsertReferenceBitsMultiple(false), - HasMiscellaneousExtensions3(false), HasMessageSecurityAssist9(false), - HasVectorEnhancements2(false), HasVectorPackedDecimalEnhancement(false), - HasEnhancedSort(false), HasDeflateConversion(false), HasSoftFloat(false), - TargetTriple(TT), InstrInfo(initializeSubtargetDependencies(CPU, FS)), - TLInfo(TM, *this), TSInfo(), FrameLowering() {} - + HasInsertReferenceBitsMultiple(false), HasMiscellaneousExtensions3(false), + HasMessageSecurityAssist9(false), HasVectorEnhancements2(false), + HasVectorPackedDecimalEnhancement(false), HasEnhancedSort(false), + HasDeflateConversion(false), HasSoftFloat(false), TargetTriple(TT), + SpecialRegisters(initializeSpecialRegisters()), + InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), + TSInfo(), FrameLowering() {} + +SystemZSubtarget::~SystemZSubtarget() { delete getSpecialRegisters(); } bool SystemZSubtarget::enableSubRegLiveness() const { return UseSubRegLiveness;