summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp32
-rw-r--r--clang/lib/CodeGen/CGException.cpp15
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp32
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;
OpenPOWER on IntegriCloud