76#include "llvm/IR/IntrinsicsWebAssembly.h"
84#define DEBUG_TYPE "wasm-eh-prepare"
87class WasmEHPrepareImpl {
88 friend class WasmEHPrepare;
90 Type *LPadContextTy =
nullptr;
105 void prepareEHPad(
BasicBlock *BB,
bool NeedPersonality,
unsigned Index = 0);
108 WasmEHPrepareImpl() =
default;
109 WasmEHPrepareImpl(
Type *LPadContextTy_,
111 : LPadContextTy(LPadContextTy_), RTLCI(&RTLCI_) {}
122 bool doInitialization(
Module &M)
override;
125 &getAnalysis<RuntimeLibraryInfoWrapper>().getRTLCI(*
F.getParent());
126 return P.runOnFunction(
F);
134 return "WebAssembly Exception handling preparation";
142 auto &Context =
F.getContext();
148 "' analysis required");
154 auto *LPadContextTy =
156 WasmEHPrepareImpl
P(LPadContextTy, *RTLCI);
161char WasmEHPrepare::ID = 0;
163 "Prepare WebAssembly exceptions",
false,
false)
170bool WasmEHPrepare::doInitialization(
Module &M) {
181template <
typename Container>
184 while (!WL.
empty()) {
193bool WasmEHPrepareImpl::runOnFunction(
Function &
F) {
203bool WasmEHPrepareImpl::prepareThrows(
Function &
F) {
215 if (!ThrowI || ThrowI->getFunction() != &
F)
218 auto *BB = ThrowI->getParent();
221 IRB.SetInsertPoint(BB);
222 IRB.CreateUnreachable();
229bool WasmEHPrepareImpl::prepareEHPads(
Function &
F) {
247 if (!
F.hasPersonalityFn())
254 "' does not have a supported Wasm personality function");
256 assert(
F.hasPersonalityFn() &&
"Personality function not found");
258 RTLIB::LibcallImpl GetWasmLPadContextImpl =
259 RTLIB::impl__Unwind_GetWasmLPadContext;
260 if (!RTLCI->isAvailable(GetWasmLPadContextImpl)) {
261 Ctx.
emitError(
"no libcall available for wasm landing pad context");
288 F->setDoesNotThrow();
290 auto [UnwindGetWasmLPadContextType, UnwindGetWasmLPadContextAttrs] =
291 RTLCI->getFunctionTy(Ctx,
M.getTargetTriple(),
M.getDataLayout(),
292 GetWasmLPadContextImpl);
293 assert(UnwindGetWasmLPadContextType &&
294 "missing signature for _Unwind_GetWasmLPadContext");
305 GetWasmLPadContextImpl),
306 UnwindGetWasmLPadContextType,
307 UnwindGetWasmLPadContextAttrs)
309 GetWasmLPadContextF->setCallingConv(
310 RTLCI->getLibcallImplCallingConv(GetWasmLPadContextImpl));
313 for (
auto *BB : CatchPads) {
317 if (CPI->arg_size() == 1 &&
319 prepareEHPad(BB,
false);
321 prepareEHPad(BB,
true, Index++);
325 for (
auto *BB : CleanupPads)
326 prepareEHPad(BB,
false);
333void WasmEHPrepareImpl::prepareEHPad(
BasicBlock *BB,
bool NeedPersonality,
339 Instruction *GetExnCI =
nullptr, *GetSelectorCI =
nullptr;
340 for (
auto &U : FPI->uses()) {
342 if (CI->getCalledOperand() == GetExnF)
344 if (CI->getCalledOperand() == GetSelectorF)
353 "wasm.get.ehselector() cannot exist w/o wasm.get.exception()");
368 if (!NeedPersonality) {
370 assert(GetSelectorCI->use_empty() &&
371 "wasm.get.ehselector() still has uses!");
372 GetSelectorCI->eraseFromParent();
381 LPadContext->
setCallingConv(GetWasmLPadContextF->getCallingConv());
383 Value *LPadIndexField = LPadContext;
384 Value *LSDAField = IRB.CreateConstInBoundsGEP2_32(LPadContextTy, LPadContext,
386 Value *SelectorField = IRB.CreateConstInBoundsGEP2_32(
387 LPadContextTy, LPadContext, 0, 2,
"selector_gep");
392 IRB.CreateCall(LPadIndexF, {FPI, IRB.getInt32(Index)});
395 IRB.CreateStore(IRB.getInt32(Index), LPadIndexField);
401 IRB.CreateStore(IRB.CreateCall(LSDAF), LSDAField);
410 IRB.CreateLoad(IRB.getInt32Ty(), SelectorField,
"selector");
414 assert(GetSelectorCI &&
"wasm.get.ehselector() call does not exist");
415 GetSelectorCI->replaceAllUsesWith(Selector);
416 GetSelectorCI->eraseFromParent();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static void eraseDeadBBsAndChildren(const Container &BBs)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM Basic Block Representation.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
InstListType::iterator iterator
Instruction iterators...
bool isEHPad() const
Return true if this basic block is an exception handling block.
void setCallingConv(CallingConv::ID CC)
This class represents a function call, abstracting a target machine's calling convention.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionPass class - This class is used to implement most global optimizations.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
A Module instance is used to store all the information related to an LLVM module.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
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.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
LLVM Value Representation.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
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.
LLVM_ABI StringRef getEHPersonalityName(EHPersonality Pers)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
LLVM_ABI FunctionPass * createWasmEHPass()
createWasmEHPass - This pass adapts exception handling code to use WebAssembly's exception handling s...
LLVM_ABI void DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU=nullptr, bool KeepOneInputPHIs=false)
Delete the specified block, which must have no predecessors.
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch,...
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
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...
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)
OperandBundleDefT< Value * > OperandBundleDef
@ Wasm
WebAssembly Exception Handling.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool pred_empty(const BasicBlock *BB)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
A simple container for information about the supported runtime calls.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.