summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsivarv <sivarv@microsoft.com>2016-03-15 13:23:29 -0700
committersivarv <sivarv@microsoft.com>2016-03-15 14:32:56 -0700
commit301bf0a08a391797edcb8f9e7fffd29f232d09cb (patch)
treec8114ecc85c500b118fe5670e27d29b73b192aca
parentcdbc51ff1e216804027533baa42eb9c9be7bef1f (diff)
downloadcoreclr-301bf0a08a391797edcb8f9e7fffd29f232d09cb.tar.gz
coreclr-301bf0a08a391797edcb8f9e7fffd29f232d09cb.tar.bz2
coreclr-301bf0a08a391797edcb8f9e7fffd29f232d09cb.zip
Fix to issue #3734
-rw-r--r--src/jit/morph.cpp33
1 files changed, 21 insertions, 12 deletions
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp
index 16ece5f76f..44ec95de52 100644
--- a/src/jit/morph.cpp
+++ b/src/jit/morph.cpp
@@ -14165,28 +14165,32 @@ void Compiler::fgMorphBlocks()
fgReturnCount--;
}
- // Block is guaranteed to have last stmt as its jump kind is BBJ_RETURN.
- // Note that it a block with jump kind BBJ_RETURN not necessarily needs to end with GT_RETURN.
+ // Note 1: A block is not guaranteed to have a last stmt if its jump kind is BBJ_RETURN.
+ // For example a method returning void could have an empty block with jump kind BBJ_RETURN.
+ // Such blocks do materialize as part of in-lining.
+ //
+ // Note 2: A block with jump kind BBJ_RETURN does not necessarily need to end with GT_RETURN.
// It could end with a tail call or rejected tail call or monitor.exit or a GT_INTRINSIC.
// For now it is safe to explicitly check whether last stmt is GT_RETURN if genReturnLocal
// is BAD_VAR_NUM.
//
// TODO: Need to characterize the last top level stmt of a block ending with BBJ_RETURN.
- noway_assert(block->bbTreeList);
- GenTreePtr last = block->bbTreeList->gtPrev;
- noway_assert(last != nullptr);
- noway_assert(last->gtNext == nullptr);
- noway_assert(last->gtOper == GT_STMT);
-
- GenTreePtr ret = last->gtStmt.gtStmtExpr;
- noway_assert(ret != nullptr);
-
+ GenTreePtr last = (block->bbTreeList != nullptr) ? block->bbTreeList->gtPrev : nullptr;
+ GenTreePtr ret = (last != nullptr) ? last->gtStmt.gtStmtExpr : nullptr;
+
//replace the GT_RETURN node to be a GT_ASG that stores the return value into genReturnLocal.
if (genReturnLocal != BAD_VAR_NUM)
{
+ // Method must be returning a value other than TYP_VOID.
noway_assert(compMethodHasRetVal());
+ // This block must be ending with a GT_RETURN
+ noway_assert(last != nullptr);
+ noway_assert(last->gtOper == GT_STMT);
+ noway_assert(last->gtNext == nullptr);
+ noway_assert(ret != nullptr);
+
// GT_RETURN must have non-null operand as the method is returning the value assigned to genReturnLocal
noway_assert(ret->OperGet() == GT_RETURN);
noway_assert(ret->gtGetOp1() != nullptr);
@@ -14197,8 +14201,13 @@ void Compiler::fgMorphBlocks()
//make sure that copy-prop ignores this assignment.
last->gtStmt.gtStmtExpr->gtFlags |= GTF_DONT_CSE;
}
- else if (ret->OperGet() == GT_RETURN)
+ else if (ret != nullptr && ret->OperGet() == GT_RETURN)
{
+ // This block ends with a GT_RETURN
+ noway_assert(last != nullptr);
+ noway_assert(last->gtOper == GT_STMT);
+ noway_assert(last->gtNext == nullptr);
+
// Must be a void GT_RETURN with null operand; delete it as this block branches to oneReturn block
noway_assert(ret->TypeGet() == TYP_VOID);
noway_assert(ret->gtGetOp1() == nullptr);