aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGExprComplex.cpp1
-rw-r--r--lib/CodeGen/CGExprScalar.cpp1
-rw-r--r--lib/CodeGen/CGObjC.cpp1
-rw-r--r--lib/CodeGen/CGObjCMac.cpp12
-rw-r--r--lib/CodeGen/CGStmt.cpp42
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp8
-rw-r--r--lib/CodeGen/CodeGenFunction.h52
7 files changed, 68 insertions, 49 deletions
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index b4ca6c0f57..afe6fc2329 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -461,6 +461,7 @@ ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
CGF.EmitStmt(E->getLHS());
+ CGF.EnsureInsertPoint();
return Visit(E->getRHS());
}
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index bf22902b68..339430cf61 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -1101,6 +1101,7 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) {
CGF.EmitStmt(E->getLHS());
+ CGF.EnsureInsertPoint();
return Visit(E->getRHS());
}
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 9079284052..3ffdb4d866 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -334,6 +334,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S)
if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
EmitStmt(SD);
+ assert(HaveInsertPoint() && "DeclStmt destroyed insert point!");
const ScopedDecl* D = SD->getSolitaryDecl();
ElementTy = cast<ValueDecl>(D)->getType();
DeclAddress = LocalDeclMap[D];
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 8722e15dc0..70b9b49f7d 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -1621,6 +1621,7 @@ void CGObjCMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
if (AllMatched) {
if (CatchParam) {
CGF.EmitStmt(CatchParam);
+ assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(VD));
}
@@ -1648,6 +1649,7 @@ void CGObjCMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
// Emit the @catch block.
CGF.EmitBlock(MatchedBlock);
CGF.EmitStmt(CatchParam);
+ assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
llvm::Value *Tmp =
CGF.Builder.CreateBitCast(Caught, CGF.ConvertType(VD->getType()),
@@ -1717,15 +1719,15 @@ void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
CGF.Builder.CreateCall(ObjCTypes.ExceptionThrowFn, ExceptionAsObject);
CGF.Builder.CreateUnreachable();
- CGF.EmitDummyBlock();
+
+ // Clear the insertion point to indicate we are in unreachable code.
+ CGF.Builder.ClearInsertionPoint();
}
void CodeGenFunction::EmitJumpThroughFinally(ObjCEHEntry *E,
llvm::BasicBlock *Dst,
bool ExecuteTryExit) {
- llvm::BasicBlock *Src = Builder.GetInsertBlock();
-
- if (!Src || isDummyBlock(Src))
+ if (!HaveInsertPoint())
return;
// Find the destination code for this block. We always use 0 for the
@@ -1746,7 +1748,7 @@ void CodeGenFunction::EmitJumpThroughFinally(ObjCEHEntry *E,
// Set the destination code and branch.
Builder.CreateStore(ID, E->DestCode);
- Builder.CreateBr(ExecuteTryExit ? E->FinallyBlock : E->FinallyNoExit);
+ EmitBranch(ExecuteTryExit ? E->FinallyBlock : E->FinallyNoExit);
}
/* *** Private Interface *** */
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 97a7a05768..daad3f5e79 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -27,6 +27,13 @@ using namespace CodeGen;
void CodeGenFunction::EmitStmt(const Stmt *S) {
assert(S && "Null statement?");
+
+ // If we happen to be at an unreachable point just create a dummy
+ // basic block to hold the code. We could change parts of irgen to
+ // simply not generate this code, but this situation is rare and
+ // probably not worth the effort.
+ // FIXME: Verify previous performance/effort claim.
+ EnsureInsertPoint();
// Generate stoppoints if we are emitting debug info.
// Beginning of a Compound Statement (e.g. an opening '{') does not produce
@@ -128,6 +135,7 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
EmitStmt(*I);
if (DI) {
+ EnsureInsertPoint();
DI->setLocation(S.getRBracLoc());
DI->EmitRegionEnd(CurFn, Builder);
}
@@ -145,6 +153,8 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
LastStmt = LS->getSubStmt();
}
+ EnsureInsertPoint();
+
return EmitAnyExpr(cast<Expr>(LastStmt), AggLoc);
}
@@ -164,10 +174,6 @@ void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) {
if (!CurBB || CurBB->getTerminator()) {
// If there is no insert point or the previous block is already
// terminated, don't touch it.
- } else if (isDummyBlock(CurBB)) {
- // If the last block was an empty placeholder, remove it now.
- // TODO: cache and reuse these.
- CurBB->eraseFromParent();
} else {
// Otherwise, create a fall-through branch.
Builder.CreateBr(Target);
@@ -176,10 +182,6 @@ void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) {
Builder.ClearInsertionPoint();
}
-void CodeGenFunction::EmitDummyBlock() {
- EmitBlock(createBasicBlock());
-}
-
void CodeGenFunction::EmitLabel(const LabelStmt &S) {
llvm::BasicBlock *NextBB = getBasicBlockForLabel(&S);
EmitBlock(NextBB);
@@ -199,10 +201,6 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
}
EmitBranch(getBasicBlockForLabel(S.getLabel()));
-
- // Emit a block after the branch so that dead code after a goto has some place
- // to go.
- EmitDummyBlock();
}
void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
@@ -221,9 +219,8 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
llvm::SwitchInst *I = Builder.CreateSwitch(V, Builder.GetInsertBlock());
IndirectSwitches.push_back(I);
- // Emit a block after the branch so that dead code after a goto has some place
- // to go.
- EmitDummyBlock();
+ // Clear the insertion point to indicate we are in unreachable code.
+ Builder.ClearInsertionPoint();
}
void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
@@ -445,10 +442,6 @@ void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
StoreComplexToAddr(RV.getComplexVal(), ReturnValue, false);
}
EmitBranch(ReturnBlock);
-
- // Emit a block after the branch so that dead code after a return has some
- // place to go.
- EmitDummyBlock();
}
/// EmitReturnStmt - Note that due to GCC extensions, this can have an operand
@@ -485,10 +478,6 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
}
EmitBranch(ReturnBlock);
-
- // Emit a block after the branch so that dead code after a return has some
- // place to go.
- EmitDummyBlock();
}
void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) {
@@ -502,7 +491,6 @@ void CodeGenFunction::EmitBreakStmt() {
llvm::BasicBlock *Block = BreakContinueStack.back().BreakBlock;
EmitBranch(Block);
- EmitDummyBlock();
}
void CodeGenFunction::EmitContinueStmt() {
@@ -510,7 +498,6 @@ void CodeGenFunction::EmitContinueStmt() {
llvm::BasicBlock *Block = BreakContinueStack.back().ContinueBlock;
EmitBranch(Block);
- EmitDummyBlock();
}
/// EmitCaseStmtRange - If case statement range is not too big then
@@ -566,7 +553,10 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) {
Builder.CreateCondBr(Cond, CaseDest, FalseDest);
// Restore the appropriate insertion point.
- Builder.SetInsertPoint(RestoreBB);
+ if (RestoreBB)
+ Builder.SetInsertPoint(RestoreBB);
+ else
+ Builder.ClearInsertionPoint();
}
void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) {
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index bcd1e09800..d5e8c8a588 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -156,14 +156,6 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD,
}
}
-/// isDummyBlock - Return true if BB is an empty basic block
-/// with no predecessors.
-bool CodeGenFunction::isDummyBlock(const llvm::BasicBlock *BB) {
- if (BB->empty() && pred_begin(BB) == pred_end(BB) && !BB->hasName())
- return true;
- return false;
-}
-
/// ContainsLabel - Return true if the statement contains a label in it. If
/// this statement is not executed normally, it not containing a label means
/// that we can just remove the code.
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index b833380e49..1b573700da 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -119,7 +119,8 @@ public:
/// EmitJumpThroughFinally - Emit a branch from the current insert
/// point through the finally handling code for \arg Entry and then
- /// on to \arg Dest.
+ /// on to \arg Dest. It is legal to call this function even if there
+ /// is no current insertion point.
///
/// \param ExecuteTryExit - When true, the try_exit runtime function
/// should be called prior to executing the finally code.
@@ -186,6 +187,10 @@ public:
llvm::Function *Fn,
const FunctionArgList &Args,
SourceLocation StartLoc);
+
+ /// FinishFunction - Complete IR generation of the current
+ /// function. It is legal to call this function even if there is no
+ /// current insertion point.
void FinishFunction(SourceLocation EndLoc=SourceLocation());
/// EmitFunctionProlog - Emit the target specific LLVM code to load
@@ -224,21 +229,38 @@ public:
/// label maps to.
llvm::BasicBlock *getBasicBlockForLabel(const LabelStmt *S);
+ /// EmitBlock - Emit the given block \arg BB and set it as the
+ /// insert point, adding a fall-through branch from the current
+ /// insert block if necessary. It is legal to call this function
+ /// even if there is no current insertion point.
void EmitBlock(llvm::BasicBlock *BB);
/// EmitBranch - Emit a branch to the specified basic block from the
/// current insert block, taking care to avoid creation of branches
- /// from dummy blocks.
+ /// from dummy blocks. It is legal to call this function even if
+ /// there is no current insertion point.
///
/// This function clears the current insertion point. The caller
/// should follow calls to this function with calls to Emit*Block
/// prior to generation new code.
void EmitBranch(llvm::BasicBlock *Block);
- /// EmitDummyBlock - Emit a new block which will never be branched
- /// to. This is used to satisfy the invariant that codegen always
- /// has an active unterminated block to dump code into.
- void EmitDummyBlock();
+ /// HaveInsertPoint - True if an insertion point is defined. If not,
+ /// this indicates that the current code being emitted is
+ /// unreachable.
+ bool HaveInsertPoint() const {
+ return Builder.GetInsertBlock() != 0;
+ }
+
+ /// EnsureInsertPoint - Ensure that an insertion point is defined so
+ /// that emitted IR has a place to go. Note that by definition, if
+ /// this function creates a block then that block is unreachable;
+ /// callers may do better to detect when no insertion point is
+ /// defined and simply skip IR generation.
+ void EnsureInsertPoint() {
+ if (!HaveInsertPoint())
+ EmitBlock(createBasicBlock());
+ }
/// ErrorUnsupported - Print out an error that codegen doesn't support the
/// specified stmt yet.
@@ -276,10 +298,6 @@ public:
void EmitAggregateClear(llvm::Value *DestPtr, QualType Ty);
- /// isDummyBlock - Return true if BB is an empty basic block
- /// with no predecessors.
- static bool isDummyBlock(const llvm::BasicBlock *BB);
-
/// StartBlock - Start new block named N. If insert block is a dummy block
/// then reuse it.
void StartBlock(const char *N);
@@ -324,10 +342,24 @@ public:
// Statement Emission
//===--------------------------------------------------------------------===//
+ /// EmitStmt - Emit the code for the statement \arg S. It is legal
+ /// to call this function even if there is no current insertion
+ /// point.
+ ///
+ /// This function may clear the current insertion point; callers
+ /// should use EnsureInsertPoint if they wish to subsequently
+ /// generate code without first calling EmitBlock, EmitBranch, or
+ /// EmitStmt.
void EmitStmt(const Stmt *S);
+
RValue EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
llvm::Value *AggLoc = 0, bool isAggVol = false);
+
+ /// EmitLabel - Emit the block for the given label. It is legal
+ /// to call this function even if there is no current insertion
+ /// point.
void EmitLabel(const LabelStmt &S); // helper for EmitLabelStmt.
+
void EmitLabelStmt(const LabelStmt &S);
void EmitGotoStmt(const GotoStmt &S);
void EmitIndirectGotoStmt(const IndirectGotoStmt &S);