summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGException.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGException.cpp')
-rw-r--r--lib/CodeGen/CGException.cpp68
1 files changed, 23 insertions, 45 deletions
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index d956c1c..142cb81 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -427,6 +427,26 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
}
void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
+ CXXTryStmtInfo Info = EnterCXXTryStmt(S);
+ EmitStmt(S.getTryBlock());
+ ExitCXXTryStmt(S, Info);
+}
+
+CodeGenFunction::CXXTryStmtInfo
+CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S) {
+ CXXTryStmtInfo Info;
+ Info.SavedLandingPad = getInvokeDest();
+ Info.HandlerBlock = createBasicBlock("try.handler");
+ Info.FinallyBlock = createBasicBlock("finally");
+
+ PushCleanupBlock(Info.FinallyBlock);
+ setInvokeDest(Info.HandlerBlock);
+
+ return Info;
+}
+
+void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S,
+ CXXTryStmtInfo TryInfo) {
// Pointer to the personality function
llvm::Constant *Personality =
CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
@@ -439,54 +459,12 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
llvm::Value *llvm_eh_selector =
CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
- llvm::BasicBlock *PrevLandingPad = getInvokeDest();
- llvm::BasicBlock *TryHandler = createBasicBlock("try.handler");
- llvm::BasicBlock *FinallyBlock = createBasicBlock("finally");
+ llvm::BasicBlock *PrevLandingPad = TryInfo.SavedLandingPad;
+ llvm::BasicBlock *TryHandler = TryInfo.HandlerBlock;
+ llvm::BasicBlock *FinallyBlock = TryInfo.FinallyBlock;
llvm::BasicBlock *FinallyRethrow = createBasicBlock("finally.throw");
llvm::BasicBlock *FinallyEnd = createBasicBlock("finally.end");
- // Push an EH context entry, used for handling rethrows.
- PushCleanupBlock(FinallyBlock);
-
- // Emit the statements in the try {} block
- setInvokeDest(TryHandler);
-
- // FIXME: We should not have to do this here. The AST should have the member
- // initializers under the CXXTryStmt's TryBlock.
- if (OuterTryBlock == &S) {
- GlobalDecl GD = CurGD;
- const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
-
- if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
- size_t OldCleanupStackSize = CleanupEntries.size();
- EmitCtorPrologue(CD, CurGD.getCtorType());
- EmitStmt(S.getTryBlock());
-
- // If any of the member initializers are temporaries bound to references
- // make sure to emit their destructors.
- EmitCleanupBlocks(OldCleanupStackSize);
- } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
- llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue");
- PushCleanupBlock(DtorEpilogue);
-
- InitializeVtablePtrs(DD->getParent());
- EmitStmt(S.getTryBlock());
-
- CleanupBlockInfo Info = PopCleanupBlock();
-
- assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
- EmitBlock(DtorEpilogue);
- EmitDtorEpilogue(DD, GD.getDtorType());
-
- if (Info.SwitchBlock)
- EmitBlock(Info.SwitchBlock);
- if (Info.EndBlock)
- EmitBlock(Info.EndBlock);
- } else
- EmitStmt(S.getTryBlock());
- } else
- EmitStmt(S.getTryBlock());
-
// Jump to end if there is no exception
EmitBranchThroughCleanup(FinallyEnd);
OpenPOWER on IntegriCloud