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