[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)
+ .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)
----------------
uweigand wrote:
Here I guess we have to hardcode this.
https://github.com/llvm/llvm-project/pull/116642
More information about the cfe-commits
mailing list