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

Code before:
    {
        // Copy the pointer-sized non-gc-pointer slots one at a time using regular I-sized load/store pairs,
        //  and gc-pointer slots using a write barrier.
        if (!layout->IsGCPtr(i))
        {
            // Do a pointer-sized load+store pair at the appropriate offset relative to dest and source
            emit->emitIns_I(INS_local_get, attrDstAddr, WasmRegToIndex(dstReg));
            emit->emitIns_I(INS_local_get, attrSrcAddr, WasmRegToIndex(srcReg));
            emit->emitIns_I(INS_I_load, EA_PTRSIZE, srcOffset);
            emit->emitIns_I(INS_I_store, EA_PTRSIZE, dstOffset);
        }
        else
        {
            // Load the sp onto the stack for the helper call.
            // TODO-WASM: Implement a special calling convention for this helper that doesn't accept sp/pep.
            emit->emitIns_I(INS_local_get, EA_PTRSIZE, WasmRegToIndex(GetStackPointerReg()));
            // Compute the actual dest/src of the slot being copied to pass to the helper.
            emit->emitIns_I(INS_local_get, attrDstAddr, WasmRegToIndex(dstReg));
            emit->emitIns_I(INS_I_const, attrDstAddr, dstOffset);
            emit->emitIns(INS_I_add);
            emit->emitIns_I(INS_local_get, attrSrcAddr, WasmRegToIndex(srcReg));
            emit->emitIns_I(INS_I_const, attrSrcAddr, srcOffset);
            emit->emitIns(INS_I_add);
            // TODO-WASM: Load the PEP value for the helper onto the stack here? Right now genEmitHelperCall does it.
            // Call the byref assign helper. On other targets this updates the dst/src regs but here it won't,
            //  so we have to do the local.get+i32.const+i32.add dance every time.
            genEmitHelperCall(CORINFO_HELP_ASSIGN_BYREF, 0, EA_PTRSIZE);
            gcPtrCount--;
        }
        ++i;
        srcOffset += TARGET_POINTER_SIZE;
        dstOffset += TARGET_POINTER_SIZE;
    }

    assert(gcPtrCount == 0);

    if (cpObjNode->IsVolatile())
    {
        // TODO-WASM: Memory barrier
    }

    WasmProduceReg(cpObjNode);
}

//------------------------------------------------------------------------
// genCodeForInitBlkLoop - Generate code for an InitBlk using an inlined for-loop.
//    It's needed for cases when size is too big to unroll and we're not allowed
//    to use memset call due to atomicity requirements.
//
// Arguments:
//    blkOp - the GT_STORE_BLK node

Review comment (refactor):
```suggestion
            // TODO-WASM: don't load PEP in genEmitHelperCall for write barriers.
            // TODO-WASM-CQ: add a version of CORINFO_HELP_ASSIGN_BYREF that returns the updated dest/src
            // pointers as a multi-value tuple and use it here.
```

Code after:
    unsigned     slots  = layout->GetSlotCount();

    emitAttr attrSrcAddr = emitActualTypeSize(srcAddrType);
    emitAttr attrDstAddr = emitActualTypeSize(dstAddr->TypeGet());

    unsigned gcPtrCount = cpObjNode->GetLayout()->GetGCPtrCount();

    unsigned i = 0;
    while (i < slots)
    {
        // Copy the pointer-sized non-gc-pointer slots one at a time using regular I-sized load/store pairs,
        //  and gc-pointer slots using a write barrier.
        if (!layout->IsGCPtr(i))
        {
            // Do a pointer-sized load+store pair at the appropriate offset relative to dest and source
            emit->emitIns_I(INS_local_get, attrDstAddr, WasmRegToIndex(dstReg));
            emit->emitIns_I(INS_local_get, attrSrcAddr, WasmRegToIndex(srcReg));
            emit->emitIns_I(INS_I_load, EA_PTRSIZE, srcOffset);
            emit->emitIns_I(INS_I_store, EA_PTRSIZE, dstOffset);
        }
        else
        {
            // Load the sp onto the stack for the helper call.
            // TODO-WASM: Implement a special calling convention for this helper that doesn't accept sp/pep.
            emit->emitIns_I(INS_local_get, EA_PTRSIZE, WasmRegToIndex(GetStackPointerReg()));
            // Compute the actual dest/src of the slot being copied to pass to the helper.
            emit->emitIns_I(INS_local_get, attrDstAddr, WasmRegToIndex(dstReg));
            emit->emitIns_I(INS_I_const, attrDstAddr, dstOffset);
            emit->emitIns(INS_I_add);
            emit->emitIns_I(INS_local_get, attrSrcAddr, WasmRegToIndex(srcReg));
            emit->emitIns_I(INS_I_const, attrSrcAddr, srcOffset);
            emit->emitIns(INS_I_add);
            // TODO-WASM: don't load PEP in genEmitHelperCall for write barriers.
            // TODO-WASM-CQ: add a version of CORINFO_HELP_ASSIGN_BYREF that returns the updated dest/src
            // pointers as a multi-value tuple and use it here.
            genEmitHelperCall(CORINFO_HELP_ASSIGN_BYREF, 0, EA_PTRSIZE);
            gcPtrCount--;
        }
        ++i;
        srcOffset += TARGET_POINTER_SIZE;
        dstOffset += TARGET_POINTER_SIZE;
    }

    assert(gcPtrCount == 0);

    if (cpObjNode->IsVolatile())
    {
        // TODO-WASM: Memory barrier
    }
}