1 | //===-- BPFRegisterInfo.cpp - BPF Register Information ----------*- C++ -*-===// |
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 file contains the BPF implementation of the TargetRegisterInfo class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "BPFRegisterInfo.h" |
14 | #include "BPF.h" |
15 | #include "BPFSubtarget.h" |
16 | #include "llvm/CodeGen/MachineFrameInfo.h" |
17 | #include "llvm/CodeGen/MachineFunction.h" |
18 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
19 | #include "llvm/CodeGen/RegisterScavenging.h" |
20 | #include "llvm/CodeGen/TargetFrameLowering.h" |
21 | #include "llvm/CodeGen/TargetInstrInfo.h" |
22 | #include "llvm/IR/DiagnosticInfo.h" |
23 | #include "llvm/Support/CommandLine.h" |
24 | #include "llvm/Support/ErrorHandling.h" |
25 | |
26 | #define GET_REGINFO_TARGET_DESC |
27 | #include "BPFGenRegisterInfo.inc" |
28 | using namespace llvm; |
29 | |
30 | static cl::opt<int> |
31 | BPFStackSizeOption("bpf-stack-size" , |
32 | cl::desc("Specify the BPF stack size limit" ), |
33 | cl::init(512)); |
34 | |
35 | BPFRegisterInfo::BPFRegisterInfo() |
36 | : BPFGenRegisterInfo(BPF::R0) {} |
37 | |
38 | const MCPhysReg * |
39 | BPFRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { |
40 | return CSR_SaveList; |
41 | } |
42 | |
43 | BitVector BPFRegisterInfo::getReservedRegs(const MachineFunction &MF) const { |
44 | BitVector Reserved(getNumRegs()); |
45 | markSuperRegs(Reserved, BPF::W10); // [W|R]10 is read only frame pointer |
46 | markSuperRegs(Reserved, BPF::W11); // [W|R]11 is pseudo stack pointer |
47 | return Reserved; |
48 | } |
49 | |
50 | static void WarnSize(int Offset, MachineFunction &MF, DebugLoc& DL) |
51 | { |
52 | if (Offset <= -BPFStackSizeOption) { |
53 | const Function &F = MF.getFunction(); |
54 | DiagnosticInfoUnsupported DiagStackSize( |
55 | F, |
56 | "Looks like the BPF stack limit is exceeded. " |
57 | "Please move large on stack variables into BPF per-cpu array map. For " |
58 | "non-kernel uses, the stack can be increased using -mllvm " |
59 | "-bpf-stack-size.\n" , |
60 | DL); |
61 | F.getContext().diagnose(DI: DiagStackSize); |
62 | } |
63 | } |
64 | |
65 | bool BPFRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, |
66 | int SPAdj, unsigned FIOperandNum, |
67 | RegScavenger *RS) const { |
68 | assert(SPAdj == 0 && "Unexpected" ); |
69 | |
70 | unsigned i = 0; |
71 | MachineInstr &MI = *II; |
72 | MachineBasicBlock &MBB = *MI.getParent(); |
73 | MachineFunction &MF = *MBB.getParent(); |
74 | DebugLoc DL = MI.getDebugLoc(); |
75 | |
76 | if (!DL) |
77 | /* try harder to get some debug loc */ |
78 | for (auto &I : MBB) |
79 | if (I.getDebugLoc()) { |
80 | DL = I.getDebugLoc(); |
81 | break; |
82 | } |
83 | |
84 | while (!MI.getOperand(i).isFI()) { |
85 | ++i; |
86 | assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!" ); |
87 | } |
88 | |
89 | Register FrameReg = getFrameRegister(MF); |
90 | int FrameIndex = MI.getOperand(i).getIndex(); |
91 | const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); |
92 | |
93 | if (MI.getOpcode() == BPF::MOV_rr) { |
94 | int Offset = MF.getFrameInfo().getObjectOffset(ObjectIdx: FrameIndex); |
95 | |
96 | WarnSize(Offset, MF, DL); |
97 | MI.getOperand(i).ChangeToRegister(Reg: FrameReg, isDef: false); |
98 | Register reg = MI.getOperand(i: i - 1).getReg(); |
99 | BuildMI(MBB, ++II, DL, TII.get(BPF::ADD_ri), reg) |
100 | .addReg(reg) |
101 | .addImm(Offset); |
102 | return false; |
103 | } |
104 | |
105 | int Offset = MF.getFrameInfo().getObjectOffset(ObjectIdx: FrameIndex) + |
106 | MI.getOperand(i: i + 1).getImm(); |
107 | |
108 | if (!isInt<32>(x: Offset)) |
109 | llvm_unreachable("bug in frame offset" ); |
110 | |
111 | WarnSize(Offset, MF, DL); |
112 | |
113 | if (MI.getOpcode() == BPF::FI_ri) { |
114 | // architecture does not really support FI_ri, replace it with |
115 | // MOV_rr <target_reg>, frame_reg |
116 | // ADD_ri <target_reg>, imm |
117 | Register reg = MI.getOperand(i: i - 1).getReg(); |
118 | |
119 | BuildMI(MBB, ++II, DL, TII.get(BPF::MOV_rr), reg) |
120 | .addReg(FrameReg); |
121 | BuildMI(MBB, II, DL, TII.get(BPF::ADD_ri), reg) |
122 | .addReg(reg) |
123 | .addImm(Offset); |
124 | |
125 | // Remove FI_ri instruction |
126 | MI.eraseFromParent(); |
127 | } else { |
128 | MI.getOperand(i).ChangeToRegister(Reg: FrameReg, isDef: false); |
129 | MI.getOperand(i: i + 1).ChangeToImmediate(ImmVal: Offset); |
130 | } |
131 | return false; |
132 | } |
133 | |
134 | Register BPFRegisterInfo::getFrameRegister(const MachineFunction &MF) const { |
135 | return BPF::R10; |
136 | } |
137 | |