diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 32 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 15 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 32 |
3 files changed, 52 insertions, 27 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 46873bf0621..0b7f3a06a70 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -357,11 +357,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Builder.CreateCall(F)); } case Builtin::BI__builtin_unreachable: { - if (CatchUndefined && HaveInsertPoint()) + if (CatchUndefined) EmitBranch(getTrapBB()); - Value *V = Builder.CreateUnreachable(); - Builder.ClearInsertionPoint(); - return RValue::get(V); + else + Builder.CreateUnreachable(); + + // We do need to preserve an insertion point. + CGF.EmitBlock(createBasicBlock("unreachable.cont")); + + return RValue::get(0); } case Builtin::BI__builtin_powi: @@ -629,9 +633,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, : Intrinsic::eh_return_i64, 0, 0); Builder.CreateCall2(F, Int, Ptr); - Value *V = Builder.CreateUnreachable(); - Builder.ClearInsertionPoint(); - return RValue::get(V); + Builder.CreateUnreachable(); + + // We do need to preserve an insertion point. + CGF.EmitBlock(CGF.createBasicBlock("builtin_eh_return.cont")); + + return RValue::get(0); } case Builtin::BI__builtin_unwind_init: { Value *F = CGM.getIntrinsic(Intrinsic::eh_unwind_init, 0, 0); @@ -694,10 +701,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, // Call LLVM's EH longjmp, which is lightweight. Builder.CreateCall(CGM.getIntrinsic(Intrinsic::eh_sjlj_longjmp), Buf); - // longjmp doesn't return; mark this as unreachable - Value *V = Builder.CreateUnreachable(); - Builder.ClearInsertionPoint(); - return RValue::get(V); + // longjmp doesn't return; mark this as unreachable. + Builder.CreateUnreachable(); + + // We do need to preserve an insertion point. + CGF.EmitBlock(CGF.createBasicBlock("longjmp.cont")); + + return RValue::get(0); } case Builtin::BI__sync_fetch_and_add: case Builtin::BI__sync_fetch_and_sub: diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 11e5e645280..252e547b5d1 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -577,8 +577,10 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { Builder.CreateUnreachable(); } - // Clear the insertion point to indicate we are in unreachable code. - Builder.ClearInsertionPoint(); + // throw is an expression, and the expression emitters expect us + // to leave ourselves at a valid insertion point. + EmitBlock(createBasicBlock("throw.cont")); + return; } @@ -627,12 +629,9 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { Builder.CreateUnreachable(); } - // Clear the insertion point to indicate we are in unreachable code. - Builder.ClearInsertionPoint(); - - // FIXME: For now, emit a dummy basic block because expr emitters in generally - // are not ready to handle emitting expressions at unreachable points. - EnsureInsertPoint(); + // throw is an expression, and the expression emitters expect us + // to leave ourselves at a valid insertion point. + EmitBlock(createBasicBlock("throw.cont")); } void CodeGenFunction::EmitStartEHSpec(const Decl *D) { diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index dbef09f63a8..b0278c7d02d 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -89,18 +89,34 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { #define EXPR(Type, Base) \ case Stmt::Type##Class: #include "clang/AST/StmtNodes.inc" + { + // Remember the block we came in on. + llvm::BasicBlock *incoming = Builder.GetInsertBlock(); + assert(incoming && "expression emission must have an insertion point"); + EmitIgnoredExpr(cast<Expr>(S)); - // Expression emitters don't handle unreachable blocks yet, so look for one - // explicitly here. This handles the common case of a call to a noreturn - // function. - if (llvm::BasicBlock *CurBB = Builder.GetInsertBlock()) { - if (CurBB->empty() && CurBB->use_empty()) { - CurBB->eraseFromParent(); - Builder.ClearInsertionPoint(); - } + llvm::BasicBlock *outgoing = Builder.GetInsertBlock(); + assert(outgoing && "expression emission cleared block!"); + + // The expression emitters assume (reasonably!) that the insertion + // point is always set. To maintain that, the call-emission code + // for noreturn functions has to enter a new block with no + // predecessors. We want to kill that block and mark the current + // insertion point unreachable in the common case of a call like + // "exit();". Since expression emission doesn't otherwise create + // blocks with no predecessors, we can just test for that. + // However, we must be careful not to do this to our incoming + // block, because *statement* emission does sometimes create + // reachable blocks which will have no predecessors until later in + // the function. This occurs with, e.g., labels that are not + // reachable by fallthrough. + if (incoming != outgoing && outgoing->use_empty()) { + outgoing->eraseFromParent(); + Builder.ClearInsertionPoint(); } break; + } case Stmt::IndirectGotoStmtClass: EmitIndirectGotoStmt(cast<IndirectGotoStmt>(*S)); break; |