Skip to content

Commit 4f0d352

Browse files
[RyuJit/WASM] Reach the NYI in "genFnProlog"
1 parent ea953c1 commit 4f0d352

File tree

13 files changed

+406
-36
lines changed

13 files changed

+406
-36
lines changed

src/coreclr/jit/codegencommon.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6949,6 +6949,7 @@ void CodeGen::genLongReturn(GenTree* treeNode)
69496949
inst_Mov(targetType, REG_LNGRET_HI, hiRetVal->GetRegNum(), /* canSkip */ true, emitActualTypeSize(TYP_INT));
69506950
}
69516951
#endif // TARGET_X86 || TARGET_ARM
6952+
#endif // !TARGET_WASM
69526953

69536954
//------------------------------------------------------------------------
69546955
// genReturn: Generates code for return statement.
@@ -6995,7 +6996,7 @@ void CodeGen::genReturn(GenTree* treeNode)
69956996
else if (targetType != TYP_VOID)
69966997
{
69976998
assert(op1 != nullptr);
6998-
noway_assert(op1->GetRegNum() != REG_NA);
6999+
noway_assert(!HAS_FIXED_REGISTER_SET || (op1->GetRegNum() != REG_NA));
69997000

70007001
// !! NOTE !! genConsumeReg will clear op1 as GC ref after it has
70017002
// consumed a reg for the operand. This is because the variable
@@ -7005,6 +7006,7 @@ void CodeGen::genReturn(GenTree* treeNode)
70057006
// instructions until emitted then should not rely on the outdated GC info.
70067007
genConsumeReg(op1);
70077008

7009+
#if HAS_FIXED_REGISTER_SET
70087010
#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
70097011
genSimpleReturn(treeNode);
70107012
#else // !TARGET_ARM64 || !TARGET_LOONGARCH64 || !TARGET_RISCV64
@@ -7047,6 +7049,7 @@ void CodeGen::genReturn(GenTree* treeNode)
70477049
inst_Mov_Extend(targetType, /* srcInReg */ true, retReg, op1->GetRegNum(), /* canSkip */ true);
70487050
}
70497051
#endif // !TARGET_ARM64 || !TARGET_LOONGARCH64 || !TARGET_RISCV64
7052+
#endif // HAS_FIXED_REGISTER_SET
70507053
}
70517054
}
70527055

@@ -7055,10 +7058,12 @@ void CodeGen::genReturn(GenTree* treeNode)
70557058
instGen_Set_Reg_To_Zero(EA_PTRSIZE, REG_ASYNC_CONTINUATION_RET);
70567059
}
70577060

7061+
#if EMIT_GENERATE_GCINFO
70587062
if (treeNode->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET))
70597063
{
70607064
genMarkReturnGCInfo();
70617065
}
7066+
#endif // EMIT_GENERATE_GCINFO
70627067

70637068
#ifdef PROFILING_SUPPORTED
70647069

@@ -7103,6 +7108,7 @@ void CodeGen::genReturn(GenTree* treeNode)
71037108
#endif // defined(DEBUG) && defined(TARGET_XARCH)
71047109
}
71057110

7111+
#ifndef TARGET_WASM
71067112
#ifdef SWIFT_SUPPORT
71077113
//------------------------------------------------------------------------
71087114
// genSwiftErrorReturn: Generates code for returning the normal return value,
@@ -7200,6 +7206,7 @@ void CodeGen::genCodeForAsyncContinuation(GenTree* tree)
72007206

72017207
genProduceReg(tree);
72027208
}
7209+
#endif // !TARGET_WASM
72037210

72047211
//------------------------------------------------------------------------
72057212
// isStructReturn: Returns whether the 'treeNode' is returning a struct.
@@ -7234,6 +7241,7 @@ bool CodeGen::isStructReturn(GenTree* treeNode)
72347241
#endif
72357242
}
72367243

7244+
#ifndef TARGET_WASM
72377245
//------------------------------------------------------------------------
72387246
// genStructReturn: Generates code for returning a struct.
72397247
//

src/coreclr/jit/codegenlinear.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,7 @@ void CodeGenInterface::genUpdateVarReg(LclVarDsc* varDsc, GenTree* tree, int reg
10621062
assert(tree->IsMultiRegLclVar() || tree->OperIs(GT_COPY));
10631063
varDsc->SetRegNum(tree->GetRegByIndex(regIndex));
10641064
}
1065+
#endif // !TARGET_WASM
10651066

10661067
//------------------------------------------------------------------------
10671068
// genUpdateVarReg: Update the current register location for a lclVar
@@ -1078,6 +1079,7 @@ void CodeGenInterface::genUpdateVarReg(LclVarDsc* varDsc, GenTree* tree)
10781079
varDsc->SetRegNum(tree->GetRegNum());
10791080
}
10801081

1082+
#ifndef TARGET_WASM
10811083
//------------------------------------------------------------------------
10821084
// genUnspillLocal: Reload a register candidate local into a register, if needed.
10831085
//
@@ -1610,7 +1612,6 @@ regNumber CodeGen::genConsumeReg(GenTree* tree)
16101612
return tree->GetRegNum();
16111613
}
16121614

1613-
#ifndef TARGET_WASM
16141615
// Do liveness update for an address tree: one of GT_LEA, GT_LCL_VAR, or GT_CNS_INT (for call indirect).
16151616
void CodeGen::genConsumeAddress(GenTree* addr)
16161617
{
@@ -1763,6 +1764,7 @@ void CodeGen::genConsumeOperands(GenTreeOp* tree)
17631764
}
17641765
}
17651766

1767+
#ifndef TARGET_WASM
17661768
#if defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
17671769
//------------------------------------------------------------------------
17681770
// genConsumeOperands: Do liveness update for the operands of a multi-operand node,
@@ -2087,6 +2089,7 @@ void CodeGen::genSpillLocal(unsigned varNum, var_types type, GenTreeLclVar* lclN
20872089
varNum, 0);
20882090
}
20892091
}
2092+
#endif // !TARGET_WASM
20902093

20912094
//-------------------------------------------------------------------------
20922095
// genProduceReg: do liveness update for register produced by the current
@@ -2105,6 +2108,7 @@ void CodeGen::genProduceReg(GenTree* tree)
21052108
tree->gtDebugFlags |= GTF_DEBUG_NODE_CG_PRODUCED;
21062109
#endif
21072110

2111+
#if HAS_FIXED_REGISTER_SET
21082112
if (tree->gtFlags & GTF_SPILL)
21092113
{
21102114
// Code for GT_COPY node gets generated as part of consuming regs by its parent.
@@ -2174,10 +2178,12 @@ void CodeGen::genProduceReg(GenTree* tree)
21742178
return;
21752179
}
21762180
}
2181+
#endif // HAS_FIXED_REGISTER_SET
21772182

21782183
// Updating variable liveness after instruction was emitted
21792184
genUpdateLife(tree);
21802185

2186+
#if EMIT_GENERATE_GCINFO
21812187
// If we've produced a register, mark it as a pointer, as needed.
21822188
if (tree->gtHasReg(compiler))
21832189
{
@@ -2254,8 +2260,10 @@ void CodeGen::genProduceReg(GenTree* tree)
22542260
}
22552261
}
22562262
}
2263+
#endif // EMIT_GENERATE_GCINFO
22572264
}
22582265

2266+
#ifndef TARGET_WASM
22592267
// transfer gc/byref status of src reg to dst reg
22602268
void CodeGen::genTransferRegGCState(regNumber dst, regNumber src)
22612269
{

src/coreclr/jit/codegenwasm.cpp

Lines changed: 108 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,105 @@ void CodeGen::genFuncletEpilog()
5959
NYI_WASM("genFuncletEpilog");
6060
}
6161

62-
void CodeGen::genCodeForTreeNode(GenTree* node)
62+
void CodeGen::genCodeForTreeNode(GenTree* treeNode)
6363
{
64-
NYI_WASM("genCodeForTreeNode");
64+
#ifdef DEBUG
65+
lastConsumedNode = nullptr;
66+
if (compiler->verbose)
67+
{
68+
compiler->gtDispLIRNode(treeNode, "Generating: ");
69+
}
70+
#endif // DEBUG
71+
72+
assert(!treeNode->IsReuseRegVal()); // TODO-WASM-CQ: enable.
73+
74+
// Contained nodes are part of the parent for codegen purposes.
75+
if (treeNode->isContained())
76+
{
77+
return;
78+
}
79+
80+
switch (treeNode->OperGet())
81+
{
82+
case GT_ADD:
83+
genCodeForBinary(treeNode->AsOp());
84+
break;
85+
86+
case GT_LCL_VAR:
87+
genCodeForLclVar(treeNode->AsLclVar());
88+
break;
89+
90+
case GT_RETURN:
91+
genReturn(treeNode);
92+
break;
93+
94+
case GT_IL_OFFSET:
95+
// Do nothing; this node is a marker for debug info.
96+
break;
97+
98+
default:
99+
NYIRAW(GenTree::OpName(treeNode->OperGet()));
100+
break;
101+
}
102+
}
103+
104+
//------------------------------------------------------------------------
105+
// genCodeForBinary: Generate code for a binary arithmetic operator
106+
//
107+
// Arguments:
108+
// treeNode - The binary operation for which we are generating code.
109+
//
110+
void CodeGen::genCodeForBinary(GenTreeOp* treeNode)
111+
{
112+
genConsumeOperands(treeNode);
113+
114+
instruction ins;
115+
switch (treeNode->OperGet())
116+
{
117+
case GT_ADD:
118+
if (!treeNode->TypeIs(TYP_INT))
119+
{
120+
NYI_WASM("genCodeForBinary: non-INT GT_ADD");
121+
}
122+
ins = INS_i32_add;
123+
break;
124+
default:
125+
ins = INS_none;
126+
NYI_WASM("genCodeForBinary");
127+
break;
128+
}
129+
130+
GetEmitter()->emitIns(ins);
131+
genProduceReg(treeNode);
132+
}
133+
134+
//------------------------------------------------------------------------
135+
// genCodeForLclVar: Produce code for a GT_LCL_VAR node.
136+
//
137+
// Arguments:
138+
// tree - the GT_LCL_VAR node
139+
//
140+
void CodeGen::genCodeForLclVar(GenTreeLclVar* tree)
141+
{
142+
assert(tree->OperIs(GT_LCL_VAR) && !tree->IsMultiReg());
143+
LclVarDsc* varDsc = compiler->lvaGetDesc(tree);
144+
145+
// Unlike other targets, we can't "reload at the point of use", since that would require inserting instructions
146+
// into the middle of an already-emitted instruction group. Instead, we order the nodes in a way that obeys the
147+
// value stack constraints of WASM precisely. However, the liveness tracking is done in the same way as for other
148+
// targets, hence "genProduceReg" is only called for non-candidates.
149+
if (!varDsc->lvIsRegCandidate())
150+
{
151+
var_types type = varDsc->GetRegisterType(tree);
152+
// TODO-WASM: actually local.get the frame base local here.
153+
GetEmitter()->emitIns_S(ins_Load(type), emitTypeSize(tree), tree->GetLclNum(), 0);
154+
genProduceReg(tree);
155+
}
156+
else
157+
{
158+
unsigned wasmLclIndex = UnpackWasmReg(tree->GetRegNum());
159+
GetEmitter()->emitIns_I(INS_local_get, emitTypeSize(tree), wasmLclIndex);
160+
}
65161
}
66162

67163
BasicBlock* CodeGen::genCallFinally(BasicBlock* block)
@@ -76,13 +172,23 @@ void CodeGen::genEHCatchRet(BasicBlock* block)
76172
NYI_WASM("genEHCatchRet");
77173
}
78174

175+
void CodeGen::genStructReturn(GenTree* treeNode)
176+
{
177+
NYI_WASM("genStructReturn");
178+
}
179+
79180
void CodeGen::genEmitGSCookieCheck(bool tailCall)
80181
{
81182
// TODO-WASM: GS cookie checks have limited utility on WASM since they can only help
82183
// with detecting linear memory stack corruption. Decide if we want them anyway.
83184
NYI_WASM("genEmitGSCookieCheck");
84185
}
85186

187+
void CodeGen::genProfilingLeaveCallback(unsigned helper)
188+
{
189+
NYI_WASM("genProfilingLeaveCallback");
190+
}
191+
86192
void CodeGen::genSpillVar(GenTree* tree)
87193
{
88194
NYI_WASM("Put all spillng to memory under '#if HAS_FIXED_REGISTER_SET'");
@@ -159,11 +265,6 @@ void CodeGenInterface::genUpdateVarReg(LclVarDsc* varDsc, GenTree* tree, int reg
159265
NYI_WASM("Move genUpdateVarReg from codegenlinear.cpp to codegencommon.cpp shared code");
160266
}
161267

162-
void CodeGenInterface::genUpdateVarReg(LclVarDsc* varDsc, GenTree* tree)
163-
{
164-
NYI_WASM("Move genUpdateVarReg from codegenlinear.cpp to codegencommon.cpp shared code");
165-
}
166-
167268
void RegSet::verifyRegUsed(regNumber reg)
168269
{
169270
}

src/coreclr/jit/emit.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10102,7 +10102,7 @@ void emitter::emitRemoveLastInstruction()
1010210102
* emitGetInsSC: Get the instruction's constant value.
1010310103
*/
1010410104

10105-
cnsval_ssize_t emitter::emitGetInsSC(const instrDesc* id) const
10105+
cnsval_ssize_t emitter::emitGetInsSC(const instrDesc* id)
1010610106
{
1010710107
#ifdef TARGET_ARM // should it be TARGET_ARMARCH? Why do we need this? Note that on ARM64 we store scaled immediates
1010810108
// for some formats

src/coreclr/jit/emit.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,12 +1264,7 @@ class emitter
12641264
_idCodeSize = sz;
12651265
}
12661266
#elif defined(TARGET_WASM)
1267-
unsigned idCodeSize() const
1268-
{
1269-
// TODO-WASM: return an accurate number here based on instruction format/opcode like ARM64 above.
1270-
NYI_WASM("isCodeSize");
1271-
return 0;
1272-
}
1267+
unsigned idCodeSize() const;
12731268
#endif
12741269

12751270
emitAttr idOpSize() const
@@ -2460,8 +2455,8 @@ class emitter
24602455
static bool HasApxPpx(instruction ins);
24612456
#endif // TARGET_XARCH
24622457

2463-
cnsval_ssize_t emitGetInsSC(const instrDesc* id) const;
2464-
unsigned emitInsCount;
2458+
NOT_ARM(static) cnsval_ssize_t emitGetInsSC(const instrDesc* id);
2459+
unsigned emitInsCount;
24652460

24662461
/************************************************************************/
24672462
/* A few routines used for debug display purposes */

src/coreclr/jit/emitfmtswasm.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ enum ID_OPS
2626
// (unused)
2727
//////////////////////////////////////////////////////////////////////////////
2828

29-
IF_DEF(NONE, IS_NONE, NONE)
29+
IF_DEF(NONE, IS_NONE, NONE)
30+
IF_DEF(OPCODE, IS_NONE, NONE) // <opcode>
31+
IF_DEF(ULEB128, IS_NONE, NONE) // <opcode> <ULEB128 immediate>
32+
IF_DEF(MEMARG, IS_NONE, NONE) // <opcode> <memarg> (<align> <offset>)
3033

3134
#undef IF_DEF
3235
#endif // !DEFINE_ID_OPS

0 commit comments

Comments
 (0)