LLVM: lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

25using namespace llvm;

26

27#define DEBUG_TYPE "wasm-late-eh-prepare"

28

29namespace {

31 StringRef getPassName() const override {

32 return "WebAssembly Late Prepare Exception";

33 }

34

44

47

48public:

49 static char ID;

51};

52}

53

54char WebAssemblyLateEHPrepare::ID = 0;

56 "WebAssembly Late Exception Preparation", false, false)

57

59 return new WebAssemblyLateEHPrepare();

60}

61

62

63

64

65

66

67

69WebAssemblyLateEHPrepare::getMatchingEHPad(MachineInstr *MI) {

70 MachineFunction *MF = MI->getParent()->getParent();

72 SmallPtrSet<MachineBasicBlock *, 2> Visited;

74 MachineBasicBlock *EHPad = nullptr;

75 while (!WL.empty()) {

78 continue;

80 if (EHPad && EHPad != MBB)

81 return nullptr;

82 EHPad = MBB;

83 continue;

84 }

86 return nullptr;

88 if (!CatchRetBBs.count(Pred))

90 }

91 return EHPad;

92}

93

94

95

96template

100 while (!WL.empty()) {

103 continue;

105 WL.append(MBB->succ_begin(), MBB->succ_end());

106 for (auto *Succ : Succs)

107 MBB->removeSuccessor(Succ);

108

109

111 MBB->eraseFromParent();

112 }

113}

114

115bool WebAssemblyLateEHPrepare::runOnMachineFunction(MachineFunction &MF) {

116 LLVM_DEBUG(dbgs() << "********** Late EH Prepare **********\n"

117 "********** Function: "

118 << MF.getName() << '\n');

119

121 ExceptionHandling::Wasm)

122 return false;

123

126 Changed |= removeUnreachableEHPads(MF);

127 recordCatchRetBBs(MF);

128 Changed |= hoistCatches(MF);

129 Changed |= addCatchAlls(MF);

130 Changed |= replaceFuncletReturns(MF);

132 Changed |= addCatchRefsAndThrowRefs(MF);

133 }

134 Changed |= removeUnnecessaryUnreachables(MF);

136 Changed |= restoreStackPointer(MF);

138}

139

140

141

142bool WebAssemblyLateEHPrepare::removeUnreachableEHPads(MachineFunction &MF) {

143 SmallVector<MachineBasicBlock *, 4> ToDelete;

144 for (auto &MBB : MF)

148 return !ToDelete.empty();

149}

150

151

152

153

154void WebAssemblyLateEHPrepare::recordCatchRetBBs(MachineFunction &MF) {

155 CatchRetBBs.clear();

156 for (auto &MBB : MF) {

158 if (Pos == MBB.end())

159 continue;

160 MachineInstr *TI = &*Pos;

161 if (TI->getOpcode() == WebAssembly::CATCHRET)

162 CatchRetBBs.insert(&MBB);

163 }

164}

165

166

167

168

169

170

171

172

173

174

175

176

177

178bool WebAssemblyLateEHPrepare::hoistCatches(MachineFunction &MF) {

181 for (auto &MBB : MF)

182 for (auto &MI : MBB)

185

186 for (auto *Catch : Catches) {

187 MachineBasicBlock *EHPad = getMatchingEHPad(Catch);

188 assert(EHPad && "No matching EH pad for catch");

189 auto InsertPos = EHPad->begin();

190

191

192

193 while (InsertPos != EHPad->end() && InsertPos->isEHLabel())

194 InsertPos++;

195 if (InsertPos == Catch)

196 continue;

198 EHPad->insert(InsertPos, Catch->removeFromParent());

199 }

201}

202

203

204bool WebAssemblyLateEHPrepare::addCatchAlls(MachineFunction &MF) {

206 const auto &TII = *MF.getSubtarget().getInstrInfo();

207

208 for (auto &MBB : MF) {

210 continue;

211 auto InsertPos = MBB.begin();

212

213 while (InsertPos != MBB.end() && InsertPos->isEHLabel())

214 InsertPos++;

215

216

217 if (InsertPos == MBB.end() ||

221 ? WebAssembly::CATCH_ALL_LEGACY

222 : WebAssembly::CATCH_ALL;

224 InsertPos == MBB.end() ? DebugLoc() : InsertPos->getDebugLoc(),

225 TII.get(CatchAllOpcode));

226 }

227 }

229}

230

231

232

233bool WebAssemblyLateEHPrepare::replaceFuncletReturns(MachineFunction &MF) {

235 const auto &TII = *MF.getSubtarget().getInstrInfo();

236

237 for (auto &MBB : MF) {

239 if (Pos == MBB.end())

240 continue;

241 MachineInstr *TI = &*Pos;

242

244 case WebAssembly::CATCHRET: {

245

252 break;

253 }

254 case WebAssembly::RETHROW:

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

276 break;

277 case WebAssembly::CLEANUPRET: {

278

279

280

281

282

283

284

289 break;

290 }

291 }

292 }

294}

295

296

297

298bool WebAssemblyLateEHPrepare::addCatchRefsAndThrowRefs(MachineFunction &MF) {

299 const auto &TII = *MF.getSubtarget().getInstrInfo();

301 DenseMap<MachineBasicBlock *, SmallVector<MachineInstr *, 2>> EHPadToRethrows;

302

303

304 for (auto &MBB : MF)

305 for (auto &MI : MBB)

306 if (MI.getOpcode() == WebAssembly::RETHROW)

307 EHPadToRethrows[MI.getOperand(0).getMBB()].push_back(&MI);

308 if (EHPadToRethrows.empty())

309 return false;

310

311

312

313 for (auto &[EHPad, Rethrows] : EHPadToRethrows) {

315 auto *InsertPos = Catch->getIterator()->getNextNode();

316 auto ExnReg = MRI.createVirtualRegister(&WebAssembly::EXNREFRegClass);

317 if (Catch->getOpcode() == WebAssembly::CATCH) {

318 MachineInstrBuilder MIB = BuildMI(*EHPad, InsertPos, Catch->getDebugLoc(),

319 TII.get(WebAssembly::CATCH_REF));

320

321 for (const auto &Def : Catch->defs())

323 MIB.addDef(ExnReg);

324

325

326 for (const auto &Use : Catch->uses()) {

328 break;

329 }

330 } else if (Catch->getOpcode() == WebAssembly::CATCH_ALL) {

331 BuildMI(*EHPad, InsertPos, Catch->getDebugLoc(),

332 TII.get(WebAssembly::CATCH_ALL_REF))

334 } else {

336 }

337 Catch->eraseFromParent();

338

339 for (auto *Rethrow : Rethrows) {

340 auto InsertPos = std::next(Rethrow->getIterator());

341 BuildMI(*Rethrow->getParent(), InsertPos, Rethrow->getDebugLoc(),

342 TII.get(WebAssembly::THROW_REF))

345 }

346 }

347

348 return true;

349}

350

351

352bool WebAssemblyLateEHPrepare::removeUnnecessaryUnreachables(

353 MachineFunction &MF) {

355 for (auto &MBB : MF) {

356 for (auto &MI : MBB) {

357 if (MI.getOpcode() != WebAssembly::THROW &&

358 MI.getOpcode() != WebAssembly::RETHROW &&

359 MI.getOpcode() != WebAssembly::THROW_REF)

360 continue;

362

363

364

365

366

368 SmallVector<MachineBasicBlock *, 8> Succs(MBB.successors());

369 for (auto *Succ : Succs)

370 if (!Succ->isEHPad())

373 }

374 }

375

377}

378

379

380

381

382bool WebAssemblyLateEHPrepare::restoreStackPointer(MachineFunction &MF) {

383 const auto *FrameLowering = static_cast<const WebAssemblyFrameLowering *>(

385 if (!FrameLowering->needsPrologForEH(MF))

386 return false;

388

389 for (auto &MBB : MF) {

391 continue;

393

394

395

396

397

398

399

400 auto InsertPos = MBB.begin();

401

402 while (InsertPos != MBB.end() && InsertPos->isEHLabel())

403 InsertPos++;

406 "catch/catch_all should be present in every EH pad at this point");

407 ++InsertPos;

408 FrameLowering->writeSPToGlobal(FrameLowering->getSPReg(MF), MF, MBB,

409 InsertPos, MBB.begin()->getDebugLoc());

410 }

412}

unsigned const MachineRegisterInfo * MRI

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB

This file defines the SmallPtrSet class.

static void eraseDeadBBsAndChildren(const Container &BBs)

This file declares the WebAssembly-specific subclass of TargetSubtarget.

This file declares the WebAssembly-specific subclass of TargetMachine.

This file contains the declaration of the WebAssembly-specific utility functions.

This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.

FunctionPass class - This class is used to implement most global optimizations.

bool hasPersonalityFn() const

Check whether this function has a personality function.

ExceptionHandling getExceptionHandlingType() const

const MCInstrDesc & get(unsigned Opcode) const

Return the machine instruction descriptor that corresponds to the specified instruction opcode.

bool isEHPad() const

Returns true if the block is a landing pad.

LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)

Insert MI into the instruction list before I, possibly inside a bundle.

LLVM_ABI iterator getFirstTerminator()

Returns an iterator to the first terminator instruction of this basic block.

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 instr_iterator erase(instr_iterator I)

Remove an instruction from the instruction list and delete it.

iterator_range< succ_iterator > successors()

iterator_range< pred_iterator > predecessors()

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.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

const MachineBasicBlock & front() const

const TargetMachine & getTarget() const

getTarget - Return the target machine this machine code is compiled with

const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const

const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const

Add a virtual register definition operand.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)

Add the specified operand to the instruction.

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

LLVM_ABI void eraseFromParent()

Unlink 'this' from the containing basic block and delete it.

LLVM_ABI void removeOperand(unsigned OpNo)

Erase an operand from an instruction, leaving it with one fewer operand than it started with.

const MachineOperand & getOperand(unsigned i) const

MachineBasicBlock * getMBB() const

static MachineOperand CreateMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0)

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

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.

const MCAsmInfo * getMCAsmInfo() const

Return target specific asm information.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

cl::opt< bool > WasmUseLegacyEH

MachineInstr * findCatch(MachineBasicBlock *EHPad)

Find a catch instruction from an EH pad.

bool isCatch(unsigned Opc)

NodeAddr< DefNode * > Def

NodeAddr< UseNode * > Use

This is an optimization pass for GlobalISel generic memory operations.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

FunctionPass * createWebAssemblyLateEHPrepare()

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...