[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