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 _Unwind_RaiseException r0 = 0; unwind_exit
15// invoke _Unwind_RaiseException 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// _Unwind_RaiseException() is how a language runtime starts an unwind with the
23// Itanium ABI, e.g. at the end of a panic handler. To start one and to carry
24// one on is the same thing here: leave the frame with unwind_exit, after its
25// own pad if it has one. It cannot fail, so it does not return.
26//
27// There are no tables and nothing for a loader to do.
28//
29//===----------------------------------------------------------------------===//
30
31#include "BPF.h"
32#include "BPFInstrInfo.h"
33#include "BPFSubtarget.h"
35#include "llvm/ADT/SetVector.h"
40#include "llvm/IR/IRBuilder.h"
43#include "llvm/IR/Module.h"
45
46using namespace llvm;
47
48/// On other targets it is a function of the unwinder library, which is why
49/// nothing else in LLVM knows the name.
50static constexpr StringLiteral UnwindRaise = "_Unwind_RaiseException";
51
52/// Not being nounwind is the default in IR, so that alone is not enough:
53/// uwtable is how a frontend asks for unwinding through a function to work.
54static bool canUnwind(const Function &F) {
55 return F.hasUWTable() && !F.doesNotThrow();
56}
57
58namespace {
59
60/// Make every call that may unwind an invoke: it ends its block and has a pad.
61struct BPFUnwindPrepare : public ModulePass {
62 static char ID;
63 BPFUnwindPrepare() : ModulePass(ID) {}
64 StringRef getPassName() const override { return "BPF Unwind Prepare"; }
65
66 static bool isRaise(const CallBase &CB) {
67 const auto *F = dyn_cast<Function>(CB.getCalledOperand());
68 return F && F->isDeclaration() && F->getName() == UnwindRaise;
69 }
70
71 static bool mayUnwind(const Instruction &I) {
72 const auto *CB = dyn_cast<CallBase>(&I);
73 return CB && !CB->doesNotThrow() && !CB->isInlineAsm() &&
75 }
76
77 bool runOnModule(Module &M) override {
78 bool Changed = false;
79
80 for (Function &F : M) {
81 if (F.isDeclaration() || !canUnwind(F))
82 continue;
83
84 LLVMContext &C = M.getContext();
86 for (Instruction &I : instructions(F)) {
87 auto *CB = dyn_cast<CallBase>(&I);
88 if (CB && isRaise(*CB)) {
89 // Nobody looks at the exception object.
90 for (Use &Arg : CB->args())
91 Arg.set(PoisonValue::get(Arg->getType()));
92 CB->setDoesNotReturn();
93 // Without a pad it leaves the frame.
94 if (isa<CallInst>(CB))
95 CB->setDoesNotThrow();
96 Changed = true;
97 } else if (isa<CallInst>(I) && mayUnwind(I)) {
98 Calls.push_back(cast<CallInst>(&I));
99 } else if (auto *RI = dyn_cast<ResumeInst>(&I)) {
100 // DwarfEHPrepare passes it to _Unwind_Resume(). Don't keep it alive
101 // over the pad for that.
102 RI->setOperand(0, PoisonValue::get(RI->getValue()->getType()));
103 Changed = true;
104 }
105 }
106 if (Calls.empty())
107 continue;
108
109 if (!F.hasPersonalityFn())
110 F.setPersonalityFn(cast<Constant>(
111 M.getOrInsertFunction("__gcc_personality_v0",
112 FunctionType::get(Type::getInt32Ty(C), true))
113 .getCallee()));
114 BasicBlock *Pad = BasicBlock::Create(C, "unwind.resume", &F);
115 IRBuilder<> B(Pad);
116 LandingPadInst *LP = B.CreateLandingPad(
117 StructType::get(PointerType::getUnqual(C), Type::getInt32Ty(C)), 0);
118 LP->setCleanup(true);
119 B.CreateResume(PoisonValue::get(LP->getType()));
120 for (CallInst *CI : Calls)
122 Changed = true;
123 }
124 return Changed;
125 }
126};
127
128/// After register allocation, which took call -> pad for an EH edge and so
129/// keeps only r6-r9 and the stack alive over it, turn the edge into a branch.
130struct BPFUnwindLower : public MachineFunctionPass {
131 static char ID;
132 BPFUnwindLower() : MachineFunctionPass(ID) {}
133 StringRef getPassName() const override { return "BPF Unwind Lower"; }
134
135 /// What DwarfEHPrepare made of 'resume'.
136 StringRef UnwindResume;
137
138 bool leavesFrame(const MachineInstr &MI) const {
139 const MachineOperand &MO = MI.getOperand(0);
140 // A program that defines them gets what it defines.
141 if (!MO.isGlobal() || !MO.getGlobal()->isDeclaration())
142 return false;
143 StringRef Name = MO.getGlobal()->getName();
144 return Name == UnwindRaise || Name == UnwindResume;
145 }
146
147 /// Nothing after \p MI in its block runs: \p Succ, if any, is what follows.
148 static void endBlockAfter(MachineInstr &MI, MachineBasicBlock *Succ) {
149 MachineBasicBlock &MBB = *MI.getParent();
150 MBB.erase(std::next(MI.getIterator()), MBB.end());
151 while (!MBB.succ_empty())
153 if (Succ)
154 MBB.addSuccessor(Succ);
155 }
156
157 /// The argument of a call that goes away is poison, which is 'r1 = 0'.
158 /// Nothing reads r1 after a call.
159 static void eraseArg(MachineInstr &Call) {
160 MachineBasicBlock::iterator I = Call, Begin = Call.getParent()->begin();
161 if (I == Begin)
162 return;
163 I = prev_nodbg(I, Begin);
164 if (I->getOpcode() == BPF::MOV_ri && I->getOperand(0).getReg() == BPF::R1)
165 I->eraseFromParent();
166 }
167
168 static const char *unsupported(const MachineFunction &MF) {
169 if (MF.getLandingPads().empty())
170 return nullptr;
171 // Not canUnwind(): a function that catches everything is nounwind.
172 if (!MF.getFunction().hasUWTable())
173 return "BPF needs uwtable on a function with a landing pad";
174 // Every pad is a catch-all: the branch is taken whatever was thrown.
175 for (const LandingPadInfo &LP : MF.getLandingPads()) {
176 for (int TId : LP.TypeIds) {
177 if (TId > 0 && MF.getTypeInfos()[TId - 1])
178 return "BPF does not support type-specific exception catches yet";
179 // An empty filter lets nothing through, so it is a catch-all too. rustc
180 // guards every function that must not unwind with one.
181 if (TId < 0 && MF.getFilterIds()[-1 - TId])
182 return "BPF does not support exception filters yet";
183 }
184 }
185 return nullptr;
186 }
187
188 bool runOnMachineFunction(MachineFunction &MF) override {
189 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
190 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
191 UnwindResume = MF.getSubtarget().getTargetLowering()->getLibcallName(
192 RTLIB::UNWIND_RESUME);
193 DenseMap<MCSymbol *, MachineBasicBlock *> Begin;
195 SmallVector<MachineInstr *, 8> Labels, Resumes;
196 SmallSetVector<MachineBasicBlock *, 8> Pads;
197
198 if (const char *Msg = unsupported(MF)) {
199 const Function &F = MF.getFunction();
200 F.getContext().diagnose(DiagnosticInfoUnsupported(F, Msg));
201 return false;
202 }
203
204 for (const LandingPadInfo &LP : MF.getLandingPads())
205 for (MCSymbol *Sym : LP.BeginLabels)
206 Begin[Sym] = LP.LandingPadBlock;
207
208 // The call is not always in the block of the label: an argument that is
209 // a select is computed after the label and takes blocks of its own.
210 SmallPtrSet<MachineInstr *, 8> Invokes;
211 for (MachineBasicBlock &MBB : MF) {
212 for (MachineInstr &Label : MBB) {
213 if (!Label.isEHLabel())
214 continue;
215 Labels.push_back(&Label);
216 MachineBasicBlock *Pad =
217 Begin.lookup(Label.getOperand(0).getMCSymbol());
218 if (!Pad)
219 continue;
221 4>
222 Work{{&MBB, std::next(Label.getIterator())}};
223 SmallPtrSet<MachineBasicBlock *, 4> Seen;
224 while (!Work.empty()) {
225 auto [Cur, I] = Work.pop_back_val();
226 // The next label ends the range.
227 for (; I != Cur->end() && !I->isEHLabel(); ++I)
228 if (I->isCall() && Invokes.insert(&*I).second)
229 Sites.push_back({&*I, Pad});
230 if (I != Cur->end())
231 continue;
232 for (MachineBasicBlock *Succ : Cur->successors())
233 if (!Succ->isEHPad() && Seen.insert(Succ).second)
234 Work.push_back({Succ, Succ->begin()});
235 }
236 }
237 }
238 for (MachineBasicBlock &MBB : MF)
239 for (MachineInstr &MI : MBB)
240 if (MI.isCall() && !Invokes.count(&MI) && leavesFrame(MI))
241 Resumes.push_back(&MI);
242 if (Labels.empty() && Resumes.empty())
243 return false;
244 // There is no unwind_goto after the calls of it.
245 if (!Resumes.empty() && !canUnwind(MF.getFunction())) {
246 const Function &F = MF.getFunction();
247 F.getContext().diagnose(DiagnosticInfoUnsupported(
248 F, "BPF cannot unwind out of a function that is nounwind or has no "
249 "uwtable"));
250 return false;
251 }
252 for (MachineInstr *MI : Labels)
253 MI->eraseFromParent();
254
255 for (auto [Call, Pad] : Sites) {
256 MachineBasicBlock *MBB = Call->getParent();
258 const auto *II =
260
261 Pads.insert(Pad);
262 if (leavesFrame(*Call)) {
263 endBlockAfter(*Call, Pad);
264 BuildMI(MBB, DL, TII.get(BPF::JMP)).addMBB(Pad);
265 eraseArg(*Call);
267 } else if (II && II->doesNotReturn()) {
268 // Nothing sensible follows the call, but something has to.
269 endBlockAfter(*Call, Pad);
270 BuildMI(MBB, DL, TII.get(BPF::UNWIND_GOTO)).addMBB(Pad);
271 BuildMI(MBB, DL, TII.get(BPF::JMP)).addMBB(Pad);
272 } else {
273 MachineBasicBlock *Rest = MBB->splitAt(*Call);
274 if (Rest != MBB) {
275 Rest->removeSuccessor(Pad);
276 MBB->addSuccessor(Pad);
277 }
278 BuildMI(MBB, DL, TII.get(BPF::UNWIND_GOTO)).addMBB(Pad);
279 }
280 }
281
282 for (MachineBasicBlock *Pad : Pads) {
283 LivePhysRegs Live(TRI);
284 Live.addLiveOuts(*Pad);
285 for (MachineInstr &MI : reverse(*Pad))
286 Live.stepBackward(MI);
287 if (!Live.available(MF.getRegInfo(), BPF::R0))
288 BuildMI(*Pad, Pad->begin(), DebugLoc(), TII.get(BPF::MOV_ri), BPF::R0)
289 .addImm(0);
290 Pad->removeLiveIn(BPF::R0);
291 }
292
293 // unwind_exit returns what exit returns: a value of more than 8 bytes is in
294 // r0 and r2.
296 const Function &F = MF.getFunction();
297 GetReturnInfo(F.getCallingConv(), F.getReturnType(), F.getAttributes(),
298 Outs, *MF.getSubtarget().getTargetLowering(),
299 MF.getDataLayout());
300
301 for (MachineInstr *Call : Resumes) {
302 MachineBasicBlock *MBB = Call->getParent();
304
305 eraseArg(*Call);
306 BuildMI(*MBB, Call, DL, TII.get(BPF::MOV_ri), BPF::R0).addImm(0);
307 MachineInstrBuilder Exit =
308 BuildMI(*MBB, Call, DL, TII.get(BPF::UNWIND_EXIT))
309 .addReg(BPF::R0, RegState::Implicit);
310 if (Outs.size() > 1) {
311 BuildMI(*MBB, *Exit, DL, TII.get(BPF::MOV_ri), BPF::R2).addImm(0);
312 Exit.addReg(BPF::R2, RegState::Implicit);
313 }
314 endBlockAfter(*Exit, nullptr);
315 }
316
317 // The pads are plain blocks now and there is no table to emit.
318 for (MachineBasicBlock &MBB : MF)
319 MBB.setIsEHPad(false);
320 MF.clearLandingPads();
321
322 // What was behind a call that does not return. It can be a loop.
323 df_iterator_default_set<MachineBasicBlock *> Reachable;
324 for (MachineBasicBlock *MBB : depth_first_ext(&MF, Reachable))
325 (void)MBB;
326 for (MachineBasicBlock &MBB : make_early_inc_range(MF)) {
327 if (Reachable.count(&MBB) || MBB.hasAddressTaken())
328 continue;
329 while (!MBB.succ_empty())
332 }
333 for (MachineBasicBlock &MBB : MF)
334 if (!MBB.empty() && MBB.back().getOpcode() == BPF::JMP &&
337 return true;
338 }
339};
340
341} // namespace
342
343char BPFUnwindPrepare::ID = 0;
344char BPFUnwindLower::ID = 0;
345
347 return new BPFUnwindPrepare();
348}
349FunctionPass *llvm::createBPFUnwindLowerPass() { return new BPFUnwindLower(); }
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static constexpr StringLiteral UnwindRaise
On other targets it is a function of the unwinder library, which is why nothing else in LLVM knows th...
Definition BPFUnwind.cpp:50
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:54
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
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
bool isInlineAsm() const
Check if this call is an inline asm statement.
void setDoesNotReturn()
void setDoesNotThrow()
Value * getCalledOperand() const
bool doesNotThrow() const
Determine if the call cannot unwind.
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
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
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition Globals.cpp:408
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.
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.
MachineInstrBundleIterator< MachineInstr > iterator
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.
const GlobalValue * getGlobal() const
MachineBasicBlock * getMBB() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:253
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
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)
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:888
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
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:315
const ParentTy * getParent() const
Definition ilist_node.h:34
CallInst * Call
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
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:2631
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.
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
FunctionPass * createBPFUnwindLowerPass()
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
IterT prev_nodbg(IterT It, IterT Begin, bool SkipPseudoOp=true)
Decrement It, then continue decrementing it while it points to a debug instruction.
ModulePass * createBPFUnwindPreparePass()