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

1

2

3

4

5

6

7

8

9

10

11

12

13

40#include

41

42using namespace llvm;

43

44#define DEBUG_TYPE "dwarf-eh-prepare"

45

46STATISTIC(NumResumesLowered, "Number of resume calls lowered");

47STATISTIC(NumCleanupLandingPadsUnreachable,

48 "Number of cleanup landing pads found unreachable");

50 "Number of cleanup landing pads remaining");

51STATISTIC(NumNoUnwind, "Number of functions with nounwind");

52STATISTIC(NumUnwind, "Number of functions with unwind");

53

54namespace {

55

56class DwarfEHPrepare {

58

63 const Triple &TargetTriple;

64

65

66

67

69

70

71

72 size_t

75

76

77

78 bool InsertUnwindResumeCalls();

79

80public:

84 : OptLevel(OptLevel_), F(F_), TLI(TLI_), DTU(DTU_), TTI(TTI_),

85 TargetTriple(TargetTriple_) {}

86

87 bool run();

88};

89

90}

91

92Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {

94 Value *ExnObj = nullptr;

96 LoadInst *SelLoad = nullptr;

97 InsertValueInst *ExcIVI = nullptr;

98 bool EraseIVIs = false;

99

100 if (SelIVI) {

107 EraseIVIs = true;

108 }

109 }

110 }

111

112 if (!ExnObj)

115

117

118 if (EraseIVIs) {

123 if (SelLoad && SelLoad->use_empty())

125 }

126

127 return ExnObj;

128}

129

130size_t DwarfEHPrepare::pruneUnreachableResumes(

131 SmallVectorImpl<ResumeInst *> &Resumes,

132 SmallVectorImpl<LandingPadInst *> &CleanupLPads) {

133 assert(DTU && "Should have DomTreeUpdater here.");

134

135 BitVector ResumeReachable(Resumes.size());

136 size_t ResumeIndex = 0;

137 for (auto *RI : Resumes) {

138 for (auto *LP : CleanupLPads) {

140 ResumeReachable.set(ResumeIndex);

141 break;

142 }

143 }

144 ++ResumeIndex;

145 }

146

147

148 if (ResumeReachable.all())

149 return Resumes.size();

150

151 LLVMContext &Ctx = F.getContext();

152

153

154 size_t ResumesLeft = 0;

155 for (size_t I = 0, E = Resumes.size(); I < E; ++I) {

156 ResumeInst *RI = Resumes[I];

157 if (ResumeReachable[I]) {

158 Resumes[ResumesLeft++] = RI;

159 } else {

161 new UnreachableInst(Ctx, RI->getIterator());

164 }

165 }

166 Resumes.resize(ResumesLeft);

167 return ResumesLeft;

168}

169

170bool DwarfEHPrepare::InsertUnwindResumeCalls() {

173 if (F.doesNotThrow())

174 NumNoUnwind++;

175 else

176 NumUnwind++;

177 for (BasicBlock &BB : F) {

181 if (LP->isCleanup())

183 }

184

185 NumCleanupLandingPadsRemaining += CleanupLPads.size();

186

187 if (Resumes.empty())

188 return false;

189

190

193 return false;

194

195 LLVMContext &Ctx = F.getContext();

196

197 size_t ResumesLeft = Resumes.size();

198 if (OptLevel != CodeGenOptLevel::None) {

199 ResumesLeft = pruneUnreachableResumes(Resumes, CleanupLPads);

200#if LLVM_ENABLE_STATS

201 unsigned NumRemainingLPs = 0;

202 for (BasicBlock &BB : F) {

204 if (LP->isCleanup())

205 NumRemainingLPs++;

206 }

207 NumCleanupLandingPadsUnreachable += CleanupLPads.size() - NumRemainingLPs;

208 NumCleanupLandingPadsRemaining -= CleanupLPads.size() - NumRemainingLPs;

209#endif

210 }

211

212 if (ResumesLeft == 0)

213 return true;

214

215

216 FunctionCallee RewindFunction;

217 CallingConv::ID RewindFunctionCallingConv;

218 FunctionType *FTy;

219 const char *RewindName;

220 bool DoesRewindFunctionNeedExceptionObject;

221

222 if ((Pers == EHPersonality::GNU_CXX || Pers == EHPersonality::GNU_CXX_SjLj) &&

224 RewindName = TLI.getLibcallName(RTLIB::CXA_END_CLEANUP);

225 FTy = FunctionType::get(Type::getVoidTy(Ctx), false);

226 RewindFunctionCallingConv =

228 DoesRewindFunctionNeedExceptionObject = false;

229 } else {

230 RewindName = TLI.getLibcallName(RTLIB::UNWIND_RESUME);

231 FTy = FunctionType::get(Type::getVoidTy(Ctx), PointerType::getUnqual(Ctx),

232 false);

234 DoesRewindFunctionNeedExceptionObject = true;

235 }

236 RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy);

237

238

239 if (ResumesLeft == 1) {

240

241

242 ResumeInst *RI = Resumes.front();

244 Value *ExnObj = GetExceptionObject(RI);

246 if (DoesRewindFunctionNeedExceptionObject)

247 RewindFunctionArgs.push_back(ExnObj);

248

249

250 CallInst *CI =

251 CallInst::Create(RewindFunction, RewindFunctionArgs, "", UnwindBB);

252

253

254

257 if (DISubprogram *SP = F.getSubprogram())

258 CI->setDebugLoc(DILocation::get(SP->getContext(), 0, 0, SP));

260

261

263 new UnreachableInst(Ctx, UnwindBB);

264 return true;

265 }

266

267 std::vectorDominatorTree::UpdateType Updates;

268 Updates.reserve(Resumes.size());

269

271

273 PHINode *PN = PHINode::Create(PointerType::getUnqual(Ctx), ResumesLeft,

274 "exn.obj", UnwindBB);

275

276

277

278 for (ResumeInst *RI : Resumes) {

281 Updates.push_back({DominatorTree::Insert, Parent, UnwindBB});

282

283 Value *ExnObj = GetExceptionObject(RI);

285

286 ++NumResumesLowered;

287 }

288

289 if (DoesRewindFunctionNeedExceptionObject)

290 RewindFunctionArgs.push_back(PN);

291

292

293 CallInst *CI =

294 CallInst::Create(RewindFunction, RewindFunctionArgs, "", UnwindBB);

295

296

297

300 if (DISubprogram *SP = F.getSubprogram())

301 CI->setDebugLoc(DILocation::get(SP->getContext(), 0, 0, SP));

303

304

306 new UnreachableInst(Ctx, UnwindBB);

307

308 if (DTU)

310

311 return true;

312}

313

314bool DwarfEHPrepare::run() {

315 bool Changed = InsertUnwindResumeCalls();

316

318}

319

323 const Triple &TargetTriple) {

324 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);

325

326 return DwarfEHPrepare(OptLevel, F, TLI, DT ? &DTU : nullptr, TTI,

327 TargetTriple)

328 .run();

329}

330

331namespace {

332

333class DwarfEHPrepareLegacyPass : public FunctionPass {

334

336

337public:

338 static char ID;

339

340 DwarfEHPrepareLegacyPass(CodeGenOptLevel OptLevel = CodeGenOptLevel::Default)

341 : FunctionPass(ID), OptLevel(OptLevel) {}

342

344 const TargetMachine &TM =

345 getAnalysis().getTM();

347 DominatorTree *DT = nullptr;

348 const TargetTransformInfo *TTI = nullptr;

349 if (auto *DTWP = getAnalysisIfAvailable())

350 DT = &DTWP->getDomTree();

351 if (OptLevel != CodeGenOptLevel::None) {

352 if (!DT)

353 DT = &getAnalysis().getDomTree();

354 TTI = &getAnalysis().getTTI(F);

355 }

357 }

358

359 void getAnalysisUsage(AnalysisUsage &AU) const override {

361 AU.addRequired();

362 if (OptLevel != CodeGenOptLevel::None) {

363 AU.addRequired();

364 AU.addRequired();

365 }

367 }

368

369 StringRef getPassName() const override {

370 return "Exception handling preparation";

371 }

372};

373

374}

375

378 const auto &TLI = *TM->getSubtargetImpl(F)->getTargetLowering();

381 auto OptLevel = TM->getOptLevel();

383 if (!DT)

386 }

389

394 return PA;

395}

396

397char DwarfEHPrepareLegacyPass::ID = 0;

398

400 "Prepare DWARF exceptions", false, false)

406

408 return new DwarfEHPrepareLegacyPass(OptLevel);

409}

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

This file implements the BitVector class.

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 prepareDwarfEH(CodeGenOptLevel OptLevel, Function &F, const TargetLowering &TLI, DominatorTree *DT, const TargetTransformInfo *TTI, const Triple &TargetTriple)

Definition DwarfEHPrepare.cpp:320

static bool runOnFunction(Function &F, bool PostInlining)

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

FunctionAnalysisManager FAM

#define INITIALIZE_PASS_DEPENDENCY(depName)

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

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

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)

This file describes how to lower LLVM code to machine code.

Target-Independent Code Generator Pass Configuration Options pass.

This pass exposes codegen information to IR-level passes.

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

LLVM_ABI const LandingPadInst * getLandingPadInst() const

Return the landingpad instruction associated with the landing pad.

static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)

Creates a new BasicBlock.

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)

void setCallingConv(CallingConv::ID CC)

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

Analysis pass which computes a DominatorTree.

Legacy analysis pass which computes a DominatorTree.

Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.

PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)

Definition DwarfEHPrepare.cpp:376

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

DISubprogram * getSubprogram() const

Get the attached subprogram.

DomTreeT & getDomTree()

Flush DomTree updates and return DomTree.

void applyUpdates(ArrayRef< UpdateT > Updates)

Submit updates to all available trees.

unsigned getNumIndices() const

idx_iterator idx_begin() const

LLVM_ABI InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

void setDebugLoc(DebugLoc Loc)

Set the debug location information for this instruction.

void addIncoming(Value *V, BasicBlock *BB)

Add an incoming value to the end of the PHI list.

static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

PreservedAnalyses & preserve()

Mark an analysis as preserved.

Resume the propagation of an exception.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void push_back(const T &Elt)

Analysis pass providing the TargetTransformInfo.

CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const

Get the CallingConv that should be used for the specified libcall.

const char * getLibcallName(RTLIB::Libcall Call) const

Get the libcall routine name for the specified libcall.

This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...

const Triple & getTargetTriple() const

virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const

Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...

Target-Independent Code Generator Pass Configuration Options.

virtual const TargetLowering * getTargetLowering() const

Wrapper pass for TargetTransformInfo.

This pass provides access to the codegen interfaces that are needed for IR-level transformations.

Triple - Helper class for working with autoconf configuration names.

bool isTargetEHABICompatible() const

Tests whether the target supports the EHABI exception handling standard.

Value * getOperand(unsigned i) const

LLVM Value Representation.

const ParentTy * getParent() const

self_iterator getIterator()

unsigned ID

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

@ BasicBlock

Various leaf nodes.

PointerTypeMap run(const Module &M)

Compute the PointerTypeMap for 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.

bool isScopedEHPersonality(EHPersonality Pers)

Returns true if this personality uses scope-style EH IR instructions: catchswitch,...

LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)

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

LLVM_ABI FunctionPass * createDwarfEHPass(CodeGenOptLevel OptLevel)

createDwarfEHPass - This pass mulches exception handling code into a form adapted to code generation.

Definition DwarfEHPrepare.cpp:407

CodeGenOptLevel

Code generation optimization level.

class LLVM_GSL_OWNER SmallVector

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

bool isa(const From &Val)

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

LLVM_ABI bool simplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, DomTreeUpdater *DTU=nullptr, const SimplifyCFGOptions &Options={}, ArrayRef< WeakVH > LoopHeaders={})

AnalysisManager< Function > FunctionAnalysisManager

Convenience typedef for the Function analysis manager.

LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)

Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...