blob: 6535b76d92584be8debc40237c7461d0e76f9829 [file] [log] [blame]
Reid Kleckner43a75fc2013-06-19 17:07:50 +00001//===-- EHScopeStack.h - Stack for cleanup IR generation --------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// These classes should be the minimum interface required for other parts of
11// CodeGen to emit cleanups. The implementation is in CGCleanup.cpp and other
12// implemenentation details that are not widely needed are in CGCleanup.h.
13//
14//===----------------------------------------------------------------------===//
15
Stephen Hines176edba2014-12-01 14:53:08 -080016#ifndef LLVM_CLANG_LIB_CODEGEN_EHSCOPESTACK_H
17#define LLVM_CLANG_LIB_CODEGEN_EHSCOPESTACK_H
Reid Kleckner43a75fc2013-06-19 17:07:50 +000018
19#include "clang/Basic/LLVM.h"
20#include "llvm/ADT/SmallVector.h"
21#include "llvm/IR/BasicBlock.h"
Reid Kleckner43a75fc2013-06-19 17:07:50 +000022#include "llvm/IR/Instructions.h"
Stephen Hines651f13c2014-04-23 16:59:28 -070023#include "llvm/IR/Value.h"
Reid Kleckner43a75fc2013-06-19 17:07:50 +000024
25namespace clang {
26namespace CodeGen {
27
28class CodeGenFunction;
29
30/// A branch fixup. These are required when emitting a goto to a
31/// label which hasn't been emitted yet. The goto is optimistically
32/// emitted as a branch to the basic block for the label, and (if it
33/// occurs in a scope with non-trivial cleanups) a fixup is added to
34/// the innermost cleanup. When a (normal) cleanup is popped, any
35/// unresolved fixups in that scope are threaded through the cleanup.
36struct BranchFixup {
37 /// The block containing the terminator which needs to be modified
38 /// into a switch if this fixup is resolved into the current scope.
39 /// If null, LatestBranch points directly to the destination.
40 llvm::BasicBlock *OptimisticBranchBlock;
41
42 /// The ultimate destination of the branch.
43 ///
44 /// This can be set to null to indicate that this fixup was
45 /// successfully resolved.
46 llvm::BasicBlock *Destination;
47
48 /// The destination index value.
49 unsigned DestinationIndex;
50
51 /// The initial branch of the fixup.
52 llvm::BranchInst *InitialBranch;
53};
54
55template <class T> struct InvariantValue {
56 typedef T type;
57 typedef T saved_type;
58 static bool needsSaving(type value) { return false; }
59 static saved_type save(CodeGenFunction &CGF, type value) { return value; }
60 static type restore(CodeGenFunction &CGF, saved_type value) { return value; }
61};
62
63/// A metaprogramming class for ensuring that a value will dominate an
64/// arbitrary position in a function.
65template <class T> struct DominatingValue : InvariantValue<T> {};
66
67template <class T, bool mightBeInstruction =
Stephen Hines651f13c2014-04-23 16:59:28 -070068 std::is_base_of<llvm::Value, T>::value &&
69 !std::is_base_of<llvm::Constant, T>::value &&
70 !std::is_base_of<llvm::BasicBlock, T>::value>
Reid Kleckner43a75fc2013-06-19 17:07:50 +000071struct DominatingPointer;
72template <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {};
73// template <class T> struct DominatingPointer<T,true> at end of file
74
75template <class T> struct DominatingValue<T*> : DominatingPointer<T> {};
76
Stephen Hines176edba2014-12-01 14:53:08 -080077enum CleanupKind : unsigned {
Stephen Hines0e2c34f2015-03-23 12:09:02 -070078 /// Denotes a cleanup that should run when a scope is exited using exceptional
79 /// control flow (a throw statement leading to stack unwinding, ).
Reid Kleckner43a75fc2013-06-19 17:07:50 +000080 EHCleanup = 0x1,
Stephen Hines0e2c34f2015-03-23 12:09:02 -070081
82 /// Denotes a cleanup that should run when a scope is exited using normal
83 /// control flow (falling off the end of the scope, return, goto, ...).
Reid Kleckner43a75fc2013-06-19 17:07:50 +000084 NormalCleanup = 0x2,
Stephen Hines0e2c34f2015-03-23 12:09:02 -070085
Reid Kleckner43a75fc2013-06-19 17:07:50 +000086 NormalAndEHCleanup = EHCleanup | NormalCleanup,
87
88 InactiveCleanup = 0x4,
89 InactiveEHCleanup = EHCleanup | InactiveCleanup,
90 InactiveNormalCleanup = NormalCleanup | InactiveCleanup,
91 InactiveNormalAndEHCleanup = NormalAndEHCleanup | InactiveCleanup
92};
93
94/// A stack of scopes which respond to exceptions, including cleanups
95/// and catch blocks.
96class EHScopeStack {
97public:
98 /// A saved depth on the scope stack. This is necessary because
99 /// pushing scopes onto the stack invalidates iterators.
100 class stable_iterator {
101 friend class EHScopeStack;
102
103 /// Offset from StartOfData to EndOfBuffer.
104 ptrdiff_t Size;
105
106 stable_iterator(ptrdiff_t Size) : Size(Size) {}
107
108 public:
109 static stable_iterator invalid() { return stable_iterator(-1); }
110 stable_iterator() : Size(-1) {}
111
112 bool isValid() const { return Size >= 0; }
113
114 /// Returns true if this scope encloses I.
115 /// Returns false if I is invalid.
116 /// This scope must be valid.
117 bool encloses(stable_iterator I) const { return Size <= I.Size; }
118
119 /// Returns true if this scope strictly encloses I: that is,
120 /// if it encloses I and is not I.
121 /// Returns false is I is invalid.
122 /// This scope must be valid.
123 bool strictlyEncloses(stable_iterator I) const { return Size < I.Size; }
124
125 friend bool operator==(stable_iterator A, stable_iterator B) {
126 return A.Size == B.Size;
127 }
128 friend bool operator!=(stable_iterator A, stable_iterator B) {
129 return A.Size != B.Size;
130 }
131 };
132
133 /// Information for lazily generating a cleanup. Subclasses must be
134 /// POD-like: cleanups will not be destructed, and they will be
135 /// allocated on the cleanup stack and freely copied and moved
136 /// around.
137 ///
138 /// Cleanup implementations should generally be declared in an
139 /// anonymous namespace.
140 class Cleanup {
141 // Anchor the construction vtable.
142 virtual void anchor();
143 public:
144 /// Generation flags.
145 class Flags {
146 enum {
147 F_IsForEH = 0x1,
148 F_IsNormalCleanupKind = 0x2,
149 F_IsEHCleanupKind = 0x4
150 };
151 unsigned flags;
152
153 public:
154 Flags() : flags(0) {}
155
156 /// isForEH - true if the current emission is for an EH cleanup.
157 bool isForEHCleanup() const { return flags & F_IsForEH; }
158 bool isForNormalCleanup() const { return !isForEHCleanup(); }
159 void setIsForEHCleanup() { flags |= F_IsForEH; }
160
161 bool isNormalCleanupKind() const { return flags & F_IsNormalCleanupKind; }
162 void setIsNormalCleanupKind() { flags |= F_IsNormalCleanupKind; }
163
164 /// isEHCleanupKind - true if the cleanup was pushed as an EH
165 /// cleanup.
166 bool isEHCleanupKind() const { return flags & F_IsEHCleanupKind; }
167 void setIsEHCleanupKind() { flags |= F_IsEHCleanupKind; }
168 };
169
170 // Provide a virtual destructor to suppress a very common warning
171 // that unfortunately cannot be suppressed without this. Cleanups
172 // should not rely on this destructor ever being called.
173 virtual ~Cleanup() {}
174
175 /// Emit the cleanup. For normal cleanups, this is run in the
176 /// same EH context as when the cleanup was pushed, i.e. the
177 /// immediately-enclosing context of the cleanup scope. For
178 /// EH cleanups, this is run in a terminate context.
179 ///
180 // \param flags cleanup kind.
181 virtual void Emit(CodeGenFunction &CGF, Flags flags) = 0;
182 };
183
184 /// ConditionalCleanupN stores the saved form of its N parameters,
185 /// then restores them and performs the cleanup.
186 template <class T, class A0>
187 class ConditionalCleanup1 : public Cleanup {
188 typedef typename DominatingValue<A0>::saved_type A0_saved;
189 A0_saved a0_saved;
190
Stephen Hines651f13c2014-04-23 16:59:28 -0700191 void Emit(CodeGenFunction &CGF, Flags flags) override {
Reid Kleckner43a75fc2013-06-19 17:07:50 +0000192 A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
193 T(a0).Emit(CGF, flags);
194 }
195
196 public:
197 ConditionalCleanup1(A0_saved a0)
198 : a0_saved(a0) {}
199 };
200
201 template <class T, class A0, class A1>
202 class ConditionalCleanup2 : public Cleanup {
203 typedef typename DominatingValue<A0>::saved_type A0_saved;
204 typedef typename DominatingValue<A1>::saved_type A1_saved;
205 A0_saved a0_saved;
206 A1_saved a1_saved;
207
Stephen Hines651f13c2014-04-23 16:59:28 -0700208 void Emit(CodeGenFunction &CGF, Flags flags) override {
Reid Kleckner43a75fc2013-06-19 17:07:50 +0000209 A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
210 A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
211 T(a0, a1).Emit(CGF, flags);
212 }
213
214 public:
215 ConditionalCleanup2(A0_saved a0, A1_saved a1)
216 : a0_saved(a0), a1_saved(a1) {}
217 };
218
219 template <class T, class A0, class A1, class A2>
220 class ConditionalCleanup3 : public Cleanup {
221 typedef typename DominatingValue<A0>::saved_type A0_saved;
222 typedef typename DominatingValue<A1>::saved_type A1_saved;
223 typedef typename DominatingValue<A2>::saved_type A2_saved;
224 A0_saved a0_saved;
225 A1_saved a1_saved;
226 A2_saved a2_saved;
227
Stephen Hines651f13c2014-04-23 16:59:28 -0700228 void Emit(CodeGenFunction &CGF, Flags flags) override {
Reid Kleckner43a75fc2013-06-19 17:07:50 +0000229 A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
230 A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
231 A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
232 T(a0, a1, a2).Emit(CGF, flags);
233 }
234
235 public:
236 ConditionalCleanup3(A0_saved a0, A1_saved a1, A2_saved a2)
237 : a0_saved(a0), a1_saved(a1), a2_saved(a2) {}
238 };
239
240 template <class T, class A0, class A1, class A2, class A3>
241 class ConditionalCleanup4 : public Cleanup {
242 typedef typename DominatingValue<A0>::saved_type A0_saved;
243 typedef typename DominatingValue<A1>::saved_type A1_saved;
244 typedef typename DominatingValue<A2>::saved_type A2_saved;
245 typedef typename DominatingValue<A3>::saved_type A3_saved;
246 A0_saved a0_saved;
247 A1_saved a1_saved;
248 A2_saved a2_saved;
249 A3_saved a3_saved;
250
Stephen Hines651f13c2014-04-23 16:59:28 -0700251 void Emit(CodeGenFunction &CGF, Flags flags) override {
Reid Kleckner43a75fc2013-06-19 17:07:50 +0000252 A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
253 A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
254 A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
255 A3 a3 = DominatingValue<A3>::restore(CGF, a3_saved);
256 T(a0, a1, a2, a3).Emit(CGF, flags);
257 }
258
259 public:
260 ConditionalCleanup4(A0_saved a0, A1_saved a1, A2_saved a2, A3_saved a3)
261 : a0_saved(a0), a1_saved(a1), a2_saved(a2), a3_saved(a3) {}
262 };
263
264private:
265 // The implementation for this class is in CGException.h and
266 // CGException.cpp; the definition is here because it's used as a
267 // member of CodeGenFunction.
268
269 /// The start of the scope-stack buffer, i.e. the allocated pointer
270 /// for the buffer. All of these pointers are either simultaneously
271 /// null or simultaneously valid.
272 char *StartOfBuffer;
273
274 /// The end of the buffer.
275 char *EndOfBuffer;
276
277 /// The first valid entry in the buffer.
278 char *StartOfData;
279
280 /// The innermost normal cleanup on the stack.
281 stable_iterator InnermostNormalCleanup;
282
283 /// The innermost EH scope on the stack.
284 stable_iterator InnermostEHScope;
285
286 /// The current set of branch fixups. A branch fixup is a jump to
287 /// an as-yet unemitted label, i.e. a label for which we don't yet
288 /// know the EH stack depth. Whenever we pop a cleanup, we have
289 /// to thread all the current branch fixups through it.
290 ///
291 /// Fixups are recorded as the Use of the respective branch or
292 /// switch statement. The use points to the final destination.
293 /// When popping out of a cleanup, these uses are threaded through
294 /// the cleanup and adjusted to point to the new cleanup.
295 ///
296 /// Note that branches are allowed to jump into protected scopes
297 /// in certain situations; e.g. the following code is legal:
298 /// struct A { ~A(); }; // trivial ctor, non-trivial dtor
299 /// goto foo;
300 /// A a;
301 /// foo:
302 /// bar();
303 SmallVector<BranchFixup, 8> BranchFixups;
304
305 char *allocate(size_t Size);
306
307 void *pushCleanup(CleanupKind K, size_t DataSize);
308
309public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700310 EHScopeStack() : StartOfBuffer(nullptr), EndOfBuffer(nullptr),
311 StartOfData(nullptr), InnermostNormalCleanup(stable_end()),
Reid Kleckner43a75fc2013-06-19 17:07:50 +0000312 InnermostEHScope(stable_end()) {}
313 ~EHScopeStack() { delete[] StartOfBuffer; }
314
Reid Kleckner43a75fc2013-06-19 17:07:50 +0000315 /// Push a lazily-created cleanup on the stack.
Stephen Hines0e2c34f2015-03-23 12:09:02 -0700316 template <class T, class... As> void pushCleanup(CleanupKind Kind, As... A) {
Reid Kleckner43a75fc2013-06-19 17:07:50 +0000317 void *Buffer = pushCleanup(Kind, sizeof(T));
Stephen Hines0e2c34f2015-03-23 12:09:02 -0700318 Cleanup *Obj = new (Buffer) T(A...);
Reid Kleckner43a75fc2013-06-19 17:07:50 +0000319 (void) Obj;
320 }
321
322 // Feel free to add more variants of the following:
323
324 /// Push a cleanup with non-constant storage requirements on the
325 /// stack. The cleanup type must provide an additional static method:
326 /// static size_t getExtraSize(size_t);
327 /// The argument to this method will be the value N, which will also
328 /// be passed as the first argument to the constructor.
329 ///
330 /// The data stored in the extra storage must obey the same
331 /// restrictions as normal cleanup member data.
332 ///
333 /// The pointer returned from this method is valid until the cleanup
334 /// stack is modified.
Stephen Hines0e2c34f2015-03-23 12:09:02 -0700335 template <class T, class... As>
336 T *pushCleanupWithExtra(CleanupKind Kind, size_t N, As... A) {
Reid Kleckner43a75fc2013-06-19 17:07:50 +0000337 void *Buffer = pushCleanup(Kind, sizeof(T) + T::getExtraSize(N));
Stephen Hines0e2c34f2015-03-23 12:09:02 -0700338 return new (Buffer) T(N, A...);
Reid Kleckner43a75fc2013-06-19 17:07:50 +0000339 }
340
341 void pushCopyOfCleanup(CleanupKind Kind, const void *Cleanup, size_t Size) {
342 void *Buffer = pushCleanup(Kind, Size);
343 std::memcpy(Buffer, Cleanup, Size);
344 }
345
346 /// Pops a cleanup scope off the stack. This is private to CGCleanup.cpp.
347 void popCleanup();
348
349 /// Push a set of catch handlers on the stack. The catch is
350 /// uninitialized and will need to have the given number of handlers
351 /// set on it.
352 class EHCatchScope *pushCatch(unsigned NumHandlers);
353
354 /// Pops a catch scope off the stack. This is private to CGException.cpp.
355 void popCatch();
356
357 /// Push an exceptions filter on the stack.
358 class EHFilterScope *pushFilter(unsigned NumFilters);
359
360 /// Pops an exceptions filter off the stack.
361 void popFilter();
362
363 /// Push a terminate handler on the stack.
364 void pushTerminate();
365
366 /// Pops a terminate handler off the stack.
367 void popTerminate();
368
369 /// Determines whether the exception-scopes stack is empty.
370 bool empty() const { return StartOfData == EndOfBuffer; }
371
372 bool requiresLandingPad() const {
373 return InnermostEHScope != stable_end();
374 }
375
376 /// Determines whether there are any normal cleanups on the stack.
377 bool hasNormalCleanups() const {
378 return InnermostNormalCleanup != stable_end();
379 }
380
381 /// Returns the innermost normal cleanup on the stack, or
382 /// stable_end() if there are no normal cleanups.
383 stable_iterator getInnermostNormalCleanup() const {
384 return InnermostNormalCleanup;
385 }
386 stable_iterator getInnermostActiveNormalCleanup() const;
387
388 stable_iterator getInnermostEHScope() const {
389 return InnermostEHScope;
390 }
391
392 stable_iterator getInnermostActiveEHScope() const;
393
394 /// An unstable reference to a scope-stack depth. Invalidated by
395 /// pushes but not pops.
396 class iterator;
397
398 /// Returns an iterator pointing to the innermost EH scope.
399 iterator begin() const;
400
401 /// Returns an iterator pointing to the outermost EH scope.
402 iterator end() const;
403
404 /// Create a stable reference to the top of the EH stack. The
405 /// returned reference is valid until that scope is popped off the
406 /// stack.
407 stable_iterator stable_begin() const {
408 return stable_iterator(EndOfBuffer - StartOfData);
409 }
410
411 /// Create a stable reference to the bottom of the EH stack.
412 static stable_iterator stable_end() {
413 return stable_iterator(0);
414 }
415
416 /// Translates an iterator into a stable_iterator.
417 stable_iterator stabilize(iterator it) const;
418
419 /// Turn a stable reference to a scope depth into a unstable pointer
420 /// to the EH stack.
421 iterator find(stable_iterator save) const;
422
423 /// Removes the cleanup pointed to by the given stable_iterator.
424 void removeCleanup(stable_iterator save);
425
426 /// Add a branch fixup to the current cleanup scope.
427 BranchFixup &addBranchFixup() {
428 assert(hasNormalCleanups() && "adding fixup in scope without cleanups");
429 BranchFixups.push_back(BranchFixup());
430 return BranchFixups.back();
431 }
432
433 unsigned getNumBranchFixups() const { return BranchFixups.size(); }
434 BranchFixup &getBranchFixup(unsigned I) {
435 assert(I < getNumBranchFixups());
436 return BranchFixups[I];
437 }
438
439 /// Pops lazily-removed fixups from the end of the list. This
440 /// should only be called by procedures which have just popped a
441 /// cleanup or resolved one or more fixups.
442 void popNullFixups();
443
444 /// Clears the branch-fixups list. This should only be called by
445 /// ResolveAllBranchFixups.
446 void clearFixups() { BranchFixups.clear(); }
447};
448
449} // namespace CodeGen
450} // namespace clang
451
452#endif