diff options
Diffstat (limited to 'compiler/optimizing/graph_checker.cc')
| -rw-r--r-- | compiler/optimizing/graph_checker.cc | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index fd28f0b83f..d7e6bd8161 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -81,7 +81,10 @@ void GraphChecker::VisitBasicBlock(HBasicBlock* block) { } // Ensure `block` ends with a branch instruction. - if (!block->EndsWithControlFlowInstruction()) { + // This invariant is not enforced on non-SSA graphs. Graph built from DEX with + // dead code that falls out of the method will not end with a control-flow + // instruction. Such code is removed during the SSA-building DCE phase. + if (GetGraph()->IsInSsaForm() && !block->EndsWithControlFlowInstruction()) { AddError(StringPrintf("Block %d does not end with a branch instruction.", block->GetBlockId())); } @@ -253,6 +256,22 @@ void GraphChecker::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) { } } +void GraphChecker::VisitReturn(HReturn* ret) { + if (!ret->GetBlock()->GetSingleSuccessor()->IsExitBlock()) { + AddError(StringPrintf("%s:%d does not jump to the exit block.", + ret->DebugName(), + ret->GetId())); + } +} + +void GraphChecker::VisitReturnVoid(HReturnVoid* ret) { + if (!ret->GetBlock()->GetSingleSuccessor()->IsExitBlock()) { + AddError(StringPrintf("%s:%d does not jump to the exit block.", + ret->DebugName(), + ret->GetId())); + } +} + void SSAChecker::VisitBasicBlock(HBasicBlock* block) { super_type::VisitBasicBlock(block); |