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

Code before:
//    callNode - The GT_CALL node
//
void WasmRegAlloc::CollectReferencesForCall(GenTreeCall* callNode)
{
    if (callNode->NeedsNullCheck())
    {
        CallArg* thisArg  = callNode->gtArgs.GetThisArg();
        GenTree* thisNode = thisArg->GetNode();
        ConsumeTemporaryRegForOperand(thisNode DEBUGARG("null check for call"));
    }
}

//------------------------------------------------------------------------
// CollectReferencesForCast: Collect virtual register references for a cast.
//
// Consumes temporary registers for a cast.
//
// Arguments:
//    castNode - The GT_CAST node
//
void WasmRegAlloc::CollectReferencesForCast(GenTreeOp* castNode)
{
    if (castNode->gtOverflow())
    {
        ConsumeTemporaryRegForOperand(castNode->gtGetOp1() DEBUGARG("cast overflow check"));
    }
}

//------------------------------------------------------------------------
// RewriteLocalStackStore: rewrite a store to the stack to STOREIND(LCL_ADDR, ...).
//
// This is needed to obey WASM stack ordering constraints: as in IR, the
// address operands comes first and we can't insert that into the middle
// of an already generated instruction stream at codegen time.
//
// Arguments:
//    lclNode - The local store node
//
void WasmRegAlloc::RewriteLocalStackStore(GenTreeLclVarCommon* lclNode)
{
    // At this point, the IR is already stackified, so we just need to find the first node in the dataflow.
    // TODO-WASM-TP: this is nice and simple, but can we do this more efficiently?
    GenTree*             value = lclNode->Data();
    GenTree*             op    = value;
    GenTree::VisitResult visitResult;
    do
    {
        visitResult = op->VisitOperands([&op](GenTree* operand) {
            op = operand;
            return GenTree::VisitResult::Abort;
        });

Review comment (bug):
```suggestion
    ConsumeTemporaryRegForOperand(castNode->AsCast()->CastOp() DEBUGARG("cast overflow check"));
```

Code after:
//    callNode - The GT_CALL node
//
void WasmRegAlloc::CollectReferencesForCall(GenTreeCall* callNode)
{
    CallArg* thisArg = callNode->gtArgs.GetThisArg();

    if (thisArg != nullptr)
    {
        ConsumeTemporaryRegForOperand(thisArg->GetNode() DEBUGARG("call this argument"));
    }
}

//------------------------------------------------------------------------
// CollectReferencesForCast: Collect virtual register references for a cast.
//
// Consumes temporary registers for a cast.
//
// Arguments:
//    castNode - The GT_CAST node
//
void WasmRegAlloc::CollectReferencesForCast(GenTreeOp* castNode)
{
    ConsumeTemporaryRegForOperand(castNode->gtGetOp1() DEBUGARG("cast overflow check"));
}

//------------------------------------------------------------------------
// RewriteLocalStackStore: rewrite a store to the stack to STOREIND(LCL_ADDR, ...).
//
// This is needed to obey WASM stack ordering constraints: as in IR, the
// address operands comes first and we can't insert that into the middle
// of an already generated instruction stream at codegen time.
//
// Arguments:
//    lclNode - The local store node
//
void WasmRegAlloc::RewriteLocalStackStore(GenTreeLclVarCommon* lclNode)
{
    // At this point, the IR is already stackified, so we just need to find the first node in the dataflow.
    // TODO-WASM-TP: this is nice and simple, but can we do this more efficiently?
    GenTree* value          = lclNode->Data();
    GenTree* insertionPoint = value->gtFirstNodeInOperandOrder();

    // TODO-WASM-RA: figure out the address mode story here. Right now this will produce an address not folded
    // into the store's address mode. We can utilize a contained LEA, but that will require some liveness work.
    uint16_t offset = lclNode->GetLclOffs();
    lclNode->SetOper(GT_LCL_ADDR);
    lclNode->ChangeType(TYP_I_IMPL);
    lclNode->AsLclFld()->SetLclOffs(offset);

    GenTree*     store;
    GenTreeFlags indFlags = GTF_IND_NONFAULTING | GTF_IND_TGT_NOT_HEAP;