diff options
author | John McCall <rjmccall@apple.com> | 2010-07-13 20:32:21 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-07-13 20:32:21 +0000 |
commit | da65ea86482bc116906edfb9ba1d7124f76cc867 (patch) | |
tree | fc92862d7909d8eeaa367fa4fe686a875a934bf8 /lib/CodeGen/CodeGenFunction.h | |
parent | 77a3c9ede5cdb26b5eb3001e82bb0a36ca997e1f (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.h | 54 |
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 |