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;

98 bool EraseIVIs = false;

99

100 if (SelIVI) {

102 ExcIVI = dyn_cast(SelIVI->getOperand(0));

103 if (ExcIVI && isa(ExcIVI->getOperand(0)) &&

106 SelLoad = dyn_cast(SelIVI->getOperand(1));

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(

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

134

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

152

153

154 size_t ResumesLeft = 0;

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

157 if (ResumeReachable[I]) {

158 Resumes[ResumesLeft++] = RI;

159 } else {

164 }

165 }

166 Resumes.resize(ResumesLeft);

167 return ResumesLeft;

168}

169

170bool DwarfEHPrepare::InsertUnwindResumeCalls() {

173 if (F.doesNotThrow())

174 NumNoUnwind++;

175 else

176 NumUnwind++;

178 if (auto *RI = dyn_cast(BB.getTerminator()))

181 if (LP->isCleanup())

183 }

184

185 NumCleanupLandingPadsRemaining += CleanupLPads.size();

186

187 if (Resumes.empty())

188 return false;

189

190

193 return false;

194

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;

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

219 const char *RewindName;

220 bool DoesRewindFunctionNeedExceptionObject;

221

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

223 TargetTriple.isTargetEHABICompatible()) {

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

226 RewindFunctionCallingConv =

227 TLI.getLibcallCallingConv(RTLIB::CXA_END_CLEANUP);

228 DoesRewindFunctionNeedExceptionObject = false;

229 } else {

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

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

232 false);

233 RewindFunctionCallingConv = TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME);

234 DoesRewindFunctionNeedExceptionObject = true;

235 }

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

237

238

239 if (ResumesLeft == 1) {

240

241

244 Value *ExnObj = GetExceptionObject(RI);

246 if (DoesRewindFunctionNeedExceptionObject)

247 RewindFunctionArgs.push_back(ExnObj);

248

249

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

252

253

254

255 Function *RewindFn = dyn_cast(RewindFunction.getCallee());

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

260

261

264 return true;

265 }

266

267 std::vectorDominatorTree::UpdateType Updates;

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

269

271

274 "exn.obj", UnwindBB);

275

276

277

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

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

295

296

297

298 Function *RewindFn = dyn_cast(RewindFunction.getCallee());

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

303

304

307

308 if (DTU)

309 DTU->applyUpdates(Updates);

310

311 return true;

312}

313

314bool DwarfEHPrepare::run() {

315 bool Changed = InsertUnwindResumeCalls();

316

317 return Changed;

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)

342

345 getAnalysis().getTM<TargetMachine>();

346 const TargetLowering &TLI = *TM.getSubtargetImpl(F)->getTargetLowering();

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

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

365 }

367 }

368

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 }

387 bool Changed =

389

390 if (!Changed)

394 return PA;

395}

396

397char DwarfEHPrepareLegacyPass::ID = 0;

398

400 "Prepare DWARF exceptions", false, false)

406

408 return new DwarfEHPrepareLegacyPass(OptLevel);

409}

This file implements the BitVector class.

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)

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)

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

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.

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

PassT::Result * getCachedResult(IRUnitT &IR) const

Get the cached result of an analysis pass for a given IR unit.

PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)

Get the result of an analysis pass for a given IR unit.

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

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

LLVM Basic Block Representation.

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)

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)

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)

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.

DISubprogram * getSubprogram() const

Get the attached subprogram.

This instruction inserts a struct field of array element value into an aggregate value.

unsigned getNumIndices() const

idx_iterator idx_begin() const

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.

This is an important class for using LLVM in a threaded context.

An instruction for reading from memory.

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

virtual void getAnalysisUsage(AnalysisUsage &) const

getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...

virtual StringRef getPassName() const

getPassName - Return a nice clean name for a pass.

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.

void 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)

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.

Analysis pass providing the TargetTransformInfo.

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

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

Target-Independent Code Generator Pass Configuration Options.

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.

static Type * getVoidTy(LLVMContext &C)

This function has undefined behavior.

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.

PointerTypeMap run(const Module &M)

Compute the PointerTypeMap for the module M.

This is an optimization pass for GlobalISel generic memory operations.

bool isScopedEHPersonality(EHPersonality Pers)

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

EHPersonality classifyEHPersonality(const Value *Pers)

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

FunctionPass * createDwarfEHPass(CodeGenOptLevel OptLevel)

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

CodeGenOptLevel

Code generation optimization level.

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

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