diff options
-rw-r--r-- | src/jit/compiler.h | 8 | ||||
-rw-r--r-- | src/jit/importer.cpp | 71 |
2 files changed, 73 insertions, 6 deletions
diff --git a/src/jit/compiler.h b/src/jit/compiler.h index dd4fb3068f..169b70067a 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -3059,13 +3059,13 @@ protected: GenTreePtr impTreeList; // Trees for the BB being imported GenTreePtr impTreeLast; // The last tree for the current BB +public: enum { CHECK_SPILL_ALL = -1, CHECK_SPILL_NONE = -2 }; -public: void impBeginTreeList(); void impEndTreeList(BasicBlock* block, GenTreePtr firstStmt, GenTreePtr lastStmt); void impEndTreeList(BasicBlock* block); @@ -5799,11 +5799,7 @@ public: optMethodFlags &= ~OMF_HAS_FATPOINTER; } - void addFatPointerCandidate(GenTreeCall* call) - { - setMethodHasFatPointer(); - call->SetFatPointerCandidate(); - } + void addFatPointerCandidate(GenTreeCall* call); unsigned optMethodFlags; diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index d671894ed0..f75c2faa07 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -19494,3 +19494,74 @@ CORINFO_RESOLVED_TOKEN* Compiler::impAllocateToken(CORINFO_RESOLVED_TOKEN token) *memory = token; return memory; } + +//------------------------------------------------------------------------ +// SpillRetExprHelper: iterate through arguments tree and spill ret_expr to local varibales. +// +class SpillRetExprHelper +{ +public: + SpillRetExprHelper(Compiler* comp) : comp(comp) + { + } + + void StoreRetExprResultsInArgs(GenTreeCall* call) + { + GenTreePtr args = call->gtCallArgs; + if (args != nullptr) + { + comp->fgWalkTreePre(&args, SpillRetExprVisitor, this); + } + GenTreePtr thisArg = call->gtCallObjp; + if (thisArg != nullptr) + { + comp->fgWalkTreePre(&thisArg, SpillRetExprVisitor, this); + } + } + +private: + static Compiler::fgWalkResult SpillRetExprVisitor(GenTree** pTree, Compiler::fgWalkData* fgWalkPre) + { + assert((pTree != nullptr) && (*pTree != nullptr)); + GenTreePtr tree = *pTree; + if ((tree->gtFlags & GTF_CALL) == 0) + { + // Trees with ret_expr are marked as GTF_CALL. + return Compiler::WALK_SKIP_SUBTREES; + } + if (tree->OperGet() == GT_RET_EXPR) + { + SpillRetExprHelper* walker = static_cast<SpillRetExprHelper*>(fgWalkPre->pCallbackData); + walker->StoreRetExprAsLocalVar(pTree); + } + return Compiler::WALK_CONTINUE; + } + + void StoreRetExprAsLocalVar(GenTreePtr* pRetExpr) + { + GenTreePtr retExpr = *pRetExpr; + assert(retExpr->OperGet() == GT_RET_EXPR); + JITDUMP("Store return expression %u as a local var.\n", retExpr->gtTreeID); + unsigned tmp = comp->lvaGrabTemp(true DEBUGARG("spilling ret_expr")); + comp->impAssignTempGen(tmp, retExpr, (unsigned)Compiler::CHECK_SPILL_NONE); + *pRetExpr = comp->gtNewLclvNode(tmp, retExpr->TypeGet()); + } + +private: + Compiler* comp; +}; + +//------------------------------------------------------------------------ +// addFatPointerCandidate: mark the call and the method, that they have a fat pointer candidate. +// Spill ret_expr in the call node, because they can't be cloned. +// +// Arguments: +// call - fat calli candidate +// +void Compiler::addFatPointerCandidate(GenTreeCall* call) +{ + setMethodHasFatPointer(); + call->SetFatPointerCandidate(); + SpillRetExprHelper helper(this); + helper.StoreRetExprResultsInArgs(call); +} |