diff options
author | Egor Chesakov <Egor.Chesakov@microsoft.com> | 2018-11-12 16:41:01 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-12 16:41:01 -0800 |
commit | ce7e79770b924c3ed4649c60074fa36c1401b4ee (patch) | |
tree | 633e0e7579b6102431febf4d0ef79101a149f91f /src/jit/lower.cpp | |
parent | 7e263a2fafaddcb1fd787b001adb3ffda393c147 (diff) | |
download | coreclr-ce7e79770b924c3ed4649c60074fa36c1401b4ee.tar.gz coreclr-ce7e79770b924c3ed4649c60074fa36c1401b4ee.tar.bz2 coreclr-ce7e79770b924c3ed4649c60074fa36c1401b4ee.zip |
Lower fast tail call wasn't patching control expression (#20740)
Lower fast tail call can replace local variables (holding Caller stack arguments) with new temps in order to set up Callee stack arguments correctly. This involves patching corresponding LCL_VAR and LCL_VAR_ADDR nodes and replacing them with the location of a new temp.
This was not done for control expression which continued pointing to the old location and could contain a Callee argument.
Diffstat (limited to 'src/jit/lower.cpp')
-rw-r--r-- | src/jit/lower.cpp | 47 |
1 files changed, 27 insertions, 20 deletions
diff --git a/src/jit/lower.cpp b/src/jit/lower.cpp index 5e29c0b717..f125eaa35b 100644 --- a/src/jit/lower.cpp +++ b/src/jit/lower.cpp @@ -1572,7 +1572,7 @@ void Lowering::LowerCall(GenTree* node) LowerArgsForCall(call); // note that everything generated from this point on runs AFTER the outgoing args are placed - GenTree* result = nullptr; + GenTree* controlExpr = nullptr; // for x86, this is where we record ESP for checking later to make sure stack is balanced @@ -1581,7 +1581,7 @@ void Lowering::LowerCall(GenTree* node) // an indirect call. if (call->IsDelegateInvoke()) { - result = LowerDelegateInvoke(call); + controlExpr = LowerDelegateInvoke(call); } else { @@ -1589,26 +1589,26 @@ void Lowering::LowerCall(GenTree* node) switch (call->gtFlags & GTF_CALL_VIRT_KIND_MASK) { case GTF_CALL_VIRT_STUB: - result = LowerVirtualStubCall(call); + controlExpr = LowerVirtualStubCall(call); break; case GTF_CALL_VIRT_VTABLE: // stub dispatching is off or this is not a virtual call (could be a tailcall) - result = LowerVirtualVtableCall(call); + controlExpr = LowerVirtualVtableCall(call); break; case GTF_CALL_NONVIRT: if (call->IsUnmanaged()) { - result = LowerNonvirtPinvokeCall(call); + controlExpr = LowerNonvirtPinvokeCall(call); } else if (call->gtCallType == CT_INDIRECT) { - result = LowerIndirectNonvirtCall(call); + controlExpr = LowerIndirectNonvirtCall(call); } else { - result = LowerDirectCall(call); + controlExpr = LowerDirectCall(call); } break; @@ -1621,26 +1621,22 @@ void Lowering::LowerCall(GenTree* node) if (call->IsTailCallViaHelper()) { // Either controlExpr or gtCallAddr must contain real call target. - if (result == nullptr) + if (controlExpr == nullptr) { assert(call->gtCallType == CT_INDIRECT); assert(call->gtCallAddr != nullptr); - result = call->gtCallAddr; + controlExpr = call->gtCallAddr; } - result = LowerTailCallViaHelper(call, result); - } - else if (call->IsFastTailCall()) - { - LowerFastTailCall(call); + controlExpr = LowerTailCallViaHelper(call, controlExpr); } - if (result != nullptr) + if (controlExpr != nullptr) { - LIR::Range resultRange = LIR::SeqTree(comp, result); + LIR::Range controlExprRange = LIR::SeqTree(comp, controlExpr); JITDUMP("results of lowering call:\n"); - DISPRANGE(resultRange); + DISPRANGE(controlExprRange); GenTree* insertionPoint = call; if (!call->IsTailCallViaHelper()) @@ -1671,10 +1667,21 @@ void Lowering::LowerCall(GenTree* node) } } - ContainCheckRange(resultRange); - BlockRange().InsertBefore(insertionPoint, std::move(resultRange)); + ContainCheckRange(controlExprRange); + BlockRange().InsertBefore(insertionPoint, std::move(controlExprRange)); - call->gtControlExpr = result; + call->gtControlExpr = controlExpr; + } + if (call->IsFastTailCall()) + { + // Lower fast tail call can introduce new temps to set up args correctly for Callee. + // This involves patching LCL_VAR and LCL_VAR_ADDR nodes holding Caller stack args + // and replacing them with a new temp. Control expr also can contain nodes that need + // to be patched. + // Therefore lower fast tail call must be done after controlExpr is inserted into LIR. + // There is one side effect which is flipping the order of PME and control expression + // since LowerFastTailCall calls InsertPInvokeMethodEpilog. + LowerFastTailCall(call); } if (comp->opts.IsJit64Compat()) |