diff --git a/src/coreclr/jit/codegenwasm.cpp b/src/coreclr/jit/codegenwasm.cpp index 7a0bbb5efeb440..c5207235cd3f07 100644 --- a/src/coreclr/jit/codegenwasm.cpp +++ b/src/coreclr/jit/codegenwasm.cpp @@ -2652,6 +2652,12 @@ void CodeGen::genCodeForIndir(GenTreeIndir* tree) genConsumeAddress(tree->Addr()); + if ((tree->gtFlags & GTF_IND_NONFAULTING) == 0) + { + regNumber addrReg = GetMultiUseOperandReg(tree->Addr()); + genEmitNullCheck(addrReg); + } + // TODO-WASM: Memory barriers GetEmitter()->emitIns_I(ins, emitActualTypeSize(type), 0); @@ -3587,6 +3593,19 @@ void CodeGen::genCallFinally(BasicBlock* block) { GetEmitter()->emitIns(INS_end); } + + return; + } + + // Branch to the continuation block if it's not the next block. + assert(block->isBBCallFinallyPair()); + BasicBlock* const callFinallyRet = block->Next(); + assert(callFinallyRet->KindIs(BBJ_CALLFINALLYRET)); + BasicBlock* const continuation = callFinallyRet->GetTarget(); + + if (continuation != callFinallyRet->Next()) + { + inst_JMP(EJ_jmp, continuation); } } diff --git a/src/coreclr/jit/lowerwasm.cpp b/src/coreclr/jit/lowerwasm.cpp index 78cda8482f64d6..6818460dfa94f0 100644 --- a/src/coreclr/jit/lowerwasm.cpp +++ b/src/coreclr/jit/lowerwasm.cpp @@ -458,6 +458,11 @@ void Lowering::ContainCheckIndir(GenTreeIndir* indirNode) return; } + if (indirNode->OperIs(GT_IND) && ((indirNode->gtFlags & GTF_IND_NONFAULTING) == 0)) + { + SetMultiplyUsed(indirNode->Addr() DEBUGARG("ContainCheckIndir faulting load Addr")); + } + // TODO-WASM-CQ: contain suitable LEAs here. Take note of the fact that for this to be correct we must prove the // LEA doesn't overflow. It will involve creating a new frontend node to represent "nuw" (offset) addition. } diff --git a/src/coreclr/jit/regallocwasm.cpp b/src/coreclr/jit/regallocwasm.cpp index f8cac164887670..accca547daf71f 100644 --- a/src/coreclr/jit/regallocwasm.cpp +++ b/src/coreclr/jit/regallocwasm.cpp @@ -486,8 +486,9 @@ void WasmRegAlloc::CollectReferencesForNode(GenTree* node) CollectReferencesForBinop(node->AsOp()); break; + case GT_IND: case GT_STOREIND: - CollectReferencesForStoreInd(node->AsStoreInd()); + CollectReferencesForIndir(node->AsIndir()); break; case GT_STORE_BLK: @@ -648,15 +649,15 @@ void WasmRegAlloc::CollectReferencesForBinop(GenTreeOp* binopNode) } //------------------------------------------------------------------------ -// CollectReferencesForStoreInd: Collect virtual register references for an indirect store +// CollectReferencesForIndir: Collect virtual register references for an indirection. // // Arguments: -// node - The GT_STOREIND node +// node - The indirection node. // -void WasmRegAlloc::CollectReferencesForStoreInd(GenTreeStoreInd* node) +void WasmRegAlloc::CollectReferencesForIndir(GenTreeIndir* node) { GenTree* const addr = node->Addr(); - ConsumeTemporaryRegForOperand(addr DEBUGARG("storeind null check")); + ConsumeTemporaryRegForOperand(addr DEBUGARG("indirection address")); } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/regallocwasm.h b/src/coreclr/jit/regallocwasm.h index bc0f399b07e5ae..344a51260955fc 100644 --- a/src/coreclr/jit/regallocwasm.h +++ b/src/coreclr/jit/regallocwasm.h @@ -155,7 +155,7 @@ class WasmRegAlloc : public RegAllocInterface void CollectReferencesForCall(GenTreeCall* callNode); void CollectReferencesForCast(GenTreeOp* castNode); void CollectReferencesForBinop(GenTreeOp* binOpNode); - void CollectReferencesForStoreInd(GenTreeStoreInd* node); + void CollectReferencesForIndir(GenTreeIndir* node); void CollectReferencesForBlockStore(GenTreeBlk* node); void CollectReferencesForLclVar(GenTreeLclVar* lclVar); void CollectReferencesForIndexAddr(GenTreeIndexAddr* indexAddrNode); diff --git a/src/coreclr/jit/stacklevelsetter.cpp b/src/coreclr/jit/stacklevelsetter.cpp index 32f7fcf73dc244..91ae68a7e35b0a 100644 --- a/src/coreclr/jit/stacklevelsetter.cpp +++ b/src/coreclr/jit/stacklevelsetter.cpp @@ -190,7 +190,7 @@ void StackLevelSetter::ProcessBlock(BasicBlock* block) if (checkForHelpers) { - if (((node->gtFlags & GTF_EXCEPT) != 0) && node->OperMayThrow(m_compiler)) + if (MayUseThrowHelperBlock(node)) { SetThrowHelperBlocks(node, block); } @@ -199,6 +199,42 @@ void StackLevelSetter::ProcessBlock(BasicBlock* block) assert(currentStackLevel == 0); } +//------------------------------------------------------------------------ +// MayUseThrowHelperBlock: Check whether codegen may branch to a throw helper block. +// +// Arguments: +// node - The node to process. +// +// Return Value: +// True if the node may branch to a throw helper block. +// +bool StackLevelSetter::MayUseThrowHelperBlock(GenTree* node) +{ + if (((node->gtFlags & GTF_EXCEPT) != 0) && node->OperMayThrow(m_compiler)) + { + return true; + } + +#if defined(TARGET_WASM) + switch (node->OperGet()) + { + case GT_NULLCHECK: + case GT_IND: + case GT_STORE_BLK: + case GT_STOREIND: + return (node->gtFlags & GTF_IND_NONFAULTING) == 0; + + case GT_CALL: + return node->AsCall()->NeedsNullCheck(); + + default: + break; + } +#endif // defined(TARGET_WASM) + + return false; +} + //------------------------------------------------------------------------ // SetThrowHelperBlocks: Set throw helper blocks incoming stack levels targeted // from the node. @@ -213,7 +249,7 @@ void StackLevelSetter::ProcessBlock(BasicBlock* block) // void StackLevelSetter::SetThrowHelperBlocks(GenTree* node, BasicBlock* block) { - assert(node->OperMayThrow(m_compiler)); + assert(MayUseThrowHelperBlock(node)); // Check that it uses throw block, find its kind, find the block, set level. switch (node->OperGet()) diff --git a/src/coreclr/jit/stacklevelsetter.h b/src/coreclr/jit/stacklevelsetter.h index 55fdeb8428a274..339ae10fdc443a 100644 --- a/src/coreclr/jit/stacklevelsetter.h +++ b/src/coreclr/jit/stacklevelsetter.h @@ -17,6 +17,7 @@ class StackLevelSetter final : public Phase void ProcessBlocks(); void ProcessBlock(BasicBlock* block); + bool MayUseThrowHelperBlock(GenTree* node); void SetThrowHelperBlocks(GenTree* node, BasicBlock* block); void SetThrowHelperBlock(SpecialCodeKind kind, BasicBlock* block);