@@ -1238,16 +1238,14 @@ insGroup* emitter::emitSavIG(bool emitAdd)
12381238
12391239 assert (last == nullptr || last->idjOffs > nj->idjOffs );
12401240
1241- if (ig->igFlags & IGF_FUNCLET_PROLOG )
1241+ if (( ig->igFlags & IGF_OUT_OF_ORDER_MASK ) != 0 )
12421242 {
1243- // Our funclet prologs have short jumps, if the prolog would ever have
1244- // long jumps, then we'd have to insert the list in sorted order than
1245- // just append to the emitJumpList.
1246- noway_assert (nj->idjShort );
1247- if (nj->idjShort )
1248- {
1249- continue ;
1250- }
1243+ // Our out of order groups have short jumps. If we ever need the shortening capability
1244+ // for these jumps, we'll need to insert them at the appropriate place in emitJumpList.
1245+ nj->idjNext = emitFixedSizeJumpList;
1246+ emitFixedSizeJumpList = nj;
1247+ assert (nj->idjShort );
1248+ continue ;
12511249 }
12521250
12531251 // Append the new jump to the list
@@ -1264,8 +1262,7 @@ insGroup* emitter::emitSavIG(bool emitAdd)
12641262 if (last != nullptr )
12651263 {
12661264 // Append the jump(s) from this IG to the global list
1267- bool prologJump = emitIGisInProlog (ig);
1268- if ((emitJumpList == nullptr ) || prologJump)
1265+ if (emitJumpList == nullptr )
12691266 {
12701267 last->idjNext = emitJumpList;
12711268 emitJumpList = list;
@@ -1276,10 +1273,7 @@ insGroup* emitter::emitSavIG(bool emitAdd)
12761273 emitJumpLast->idjNext = list;
12771274 }
12781275
1279- if (!prologJump || (emitJumpLast == nullptr ))
1280- {
1281- emitJumpLast = last;
1282- }
1276+ emitJumpLast = last;
12831277 }
12841278 }
12851279
@@ -1372,6 +1366,7 @@ void emitter::emitBegFN(bool hasFramePtr
13721366 /* We don't have any jumps */
13731367
13741368 emitJumpList = emitJumpLast = nullptr ;
1369+ emitFixedSizeJumpList = nullptr ;
13751370 emitCurIGjmpList = nullptr ;
13761371
13771372 emitFwdJumps = false ;
@@ -2416,14 +2411,15 @@ void emitter::emitBegPrologEpilog(insGroup* igPh)
24162411 emitThisGCrefRegs = emitInitGCrefRegs = igPh->igPhData ->igPhInitGCrefRegs ;
24172412 emitThisByrefRegs = emitInitByrefRegs = igPh->igPhData ->igPhInitByrefRegs ;
24182413
2414+ // Set the current BB for label creation.
2415+ m_compiler->compCurBB = igPh->igPhData ->igPhBB ;
2416+
24192417 igPh->igPhData = nullptr ;
24202418
24212419 /* Create a non-placeholder group pointer that we'll now use */
2422-
24232420 insGroup* ig = igPh;
24242421
24252422 /* Set the current function using the function index we stored */
2426-
24272423 m_compiler->funSetCurrentFunc (ig->igFuncIdx );
24282424
24292425 /* Set the new IG as the place to generate code */
@@ -3602,6 +3598,26 @@ void emitter::emitSetSecondRetRegGCType(instrDescCGCA* id, emitAttr secondRetSiz
36023598#endif // MULTIREG_HAS_SECOND_GC_RET
36033599
36043600#ifndef TARGET_WASM
3601+ // ------------------------------------------------------------------------
3602+ // emitIns_ShortJ: Emit a 'forced' short jump.
3603+ //
3604+ // Jumps in prologs are hardcoded to be short since we don't shorten
3605+ // them in binding.
3606+ //
3607+ // Arguments:
3608+ // ins - The jump instruction
3609+ // dst - The destination label (must already be bound to an IG)
3610+ //
3611+ void emitter::emitIns_ShortJ (instruction ins, BasicBlock* dst)
3612+ {
3613+ assert ((emitCurIG->igFlags & IGF_OUT_OF_ORDER_MASK ) != 0 );
3614+
3615+ // We currently have a limitation where all jumps in the prolog must be short.
3616+ // This is mostly because we the prolog can't change size in emission, as we
3617+ // currently hardcode offsets from it into the unwind info during IG building.
3618+ // We also don't insert the jumps into the jump list in layout order.
3619+ emitIns_J (ins, dst, /* keepShort */ true );
3620+ }
36053621
36063622/* ****************************************************************************
36073623 *
@@ -4903,6 +4919,15 @@ void emitter::emitJumpDistBind()
49034919 }
49044920#endif
49054921
4922+ // For the fixed-size jumps, we only need to bind them.
4923+ for (instrDescJmp* jmp = emitFixedSizeJumpList; jmp != nullptr ; jmp = jmp->idjNext )
4924+ {
4925+ if (!jmp->idIsBound ())
4926+ {
4927+ emitBindJump (jmp);
4928+ }
4929+ }
4930+
49064931 instrDescJmp* jmp;
49074932
49084933 UNATIVE_OFFSET minShortExtra; // The smallest offset greater than that required for a jump to be converted
@@ -5220,40 +5245,7 @@ void emitter::emitJumpDistBind()
52205245 else
52215246 {
52225247 /* First time we've seen this label, convert its target */
5223-
5224- #ifdef DEBUG
5225- if (EMITVERBOSE )
5226- {
5227- printf (" Binding: " );
5228- emitDispIns (jmp, false , false , false );
5229- printf (" Binding L_M%03u_" FMT_BB , m_compiler->compMethodID , jmp->idAddr ()->iiaBBlabel ->bbNum );
5230- }
5231- #endif // DEBUG
5232-
5233- tgtIG = (insGroup*)emitCodeGetCookie (jmp->idAddr ()->iiaBBlabel );
5234-
5235- #ifdef DEBUG
5236- if (EMITVERBOSE )
5237- {
5238- if (tgtIG)
5239- {
5240- printf (" to %s\n " , emitLabelString (tgtIG));
5241- }
5242- else
5243- {
5244- printf (" -- ERROR, no emitter cookie for " FMT_BB " ; it is probably missing BBF_HAS_LABEL.\n " ,
5245- jmp->idAddr ()->iiaBBlabel ->bbNum );
5246- }
5247- }
5248- #endif // DEBUG
5249-
5250- assert (jmp->idAddr ()->iiaBBlabel ->HasFlag (BBF_HAS_LABEL ));
5251- assert (tgtIG);
5252-
5253- /* Record the bound target */
5254-
5255- jmp->idAddr ()->iiaIGlabel = tgtIG;
5256- jmp->idSetIsBound ();
5248+ tgtIG = emitBindJump (jmp);
52575249 }
52585250
52595251 // We should not be jumping/branching across funclets/functions
@@ -5674,6 +5666,54 @@ void emitter::emitJumpDistBind()
56745666 emitCheckIGList ();
56755667#endif // DEBUG
56765668}
5669+
5670+ // ------------------------------------------------------------------------
5671+ // emitBindJump: 'Bind' a jump by assigning its target label field.
5672+ //
5673+ // Arguments:
5674+ // jmp - The jump instruction
5675+ //
5676+ // Return Value:
5677+ // The target IG "jmp" was bound to.
5678+ //
5679+ insGroup* emitter::emitBindJump (instrDescJmp* jmp)
5680+ {
5681+ assert (!jmp->idIsBound ());
5682+
5683+ #ifdef DEBUG
5684+ if (EMITVERBOSE )
5685+ {
5686+ printf (" Binding: " );
5687+ emitDispIns (jmp, false , false , false );
5688+ printf (" Binding L_M%03u_" FMT_BB , m_compiler->compMethodID , jmp->idAddr ()->iiaBBlabel ->bbNum );
5689+ }
5690+ #endif // DEBUG
5691+
5692+ insGroup* tgtIG = (insGroup*)emitCodeGetCookie (jmp->idAddr ()->iiaBBlabel );
5693+
5694+ #ifdef DEBUG
5695+ if (EMITVERBOSE )
5696+ {
5697+ if (tgtIG)
5698+ {
5699+ printf (" to %s\n " , emitLabelString (tgtIG));
5700+ }
5701+ else
5702+ {
5703+ printf (" -- ERROR, no emitter cookie for " FMT_BB " ; it is probably missing BBF_HAS_LABEL.\n " ,
5704+ jmp->idAddr ()->iiaBBlabel ->bbNum );
5705+ }
5706+ }
5707+ #endif // DEBUG
5708+
5709+ assert (jmp->idAddr ()->iiaBBlabel ->HasFlag (BBF_HAS_LABEL ));
5710+ assert (tgtIG != nullptr );
5711+
5712+ /* Record the bound target */
5713+ jmp->idAddr ()->iiaIGlabel = tgtIG;
5714+ jmp->idSetIsBound ();
5715+ return tgtIG;
5716+ }
56775717#endif
56785718
56795719#if FEATURE_LOOP_ALIGN
@@ -6604,13 +6644,6 @@ void emitter::emitCheckFuncletBranch(instrDesc* jmp, insGroup* jmpIG)
66046644 }
66056645#endif
66066646
6607- if (jmp->idAddr ()->iiaHasInstrCount ())
6608- {
6609- // Too hard to figure out funclets from just an instruction count
6610- // You're on your own!
6611- return ;
6612- }
6613-
66146647#ifdef TARGET_ARM64
66156648 // No interest if it's not jmp.
66166649 if (emitIsLoadLabel (jmp) || emitIsLoadConstant (jmp))
@@ -7634,7 +7667,6 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
76347667 // Presumably we could also just call "emitOutputLJ(NULL, adr, jmp)", like for long jumps?
76357668 *(short int *)(adr + writeableOffset) -= (short )adj;
76367669#elif defined(TARGET_ARM64)
7637- assert (!jmp->idAddr ()->iiaHasInstrCount ());
76387670 emitOutputLJ (NULL , adr, jmp);
76397671#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
76407672 // For LoongArch64 and RiscV64 `emitFwdJumps` is always false.
@@ -7651,7 +7683,6 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
76517683#if defined(TARGET_XARCH)
76527684 *(int *)(adr + writeableOffset) -= adj;
76537685#elif defined(TARGET_ARMARCH)
7654- assert (!jmp->idAddr ()->iiaHasInstrCount ());
76557686 emitOutputLJ (NULL , adr, jmp);
76567687#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
76577688 // For LoongArch64 and RiscV64 `emitFwdJumps` is always false.
0 commit comments