xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVLandingPadSetup.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===------------ RISCVLandingPadSetup.cpp ---------------------------------==//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // This is a RISC-V pass to setup landing pad labels for indirect jumps.
10*700637cbSDimitry Andric // Currently this pass only supports fixed labels.
11*700637cbSDimitry Andric //
12*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
13*700637cbSDimitry Andric 
14*700637cbSDimitry Andric #include "RISCV.h"
15*700637cbSDimitry Andric #include "RISCVInstrInfo.h"
16*700637cbSDimitry Andric #include "RISCVSubtarget.h"
17*700637cbSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
18*700637cbSDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
19*700637cbSDimitry Andric 
20*700637cbSDimitry Andric using namespace llvm;
21*700637cbSDimitry Andric 
22*700637cbSDimitry Andric #define DEBUG_TYPE "riscv-lpad-setup"
23*700637cbSDimitry Andric #define PASS_NAME "RISC-V Landing Pad Setup"
24*700637cbSDimitry Andric 
25*700637cbSDimitry Andric extern cl::opt<uint32_t> PreferredLandingPadLabel;
26*700637cbSDimitry Andric 
27*700637cbSDimitry Andric namespace {
28*700637cbSDimitry Andric 
29*700637cbSDimitry Andric class RISCVLandingPadSetup : public MachineFunctionPass {
30*700637cbSDimitry Andric public:
31*700637cbSDimitry Andric   static char ID;
32*700637cbSDimitry Andric 
RISCVLandingPadSetup()33*700637cbSDimitry Andric   RISCVLandingPadSetup() : MachineFunctionPass(ID) {}
34*700637cbSDimitry Andric 
35*700637cbSDimitry Andric   bool runOnMachineFunction(MachineFunction &F) override;
36*700637cbSDimitry Andric 
getPassName() const37*700637cbSDimitry Andric   StringRef getPassName() const override { return PASS_NAME; }
38*700637cbSDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const39*700637cbSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
40*700637cbSDimitry Andric     AU.setPreservesCFG();
41*700637cbSDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
42*700637cbSDimitry Andric   }
43*700637cbSDimitry Andric };
44*700637cbSDimitry Andric 
45*700637cbSDimitry Andric } // end anonymous namespace
46*700637cbSDimitry Andric 
runOnMachineFunction(MachineFunction & MF)47*700637cbSDimitry Andric bool RISCVLandingPadSetup::runOnMachineFunction(MachineFunction &MF) {
48*700637cbSDimitry Andric   const auto &STI = MF.getSubtarget<RISCVSubtarget>();
49*700637cbSDimitry Andric   const RISCVInstrInfo &TII = *STI.getInstrInfo();
50*700637cbSDimitry Andric 
51*700637cbSDimitry Andric   if (!STI.hasStdExtZicfilp())
52*700637cbSDimitry Andric     return false;
53*700637cbSDimitry Andric 
54*700637cbSDimitry Andric   uint32_t Label = 0;
55*700637cbSDimitry Andric   if (PreferredLandingPadLabel.getNumOccurrences() > 0) {
56*700637cbSDimitry Andric     if (!isUInt<20>(PreferredLandingPadLabel))
57*700637cbSDimitry Andric       report_fatal_error("riscv-landing-pad-label=<val>, <val> needs to fit in "
58*700637cbSDimitry Andric                          "unsigned 20-bits");
59*700637cbSDimitry Andric     Label = PreferredLandingPadLabel;
60*700637cbSDimitry Andric   }
61*700637cbSDimitry Andric 
62*700637cbSDimitry Andric   // Zicfilp does not check X7 if landing pad label is zero.
63*700637cbSDimitry Andric   if (Label == 0)
64*700637cbSDimitry Andric     return false;
65*700637cbSDimitry Andric 
66*700637cbSDimitry Andric   bool Changed = false;
67*700637cbSDimitry Andric   for (MachineBasicBlock &MBB : MF)
68*700637cbSDimitry Andric     for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
69*700637cbSDimitry Andric       if (MI.getOpcode() != RISCV::PseudoBRINDNonX7 &&
70*700637cbSDimitry Andric           MI.getOpcode() != RISCV::PseudoCALLIndirectNonX7 &&
71*700637cbSDimitry Andric           MI.getOpcode() != RISCV::PseudoTAILIndirectNonX7)
72*700637cbSDimitry Andric         continue;
73*700637cbSDimitry Andric       BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(RISCV::LUI), RISCV::X7)
74*700637cbSDimitry Andric           .addImm(Label);
75*700637cbSDimitry Andric       MachineInstrBuilder(MF, &MI).addUse(RISCV::X7, RegState::ImplicitKill);
76*700637cbSDimitry Andric       Changed = true;
77*700637cbSDimitry Andric     }
78*700637cbSDimitry Andric 
79*700637cbSDimitry Andric   return Changed;
80*700637cbSDimitry Andric }
81*700637cbSDimitry Andric 
82*700637cbSDimitry Andric INITIALIZE_PASS(RISCVLandingPadSetup, DEBUG_TYPE, PASS_NAME, false, false)
83*700637cbSDimitry Andric 
84*700637cbSDimitry Andric char RISCVLandingPadSetup::ID = 0;
85*700637cbSDimitry Andric 
createRISCVLandingPadSetupPass()86*700637cbSDimitry Andric FunctionPass *llvm::createRISCVLandingPadSetupPass() {
87*700637cbSDimitry Andric   return new RISCVLandingPadSetup();
88*700637cbSDimitry Andric }
89