aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CodeGenFunction.h
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-07-13 20:32:21 +0000
committerJohn McCall <rjmccall@apple.com>2010-07-13 20:32:21 +0000
commitda65ea86482bc116906edfb9ba1d7124f76cc867 (patch)
treefc92862d7909d8eeaa367fa4fe686a875a934bf8 /lib/CodeGen/CodeGenFunction.h
parent77a3c9ede5cdb26b5eb3001e82bb0a36ca997e1f (diff)
Teach IR generation how to lazily emit cleanups. This has a lot of advantages,
mostly in avoiding unnecessary work at compile time but also in producing more sensible block orderings. Move the destructor cleanups for local variables over to use lazy cleanups. Eventually all cleanups will do this; for now we have some awkward code duplication. Tell IR generation just to never produce landing pads in -fno-exceptions. This is a much more comprehensive solution to a problem which previously was half-solved by checks in most cleanup-generation spots. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108270 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CodeGenFunction.h')
-rw-r--r--lib/CodeGen/CodeGenFunction.h54
1 files changed, 52 insertions, 2 deletions
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 26fb882e56..ce3453ae5e 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -95,6 +95,8 @@ struct BranchFixup {
unsigned LatestBranchIndex;
};
+enum CleanupKind { NormalAndEHCleanup, EHCleanup, NormalCleanup };
+
/// A stack of scopes which respond to exceptions, including cleanups
/// and catch blocks.
class EHScopeStack {
@@ -123,6 +125,28 @@ public:
}
};
+ /// A lazy cleanup. These will be allocated on the cleanup stack
+ /// and so must be trivially copyable. We "enforce" this by
+ /// providing no virtual destructor so that subclasses will be
+ /// encouraged to contain no non-POD types.
+ ///
+ /// LazyCleanup implementations should generally be declared in an
+ /// anonymous namespace.
+ class LazyCleanup {
+ // Anchor the construction vtable.
+ virtual void _anchor();
+
+ public:
+ /// Emit the cleanup. For normal cleanups, this is run in the
+ /// same EH context as when the cleanup was pushed, i.e. the
+ /// immediately-enclosing context of the cleanup scope. For
+ /// EH cleanups, this is run in a terminate context.
+ ///
+ // \param IsForEHCleanup true if this is for an EH cleanup, false
+ /// if for a normal cleanup.
+ virtual void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) = 0;
+ };
+
private:
// The implementation for this class is in CGException.h and
// CGException.cpp; the definition is here because it's used as a
@@ -171,6 +195,8 @@ private:
void popNullFixups();
+ void *pushLazyCleanup(CleanupKind K, size_t DataSize);
+
public:
EHScopeStack() : StartOfBuffer(0), EndOfBuffer(0), StartOfData(0),
InnermostNormalCleanup(stable_end()),
@@ -178,6 +204,32 @@ public:
CatchDepth(0) {}
~EHScopeStack() { delete[] StartOfBuffer; }
+ // Variadic templates would make this not terrible.
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0, class A1>
+ void pushLazyCleanup(CleanupKind Kind, A0 a0, A1 a1) {
+ void *Buffer = pushLazyCleanup(Kind, sizeof(T));
+ LazyCleanup *Obj = new(Buffer) T(a0, a1);
+ (void) Obj;
+ }
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0, class A1, class A2>
+ void pushLazyCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2) {
+ void *Buffer = pushLazyCleanup(Kind, sizeof(T));
+ LazyCleanup *Obj = new(Buffer) T(a0, a1, a2);
+ (void) Obj;
+ }
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0, class A1, class A2, class A3>
+ void pushLazyCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3) {
+ void *Buffer = pushLazyCleanup(Kind, sizeof(T));
+ LazyCleanup *Obj = new(Buffer) T(a0, a1, a2, a3);
+ (void) Obj;
+ }
+
/// Push a cleanup on the stack.
void pushCleanup(llvm::BasicBlock *NormalEntry,
llvm::BasicBlock *NormalExit,
@@ -375,8 +427,6 @@ public:
llvm::Constant *RethrowFn);
void ExitFinallyBlock(FinallyInfo &FinallyInfo);
- enum CleanupKind { NormalAndEHCleanup, EHCleanup, NormalCleanup };
-
/// PushDestructorCleanup - Push a cleanup to call the
/// complete-object destructor of an object of the given type at the
/// given address. Does nothing if T is not a C++ class type with a