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"

90

91using namespace llvm;

92

93#define DEBUG_TYPE "wasm-eh-prepare"

94

95namespace {

96class WasmEHPrepareImpl {

97 friend class WasmEHPrepare;

98

99 Type *LPadContextTy = nullptr;

100 GlobalVariable *LPadContextGV = nullptr;

101

102

103 Value *LPadIndexField = nullptr;

104 Value *LSDAField = nullptr;

105 Value *SelectorField = nullptr;

106

107 Function *ThrowF = nullptr;

108 Function *LPadIndexF = nullptr;

109 Function *LSDAF = nullptr;

110 Function *GetExnF = nullptr;

111 Function *CatchF = nullptr;

112 Function *GetSelectorF = nullptr;

114 nullptr;

115

118 void prepareEHPad(BasicBlock *BB, bool NeedPersonality, unsigned Index = 0);

119

120public:

121 WasmEHPrepareImpl() = default;

122 WasmEHPrepareImpl(Type *LPadContextTy_) : LPadContextTy(LPadContextTy_) {}

124};

125

127 WasmEHPrepareImpl P;

128

129public:

130 static char ID;

131

135

137 return "WebAssembly Exception handling preparation";

138 }

139};

140

141}

142

145 auto &Context = F.getContext();

148 auto *LPadContextTy =

149 StructType::get(I32Ty , PtrTy , I32Ty );

150 WasmEHPrepareImpl P(LPadContextTy);

151 bool Changed = P.runOnFunction(F);

153}

154

155char WasmEHPrepare::ID = 0;

157 "Prepare WebAssembly exceptions", false, false)

160

162

163bool WasmEHPrepare::doInitialization(Module &M) {

165 P.LPadContextTy = StructType::get(IRB.getInt32Ty(),

166 IRB.getPtrTy(),

167 IRB.getInt32Ty()

168 );

169 return false;

170}

171

172

173

174template

177 while (!WL.empty()) {

180 continue;

183 }

184}

185

186bool WasmEHPrepareImpl::runOnFunction(Function &F) {

187 bool Changed = false;

188 Changed |= prepareThrows(F);

189 Changed |= prepareEHPads(F);

190 return Changed;

191}

192

193bool WasmEHPrepareImpl::prepareThrows(Function &F) {

196 bool Changed = false;

197

198

200

201

202

203 for (User *U : ThrowF->users()) {

204

205

206 auto *ThrowI = cast(U);

207 if (ThrowI->getFunction() != &F)

208 continue;

209 Changed = true;

210 auto *BB = ThrowI->getParent();

213 IRB.SetInsertPoint(BB);

214 IRB.CreateUnreachable();

216 }

217

218 return Changed;

219}

220

221bool WasmEHPrepareImpl::prepareEHPads(Function &F) {

224

228 if (!BB.isEHPad())

229 continue;

230 auto *Pad = BB.getFirstNonPHI();

231 if (isa(Pad))

233 else if (isa(Pad))

235 }

236 if (CatchPads.empty() && CleanupPads.empty())

237 return false;

238

239 if (F.hasPersonalityFn() ||

242 "' does not have a correct Wasm personality function "

243 "'__gxx_wasm_personality_v0'");

244 }

245 assert(F.hasPersonalityFn() && "Personality function not found");

246

247

248

249

250

251

252 LPadContextGV = cast(

253 M.getOrInsertGlobal("__wasm_lpad_context", LPadContextTy));

255

256 LPadIndexField = LPadContextGV;

257 LSDAField = IRB.CreateConstInBoundsGEP2_32(LPadContextTy, LPadContextGV, 0, 1,

258 "lsda_gep");

259 SelectorField = IRB.CreateConstInBoundsGEP2_32(LPadContextTy, LPadContextGV,

260 0, 2, "selector_gep");

261

262

263 LPadIndexF =

265

266

268

269

270 GetExnF =

272 GetSelectorF =

274

275

276

278

279

280 CallPersonalityF = M.getOrInsertFunction("_Unwind_CallPersonality",

281 IRB.getInt32Ty(), IRB.getPtrTy());

282 if (Function *F = dyn_cast(CallPersonalityF.getCallee()))

283 F->setDoesNotThrow();

284

285 unsigned Index = 0;

286 for (auto *BB : CatchPads) {

287 auto *CPI = cast(BB->getFirstNonPHI());

288

289

290 if (CPI->arg_size() == 1 &&

291 cast(CPI->getArgOperand(0))->isNullValue())

292 prepareEHPad(BB, false);

293 else

294 prepareEHPad(BB, true, Index++);

295 }

296

297

298 for (auto *BB : CleanupPads)

299 prepareEHPad(BB, false);

300

301 return true;

302}

303

304

305

306void WasmEHPrepareImpl::prepareEHPad(BasicBlock *BB, bool NeedPersonality,

307 unsigned Index) {

311

312 auto *FPI = cast(BB->getFirstNonPHI());

313 Instruction *GetExnCI = nullptr, *GetSelectorCI = nullptr;

314 for (auto &U : FPI->uses()) {

315 if (auto *CI = dyn_cast(U.getUser())) {

316 if (CI->getCalledOperand() == GetExnF)

317 GetExnCI = CI;

318 if (CI->getCalledOperand() == GetSelectorF)

319 GetSelectorCI = CI;

320 }

321 }

322

323

324

325 if (!GetExnCI) {

326 assert(!GetSelectorCI &&

327 "wasm.get.ehselector() cannot exist w/o wasm.get.exception()");

328 return;

329 }

330

331

332

333

334

339

340

341

342 if (!NeedPersonality) {

343 if (GetSelectorCI) {

344 assert(GetSelectorCI->use_empty() &&

345 "wasm.get.ehselector() still has uses!");

346 GetSelectorCI->eraseFromParent();

347 }

348 return;

349 }

350 IRB.SetInsertPoint(CatchCI->getNextNode());

351

352

353

354

355 IRB.CreateCall(LPadIndexF, {FPI, IRB.getInt32(Index)});

356

357

358 IRB.CreateStore(IRB.getInt32(Index), LPadIndexField);

359

360 auto *CPI = cast(FPI);

361

362

363

364

365 IRB.CreateStore(IRB.CreateCall(LSDAF), LSDAField);

366

367

368 CallInst *PersCI = IRB.CreateCall(CallPersonalityF, CatchCI,

371

372

374 IRB.CreateLoad(IRB.getInt32Ty(), SelectorField, "selector");

375

376

377

378 assert(GetSelectorCI && "wasm.get.ehselector() call does not exist");

379 GetSelectorCI->replaceAllUsesWith(Selector);

380 GetSelectorCI->eraseFromParent();

381}

382

384

385

386

387

388 for (const auto &BB : *F) {

390 continue;

392

393 if (const auto *CatchPad = dyn_cast(Pad)) {

394 const auto *UnwindBB = CatchPad->getCatchSwitch()->getUnwindDest();

395 if (!UnwindBB)

396 continue;

397 const Instruction *UnwindPad = UnwindBB->getFirstNonPHI();

398 if (const auto *CatchSwitch = dyn_cast(UnwindPad))

399

401 else

403 }

404 }

405}

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)

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

static void eraseDeadBBsAndChildren(const Container &BBs)

A container for analyses that lazily runs them and caches their results.

LLVM Basic Block Representation.

iterator begin()

Instruction iterator methods.

const_iterator getFirstInsertionPt() const

Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...

const Instruction * getFirstNonPHI() const

Returns a pointer to the first instruction in this block that is not a PHINode instruction.

InstListType::iterator iterator

Instruction iterators...

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.

virtual bool runOnFunction(Function &F)=0

runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

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.

virtual bool doInitialization(Module &)

doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...

virtual StringRef getPassName() const

getPassName - Return a nice clean name for a pass.

static 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 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 IntegerType * getInt32Ty(LLVMContext &C)

LLVM Value Representation.

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)

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.

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.

auto successors(const MachineBasicBlock *BB)

FunctionPass * createWasmEHPass()

createWasmEHPass - This pass adapts exception handling code to use WebAssembly's exception handling s...

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,...

OperandBundleDefT< Value * > OperandBundleDef

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

EHPersonality classifyEHPersonality(const Value *Pers)

See if the given exception handling personality function is one that we understand.

RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)

RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)

void calculateWasmEHInfo(const Function *F, WasmEHFuncInfo &EHInfo)

bool pred_empty(const BasicBlock *BB)

void setUnwindDest(const BasicBlock *BB, const BasicBlock *Dest)