LLVM: lib/CodeGen/SjLjEHPrepare.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

33using namespace llvm;

34

35#define DEBUG_TYPE "sjlj-eh-prepare"

36

37STATISTIC(NumInvokes, "Number of invokes replaced");

38STATISTIC(NumSpilled, "Number of registers live across unwind edges");

39

40namespace {

41class SjLjEHPrepareImpl {

43 Type *doubleUnderDataTy = nullptr;

44 Type *doubleUnderJBufTy = nullptr;

45 Type *FunctionContextTy = nullptr;

48 Function *BuiltinSetupDispatchFn = nullptr;

49 Function *FrameAddrFn = nullptr;

50 Function *StackAddrFn = nullptr;

51 Function *StackRestoreFn = nullptr;

52 Function *LSDAAddrFn = nullptr;

53 Function *CallSiteFn = nullptr;

54 Function *FuncCtxFn = nullptr;

57

58public:

59 explicit SjLjEHPrepareImpl(const TargetMachine *TM = nullptr) : TM(TM) {}

60 bool doInitialization(Module &M);

62

63private:

64 bool setupEntryBlockAndCallSites(Function &F);

65 void substituteLPadValues(LandingPadInst *LPI, Value *ExnVal, Value *SelVal);

67 void lowerIncomingArguments(Function &F);

69 void insertCallSiteStore(Instruction *I, int Number);

70};

71

73 SjLjEHPrepareImpl Impl;

74

75public:

76 static char ID;

77 explicit SjLjEHPrepare(const TargetMachine *TM = nullptr)

78 : FunctionPass(ID), Impl(TM) {}

79 bool doInitialization(Module &M) override { return Impl.doInitialization(M); }

80 bool runOnFunction(Function &F) override { return Impl.runOnFunction(F); };

81

82 StringRef getPassName() const override {

83 return "SJLJ Exception Handling preparation";

84 }

85};

86

87}

88

91 SjLjEHPrepareImpl Impl(TM);

92 Impl.doInitialization(*F.getParent());

93 bool Changed = Impl.runOnFunction(F);

95}

96

97char SjLjEHPrepare::ID = 0;

99 false, false)

100

101

103 return new SjLjEHPrepare(TM);

104}

105

106

107

108bool SjLjEHPrepareImpl::doInitialization(Module &M) {

109

110

112 unsigned DataBits =

118 DataTy,

119 doubleUnderDataTy,

120 VoidPtrTy,

121 VoidPtrTy,

122 doubleUnderJBufTy

123 );

124

125 return false;

126}

127

128

129

130void SjLjEHPrepareImpl::insertCallSiteStore(Instruction *I, int Number) {

132

133

139 Builder.CreateGEP(FunctionContextTy, FuncCtx, Idxs, "call_site");

140

141

143 Builder.CreateStore(CallSiteNoC, CallSite, true );

144}

145

146

147

150 if (!LiveBBs.insert(BB).second)

151 return;

152

154}

155

156

157

158void SjLjEHPrepareImpl::substituteLPadValues(LandingPadInst *LPI, Value *ExnVal,

161 while (!UseWorkList.empty()) {

162 Value *Val = UseWorkList.pop_back_val();

164 if (!EVI)

165 continue;

166 if (EVI->getNumIndices() != 1)

167 continue;

168 if (*EVI->idx_begin() == 0)

169 EVI->replaceAllUsesWith(ExnVal);

170 else if (*EVI->idx_begin() == 1)

171 EVI->replaceAllUsesWith(SelVal);

172 if (EVI->use_empty())

173 EVI->eraseFromParent();

174 }

175

177 return;

178

179

180

184 IRBuilder<> Builder(SelI->getParent(), std::next(SelI->getIterator()));

185 LPadVal = Builder.CreateInsertValue(LPadVal, ExnVal, 0, "lpad.val");

186 LPadVal = Builder.CreateInsertValue(LPadVal, SelVal, 1, "lpad.val");

187

189}

190

191

192

194SjLjEHPrepareImpl::setupFunctionContext(Function &F,

197

198

199

200

201 auto &DL = F.getDataLayout();

202 const Align Alignment = DL.getPrefTypeAlign(FunctionContextTy);

203 FuncCtx = new AllocaInst(FunctionContextTy, DL.getAllocaAddrSpace(), nullptr,

204 Alignment, "fn_context", EntryBB->begin());

205

206

209 LPI->getParent()->getFirstInsertionPt());

210

211

213 Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 2, "__data");

214

215

216 Value *ExceptionAddr = Builder.CreateConstGEP2_32(doubleUnderDataTy, FCData,

217 0, 0, "exception_gep");

218 Value *ExnVal = Builder.CreateLoad(DataTy, ExceptionAddr, true, "exn_val");

219 ExnVal = Builder.CreateIntToPtr(ExnVal, Builder.getPtrTy());

220

221 Value *SelectorAddr = Builder.CreateConstGEP2_32(doubleUnderDataTy, FCData,

222 0, 1, "exn_selector_gep");

224 Builder.CreateLoad(DataTy, SelectorAddr, true, "exn_selector_val");

225

226

227 SelVal = Builder.CreateTrunc(SelVal, Type::getInt32Ty(F.getContext()));

228

229 substituteLPadValues(LPI, ExnVal, SelVal);

230 }

231

232

234 Value *PersonalityFn = F.getPersonalityFn();

235 Value *PersonalityFieldPtr = Builder.CreateConstGEP2_32(

236 FunctionContextTy, FuncCtx, 0, 3, "pers_fn_gep");

237 Builder.CreateStore(PersonalityFn, PersonalityFieldPtr, true);

238

239

240 Value *LSDA = Builder.CreateCall(LSDAAddrFn, {}, "lsda_addr");

241 Value *LSDAFieldPtr =

242 Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 4, "lsda_gep");

243 Builder.CreateStore(LSDA, LSDAFieldPtr, true);

244

245 return FuncCtx;

246}

247

248

249

250

251

252void SjLjEHPrepareImpl::lowerIncomingArguments(Function &F) {

256 ++AfterAllocaInsPt;

257 assert(AfterAllocaInsPt != F.front().end());

258

259 for (auto &AI : F.args()) {

260

261

262

263

264 if (AI.isSwiftError())

265 continue;

266

267 Type *Ty = AI.getType();

268

269

273 TrueValue, &AI, PoisonValue, AI.getName() + ".tmp", AfterAllocaInsPt);

274 AI.replaceAllUsesWith(SI);

275

276

277 SI->setOperand(1, &AI);

278 }

279}

280

281

282

283void SjLjEHPrepareImpl::lowerAcrossUnwindEdges(Function &F,

285

288

289

290

291 if (Inst.use_empty())

292 continue;

293 if (Inst.hasOneUse() &&

296 continue;

297

298

299

301 if (AI->isStaticAlloca())

302 continue;

303

304

309 Users.push_back(UI);

310 }

311

312

315 while (Users.empty()) {

317

320 } else {

321

326 }

327 }

328

329

330

331 bool NeedsSpill = false;

333 BasicBlock *UnwindBlock = Invoke->getUnwindDest();

334 if (UnwindBlock != &BB && LiveBBs.count(UnwindBlock)) {

335 LLVM_DEBUG(dbgs() << "SJLJ Spill: " << Inst << " around "

336 << UnwindBlock->getName() << "\n");

337 NeedsSpill = true;

338 break;

339 }

340 }

341

342

343

344

345

346 if (NeedsSpill) {

348 ++NumSpilled;

349 }

350 }

351 }

352

353

355 BasicBlock *UnwindBlock = Invoke->getUnwindDest();

357

358

362 if (PHIsToDemote.empty())

363 continue;

364

365

366 for (PHINode *PN : PHIsToDemote)

368

369

371 }

372}

373

374

375

376

377bool SjLjEHPrepareImpl::setupEntryBlockAndCallSites(Function &F) {

381

382

385 if (Function *Callee = II->getCalledFunction())

386 if (Callee->getIntrinsicID() == Intrinsic::donothing) {

387

389 II->eraseFromParent();

390 continue;

391 }

392

394 LPads.insert(II->getUnwindDest()->getLandingPadInst());

397 }

398

399 if (Invokes.empty())

400 return false;

401

402 NumInvokes += Invokes.size();

403

404 lowerIncomingArguments(F);

405 lowerAcrossUnwindEdges(F, Invokes);

406

411

412

414 Builder.CreateConstGEP2_32(FunctionContextTy, FuncCtx, 0, 5, "jbuf_gep");

415

416

417 Value *FramePtr = Builder.CreateConstGEP2_32(doubleUnderJBufTy, JBufPtr, 0, 0,

418 "jbuf_fp_gep");

419

420 Value *Val = Builder.CreateCall(FrameAddrFn, Builder.getInt32(0), "fp");

421 Builder.CreateStore(Val, FramePtr, true);

422

423

424 Value *StackPtr = Builder.CreateConstGEP2_32(doubleUnderJBufTy, JBufPtr, 0, 2,

425 "jbuf_sp_gep");

426

427 Val = Builder.CreateCall(StackAddrFn, {}, "sp");

428 Builder.CreateStore(Val, StackPtr, true);

429

430

431 Builder.CreateCall(BuiltinSetupDispatchFn, {});

432

433

434

435 Builder.CreateCall(FuncCtxFn, FuncCtx);

436

437

438 CallInst *Register = Builder.CreateCall(RegisterFn, FuncCtx, "");

440

441

442

443 for (unsigned I = 0, E = Invokes.size(); I != E; ++I) {

444 insertCallSiteStore(Invokes[I], I + 1);

445

448

449

450

451 CallInst::Create(CallSiteFn, CallSiteNum, "", Invokes[I]->getIterator());

452 }

453

454

455

456

457

458

460 if (&BB == &F.front())

461 continue;

464 insertCallSiteStore(&I, -1);

465 }

466

467

468

470 if (&BB == &F.front())

471 continue;

474 if (CI->getCalledFunction() != StackRestoreFn)

475 continue;

477 continue;

478 }

481 new StoreInst(StackAddr, StackPtr, true,

483 }

484 }

485

486

487

490 if (CallInst *CI = Return->getParent()->getTerminatingMustTailCall())

491 InsertPoint = CI;

493 }

494

495 return true;

496}

497

498bool SjLjEHPrepareImpl::runOnFunction(Function &F) {

500 RegisterFn = M.getOrInsertFunction(

503 UnregisterFn = M.getOrInsertFunction(

506

507 PointerType *AllocaPtrTy = M.getDataLayout().getAllocaPtrType(M.getContext());

508

510 {AllocaPtrTy});

512 {AllocaPtrTy});

514 &M, Intrinsic::stackrestore, {AllocaPtrTy});

515 BuiltinSetupDispatchFn =

518 CallSiteFn =

520 FuncCtxFn =

522

523 bool Res = setupEntryBlockAndCallSites(F);

524 return Res;

525}

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

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

This file contains the declarations for the subclasses of Constant, which represent the different fla...

static bool runOnFunction(Function &F, bool PostInlining)

Module.h This file contains the declarations for the Module class.

iv Induction Variable Users

Machine Check Debug Module

uint64_t IntrinsicInst * II

FunctionAnalysisManager FAM

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

This file implements a set that has insertion order iteration characteristics.

static void MarkBlocksLiveIn(BasicBlock *BB, SmallPtrSetImpl< BasicBlock * > &LiveBBs)

MarkBlocksLiveIn - Insert BB and all of its predecessors into LiveBBs until we reach blocks we've alr...

Definition SjLjEHPrepare.cpp:148

This file defines the SmallPtrSet class.

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

static const unsigned FramePtr

an instruction to allocate memory on the stack

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)

This static method is the primary way to construct an ArrayType.

LLVM Basic Block Representation.

iterator begin()

Instruction iterator methods.

LLVM_ABI const LandingPadInst * getLandingPadInst() const

Return the landingpad instruction associated with the landing pad.

const Instruction & front() const

InstListType::iterator iterator

Instruction iterators...

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)

This class represents a function call, abstracting a target machine's calling convention.

static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

This is the shared class of boolean and integer constants.

static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)

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 void moveBefore(InstListType::iterator InsertPos)

Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...

LLVM_ABI void insertAfter(Instruction *InsertPos)

Insert an unlinked instruction into a basic block immediately after the specified instruction.

Class to represent integer types.

The landingpad instruction holds all of the information necessary to generate correct exception handl...

A Module instance is used to store all the information related to an LLVM module.

BasicBlock * getIncomingBlock(unsigned i) const

Return incoming basic block number i.

Value * getIncomingValue(unsigned i) const

Return incoming value number x.

unsigned getNumIncomingValues() const

Return the number of incoming edges.

Class to represent pointers.

static PointerType * getUnqual(Type *ElementType)

This constructs a pointer to an object of the specified type in the default address space (address sp...

In order to facilitate speculative execution, many instructions do not invoke immediate undefined beh...

static LLVM_ABI PoisonValue * get(Type *T)

Static factory methods - Return an 'poison' object of the specified type.

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.

Wrapper class representing virtual and physical registers.

Return a value (possibly void), from a function.

static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, const Instruction *MDFrom=nullptr)

iterator end()

Get an iterator to the end of the SetVector.

iterator begin()

Get an iterator to the beginning of the SetVector.

bool insert(const value_type &X)

Insert a new element into the SetVector.

PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)

Definition SjLjEHPrepare.cpp:89

A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...

size_type count(ConstPtrType Ptr) const

count - Return 1 if the specified pointer is in the set, 0 otherwise.

void insert_range(Range &&R)

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.

A SetVector that performs no allocations if smaller than a certain size.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

An instruction for storing to memory.

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.

Primary interface to the complete machine description for the target machine.

static constexpr unsigned DefaultSjLjDataSize

The integer bit size to use for SjLj based exception handling.

The instances of the Type class are immutable: once they are created, they are never changed.

static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)

static LLVM_ABI Type * getVoidTy(LLVMContext &C)

static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

LLVM_ABI void replaceAllUsesWith(Value *V)

Change all uses of this to point to a new Value.

iterator_range< user_iterator > users()

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

const ParentTy * getParent() const

self_iterator getIterator()

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.

FunctionAddr VTableAddr Value

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty

LLVM_ABI AllocaInst * DemoteRegToStack(Instruction &X, bool VolatileLoads=false, std::optional< BasicBlock::iterator > AllocaPoint=std::nullopt)

This function takes a virtual register computed by an Instruction and replaces it with a slot in the ...

LLVM_ABI AllocaInst * DemotePHIToStack(PHINode *P, std::optional< BasicBlock::iterator > AllocaPoint=std::nullopt)

This function takes a virtual register computed by a phi node and replaces it with a slot in the stac...

iterator_range< idf_iterator< T > > inverse_depth_first(const T &G)

LLVM_ABI raw_ostream & dbgs()

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

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

ArrayRef(const T &OneElt) -> ArrayRef< T >

LLVM_ABI FunctionPass * createSjLjEHPreparePass(const TargetMachine *TM)

createSjLjEHPreparePass - This pass adapts exception handling code to use the GCC-style builtin setjm...

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

AnalysisManager< Function > FunctionAnalysisManager

Convenience typedef for the Function analysis manager.

This struct is a compact representation of a valid (non-zero power of two) alignment.