diff options
-rw-r--r-- | lib/CodeGen/CGExprComplex.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 12 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 42 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 52 |
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); |