// The following are boolean flags that keep track of the state of internal data structures
- bool fgStmtListThreaded;
+ bool fgStmtListThreaded; // true if the node list is now threaded
bool fgCanRelocateEHRegions; // true if we are allowed to relocate the EH regions
bool fgEdgeWeightsComputed; // true after we have called fgComputeEdgeWeights
bool fgHaveValidEdgeWeights; // true if we were successful in computing all of the edge weights
void fgDebugCheckBBlist(bool checkBBNum = false, bool checkBBRefs = true);
void fgDebugCheckBlockLinks();
void fgDebugCheckLinks(bool morphTrees = false);
+ void fgDebugCheckStmtsList(BasicBlock* block, bool morphTrees);
void fgDebugCheckNodeLinks(BasicBlock* block, GenTreePtr stmt);
void fgDebugCheckFlags(GenTreePtr tree);
void fgDebugCheckFlagsHelper(GenTreePtr tree, unsigned treeFlags, unsigned chkFlags);
fgDebugCheckBlockLinks();
/* For each basic block check the bbTreeList links */
- for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
+ for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
{
- PROCESS_BLOCK_AGAIN:;
if (block->IsLIR())
{
LIR::AsRange(block).CheckLIR(this);
}
else
{
- for (GenTreeStmt* stmt = block->firstStmt(); stmt; stmt = stmt->gtNextStmt)
- {
- /* Verify that bbTreeList is threaded correctly */
- /* Note that for the GT_STMT list, the gtPrev list is circular. The gtNext list is not: gtNext of the
- * last GT_STMT in a block is nullptr. */
+ fgDebugCheckStmtsList(block, morphTrees);
+ }
+ }
+}
- noway_assert(stmt->gtPrev);
+//------------------------------------------------------------------------------
+// fgDebugCheckStmtsList : Perfoms the set of checks:
+// - all statements in the block are linked correctly
+// - check statements flags
+// - check nodes gtNext and gtPrev values, if the node list is threaded
+//
+// Arguments:
+// block - the block to check statements in
+// morphTrees - try to morph trees in the checker
+//
+// Note:
+// Checking that all bits that are set in treeFlags are also set in chkFlags is currently disabled.
- if (stmt == block->bbTreeList)
- {
- noway_assert(stmt->gtPrev->gtNext == nullptr);
- }
- else
- {
- noway_assert(stmt->gtPrev->gtNext == stmt);
- }
+void Compiler::fgDebugCheckStmtsList(BasicBlock* block, bool morphTrees)
+{
+ for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->gtNextStmt)
+ {
+ /* Verify that bbTreeList is threaded correctly */
+ /* Note that for the GT_STMT list, the gtPrev list is circular. The gtNext list is not: gtNext of the
+ * last GT_STMT in a block is nullptr. */
- if (stmt->gtNext)
- {
- noway_assert(stmt->gtNext->gtPrev == stmt);
- }
- else
- {
- noway_assert(block->lastStmt() == stmt);
- }
+ noway_assert(stmt->gtPrev);
- /* For each statement check that the exception flags are properly set */
+ if (stmt == block->bbTreeList)
+ {
+ noway_assert(stmt->gtPrev->gtNext == nullptr);
+ }
+ else
+ {
+ noway_assert(stmt->gtPrev->gtNext == stmt);
+ }
- noway_assert(stmt->gtStmtExpr);
+ if (stmt->gtNext)
+ {
+ noway_assert(stmt->gtNext->gtPrev == stmt);
+ }
+ else
+ {
+ noway_assert(block->lastStmt() == stmt);
+ }
- if (verbose && 0)
- {
- gtDispTree(stmt->gtStmtExpr);
- }
+ /* For each statement check that the exception flags are properly set */
- fgDebugCheckFlags(stmt->gtStmtExpr);
+ noway_assert(stmt->gtStmtExpr);
- // Not only will this stress fgMorphBlockStmt(), but we also get all the checks
- // done by fgMorphTree()
+ if (verbose && 0)
+ {
+ gtDispTree(stmt->gtStmtExpr);
+ }
- if (morphTrees)
- {
- // If 'stmt' is removed from the block, restart
- if (fgMorphBlockStmt(block, stmt DEBUGARG("test morphing")))
- {
- goto PROCESS_BLOCK_AGAIN;
- }
- }
+ fgDebugCheckFlags(stmt->gtStmtExpr);
- /* For each GT_STMT node check that the nodes are threaded correcly - gtStmtList */
+ // Not only will this stress fgMorphBlockStmt(), but we also get all the checks
+ // done by fgMorphTree()
- if (fgStmtListThreaded)
- {
- fgDebugCheckNodeLinks(block, stmt);
- }
+ if (morphTrees)
+ {
+ // If 'stmt' is removed from the block, start a new check for the current block,
+ // break the current check.
+ if (fgMorphBlockStmt(block, stmt DEBUGARG("test morphing")))
+ {
+ fgDebugCheckStmtsList(block, morphTrees);
+ break;
}
}
+
+ /* For each GT_STMT node check that the nodes are threaded correcly - gtStmtList */
+
+ if (fgStmtListThreaded)
+ {
+ fgDebugCheckNodeLinks(block, stmt);
+ }
}
}
{
assert(fgFirstBB->bbPrev == nullptr);
- for (BasicBlock* block = fgFirstBB; block; block = block->bbNext)
+ for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext)
{
if (block->bbNext)
{
//
// Likewise the depth limit is a policy consideration, and serves mostly
// as a safeguard to prevent runaway inlining of small methods.
-
+//
unsigned Compiler::fgCheckInlineDepthAndRecursion(InlineInfo* inlineInfo)
{
BYTE* candidateCode = inlineInfo->inlineCandidateInfo->methInfo.ILCode;