diff --git a/src/coreclr/jit/abi.cpp b/src/coreclr/jit/abi.cpp index 35d7fc1aa70a31..04043c359246e5 100644 --- a/src/coreclr/jit/abi.cpp +++ b/src/coreclr/jit/abi.cpp @@ -246,6 +246,30 @@ ABIPassingSegment& ABIPassingInformation::Segment(unsigned index) return const_cast(static_cast(*this).Segment(index)); } +//----------------------------------------------------------------------------- +// Segments: +// Get an iterator pair that can be used with range-based for to iterate the +// segments. +// +// Returns: +// Iterator pair. +// +IteratorPair ABIPassingInformation::Segments() const +{ + const ABIPassingSegment* begin; + if (NumSegments == 1) + { + begin = &m_singleSegment; + } + else + { + begin = m_segments; + } + + return IteratorPair(ABIPassingSegmentIterator(begin), + ABIPassingSegmentIterator(begin + NumSegments)); +} + //----------------------------------------------------------------------------- // HasAnyRegisterSegment: // Check if any part of this value is passed in a register. @@ -255,9 +279,9 @@ ABIPassingSegment& ABIPassingInformation::Segment(unsigned index) // bool ABIPassingInformation::HasAnyRegisterSegment() const { - for (unsigned i = 0; i < NumSegments; i++) + for (const ABIPassingSegment& seg : Segments()) { - if (Segment(i).IsPassedInRegister()) + if (seg.IsPassedInRegister()) { return true; } @@ -274,9 +298,9 @@ bool ABIPassingInformation::HasAnyRegisterSegment() const // bool ABIPassingInformation::HasAnyFloatingRegisterSegment() const { - for (unsigned i = 0; i < NumSegments; i++) + for (const ABIPassingSegment& seg : Segments()) { - if (Segment(i).IsPassedInRegister() && genIsValidFloatReg(Segment(i).GetRegister())) + if (seg.IsPassedInRegister() && genIsValidFloatReg(seg.GetRegister())) { return true; } @@ -293,9 +317,9 @@ bool ABIPassingInformation::HasAnyFloatingRegisterSegment() const // bool ABIPassingInformation::HasAnyStackSegment() const { - for (unsigned i = 0; i < NumSegments; i++) + for (const ABIPassingSegment& seg : Segments()) { - if (Segment(i).IsPassedOnStack()) + if (seg.IsPassedOnStack()) { return true; } @@ -365,9 +389,8 @@ unsigned ABIPassingInformation::CountRegsAndStackSlots() const { unsigned numSlots = 0; - for (unsigned i = 0; i < NumSegments; i++) + for (const ABIPassingSegment& seg : Segments()) { - const ABIPassingSegment& seg = Segment(i); if (seg.IsPassedInRegister()) { numSlots++; @@ -547,9 +570,9 @@ ABIPassingInformation SwiftABIClassifier::Classify(Compiler* comp, var_types elemType = JITtype2varType(lowering->loweredElements[i]); ABIPassingInformation elemInfo = m_classifier.Classify(comp, elemType, nullptr, WellKnownArg::None); - for (unsigned j = 0; j < elemInfo.NumSegments; j++) + for (const ABIPassingSegment& seg : elemInfo.Segments()) { - ABIPassingSegment newSegment = elemInfo.Segment(j); + ABIPassingSegment newSegment = seg; newSegment.Offset += lowering->offsets[i]; // Adjust the tail size if necessary; the lowered sequence can // pass the tail as a larger type than the tail size. diff --git a/src/coreclr/jit/abi.h b/src/coreclr/jit/abi.h index 67df674c893ffc..66566f44db5fa6 100644 --- a/src/coreclr/jit/abi.h +++ b/src/coreclr/jit/abi.h @@ -40,6 +40,41 @@ class ABIPassingSegment static ABIPassingSegment OnStack(unsigned stackOffset, unsigned offset, unsigned size); }; +class ABIPassingSegmentIterator +{ + const ABIPassingSegment* m_value; +public: + explicit ABIPassingSegmentIterator(const ABIPassingSegment* value) + : m_value(value) + { + } + + const ABIPassingSegment& operator*() const + { + return *m_value; + } + const ABIPassingSegment* operator->() const + { + return m_value; + } + + ABIPassingSegmentIterator& operator++() + { + m_value++; + return *this; + } + + bool operator==(const ABIPassingSegmentIterator& other) const + { + return m_value == other.m_value; + } + + bool operator!=(const ABIPassingSegmentIterator& other) const + { + return m_value != other.m_value; + } +}; + struct ABIPassingInformation { private: @@ -71,8 +106,9 @@ struct ABIPassingInformation ABIPassingInformation(Compiler* comp, unsigned numSegments); - const ABIPassingSegment& Segment(unsigned index) const; - ABIPassingSegment& Segment(unsigned index); + const ABIPassingSegment& Segment(unsigned index) const; + ABIPassingSegment& Segment(unsigned index); + IteratorPair Segments() const; bool HasAnyRegisterSegment() const; bool HasAnyFloatingRegisterSegment() const; diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 5617c6dfc9135f..99220ca4be928d 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -3503,9 +3503,8 @@ void CodeGen::genCallInstruction(GenTreeCall* call) for (CallArg& arg : call->gtArgs.Args()) { - for (unsigned i = 0; i < arg.NewAbiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : arg.NewAbiInfo.Segments()) { - const ABIPassingSegment& seg = arg.NewAbiInfo.Segment(i); if (seg.IsPassedInRegister() && ((trashedByEpilog & seg.GetRegisterMask()) != 0)) { JITDUMP("Tail call node:\n"); @@ -3738,9 +3737,8 @@ void CodeGen::genJmpPlaceVarArgs() for (unsigned varNum = 0; varNum < compiler->info.compArgsCount; varNum++) { const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(varNum); - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& segment : abiInfo.Segments()) { - const ABIPassingSegment& segment = abiInfo.Segment(i); if (segment.IsPassedInRegister()) { potentialArgs &= ~segment.GetRegisterMask(); diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index aef98b007d4824..bc0bda41152afe 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -3253,9 +3253,8 @@ void CodeGen::genSpillOrAddRegisterParam(unsigned lclNum, RegGraph* graph) unsigned paramLclNum = varDsc->lvIsStructField ? varDsc->lvParentLcl : lclNum; LclVarDsc* paramVarDsc = compiler->lvaGetDesc(paramLclNum); const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(paramLclNum); - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : abiInfo.Segments()) { - const ABIPassingSegment& seg = abiInfo.Segment(i); if (!seg.IsPassedInRegister() || ((paramRegs & genRegMask(seg.GetRegister())) == 0)) { continue; @@ -3376,9 +3375,8 @@ void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) } const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : abiInfo.Segments()) { - const ABIPassingSegment& seg = abiInfo.Segment(i); if (seg.IsPassedInRegister() && ((paramRegs & genRegMask(seg.GetRegister())) != 0)) { var_types storeType = genParamStackType(lclDsc, seg); @@ -4425,9 +4423,8 @@ void CodeGen::genHomeSwiftStructParameters(bool handleStack) const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); DBEXEC(VERBOSE, abiInfo.Dump()); - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : abiInfo.Segments()) { - const ABIPassingSegment& seg = abiInfo.Segment(i); if (seg.IsPassedOnStack() != handleStack) { continue; @@ -7489,9 +7486,8 @@ void CodeGen::genCallPlaceRegArgs(GenTreeCall* call) if (argNode->OperIs(GT_FIELD_LIST)) { GenTreeFieldList::Use* use = argNode->AsFieldList()->Uses().begin().GetUse(); - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : abiInfo.Segments()) { - const ABIPassingSegment& seg = abiInfo.Segment(i); if (!seg.IsPassedInRegister()) { continue; @@ -7519,9 +7515,8 @@ void CodeGen::genCallPlaceRegArgs(GenTreeCall* call) assert(compFeatureArgSplit()); genConsumeArgSplitStruct(argNode->AsPutArgSplit()); unsigned regIndex = 0; - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : abiInfo.Segments()) { - const ABIPassingSegment& seg = abiInfo.Segment(i); if (!seg.IsPassedInRegister()) { continue; @@ -7557,9 +7552,8 @@ void CodeGen::genCallPlaceRegArgs(GenTreeCall* call) { for (CallArg& arg : call->gtArgs.Args()) { - for (unsigned i = 0; i < arg.NewAbiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : arg.NewAbiInfo.Segments()) { - const ABIPassingSegment& seg = arg.NewAbiInfo.Segment(i); if (seg.IsPassedInRegister() && genIsValidFloatReg(seg.GetRegister())) { regNumber targetReg = compiler->getCallArgIntRegister(seg.GetRegister()); @@ -7640,9 +7634,8 @@ void CodeGen::genJmpPlaceArgs(GenTree* jmp) LclVarDsc* varDsc = compiler->lvaGetDesc(varNum); const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(varNum); - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& segment : abiInfo.Segments()) { - const ABIPassingSegment& segment = abiInfo.Segment(i); if (segment.IsPassedOnStack()) { continue; diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 4102d4c7711150..c622304e1a8e93 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -6559,9 +6559,8 @@ void CodeGen::genJmpPlaceVarArgs() for (unsigned varNum = 0; varNum < compiler->info.compArgsCount; varNum++) { const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(varNum); - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& segment : abiInfo.Segments()) { - const ABIPassingSegment& segment = abiInfo.Segment(i); if (segment.IsPassedOnStack()) { continue; diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index d4adbd6b9907a0..2be18fd50cac0e 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -1741,9 +1741,8 @@ void Compiler::lvaClassifyParameterABI() } } - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& segment : abiInfo.Segments()) { - const ABIPassingSegment& segment = abiInfo.Segment(i); if (segment.IsPassedInRegister()) { argRegs |= segment.GetRegisterMask(); @@ -5959,9 +5958,8 @@ bool Compiler::lvaGetRelativeOffsetToCallerAllocatedSpaceForParameter(unsigned l { const ABIPassingInformation& abiInfo = lvaGetParameterABIInfo(lclNum); - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& segment : abiInfo.Segments()) { - const ABIPassingSegment& segment = abiInfo.Segment(i); if (!segment.IsPassedOnStack()) { #if defined(WINDOWS_AMD64_ABI) diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 368a5e82d53c75..fa3ce2ccc9320a 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -2292,9 +2292,8 @@ void LinearScan::buildIntervals() } const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : abiInfo.Segments()) { - const ABIPassingSegment& seg = abiInfo.Segment(i); if (seg.IsPassedInRegister()) { RegState* regState = genIsValidFloatReg(seg.GetRegister()) ? floatRegState : intRegState; diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index 7f50c8be9b5077..cf3f3efacd9fac 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -1226,9 +1226,8 @@ int LinearScan::BuildCall(GenTreeCall* call) { for (CallArg& arg : call->gtArgs.LateArgs()) { - for (unsigned i = 0; i < arg.NewAbiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : arg.NewAbiInfo.Segments()) { - const ABIPassingSegment& seg = arg.NewAbiInfo.Segment(i); if (seg.IsPassedInRegister() && genIsValidFloatReg(seg.GetRegister())) { regNumber argReg = seg.GetRegister(); diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 10bd141b8b4d8b..45e1c16ecf8932 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -2162,9 +2162,8 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call arg.AbiInfo.SetSplit(true); arg.AbiInfo.ByteOffset = 0; unsigned regNumIndex = 0; - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& segment : abiInfo.Segments()) { - const ABIPassingSegment& segment = abiInfo.Segment(i); if (segment.IsPassedInRegister()) { if (regNumIndex < MAX_ARG_REG_COUNT) @@ -2187,10 +2186,8 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call m_hasRegArgs = true; unsigned regNumIndex = 0; - for (unsigned i = 0; i < abiInfo.NumSegments; i++) + for (const ABIPassingSegment& segment : abiInfo.Segments()) { - const ABIPassingSegment& segment = abiInfo.Segment(i); - if (regNumIndex < MAX_ARG_REG_COUNT) { arg.AbiInfo.SetRegNum(regNumIndex, segment.GetRegister()); @@ -2976,9 +2973,8 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg) { bool fieldsMatch = true; - for (unsigned i = 0; i < arg->NewAbiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : arg->NewAbiInfo.Segments()) { - const ABIPassingSegment& seg = arg->NewAbiInfo.Segment(i); if (seg.IsPassedInRegister()) { unsigned fieldLclNum = lvaGetFieldLocal(varDsc, seg.Offset); @@ -3119,9 +3115,8 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg) newArg = new (this, GT_FIELD_LIST) GenTreeFieldList(); - for (unsigned i = 0; i < arg->NewAbiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : arg->NewAbiInfo.Segments()) { - const ABIPassingSegment& seg = arg->NewAbiInfo.Segment(i); if (seg.IsPassedInRegister()) { var_types regType = seg.GetRegisterType(); diff --git a/src/coreclr/jit/promotion.cpp b/src/coreclr/jit/promotion.cpp index 7fe9bffa70e943..d3051286c34c2a 100644 --- a/src/coreclr/jit/promotion.cpp +++ b/src/coreclr/jit/promotion.cpp @@ -2133,10 +2133,8 @@ bool ReplaceVisitor::ReplaceCallArgWithFieldList(GenTreeCall* call, GenTreeLclVa assert(layout != nullptr); StructDeaths deaths = m_liveness->GetDeathsForStructLocal(argNode); GenTreeFieldList* fieldList = new (m_compiler, GT_FIELD_LIST) GenTreeFieldList; - for (unsigned i = 0; i < callArg->NewAbiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : callArg->NewAbiInfo.Segments()) { - const ABIPassingSegment& seg = callArg->NewAbiInfo.Segment(i); - Replacement* rep = nullptr; if (agg->OverlappingReplacements(argNode->GetLclOffs() + seg.Offset, seg.Size, &rep, nullptr) && rep->NeedsWriteBack) @@ -2228,9 +2226,8 @@ bool ReplaceVisitor::CanReplaceCallArgWithFieldListOfReplacements(GenTreeCall* assert(agg != nullptr); bool anyReplacements = false; - for (unsigned i = 0; i < callArg->NewAbiInfo.NumSegments; i++) + for (const ABIPassingSegment& seg : callArg->NewAbiInfo.Segments()) { - const ABIPassingSegment& seg = callArg->NewAbiInfo.Segment(i); assert(seg.IsPassedInRegister()); auto callback = [=, &anyReplacements, &seg](Replacement& rep) {