42#include "llvm/IR/IntrinsicsBPF.h"
51 return F.hasUWTable() && !
F.doesNotThrow();
60 BPFUnwindPrepare() : ModulePass(ID) {}
61 StringRef getPassName()
const override {
return "BPF Unwind Prepare"; }
72 static bool mayUnwind(
const Instruction &
I) {
74 return CB && !CB->doesNotThrow() && !CB->isInlineAsm() &&
78 bool runOnModule(
Module &M)
override {
80 LLVMContext &
C =
M.getContext();
84 if (
F.isDeclaration())
88 for (BasicBlock &BB :
F) {
108 if (!
F.hasPersonalityFn())
110 M.getOrInsertFunction(
"__gcc_personality_v0",
111 FunctionType::get(Type::getInt32Ty(
C),
true))
115 LandingPadInst *LP =
B.CreateLandingPad(
118 B.CreateCall(getUnwindExit(M));
119 B.CreateUnreachable();
120 for (CallInst *CI : Calls)
131 BPFUnwindLower() : MachineFunctionPass(ID) {}
132 StringRef getPassName()
const override {
return "BPF Unwind Lower"; }
135 static void endBlockAfter(MachineInstr &
MI, MachineBasicBlock *Succ) {
149 return "BPF needs uwtable on a function with a landing pad";
152 for (
int TId : LP.TypeIds) {
154 return "BPF does not support type-specific exception catches yet";
158 return "BPF does not support exception filters yet";
167 DenseMap<MCSymbol *, MachineBasicBlock *> Begin;
169 SmallVector<MachineInstr *, 8> Labels, Resumes;
170 SmallSetVector<MachineBasicBlock *, 8> Pads;
179 for (MCSymbol *Sym : LP.BeginLabels)
180 Begin[Sym] = LP.LandingPadBlock;
184 SmallPtrSet<MachineInstr *, 8> Invokes;
185 for (MachineBasicBlock &
MBB : MF) {
186 for (MachineInstr &Label :
MBB) {
187 if (!
Label.isEHLabel())
190 MachineBasicBlock *Pad =
196 Work{{&
MBB, std::next(
Label.getIterator())}};
197 SmallPtrSet<MachineBasicBlock *, 4> Seen;
198 while (!Work.
empty()) {
201 for (;
I != Cur->end() && !
I->isEHLabel(); ++
I)
202 if (
I->isCall() && Invokes.
insert(&*
I).second)
206 for (MachineBasicBlock *Succ : Cur->successors())
212 for (MachineBasicBlock &
MBB : MF)
213 for (MachineInstr &
MI :
MBB)
214 if (
MI.getOpcode() == BPF::UNWIND_EXIT_PSEUDO && !Invokes.
count(&
MI))
221 F.getContext().diagnose(DiagnosticInfoUnsupported(
222 F,
"BPF cannot unwind out of a function that is nounwind or has no "
225 for (MachineInstr *
MI : Labels)
226 MI->eraseFromParent();
228 for (
auto [
Call, Pad] : Sites) {
236 endBlockAfter(*
Call, Pad);
239 }
else if (
II &&
II->doesNotReturn()) {
241 endBlockAfter(*
Call, Pad);
254 for (MachineBasicBlock *Pad : Pads) {
255 LivePhysRegs Live(
TRI);
256 Live.addLiveOuts(*Pad);
258 Live.stepBackward(
MI);
259 if (!Live.available(MF.getRegInfo(), BPF::R0))
270 Outs, *MF.getSubtarget().getTargetLowering(),
273 for (MachineInstr *
Call : Resumes) {
278 MachineInstrBuilder
Exit =
280 .
addReg(BPF::R0, RegState::Implicit);
281 if (Outs.
size() > 1) {
283 Exit.addReg(BPF::R2, RegState::Implicit);
285 endBlockAfter(*Exit,
nullptr);
289 for (MachineBasicBlock &
MBB : MF)
291 MF.clearLandingPads();
294 df_iterator_default_set<MachineBasicBlock *> Reachable;
304 for (MachineBasicBlock &
MBB : MF)
314char BPFUnwindPrepare::ID = 0;
315char BPFUnwindLower::ID = 0;
323 return new BPFUnwindPrepare();
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 ...
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
Module.h This file contains the declarations for the Module class.
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
Register const TargetRegisterInfo * TRI
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
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.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
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.
FunctionPass class - This class is used to implement most global optimizations.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool hasUWTable() const
True if the ABI mandates (or the user requested) that this function be in a unwind table.
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.
succ_iterator succ_begin()
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...
bool insert(const value_type &X)
Insert a new element into the SetVector.
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.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
const ParentTy * getParent() const
@ BasicBlock
Various leaf nodes.
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.
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.
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...
auto dyn_cast_or_null(const Y &Val)
auto reverse(ContainerTy &&C)
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...
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...
FunctionPass * createBPFUnwindLowerPass()
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.