diff --git a/clang/test/CodeGen/SystemZ/mbackchain-4.c b/clang/test/CodeGen/SystemZ/mbackchain-4.c new file mode 100644 index 0000000000000..6e5f4fc5da400 --- /dev/null +++ b/clang/test/CodeGen/SystemZ/mbackchain-4.c @@ -0,0 +1,11 @@ +// RUN: %clang --target=s390x-linux -O1 -S -o - %s | FileCheck %s + +__attribute__((target("backchain"))) +void *foo(void) { + return __builtin_return_address(1); +} + +// CHECK-LABEL: foo: +// CHECK: lg %r1, 0(%r15) +// CHECK: lg %r2, 112(%r1) +// CHECK: br %r14 diff --git a/llvm/lib/Target/SystemZ/SystemZFeatures.td b/llvm/lib/Target/SystemZ/SystemZFeatures.td index 78b8394d64865..fdd94206421a4 100644 --- a/llvm/lib/Target/SystemZ/SystemZFeatures.td +++ b/llvm/lib/Target/SystemZ/SystemZFeatures.td @@ -32,6 +32,11 @@ def FeatureSoftFloat : SystemZFeature< "Use software emulation for floating point" >; +def FeatureBackChain : SystemZFeature< + "backchain", "BackChain", (all_of FeatureBackChain), + "Store the address of the caller's frame into the callee's stack frame" +>; + //===----------------------------------------------------------------------===// // // New features added in the Ninth Edition of the z/Architecture diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp index bfd31709eb3e0..7522998fd06d8 100644 --- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp @@ -443,7 +443,7 @@ void SystemZELFFrameLowering::processFunctionBeforeFrameFinalized( MachineFrameInfo &MFFrame = MF.getFrameInfo(); SystemZMachineFunctionInfo *ZFI = MF.getInfo(); MachineRegisterInfo *MRI = &MF.getRegInfo(); - bool BackChain = MF.getFunction().hasFnAttribute("backchain"); + bool BackChain = MF.getSubtarget().hasBackChain(); if (!usePackedStack(MF) || BackChain) // Create the incoming register save area. @@ -628,7 +628,7 @@ void SystemZELFFrameLowering::emitPrologue(MachineFunction &MF, .addImm(StackSize); } else { - bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain"); + bool StoreBackchain = MF.getSubtarget().hasBackChain(); // If we need backchain, save current stack pointer. R1 is free at // this point. if (StoreBackchain) @@ -786,7 +786,7 @@ void SystemZELFFrameLowering::inlineStackProbe( .addMemOperand(MMO); }; - bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain"); + bool StoreBackchain = MF.getSubtarget().hasBackChain(); if (StoreBackchain) BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR)) .addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D); @@ -861,8 +861,9 @@ StackOffset SystemZELFFrameLowering::getFrameIndexReference( unsigned SystemZELFFrameLowering::getRegSpillOffset(MachineFunction &MF, Register Reg) const { bool IsVarArg = MF.getFunction().isVarArg(); - bool BackChain = MF.getFunction().hasFnAttribute("backchain"); - bool SoftFloat = MF.getSubtarget().hasSoftFloat(); + const SystemZSubtarget &Subtarget = MF.getSubtarget(); + bool BackChain = Subtarget.hasBackChain(); + bool SoftFloat = Subtarget.hasSoftFloat(); unsigned Offset = RegSpillOffsets[Reg]; if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) { if (SystemZ::GR64BitRegClass.contains(Reg)) @@ -890,8 +891,9 @@ int SystemZELFFrameLowering::getOrCreateFramePointerSaveIndex( bool SystemZELFFrameLowering::usePackedStack(MachineFunction &MF) const { bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack"); - bool BackChain = MF.getFunction().hasFnAttribute("backchain"); - bool SoftFloat = MF.getSubtarget().hasSoftFloat(); + const SystemZSubtarget &Subtarget = MF.getSubtarget(); + bool BackChain = Subtarget.hasBackChain(); + bool SoftFloat = Subtarget.hasSoftFloat(); if (HasPackedStackAttr && BackChain && !SoftFloat) report_fatal_error("packed-stack + backchain + hard-float is unsupported."); bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC; @@ -946,7 +948,7 @@ static bool isXPLeafCandidate(const MachineFunction &MF) { return false; // If the backchain pointer should be stored, then it is not a XPLeaf routine. - if (MF.getFunction().hasFnAttribute("backchain")) + if (MF.getSubtarget().hasBackChain()) return false; // If function acquires its own stack frame, then it is not a XPLeaf routine. @@ -989,7 +991,7 @@ bool SystemZXPLINKFrameLowering::assignCalleeSavedSpillSlots( // If the function needs a frame pointer, or if the backchain pointer should // be stored, then save the stack pointer register R4. - if (hasFP(MF) || MF.getFunction().hasFnAttribute("backchain")) + if (hasFP(MF) || Subtarget.hasBackChain()) CSI.push_back(CalleeSavedInfo(Regs.getStackPointerRegister())); // Scan the call-saved GPRs and find the bounds of the register spill area. diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index e6ea4205623d3..4e57986206dc6 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -3631,7 +3631,7 @@ SDValue SystemZTargetLowering::lowerFRAMEADDR(SDValue Op, if (Depth > 0) { // FIXME The frontend should detect this case. - if (!MF.getFunction().hasFnAttribute("backchain")) + if (!MF.getSubtarget().hasBackChain()) report_fatal_error("Unsupported stack frame traversal count"); SDValue Offset = DAG.getConstant(TFL->getBackchainOffset(MF), DL, PtrVT); @@ -3660,7 +3660,7 @@ SDValue SystemZTargetLowering::lowerRETURNADDR(SDValue Op, if (Depth > 0) { // FIXME The frontend should detect this case. - if (!MF.getFunction().hasFnAttribute("backchain")) + if (!MF.getSubtarget().hasBackChain()) report_fatal_error("Unsupported stack frame traversal count"); SDValue FrameAddr = lowerFRAMEADDR(Op, DAG); @@ -3886,7 +3886,7 @@ SystemZTargetLowering::lowerDYNAMIC_STACKALLOC_ELF(SDValue Op, const TargetFrameLowering *TFI = Subtarget.getFrameLowering(); MachineFunction &MF = DAG.getMachineFunction(); bool RealignOpt = !MF.getFunction().hasFnAttribute("no-realign-stack"); - bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain"); + bool StoreBackchain = MF.getSubtarget().hasBackChain(); SDValue Chain = Op.getOperand(0); SDValue Size = Op.getOperand(1); @@ -4563,7 +4563,7 @@ SDValue SystemZTargetLowering::lowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG) const { MachineFunction &MF = DAG.getMachineFunction(); auto *Regs = Subtarget.getSpecialRegisters(); - bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain"); + bool StoreBackchain = MF.getSubtarget().hasBackChain(); if (MF.getFunction().getCallingConv() == CallingConv::GHC) report_fatal_error("Variable-sized stack allocations are not supported " diff --git a/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp b/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp index 186494ad2ac61..73e01e3ec1844 100644 --- a/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp +++ b/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp @@ -169,12 +169,14 @@ SystemZTargetMachine::getSubtargetImpl(const Function &F) const { FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; // FIXME: This is related to the code below to reset the target options, - // we need to know whether or not the soft float flag is set on the - // function, so we can enable it as a subtarget feature. + // we need to know whether the soft float and backchain flags are set on the + // function, so we can enable them as subtarget features. bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsBool(); - if (SoftFloat) FS += FS.empty() ? "+soft-float" : ",+soft-float"; + bool BackChain = F.hasFnAttribute("backchain"); + if (BackChain) + FS += FS.empty() ? "+backchain" : ",+backchain"; auto &I = SubtargetMap[CPU + TuneCPU + FS]; if (!I) {