clang: lib/CodeGen/CGCleanup.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13#ifndef LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H

14#define LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H

15

17

19#include "llvm/ADT/STLExtras.h"

20#include "llvm/ADT/SetVector.h"

21#include "llvm/ADT/SmallPtrSet.h"

22#include "llvm/ADT/SmallVector.h"

23#include "llvm/IR/Instruction.h"

24

25namespace llvm {

26class BasicBlock;

28class ConstantInt;

29}

30

32class FunctionDecl;

33namespace CodeGen {

34class CodeGenModule;

35class CodeGenFunction;

36

37

38

42};

43

44

46public:

48

49private:

50 llvm::BasicBlock *CachedLandingPad;

51 llvm::BasicBlock *CachedEHDispatchBlock;

52

54

55 class CommonBitFields {

57 LLVM_PREFERRED_TYPE(Kind)

58 unsigned Kind : 3;

59 };

60 enum { NumCommonBits = 3 };

61

62protected:

66

67 unsigned NumHandlers : 32 - NumCommonBits;

68 };

69

73

74

75 LLVM_PREFERRED_TYPE(bool)

76 unsigned IsNormalCleanup : 1;

77

78

79 LLVM_PREFERRED_TYPE(bool)

80 unsigned IsEHCleanup : 1;

81

82

83 LLVM_PREFERRED_TYPE(bool)

84 unsigned IsActive : 1;

85

86

87 LLVM_PREFERRED_TYPE(bool)

88 unsigned IsLifetimeMarker : 1;

89

90

91 LLVM_PREFERRED_TYPE(bool)

92 unsigned TestFlagInNormalCleanup : 1;

93

94

95 LLVM_PREFERRED_TYPE(bool)

96 unsigned TestFlagInEHCleanup : 1;

97

98

99

100 unsigned CleanupSize : 12;

101 };

102

106

107 unsigned NumFilters : 32 - NumCommonBits;

108 };

109

110 union {

115 };

116

117public:

119 : CachedLandingPad(nullptr), CachedEHDispatchBlock(nullptr),

120 EnclosingEHScope(enclosingEHScope) {

122 }

123

125

127 return CachedLandingPad;

128 }

129

131 CachedLandingPad = block;

132 }

133

135 return CachedEHDispatchBlock;

136 }

137

139 CachedEHDispatchBlock = block;

140 }

141

144 return !block->use_empty();

145 return false;

146 }

147

149 return EnclosingEHScope;

150 }

151};

152

153

154

155

156

157

159

160

161

162

163

164public:

166

167

169

170

172

174 };

175

176private:

178

180 return reinterpret_cast<Handler*>(this+1);

181 }

182

183 const Handler *getHandlers() const {

184 return reinterpret_cast<const Handler*>(this+1);

185 }

186

187public:

190 }

191

195 CatchBits.NumHandlers = numHandlers;

196 assert(CatchBits.NumHandlers == numHandlers && "NumHandlers overflow?");

197 }

198

201 }

202

205 }

206

211 }

212

215 getHandlers()[I].Type = Type;

217 }

218

221 return getHandlers()[I];

222 }

223

224

225

226

227

229 for (unsigned I = 0, N = getNumHandlers(); I != N; ++I)

231 }

232

236

239 }

240};

241

242

244

246

247

249

250

251

252 llvm::BasicBlock *NormalBlock;

253

254

255

257

258

259

260

261

262 struct ExtInfo {

263

265

266

268 BranchAfters;

269 };

270 mutable struct ExtInfo *ExtInfo;

271

272

273

274

275 struct AuxillaryAllocas {

277 bool used = false;

278

279

280 void Add(llvm::AllocaInst *Alloca) { AuxAllocas.push_back(Alloca); }

281

282

283 void MarkUsed() {

284 used = true;

285 AuxAllocas.clear();

286 }

287

288 ~AuxillaryAllocas() {

289 if (used)

290 return;

291 llvm::SetVector<llvm::Instruction *> Uses;

292 for (auto *Inst : llvm::reverse(AuxAllocas))

293 CollectUses(Inst, Uses);

294

295 for (auto *I : llvm::reverse(Uses))

296 I->eraseFromParent();

297 }

298

299 private:

300 void CollectUses(llvm::Instruction *I,

301 llvm::SetVector<llvm::Instruction *> &Uses) {

302 if (!I || !Uses.insert(I))

303 return;

304 for (auto *User : I->users())

305 CollectUses(castllvm::Instruction(User), Uses);

306 }

307 };

308 mutable struct AuxillaryAllocas *AuxAllocas;

309

310 AuxillaryAllocas &getAuxillaryAllocas() {

311 if (!AuxAllocas) {

312 AuxAllocas = new struct AuxillaryAllocas();

313 }

314 return *AuxAllocas;

315 }

316

317

318

319

320 unsigned FixupDepth;

321

322 struct ExtInfo &getExtInfo() {

323 if (!ExtInfo) ExtInfo = new struct ExtInfo();

324 return *ExtInfo;

325 }

326

327 const struct ExtInfo &getExtInfo() const {

328 if (!ExtInfo) ExtInfo = new struct ExtInfo();

329 return *ExtInfo;

330 }

331

332public:

333

334

337 }

338

341 }

342

344 unsigned fixupDepth,

348 EnclosingNormal(enclosingNormal), NormalBlock(nullptr),

349 ActiveFlag(Address::invalid()), ExtInfo(nullptr), AuxAllocas(nullptr),

350 FixupDepth(fixupDepth) {

355 CleanupBits.TestFlagInNormalCleanup = false;

358

359 assert(CleanupBits.CleanupSize == cleanupSize && "cleanup size overflow");

360 }

361

363 if (AuxAllocas)

364 delete AuxAllocas;

365 delete ExtInfo;

366 }

368 for (auto *Alloca : Allocas)

369 getAuxillaryAllocas().Add(Alloca);

370 }

371 void MarkEmitted() { getAuxillaryAllocas().MarkUsed(); }

372

374

378

380

383

386

389 return ActiveFlag;

390 }

393 ActiveFlag = Var;

394 }

395

397 CleanupBits.TestFlagInNormalCleanup = true;

398 }

400 return CleanupBits.TestFlagInNormalCleanup;

401 }

402

405 }

408 }

409

412 return EnclosingNormal;

413 }

414

417

420 }

421

422

423 bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); }

424

425

426

427

428

429

430

431

432

433

434

435

437 llvm::BasicBlock *Block) {

438 struct ExtInfo &ExtInfo = getExtInfo();

439 if (ExtInfo.Branches.insert(Block).second)

440 ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index));

441 }

442

443

445 return ExtInfo ? ExtInfo->BranchAfters.size() : 0;

446 }

447

450 return ExtInfo->BranchAfters[I].first;

451 }

452

455 return ExtInfo->BranchAfters[I].second;

456 }

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

474 return getExtInfo().Branches.insert(Block).second;

475 }

476

477

479 if (!ExtInfo) return false;

480 return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size());

481 }

482

485 }

486};

487

488

489

490

491

492

494 "EHCleanupScope expected alignment");

495

496

497

498

499

500

502

503

504

505 llvm::Value **getFilters() {

506 return reinterpret_castllvm::Value\*\*\(this+1);

507 }

508

509 llvm::Value * const *getFilters() const {

510 return reinterpret_cast<llvm::Value* const *>(this+1);

511 }

512

513public:

517 assert(FilterBits.NumFilters == numFilters && "NumFilters overflow");

518 }

519

521 return sizeof(EHFilterScope) + numFilters * sizeof(llvm::Value*);

522 }

523

525

526 void setFilter(unsigned i, llvm::Value *filterValue) {

528 getFilters()[i] = filterValue;

529 }

530

533 return getFilters()[i];

534 }

535

538 }

539};

540

541

542

544public:

548

551 }

552};

553

554

556 char *Ptr;

557

559 explicit iterator(char *Ptr) : Ptr(Ptr) {}

560

561public:

563

565 return reinterpret_cast<EHScope*>(Ptr);

566 }

567

570

572 size_t Size;

576 static_cast<const EHCatchScope *>(get())->getNumHandlers());

577 break;

578

582 break;

583

585 Size = static_cast<const EHCleanupScope *>(get())->getAllocatedSize();

586 break;

587

590 break;

591 }

593 return *this;

594 }

595

598 ++copy;

599 return copy;

600 }

601

605 return copy;

606 }

607

610

613};

614

616 return iterator(StartOfData);

617}

618

620 return iterator(EndOfBuffer);

621}

622

624 assert(empty() && "popping exception stack when not empty");

625

629}

630

632 assert(empty() && "popping exception stack when not empty");

633

637}

638

640 assert(sp.isValid() && "finding invalid savepoint");

641 assert(sp.Size <= stable_begin().Size && "finding savepoint after pop");

642 return iterator(EndOfBuffer - sp.Size);

643}

644

647 assert(StartOfData <= ir.Ptr && ir.Ptr <= EndOfBuffer);

649}

650

651

654

655

656

657

659

662

681

682

683

686 }

687

691 }

692

694

696};

697}

698}

699

700#endif

enum clang::sema::@1727::IndirectLocalPathEntry::EntryKind Kind

static Decl::Kind getKind(const Decl *D)

bool isOne() const

isOne - Test whether the quantity equals one.

Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...

CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...

This class organizes the cross-function state that is used while generating LLVM code.

A scope which attempts to handle some, possibly all, types of exceptions.

EHCatchScope(unsigned numHandlers, EHScopeStack::stable_iterator enclosingEHScope)

const Handler & getHandler(unsigned I) const

void setHandler(unsigned I, llvm::Constant *Type, llvm::BasicBlock *Block)

static size_t getSizeForNumHandlers(unsigned N)

void setHandler(unsigned I, CatchTypeInfo Type, llvm::BasicBlock *Block)

void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block)

void clearHandlerBlocks()

static bool classof(const EHScope *Scope)

unsigned getNumHandlers() const

A cleanup scope which generates the cleanup blocks lazily.

bool shouldTestFlagInEHCleanup() const

bool isLifetimeMarker() const

Address getActiveFlag() const

EHScopeStack::stable_iterator getEnclosingNormalCleanup() const

size_t getAllocatedSize() const

bool hasActiveFlag() const

void setNormalBlock(llvm::BasicBlock *BB)

llvm::ConstantInt * getBranchAfterIndex(unsigned I) const

bool shouldTestFlagInNormalCleanup() const

bool addBranchThrough(llvm::BasicBlock *Block)

Add a branch-through to this cleanup scope.

llvm::BasicBlock * getBranchAfterBlock(unsigned I) const

void AddAuxAllocas(llvm::SmallVector< llvm::AllocaInst * > Allocas)

void setTestFlagInNormalCleanup()

void setTestFlagInEHCleanup()

void * getCleanupBuffer()

unsigned getNumBranchAfters() const

Return the number of unique branch-afters on this scope.

bool isNormalCleanup() const

static size_t getSizeForCleanupSize(size_t Size)

Gets the size required for a lazy cleanup scope with the given cleanup-data requirements.

bool hasBranches() const

True if this cleanup scope has any branch-afters or branch-throughs.

void addBranchAfter(llvm::ConstantInt *Index, llvm::BasicBlock *Block)

Add a branch-after to this cleanup scope.

void setActiveFlag(RawAddress Var)

EHCleanupScope(bool isNormal, bool isEH, unsigned cleanupSize, unsigned fixupDepth, EHScopeStack::stable_iterator enclosingNormal, EHScopeStack::stable_iterator enclosingEH)

EHScopeStack::Cleanup * getCleanup()

unsigned getFixupDepth() const

size_t getCleanupSize() const

static bool classof(const EHScope *Scope)

llvm::BasicBlock * getNormalBlock() const

bool hasBranchThroughs() const

Determines if this cleanup scope has any branch throughs.

An exceptions scope which filters exceptions thrown through it.

void setFilter(unsigned i, llvm::Value *filterValue)

static size_t getSizeForNumFilters(unsigned numFilters)

EHFilterScope(unsigned numFilters)

llvm::Value * getFilter(unsigned i) const

unsigned getNumFilters() const

static bool classof(const EHScope *scope)

Information for lazily generating a cleanup.

A non-stable pointer into the scope stack.

bool operator!=(iterator other) const

EHScope & operator*() const

bool encloses(iterator other) const

bool strictlyEncloses(iterator other) const

EHScope * operator->() const

bool operator==(iterator other) const

A saved depth on the scope stack.

A stack of scopes which respond to exceptions, including cleanups and catch blocks.

stable_iterator stable_begin() const

Create a stable reference to the top of the EH stack.

bool empty() const

Determines whether the exception-scopes stack is empty.

iterator end() const

Returns an iterator pointing to the outermost EH scope.

iterator begin() const

Returns an iterator pointing to the innermost EH scope.

void popCatch()

Pops a catch scope off the stack. This is private to CGException.cpp.

iterator find(stable_iterator save) const

Turn a stable reference to a scope depth into a unstable pointer to the EH stack.

stable_iterator stabilize(iterator it) const

Translates an iterator into a stable_iterator.

void popTerminate()

Pops a terminate handler off the stack.

A protected scope for zero-cost EH handling.

llvm::BasicBlock * getCachedLandingPad() const

EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope)

void setCachedLandingPad(llvm::BasicBlock *block)

CleanupBitFields CleanupBits

FilterBitFields FilterBits

EHScopeStack::stable_iterator getEnclosingEHScope() const

llvm::BasicBlock * getCachedEHDispatchBlock() const

void setCachedEHDispatchBlock(llvm::BasicBlock *block)

bool hasEHBranches() const

CommonBitFields CommonBits

An exceptions scope which calls std::terminate if any exception reaches it.

EHTerminateScope(EHScopeStack::stable_iterator enclosingEHScope)

static bool classof(const EHScope *scope)

An abstract representation of an aligned address.

CharUnits getAlignment() const

Return the alignment of this pointer.

Represents a function declaration or definition.

Scope - A scope is a transient data structure that is used while parsing the program.

The base class of the type hierarchy.

@ Type

The l-value was considered opaque, so the alignment was determined from a type.

The JSON file list parser is used to communicate input to InstallAPI.

Diagnostic wrappers for TextAPI types for error reporting.

The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the type of a catch handler,...

CatchTypeInfo Type

A type info value, or null (C++ null, not an LLVM null pointer) for a catch-all.

llvm::BasicBlock * Block

The catch handler for this type.

The exceptions personality for a function.

bool isMSVCXXPersonality() const

static const EHPersonality & get(CodeGenModule &CGM, const FunctionDecl *FD)

static const EHPersonality XL_CPlusPlus

static const EHPersonality GNU_ObjC_SJLJ

bool isWasmPersonality() const

static const EHPersonality ZOS_CPlusPlus

static const EHPersonality GNUstep_ObjC

static const EHPersonality MSVC_CxxFrameHandler3

bool usesFuncletPads() const

Does this personality use landingpads or the family of pad instructions designed to form funclets?

static const EHPersonality MSVC_C_specific_handler

static const EHPersonality GNU_CPlusPlus_SEH

static const EHPersonality GNU_ObjC

static const EHPersonality GNU_CPlusPlus_SJLJ

static const EHPersonality GNU_C_SJLJ

static const EHPersonality GNU_C

static const EHPersonality NeXT_ObjC

const char * CatchallRethrowFn

static const EHPersonality GNU_CPlusPlus

static const EHPersonality GNU_ObjCXX

bool isMSVCPersonality() const

static const EHPersonality GNU_C_SEH

static const EHPersonality MSVC_except_handler

static const EHPersonality GNU_ObjC_SEH

const char * PersonalityFn

static const EHPersonality GNU_Wasm_CPlusPlus