void CodeGen::siCheckVarScope(unsigned varNum, IL_OFFSET offs) { assert(compiler->opts.compScopeInfo && !compiler->opts.compDbgCode && (compiler->info.compVarScopesCount > 0)); #if FEATURE_EH_FUNCLETS if (siInFuncletRegion) { return; } #endif // FEATURE_EH_FUNCLETS if (offs == BAD_IL_OFFSET) { return; } siScope* scope; LclVarDsc* lclVarDsc1 = &compiler->lvaTable[varNum]; // If there is an open scope corresponding to varNum, find it if (lclVarDsc1->lvTracked) { scope = siLatestTrackedScopes[lclVarDsc1->lvVarIndex]; } else { for (scope = siOpenScopeList.scNext; scope; scope = scope->scNext) { if (scope->scVarNum == varNum) { break; } } } // Look up the compiler->info.compVarScopes[] to find the local var info for (varNum->lvSlotNum, offs) VarScopeDsc* varScope = compiler->compFindLocalVar(varNum, offs); if (varScope == nullptr) { return; } // If the currently open scope does not have the correct LVnum, close it // and create a new scope with this new LVnum if (scope) { if (scope->scLVnum != varScope->vsdLVnum) { siEndScope(scope); siNewScope(varScope->vsdLVnum, varScope->vsdVarNum); } } else { siNewScope(varScope->vsdLVnum, varScope->vsdVarNum); } }
void CodeGen::siBeginBlock(BasicBlock* block) { assert(block != nullptr); if (!compiler->opts.compScopeInfo) return; if (compiler->info.compVarScopesCount == 0) return; #if FEATURE_EH_FUNCLETS if (siInFuncletRegion) return; if (block->bbFlags & BBF_FUNCLET_BEG) { // For now, don't report any scopes in funclets. JIT64 doesn't. siInFuncletRegion = true; JITDUMP("Scope info: found beginning of funclet region at block BB%02u; ignoring following blocks\n", block->bbNum); return; } #endif // FEATURE_EH_FUNCLETS #ifdef DEBUG if (verbose) { printf("\nScope info: begin block BB%02u, IL range ", block->bbNum); block->dspBlockILRange(); printf("\n"); } #endif // DEBUG unsigned beginOffs = block->bbCodeOffs; if (beginOffs == BAD_IL_OFFSET) { JITDUMP("Scope info: ignoring block beginning\n"); return; } if (!compiler->opts.compDbgCode) { /* For non-debuggable code */ // End scope of variables which are not live for this block siUpdate(); // Check that vars which are live on entry have an open scope VARSET_ITER_INIT(compiler, iter, block->bbLiveIn, i); while (iter.NextElem(compiler, &i)) { unsigned varNum = compiler->lvaTrackedToVarNum[i]; // lvRefCnt may go down to 0 after liveness-analysis. // So we need to check if this tracked variable is actually used. if (!compiler->lvaTable[varNum].lvIsInReg() && !compiler->lvaTable[varNum].lvOnFrame) { assert(compiler->lvaTable[varNum].lvRefCnt == 0); continue; } siCheckVarScope(varNum, beginOffs); } } else { // For debuggable code, scopes can begin only on block boundaries. // Check if there are any scopes on the current block's start boundary. VarScopeDsc* varScope; #if FEATURE_EH_FUNCLETS // If we find a spot where the code offset isn't what we expect, because // there is a gap, it might be because we've moved the funclets out of // line. Catch up with the enter and exit scopes of the current block. // Ignore the enter/exit scope changes of the missing scopes, which for // funclets must be matched. if (siLastEndOffs != beginOffs) { assert(beginOffs > 0); assert(siLastEndOffs < beginOffs); JITDUMP("Scope info: found offset hole. lastOffs=%u, currOffs=%u\n", siLastEndOffs, beginOffs); // Skip enter scopes while ((varScope = compiler->compGetNextEnterScope(beginOffs - 1, true)) != NULL) { /* do nothing */ JITDUMP("Scope info: skipping enter scope, LVnum=%u\n", varScope->vsdLVnum); } // Skip exit scopes while ((varScope = compiler->compGetNextExitScope(beginOffs - 1, true)) != NULL) { /* do nothing */ JITDUMP("Scope info: skipping exit scope, LVnum=%u\n", varScope->vsdLVnum); } } #else // FEATURE_EH_FUNCLETS if (siLastEndOffs != beginOffs) { assert(siLastEndOffs < beginOffs); return; } #endif // FEATURE_EH_FUNCLETS while ((varScope = compiler->compGetNextEnterScope(beginOffs)) != NULL) { // brace-matching editor workaround for following line: ( JITDUMP("Scope info: opening scope, LVnum=%u [%03X..%03X)\n", varScope->vsdLVnum, varScope->vsdLifeBeg, varScope->vsdLifeEnd); siNewScope(varScope->vsdLVnum, varScope->vsdVarNum); #ifdef DEBUG LclVarDsc* lclVarDsc1 = &compiler->lvaTable[varScope->vsdVarNum]; if (VERBOSE) { printf("Scope info: >> new scope, VarNum=%u, tracked? %s, VarIndex=%u, bbLiveIn=%s ", varScope->vsdVarNum, lclVarDsc1->lvTracked ? "yes" : "no", lclVarDsc1->lvVarIndex, VarSetOps::ToString(compiler, block->bbLiveIn)); dumpConvertedVarSet(compiler, block->bbLiveIn); printf("\n"); } assert(!lclVarDsc1->lvTracked || VarSetOps::IsMember(compiler, block->bbLiveIn, lclVarDsc1->lvVarIndex)); #endif // DEBUG } } #ifdef DEBUG if (verbose) siDispOpenScopes(); #endif }