From f408c06d2efaa82ee2ff296462a237b67b2332dc Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Mon, 30 Mar 2026 11:50:52 -0700 Subject: [PATCH 1/4] Support struct returns where the operand is a single-element fieldlist by just generating a return --- src/coreclr/jit/codegenwasm.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/coreclr/jit/codegenwasm.cpp b/src/coreclr/jit/codegenwasm.cpp index cc10f56f0c8a96..5a90ac9a29f31f 100644 --- a/src/coreclr/jit/codegenwasm.cpp +++ b/src/coreclr/jit/codegenwasm.cpp @@ -3098,6 +3098,38 @@ void CodeGen::genEHCatchRet(BasicBlock* block) void CodeGen::genStructReturn(GenTree* treeNode) { + assert(treeNode->OperIs(GT_RETURN)); + + GenTree* op1 = treeNode->AsOp()->GetReturnValue(); + GenTree* actualOp1 = op1->gtSkipReloadOrCopy(); + + const ReturnTypeDesc& retTypeDesc = m_compiler->compRetTypeDesc; + const unsigned regCount = retTypeDesc.GetReturnRegCount(); + + assert(regCount <= MAX_RET_REG_COUNT); + + if (op1->OperIsFieldList()) + { + // Go through and consume the fields in the field list so liveness is correct. + unsigned regIndex = 0; + for (GenTreeFieldList::Use& use : op1->AsFieldList()->Uses()) + { + GenTree* fieldNode = use.GetNode(); + regNumber sourceReg = genConsumeReg(fieldNode); + regIndex++; + } + + // We should only have one field in the field list. + assert(regIndex == 1); + + // The field list's individual fields should have preceded us in LIR and code to push them onto the stack + // should already have been generated. We should also only have one field (see MAX_RET_REG_COUNT assert, + // above.) As a result, all we need to do is generate a return opcode. + GetEmitter()->emitIns(INS_return); + + return; + } + NYI_WASM("genStructReturn"); } From c36227bbf3c615271a7e289f9093fbe26bac9f13 Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Mon, 30 Mar 2026 13:30:17 -0700 Subject: [PATCH 2/4] Address copilot feedback --- src/coreclr/jit/codegenwasm.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/codegenwasm.cpp b/src/coreclr/jit/codegenwasm.cpp index 5a90ac9a29f31f..397fe9b52661ee 100644 --- a/src/coreclr/jit/codegenwasm.cpp +++ b/src/coreclr/jit/codegenwasm.cpp @@ -3108,18 +3108,18 @@ void CodeGen::genStructReturn(GenTree* treeNode) assert(regCount <= MAX_RET_REG_COUNT); - if (op1->OperIsFieldList()) + if (actualOp1->OperIsFieldList()) { // Go through and consume the fields in the field list so liveness is correct. unsigned regIndex = 0; for (GenTreeFieldList::Use& use : op1->AsFieldList()->Uses()) { - GenTree* fieldNode = use.GetNode(); - regNumber sourceReg = genConsumeReg(fieldNode); + genConsumeReg(use.GetNode()); regIndex++; } - // We should only have one field in the field list. + // We should only have one field in the field list, and MAX_RET_REG_COUNT is 1 on Wasm. + assert(regIndex == regCount); assert(regIndex == 1); // The field list's individual fields should have preceded us in LIR and code to push them onto the stack From 04e0d6cb4d97406ded968607dc2b471e5ddfbc90 Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Mon, 30 Mar 2026 13:39:58 -0700 Subject: [PATCH 3/4] Add missing change --- src/coreclr/jit/codegenwasm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/codegenwasm.cpp b/src/coreclr/jit/codegenwasm.cpp index 397fe9b52661ee..3818d2c328ae0c 100644 --- a/src/coreclr/jit/codegenwasm.cpp +++ b/src/coreclr/jit/codegenwasm.cpp @@ -3112,7 +3112,7 @@ void CodeGen::genStructReturn(GenTree* treeNode) { // Go through and consume the fields in the field list so liveness is correct. unsigned regIndex = 0; - for (GenTreeFieldList::Use& use : op1->AsFieldList()->Uses()) + for (GenTreeFieldList::Use& use : actualOp1->AsFieldList()->Uses()) { genConsumeReg(use.GetNode()); regIndex++; From 9ba57f0333623730a4e5971582e71ac69b258e05 Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Tue, 31 Mar 2026 09:02:41 -0700 Subject: [PATCH 4/4] Don't emit a return --- src/coreclr/jit/codegenwasm.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/coreclr/jit/codegenwasm.cpp b/src/coreclr/jit/codegenwasm.cpp index 3818d2c328ae0c..67b60e64d15304 100644 --- a/src/coreclr/jit/codegenwasm.cpp +++ b/src/coreclr/jit/codegenwasm.cpp @@ -3122,15 +3122,10 @@ void CodeGen::genStructReturn(GenTree* treeNode) assert(regIndex == regCount); assert(regIndex == 1); - // The field list's individual fields should have preceded us in LIR and code to push them onto the stack - // should already have been generated. We should also only have one field (see MAX_RET_REG_COUNT assert, - // above.) As a result, all we need to do is generate a return opcode. - GetEmitter()->emitIns(INS_return); - return; } - NYI_WASM("genStructReturn"); + NYI_WASM("genStructReturn non-fieldlist cases"); } void CodeGen::genEmitGSCookieCheck(bool tailCall)