Пример #1
0
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);
    }
}
Пример #2
0
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

}