Repository: dotnet/runtime
File: src/coreclr/jit/codegenwasm.cpp (C++)

Code before:
// genPushCalleeSavedRegisters: no-op since we don't need to save anything.
//
void CodeGen::genPushCalleeSavedRegisters()
{
}

//------------------------------------------------------------------------
// genAllocLclFrame: initialize the SP and FP locals.
//
// Arguments:
//    frameSize         - Size of the frame to establish
//    initReg           - Unused
//    pInitRegZeroed    - Unused
//    maskArgRegsLiveIn - Unused
//
void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pInitRegZeroed, regMaskTP maskArgRegsLiveIn)
{
    assert(compiler->compGeneratingProlog);
    regNumber spReg = GetStackPointerReg();
    if (spReg == REG_NA)
    {
        assert(!isFramePointerUsed());
        return;
    }

    unsigned initialSPLclIndex = compiler->lvaWasmSpArg;
    unsigned spLclIndex        = WasmRegToIndex(spReg);
    assert(initialSPLclIndex == spLclIndex);
    if (frameSize != 0)
    {
        GetEmitter()->emitIns_I(INS_local_get, EA_PTRSIZE, initialSPLclIndex);
        GetEmitter()->emitIns_I(INS_I_const, EA_PTRSIZE, frameSize);
        GetEmitter()->emitIns(INS_I_sub);
        GetEmitter()->emitIns_I(INS_local_set, EA_PTRSIZE, spLclIndex);
    }
    regNumber fpReg = GetFramePointerReg();
    if ((fpReg != REG_NA) && (fpReg != spReg))
    {
        GetEmitter()->emitIns_I(INS_local_get, EA_PTRSIZE, spLclIndex);
        GetEmitter()->emitIns_I(INS_local_set, EA_PTRSIZE, WasmRegToIndex(fpReg));
    }
}

//------------------------------------------------------------------------
// genEnregisterOSRArgsAndLocals: enregister OSR args and locals.
//
void CodeGen::genEnregisterOSRArgsAndLocals()
{
    unreached(); // OSR not supported on WASM.
}


Review comment (suggestion):
This is a WASM local index, not the the local number (though they will be the same value). So this was intended to be something like:
```
WasmRegToIndex(compiler->lvaGetParameterABIInfo(compiler->lvaWasmSpArg).Segment(0).GetRegister());
```

More importantly, this should check for `compiler->lvaWasmSpArg == BAD_VAR_NUM` and `NIY_WASM` that case away.

Code after:
// genPushCalleeSavedRegisters: no-op since we don't need to save anything.
//
void CodeGen::genPushCalleeSavedRegisters()
{
}

//------------------------------------------------------------------------
// genAllocLclFrame: initialize the SP and FP locals.
//
// Arguments:
//    frameSize         - Size of the frame to establish
//    initReg           - Unused
//    pInitRegZeroed    - Unused
//    maskArgRegsLiveIn - Unused
//
void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pInitRegZeroed, regMaskTP maskArgRegsLiveIn)
{
    assert(compiler->compGeneratingProlog);
    regNumber spReg = GetStackPointerReg();
    if (spReg == REG_NA)
    {
        assert(!isFramePointerUsed());
        return;
    }

    // TODO-WASM: reverse pinvoke frame allocation
    //
    if (compiler->lvaWasmSpArg == BAD_VAR_NUM)
    {
        NYI_WASM("alloc local frame for reverse pinvoke");
    }

    unsigned initialSPLclIndex =
        WasmRegToIndex(compiler->lvaGetParameterABIInfo(compiler->lvaWasmSpArg).Segment(0).GetRegister());
    unsigned spLclIndex = WasmRegToIndex(spReg);
    assert(initialSPLclIndex == spLclIndex);
    if (frameSize != 0)
    {
        GetEmitter()->emitIns_I(INS_local_get, EA_PTRSIZE, initialSPLclIndex);
        GetEmitter()->emitIns_I(INS_I_const, EA_PTRSIZE, frameSize);
        GetEmitter()->emitIns(INS_I_sub);
        GetEmitter()->emitIns_I(INS_local_set, EA_PTRSIZE, spLclIndex);
    }
    regNumber fpReg = GetFramePointerReg();
    if ((fpReg != REG_NA) && (fpReg != spReg))
    {
        GetEmitter()->emitIns_I(INS_local_get, EA_PTRSIZE, spLclIndex);
        GetEmitter()->emitIns_I(INS_local_set, EA_PTRSIZE, WasmRegToIndex(fpReg));
    }
}