[clang] [llvm] Support for __builtin_setjmp and __builtin_longjmp (PR #116642)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 18 07:42:46 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen
Author: None (anoopkg6)
<details>
<summary>Changes</summary>
Implementation for __builtin_setjmp and __builtin_longjmp for SystemZ.
---
Patch is 665.11 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/116642.diff
76 Files Affected:
- (modified) clang/lib/Basic/Targets/SystemZ.h (+2)
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+6)
- (modified) llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp (+4)
- (modified) llvm/lib/Target/SystemZ/SystemZISelLowering.cpp (+252-1)
- (modified) llvm/lib/Target/SystemZ/SystemZISelLowering.h (+7)
- (modified) llvm/lib/Target/SystemZ/SystemZInstrInfo.td (+14)
- (modified) llvm/lib/Target/SystemZ/SystemZLongBranch.cpp (+4-1)
- (modified) llvm/lib/Target/SystemZ/SystemZOperators.td (+12)
- (modified) llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp (+5)
- (modified) llvm/lib/Target/SystemZ/SystemZRegisterInfo.h (+1)
- (added) llvm/test/CodeGen/SystemZ/builtin-longjmp-01.ll (+44)
- (added) llvm/test/CodeGen/SystemZ/builtin-longjmp-backchain-01.ll (+46)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-01.ll (+60)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-backchain-01.ll (+65)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-01.ll (+72)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-02.ll (+101)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-03.ll (+87)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-04-o0.ll (+94)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-04-o2.ll (+93)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-00-o0.ll (+284)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-00-o2.ll (+170)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-00.ll (+170)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-01.ll (+343)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-02.ll (+329)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-03.ll (+1037)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-04-o0.ll (+149)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-04-o2.ll (+157)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-04.ll (+157)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-00-o0.ll (+286)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-00-o2.ll (+170)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-01.ll (+343)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-02.ll (+330)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-03.ll (+1038)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-04-o0.ll (+150)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-alloca-backchain-04-o2.ll (+133)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-backchain-01.ll (+73)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-backchain-02.ll (+82)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-backchain-03.ll (+88)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-backchain-04-o0.ll (+95)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-backchain-04-o2.ll (+95)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-00.ll (+94)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-01.ll (+203)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-02.ll (+276)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-03.ll (+291)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-04.ll (+264)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-backchain-00.ll (+94)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-backchain-01.ll (+175)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-backchain-02.ll (+277)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-backchain-03.ll (+290)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-literal-pool-backchain-04.ll (+264)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-global-02-o2.ll (+133)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-global-0l-o2.ll (+109)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-global-backchain-02-o2.ll (+135)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-global-backchain-0l-o2.ll (+111)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-local-01-o0.ll (+105)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-local-02-o0.ll (+147)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-local-03.ll (+393)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-local-backchain-01-o0.ll (+106)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-local-backchain-02-o0.ll (+147)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-local-backchain-03.ll (+393)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-volatile-01-o2.ll (+104)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-volatile-02-o2.ll (+122)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-volatile-backchain-01-o2.ll (+105)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-longjmp-malloc-volatile-backchain-02-o2.ll (+124)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-double-01.ll (+245)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-double-02.ll (+152)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-double-03.ll (+223)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-double-backchain-01.ll (+246)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-double-backchain-02.ll (+153)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-double-backchain-03.ll (+225)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-int-01.ll (+243)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-int-02.ll (+151)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-int-03.ll (+222)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-int-backchain-01.ll (+241)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-int-backchain-02.ll (+155)
- (added) llvm/test/CodeGen/SystemZ/builtin-setjmp-spills-int-backchain-03.ll (+227)
``````````diff
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index ef9a07033a6e4f..e6405f174f660f 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -247,6 +247,8 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
return RegNo < 4 ? 6 + RegNo : -1;
}
+ bool hasSjLjLowering() const override { return true; }
+
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(256, 256);
}
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index e2d03eff8ab4a0..1de6aded302ceb 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4619,6 +4619,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// Buffer is a void**.
Address Buf = EmitPointerWithAlignment(E->getArg(0));
+ if (getTarget().getTriple().getArch() == llvm::Triple::systemz) {
+ // Call LLVM's EH setjmp, which is lightweight.
+ Function *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp);
+ return RValue::get(Builder.CreateCall(F, Buf.emitRawPointer(*this)));
+ }
+
// Store the frame pointer to the setjmp buffer.
Value *FrameAddr = Builder.CreateCall(
CGM.getIntrinsic(Intrinsic::frameaddress, AllocaInt8PtrTy),
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 050a482c69d528..a75dac5b91ceca 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -687,6 +687,10 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
return;
}
+ // EH_SjLj_Setup is a dummy terminator instruction of size 0,
+ // It is used to handle the clobber register for builtin setjmp.
+ case SystemZ::EH_SjLj_Setup:
+ return;
default:
Lower.lower(MI, LoweredMI);
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 3e05f3b0180a78..f498f9eab865f1 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -751,6 +751,13 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
+ // We're not using SJLJ for exception handling, but they're implemented
+ // solely to support use of __builtin_setjmp / __builtin_longjmp.
+ setOperationAction(ISD::EH_SJLJ_SETJMP, MVT::i32, Custom);
+ setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom);
+
+
+
// We want to use MVC in preference to even a single load/store pair.
MaxStoresPerMemcpy = Subtarget.hasVector() ? 2 : 0;
MaxStoresPerMemcpyOptSize = 0;
@@ -940,7 +947,242 @@ bool SystemZTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
return SystemZVectorConstantInfo(Imm).isVectorConstantLegal(Subtarget);
}
-/// Returns true if stack probing through inline assembly is requested.
+
+MachineBasicBlock *
+SystemZTargetLowering::emitEHSjLjSetJmp(MachineInstr &MI,
+ MachineBasicBlock *MBB) const {
+
+ DebugLoc DL = MI.getDebugLoc();
+ const TargetInstrInfo *TII = Subtarget.getInstrInfo();
+ const SystemZRegisterInfo *TRI = Subtarget.getRegisterInfo();
+
+ MachineFunction *MF = MBB->getParent();
+ MachineRegisterInfo &MRI = MF->getRegInfo();
+
+ const BasicBlock *BB = MBB->getBasicBlock();
+ MachineFunction::iterator I = ++MBB->getIterator();
+
+ Register DstReg = MI.getOperand(0).getReg();
+ const TargetRegisterClass *RC = MRI.getRegClass(DstReg);
+ assert(TRI->isTypeLegalForClass(*RC, MVT::i32) && "Invalid destination!");
+ Register mainDstReg = MRI.createVirtualRegister(RC);
+ Register restoreDstReg = MRI.createVirtualRegister(RC);
+
+ MVT PVT = getPointerTy(MF->getDataLayout());
+ assert((PVT == MVT::i64 || PVT == MVT::i32) &&
+ "Invalid Pointer Size!");
+ // For v = setjmp(buf), we generate.
+ // Algorithm:
+ //
+ // ---------
+ // | thisMBB |
+ // ---------
+ // |
+ // ------------------------
+ // | |
+ // ---------- ---------------
+ // | mainMBB | | restoreMBB |
+ // | v = 0 | | v = 1 |
+ // ---------- ---------------
+ // | |
+ // -------------------------
+ // |
+ // -----------------------------
+ // | sinkMBB |
+ // | phi(v_mainMBB,v_restoreMBB) |
+ // -----------------------------
+ // thisMBB:
+ // buf[0] = Frame Pointer if hasFP.
+ // buf[LabelOffset] = restoreMBB <-- takes address of restoreMBB.
+ // buf[BCOffset] = Backchain value if building with -mbackchain.
+ // buf[SPOffset] = Stack Pointer.
+ // buf[LPOffset] = We never write this slot with R13, gcc stores R13 always.
+ // SjLjSetup restoreMBB
+ // mainMBB:
+ // v_main = 0
+ // sinkMBB:
+ // v = phi(v_main, v_restore)
+ // restoreMBB:
+ // v_restore = 1
+
+ MachineBasicBlock *thisMBB = MBB;
+ MachineBasicBlock *mainMBB = MF->CreateMachineBasicBlock(BB);
+ MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(BB);
+ MachineBasicBlock *restoreMBB = MF->CreateMachineBasicBlock(BB);
+
+ MF->insert(I, mainMBB);
+ MF->insert(I, sinkMBB);
+ MF->push_back(restoreMBB);
+ restoreMBB->setMachineBlockAddressTaken();
+
+ MachineInstrBuilder MIB;
+
+ // Transfer the remainder of BB and its successor edges to sinkMBB.
+ sinkMBB->splice(sinkMBB->begin(), MBB,
+ std::next(MachineBasicBlock::iterator(MI)), MBB->end());
+ sinkMBB->transferSuccessorsAndUpdatePHIs(MBB);
+
+
+ // thisMBB:
+ const int64_t LabelOffset = 1 * PVT.getStoreSize(); // Slot 2.
+ const int64_t SPOffset = 3 * PVT.getStoreSize(); // Slot 4.
+
+ // Buf address.
+ Register BufReg = MI.getOperand(1).getReg();
+
+ unsigned LabelReg = 0;
+ const TargetRegisterClass *PtrRC = getRegClassFor(PVT);
+ LabelReg = MRI.createVirtualRegister(PtrRC);
+
+ // prepare IP for longjmp.
+ BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::LARL), LabelReg)
+ .addMBB(restoreMBB);
+
+ // store IP for return from jmp, slot 2, offset = 1.
+ BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::STG))
+ .addReg(LabelReg)
+ .addReg(BufReg)
+ .addImm(LabelOffset)
+ .addReg(0);
+
+ bool HasFP = Subtarget.getFrameLowering()->hasFP(*MF);
+ if (HasFP) {
+ const int64_t FPOffset = 0;
+ BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::STG))
+ .addReg(SystemZ::R11D)
+ .addReg(BufReg)
+ .addImm(FPOffset)
+ .addReg(0);
+ }
+
+ // store SP.
+ BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::STG))
+ .addReg(SystemZ::R15D)
+ .addReg(BufReg)
+ .addImm(SPOffset)
+ .addReg(0);
+
+ // Slot 3(Offset = 2) Backchain value (if building with -mbackchain).
+ bool BackChain = MF->getSubtarget<SystemZSubtarget>().hasBackChain();
+ if (BackChain) {
+ const int64_t BCOffset = 2 * PVT.getStoreSize();
+ Register BCReg = MRI.createVirtualRegister(RC);
+ MIB = BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::LG), BCReg)
+ .addReg(SystemZ::R15D)
+ .addImm(0)
+ .addReg(0);
+
+ BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::STG))
+ .addReg(BCReg)
+ .addReg(BufReg)
+ .addImm(BCOffset)
+ .addReg(0);
+ }
+
+ // Setup.
+ MIB = BuildMI(*thisMBB, MI, DL, TII->get(SystemZ::EH_SjLj_Setup))
+ .addMBB(restoreMBB);
+
+ const SystemZRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
+ MIB.addRegMask(RegInfo->getNoPreservedMask());
+
+ thisMBB->addSuccessor(mainMBB);
+ thisMBB->addSuccessor(restoreMBB);
+
+ // mainMBB:
+ BuildMI(mainMBB, DL, TII->get(SystemZ::LHI), mainDstReg).addImm(0);
+ mainMBB->addSuccessor(sinkMBB);
+
+ // sinkMBB:
+ BuildMI(*sinkMBB, sinkMBB->begin(), DL, TII->get(SystemZ::PHI), DstReg)
+ .addReg(mainDstReg)
+ .addMBB(mainMBB)
+ .addReg(restoreDstReg)
+ .addMBB(restoreMBB);
+
+ // restoreMBB.
+ BuildMI(restoreMBB, DL, TII->get(SystemZ::LHI), restoreDstReg).addImm(1);
+ BuildMI(restoreMBB, DL, TII->get(SystemZ::J)).addMBB(sinkMBB);
+ restoreMBB->addSuccessor(sinkMBB);
+
+ MI.eraseFromParent();
+
+ return sinkMBB;
+}
+
+MachineBasicBlock *
+SystemZTargetLowering::emitEHSjLjLongJmp(MachineInstr &MI,
+ MachineBasicBlock *MBB) const {
+
+ DebugLoc DL = MI.getDebugLoc();
+ const TargetInstrInfo *TII = Subtarget.getInstrInfo();
+
+ MachineFunction *MF = MBB->getParent();
+ MachineRegisterInfo &MRI = MF->getRegInfo();
+
+ MVT PVT = getPointerTy(MF->getDataLayout());
+ assert((PVT == MVT::i64 || PVT == MVT::i32) &&
+ "Invalid Pointer Size!");
+ Register BufReg = MI.getOperand(0).getReg();
+ const TargetRegisterClass *RC = MRI.getRegClass(BufReg);
+
+ Register Tmp = MRI.createVirtualRegister(RC);
+ Register BCReg = MRI.createVirtualRegister(RC);
+
+ MachineInstrBuilder MIB;
+
+ const int64_t FPOffset = 0;
+ const int64_t LabelOffset = 1 * PVT.getStoreSize();
+ const int64_t SPOffset = 3 * PVT.getStoreSize();
+ const int64_t LPOffset = 4 * PVT.getStoreSize();
+
+ MIB = BuildMI(*MBB, MI, DL, TII->get(SystemZ::LG), Tmp)
+ .addReg(BufReg)
+ .addImm(LabelOffset)
+ .addReg(0);
+
+ MIB = BuildMI(*MBB, MI, DL, TII->get(SystemZ::LG), SystemZ::R11D)
+ .addReg(BufReg)
+ .addImm(FPOffset)
+ .addReg(0);
+
+ // We are restoring R13 even though we never stored in setjmp from llvm,
+ // as gcc always stores R13 in builtin_setjmp. We could have mixed code
+ // gcc setjmp and llvm longjmp.
+ MIB = BuildMI(*MBB, MI, DL, TII->get(SystemZ::LG), SystemZ::R13D)
+ .addReg(BufReg)
+ .addImm(LPOffset)
+ .addReg(0);
+
+ bool BackChain = MF->getSubtarget<SystemZSubtarget>().hasBackChain();
+ if (BackChain) {
+ const int64_t BCOffset = 2 * PVT.getStoreSize();
+ MIB = BuildMI(*MBB, MI, DL, TII->get(SystemZ::LG), BCReg)
+ .addReg(BufReg)
+ .addImm(BCOffset)
+ .addReg(0);
+ }
+
+ MIB = BuildMI(*MBB, MI, DL, TII->get(SystemZ::LG), SystemZ::R15D)
+ .addReg(BufReg)
+ .addImm(SPOffset)
+ .addReg(0);
+
+ if (BackChain) {
+ BuildMI(*MBB, MI, DL, TII->get(SystemZ::STG))
+ .addReg(BCReg)
+ .addReg(SystemZ::R15D)
+ .addImm(0)
+ .addReg(0);
+ }
+
+ MIB = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BR)).addReg(Tmp);
+
+ MI.eraseFromParent();
+ return MBB;
+}
+
+// Returns true if stack probing through inline assembly is requested.
bool SystemZTargetLowering::hasInlineStackProbe(const MachineFunction &MF) const {
// If the function specifically requests inline stack probes, emit them.
if (MF.getFunction().hasFnAttribute("probe-stack"))
@@ -6292,6 +6534,10 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op,
return lowerGET_ROUNDING(Op, DAG);
case ISD::READCYCLECOUNTER:
return lowerREADCYCLECOUNTER(Op, DAG);
+ case ISD::EH_SJLJ_SETJMP:
+ case ISD::EH_SJLJ_LONGJMP:
+ return Op;
+
default:
llvm_unreachable("Unexpected node to lower");
}
@@ -9724,6 +9970,11 @@ MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter(
case SystemZ::PROBED_ALLOCA:
return emitProbedAlloca(MI, MBB);
+
+ case SystemZ::EH_SjLj_SetJmp:
+ return emitEHSjLjSetJmp(MI, MBB);
+ case SystemZ::EH_SjLj_LongJmp:
+ return emitEHSjLjLongJmp(MI, MBB);
case TargetOpcode::STACKMAP:
case TargetOpcode::PATCHPOINT:
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 3c06c1fdf2b1bc..92ac938c903b68 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -476,6 +476,12 @@ class SystemZTargetLowering : public TargetLowering {
// LD, and having the full constant in memory enables reg/mem opcodes.
return VT != MVT::f64;
}
+ MachineBasicBlock *emitEHSjLjSetJmp(MachineInstr &MI,
+ MachineBasicBlock *MBB) const;
+
+ MachineBasicBlock *emitEHSjLjLongJmp(MachineInstr &MI,
+ MachineBasicBlock *MBB) const;
+
bool hasInlineStackProbe(const MachineFunction &MF) const override;
AtomicExpansionKind shouldCastAtomicLoadInIR(LoadInst *LI) const override;
AtomicExpansionKind shouldCastAtomicStoreInIR(StoreInst *SI) const override;
@@ -723,6 +729,7 @@ class SystemZTargetLowering : public TargetLowering {
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const;
+
bool canTreatAsByteVector(EVT VT) const;
SDValue combineExtract(const SDLoc &DL, EVT ElemVT, EVT VecVT, SDValue OrigOp,
unsigned Index, DAGCombinerInfo &DCI,
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
index f3baf896658de5..ad7ee522a8c6f7 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -1871,6 +1871,20 @@ let mayLoad = 1, mayStore = 1, Defs = [CC] in {
}
}
+//--------------------------------------------------------------------------
+// Setjmp/Longjmp.
+//--------------------------------------------------------------------------
+let isTerminator = 1, isBarrier = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1, Size = 0 in {
+ def EH_SjLj_Setup : Pseudo<(outs), (ins brtarget32:$dst), []>;
+}
+
+let hasSideEffects = 1, isBarrier = 1, usesCustomInserter = 1, hasNoSchedulingInfo = 1 in {
+ def EH_SjLj_SetJmp : Pseudo<(outs GR32:$dst), (ins ADDR64:$R2), [(set GR32:$dst, (z_eh_sjlj_setjmp ADDR64:$R2))]>;
+}
+
+let hasSideEffects = 1, isTerminator = 1, isBarrier = 1, usesCustomInserter = 1, hasNoSchedulingInfo = 1 in {
+ def EH_SjLj_LongJmp : Pseudo<(outs), (ins ADDR64:$R2), [(z_eh_sjlj_longjmp ADDR64:$R2)]>;
+}
//===----------------------------------------------------------------------===//
// Message-security assist
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp b/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp
index 632218cc61eefe..8267d398c50ed6 100644
--- a/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp
@@ -220,7 +220,10 @@ static unsigned getInstSizeInBytes(const MachineInstr &MI,
MI.isImplicitDef() || MI.getOpcode() == TargetOpcode::MEMBARRIER ||
// These have a size that may be zero:
MI.isInlineAsm() || MI.getOpcode() == SystemZ::STACKMAP ||
- MI.getOpcode() == SystemZ::PATCHPOINT) &&
+ MI.getOpcode() == SystemZ::PATCHPOINT ||
+ // EH_SjLj_Setup is a dummy terminator instruction of size 0,
+ // It is used to handle the clobber register for builtin setjmp.
+ MI.getOpcode() == SystemZ::EH_SjLj_Setup) &&
"Missing size value for instruction.");
return Size;
}
diff --git a/llvm/lib/Target/SystemZ/SystemZOperators.td b/llvm/lib/Target/SystemZ/SystemZOperators.td
index 6cb89ccff85e68..90fb4e5f370dab 100644
--- a/llvm/lib/Target/SystemZ/SystemZOperators.td
+++ b/llvm/lib/Target/SystemZ/SystemZOperators.td
@@ -238,6 +238,12 @@ def SDT_ZTest : SDTypeProfile<1, 2,
[SDTCisVT<0, i32>,
SDTCisVT<2, i64>]>;
+def SDT_ZSetJmp : SDTypeProfile<1, 1,
+ [SDTCisInt<0>,
+ SDTCisPtrTy<1>]>;
+def SDT_ZLongJmp : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
+
+
//===----------------------------------------------------------------------===//
// Node definitions
//===----------------------------------------------------------------------===//
@@ -314,6 +320,12 @@ def z_stckf : SDNode<"SystemZISD::STCKF", SDT_ZStoreInherent,
def z_tdc : SDNode<"SystemZISD::TDC", SDT_ZTest>;
+def z_eh_sjlj_setjmp : SDNode<"ISD::EH_SJLJ_SETJMP", SDT_ZSetJmp,
+ [SDNPHasChain, SDNPSideEffect]>;
+def z_eh_sjlj_longjmp : SDNode<"ISD::EH_SJLJ_LONGJMP", SDT_ZLongJmp,
+ [SDNPHasChain, SDNPSideEffect]>;
+
+
// Defined because the index is an i32 rather than a pointer.
def z_vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT",
SDT_ZInsertVectorElt>;
diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
index d246d3f3c5bd11..6d3e542c1b4e81 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
@@ -254,6 +254,11 @@ SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
return Regs->getCallPreservedMask(MF, CC);
}
+const uint32_t*
+SystemZRegisterInfo::getNoPreservedMask() const {
+ return CSR_SystemZ_NoRegs_RegMask;
+}
+
BitVector
SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved(getNumRegs());
diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h
index cbc02c73f1ac70..4f497f8d23d29a 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.h
@@ -161,6 +161,7 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo {
const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
const uint32_t *getCallPreservedMask(const MachineFunction &MF,
CallingConv::ID CC) const override;
+ const uint32_t *getNoPreservedMask() const override;
BitVector getReservedRegs(const MachineFunction &MF) const override;
bool eliminateFrameIndex(MachineBasicBlock::iterator MI,
int SPAdj, unsigned FIOperandNum,
diff --git a/llvm/test/CodeGen/SystemZ/builtin-longjmp-01.ll b/llvm/test/CodeGen/SystemZ/builtin-longjmp-01.ll
new file mode 100644
index 00000000000000..413b651acb64a7
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/builtin-longjmp-01.ll
@@ -0,0 +1,44 @@
+;Test longjmp load from jmp_buf.
+; Frame pointer from Slot 1.
+; Jump address from Slot 2.
+; Stack Pointer from Slot 4.
+; Literal Pool Pointer from Slot 5.
+
+; RUN: llc -O2 < %s | FileCheck %s
+
+
+; ModuleID = 'longjmp.c'
+source_filename = "longjmp.c"
+target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
+target triple = "s390x-unknown-linux-gnu"
+
+ at buf = dso_local global [20 x ptr] zeroinitializer, align 8
+
+; Function Attrs: noreturn nounwind
+define dso_local void @foo() local_unnamed_addr #0 {
+entry:
+; CHECK: stmg %r11, %r15, 88(%r15)
+; CHECK: larl %r1, buf
+; CHECK: lg %r2, 8(%r1)
+; CHECK: lg %r11, 0(%r1)
+; CHECK: lg %r13, 32(%r1)
+; CHECK: lg %r15, 24(%r1)
+; CHECK: br %r2
+
+ tail call void @llvm.eh.sjlj.longjmp(ptr nonnull @buf)
+ unreachable
+}
+
+; Function Attrs: noreturn nounwind
+declare void @llvm.eh.sjlj.longjmp(ptr) #1
+
+attributes #0 = { noreturn nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="z10" }
+attributes #1 = { noreturn nounwind }
+
+!llvm.module.flags = !{!0, !1, !2}
+!llvm.ident = !{!3}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 8, !"PIC Level", i32 2}
+!2 = !{i32 7, !"PIE Level", i32 2}
+!3 = !{!"clang version 20.0.0git (https://github.com/llvm/llvm-project.git 79880371396d6e486bf6bacd6c4087ebdac591f8)"}
diff --git a/llvm/test/CodeGen/SystemZ/builtin-longjmp-backchain-01.ll b/llvm/test/CodeGen/SystemZ/builtin-longjmp-backchain-01.ll
new file mode 100644
index 00000000000000..39ee483c27cbd5
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/builtin-longjmp-backchain-01.ll
@@ -0,0 +1,46 @@
+;Test -mba...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/116642
More information about the cfe-commits
mailing list