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>(x: PreferredLandingPadLabel)) |
57 | report_fatal_error(reason: "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(Range&: MBB)) { |
69 | if (MI.getOpcode() != RISCV::PseudoBRINDNonX7 && |
70 | MI.getOpcode() != RISCV::PseudoCALLIndirectNonX7 && |
71 | MI.getOpcode() != RISCV::PseudoTAILIndirectNonX7) |
72 | continue; |
73 | BuildMI(BB&: MBB, I&: MI, MIMD: MI.getDebugLoc(), MCID: TII.get(Opcode: RISCV::LUI), DestReg: RISCV::X7) |
74 | .addImm(Val: Label); |
75 | MachineInstrBuilder(MF, &MI).addUse(RegNo: RISCV::X7, Flags: 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 | |