1 //===------ RISCVIndirectBranchTracking.cpp - Enables lpad mechanism ------===// 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 // The pass adds LPAD (AUIPC with rs1 = X0) machine instructions at the 10 // beginning of each basic block or function that is referenced by an indrect 11 // jump/call instruction. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "RISCV.h" 16 #include "RISCVInstrInfo.h" 17 #include "RISCVSubtarget.h" 18 #include "llvm/ADT/Statistic.h" 19 #include "llvm/CodeGen/MachineFunctionPass.h" 20 #include "llvm/CodeGen/MachineInstrBuilder.h" 21 #include "llvm/CodeGen/MachineModuleInfo.h" 22 23 using namespace llvm; 24 25 cl::opt<uint32_t> PreferredLandingPadLabel( 26 "riscv-landing-pad-label", cl::ReallyHidden, 27 cl::desc("Use preferred fixed label for all labels")); 28 29 namespace { 30 class RISCVIndirectBranchTrackingPass : public MachineFunctionPass { 31 public: 32 RISCVIndirectBranchTrackingPass() : MachineFunctionPass(ID) {} 33 34 StringRef getPassName() const override { 35 return "RISC-V Indirect Branch Tracking"; 36 } 37 38 bool runOnMachineFunction(MachineFunction &MF) override; 39 40 private: 41 static char ID; 42 const Align LpadAlign = Align(4); 43 }; 44 45 } // end anonymous namespace 46 47 char RISCVIndirectBranchTrackingPass::ID = 0; 48 49 FunctionPass *llvm::createRISCVIndirectBranchTrackingPass() { 50 return new RISCVIndirectBranchTrackingPass(); 51 } 52 53 static void emitLpad(MachineBasicBlock &MBB, const RISCVInstrInfo *TII, 54 uint32_t Label) { 55 auto I = MBB.begin(); 56 BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(RISCV::AUIPC), RISCV::X0) 57 .addImm(Label); 58 } 59 60 bool RISCVIndirectBranchTrackingPass::runOnMachineFunction( 61 MachineFunction &MF) { 62 const auto &Subtarget = MF.getSubtarget<RISCVSubtarget>(); 63 const RISCVInstrInfo *TII = Subtarget.getInstrInfo(); 64 if (!Subtarget.hasStdExtZicfilp()) 65 return false; 66 67 uint32_t FixedLabel = 0; 68 if (PreferredLandingPadLabel.getNumOccurrences() > 0) { 69 if (!isUInt<20>(PreferredLandingPadLabel)) 70 report_fatal_error("riscv-landing-pad-label=<val>, <val> needs to fit in " 71 "unsigned 20-bits"); 72 FixedLabel = PreferredLandingPadLabel; 73 } 74 75 bool Changed = false; 76 for (MachineBasicBlock &MBB : MF) { 77 if (&MBB == &MF.front()) { 78 Function &F = MF.getFunction(); 79 // When trap is taken, landing pad is not needed. 80 if (F.hasFnAttribute("interrupt")) 81 continue; 82 83 if (F.hasAddressTaken() || !F.hasLocalLinkage()) { 84 emitLpad(MBB, TII, FixedLabel); 85 if (MF.getAlignment() < LpadAlign) 86 MF.setAlignment(LpadAlign); 87 Changed = true; 88 } 89 continue; 90 } 91 92 if (MBB.hasAddressTaken()) { 93 emitLpad(MBB, TII, FixedLabel); 94 if (MBB.getAlignment() < LpadAlign) 95 MBB.setAlignment(LpadAlign); 96 Changed = true; 97 } 98 } 99 100 return Changed; 101 } 102