diff options
Diffstat (limited to 'src/jit/lower.cpp')
-rw-r--r-- | src/jit/lower.cpp | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/src/jit/lower.cpp b/src/jit/lower.cpp index 3f609e70e4..1d3eb257d3 100644 --- a/src/jit/lower.cpp +++ b/src/jit/lower.cpp @@ -3189,6 +3189,16 @@ GenTree* Lowering::LowerDirectCall(GenTreeCall* call) result = Ind(Ind(result)); break; + case IAT_RELPVALUE: + { + // Non-virtual direct calls to addresses accessed by + // a single relative indirection. + GenTree* cellAddr = AddrGen(addr); + GenTree* indir = Ind(cellAddr); + result = comp->gtNewOperNode(GT_ADD, TYP_I_IMPL, indir, AddrGen(addr)); + break; + } + default: noway_assert(!"Bad accessType"); break; @@ -3977,6 +3987,9 @@ GenTree* Lowering::LowerNonvirtPinvokeCall(GenTreeCall* call) case IAT_PPVALUE: result = Ind(Ind(AddrGen(addr))); break; + + case IAT_RELPVALUE: + unreached(); } } @@ -4073,19 +4086,24 @@ GenTree* Lowering::LowerVirtualVtableCall(GenTreeCall* call) // // Save relative offset to tmp (vtab is virtual table pointer, vtabOffsOfIndirection is offset of // vtable-1st-level-indirection): - // tmp = [vtab + vtabOffsOfIndirection] + // tmp = vtab // // Save address of method to result (vtabOffsAfterIndirection is offset of vtable-2nd-level-indirection): - // result = [vtab + vtabOffsOfIndirection + vtabOffsAfterIndirection + tmp] + // result = [tmp + vtabOffsOfIndirection + vtabOffsAfterIndirection + [tmp + vtabOffsOfIndirection]] + // + // + // If relative pointers are also in second level indirection, additional temporary is used: + // tmp1 = vtab + // tmp2 = tmp1 + vtabOffsOfIndirection + vtabOffsAfterIndirection + [tmp1 + vtabOffsOfIndirection] + // result = tmp2 + [tmp2] + // unsigned lclNumTmp = comp->lvaGrabTemp(true DEBUGARG("lclNumTmp")); - comp->lvaTable[lclNumTmp].incRefCnts(comp->compCurBB->getBBWeight(comp), comp); - GenTree* lclvNodeStore = comp->gtNewTempAssign(lclNumTmp, result); - LIR::Range range = LIR::SeqTree(comp, lclvNodeStore); - JITDUMP("result of obtaining pointer to virtual table:\n"); - DISPRANGE(range); - BlockRange().InsertBefore(call, std::move(range)); + unsigned lclNumTmp2 = comp->lvaGrabTemp(true DEBUGARG("lclNumTmp2")); + comp->lvaTable[lclNumTmp2].incRefCnts(comp->compCurBB->getBBWeight(comp), comp); + + GenTree* lclvNodeStore = comp->gtNewTempAssign(lclNumTmp, result); GenTree* tmpTree = comp->gtNewLclvNode(lclNumTmp, result->TypeGet()); tmpTree = Offset(tmpTree, vtabOffsOfIndirection); @@ -4094,7 +4112,22 @@ GenTree* Lowering::LowerVirtualVtableCall(GenTreeCall* call) GenTree* offs = comp->gtNewIconNode(vtabOffsOfIndirection + vtabOffsAfterIndirection, TYP_INT); result = comp->gtNewOperNode(GT_ADD, TYP_I_IMPL, comp->gtNewLclvNode(lclNumTmp, result->TypeGet()), offs); - result = Ind(OffsetByIndex(result, tmpTree)); + GenTree* base = OffsetByIndexWithScale(result, tmpTree, 1); + GenTree* lclvNodeStore2 = comp->gtNewTempAssign(lclNumTmp2, base); + + LIR::Range range = LIR::SeqTree(comp, lclvNodeStore); + JITDUMP("result of obtaining pointer to virtual table:\n"); + DISPRANGE(range); + BlockRange().InsertBefore(call, std::move(range)); + + LIR::Range range2 = LIR::SeqTree(comp, lclvNodeStore2); + JITDUMP("result of obtaining pointer to virtual table 2nd level indirection:\n"); + DISPRANGE(range2); + BlockRange().InsertAfter(lclvNodeStore, std::move(range2)); + + result = Ind(comp->gtNewLclvNode(lclNumTmp2, result->TypeGet())); + result = + comp->gtNewOperNode(GT_ADD, TYP_I_IMPL, result, comp->gtNewLclvNode(lclNumTmp2, result->TypeGet())); } else { |