Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 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
9 changes: 5 additions & 4 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4109,7 +4109,7 @@ GenTree* Compiler::optAssertionProp_ModDiv(ASSERT_VALARG_TP assertions, GenTreeO
}

//------------------------------------------------------------------------
// optAssertionProp_Return: Try and optimize a GT_RETURN via assertions.
// optAssertionProp_Return: Try and optimize a GT_RETURN/GT_SWIFT_ERROR_RET via assertions.
//
// Propagates ZEROOBJ for the return value.
//
Expand All @@ -4124,9 +4124,9 @@ GenTree* Compiler::optAssertionProp_ModDiv(ASSERT_VALARG_TP assertions, GenTreeO
// Notes:
// stmt may be nullptr during local assertion prop
//
GenTree* Compiler::optAssertionProp_Return(ASSERT_VALARG_TP assertions, GenTreeUnOp* ret, Statement* stmt)
GenTree* Compiler::optAssertionProp_Return(ASSERT_VALARG_TP assertions, GenTreeOp* ret, Statement* stmt)
{
GenTree* retValue = ret->gtGetOp1();
GenTree* retValue = ret->GetReturnValue();

// Only propagate zeroes that lowering can deal with.
if (!ret->TypeIs(TYP_VOID) && varTypeIsStruct(retValue) && !varTypeIsStruct(info.compRetNativeType))
Expand Down Expand Up @@ -5512,7 +5512,8 @@ GenTree* Compiler::optAssertionProp(ASSERT_VALARG_TP assertions, GenTree* tree,
return optAssertionProp_BlockStore(assertions, tree->AsBlk(), stmt);

case GT_RETURN:
return optAssertionProp_Return(assertions, tree->AsUnOp(), stmt);
case GT_SWIFT_ERROR_RET:
return optAssertionProp_Return(assertions, tree->AsOp(), stmt);

case GT_MOD:
case GT_DIV:
Expand Down
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);
inst_Mov(swiftErrorNode->TypeGet(), REG_SWIFT_ERROR, errorSrcReg, true, EA_PTRSIZE);
genReturn(treeNode);
}
#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
5 changes: 3 additions & 2 deletions src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,9 +498,10 @@ void CodeGen::genCodeForBBlist()
// as the determiner because something we are tracking as a byref
// might be used as a return value of a int function (which is legal)
GenTree* blockLastNode = block->lastNode();
if ((blockLastNode != nullptr) && (blockLastNode->gtOper == GT_RETURN) &&
if ((blockLastNode != nullptr) && (blockLastNode->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET)) &&
(varTypeIsGC(compiler->info.compRetType) ||
(blockLastNode->AsOp()->gtOp1 != nullptr && varTypeIsGC(blockLastNode->AsOp()->gtOp1->TypeGet()))))
(blockLastNode->AsOp()->GetReturnValue() != nullptr &&
varTypeIsGC(blockLastNode->AsOp()->GetReturnValue()->TypeGet()))))
{
nonVarPtrRegs &= ~RBM_INTRET;
}
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
6 changes: 6 additions & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4717,6 +4717,12 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
//
DoPhase(this, PHASE_MORPH_ADD_INTERNAL, &Compiler::fgAddInternal);

#ifdef SWIFT_SUPPORT
// Transform GT_RETURN nodes into GT_SWIFT_ERROR_RET nodes if this method has Swift error handling
//
DoPhase(this, PHASE_SWIFT_ERROR_RET, &Compiler::fgAddSwiftErrorReturns);
#endif // SWIFT_SUPPORT

// Remove empty try regions
//
DoPhase(this, PHASE_EMPTY_TRY, &Compiler::fgRemoveEmptyTry);
Expand Down
12 changes: 10 additions & 2 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5279,6 +5279,10 @@ class Compiler

PhaseStatus fgAddInternal();

#ifdef SWIFT_SUPPORT
PhaseStatus fgAddSwiftErrorReturns();
#endif // SWIFT_SUPPORT

enum class FoldResult
{
FOLD_DID_NOTHING,
Expand Down Expand Up @@ -6523,7 +6527,7 @@ class Compiler
GenTree* fgOptimizeBitwiseAnd(GenTreeOp* andOp);
GenTree* fgOptimizeBitwiseXor(GenTreeOp* xorOp);
GenTree* fgPropagateCommaThrow(GenTree* parent, GenTreeOp* commaThrow, GenTreeFlags precedingSideEffects);
GenTree* fgMorphRetInd(GenTreeUnOp* tree);
GenTree* fgMorphRetInd(GenTreeOp* tree);
GenTree* fgMorphModToZero(GenTreeOp* tree);
GenTree* fgMorphModToSubMulDiv(GenTreeOp* tree);
GenTree* fgMorphUModToAndSub(GenTreeOp* tree);
Expand Down Expand Up @@ -7878,7 +7882,7 @@ class Compiler
GenTree* optAssertionProp_LocalStore(ASSERT_VALARG_TP assertions, GenTreeLclVarCommon* store, Statement* stmt);
GenTree* optAssertionProp_BlockStore(ASSERT_VALARG_TP assertions, GenTreeBlk* store, Statement* stmt);
GenTree* optAssertionProp_ModDiv(ASSERT_VALARG_TP assertions, GenTreeOp* tree, Statement* stmt);
GenTree* optAssertionProp_Return(ASSERT_VALARG_TP assertions, GenTreeUnOp* ret, Statement* stmt);
GenTree* optAssertionProp_Return(ASSERT_VALARG_TP assertions, GenTreeOp* ret, Statement* stmt);
GenTree* optAssertionProp_Ind(ASSERT_VALARG_TP assertions, GenTree* tree, Statement* stmt);
GenTree* optAssertionProp_Cast(ASSERT_VALARG_TP assertions, GenTreeCast* cast, Statement* stmt);
GenTree* optAssertionProp_Call(ASSERT_VALARG_TP assertions, GenTreeCall* call, Statement* stmt);
Expand Down Expand Up @@ -8406,6 +8410,10 @@ class Compiler
unsigned genReturnLocal; // Local number for the return value when applicable.
BasicBlock* genReturnBB; // jumped to when not optimizing for speed.

#ifdef SWIFT_SUPPORT
unsigned genReturnErrorLocal; // Local number for the Swift error value when applicable.
#endif // SWIFT_SUPPORT

// The following properties are part of CodeGenContext. Getters are provided here for
// convenience and backward compatibility, but the properties can only be set by invoking
// the setter on CodeGenContext directly.
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/compphases.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ CompPhaseNameMacro(PHASE_INCPROFILE, "Profile incorporation",
CompPhaseNameMacro(PHASE_MORPH_INIT, "Morph - Init", false, -1, false)
CompPhaseNameMacro(PHASE_MORPH_INLINE, "Morph - Inlining", false, -1, true)
CompPhaseNameMacro(PHASE_MORPH_ADD_INTERNAL, "Morph - Add internal blocks", false, -1, true)
CompPhaseNameMacro(PHASE_SWIFT_ERROR_RET, "Add Swift error returns", false, -1, true)
CompPhaseNameMacro(PHASE_ALLOCATE_OBJECTS, "Allocate Objects", false, -1, false)
CompPhaseNameMacro(PHASE_EMPTY_TRY, "Remove empty try", false, -1, false)
CompPhaseNameMacro(PHASE_EMPTY_FINALLY, "Remove empty finally", false, -1, false)
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/jit/decomposelongs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ GenTree* DecomposeLongs::DecomposeNode(GenTree* tree)
break;

case GT_RETURN:
assert(tree->AsOp()->gtOp1->OperGet() == GT_LONG);
case GT_SWIFT_ERROR_RET:
assert(tree->AsOp()->GetReturnValue()->OperIs(GT_LONG));
break;

case GT_STOREIND:
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/jit/fgbasic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ void Compiler::fgInit()
genReturnBB = nullptr;
genReturnLocal = BAD_VAR_NUM;

#ifdef SWIFT_SUPPORT
genReturnErrorLocal = BAD_VAR_NUM;
#endif // SWIFT_SUPPORT

/* We haven't reached the global morphing phase */
fgGlobalMorph = false;
fgGlobalMorphDone = false;
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
51 changes: 50 additions & 1 deletion src/coreclr/jit/flowgraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1586,7 +1586,7 @@ GenTree* Compiler::fgCreateMonitorTree(unsigned lvaMonAcquired, unsigned lvaThis
}
#endif

if (block->KindIs(BBJ_RETURN) && block->lastStmt()->GetRootNode()->gtOper == GT_RETURN)
if (block->KindIs(BBJ_RETURN) && block->lastStmt()->GetRootNode()->OperIs(GT_RETURN))
{
GenTreeUnOp* retNode = block->lastStmt()->GetRootNode()->AsUnOp();
GenTree* retExpr = retNode->gtOp1;
Expand Down Expand Up @@ -2559,6 +2559,55 @@ PhaseStatus Compiler::fgAddInternal()
return madeChanges ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING;
}

#ifdef SWIFT_SUPPORT
//------------------------------------------------------------------------
// fgAddSwiftErrorReturns: If this method uses Swift error handling,
// transform all GT_RETURN nodes into GT_SWIFT_ERROR_RET nodes
// to handle returning the error value alongside the normal return value.
//
// Returns:
// Suitable phase status.
//
PhaseStatus Compiler::fgAddSwiftErrorReturns()
{
if (lvaSwiftErrorArg == BAD_VAR_NUM)
{
// No Swift error handling in this method
return PhaseStatus::MODIFIED_NOTHING;
}

assert(lvaSwiftErrorLocal != BAD_VAR_NUM);
assert(info.compCallConv == CorInfoCallConvExtension::Swift);

for (BasicBlock* block : Blocks())
{
if (block->KindIs(BBJ_RETURN))
{
GenTree* const ret = block->lastNode();
assert(ret->OperIs(GT_RETURN));
ret->SetOperRaw(GT_SWIFT_ERROR_RET);
ret->AsOp()->gtOp2 = ret->AsOp()->gtOp1;

// If this is the merged return block, use the merged return error local as the error operand.
// Else, load the error value from the SwiftError pseudolocal (this will probably get promoted, anyway).
if (block == genReturnBB)
{
assert(genReturnErrorLocal == BAD_VAR_NUM);
genReturnErrorLocal = lvaGrabTemp(true DEBUGARG("Single return block SwiftError value"));
lvaGetDesc(genReturnErrorLocal)->lvType = genActualType(TYP_I_IMPL);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
lvaGetDesc(genReturnErrorLocal)->lvType = genActualType(TYP_I_IMPL);
lvaGetDesc(genReturnErrorLocal)->lvType = TYP_I_IMPL;

ret->AsOp()->gtOp1 = gtNewLclvNode(genReturnErrorLocal, TYP_I_IMPL);
}
else
{
ret->AsOp()->gtOp1 = gtNewLclFldNode(lvaSwiftErrorLocal, TYP_I_IMPL, 0);
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

I still think it would be nice to do the replacement of lvaSwiftErrorArg with lvaSwiftErrorLocal here too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That was my plan, though I was hitting asserts around fgNodeThreading being invalid when trying to use any of the GenTree iterators -- LocalsGenTreeList seems like it would be the most efficient one for finding the SwiftError* arg uses. Is there a clean way of doing the IR traversal without breaking any of these iterators' invariants?

Copy link
Member

Choose a reason for hiding this comment

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

At this point we don't have threaded IR nodes (the comment on fgNodeThreading has some relevant information), but you can use GenTreeVisitor to do it.

Copy link
Member

Choose a reason for hiding this comment

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

optReplaceScalarUsesWithConst looks close to what you want to do I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

optReplaceScalarUsesWithConst looks close to what you want to do I think.

Thanks! GenTreeVisitor works.


return PhaseStatus::MODIFIED_EVERYTHING;
}
#endif // SWIFT_SUPPORT

/*****************************************************************************/
/*****************************************************************************/

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/forwardsub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ bool Compiler::fgForwardSubStatement(Statement* stmt)
// interaction between decomposition and RA.
//
if (compMethodReturnsMultiRegRetType() && (fsv.GetParentNode() != nullptr) &&
fsv.GetParentNode()->OperIs(GT_RETURN))
fsv.GetParentNode()->OperIs(GT_RETURN, GT_SWIFT_ERROR_RET))
{
#if defined(TARGET_X86)
if (fwdSubNode->TypeGet() == TYP_LONG)
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
Loading