clang 20.0.0git
CGCleanup.h
Go to the documentation of this file.
1//===-- CGCleanup.h - Classes for cleanups IR generation --------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// These classes support the generation of LLVM IR for cleanups.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H
14#define LLVM_CLANG_LIB_CODEGEN_CGCLEANUP_H
15
16#include "EHScopeStack.h"
17
18#include "Address.h"
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;
27class Value;
28class ConstantInt;
29}
30
31namespace clang {
32class FunctionDecl;
33namespace CodeGen {
34class CodeGenModule;
35class CodeGenFunction;
36
37/// The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the
38/// type of a catch handler, so we use this wrapper.
40 llvm::Constant *RTTI;
41 unsigned Flags;
42};
43
44/// A protected scope for zero-cost EH handling.
45class EHScope {
46public:
48
49private:
50 llvm::BasicBlock *CachedLandingPad;
51 llvm::BasicBlock *CachedEHDispatchBlock;
52
53 EHScopeStack::stable_iterator EnclosingEHScope;
54
55 class CommonBitFields {
56 friend class EHScope;
57 LLVM_PREFERRED_TYPE(Kind)
58 unsigned Kind : 3;
59 };
60 enum { NumCommonBits = 3 };
61
62protected:
64 friend class EHCatchScope;
65 unsigned : NumCommonBits;
66
67 unsigned NumHandlers : 32 - NumCommonBits;
68 };
69
71 friend class EHCleanupScope;
72 unsigned : NumCommonBits;
73
74 /// Whether this cleanup needs to be run along normal edges.
75 LLVM_PREFERRED_TYPE(bool)
76 unsigned IsNormalCleanup : 1;
77
78 /// Whether this cleanup needs to be run along exception edges.
79 LLVM_PREFERRED_TYPE(bool)
80 unsigned IsEHCleanup : 1;
81
82 /// Whether this cleanup is currently active.
83 LLVM_PREFERRED_TYPE(bool)
84 unsigned IsActive : 1;
85
86 /// Whether this cleanup is a lifetime marker
87 LLVM_PREFERRED_TYPE(bool)
88 unsigned IsLifetimeMarker : 1;
89
90 /// Whether the normal cleanup should test the activation flag.
91 LLVM_PREFERRED_TYPE(bool)
92 unsigned TestFlagInNormalCleanup : 1;
93
94 /// Whether the EH cleanup should test the activation flag.
95 LLVM_PREFERRED_TYPE(bool)
96 unsigned TestFlagInEHCleanup : 1;
97
98 /// The amount of extra storage needed by the Cleanup.
99 /// Always a multiple of the scope-stack alignment.
100 unsigned CleanupSize : 12;
101 };
102
104 friend class EHFilterScope;
105 unsigned : NumCommonBits;
106
107 unsigned NumFilters : 32 - NumCommonBits;
108 };
109
110 union {
111 CommonBitFields CommonBits;
115 };
116
117public:
119 : CachedLandingPad(nullptr), CachedEHDispatchBlock(nullptr),
120 EnclosingEHScope(enclosingEHScope) {
121 CommonBits.Kind = kind;
122 }
123
124 Kind getKind() const { return static_cast<Kind>(CommonBits.Kind); }
125
126 llvm::BasicBlock *getCachedLandingPad() const {
127 return CachedLandingPad;
128 }
129
130 void setCachedLandingPad(llvm::BasicBlock *block) {
131 CachedLandingPad = block;
132 }
133
134 llvm::BasicBlock *getCachedEHDispatchBlock() const {
135 return CachedEHDispatchBlock;
136 }
137
138 void setCachedEHDispatchBlock(llvm::BasicBlock *block) {
139 CachedEHDispatchBlock = block;
140 }
141
142 bool hasEHBranches() const {
143 if (llvm::BasicBlock *block = getCachedEHDispatchBlock())
144 return !block->use_empty();
145 return false;
146 }
147
149 return EnclosingEHScope;
150 }
151};
152
153/// A scope which attempts to handle some, possibly all, types of
154/// exceptions.
155///
156/// Objective C \@finally blocks are represented using a cleanup scope
157/// after the catch scope.
158class EHCatchScope : public EHScope {
159 // In effect, we have a flexible array member
160 // Handler Handlers[0];
161 // But that's only standard in C99, not C++, so we have to do
162 // annoying pointer arithmetic instead.
163
164public:
165 struct Handler {
166 /// A type info value, or null (C++ null, not an LLVM null pointer)
167 /// for a catch-all.
169
170 /// The catch handler for this type.
171 llvm::BasicBlock *Block;
172
173 bool isCatchAll() const { return Type.RTTI == nullptr; }
174 };
175
176private:
177 friend class EHScopeStack;
178
179 Handler *getHandlers() {
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:
188 static size_t getSizeForNumHandlers(unsigned N) {
189 return sizeof(EHCatchScope) + N * sizeof(Handler);
190 }
191
192 EHCatchScope(unsigned numHandlers,
193 EHScopeStack::stable_iterator enclosingEHScope)
194 : EHScope(Catch, enclosingEHScope) {
195 CatchBits.NumHandlers = numHandlers;
196 assert(CatchBits.NumHandlers == numHandlers && "NumHandlers overflow?");
197 }
198
199 unsigned getNumHandlers() const {
200 return CatchBits.NumHandlers;
201 }
202
203 void setCatchAllHandler(unsigned I, llvm::BasicBlock *Block) {
204 setHandler(I, CatchTypeInfo{nullptr, 0}, Block);
205 }
206
207 void setHandler(unsigned I, llvm::Constant *Type, llvm::BasicBlock *Block) {
208 assert(I < getNumHandlers());
209 getHandlers()[I].Type = CatchTypeInfo{Type, 0};
210 getHandlers()[I].Block = Block;
211 }
212
213 void setHandler(unsigned I, CatchTypeInfo Type, llvm::BasicBlock *Block) {
214 assert(I <