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

Code before:
//    has no arguments.
//
GenTree* Lowering::FindEarliestPutArg(GenTreeCall* call)
{
    size_t numMarkedNodes = MarkCallPutArgAndFieldListNodes(call);

    if (numMarkedNodes <= 0)
    {
        return nullptr;
    }

    GenTree* node = call;
    do
    {
        node = node->gtPrev;

        assert((node != nullptr) && "Reached beginning of basic block while looking for marked nodes");

        if ((node->gtLIRFlags & LIR::Flags::Mark) != 0)
        {
            node->gtLIRFlags &= ~LIR::Flags::Mark;
            numMarkedNodes--;
        }
    } while (numMarkedNodes > 0);

    // WASM-FIXME: !HAS_FIXED_REGISTER_SET ||
    assert(node->OperIsPutArg());
    return node;
}

//------------------------------------------------------------------------
// MarkCallPutArgNodes: Mark all operand FIELD_LIST and PUTARG nodes
// corresponding to a call.
//
// Arguments:
//   call - the call
//
// Returns:
//   The number of nodes marked.
//
// Remarks:
//   FIELD_LIST operands are marked too, and their PUTARG operands are in turn
//   marked as well.
//
size_t Lowering::MarkCallPutArgAndFieldListNodes(GenTreeCall* call)
{
    size_t numMarkedNodes = 0;
    for (CallArg& arg : call->gtArgs.Args())
    {
        if (arg.GetEarlyNode() != nullptr)
        {

Review comment (bug):
The WASM-FIXME comment suggests that the assertion at line 3106 may fail for WASM because !HAS_FIXED_REGISTER_SET means there are no PUTARG nodes. However, this function already returns nullptr at line 3088 if numMarkedNodes is 0, which would happen when MarkPutArgAndFieldListNodes returns 0 (as it does for WASM when there are no PutArg or FieldList nodes). The assertion may still be reachable if there are FieldList nodes without PutArg nodes. Consider whether this assertion should be conditional on HAS_FIXED_REGISTER_SET, or whether the early exit logic needs adjustment.
```suggestion
    assert(!HAS_FIXED_REGISTER_SET || node->OperIsPutArg());
```

Code after:
//    has no arguments.
//
GenTree* Lowering::FindEarliestPutArg(GenTreeCall* call)
{
    size_t numMarkedNodes = MarkCallPutArgAndFieldListNodes(call);

    if (numMarkedNodes <= 0)
    {
        return nullptr;
    }

    GenTree* node = call;
    do
    {
        node = node->gtPrev;

        assert((node != nullptr) && "Reached beginning of basic block while looking for marked nodes");

        if ((node->gtLIRFlags & LIR::Flags::Mark) != 0)
        {
            node->gtLIRFlags &= ~LIR::Flags::Mark;
            numMarkedNodes--;
        }
    } while (numMarkedNodes > 0);

    assert(node->OperIsPutArg());
    return node;
}

//------------------------------------------------------------------------
// MarkCallPutArgNodes: Mark all operand FIELD_LIST and PUTARG nodes
// corresponding to a call.
//
// Arguments:
//   call - the call
//
// Returns:
//   The number of nodes marked.
//
// Remarks:
//   FIELD_LIST operands are marked too, and their PUTARG operands are in turn
//   marked as well.
//
size_t Lowering::MarkCallPutArgAndFieldListNodes(GenTreeCall* call)
{
    size_t numMarkedNodes = 0;
    for (CallArg& arg : call->gtArgs.Args())
    {
        if (arg.GetEarlyNode() != nullptr)
        {
            numMarkedNodes += MarkPutArgAndFieldListNodes(arg.GetEarlyNode());