diff --git a/src/coreclr/jit/emitfmtswasm.h b/src/coreclr/jit/emitfmtswasm.h index 55b852649192f5..f752369ae14b35 100644 --- a/src/coreclr/jit/emitfmtswasm.h +++ b/src/coreclr/jit/emitfmtswasm.h @@ -36,6 +36,7 @@ IF_DEF(F32, IS_NONE, NONE) // IF_DEF(MEMARG, IS_NONE, NONE) // ( ) IF_DEF(LOCAL_DECL, IS_NONE, NONE) // +IF_DEF(MEMCPY, IS_NONE, NONE) // #undef IF_DEF #endif // !DEFINE_ID_OPS diff --git a/src/coreclr/jit/emitwasm.cpp b/src/coreclr/jit/emitwasm.cpp index 8d08ab6a9bd826..9b3bec1e483cb7 100644 --- a/src/coreclr/jit/emitwasm.cpp +++ b/src/coreclr/jit/emitwasm.cpp @@ -319,6 +319,11 @@ unsigned emitter::instrDesc::idCodeSize() const size += idIsCnsReloc() ? PADDED_RELOC_SIZE : SizeOfULEB128(emitGetInsSC(this)); break; } + case IF_MEMCPY: + { + size += idIsCnsReloc() ? PADDED_RELOC_SIZE : SizeOfULEB128(emitGetInsSC(this)); + size += idIsCnsReloc() ? PADDED_RELOC_SIZE : SizeOfULEB128(emitGetInsSC(this)); + } default: unreached(); } @@ -481,6 +486,14 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) dst += emitOutputByte(dst, valType); break; } + case IF_MEMCPY: + { + dst += emitOutputOpcode(dst, ins); + cnsval_ssize_t constant = emitGetInsSC(id); + dst += emitOutputULEB128(dst, (uint64_t)constant); + dst += emitOutputULEB128(dst, (uint64_t)constant); + break; + } default: NYI_WASM("emitOutputInstr"); break; @@ -606,6 +619,13 @@ void emitter::emitDispIns( } break; + case IF_MEMCPY: + { + cnsval_ssize_t imm = emitGetInsSC(id); + printf(" %llu %llu", (uint64_t)imm, (uint64_t)imm); + dispJumpTargetIfAny(); + } + case IF_LOCAL_DECL: { unsigned int count = emitGetLclVarDeclCount(id); diff --git a/src/coreclr/jit/instrswasm.h b/src/coreclr/jit/instrswasm.h index 7230e20a64bf7e..70e870c1c55d8f 100644 --- a/src/coreclr/jit/instrswasm.h +++ b/src/coreclr/jit/instrswasm.h @@ -218,6 +218,10 @@ INST(i64_trunc_sat_f32_u, "i64.trunc_sat_f32_u", 0, IF_OPCODE, 0x05FC) INST(i64_trunc_sat_f64_s, "i64.trunc_sat_f64_s", 0, IF_OPCODE, 0x06FC) INST(i64_trunc_sat_f64_u, "i64.trunc_sat_f64_u", 0, IF_OPCODE, 0x07FC) +INST(memory_copy, "memory.copy", 0, IF_MEMCPY, 0x10FC) +INST(memory_fill, "memory.fill", 0, IF_ULEB128, 0x11FC) + + // clang-format on #undef INST diff --git a/src/coreclr/jit/lowerwasm.cpp b/src/coreclr/jit/lowerwasm.cpp index c7a8d34a437c24..7f93fa505e02c3 100644 --- a/src/coreclr/jit/lowerwasm.cpp +++ b/src/coreclr/jit/lowerwasm.cpp @@ -171,7 +171,62 @@ GenTree* Lowering::LowerBinaryArithmetic(GenTreeOp* binOp) // void Lowering::LowerBlockStore(GenTreeBlk* blkNode) { - NYI_WASM("LowerBlockStore"); + GenTree* dstAddr = blkNode->Addr(); + GenTree* src = blkNode->Data(); + unsigned size = blkNode->Size(); + + if (blkNode->OperIsInitBlkOp()) + { + if (src->OperIs(GT_INIT_VAL)) + { + src->SetContained(); + src = src->AsUnOp()->gtGetOp1(); + } + + if (blkNode->IsZeroingGcPointersOnHeap()) + { + blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindLoop; + src->SetContained(); + } + else + { + // memory.fill + } + } + else + { + assert(src->OperIs(GT_IND, GT_LCL_VAR, GT_LCL_FLD)); + src->SetContained(); + + if (src->OperIs(GT_LCL_VAR)) + { + // TODO-1stClassStructs: for now we can't work with STORE_BLOCK source in register. + // TODO-WASM: Is this true for wasm as well? + const unsigned srcLclNum = src->AsLclVar()->GetLclNum(); + comp->lvaSetVarDoNotEnregister(srcLclNum DEBUGARG(DoNotEnregisterReason::BlockOp)); + } + + ClassLayout* layout = blkNode->GetLayout(); + bool doCpObj = layout->HasGCPtr(); + + // CopyObj or CopyBlk + if (doCpObj) + { + // Try to use bulk copy helper + if (TryLowerBlockStoreAsGcBulkCopyCall(blkNode)) + { + return; + } + + assert(dstAddr->TypeIs(TYP_BYREF, TYP_I_IMPL)); + blkNode->gtBlkOpKind = GenTreeBlk::BlkOpKindCpObjUnroll; + } + else + { + assert(blkNode->OperIs(GT_STORE_BLK)); + // memory.copy + } + } } //------------------------------------------------------------------------