IRgen improvements on unreachable code:
- Split out "simple" statements which can easily handle IR generation
when there is no insert point. These are generally statements which
start by emitting a new block or are only containers for other
statements.
- This fixes a regression in emitting dummy blocks, notably for case
statements.
- This also fixes spurious emission of a number of debug stoppoint
intrinsic instructions.
Remove unneeded sw.body block, just clear the insertion point.
Lift out CodeGenFunction::EmitStopPoint which calls into the
CGDebugInfo class when generating debug info.
Normalize definitions of Emit{Break,Continue}Stmt and usage of
ErrorUnsupported.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59118 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 88da20d..e405086 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -25,9 +25,21 @@
// Statement Emission
//===----------------------------------------------------------------------===//
+void CodeGenFunction::EmitStopPoint(const Stmt *S) {
+ if (CGDebugInfo *DI = CGM.getDebugInfo()) {
+ DI->setLocation(S->getLocStart());
+ DI->EmitStopPoint(CurFn, Builder);
+ }
+}
+
void CodeGenFunction::EmitStmt(const Stmt *S) {
assert(S && "Null statement?");
+ // Check if we can handle this without bothering to generate an
+ // insert point or debug info.
+ if (EmitSimpleStmt(S))
+ return;
+
// 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
@@ -35,14 +47,8 @@
// 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
- // executable code. So do not generate a stoppoint for that.
- CGDebugInfo *DI = CGM.getDebugInfo();
- if (DI && S->getStmtClass() != Stmt::CompoundStmtClass) {
- DI->setLocation(S->getLocStart());
- DI->EmitStopPoint(CurFn, Builder);
- }
+ // Generate a stoppoint if we are emitting debug info.
+ EmitStopPoint(S);
switch (S->getStmtClass()) {
default:
@@ -59,10 +65,6 @@
ErrorUnsupported(S, "statement");
}
break;
- case Stmt::NullStmtClass: break;
- case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
- case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
- case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
case Stmt::IndirectGotoStmtClass:
EmitIndirectGotoStmt(cast<IndirectGotoStmt>(*S)); break;
@@ -73,28 +75,8 @@
case Stmt::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break;
case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break;
-
- case Stmt::BreakStmtClass:
- // FIXME: Implement break in @try or @catch blocks.
- if (!ObjCEHStack.empty()) {
- CGM.ErrorUnsupported(S, "continue inside an Obj-C exception block");
- return;
- }
- EmitBreakStmt();
- break;
-
- case Stmt::ContinueStmtClass:
- // FIXME: Implement continue in @try or @catch blocks.
- if (!ObjCEHStack.empty()) {
- CGM.ErrorUnsupported(S, "continue inside an Obj-C exception block");
- return;
- }
- EmitContinueStmt();
- break;
case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break;
- case Stmt::DefaultStmtClass: EmitDefaultStmt(cast<DefaultStmt>(*S)); break;
- case Stmt::CaseStmtClass: EmitCaseStmt(cast<CaseStmt>(*S)); break;
case Stmt::AsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break;
case Stmt::ObjCAtTryStmtClass:
@@ -118,6 +100,22 @@
}
}
+bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) {
+ switch (S->getStmtClass()) {
+ default: return false;
+ case Stmt::NullStmtClass: break;
+ case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
+ case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
+ case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
+ case Stmt::BreakStmtClass: EmitBreakStmt(cast<BreakStmt>(*S)); break;
+ case Stmt::ContinueStmtClass: EmitContinueStmt(cast<ContinueStmt>(*S)); break;
+ case Stmt::DefaultStmtClass: EmitDefaultStmt(cast<DefaultStmt>(*S)); break;
+ case Stmt::CaseStmtClass: EmitCaseStmt(cast<CaseStmt>(*S)); break;
+ }
+
+ return true;
+}
+
/// EmitCompoundStmt - Emit a compound statement {..} node. If GetLast is true,
/// this captures the expression result of the last sub-statement and returns it
/// (for use by the statement expression extension).
@@ -126,6 +124,7 @@
// FIXME: handle vla's etc.
CGDebugInfo *DI = CGM.getDebugInfo();
if (DI) {
+ EnsureInsertPoint();
DI->setLocation(S.getLBracLoc());
DI->EmitRegionStart(CurFn, Builder);
}
@@ -200,6 +199,11 @@
return;
}
+ // If this code is reachable then emit a stop point (if generating
+ // debug info). We have to do this ourselves because we are on the
+ // "simple" statement path.
+ if (HaveInsertPoint())
+ EmitStopPoint(&S);
EmitBranch(getBasicBlockForLabel(S.getLabel()));
}
@@ -485,16 +489,38 @@
EmitDecl(**I);
}
-void CodeGenFunction::EmitBreakStmt() {
+void CodeGenFunction::EmitBreakStmt(const BreakStmt &S) {
assert(!BreakContinueStack.empty() && "break stmt not in a loop or switch!");
+ // FIXME: Implement break in @try or @catch blocks.
+ if (!ObjCEHStack.empty()) {
+ CGM.ErrorUnsupported(&S, "continue inside an Obj-C exception block");
+ return;
+ }
+
+ // If this code is reachable then emit a stop point (if generating
+ // debug info). We have to do this ourselves because we are on the
+ // "simple" statement path.
+ if (HaveInsertPoint())
+ EmitStopPoint(&S);
llvm::BasicBlock *Block = BreakContinueStack.back().BreakBlock;
EmitBranch(Block);
}
-void CodeGenFunction::EmitContinueStmt() {
+void CodeGenFunction::EmitContinueStmt(const ContinueStmt &S) {
assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
+ // FIXME: Implement continue in @try or @catch blocks.
+ if (!ObjCEHStack.empty()) {
+ CGM.ErrorUnsupported(&S, "continue inside an Obj-C exception block");
+ return;
+ }
+
+ // If this code is reachable then emit a stop point (if generating
+ // debug info). We have to do this ourselves because we are on the
+ // "simple" statement path.
+ if (HaveInsertPoint())
+ EmitStopPoint(&S);
llvm::BasicBlock *Block = BreakContinueStack.back().ContinueBlock;
EmitBranch(Block);
}
@@ -595,8 +621,8 @@
SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock);
CaseRangeBlock = DefaultBlock;
- // Create basic block for body of switch
- EmitBlock(createBasicBlock("sw.body"));
+ // Clear the insertion point to indicate we are in unreachable code.
+ Builder.ClearInsertionPoint();
// All break statements jump to NextBlock. If BreakContinueStack is non empty
// then reuse last ContinueBlock.