LLVM: lib/CodeGen/WasmEHPrepare.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
86#include "llvm/IR/IntrinsicsWebAssembly.h"
91
92using namespace llvm;
93
94#define DEBUG_TYPE "wasm-eh-prepare"
95
96namespace {
97class WasmEHPrepareImpl {
98 friend class WasmEHPrepare;
99
100 Type *LPadContextTy = nullptr;
101 GlobalVariable *LPadContextGV = nullptr;
102
103
104 Value *LPadIndexField = nullptr;
105 Value *LSDAField = nullptr;
106 Value *SelectorField = nullptr;
107
108 Function *ThrowF = nullptr;
109 Function *LPadIndexF = nullptr;
110 Function *LSDAF = nullptr;
111 Function *GetExnF = nullptr;
112 Function *CatchF = nullptr;
113 Function *GetSelectorF = nullptr;
115 nullptr;
116
119 void prepareEHPad(BasicBlock *BB, bool NeedPersonality, unsigned Index = 0);
120
121public:
122 WasmEHPrepareImpl() = default;
123 WasmEHPrepareImpl(Type *LPadContextTy_) : LPadContextTy(LPadContextTy_) {}
125};
126
128 WasmEHPrepareImpl P;
129
130public:
131 static char ID;
132
134 bool doInitialization(Module &M) override;
136
137 StringRef getPassName() const override {
138 return "WebAssembly Exception handling preparation";
139 }
140};
141
142}
143
146 auto &Context = F.getContext();
149 auto *LPadContextTy =
150 StructType::get(I32Ty , PtrTy , I32Ty );
151 WasmEHPrepareImpl P(LPadContextTy);
152 bool Changed = P.runOnFunction(F);
154}
155
156char WasmEHPrepare::ID = 0;
158 "Prepare WebAssembly exceptions", false, false)
161
163
164bool WasmEHPrepare::doInitialization(Module &M) {
166 P.LPadContextTy = StructType::get(IRB.getInt32Ty(),
167 IRB.getPtrTy(),
168 IRB.getInt32Ty()
169 );
170 return false;
171}
172
173
174
175template
178 while (!WL.empty()) {
181 continue;
184 }
185}
186
187bool WasmEHPrepareImpl::runOnFunction(Function &F) {
192}
193
194bool WasmEHPrepareImpl::prepareThrows(Function &F) {
198
199
201
202
203
204 for (User *U : ThrowF->users()) {
206 if (!ThrowI || ThrowI->getFunction() != &F)
207 continue;
209 auto *BB = ThrowI->getParent();
212 IRB.SetInsertPoint(BB);
213 IRB.CreateUnreachable();
215 }
216
218}
219
220bool WasmEHPrepareImpl::prepareEHPads(Function &F) {
223
227 if (!BB.isEHPad())
228 continue;
234 }
235 if (CatchPads.empty() && CleanupPads.empty())
236 return false;
237
238 if (.hasPersonalityFn() ||
241 "' does not have a correct Wasm personality function "
242 "'__gxx_wasm_personality_v0'");
243 }
244 assert(F.hasPersonalityFn() && "Personality function not found");
245
246
247
248
249
250
251 LPadContextGV = M.getOrInsertGlobal("__wasm_lpad_context", LPadContextTy);
253
254 LPadIndexField = LPadContextGV;
255 LSDAField = IRB.CreateConstInBoundsGEP2_32(LPadContextTy, LPadContextGV, 0, 1,
256 "lsda_gep");
257 SelectorField = IRB.CreateConstInBoundsGEP2_32(LPadContextTy, LPadContextGV,
258 0, 2, "selector_gep");
259
260
261 LPadIndexF =
263
264
266
267
268 GetExnF =
270 GetSelectorF =
272
273
274
276
277
278 StringRef UnwindCallPersonalityName =
280 RTLIB::impl__Unwind_CallPersonality);
281
282
283 CallPersonalityF = M.getOrInsertFunction(UnwindCallPersonalityName,
284 IRB.getInt32Ty(), IRB.getPtrTy());
286 F->setDoesNotThrow();
287
288 unsigned Index = 0;
289 for (auto *BB : CatchPads) {
291
292
293 if (CPI->arg_size() == 1 &&
294 cast(CPI->getArgOperand(0))->isNullValue())
295 prepareEHPad(BB, false);
296 else
297 prepareEHPad(BB, true, Index++);
298 }
299
300
301 for (auto *BB : CleanupPads)
302 prepareEHPad(BB, false);
303
304 return true;
305}
306
307
308
309void WasmEHPrepareImpl::prepareEHPad(BasicBlock *BB, bool NeedPersonality,
310 unsigned Index) {
314
316 Instruction *GetExnCI = nullptr, *GetSelectorCI = nullptr;
317 for (auto &U : FPI->uses()) {
319 if (CI->getCalledOperand() == GetExnF)
320 GetExnCI = CI;
321 if (CI->getCalledOperand() == GetSelectorF)
322 GetSelectorCI = CI;
323 }
324 }
325
326
327
328 if (!GetExnCI) {
329 assert(!GetSelectorCI &&
330 "wasm.get.ehselector() cannot exist w/o wasm.get.exception()");
331 return;
332 }
333
334
335
336
337
342
343
344
345 if (!NeedPersonality) {
346 if (GetSelectorCI) {
347 assert(GetSelectorCI->use_empty() &&
348 "wasm.get.ehselector() still has uses!");
349 GetSelectorCI->eraseFromParent();
350 }
351 return;
352 }
353 IRB.SetInsertPoint(CatchCI->getNextNode());
354
355
356
357
358 IRB.CreateCall(LPadIndexF, {FPI, IRB.getInt32(Index)});
359
360
361 IRB.CreateStore(IRB.getInt32(Index), LPadIndexField);
362
364
365
366
367
368 IRB.CreateStore(IRB.CreateCall(LSDAF), LSDAField);
369
370
371 CallInst *PersCI = IRB.CreateCall(CallPersonalityF, CatchCI,
374
375
377 IRB.CreateLoad(IRB.getInt32Ty(), SelectorField, "selector");
378
379
380
381 assert(GetSelectorCI && "wasm.get.ehselector() call does not exist");
382 GetSelectorCI->replaceAllUsesWith(Selector);
383 GetSelectorCI->eraseFromParent();
384}
385
387
388
389
390
391 for (const auto &BB : *F) {
393 continue;
395
397 const auto *UnwindBB = CatchPad->getCatchSwitch()->getUnwindDest();
398 if (!UnwindBB)
399 continue;
400 const Instruction *UnwindPad = &*UnwindBB->getFirstNonPHIIt();
402
404 else
406 }
407 }
408}
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.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static void eraseDeadBBsAndChildren(const Container &BBs)
Definition WasmEHPrepare.cpp:176
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
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...
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
bool isEHPad() const
Return true if this basic block is an exception handling block.
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.
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.
A Module instance is used to store all the information related to an LLVM module.
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type 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.
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.
StringRef - 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()
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Definition WasmEHPrepare.cpp:144
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
LLVM_ABI FunctionPass * createWasmEHPass()
createWasmEHPass - This pass adapts exception handling code to use WebAssembly's exception handling s...
Definition WasmEHPrepare.cpp:162
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 - 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
void calculateWasmEHInfo(const Function *F, WasmEHFuncInfo &EHInfo)
Definition WasmEHPrepare.cpp:386
decltype(auto) cast(const From &Val)
cast - 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.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.
void setUnwindDest(const BasicBlock *BB, const BasicBlock *Dest)