@@ -71,20 +71,26 @@ int emitLocation::GetInsOffset() const
7171 return emitGetInsOfsFromCodePos (codePos);
7272}
7373
74- // Get the instruction offset in the current instruction group , which must be a funclet prolog group .
74+ // Get the instruction offset in the current instruction region , which must be a funclet prolog.
7575// This is used to find an instruction offset used in unwind data.
76- // TODO-AMD64-Bug?: We only support a single main function prolog group, but allow for multiple funclet prolog
77- // groups (not that we actually use that flexibility, since the funclet prolog will be small). How to
78- // handle that?
7976UNATIVE_OFFSET emitLocation::GetFuncletPrologOffset (emitter* emit) const
8077{
8178 assert (ig->igFuncIdx != 0 );
8279 assert ((ig->igFlags & IGF_FUNCLET_PROLOG) != 0 );
83- assert (ig == emit->emitCurIG );
80+ assert ((ig->igFlags & IGF_OUT_OF_ORDER_HEAD) != 0 );
81+ assert (GetInsOffset () == 0 );
8482
85- return emit->emitCurIGsize ;
86- }
83+ unsigned offset = 0 ;
84+ insGroup* lastIG = ig;
85+ while (lastIG != emit->emitCurIG )
86+ {
87+ offset += lastIG->igSize ;
88+ lastIG = lastIG->igNext ;
89+ }
90+ assert ((lastIG->igFlags & IGF_FUNCLET_PROLOG) != 0 );
8791
92+ return offset + emit->emitCurIGsize ;
93+ }
8894// ------------------------------------------------------------------------
8995// IsPreviousInsNum: Returns true if the emitter is on the next instruction
9096// of the same group as this emitLocation.
@@ -120,26 +126,133 @@ void emitLocation::Print(LONG compMethodID) const
120126}
121127#endif // DEBUG
122128
129+ // ------------------------------------------------------------------------
130+ // InitializeNum: Initialize this IG's order/display number.
131+ //
132+ // Each subsequently allocated group should be assigned a monotonically
133+ // increasing number.
134+ //
135+ // Arguments:
136+ // num - The number
137+ //
123138void insGroup::InitializeNum (unsigned num)
124139{
125140 igNum = num;
126141}
127142
143+ // ------------------------------------------------------------------------
144+ // GetDisplayId: Get the ID of this group used for display.
145+ //
146+ // Return Value:
147+ // A unique ID for this group.
148+ //
128149unsigned insGroup::GetDisplayId () const
129150{
130151 return igNum;
131152}
132153
154+ // ------------------------------------------------------------------------
155+ // IsBefore: Is this group before 'ig' in layout (IG list) order?
156+ //
157+ // Most groups are generated in-order, such that their 'numbers' reflect
158+ // both the layout and IG linked list order. However, for prologs/epilogs,
159+ // we can have extend groups that are generated after the IR-driven code,
160+ // and this function accounts for that.
161+ //
162+ // Arguments:
163+ // ig - The group to compare to
164+ //
165+ // Return Value:
166+ // Whether 'this' is before 'ig'.
167+ //
133168bool insGroup::IsBefore (const insGroup* ig) const
134169{
135- return igNum < ig->igNum ;
170+ assert (ig != nullptr );
171+
172+ // All IGs are generated in order, except the extend groups that may hangs off prologs and epilogs.
173+ // In turn, those groups themselves are generated in order within their respective regions.
174+ unsigned positionOfThis;
175+ if ((igFlags & IGF_OUT_OF_ORDER_MASK) != 0 )
176+ {
177+ const insGroup* nextIG = igNext;
178+ while (true )
179+ {
180+ if (nextIG == nullptr )
181+ {
182+ return false ;
183+ }
184+ if (((nextIG->igFlags & IGF_OUT_OF_ORDER_MASK) == 0 ) || ((nextIG->igFlags & IGF_OUT_OF_ORDER_HEAD) != 0 ))
185+ {
186+ positionOfThis = nextIG->igNum - 1 ; // Position equal to the in-order 'head' of the region.
187+ break ;
188+ }
189+ if (nextIG == ig)
190+ {
191+ return true ;
192+ }
193+
194+ nextIG = nextIG->igNext ;
195+ }
196+ }
197+ else
198+ {
199+ positionOfThis = igNum;
200+ }
201+
202+ unsigned positionOfIG;
203+ if ((ig->igFlags & IGF_OUT_OF_ORDER_MASK) != 0 )
204+ {
205+ const insGroup* nextIG = ig->igNext ;
206+ while (true )
207+ {
208+ if (nextIG == nullptr )
209+ {
210+ return true ;
211+ }
212+ if (((nextIG->igFlags & IGF_OUT_OF_ORDER_MASK) == 0 ) || ((nextIG->igFlags & IGF_OUT_OF_ORDER_HEAD) != 0 ))
213+ {
214+ positionOfIG = nextIG->igNum - 1 ;
215+ break ;
216+ }
217+ if (nextIG == this )
218+ {
219+ return false ;
220+ }
221+
222+ nextIG = nextIG->igNext ;
223+ }
224+ }
225+ else
226+ {
227+ positionOfIG = ig->igNum ;
228+ }
229+
230+ return positionOfThis < positionOfIG;
136231}
137232
233+ // ------------------------------------------------------------------------
234+ // IsBefore: Is this group before 'ig' in layout order, or equal to it?
235+ //
236+ // Arguments:
237+ // ig - The group to compare to
238+ //
239+ // Return Value:
240+ // Whether 'this' is before 'ig' or is equal to it.
241+ //
138242bool insGroup::IsBeforeOrEqual (const insGroup* ig) const
139243{
140244 return !IsAfter (ig);
141245}
142246
247+ // ------------------------------------------------------------------------
248+ // IsBefore: Is this group after 'ig' in layout order?
249+ //
250+ // Arguments:
251+ // ig - The group to compare to
252+ //
253+ // Return Value:
254+ // Whether 'this' is after 'ig'.
255+ //
143256bool insGroup::IsAfter (const insGroup* ig) const
144257{
145258 return ig->IsBefore (this );
@@ -1623,16 +1736,8 @@ void* emitter::emitAllocAnyInstr(size_t sz, emitAttr opsz)
16231736{
16241737#ifdef DEBUG
16251738 // Under STRESS_EMITTER, put every instruction in its own instruction group.
1626- // We can't do this for a prolog, epilog, funclet prolog, or funclet epilog,
1627- // because those are generated out of order. We currently have a limitation
1628- // where the jump shortening pass uses the instruction group number to determine
1629- // if something is earlier or later in the code stream. This implies that
1630- // these groups cannot be more than a single instruction group. Note that
1631- // the prolog/epilog placeholder groups ARE generated in order, and are
1632- // re-used. But generating additional groups would not work.
16331739 if (m_compiler->compStressCompile (Compiler::STRESS_EMITTER, 1 ) && emitCurIGinsCnt && !emitIGisInProlog (emitCurIG) &&
1634- !emitIGisInEpilog (emitCurIG) && !emitCurIG->endsWithAlignInstr () && !emitIGisInFuncletProlog (emitCurIG) &&
1635- !emitIGisInFuncletEpilog (emitCurIG))
1740+ !emitCurIG->endsWithAlignInstr ())
16361741 {
16371742 emitNxtIG (true );
16381743 }
@@ -2161,6 +2266,7 @@ void emitter::emitCreatePlaceholderIG(insGroupPlaceholderType igType,
21612266 {
21622267 igPh->igFlags |= IGF_FUNCLET_EPILOG;
21632268 }
2269+ igPh->igFlags |= IGF_OUT_OF_ORDER_HEAD;
21642270
21652271 /* Link it into the placeholder list */
21662272
@@ -2402,7 +2508,7 @@ void emitter::emitBegPrologEpilog(insGroup* igPh)
24022508 m_compiler->funSetCurrentFunc (ig->igFuncIdx );
24032509
24042510 /* Set the new IG as the place to generate code */
2405-
2511+ emitCurCodeOffset = ig-> igOffs ;
24062512 emitGenIG (ig);
24072513
24082514#if EMIT_TRACK_STACK_DEPTH
0 commit comments