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 (F.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)