Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,9 @@ class CodeGen final : public CodeGenInterface
#endif
void genCodeForTreeNode(GenTree* treeNode);
void genCodeForBinary(GenTreeOp* treeNode);
#ifdef TARGET_WASM
void genCodeForShiftOrRotate(GenTreeOp* treeNode);
Comment thread
kg marked this conversation as resolved.
#endif
bool genIsSameLocalVar(GenTree* tree1, GenTree* tree2);

#if defined(TARGET_X86)
Expand Down
173 changes: 173 additions & 0 deletions src/coreclr/jit/codegenwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,26 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
switch (treeNode->OperGet())
{
case GT_ADD:
case GT_SUB:
case GT_MUL:
case GT_DIV:
case GT_MOD:
case GT_UDIV:
case GT_UMOD:
case GT_OR:
case GT_XOR:
case GT_AND:
genCodeForBinary(treeNode->AsOp());
break;

case GT_LSH:
case GT_RSH:
case GT_RSZ:
case GT_ROL:
case GT_ROR:
genCodeForShiftOrRotate(treeNode->AsOp());
break;

case GT_LCL_VAR:
genCodeForLclVar(treeNode->AsLclVar());
break;
Expand Down Expand Up @@ -153,9 +170,13 @@ void CodeGen::genCodeForBinary(GenTreeOp* treeNode)
switch (PackOperAndType(treeNode))
{
case PackOperAndType(GT_ADD, TYP_INT):
if (treeNode->gtOverflow())
NYI_WASM("Overflow checks");
ins = INS_i32_add;
break;
case PackOperAndType(GT_ADD, TYP_LONG):
if (treeNode->gtOverflow())
NYI_WASM("Overflow checks");
ins = INS_i64_add;
break;
case PackOperAndType(GT_ADD, TYP_FLOAT):
Expand All @@ -164,6 +185,96 @@ void CodeGen::genCodeForBinary(GenTreeOp* treeNode)
case PackOperAndType(GT_ADD, TYP_DOUBLE):
ins = INS_f64_add;
break;

case PackOperAndType(GT_SUB, TYP_INT):
Comment thread
kg marked this conversation as resolved.
if (treeNode->gtOverflow())
NYI_WASM("Overflow checks");
ins = INS_i32_sub;
break;
case PackOperAndType(GT_SUB, TYP_LONG):
if (treeNode->gtOverflow())
NYI_WASM("Overflow checks");
ins = INS_i64_sub;
break;
case PackOperAndType(GT_SUB, TYP_FLOAT):
ins = INS_f32_sub;
break;
case PackOperAndType(GT_SUB, TYP_DOUBLE):
ins = INS_f64_sub;
break;

case PackOperAndType(GT_MUL, TYP_INT):
if (treeNode->gtOverflow())
NYI_WASM("Overflow checks");
ins = INS_i32_mul;
break;
case PackOperAndType(GT_MUL, TYP_LONG):
if (treeNode->gtOverflow())
NYI_WASM("Overflow checks");
ins = INS_i64_mul;
break;
case PackOperAndType(GT_MUL, TYP_FLOAT):
ins = INS_f32_mul;
break;
case PackOperAndType(GT_MUL, TYP_DOUBLE):
ins = INS_f64_mul;
break;

case PackOperAndType(GT_DIV, TYP_INT):
Comment thread
kg marked this conversation as resolved.
ins = INS_i32_div_s;
break;
case PackOperAndType(GT_DIV, TYP_LONG):
ins = INS_i64_div_s;
break;
case PackOperAndType(GT_DIV, TYP_FLOAT):
ins = INS_f32_div;
break;
case PackOperAndType(GT_DIV, TYP_DOUBLE):
ins = INS_f64_div;
break;

case PackOperAndType(GT_UDIV, TYP_INT):
ins = INS_i32_div_u;
break;
case PackOperAndType(GT_UDIV, TYP_LONG):
ins = INS_i64_div_u;
break;

case PackOperAndType(GT_MOD, TYP_INT):
ins = INS_i32_rem_s;
break;
case PackOperAndType(GT_MOD, TYP_LONG):
ins = INS_i64_rem_s;
break;

case PackOperAndType(GT_UMOD, TYP_INT):
ins = INS_i32_rem_u;
break;
case PackOperAndType(GT_UMOD, TYP_LONG):
ins = INS_i64_rem_u;
break;

case PackOperAndType(GT_AND, TYP_INT):
ins = INS_i32_and;
break;
case PackOperAndType(GT_AND, TYP_LONG):
ins = INS_i64_and;
break;

case PackOperAndType(GT_OR, TYP_INT):
ins = INS_i32_or;
break;
case PackOperAndType(GT_OR, TYP_LONG):
ins = INS_i64_or;
break;

case PackOperAndType(GT_XOR, TYP_INT):
ins = INS_i32_xor;
break;
case PackOperAndType(GT_XOR, TYP_LONG):
ins = INS_i64_xor;
break;

default:
ins = INS_none;
NYI_WASM("genCodeForBinary");
Expand All @@ -174,6 +285,68 @@ void CodeGen::genCodeForBinary(GenTreeOp* treeNode)
genProduceReg(treeNode);
}

//------------------------------------------------------------------------
// genCodeForShiftOrRotate: Generate code for a shift or rotate operator
//
// Arguments:
// treeNode - The shift or rotate operation for which we are generating code.
//
void CodeGen::genCodeForShiftOrRotate(GenTreeOp* treeNode)
{
genConsumeOperands(treeNode);

// TODO-WASM: Zero-extend the 2nd operand for shifts and rotates as needed when the 1st and 2nd operand are
// different types. The shift operand width in IR is always TYP_INT; the WASM operations have the same widths
// for both the shift and shiftee. So the shift may need to be extended (zero-extended) for TYP_LONG.

instruction ins;
switch (PackOperAndType(treeNode))
{
case PackOperAndType(GT_LSH, TYP_INT):
Comment thread
kg marked this conversation as resolved.
ins = INS_i32_shl;
break;
case PackOperAndType(GT_LSH, TYP_LONG):
ins = INS_i64_shl;
break;

case PackOperAndType(GT_RSH, TYP_INT):
ins = INS_i32_shr_s;
break;
case PackOperAndType(GT_RSH, TYP_LONG):
ins = INS_i64_shr_s;
break;

case PackOperAndType(GT_RSZ, TYP_INT):
ins = INS_i32_shr_u;
break;
case PackOperAndType(GT_RSZ, TYP_LONG):
ins = INS_i64_shr_u;
break;

case PackOperAndType(GT_ROL, TYP_INT):
ins = INS_i32_rotl;
break;
case PackOperAndType(GT_ROL, TYP_LONG):
ins = INS_i64_rotl;
break;

case PackOperAndType(GT_ROR, TYP_INT):
ins = INS_i32_rotr;
break;
case PackOperAndType(GT_ROR, TYP_LONG):
ins = INS_i64_rotr;
break;

default:
ins = INS_none;
NYI_WASM("genCodeForShiftOrRotate");
break;
}

GetEmitter()->emitIns(ins);
genProduceReg(treeNode);
}

//------------------------------------------------------------------------
// genCodeForLclVar: Produce code for a GT_LCL_VAR node.
//
Expand Down
Loading