Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: Add GT_SWIFT_ERROR_RET to represent loading error register upon return #100692

Merged
merged 29 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a9646c1
Add GT_SWIFT_ERROR_RET
amanasifkhalid Apr 5, 2024
b328337
Cleanup
amanasifkhalid Apr 5, 2024
63eb15c
Style
amanasifkhalid Apr 5, 2024
674d8f1
Style; comments
amanasifkhalid Apr 5, 2024
7d2e8fa
Binop implementation
amanasifkhalid Apr 8, 2024
a342e00
Update comment
amanasifkhalid Apr 8, 2024
6e50ea7
Merge from main
amanasifkhalid Apr 8, 2024
aa8c83c
Comments
amanasifkhalid Apr 8, 2024
9e310ec
Style
amanasifkhalid Apr 8, 2024
15d39bf
Add GetReturnValue helper
amanasifkhalid Apr 8, 2024
873e15a
Handle GT_SWIFT_ERROR_RET in LSRA
amanasifkhalid Apr 8, 2024
5d96892
Overzealous opt
amanasifkhalid Apr 9, 2024
24e8d0d
Feedback
amanasifkhalid Apr 9, 2024
bf186b7
Store error to local during return merging
amanasifkhalid Apr 10, 2024
c381c48
Handle GT_SWIFT_ERROR_RET in morph
amanasifkhalid Apr 10, 2024
70a69d7
Move GT_SWIFT_ERROR_RET creation to phase
amanasifkhalid Apr 10, 2024
de4457b
Handle remaining GT_RETURN-specific code
amanasifkhalid Apr 10, 2024
7096e23
Style
amanasifkhalid Apr 10, 2024
927a55e
Add comment
amanasifkhalid Apr 10, 2024
848704b
Remove ifdef
amanasifkhalid Apr 10, 2024
502f471
Fix store ordering
amanasifkhalid Apr 10, 2024
e8b1dbc
Style
amanasifkhalid Apr 10, 2024
2dce428
Do SwiftError local conversion in phase
amanasifkhalid Apr 10, 2024
38ad8a7
Delete assert
amanasifkhalid Apr 10, 2024
18df9c7
Fix build
amanasifkhalid Apr 10, 2024
86a0825
Fix codegen on arm64
amanasifkhalid Apr 11, 2024
41ec8f7
Feedback
amanasifkhalid Apr 11, 2024
6d9d360
Update BADCODE message
amanasifkhalid Apr 11, 2024
0cd339d
Feedback
amanasifkhalid Apr 12, 2024
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
4 changes: 4 additions & 0 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,10 @@ class CodeGen final : public CodeGenInterface

void genReturn(GenTree* treeNode);

#ifdef SWIFT_SUPPORT
void genSwiftErrorReturn(GenTree* treeNode);
#endif // SWIFT_SUPPORT

#ifdef TARGET_XARCH
void genStackPointerConstantAdjustment(ssize_t spDelta, bool trackSpAdjustments);
void genStackPointerConstantAdjustmentWithProbe(ssize_t spDelta, bool trackSpAdjustments);
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2990,14 +2990,14 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode)
// Note: treeNode's and op1's registers are already consumed.
//
// Arguments:
// treeNode - The GT_RETURN or GT_RETFILT tree node with non-struct and non-void type
// treeNode - The GT_RETURN/GT_RETFILT/GT_SWIFT_ERROR_RET tree node with non-struct and non-void type
//
// Return Value:
// None
//
void CodeGen::genSimpleReturn(GenTree* treeNode)
{
assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT);
assert(treeNode->OperIs(GT_RETURN, GT_RETFILT, GT_SWIFT_ERROR_RET));
GenTree* op1 = treeNode->gtGetOp1();
var_types targetType = treeNode->TypeGet();

Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/jit/codegenarmarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,12 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
genReturn(treeNode);
break;

#ifdef SWIFT_SUPPORT
case GT_SWIFT_ERROR_RET:
genSwiftErrorReturn(treeNode);
break;
#endif // SWIFT_SUPPORT

case GT_LEA:
// If we are here, it is the case where there is an LEA that cannot be folded into a parent instruction.
genLeaInstruction(treeNode->AsAddrMode());
Expand Down
46 changes: 28 additions & 18 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7758,16 +7758,16 @@ void CodeGen::genLongReturn(GenTree* treeNode)
// In case of LONG return on 32-bit, delegates to the genLongReturn method.
//
// Arguments:
// treeNode - The GT_RETURN or GT_RETFILT tree node.
// treeNode - The GT_RETURN/GT_RETFILT/GT_SWIFT_ERROR_RET tree node.
//
// Return Value:
// None
//
void CodeGen::genReturn(GenTree* treeNode)
{
assert(treeNode->OperIs(GT_RETURN, GT_RETFILT));
assert(treeNode->OperIs(GT_RETURN, GT_RETFILT, GT_SWIFT_ERROR_RET));

GenTree* op1 = treeNode->gtGetOp1();
GenTree* op1 = treeNode->AsOp()->GetReturnValue();
var_types targetType = treeNode->TypeGet();

// A void GT_RETFILT is the end of a finally. For non-void filter returns we need to load the result in the return
Expand Down Expand Up @@ -7869,7 +7869,7 @@ void CodeGen::genReturn(GenTree* treeNode)
//
// There should be a single GT_RETURN while generating profiler ELT callbacks.
//
if (treeNode->OperIs(GT_RETURN) && compiler->compIsProfilerHookNeeded())
if (treeNode->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET) && compiler->compIsProfilerHookNeeded())
{
// !! NOTE !!
// Since we are invalidating the assumption that we would slip into the epilog
Expand Down Expand Up @@ -7939,18 +7939,28 @@ void CodeGen::genReturn(GenTree* treeNode)

genStackPointerCheck(doStackPointerCheck, compiler->lvaReturnSpCheck);
#endif // defined(DEBUG) && defined(TARGET_XARCH)
}

#ifdef SWIFT_SUPPORT
// If this method has a SwiftError* out parameter, load the SwiftError pseudolocal value into the error register.
// TODO-CQ: Introduce GenTree node that models returning a normal and Swift error value.
if (compiler->lvaSwiftErrorArg != BAD_VAR_NUM)
{
assert(compiler->info.compCallConv == CorInfoCallConvExtension::Swift);
assert(compiler->lvaSwiftErrorLocal != BAD_VAR_NUM);
GetEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_SWIFT_ERROR, compiler->lvaSwiftErrorLocal, 0);
}
#endif // SWIFT_SUPPORT
//------------------------------------------------------------------------
// genSwiftErrorReturn: Generates code for returning the normal return value,
// and loading the SwiftError pseudolocal value in the error register.
//
// Arguments:
// treeNode - The GT_SWIFT_ERROR_RET tree node.
//
// Return Value:
// None
//
void CodeGen::genSwiftErrorReturn(GenTree* treeNode)
{
assert(treeNode->OperIs(GT_SWIFT_ERROR_RET));
GenTree* swiftErrorNode = treeNode->gtGetOp1();
const regNumber errorSrcReg = genConsumeReg(swiftErrorNode);
genReturn(treeNode);
inst_Mov(swiftErrorNode->TypeGet(), REG_SWIFT_ERROR, errorSrcReg, true, EA_PTRSIZE);
}
#endif // SWIFT_SUPPORT

//------------------------------------------------------------------------
// isStructReturn: Returns whether the 'treeNode' is returning a struct.
Expand All @@ -7959,15 +7969,15 @@ void CodeGen::genReturn(GenTree* treeNode)
// treeNode - The tree node to evaluate whether is a struct return.
//
// Return Value:
// Returns true if the 'treeNode" is a GT_RETURN node of type struct.
// Returns true if the 'treeNode' is a GT_RETURN/GT_SWIFT_ERROR_RET node of type struct.
// Otherwise returns false.
//
bool CodeGen::isStructReturn(GenTree* treeNode)
{
// This method could be called for 'treeNode' of GT_RET_FILT or GT_RETURN.
// This method could be called for 'treeNode' of GT_RET_FILT/GT_RETURN/GT_SWIFT_ERROR_RET.
// For the GT_RET_FILT, the return is always a bool or a void, for the end of a finally block.
noway_assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT);
if (treeNode->OperGet() != GT_RETURN)
noway_assert(treeNode->OperIs(GT_RETURN, GT_RETFILT, GT_SWIFT_ERROR_RET));
if (!treeNode->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET))
{
return false;
}
Expand All @@ -7994,7 +8004,7 @@ bool CodeGen::isStructReturn(GenTree* treeNode)
//
void CodeGen::genStructReturn(GenTree* treeNode)
{
assert(treeNode->OperGet() == GT_RETURN);
assert(treeNode->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET));

genConsumeRegs(treeNode->gtGetOp1());

Expand Down
10 changes: 9 additions & 1 deletion src/coreclr/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1402,13 +1402,15 @@ void CodeGen::genSIMDSplitReturn(GenTree* src, ReturnTypeDesc* retTypeDesc)
//
// Arguments:
// treeNode - The GT_RETURN or GT_RETFILT tree node with float type.
// (We don't expect treeNode to be a GT_SWIFT_ERROR_RET node,
// as Swift interop isn't supported on x86.)
//
// Return Value:
// None
//
void CodeGen::genFloatReturn(GenTree* treeNode)
{
assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT);
assert(treeNode->OperIs(GT_RETURN, GT_RETFILT));
assert(varTypeIsFloating(treeNode));

GenTree* op1 = treeNode->gtGetOp1();
Expand Down Expand Up @@ -1966,6 +1968,12 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
genReturn(treeNode);
break;

#ifdef SWIFT_SUPPORT
case GT_SWIFT_ERROR_RET:
genSwiftErrorReturn(treeNode);
break;
#endif // SWIFT_SUPPORT

case GT_LEA:
// If we are here, it is the case where there is an LEA that cannot be folded into a parent instruction.
genLeaInstruction(treeNode->AsAddrMode());
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/jit/fgstmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ void Compiler::fgInsertStmtNearEnd(BasicBlock* block, Statement* stmt)
}
else if (block->KindIs(BBJ_RETURN))
{
assert((lastStmt->GetRootNode()->OperIs(GT_RETURN, GT_JMP)) ||
assert((lastStmt->GetRootNode()->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET, GT_JMP)) ||
// BBJ_RETURN blocks in functions returning void do not get a GT_RETURN node if they
// have a .tail prefix (even if canTailCall returns false for these calls)
// code:Compiler::impImportBlockCode (search for the RET: label)
Expand Down Expand Up @@ -538,6 +538,7 @@ inline bool OperIsControlFlow(genTreeOps oper)

case GT_RETURN:
case GT_RETFILT:
case GT_SWIFT_ERROR_RET:
#if defined(FEATURE_EH_WINDOWS_X86)
case GT_END_LFIN:
#endif // FEATURE_EH_WINDOWS_X86
Expand Down
11 changes: 11 additions & 0 deletions src/coreclr/jit/flowgraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2026,6 +2026,17 @@ class MergedReturns
returnExpr = new (comp, GT_RETURN) GenTreeOp(GT_RETURN, TYP_VOID);
}

#ifdef SWIFT_SUPPORT
if (comp->lvaSwiftErrorArg != BAD_VAR_NUM)
{
assert(comp->info.compCallConv == CorInfoCallConvExtension::Swift);
assert(comp->lvaSwiftErrorLocal != BAD_VAR_NUM);
GenTree* const swiftErrorNode = comp->gtNewLclFldNode(comp->lvaSwiftErrorLocal, TYP_I_IMPL, 0);
returnExpr = new (comp, GT_SWIFT_ERROR_RET)
GenTreeOp(GT_SWIFT_ERROR_RET, returnExpr->TypeGet(), swiftErrorNode, returnExpr->gtGetOp1());
}
#endif // SWIFT_SUPPORT

// Add 'return' expression to the return block
comp->fgNewStmtAtEnd(newReturnBB, returnExpr);
// Flag that this 'return' was generated by return merging so that subsequent
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9650,6 +9650,10 @@ GenTree* Compiler::gtCloneExpr(GenTree* tree)
}
break;

case GT_SWIFT_ERROR_RET:
copy = new (this, oper) GenTreeOp(oper, tree->TypeGet(), tree->gtGetOp1(), tree->gtGetOp2());
break;

default:
assert(!GenTree::IsExOp(tree->OperKind()) && tree->OperIsSimple());
// We're in the SimpleOp case, so it's always unary or binary.
Expand Down
16 changes: 16 additions & 0 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,9 @@ struct GenTree
#endif // defined(TARGET_ARM64)

return true;

case GT_SWIFT_ERROR_RET:
return (gtType == TYP_VOID);
default:
return false;
}
Expand Down Expand Up @@ -3037,6 +3040,19 @@ struct GenTreeOp : public GenTreeUnOp
// then sets the flag GTF_DIV_BY_CNS_OPT and GTF_DONT_CSE on the constant
void CheckDivideByConstOptimized(Compiler* comp);

GenTree* GetReturnValue() const
{
assert(OperIs(GT_RETURN, GT_RETFILT, GT_SWIFT_ERROR_RET));
#ifdef SWIFT_SUPPORT
if (OperIs(GT_SWIFT_ERROR_RET))
{
return gtOp2;
}
#endif // SWIFT_SUPPORT

return gtOp1;
}

#if !defined(TARGET_64BIT) || defined(TARGET_ARM64)
bool IsValidLongMul();
#endif
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/jit/gtlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,8 @@ GTNODE(END_LFIN , GenTreeVal ,0,0,GTK_LEAF|GTK_NOVALUE) // End l
// Swift interop-specific nodes:
//-----------------------------------------------------------------------------

GTNODE(SWIFT_ERROR , GenTree ,0,0,GTK_LEAF) // Error register value post-Swift call
GTNODE(SWIFT_ERROR , GenTree ,0,0,GTK_LEAF) // Error register value post-Swift call
GTNODE(SWIFT_ERROR_RET , GenTreeOp ,0,1,GTK_BINOP|GTK_NOVALUE) // Returns normal return value, and SwiftError pseudolocal's value in REG_SWIFT_ERROR
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice with a comment that op1 has the error and op2 has the normal return value (or null if method returns void)


//-----------------------------------------------------------------------------
// Nodes used by Lower to generate a closer CPU representation of other nodes
Expand Down
16 changes: 16 additions & 0 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10883,6 +10883,22 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode)
}
}

#ifdef SWIFT_SUPPORT
// If this method has a SwiftError* out parameter, we need to set the error register upon returning.
// By placing the GT_SWIFT_ERROR_RET node before the GT_RETURN node,
// we don't have to teach the JIT that GT_SWIFT_ERROR_RET is a valid terminator for BBJ_RETURN blocks.
// During lowering, we will move the GT_SWIFT_ERROR_RET to the end of the block
// so the error register won't get trashed when returning the normal value.
if (lvaSwiftErrorArg != BAD_VAR_NUM)
{
assert(info.compCallConv == CorInfoCallConvExtension::Swift);
assert(lvaSwiftErrorLocal != BAD_VAR_NUM);
GenTree* const swiftErrorNode = gtNewLclFldNode(lvaSwiftErrorLocal, TYP_I_IMPL, 0);
op1 = new (this, GT_SWIFT_ERROR_RET)
GenTreeOp(GT_SWIFT_ERROR_RET, op1->TypeGet(), swiftErrorNode, op1->gtGetOp1());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is outdated now, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use op1->SetOper(GT_SWIFT_ERROR_RET) instead here to avoid the new node allocation. Of course that requires some shuffling of the operands, so just allocating a new node is also ok with me, if you like that better feel free to ignore this.

#endif // SWIFT_SUPPORT

impAppendTree(op1, CHECK_SPILL_NONE, impCurStmtDI);
#ifdef DEBUG
// Remember at which BC offset the tree was finished
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/jit/lclvars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1467,7 +1467,6 @@ bool Compiler::lvaInitSpecialSwiftParam(CORINFO_ARG_LIST_HANDLE argHnd,
// Instead, all usages of the SwiftError* parameter will be redirected to this pseudolocal.
lvaSwiftErrorLocal = lvaGrabTempWithImplicitUse(false DEBUGARG("SwiftError pseudolocal"));
lvaSetStruct(lvaSwiftErrorLocal, typeHnd, false);
lvaSetVarAddrExposed(lvaSwiftErrorLocal DEBUGARG(AddressExposedReason::ESCAPE_ADDRESS));
return true;
}

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/liveness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1939,6 +1939,7 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR
case GT_PUTARG_STK:
case GT_IL_OFFSET:
case GT_KEEPALIVE:
case GT_SWIFT_ERROR_RET:
// Never remove these nodes, as they are always side-effecting.
//
// NOTE: the only side-effect of some of these nodes (GT_CMP, GT_SUB_HI) is a write to the flags
Expand Down
34 changes: 28 additions & 6 deletions src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ GenTree* Lowering::LowerNode(GenTree* node)
break;

case GT_RETURN:
case GT_SWIFT_ERROR_RET:
LowerRet(node->AsUnOp());
break;

Expand Down Expand Up @@ -4544,19 +4545,19 @@ void Lowering::LowerJmpMethod(GenTree* jmp)
// Lower GT_RETURN node to insert PInvoke method epilog if required.
void Lowering::LowerRet(GenTreeUnOp* ret)
{
assert(ret->OperGet() == GT_RETURN);
assert(ret->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET));

JITDUMP("lowering GT_RETURN\n");
DISPNODE(ret);
JITDUMP("============\n");

GenTree* retVal = ret->gtGetOp1();
GenTree* retVal = ret->AsOp()->GetReturnValue();
// There are two kinds of retyping:
// - A simple bitcast can be inserted when:
// - We're returning a floating type as an integral type or vice-versa, or
// - If we're returning a struct as a primitive type, we change the type of
// 'retval' in 'LowerRetStructLclVar()'
bool needBitcast = (ret->TypeGet() != TYP_VOID) && !varTypeUsesSameRegType(ret, ret->gtGetOp1());
bool needBitcast = (ret->TypeGet() != TYP_VOID) && !varTypeUsesSameRegType(ret, retVal);
bool doPrimitiveBitcast = false;
if (needBitcast)
{
Expand Down Expand Up @@ -4625,6 +4626,27 @@ void Lowering::LowerRet(GenTreeUnOp* ret)
ContainCheckRet(ret);
}

//----------------------------------------------------------------------------------------------
// LowerSwiftErrorRet: Lower swift error return node by moving it to the end of its BBJ_RETURN block.
// We wait to do this late in the JIT's phases,
// as we typically expect BBJ_RETURN blocks to end with a GT_RETURN/GT_RETFILT node.
//
// Arguments:
// swiftErrorRet - The GT_SWIFT_ERROR_RET node.
//
// Return Value:
// The next node to be lowered.
//
GenTree* Lowering::LowerSwiftErrorRet(GenTree* swiftErrorRet)
{
assert(swiftErrorRet->OperIs(GT_SWIFT_ERROR_RET));
GenTree* const nextNode = swiftErrorRet->gtNext;
LIR::Range& blockRange = BlockRange();
blockRange.Remove(swiftErrorRet);
blockRange.InsertAtEnd(swiftErrorRet);
return nextNode;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this isn't needed anymore?


//----------------------------------------------------------------------------------------------
// LowerStoreLocCommon: platform independent part of local var or field store lowering.
//
Expand Down Expand Up @@ -4871,7 +4893,7 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret)
return;
}

assert(ret->OperIs(GT_RETURN));
assert(ret->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET));
assert(varTypeIsStruct(ret));

GenTree* retVal = ret->gtGetOp1();
Expand Down Expand Up @@ -4963,7 +4985,7 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret)
void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret)
{
assert(!comp->compMethodReturnsMultiRegRetType());
assert(ret->OperIs(GT_RETURN));
assert(ret->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET));
GenTreeLclVarCommon* lclVar = ret->gtGetOp1()->AsLclVar();
assert(lclVar->OperIs(GT_LCL_VAR));
unsigned lclNum = lclVar->GetLclNum();
Expand Down Expand Up @@ -8147,7 +8169,7 @@ void Lowering::ContainCheckLclHeap(GenTreeOp* node)
//
void Lowering::ContainCheckRet(GenTreeUnOp* ret)
{
assert(ret->OperIs(GT_RETURN));
assert(ret->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET));

#if !defined(TARGET_64BIT)
if (ret->TypeGet() == TYP_LONG)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/lower.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class Lowering final : public Phase
GenTreeCC* LowerNodeCC(GenTree* node, GenCondition condition);
void LowerJmpMethod(GenTree* jmp);
void LowerRet(GenTreeUnOp* ret);
GenTree* LowerSwiftErrorRet(GenTree* ret);
void LowerStoreLocCommon(GenTreeLclVarCommon* lclVar);
void LowerRetStruct(GenTreeUnOp* ret);
void LowerRetSingleRegStructLclVar(GenTreeUnOp* ret);
Expand Down
Loading
Loading