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