[clang] [llvm] [RISCV] SiFive CLIC Support (PR #132481)
Sam Elliott via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 25 16:06:17 PDT 2025
================
@@ -200,6 +203,149 @@ static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
CFIInstBuilder(MBB, MI, MachineInstr::FrameDestroy).buildRestore(SCSPReg);
}
+// Insert instruction to swap mscratchsw with sp
+static void emitSiFiveCLICStackSwap(MachineFunction &MF, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ const DebugLoc &DL) {
+ auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
+
+ if (!RVFI->isSiFiveStackSwapInterrupt(MF))
+ return;
+
+ const auto &STI = MF.getSubtarget<RISCVSubtarget>();
+ const RISCVInstrInfo *TII = STI.getInstrInfo();
+
+ assert(STI.hasVendorXSfmclic() && "Stack Swapping Requires XSfmclic");
+
+ BuildMI(MBB, MBBI, DL, TII->get(RISCV::CSRRW))
+ .addReg(SPReg, RegState::Define)
+ .addImm(RISCVSysReg::sf_mscratchcsw)
+ .addReg(SPReg, RegState::Kill)
+ .setMIFlag(MachineInstr::FrameSetup);
+
+ // FIXME: CFI Information for this swap.
+}
+
+static void
+createSiFivePreemptibleInterruptFrameEntries(MachineFunction &MF,
+ RISCVMachineFunctionInfo &RVFI) {
+ if (!RVFI.isSiFivePreemptibleInterrupt(MF))
+ return;
+
+ const TargetRegisterClass &RC = RISCV::GPRRegClass;
+ const TargetRegisterInfo &TRI =
+ *MF.getSubtarget<RISCVSubtarget>().getRegisterInfo();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+
+ // Create two frame objects for spilling X8 and X9, which will be done in
+ // `emitSiFiveCLICPreemptibleSaves`. This is in addition to any other stack
+ // objects we might have for X8 and X9, as they might be saved twice.
+ for (int I = 0; I < 2; ++I) {
+ int FI = MFI.CreateStackObject(TRI.getSpillSize(RC), TRI.getSpillAlign(RC),
+ true);
+ RVFI.pushInterruptCSRFrameIndex(FI);
+ }
+}
+
+static void emitSiFiveCLICPreemptibleSaves(MachineFunction &MF,
+ MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ const DebugLoc &DL) {
+ auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
+
+ if (!RVFI->isSiFivePreemptibleInterrupt(MF))
+ return;
+
+ const auto &STI = MF.getSubtarget<RISCVSubtarget>();
+ const RISCVInstrInfo *TII = STI.getInstrInfo();
+
+ // FIXME: CFI Information here is nonexistent/wrong.
+
+ // X8 and X9 might be stored into the stack twice, initially into the
+ // `interruptCSRFrameIndex` here, and then maybe again into their CSI frame
+ // index.
+ //
+ // This is done instead of telling the register allocator that we need two
+ // VRegs to store the value of `mcause` and `mepc` through the instruction,
+ // which affects other passes.
+ TII->storeRegToStackSlot(MBB, MBBI, RISCV::X8, /* IsKill=*/true,
+ RVFI->getInterruptCSRFrameIndex(0),
+ &RISCV::GPRRegClass, STI.getRegisterInfo(),
+ Register(), MachineInstr::FrameSetup);
+ TII->storeRegToStackSlot(MBB, MBBI, RISCV::X9, /* IsKill=*/true,
+ RVFI->getInterruptCSRFrameIndex(1),
+ &RISCV::GPRRegClass, STI.getRegisterInfo(),
+ Register(), MachineInstr::FrameSetup);
+
+ // Put `mcause` into X8 (s0), and `mepc` into X9 (s1). If either of these are
+ // used in the function, then they will appear in `getUnmanagedCSI` and will
+ // be saved again.
+ BuildMI(MBB, MBBI, DL, TII->get(RISCV::CSRRS))
+ .addReg(RISCV::X8, RegState::Define)
+ .addImm(RISCVSysReg::mcause)
+ .addReg(RISCV::X0)
+ .setMIFlag(MachineInstr::FrameSetup);
+ BuildMI(MBB, MBBI, DL, TII->get(RISCV::CSRRS))
+ .addReg(RISCV::X9, RegState::Define)
+ .addImm(RISCVSysReg::lookupSysRegByName("MEPC")->Encoding)
----------------
lenary wrote:
Oh, I thought I had got these. Yes definitely.
https://github.com/llvm/llvm-project/pull/132481
More information about the cfe-commits
mailing list