@@ -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 ;
@@ -2465,14 +2460,15 @@ void emitter::emitBegPrologEpilog(insGroup* igPh)
24652460 emitThisGCrefRegs = emitInitGCrefRegs = igPh->igPhData ->igPhInitGCrefRegs ;
24662461 emitThisByrefRegs = emitInitByrefRegs = igPh->igPhData ->igPhInitByrefRegs ;
24672462
2463+ // Set the current BB for label creation.
2464+ m_compiler->compCurBB = igPh->igPhData ->igPhBB ;
2465+
24682466 igPh->igPhData = nullptr ;
24692467
24702468 /* Create a non-placeholder group pointer that we'll now use */
2471-
24722469 insGroup* ig = igPh;
24732470
24742471 /* Set the current function using the function index we stored */
2475-
24762472 m_compiler->funSetCurrentFunc (ig->igFuncIdx );
24772473
24782474 /* Set the new IG as the place to generate code */
@@ -3651,6 +3647,30 @@ void emitter::emitSetSecondRetRegGCType(instrDescCGCA* id, emitAttr secondRetSiz
36513647#endif // MULTIREG_HAS_SECOND_GC_RET
36523648
36533649#ifndef TARGET_WASM
3650+ // ------------------------------------------------------------------------
3651+ // emitIns_ShortJ: Emit a 'forced' short jump.
3652+ //
3653+ // Jumps in prologs are hardcoded to be short since we don't shorten
3654+ // them in binding.
3655+ //
3656+ // Arguments:
3657+ // ins - The jump instruction
3658+ // dst - The destination label (must already be bound to an IG)
3659+ //
3660+ void emitter::emitIns_ShortJ (instruction ins, BasicBlock* dst)
3661+ {
3662+ assert ((emitCurIG->igFlags & IGF_OUT_OF_ORDER_MASK) != 0 );
3663+
3664+ emitIns_J (ins, dst);
3665+
3666+ // We currently have a limitation where all jumps in the prolog must be short.
3667+ // This is mostly because we the prolog can't change size in emission, as we
3668+ // currently hardcode offsets from it into the unwind info during IG building.
3669+ // We also don't insert the jumps into the jump list in layout order.
3670+ instrDescJmp* jumpId = static_cast <instrDescJmp*>(emitLastIns);
3671+ jumpId->idjKeepLong = false ;
3672+ emitSetShortJump (jumpId);
3673+ }
36543674
36553675/* ****************************************************************************
36563676 *
@@ -4952,6 +4972,15 @@ void emitter::emitJumpDistBind()
49524972 }
49534973#endif
49544974
4975+ // For the fixed-size jumps, we only need to bind them.
4976+ for (instrDescJmp* jmp = emitFixedSizeJumpList; jmp != nullptr ; jmp = jmp->idjNext )
4977+ {
4978+ if (!jmp->idIsBound ())
4979+ {
4980+ emitBindJump (jmp);
4981+ }
4982+ }
4983+
49554984 instrDescJmp* jmp;
49564985
49574986 UNATIVE_OFFSET minShortExtra; // The smallest offset greater than that required for a jump to be converted
@@ -5269,40 +5298,7 @@ void emitter::emitJumpDistBind()
52695298 else
52705299 {
52715300 /* First time we've seen this label, convert its target */
5272-
5273- #ifdef DEBUG
5274- if (EMITVERBOSE)
5275- {
5276- printf (" Binding: " );
5277- emitDispIns (jmp, false , false , false );
5278- printf (" Binding L_M%03u_" FMT_BB, m_compiler->compMethodID , jmp->idAddr ()->iiaBBlabel ->bbNum );
5279- }
5280- #endif // DEBUG
5281-
5282- tgtIG = (insGroup*)emitCodeGetCookie (jmp->idAddr ()->iiaBBlabel );
5283-
5284- #ifdef DEBUG
5285- if (EMITVERBOSE)
5286- {
5287- if (tgtIG)
5288- {
5289- printf (" to %s\n " , emitLabelString (tgtIG));
5290- }
5291- else
5292- {
5293- printf (" -- ERROR, no emitter cookie for " FMT_BB " ; it is probably missing BBF_HAS_LABEL.\n " ,
5294- jmp->idAddr ()->iiaBBlabel ->bbNum );
5295- }
5296- }
5297- #endif // DEBUG
5298-
5299- assert (jmp->idAddr ()->iiaBBlabel ->HasFlag (BBF_HAS_LABEL));
5300- assert (tgtIG);
5301-
5302- /* Record the bound target */
5303-
5304- jmp->idAddr ()->iiaIGlabel = tgtIG;
5305- jmp->idSetIsBound ();
5301+ tgtIG = emitBindJump (jmp);
53065302 }
53075303
53085304 // We should not be jumping/branching across funclets/functions
@@ -5723,6 +5719,54 @@ void emitter::emitJumpDistBind()
57235719 emitCheckIGList ();
57245720#endif // DEBUG
57255721}
5722+
5723+ // ------------------------------------------------------------------------
5724+ // emitBindJump: 'Bind' a jump by assigning its target label field.
5725+ //
5726+ // Arguments:
5727+ // jmp - The jump instruction
5728+ //
5729+ // Return Value:
5730+ // The target IG "jmp" was bound to.
5731+ //
5732+ insGroup* emitter::emitBindJump (instrDescJmp* jmp)
5733+ {
5734+ assert (!jmp->idIsBound ());
5735+
5736+ #ifdef DEBUG
5737+ if (EMITVERBOSE)
5738+ {
5739+ printf (" Binding: " );
5740+ emitDispIns (jmp, false , false , false );
5741+ printf (" Binding L_M%03u_" FMT_BB, m_compiler->compMethodID , jmp->idAddr ()->iiaBBlabel ->bbNum );
5742+ }
5743+ #endif // DEBUG
5744+
5745+ insGroup* tgtIG = (insGroup*)emitCodeGetCookie (jmp->idAddr ()->iiaBBlabel );
5746+
5747+ #ifdef DEBUG
5748+ if (EMITVERBOSE)
5749+ {
5750+ if (tgtIG)
5751+ {
5752+ printf (" to %s\n " , emitLabelString (tgtIG));
5753+ }
5754+ else
5755+ {
5756+ printf (" -- ERROR, no emitter cookie for " FMT_BB " ; it is probably missing BBF_HAS_LABEL.\n " ,
5757+ jmp->idAddr ()->iiaBBlabel ->bbNum );
5758+ }
5759+ }
5760+ #endif // DEBUG
5761+
5762+ assert (jmp->idAddr ()->iiaBBlabel ->HasFlag (BBF_HAS_LABEL));
5763+ assert (tgtIG != nullptr );
5764+
5765+ /* Record the bound target */
5766+ jmp->idAddr ()->iiaIGlabel = tgtIG;
5767+ jmp->idSetIsBound ();
5768+ return tgtIG;
5769+ }
57265770#endif
57275771
57285772#if FEATURE_LOOP_ALIGN
@@ -6653,13 +6697,6 @@ void emitter::emitCheckFuncletBranch(instrDesc* jmp, insGroup* jmpIG)
66536697 }
66546698#endif
66556699
6656- if (jmp->idAddr ()->iiaHasInstrCount ())
6657- {
6658- // Too hard to figure out funclets from just an instruction count
6659- // You're on your own!
6660- return ;
6661- }
6662-
66636700#ifdef TARGET_ARM64
66646701 // No interest if it's not jmp.
66656702 if (emitIsLoadLabel (jmp) || emitIsLoadConstant (jmp))
@@ -7683,7 +7720,6 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
76837720 // Presumably we could also just call "emitOutputLJ(NULL, adr, jmp)", like for long jumps?
76847721 *(short int *)(adr + writeableOffset) -= (short )adj;
76857722#elif defined(TARGET_ARM64)
7686- assert (!jmp->idAddr ()->iiaHasInstrCount ());
76877723 emitOutputLJ (NULL , adr, jmp);
76887724#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
76897725 // For LoongArch64 and RiscV64 `emitFwdJumps` is always false.
@@ -7700,7 +7736,6 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
77007736#if defined(TARGET_XARCH)
77017737 *(int *)(adr + writeableOffset) -= adj;
77027738#elif defined(TARGET_ARMARCH)
7703- assert (!jmp->idAddr ()->iiaHasInstrCount ());
77047739 emitOutputLJ (NULL , adr, jmp);
77057740#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
77067741 // For LoongArch64 and RiscV64 `emitFwdJumps` is always false.
0 commit comments