LLVM 24.0.0git
BPFUnwind.cpp
Go to the documentation of this file.
1//===-- BPFUnwind.cpp - Lower unwinding to unwind_goto and unwind_exit ----===//
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// There are two ways to leave a frame, and a call that may unwind is followed
10// by an insn that tells them apart:
11// ret exit
12// invoke f() unwind pad call f; unwind_goto pad
13// resume r0 = 0; unwind_exit
14// call llvm.bpf.unwind.exit r0 = 0; unwind_exit
15// invoke llvm.bpf.unwind.exit goto pad
16// unwind_goto is taken when the callee left with unwind_exit. No register says
17// so: how one insn tells the other is up to the JIT. Otherwise unwind_exit is
18// exit, hence r0, and r2 as well in a function that returns more than 8 bytes.
19// A pad expects the exception object in r0. There is none, so a pad that looks
20// at it starts with r0 = 0.
21//
22// There is no unwinder library. A runtime starts an unwind by calling
23// llvm.bpf.unwind.exit, which leaves the frame with unwind_exit. resume, which
24// continues an unwind into the caller, does the same, so BPFUnwindPrepare
25// replaces it with the intrinsic.
26//
27// There are no tables and nothing for a loader to do.
28//
29//===----------------------------------------------------------------------===//
30
31#include "BPF.h"
32#include "BPFSubtarget.h"
34#include "llvm/ADT/SetVector.h"
39#include "llvm/IR/IRBuilder.h"
42#include "llvm/IR/IntrinsicsBPF.h"
43#include "llvm/IR/Module.h"
45
46using namespace llvm;
47
48/// Not being nounwind is the default in IR, so that alone is not enough:
49/// uwtable is how a frontend asks for unwinding through a function to work.
50static bool canUnwind(const Function &F) {
51 return F.hasUWTable() && !F.doesNotThrow();
52}
53
54namespace {
55
56/// Turn resume into llvm.bpf.unwind.exit, and calls that may unwind into
57/// invokes.
58struct BPFUnwindPrepare : public ModulePass {
59 static char ID;
60 BPFUnwindPrepare() : ModulePass(ID) {}
61 StringRef getPassName() const override { return "BPF Unwind Prepare"; }
62
63 Function *UnwindExit = nullptr;
64
65 Function *getUnwindExit(Module &M) {
66 if (!UnwindExit)
67 UnwindExit =
68 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::bpf_unwind_exit);
69 return UnwindExit;
70 }
71
72 static bool mayUnwind(const Instruction &I) {
73 const auto *CB = dyn_cast<CallBase>(&I);
74 return CB && !CB->doesNotThrow() && !CB->isInlineAsm() &&
76 }
77
78 bool runOnModule(Module &M) override {
79 bool Changed = false;
80 LLVMContext &C = M.getContext();
81 UnwindExit = nullptr;
82
83 for (Function &F : M) {
84 if (F.isDeclaration())
85 continue;
86
87 // Replace resume even if F cannot unwind, so BPFUnwindLower reports it.
88 for (BasicBlock &BB : F) {
89 if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator())) {
90 CallInst::Create(getUnwindExit(M), "", RI->getIterator())
91 ->setDebugLoc(RI->getDebugLoc());
93 Changed = true;
94 }
95 }
96
97 if (!canUnwind(F))
98 continue;
100 for (Instruction &I : instructions(F)) {
101 if (isa<CallInst>(I) && mayUnwind(I))
102 Calls.push_back(cast<CallInst>(&I));
103 }
104
105 if (Calls.empty())
106 continue;
107
108 if (!F.hasPersonalityFn())
109 F.setPersonalityFn(cast<Constant>(
110 M.getOrInsertFunction("__gcc_personality_v0",
111 FunctionType::get(Type::getInt32Ty(C), true))
112 .getCallee()));
113 BasicBlock *Pad = BasicBlock::Create(C, "unwind.resume", &F);
114 IRBuilder<> B(Pad);
115 LandingPadInst *LP = B.CreateLandingPad(
116 StructType::get(PointerType::getUnqual(C), Type::getInt32Ty(C)), 0);
117 LP->setCleanup(true);
118 B.CreateCall(getUnwindExit(M));
119 B.CreateUnreachable();
120 for (CallInst *CI : Calls)
122 Changed = true;
123 }
124 return Changed;
125 }
126};
127
128/// After register allocation, turn edges to landing pads into branches.
129struct BPFUnwindLower : public MachineFunctionPass {
130 static char ID;
131 BPFUnwindLower() : MachineFunctionPass(ID) {}
132 StringRef getPassName() const override { return "BPF Unwind Lower"; }
133
134 /// Nothing after \p MI in its block runs: \p Succ, if any, is what follows.
135 static void endBlockAfter(MachineInstr &MI, MachineBasicBlock *Succ) {
136 MachineBasicBlock &MBB = *MI.getParent();
137 MBB.erase(std::next(MI.getIterator()), MBB.end());
138 while (!MBB.succ_empty())
140 if (Succ)
141 MBB.addSuccessor(Succ);
142 }
143
144 static const char *unsupported(const MachineFunction &MF) {
145 if (MF.getLandingPads().empty())
146 return nullptr;
147 // Not canUnwind(): a function that catches everything is nounwind.
148 if (!MF.getFunction().hasUWTable())
149 return "BPF needs uwtable on a function with a landing pad";
150 // Every pad is a catch-all: the branch is taken whatever was thrown.
151 for (const LandingPadInfo &LP : MF.getLandingPads()) {
152 for (int TId : LP.TypeIds) {
153 if (TId > 0 && MF.getTypeInfos()[TId - 1])
154 return "BPF does not support type-specific exception catches yet";
155 // An empty filter lets nothing through, so it is a catch-all too. rustc
156 // guards every function that must not unwind with one.
157 if (TId < 0 && MF.getFilterIds()[-1 - TId])
158 return "BPF does not support exception filters yet";
159 }
160 }
161 return nullptr;
162 }
163
164 bool runOnMachineFunction(MachineFunction &MF) override {
165 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
166 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
167 DenseMap<MCSymbol *, MachineBasicBlock *> Begin;
169 SmallVector<MachineInstr *, 8> Labels, Resumes;
170 SmallSetVector<MachineBasicBlock *, 8> Pads;
171
172 const char *Msg = unsupported(MF);
173 if (Msg) {
174 const Function &F = MF.getFunction();
175 F.getContext().diagnose(DiagnosticInfoUnsupported(F, Msg));
176 }
177
178 for (const LandingPadInfo &LP : MF.getLandingPads())
179 for (MCSymbol *Sym : LP.BeginLabels)
180 Begin[Sym] = LP.LandingPadBlock;
181
182 // The call is not always in the block of the label: an argument that is
183 // a select is computed after the label and takes blocks of its own.
184 SmallPtrSet<MachineInstr *, 8> Invokes;
185 for (MachineBasicBlock &MBB : MF) {
186 for (MachineInstr &Label : MBB) {
187 if (!Label.isEHLabel())
188 continue;
189 Labels.push_back(&Label);
190 MachineBasicBlock *Pad =
191 Begin.lookup(Label.getOperand(0).getMCSymbol());
192 if (!Pad)
193 continue;
195 4>
196 Work{{&MBB, std::next(Label.getIterator())}};
197 SmallPtrSet<MachineBasicBlock *, 4> Seen;
198 while (!Work.empty()) {
199 auto [Cur, I] = Work.pop_back_val();
200 // The next label ends the range.
201 for (; I != Cur->end() && !I->isEHLabel(); ++I)
202 if (I->isCall() && Invokes.insert(&*I).second)
203 Sites.push_back({&*I, Pad});
204 if (I != Cur->end())
205 continue;
206 for (MachineBasicBlock *Succ : Cur->successors())
207 if (!Succ->isEHPad() && Seen.insert(Succ).second)
208 Work.push_back({Succ, Succ->begin()});
209 }
210 }
211 }
212 for (MachineBasicBlock &MBB : MF)
213 for (MachineInstr &MI : MBB)
214 if (MI.getOpcode() == BPF::UNWIND_EXIT_PSEUDO && !Invokes.count(&MI))
215 Resumes.push_back(&MI);
216 if (Labels.empty() && Resumes.empty())
217 return false;
218 // There is no unwind_goto after the calls of it.
219 if (!Msg && !Resumes.empty() && !canUnwind(MF.getFunction())) {
220 const Function &F = MF.getFunction();
221 F.getContext().diagnose(DiagnosticInfoUnsupported(
222 F, "BPF cannot unwind out of a function that is nounwind or has no "
223 "uwtable"));
224 }
225 for (MachineInstr *MI : Labels)
226 MI->eraseFromParent();
227
228 for (auto [Call, Pad] : Sites) {
229 MachineBasicBlock *MBB = Call->getParent();
231 const auto *II =
233
234 Pads.insert(Pad);
235 if (Call->getOpcode() == BPF::UNWIND_EXIT_PSEUDO) {
236 endBlockAfter(*Call, Pad);
237 BuildMI(MBB, DL, TII.get(BPF::JMP)).addMBB(Pad);
239 } else if (II && II->doesNotReturn()) {
240 // Nothing sensible follows the call, but something has to.
241 endBlockAfter(*Call, Pad);
242 BuildMI(MBB, DL, TII.get(BPF::UNWIND_GOTO)).addMBB(Pad);
243 BuildMI(MBB, DL, TII.get(BPF::JMP)).addMBB(Pad);
244 } else {
245 MachineBasicBlock *Rest = MBB->splitAt(*Call);
246 if (Rest != MBB) {
247 Rest->removeSuccessor(Pad);
248 MBB->addSuccessor(Pad);
249 }
250 BuildMI(MBB, DL, TII.get(BPF::UNWIND_GOTO)).addMBB(Pad);
251 }
252 }
253
254 for (MachineBasicBlock *Pad : Pads) {
255 LivePhysRegs Live(TRI);
256 Live.addLiveOuts(*Pad);
257 for (MachineInstr &MI : reverse(*Pad))
258 Live.stepBackward(MI);
259 if (!Live.available(MF.getRegInfo(), BPF::R0))
260 BuildMI(*Pad, Pad->begin(), DebugLoc(), TII.get(BPF::MOV_ri), BPF::R0)
261 .addImm(0);
262 Pad->removeLiveIn(BPF::R0);
263 }
264
265 // unwind_exit returns what exit returns: a value of more than 8 bytes is in
266 // r0 and r2.
268 const Function &F = MF.getFunction();
269 GetReturnInfo(F.getCallingConv(), F.getReturnType(), F.getAttributes(),
270 Outs, *MF.getSubtarget().getTargetLowering(),
271 MF.getDataLayout());
272
273 for (MachineInstr *Call : Resumes) {
274 MachineBasicBlock *MBB = Call->getParent();
276
277 BuildMI(*MBB, Call, DL, TII.get(BPF::MOV_ri), BPF::R0).addImm(0);
278 MachineInstrBuilder Exit =
279 BuildMI(*MBB, Call, DL, TII.get(BPF::UNWIND_EXIT))
280 .addReg(BPF::R0, RegState::Implicit);
281 if (Outs.size() > 1) {
282 BuildMI(*MBB, *Exit, DL, TII.get(BPF::MOV_ri), BPF::R2).addImm(0);
283 Exit.addReg(BPF::R2, RegState::Implicit);
284 }
285 endBlockAfter(*Exit, nullptr);
286 }
287
288 // The pads are plain blocks now and there is no table to emit.
289 for (MachineBasicBlock &MBB : MF)
290 MBB.setIsEHPad(false);
291 MF.clearLandingPads();
292
293 // What was behind a call that does not return. It can be a loop.
294 df_iterator_default_set<MachineBasicBlock *> Reachable;
295 for (MachineBasicBlock *MBB : depth_first_ext(&MF, Reachable))
296 (void)MBB;
297 for (MachineBasicBlock &MBB : make_early_inc_range(MF)) {
298 if (Reachable.count(&MBB) || MBB.hasAddressTaken())
299 continue;
300 while (!MBB.succ_empty())
303 }
304 for (MachineBasicBlock &MBB : MF)
305 if (!MBB.empty() && MBB.back().getOpcode() == BPF::JMP &&
308 return true;
309 }
310};
311
312} // namespace
313
314char BPFUnwindPrepare::ID = 0;
315char BPFUnwindLower::ID = 0;
316
317INITIALIZE_PASS(BPFUnwindPrepare, "bpf-unwind-prepare", "BPF Unwind Prepare",
318 false, false)
319INITIALIZE_PASS(BPFUnwindLower, "bpf-unwind-lower", "BPF Unwind Lower", false,
320 false)
321
323 return new BPFUnwindPrepare();
324}
325FunctionPass *llvm::createBPFUnwindLowerPass() { return new BPFUnwindLower(); }
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static bool canUnwind(const Function &F)
Not being nounwind is the default in IR, so that alone is not enough: uwtable is how a frontend asks ...
Definition BPFUnwind.cpp:50
static Error unsupported(const char *Str, const Triple &T)
Definition MachO.cpp:79
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
const char * Msg
This file implements a set that has insertion order iteration characteristics.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:793
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:312
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:352
bool hasUWTable() const
True if the ABI mandates (or the user requested) that this function be in a unwind table.
Definition Function.h:657
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
void setCleanup(bool V)
Indicate that this landingpad instruction is a cleanup.
bool isEHPad() const
Returns true if the block is a landing pad.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void removeLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll())
Remove the specified register from the live in set.
bool hasAddressTaken() const
Test whether this block is used as something other than the target of a terminator,...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
LLVM_ABI bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
void setIsEHPad(bool V=true)
Indicates the block is a landing pad.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const std::vector< unsigned > & getFilterIds() const
Return a reference to the typeids encoding filters used in the current function.
const std::vector< const GlobalValue * > & getTypeInfos() const
Return a reference to the C++ typeinfo for the current function.
Function & getFunction()
Return the LLVM function that this machine code represents.
const std::vector< LandingPadInfo > & getLandingPads() const
Return a reference to the landing pad info for the current function.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineBasicBlock * getMBB() const
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:253
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void push_back(const T &Elt)
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:467
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
const ParentTy * getParent() const
Definition ilist_node.h:34
CallInst * Call
TargetPassConfig.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< df_ext_iterator< T, SetTy > > depth_first_ext(const T &G, SetTy &S)
LLVM_ABI BasicBlock * changeToInvokeAndSplitBasicBlock(CallInst *CI, BasicBlock *UnwindEdge, DomTreeUpdater *DTU=nullptr)
Convert the CallInst to InvokeInst with the specified unwind edge basic block.
Definition Local.cpp:2636
LLVM_ABI void GetReturnInfo(CallingConv::ID CC, Type *ReturnType, AttributeList attr, SmallVectorImpl< ISD::OutputArg > &Outs, const TargetLowering &TLI, const DataLayout &DL)
Given an LLVM IR type and return type attributes, compute the return value EVTs and flags,...
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
ModulePass * createBPFUnwindPreparePass()
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
Definition Local.cpp:2547
FunctionPass * createBPFUnwindLowerPass()
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559