Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
74e89c5
Optimize runtime async OSR transitions
jakobbotsch Jan 29, 2026
51a9384
Misalign OSR function stack on entry
jakobbotsch Jan 29, 2026
92bfbf5
Fix
jakobbotsch Jan 29, 2026
e1c9e53
Rename
jakobbotsch Jan 29, 2026
8d48da0
WIP
jakobbotsch Apr 14, 2026
f1d98d1
WIP
jakobbotsch Apr 14, 2026
e3d29e7
WIP
jakobbotsch Apr 14, 2026
2179ae7
WIP
jakobbotsch Apr 14, 2026
448d7cd
Run jit-format
jakobbotsch Apr 14, 2026
10cff17
Fix
jakobbotsch Apr 14, 2026
27db1a7
Fix again
jakobbotsch Apr 14, 2026
05131c3
More hacking
jakobbotsch Apr 14, 2026
480d01e
Build break
jakobbotsch Apr 14, 2026
771df5f
Switch to restoring callee saves instead
jakobbotsch Apr 15, 2026
3474bd1
Clean up
jakobbotsch Apr 15, 2026
60aa1f8
Run jit-format
jakobbotsch Apr 15, 2026
ec1a088
Fix
jakobbotsch Apr 15, 2026
df8a012
Set FP for arm64
jakobbotsch Apr 15, 2026
a1e0380
Remove assert
jakobbotsch Apr 15, 2026
dbc2d70
Fix overriding FP during restore
jakobbotsch Apr 15, 2026
4410ba3
Clean up
jakobbotsch Apr 15, 2026
6dce58b
Implement for LA64/RV64
jakobbotsch Apr 15, 2026
d8bddb7
Clean up
jakobbotsch Apr 15, 2026
b7d705e
AltJit based fixes
jakobbotsch Apr 15, 2026
b18b0fc
Fix arm build
jakobbotsch Apr 15, 2026
20d1190
Feedback
jakobbotsch Apr 15, 2026
1e4df82
Fix build
jakobbotsch Apr 15, 2026
06e9e7f
Remove unnecessary phantom unwind
jakobbotsch Apr 16, 2026
05ffa2d
Partial compilation patchpoints
jakobbotsch Apr 16, 2026
bbde19c
Merge branch 'main' into osr-arm64-restore-from-tier0
jakobbotsch Apr 16, 2026
82ad389
Support frames without fp/lr saved with callee saves
jakobbotsch Apr 17, 2026
6d784e9
Fixes
jakobbotsch Apr 17, 2026
bd302fb
Remove SPMI hack
jakobbotsch Apr 17, 2026
87e6ce5
Feedback
jakobbotsch Apr 17, 2026
bd0cc58
Merge remote-tracking branch 'origin/async-fast-osr-resume' into osr-…
jakobbotsch Apr 17, 2026
776b074
Run jit-format
jakobbotsch Apr 17, 2026
b008162
Fixes after merge, implement support for rest of targets
jakobbotsch Apr 17, 2026
4c13bd5
Fix patchpoint info
jakobbotsch Apr 17, 2026
98465e6
Merge branch 'main' of github.com:dotnet/runtime into osr-arm64-fast-…
jakobbotsch Apr 21, 2026
8d700f7
Fixes
jakobbotsch Apr 21, 2026
d519610
Fix EA_ATTR for genFtnEntry
jakobbotsch Apr 21, 2026
1d799d7
Feedback
jakobbotsch Apr 21, 2026
1fb2262
Clean up
jakobbotsch Apr 21, 2026
caf62eb
Fix build
jakobbotsch Apr 21, 2026
c1b08ae
Feedback
jakobbotsch Apr 21, 2026
a6a4d06
Remove note
jakobbotsch Apr 22, 2026
4dc2bfa
Remove unnecessary
jakobbotsch Apr 22, 2026
64aca04
Merge branch 'main' into osr-arm64-fast-osr-resumption
jakobbotsch Apr 23, 2026
8e87864
Feedback
jakobbotsch Apr 23, 2026
0b93651
More copilot comment nitpicking
jakobbotsch Apr 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 73 additions & 75 deletions src/coreclr/jit/async.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1201,16 +1201,15 @@ void AsyncTransformation::BuildContinuation(BasicBlock* block,
JITDUMP(" Call has return; continuation will have return value\n");
}

// For OSR, we store the IL offset that inspired the OSR method at the
// beginning of the data (and store -1 in the tier0 version). This must be
// at the beginning because the tier0 and OSR versions need to agree on
// this.
// For OSR, we store the address of the OSR function at the beginning of
// the data (and store 0 in the tier0 version). This must be at the
// beginning because the tier0 and OSR versions need to agree on this.
if (m_compiler->doesMethodHavePatchpoints() || m_compiler->opts.IsOSR())
{
JITDUMP(" Method %s; keeping IL offset that inspired OSR method at the beginning of non-GC data\n",
JITDUMP(" Method %s; keeping OSR address at the beginning of non-GC data\n",
m_compiler->doesMethodHavePatchpoints() ? "has patchpoints" : "is an OSR method");
// Must be pointer sized for compatibility with Continuation methods that access fields
layoutBuilder->SetNeedsOSRILOffset();
layoutBuilder->SetNeedsOSRAddress();
}

if (HasNonContextRestoreExceptionalFlow(block))
Expand Down Expand Up @@ -1252,9 +1251,9 @@ void AsyncTransformation::BuildContinuation(BasicBlock* block,
void ContinuationLayout::Dump(int indent)
{
printf("%*sContinuation layout (%u bytes):\n", indent, "", Size);
if (OSRILOffset != UINT_MAX)
if (OSRAddressOffset != UINT_MAX)
{
printf("%*s +%03u OSR IL offset\n", indent, "", OSRILOffset);
printf("%*s +%03u OSR address\n", indent, "", OSRAddressOffset);
}

if (ExceptionOffset != UINT_MAX)
Expand Down Expand Up @@ -1415,10 +1414,10 @@ ContinuationLayout* ContinuationLayoutBuilder::Create()
return offset;
};

if (m_needsOSRILOffset)
if (m_needsOSRAddress)
{
// Must be pointer sized for compatibility with Continuation methods that access fields
layout->OSRILOffset = allocLayout(TARGET_POINTER_SIZE, TARGET_POINTER_SIZE);
layout->OSRAddressOffset = allocLayout(TARGET_POINTER_SIZE, TARGET_POINTER_SIZE);
}

if (m_needsException)
Expand Down Expand Up @@ -1876,7 +1875,7 @@ GenTreeCall* AsyncTransformation::CreateAllocContinuationCall(bool
//------------------------------------------------------------------------
// AsyncTransformation::FillInDataOnSuspension:
// Create IR that fills the data array of the continuation object with
// live local values, OSR IL offset, continuation context, and execution
// live local values, OSR address, continuation context, and execution
// context.
//
// Parameters:
Expand All @@ -1894,19 +1893,23 @@ void AsyncTransformation::FillInDataOnSuspension(GenTreeCall*
{
if ((saveSet != SaveSet::MutatedLocals) && (m_compiler->doesMethodHavePatchpoints() || m_compiler->opts.IsOSR()))
{
GenTree* ilOffsetToStore;
GenTree* osrAddressToStore;
if (m_compiler->doesMethodHavePatchpoints())
ilOffsetToStore = m_compiler->gtNewIconNode(-1);
{
osrAddressToStore = m_compiler->gtNewIconNode(0, TYP_I_IMPL);
}
else
ilOffsetToStore = m_compiler->gtNewIconNode((int)m_compiler->info.compILEntry);
{
osrAddressToStore = new (m_compiler, GT_FTN_ENTRY) GenTree(GT_FTN_ENTRY, TYP_I_IMPL);
}

// OSR IL offset needs to be at offset 0 because OSR and tier0 methods
// OSR address needs to be at offset 0 because OSR and tier0 methods
// need to agree on that.
assert(layout.OSRILOffset == 0);
assert(layout.OSRAddressOffset == 0);
GenTree* newContinuation = m_compiler->gtNewLclvNode(GetNewContinuationVar(), TYP_REF);
unsigned offset = OFFSETOF__CORINFO_Continuation__data;
GenTree* storePatchpointOffset = StoreAtOffset(newContinuation, offset, ilOffsetToStore, TYP_INT);
LIR::AsRange(suspendBB).InsertAtEnd(LIR::SeqTree(m_compiler, storePatchpointOffset));
GenTree* storeOSRAddressOffset = StoreAtOffset(newContinuation, offset, osrAddressToStore, TYP_I_IMPL);
LIR::AsRange(suspendBB).InsertAtEnd(LIR::SeqTree(m_compiler, storeOSRAddressOffset));
}

// Fill in data
Expand Down Expand Up @@ -2871,7 +2874,7 @@ ContinuationLayoutBuilder* ContinuationLayoutBuilder::CreateSharedLayout(Compile
for (const AsyncState& state : states)
{
ContinuationLayoutBuilder* layout = state.Layout;
sharedLayout->m_needsOSRILOffset |= layout->m_needsOSRILOffset;
sharedLayout->m_needsOSRAddress |= layout->m_needsOSRAddress;
sharedLayout->m_needsException |= layout->m_needsException;
sharedLayout->m_needsContinuationContext |= layout->m_needsContinuationContext;
sharedLayout->m_needsKeepAlive |= layout->m_needsKeepAlive;
Expand Down Expand Up @@ -3004,55 +3007,50 @@ void AsyncTransformation::CreateResumptionSwitch()
{
JITDUMP(" Method has patch points...\n");
// If we have patchpoints then first check if we need to resume in the OSR version.
BasicBlock* callHelperBB = m_compiler->fgNewBBafter(BBJ_THROW, m_compiler->fgLastBBInMainFunction(), false);
callHelperBB->bbSetRunRarely();
callHelperBB->clearTryIndex();
callHelperBB->clearHndIndex();
BasicBlock* jmpOSR = m_compiler->fgNewBBafter(BBJ_THROW, m_compiler->fgLastBBInMainFunction(), false);
jmpOSR->bbSetRunRarely();
jmpOSR->clearTryIndex();
jmpOSR->clearHndIndex();

JITDUMP(" Created " FMT_BB " for transitions back into OSR method\n", callHelperBB->bbNum);
JITDUMP(" Created " FMT_BB " for transitions back into OSR method\n", jmpOSR->bbNum);

BasicBlock* onContinuationBB = newEntryBB->GetTrueTarget();
BasicBlock* checkILOffsetBB = m_compiler->fgNewBBbefore(BBJ_COND, onContinuationBB, true);
BasicBlock* onContinuationBB = newEntryBB->GetTrueTarget();
BasicBlock* checkOSRAddressOffsetBB = m_compiler->fgNewBBbefore(BBJ_COND, onContinuationBB, true);

JITDUMP(" Created " FMT_BB " to check whether we should transition immediately to OSR\n",
checkILOffsetBB->bbNum);
checkOSRAddressOffsetBB->bbNum);

// Redirect newEntryBB -> onContinuationBB into newEntryBB -> checkILOffsetBB -> onContinuationBB
m_compiler->fgRedirectEdge(newEntryBB->TrueEdgeRef(), checkILOffsetBB);
// Redirect newEntryBB -> onContinuationBB into newEntryBB -> checkOSRAddressOffsetBB -> onContinuationBB
m_compiler->fgRedirectEdge(newEntryBB->TrueEdgeRef(), checkOSRAddressOffsetBB);
newEntryBB->GetTrueEdge()->setLikelihood(0);
checkILOffsetBB->inheritWeightPercentage(newEntryBB, 0);
checkOSRAddressOffsetBB->inheritWeightPercentage(newEntryBB, 0);

FlowEdge* toOnContinuationBB = m_compiler->fgAddRefPred(onContinuationBB, checkILOffsetBB);
FlowEdge* toCallHelperBB = m_compiler->fgAddRefPred(callHelperBB, checkILOffsetBB);
checkILOffsetBB->SetCond(toCallHelperBB, toOnContinuationBB);
toCallHelperBB->setLikelihood(0);
FlowEdge* toOnContinuationBB = m_compiler->fgAddRefPred(onContinuationBB, checkOSRAddressOffsetBB);
FlowEdge* toJmpOSRBB = m_compiler->fgAddRefPred(jmpOSR, checkOSRAddressOffsetBB);
checkOSRAddressOffsetBB->SetCond(toJmpOSRBB, toOnContinuationBB);
toJmpOSRBB->setLikelihood(0);
toOnContinuationBB->setLikelihood(1);
callHelperBB->inheritWeightPercentage(checkILOffsetBB, 0);

// We need to dispatch to the OSR version if the IL offset is non-negative.
continuationArg = m_compiler->gtNewLclvNode(m_compiler->lvaAsyncContinuationArg, TYP_REF);
unsigned offsetOfIlOffset = OFFSETOF__CORINFO_Continuation__data;
GenTree* ilOffset = LoadFromOffset(continuationArg, offsetOfIlOffset, TYP_INT);
unsigned ilOffsetLclNum = m_compiler->lvaGrabTemp(false DEBUGARG("IL offset for tier0 OSR method"));
m_compiler->lvaGetDesc(ilOffsetLclNum)->lvType = TYP_INT;
GenTree* storeIlOffset = m_compiler->gtNewStoreLclVarNode(ilOffsetLclNum, ilOffset);
LIR::AsRange(checkILOffsetBB).InsertAtEnd(LIR::SeqTree(m_compiler, storeIlOffset));

ilOffset = m_compiler->gtNewLclvNode(ilOffsetLclNum, TYP_INT);
GenTree* zero = m_compiler->gtNewIconNode(0);
GenTree* geZero = m_compiler->gtNewOperNode(GT_GE, TYP_INT, ilOffset, zero);
GenTree* jtrue = m_compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, geZero);
LIR::AsRange(checkILOffsetBB).InsertAtEnd(ilOffset, zero, geZero, jtrue);
jmpOSR->inheritWeightPercentage(checkOSRAddressOffsetBB, 0);

ilOffset = m_compiler->gtNewLclvNode(ilOffsetLclNum, TYP_INT);
// We need to dispatch to the OSR version if the OSR address is non-zero.
continuationArg = m_compiler->gtNewLclvNode(m_compiler->lvaAsyncContinuationArg, TYP_REF);
unsigned offsetOfOSRAddressOffset = OFFSETOF__CORINFO_Continuation__data;
GenTree* osrAddress = LoadFromOffset(continuationArg, offsetOfOSRAddressOffset, TYP_I_IMPL);
unsigned osrAddressLclNum = m_compiler->lvaGrabTemp(false DEBUGARG("OSR address for tier0 OSR method"));
m_compiler->lvaGetDesc(osrAddressLclNum)->lvType = TYP_I_IMPL;
GenTree* storeOsrAddress = m_compiler->gtNewStoreLclVarNode(osrAddressLclNum, osrAddress);
LIR::AsRange(checkOSRAddressOffsetBB).InsertAtEnd(LIR::SeqTree(m_compiler, storeOsrAddress));

GenTreeCall* callHelper = m_compiler->gtNewHelperCallNode(CORINFO_HELP_PATCHPOINT_FORCED, TYP_VOID, ilOffset);
callHelper->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN;
osrAddress = m_compiler->gtNewLclvNode(osrAddressLclNum, TYP_I_IMPL);
GenTree* zero = m_compiler->gtNewIconNode(0, TYP_I_IMPL);
GenTree* neZero = m_compiler->gtNewOperNode(GT_NE, TYP_INT, osrAddress, zero);
GenTree* jtrue = m_compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, neZero);
LIR::AsRange(checkOSRAddressOffsetBB).InsertAtEnd(osrAddress, zero, neZero, jtrue);

m_compiler->compCurBB = callHelperBB;
m_compiler->fgMorphTree(callHelper);
osrAddress = m_compiler->gtNewLclvNode(osrAddressLclNum, TYP_I_IMPL);

LIR::AsRange(callHelperBB).InsertAtEnd(LIR::SeqTree(m_compiler, callHelper));
GenTree* jmpOsr = m_compiler->gtNewOperNode(GT_NONLOCAL_JMP, TYP_VOID, osrAddress);
LIR::AsRange(jmpOSR).InsertAtEnd(LIR::SeqTree(m_compiler, jmpOsr));
}
else if (m_compiler->opts.IsOSR())
{
Expand All @@ -3061,33 +3059,33 @@ void AsyncTransformation::CreateResumptionSwitch()
// version by normal means then we will see a non-zero continuation
// here that belongs to the tier0 method. In that case we should just
// ignore it, so create a BB that jumps back.
BasicBlock* onContinuationBB = newEntryBB->GetTrueTarget();
BasicBlock* onNoContinuationBB = newEntryBB->GetFalseTarget();
BasicBlock* checkILOffsetBB = m_compiler->fgNewBBbefore(BBJ_COND, onContinuationBB, true);
BasicBlock* onContinuationBB = newEntryBB->GetTrueTarget();
BasicBlock* onNoContinuationBB = newEntryBB->GetFalseTarget();
BasicBlock* checkOSRAddressOffsetBB = m_compiler->fgNewBBbefore(BBJ_COND, onContinuationBB, true);

// Switch newEntryBB -> onContinuationBB into newEntryBB -> checkILOffsetBB
m_compiler->fgRedirectEdge(newEntryBB->TrueEdgeRef(), checkILOffsetBB);
// Switch newEntryBB -> onContinuationBB into newEntryBB -> checkOSRAddressOffsetBB
m_compiler->fgRedirectEdge(newEntryBB->TrueEdgeRef(), checkOSRAddressOffsetBB);
newEntryBB->GetTrueEdge()->setLikelihood(0);
checkILOffsetBB->inheritWeightPercentage(newEntryBB, 0);
checkOSRAddressOffsetBB->inheritWeightPercentage(newEntryBB, 0);

// Make checkILOffsetBB ->(true) onNoContinuationBB
// ->(false) onContinuationBB
// Make checkOSRAddressOffsetBB ->(true) onNoContinuationBB
// ->(false) onContinuationBB

FlowEdge* toOnContinuationBB = m_compiler->fgAddRefPred(onContinuationBB, checkILOffsetBB);
FlowEdge* toOnNoContinuationBB = m_compiler->fgAddRefPred(onNoContinuationBB, checkILOffsetBB);
checkILOffsetBB->SetCond(toOnNoContinuationBB, toOnContinuationBB);
FlowEdge* toOnContinuationBB = m_compiler->fgAddRefPred(onContinuationBB, checkOSRAddressOffsetBB);
FlowEdge* toOnNoContinuationBB = m_compiler->fgAddRefPred(onNoContinuationBB, checkOSRAddressOffsetBB);
checkOSRAddressOffsetBB->SetCond(toOnNoContinuationBB, toOnContinuationBB);
toOnContinuationBB->setLikelihood(0);
toOnNoContinuationBB->setLikelihood(1);

JITDUMP(" Created " FMT_BB " to check for Tier-0 continuations\n", checkILOffsetBB->bbNum);
JITDUMP(" Created " FMT_BB " to check for Tier-0 continuations\n", checkOSRAddressOffsetBB->bbNum);

continuationArg = m_compiler->gtNewLclvNode(m_compiler->lvaAsyncContinuationArg, TYP_REF);
unsigned offsetOfIlOffset = OFFSETOF__CORINFO_Continuation__data;
GenTree* ilOffset = LoadFromOffset(continuationArg, offsetOfIlOffset, TYP_INT);
GenTree* zero = m_compiler->gtNewIconNode(0);
GenTree* ltZero = m_compiler->gtNewOperNode(GT_LT, TYP_INT, ilOffset, zero);
GenTree* jtrue = m_compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, ltZero);
LIR::AsRange(checkILOffsetBB).InsertAtEnd(LIR::SeqTree(m_compiler, jtrue));
continuationArg = m_compiler->gtNewLclvNode(m_compiler->lvaAsyncContinuationArg, TYP_REF);
unsigned offsetOfOSRAddressOffset = OFFSETOF__CORINFO_Continuation__data;
GenTree* osrAddress = LoadFromOffset(continuationArg, offsetOfOSRAddressOffset, TYP_I_IMPL);
GenTree* zero = m_compiler->gtNewIconNode(0, TYP_I_IMPL);
GenTree* eqZero = m_compiler->gtNewOperNode(GT_EQ, TYP_INT, osrAddress, zero);
GenTree* jtrue = m_compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, eqZero);
LIR::AsRange(checkOSRAddressOffsetBB).InsertAtEnd(LIR::SeqTree(m_compiler, jtrue));

if (ReuseContinuations())
{
Expand Down
12 changes: 6 additions & 6 deletions src/coreclr/jit/async.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ struct ContinuationLayoutBuilder
{
private:
Compiler* m_compiler;
bool m_needsOSRILOffset = false;
bool m_needsOSRAddress = false;
bool m_needsException = false;
bool m_needsContinuationContext = false;
bool m_needsKeepAlive = false;
Expand All @@ -70,13 +70,13 @@ struct ContinuationLayoutBuilder
{
}

void SetNeedsOSRILOffset()
void SetNeedsOSRAddress()
{
m_needsOSRILOffset = true;
m_needsOSRAddress = true;
}
bool NeedsOSRILOffset() const
bool NeedsOSRAddress() const
{
return m_needsOSRILOffset;
return m_needsOSRAddress;
}
void SetNeedsException()
{
Expand Down Expand Up @@ -128,7 +128,7 @@ struct ContinuationLayoutBuilder
struct ContinuationLayout
{
unsigned Size = 0;
unsigned OSRILOffset = UINT_MAX;
unsigned OSRAddressOffset = UINT_MAX;
unsigned ExceptionOffset = UINT_MAX;
unsigned ContinuationContextOffset = UINT_MAX;
unsigned KeepAliveOffset = UINT_MAX;
Comment thread
jakobbotsch marked this conversation as resolved.
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,7 @@ class CodeGen final : public CodeGenInterface
void genJumpTable(GenTree* tree);
void genTableBasedSwitch(GenTree* tree);
void genAsyncResumeInfo(GenTreeVal* tree);
void genFtnEntry(GenTree* tree);
UNATIVE_OFFSET genEmitAsyncResumeInfoTable(emitter::dataSection** dataSec);
CORINFO_FIELD_HANDLE genEmitAsyncResumeInfo(unsigned stateNum);
#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
Expand Down Expand Up @@ -1309,6 +1310,8 @@ class CodeGen final : public CodeGenInterface
void genSwiftErrorReturn(GenTree* treeNode);
#endif // SWIFT_SUPPORT

void genNonLocalJmp(GenTreeUnOp* treeNode);

#ifdef TARGET_XARCH
void genStackPointerConstantAdjustment(ssize_t spDelta, bool trackSpAdjustments);
void genStackPointerConstantAdjustmentWithProbe(ssize_t spDelta, bool trackSpAdjustments);
Expand Down
22 changes: 22 additions & 0 deletions src/coreclr/jit/codegenarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,17 @@ void CodeGen::genTableBasedSwitch(GenTree* treeNode)
GetEmitter()->emitIns_R_ARX(INS_ldr, EA_4BYTE, REG_PC, baseReg, idxReg, TARGET_POINTER_SIZE, 0);
}

//------------------------------------------------------------------------
// genNonLocalJmp: Not supported for arm32.
//
// Parameters:
// tree - the GT_NONLOCAL_JMP node
//
void CodeGen::genNonLocalJmp(GenTreeUnOp* tree)
{
NYI_ARM("GT_NONLOCAL_JMP is not supported on arm32");
}

//------------------------------------------------------------------------
// genJumpTable: emits the table and an instruction to get the address of the first element
//
Expand All @@ -669,6 +680,17 @@ void CodeGen::genAsyncResumeInfo(GenTreeVal* treeNode)
genProduceReg(treeNode);
}

//------------------------------------------------------------------------
// genFtnEntry: Not supported for arm32.
//
// Parameters:
// treeNode - the GT_FTN_ENTRY node
//
void CodeGen::genFtnEntry(GenTree* treeNode)
{
NYI_ARM("GT_FTN_ENTRY is not supported on arm32");
}

//------------------------------------------------------------------------
// genGetInsForOper: Return instruction encoding of the operation tree.
//
Expand Down
29 changes: 29 additions & 0 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3808,6 +3808,35 @@ void CodeGen::genAsyncResumeInfo(GenTreeVal* treeNode)
genProduceReg(treeNode);
}

//------------------------------------------------------------------------
// genFtnEntry: emits address of the current function being compiled
//
// Parameters:
// treeNode - the GT_FTN_ENTRY node
//
void CodeGen::genFtnEntry(GenTree* treeNode)
{
GetEmitter()->emitIns_R_L(INS_adr, EA_PTRSIZE, GetEmitter()->emitPrologIG, treeNode->GetRegNum());
genProduceReg(treeNode);
}

//------------------------------------------------------------------------
// genNonLocalJmp: Emit jump to the specified address.
//
// Parameters:
// tree - the GT_NONLOCAL_JMP node
//
void CodeGen::genNonLocalJmp(GenTreeUnOp* tree)
{
// Non-local jumps cannot handle the case where this function has been
// hijacked, since the VM may not restore the original LR at the right
// location in the new frame.
SetHasTailCalls(true);

genConsumeOperands(tree->AsOp());
GetEmitter()->emitIns_R(INS_br, EA_PTRSIZE, tree->gtGetOp1()->GetRegNum());
}

//------------------------------------------------------------------------
// genLockedInstructions: Generate code for a GT_XADD, GT_XAND, GT_XORR or GT_XCHG node.
//
Expand Down
Loading
Loading