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

Code before:

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

    // Our stack level should be always greater than the bytes of arguments we push. Just
    // a sanity test.
    assert((unsigned)std::abs(params.argSize) <= codeGen->genStackLevel);

#ifdef DEBUG
    if (EMIT_GC_VERBOSE)
    {
        printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, params.ptrVars));
        dumpConvertedVarSet(emitComp, params.ptrVars);
        printf("\n");
    }
#endif

    /* 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;

    assert(params.argSize % REGSIZE_BYTES == 0);


    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)
            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 */);

Review comment (suggestion):
The params.addr value is not being used in the EC_FUNC_TOKEN case. For direct calls, params.addr should be used to generate the appropriate relocation entry for the function index. Currently, this is hardcoded to 0 which will not work for actual calls. The FIXME comment acknowledges this, but it should be addressed before this code can function correctly.
```suggestion
            id  = emitNewInstrSC(EA_8BYTE, params.addr /* function index reloc */);
```

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