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

Code before:
//    so the offset will only be used if m_debugInfoSize > 0
emitter::instrDesc* emitter::emitNewInstrLclVarDecl(emitAttr      attr,
                                                    unsigned int  localCount,
                                                    WasmValueType type,
                                                    int           lclOffset)
{
    instrDescLclVarDecl* id = static_cast<instrDescLclVarDecl*>(emitAllocAnyInstr(sizeof(instrDescLclVarDecl), attr));
    id->idLclCnt(localCount);
    id->idLclType(type);

    if (m_debugInfoSize > 0)
    {
        id->idDebugOnlyInfo()->lclOffset = lclOffset;
    }

    return id;
}

//-----------------------------------------------------------------------------------
// emitIns_I_Ty: Emit an instruction for a local variable declaration, encoding both
// a count (immediate) and a value type. This is specifically used for local variable
// declarations that require both the number of locals and their type to be encoded.
//
// Arguments:
//   ins      - instruction to emit
//   imm      - immediate value (local count)
//   valType  - value type of the local variable
//   offs     - local variable offset (= count of preceding locals) for debug info
void emitter::emitIns_I_Ty(instruction ins, unsigned int imm, WasmValueType valType, int offs)
{
    instrDesc* id  = emitNewInstrLclVarDecl(EA_8BYTE, imm, valType, offs);
    insFormat  fmt = emitInsFormat(ins);

    id->idIns(ins);
    id->idInsFmt(fmt);

    dispIns(id);
    appendToCurIG(id);
}

WasmValueType emitter::emitGetLclVarDeclType(const instrDesc* id)
{
    assert(id->idIsLclVarDecl());
    return static_cast<const instrDescLclVarDecl*>(id)->lclType;
}

unsigned int emitter::emitGetLclVarDeclCount(const instrDesc* id)
{
    assert(id->idIsLclVarDecl());
    return static_cast<const instrDescLclVarDecl*>(id)->lclCnt;
}

Review comment (suggestion):
The FIXME comment indicates incomplete implementation for function index relocation. Consider creating a tracking issue or documenting the expected behavior when this is fully implemented.

Code after:
    assert(params.callType < EC_COUNT);
    assert((params.callType == EC_FUNC_TOKEN) || (params.addr == nullptr));

    /* Managed RetVal: emit sequence point for the call */
    if (emitComp->opts.compDbgInfo && params.debugInfo.GetLocation().IsValid())
    {
        codeGen->genIPmappingAdd(IPmappingDscKind::Normal, params.debugInfo, false);
    }

    /*
        We need to allocate the appropriate instruction descriptor based
        on whether this is a direct/indirect call, and whether we need to
        record an updated set of live GC variables.
     */
    instrDesc* id = nullptr;

    instruction ins;

    // FIXME-WASM: Currently while we're loading SP onto the stack we're not loading PEP, so generate one here.
    emitIns_I(INS_i32_const, EA_4BYTE, 0);

    switch (params.callType)
    {
        case EC_FUNC_TOKEN:
            ins = params.isJump ? INS_return_call : INS_call;
            id  = emitNewInstrSC(EA_8BYTE, 0 /* FIXME-WASM: function index reloc */);
            id->idIns(ins);
            id->idInsFmt(IF_ULEB128);
            break;
        case EC_INDIR_R:
            // Indirect load of actual ftn ptr from indirection cell (on the stack)
            // TODO-WASM: temporary, move this into higher layers (lowering).
            emitIns_I(INS_i32_load, EA_PTRSIZE, 0);
            ins = params.isJump ? INS_return_call_indirect : INS_call_indirect;
            id  = emitNewInstrSC(EA_8BYTE, 0 /* FIXME-WASM: type index reloc */);
            id->idIns(ins);
            id->idInsFmt(IF_CALL_INDIRECT);
            break;
        default:
            unreached();
    }

    if (m_debugInfoSize > 0)
    {
        INDEBUG(id->idDebugOnlyInfo()->idCallSig = params.sigInfo);
        id->idDebugOnlyInfo()->idMemCookie = (size_t)params.methHnd; // method token
    }

    dispIns(id);
    appendToCurIG(id);
    // emitLastMemBarrier = nullptr; // Cannot optimize away future memory barriers