/***************************************************************************** * siUpdate * * Called at the start of basic blocks, and during code-gen of a block, * for non-debuggable code, whenever the life of any tracked variable changes * and the appropriate code has been generated. For debuggable code, variables are * live over their entire scope, and so they go live or dead only on * block boundaries. */ void CodeGen::siUpdate () { if (!compiler->opts.compScopeInfo) return; if (compiler->opts.compDbgCode) return; if (compiler->info.compVarScopesCount == 0) return; #if FEATURE_EH_FUNCLETS if (siInFuncletRegion) return; #endif // FEATURE_EH_FUNCLETS VARSET_TP VARSET_INIT_NOCOPY(killed, VarSetOps::Diff(compiler, siLastLife, compiler->compCurLife)); assert(VarSetOps::IsSubset(compiler, killed, compiler->lvaTrackedVars)); VARSET_ITER_INIT(compiler, iter, killed, i); while (iter.NextElem(compiler, &i)) { #ifdef DEBUG unsigned lclNum = compiler->lvaTrackedToVarNum[i]; LclVarDsc * lclVar = &compiler->lvaTable[lclNum]; assert(lclVar->lvTracked); #endif siScope * scope = siLatestTrackedScopes[i]; siEndTrackedScope(i); } VarSetOps::Assign(compiler, siLastLife, compiler->compCurLife); }
CodeGen::siScope * CodeGen::siNewScope( unsigned LVnum, unsigned varNum) { bool tracked = compiler->lvaTable[varNum].lvTracked; unsigned varIndex = compiler->lvaTable[varNum].lvVarIndex; if (tracked) { siEndTrackedScope(varIndex); } siScope * newScope = (siScope*) compiler->compGetMem(sizeof(*newScope), CMK_SiScope); newScope->scStartLoc.CaptureLocation(getEmitter()); assert(newScope->scStartLoc.Valid()); newScope->scEndLoc.Init(); newScope->scLVnum = LVnum; newScope->scVarNum = varNum; newScope->scNext = NULL; newScope->scStackLevel = genStackLevel; // used only by stack vars siOpenScopeLast->scNext = newScope; newScope->scPrev = siOpenScopeLast; siOpenScopeLast = newScope; if (tracked) { siLatestTrackedScopes[varIndex] = newScope; } return newScope; }
void CodeGen::siEndBlock(BasicBlock* block) { assert(compiler->opts.compScopeInfo && (compiler->info.compVarScopesCount > 0)); #if FEATURE_EH_FUNCLETS if (siInFuncletRegion) return; #endif // FEATURE_EH_FUNCLETS #ifdef DEBUG if (verbose) { printf("\nScope info: end block BB%02u, IL range ", block->bbNum); block->dspBlockILRange(); printf("\n"); } #endif // DEBUG unsigned endOffs = block->bbCodeOffsEnd; if (endOffs == BAD_IL_OFFSET) { JITDUMP("Scope info: ignoring block end\n"); return; } // If non-debuggable code, find all scopes which end over this block // and close them. For debuggable code, scopes will only end on block // boundaries. VarScopeDsc* varScope; while ((varScope = compiler->compGetNextExitScope(endOffs, !compiler->opts.compDbgCode)) != NULL) { // brace-matching editor workaround for following line: ( JITDUMP("Scope info: ending scope, LVnum=%u [%03X..%03X)\n", varScope->vsdLVnum, varScope->vsdLifeBeg, varScope->vsdLifeEnd); unsigned varNum = varScope->vsdVarNum; LclVarDsc * lclVarDsc1 = &compiler->lvaTable[varNum]; assert(lclVarDsc1); if (lclVarDsc1->lvTracked) { siEndTrackedScope(lclVarDsc1->lvVarIndex); } else { siEndScope(varNum); } } siLastEndOffs = endOffs; #ifdef DEBUG if (verbose) siDispOpenScopes(); #endif }
/***************************************************************************** * siUpdate * * Called at the start of basic blocks, and during code-gen of a block, * for non-debuggable code, whenever the life of any tracked variable changes * and the appropriate code has been generated. For debuggable code, variables are * live over their entire scope, and so they go live or dead only on * block boundaries. */ void CodeGen::siUpdate() { if (!compiler->opts.compScopeInfo) { return; } if (compiler->opts.compDbgCode) { return; } if (compiler->info.compVarScopesCount == 0) { return; } #if FEATURE_EH_FUNCLETS if (siInFuncletRegion) { return; } #endif // FEATURE_EH_FUNCLETS VARSET_TP killed(VarSetOps::Diff(compiler, siLastLife, compiler->compCurLife)); assert(VarSetOps::IsSubset(compiler, killed, compiler->lvaTrackedVars)); VarSetOps::Iter iter(compiler, killed); unsigned varIndex = 0; while (iter.NextElem(&varIndex)) { #ifdef DEBUG unsigned lclNum = compiler->lvaTrackedToVarNum[varIndex]; LclVarDsc* lclVar = &compiler->lvaTable[lclNum]; assert(lclVar->lvTracked); #endif siScope* scope = siLatestTrackedScopes[varIndex]; siEndTrackedScope(varIndex); } VarSetOps::Assign(compiler, siLastLife, compiler->compCurLife); }