From 6a1e0eb557d47e85185e09bdf8721f53f4bf9c9c Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Fri, 4 Dec 2009 23:26:17 +0000 Subject: [PATCH] Add support for function try blocks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90622 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGException.cpp | 36 ++++++++++++++++++++++++++++++++- lib/CodeGen/CodeGenFunction.cpp | 11 +++++++++- lib/CodeGen/CodeGenFunction.h | 6 ++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 62064ecf41..73f66ccd3f 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -270,6 +270,7 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { EmitStmt(S.getTryBlock()); return; } + // FIXME: The below is still just a sketch of the code we need. // Pointer to the personality function llvm::Constant *Personality = @@ -295,7 +296,40 @@ void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { // Emit the statements in the try {} block setInvokeDest(TryHandler); - EmitStmt(S.getTryBlock()); + // 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(GD.getDecl()); + + if (const CXXConstructorDecl *CD = dyn_cast(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(FD)) { + llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue"); + PushCleanupBlock(DtorEpilogue); + + 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); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 88f02a9738..d35c962112 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -19,6 +19,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/StmtCXX.h" #include "llvm/Target/TargetData.h" using namespace clang; using namespace CodeGen; @@ -255,6 +256,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, FunctionArgList Args; + CurGD = GD; + OuterTryBlock = 0; if (const CXXMethodDecl *MD = dyn_cast(FD)) { if (MD->isInstance()) { // Create the implicit 'this' decl. @@ -286,7 +289,6 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, FProto->getArgType(i))); } - // FIXME: Support CXXTryStmt here, too. if (const CompoundStmt *S = FD->getCompoundBody()) { StartFunction(GD, FD->getResultType(), Fn, Args, S->getLBracLoc()); @@ -351,6 +353,13 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, } else { assert(false && "Cannot synthesize unknown implicit function"); } + } else if (const Stmt *S = FD->getBody()) { + if (const CXXTryStmt *TS = dyn_cast(S)) { + OuterTryBlock = TS; + StartFunction(GD, FD->getResultType(), Fn, Args, TS->getTryLoc()); + EmitStmt(TS); + FinishFunction(TS->getEndLoc()); + } } // Destroy the 'this' declaration. diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index bf791abfbc..8a386dec8c 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -88,6 +88,12 @@ public: QualType FnRetTy; llvm::Function *CurFn; + /// CurGD - The GlobalDecl for the current function being compiled. + GlobalDecl CurGD; + /// OuterTryBlock - This is the address of the outter most try block, 0 + /// otherwise. + const Stmt *OuterTryBlock; + /// ReturnBlock - Unified return block. llvm::BasicBlock *ReturnBlock; /// ReturnValue - The temporary alloca to hold the return value. This is null -- 2.40.0