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 static const char *unsupported(const MachineFunction &MF) {
158 if (MF.getLandingPads().empty())
159 return nullptr;
160 // Not canUnwind(): a function that catches everything is nounwind.
161 if (!MF.getFunction().hasUWTable())
162 return "BPF needs uwtable on a function with a landing pad";
163 // Every pad is a catch-all: the branch is taken whatever was thrown.
164 for (const LandingPadInfo &LP : MF.getLandingPads()) {
165 for (int TId : LP.TypeIds) {
166 if (TId > 0 && MF.getTypeInfos()[TId - 1])
167 return "BPF does not support type-specific exception catches yet";
168 // An empty filter lets nothing through, so it is a catch-all too. rustc
169 // guards every function that must not unwind with one.
170 if (TId < 0 && MF.getFilterIds()[-1 - TId])
171 return "BPF does not support exception filters yet";
172 }
173 }
174 return nullptr;
175 }
176
177 bool runOnMachineFunction(MachineFunction &MF) override {
178 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
179 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
180 UnwindResume = MF.getSubtarget().getTargetLowering()->getLibcallName(
181 RTLIB::UNWIND_RESUME);
182 DenseMap<MCSymbol *, MachineBasicBlock *> Begin;
184 SmallVector<MachineInstr *, 8> Labels, Resumes;
185 SmallSetVector<MachineBasicBlock *, 8> Pads;
186
187 if (const char *Msg = unsupported(MF)) {
188 const Function &F = MF.getFunction();
189 F.getContext().diagnose(DiagnosticInfoUnsupported(F, Msg));
190 return false;
191 }
192
193 for (const LandingPadInfo &LP : MF.getLandingPads())
194 for (MCSymbol *Sym : LP.BeginLabels)
195 Begin[Sym] = LP.LandingPadBlock;
196
197 for (MachineBasicBlock &MBB : MF) {
198 MachineBasicBlock *Pad = nullptr;
199 for (MachineInstr &MI : MBB) {
200 if (MI.isEHLabel()) {
201 Pad = Begin.lookup(MI.getOperand(0).getMCSymbol());
202 Labels.push_back(&MI);
203 } else if (MI.isCall() && Pad) {
204 Sites.push_back({&MI, Pad});
205 } else if (MI.isCall() && leavesFrame(MI)) {
206 Resumes.push_back(&MI);
207 }
208 }
209 }
210 if (Labels.empty() && Resumes.empty())
211 return false;
212 // There is no unwind_goto after the calls of it.
213 if (!Resumes.empty() && !canUnwind(MF.getFunction())) {
214 const Function &F = MF.getFunction();
215 F.getContext().diagnose(DiagnosticInfoUnsupported(
216 F, "BPF cannot unwind out of a function that is nounwind or has no "
217 "uwtable"));
218 return false;
219 }
220 for (MachineInstr *MI : Labels)
222
223 for (auto [Call, Pad] : Sites) {
224 MachineBasicBlock *MBB = Call->getParent();
226 const auto *II =
228
229 Pads.insert(Pad);
230 if (leavesFrame(*Call)) {
231 endBlockAfter(*Call, Pad);
232 BuildMI(MBB, DL, TII.get(BPF::JMP)).addMBB(Pad);
234 } else if (II && II->doesNotReturn()) {
235 // Nothing sensible follows the call, but something has to.
236 endBlockAfter(*Call, Pad);
237 BuildMI(MBB, DL, TII.get(BPF::UNWIND_GOTO)).addMBB(Pad);
238 BuildMI(MBB, DL, TII.get(BPF::JMP)).addMBB(Pad);
239 } else {
240 MachineBasicBlock *Rest = MBB->splitAt(*Call);
241 if (Rest != MBB) {
242 Rest->removeSuccessor(Pad);
243 MBB->addSuccessor(Pad);
244 }
245 BuildMI(MBB, DL, TII.get(BPF::UNWIND_GOTO)).addMBB(Pad);
246 }
247 }
248
249 for (MachineBasicBlock *Pad : Pads) {
250 LivePhysRegs Live(TRI);
251 Live.addLiveOuts(*Pad);
252 for (MachineInstr &MI : reverse(*Pad))
253 Live.stepBackward(MI);
254 if (!Live.available(MF.getRegInfo(), BPF::R0))
255 BuildMI(*Pad, Pad->begin(), DebugLoc(), TII.get(BPF::MOV_ri), BPF::R0)
256 .addImm(0);
257 Pad->removeLiveIn(BPF::R0);
258 }
259
260 // unwind_exit returns what exit returns: a value of more than 8 bytes is in
261 // r0 and r2.
263 const Function &F = MF.getFunction();
264 GetReturnInfo(F.getCallingConv(), F.getReturnType(), F.getAttributes(),
265 Outs, *MF.getSubtarget().getTargetLowering(),
266 MF.getDataLayout());
267
268 for (MachineInstr *Call : Resumes) {
269 MachineBasicBlock *MBB = Call->getParent();
271
272 BuildMI(*MBB, Call, DL, TII.get(BPF::MOV_ri), BPF::R0).addImm(0);
273 MachineInstrBuilder Exit =
274 BuildMI(*MBB, Call, DL, TII.get(BPF::UNWIND_EXIT))
275 .addReg(BPF::R0, RegState::Implicit);
276 if (Outs.size() > 1) {
277 BuildMI(*MBB, *Exit, DL, TII.get(BPF::MOV_ri), BPF::R2).addImm(0);
278 Exit.addReg(BPF::R2, RegState::Implicit);
279 }
280 endBlockAfter(*Exit, nullptr);
281 }
282
283 // The pads are plain blocks now and there is no table to emit.
284 for (MachineBasicBlock &MBB : MF)
285 MBB.setIsEHPad(false);
286 MF.clearLandingPads();
287
288 // What was behind a call that does not return. It can be a loop.
289 df_iterator_default_set<MachineBasicBlock *> Reachable;
290 for (MachineBasicBlock *MBB : depth_first_ext(&MF, Reachable))
291 (void)MBB;
292 for (MachineBasicBlock &MBB : make_early_inc_range(MF)) {
293 if (Reachable.count(&MBB) || MBB.hasAddressTaken())
294 continue;
295 while (!MBB.succ_empty())
298 }
299 for (MachineBasicBlock &MBB : MF)
300 if (!MBB.empty() && MBB.back().getOpcode() == BPF::JMP &&
303 return true;
304 }
305};
306
307} // namespace
308
309char BPFUnwindPrepare::ID = 0;
310char BPFUnwindLower::ID = 0;
311
313 return new BPFUnwindPrepare();
314}
315FunctionPass *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.
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.
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.
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
Changed
@ 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:2629
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
ModulePass * createBPFUnwindPreparePass()