[clang] [llvm] [SystemZ] Add support for __builtin_setjmp and __builtin_longjmp (PR #116642)
Ulrich Weigand via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 19 08:08:07 PST 2024
================
@@ -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)
----------------
uweigand wrote:
Even though this function will probably only be used on Linux, we still should use `getFramePointerRegister()` (from `Subtarget.getSpecialRegisters()`) here instead of hardcoding R11.
https://github.com/llvm/llvm-project/pull/116642
More information about the cfe-commits
mailing list