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(() && "popping exception stack when not empty");
625
629}
630
632 assert(() && "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