1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
19 #include "hostallocator.h"
24 /*****************************************************************************
26 * Represent an emitter location.
29 void emitLocation::CaptureLocation(emitter* emit)
32 codePos = emit->emitCurOffset();
37 bool emitLocation::IsCurrentLocation(emitter* emit) const
40 return (ig == emit->emitCurIG) && (codePos == emit->emitCurOffset());
43 UNATIVE_OFFSET emitLocation::CodeOffset(emitter* emit) const
46 return emit->emitCodeOffset(ig, codePos);
49 int emitLocation::GetInsNum() const
51 return emitGetInsNumFromCodePos(codePos);
55 // Get the instruction offset in the current instruction group, which must be a funclet prolog group.
56 // This is used to find an instruction offset used in unwind data.
57 // TODO-AMD64-Bug?: We only support a single main function prolog group, but allow for multiple funclet prolog
58 // groups (not that we actually use that flexibility, since the funclet prolog will be small). How to
60 UNATIVE_OFFSET emitLocation::GetFuncletPrologOffset(emitter* emit) const
62 assert(ig->igFuncIdx != 0);
63 assert((ig->igFlags & IGF_FUNCLET_PROLOG) != 0);
64 assert(ig == emit->emitCurIG);
66 return emit->emitCurIGsize;
68 #endif // _TARGET_AMD64_
71 void emitLocation::Print() const
73 unsigned insNum = emitGetInsNumFromCodePos(codePos);
74 unsigned insOfs = emitGetInsOfsFromCodePos(codePos);
75 printf("(G_M%03u_IG%02u,ins#%d,ofs#%d)", Compiler::s_compMethodsCount, ig->igNum, insNum, insOfs);
79 /*****************************************************************************
81 * Return the name of an instruction format.
84 #if defined(DEBUG) || EMITTER_STATS
86 const char* emitter::emitIfName(unsigned f)
88 static const char* const ifNames[] = {
89 #define IF_DEF(en, op1, op2) "IF_" #en,
93 static char errBuff[32];
95 if (f < _countof(ifNames))
100 sprintf_s(errBuff, sizeof(errBuff), "??%u??", f);
108 /* these are protected */
110 AddrMap* emitter::emitPDBOffsetTable = 0;
111 LocalMap* emitter::emitPDBLocalTable = 0;
112 bool emitter::emitIsPDBEnabled = true;
113 BYTE* emitter::emitILBaseOfCode = 0;
114 BYTE* emitter::emitILMethodBase = 0;
115 BYTE* emitter::emitILMethodStart = 0;
116 BYTE* emitter::emitImgBaseOfCode = 0;
118 void emitter::MapCode(int ilOffset, BYTE* imgDest)
120 if (emitIsPDBEnabled)
122 emitPDBOffsetTable->MapSrcToDest(ilOffset, (int)(imgDest - emitImgBaseOfCode));
126 void emitter::MapFunc(int imgOff,
133 OptJit::LclVarDsc* lvaTable,
136 if (emitIsPDBEnabled)
138 // this code stores information about local symbols for the PDB translation
140 assert(lvaCount >= 0); // don't allow a negative count
142 LvaDesc* rgLvaDesc = 0;
146 rgLvaDesc = new LvaDesc[lvaCount];
153 LvaDesc* pDst = rgLvaDesc;
154 OptJit::LclVarDsc* pSrc = lvaTable;
155 for (int i = 0; i < lvaCount; ++i, ++pDst, ++pSrc)
157 pDst->slotNum = pSrc->lvSlotNum;
158 pDst->isReg = pSrc->lvRegister;
159 pDst->reg = (pSrc->lvRegister ? pSrc->lvRegNum : frameReg);
160 pDst->off = pSrc->lvStkOffs + stkAdjust;
164 emitPDBLocalTable->AddFunc((int)(emitILMethodBase - emitILBaseOfCode), imgOff - (int)emitImgBaseOfCode, procLen,
165 dbgStart - imgOff, dbgEnd - imgOff, lvaCount, rgLvaDesc, framePtr);
166 // do not delete rgLvaDesc here -- responsibility is now on emitPDBLocalTable destructor
170 /* these are public */
172 void emitter::SetILBaseOfCode(BYTE* pTextBase)
174 emitILBaseOfCode = pTextBase;
177 void emitter::SetILMethodBase(BYTE* pMethodEntry)
179 emitILMethodBase = pMethodEntry;
182 void emitter::SetILMethodStart(BYTE* pMethodCode)
184 emitILMethodStart = pMethodCode;
187 void emitter::SetImgBaseOfCode(BYTE* pTextBase)
189 emitImgBaseOfCode = pTextBase;
192 void emitter::SetIDBaseToProlog()
194 emitInstrDescILBase = (int)(emitILMethodBase - emitILBaseOfCode);
197 void emitter::SetIDBaseToOffset(int methodOffset)
199 emitInstrDescILBase = methodOffset + (int)(emitILMethodStart - emitILBaseOfCode);
202 void emitter::DisablePDBTranslation()
204 // this function should disable PDB translation code
205 emitIsPDBEnabled = false;
208 bool emitter::IsPDBEnabled()
210 return emitIsPDBEnabled;
213 void emitter::InitTranslationMaps(int ilCodeSize)
215 if (emitIsPDBEnabled)
217 emitPDBOffsetTable = AddrMap::Create(ilCodeSize);
218 emitPDBLocalTable = LocalMap::Create();
222 void emitter::DeleteTranslationMaps()
224 if (emitPDBOffsetTable)
226 delete emitPDBOffsetTable;
227 emitPDBOffsetTable = 0;
229 if (emitPDBLocalTable)
231 delete emitPDBLocalTable;
232 emitPDBLocalTable = 0;
236 void emitter::InitTranslator(PDBRewriter* pPDB, int* rgSecMap, IMAGE_SECTION_HEADER** rgpHeader, int numSections)
238 if (emitIsPDBEnabled)
240 pPDB->InitMaps(rgSecMap, // new PE section header order
241 rgpHeader, // array of section headers
242 numSections, // number of sections
243 emitPDBOffsetTable, // code offset translation table
244 emitPDBLocalTable); // slot variable translation table
248 #endif // TRANSLATE_PDB
250 /*****************************************************************************/
254 static unsigned totAllocdSize;
255 static unsigned totActualSize;
257 unsigned emitter::emitIFcounts[emitter::IF_COUNT];
259 static unsigned emitSizeBuckets[] = {100, 1024 * 1, 1024 * 2, 1024 * 3, 1024 * 4, 1024 * 5, 1024 * 10, 0};
260 static Histogram emitSizeTable(emitSizeBuckets);
262 static unsigned GCrefsBuckets[] = {0, 1, 2, 5, 10, 20, 50, 128, 256, 512, 1024, 0};
263 static Histogram GCrefsTable(GCrefsBuckets);
265 static unsigned stkDepthBuckets[] = {0, 1, 2, 5, 10, 16, 32, 128, 1024, 0};
266 static Histogram stkDepthTable(stkDepthBuckets);
268 size_t emitter::emitSizeMethod;
270 size_t emitter::emitTotMemAlloc;
271 unsigned emitter::emitTotalInsCnt;
272 unsigned emitter::emitTotalIGcnt;
273 unsigned emitter::emitTotalPhIGcnt;
274 unsigned emitter::emitTotalIGjmps;
275 unsigned emitter::emitTotalIGptrs;
276 unsigned emitter::emitTotalIGicnt;
277 size_t emitter::emitTotalIGsize;
278 unsigned emitter::emitTotalIGmcnt;
280 unsigned emitter::emitSmallDspCnt;
281 unsigned emitter::emitLargeDspCnt;
283 unsigned emitter::emitSmallCnsCnt;
284 unsigned emitter::emitLargeCnsCnt;
285 unsigned emitter::emitSmallCns[SMALL_CNS_TSZ];
287 void emitterStaticStats(FILE* fout)
292 fprintf(fout, "insGroup:\n");
293 fprintf(fout, "Offset of igNext = %2u\n", offsetof(insGroup, igNext));
295 fprintf(fout, "Offset of igSelf = %2u\n", offsetof(insGroup, igSelf));
297 fprintf(fout, "Offset of igNum = %2u\n", offsetof(insGroup, igNum));
298 fprintf(fout, "Offset of igOffs = %2u\n", offsetof(insGroup, igOffs));
299 fprintf(fout, "Offset of igFuncIdx = %2u\n", offsetof(insGroup, igFuncIdx));
300 fprintf(fout, "Offset of igFlags = %2u\n", offsetof(insGroup, igFlags));
301 fprintf(fout, "Offset of igSize = %2u\n", offsetof(insGroup, igSize));
302 fprintf(fout, "Offset of igData = %2u\n", offsetof(insGroup, igData));
303 #if EMIT_TRACK_STACK_DEPTH
304 fprintf(fout, "Offset of igStkLvl = %2u\n", offsetof(insGroup, igStkLvl));
306 fprintf(fout, "Offset of igGCregs = %2u\n", offsetof(insGroup, igGCregs));
307 fprintf(fout, "Offset of igInsCnt = %2u\n", offsetof(insGroup, igInsCnt));
308 fprintf(fout, "Size of insGroup = %u\n", sizeof(insGroup));
310 // insPlaceholderGroupData members
313 fprintf(fout, "insPlaceholderGroupData:\n");
314 fprintf(fout, "Offset of igPhNext = %2u\n", offsetof(insPlaceholderGroupData, igPhNext));
315 fprintf(fout, "Offset of igPhBB = %2u\n", offsetof(insPlaceholderGroupData, igPhBB));
316 fprintf(fout, "Offset of igPhInitGCrefVars = %2u\n", offsetof(insPlaceholderGroupData, igPhInitGCrefVars));
317 fprintf(fout, "Offset of igPhInitGCrefRegs = %2u\n", offsetof(insPlaceholderGroupData, igPhInitGCrefRegs));
318 fprintf(fout, "Offset of igPhInitByrefRegs = %2u\n", offsetof(insPlaceholderGroupData, igPhInitByrefRegs));
319 fprintf(fout, "Offset of igPhPrevGCrefVars = %2u\n", offsetof(insPlaceholderGroupData, igPhPrevGCrefVars));
320 fprintf(fout, "Offset of igPhPrevGCrefRegs = %2u\n", offsetof(insPlaceholderGroupData, igPhPrevGCrefRegs));
321 fprintf(fout, "Offset of igPhPrevByrefRegs = %2u\n", offsetof(insPlaceholderGroupData, igPhPrevByrefRegs));
322 fprintf(fout, "Offset of igPhType = %2u\n", offsetof(insPlaceholderGroupData, igPhType));
323 fprintf(fout, "Size of insPlaceholderGroupData = %u\n", sizeof(insPlaceholderGroupData));
326 fprintf(fout, "Size of instrDesc = %2u\n", sizeof(emitter::instrDesc));
327 // fprintf(fout, "Offset of _idIns = %2u\n", offsetof(emitter::instrDesc, _idIns ));
328 // fprintf(fout, "Offset of _idInsFmt = %2u\n", offsetof(emitter::instrDesc, _idInsFmt ));
329 // fprintf(fout, "Offset of _idOpSize = %2u\n", offsetof(emitter::instrDesc, _idOpSize ));
330 // fprintf(fout, "Offset of idSmallCns = %2u\n", offsetof(emitter::instrDesc, idSmallCns ));
331 // fprintf(fout, "Offset of _idAddrUnion= %2u\n", offsetof(emitter::instrDesc, _idAddrUnion));
332 // fprintf(fout, "\n");
333 // fprintf(fout, "Size of _idAddrUnion= %2u\n", sizeof(((emitter::instrDesc*)0)->_idAddrUnion));
336 fprintf(fout, "GCInfo::regPtrDsc:\n");
337 fprintf(fout, "Offset of rpdNext = %2u\n", offsetof(GCInfo::regPtrDsc, rpdNext));
338 fprintf(fout, "Offset of rpdOffs = %2u\n", offsetof(GCInfo::regPtrDsc, rpdOffs));
339 fprintf(fout, "Offset of <union> = %2u\n", offsetof(GCInfo::regPtrDsc, rpdPtrArg));
340 fprintf(fout, "Size of GCInfo::regPtrDsc = %2u\n", sizeof(GCInfo::regPtrDsc));
345 void emitterStats(FILE* fout)
347 if (totAllocdSize > 0)
349 assert(totActualSize <= totAllocdSize);
351 fprintf(fout, "\nTotal allocated code size = %u\n", totAllocdSize);
353 if (totActualSize < totAllocdSize)
355 fprintf(fout, "Total generated code size = %u ", totActualSize);
357 fprintf(fout, "(%4.3f%% waste)", 100 * ((totAllocdSize - totActualSize) / (double)totActualSize));
361 assert(emitter::emitTotalInsCnt);
363 fprintf(fout, "Average of %4.2f bytes of code generated per instruction\n",
364 (double)totActualSize / emitter::emitTotalInsCnt);
367 fprintf(fout, "\nInstruction format frequency table:\n\n");
369 unsigned f, ic = 0, dc = 0;
371 for (f = 0; f < emitter::IF_COUNT; f++)
373 ic += emitter::emitIFcounts[f];
376 for (f = 0; f < emitter::IF_COUNT; f++)
378 unsigned c = emitter::emitIFcounts[f];
380 if ((c > 0) && (1000 * c >= ic))
383 fprintf(fout, " %-13s %8u (%5.2f%%)\n", emitter::emitIfName(f), c, 100.0 * c / ic);
387 fprintf(fout, " --------------------------------\n");
388 fprintf(fout, " %-13s %8u (%5.2f%%)\n", "Total shown", dc, 100.0 * dc / ic);
390 if (emitter::emitTotalIGmcnt)
392 fprintf(fout, "Total of %8u methods\n", emitter::emitTotalIGmcnt);
393 fprintf(fout, "Total of %8u insGroup\n", emitter::emitTotalIGcnt);
394 fprintf(fout, "Total of %8u insPlaceholderGroupData\n", emitter::emitTotalPhIGcnt);
395 fprintf(fout, "Total of %8u instructions\n", emitter::emitTotalIGicnt);
396 fprintf(fout, "Total of %8u jumps\n", emitter::emitTotalIGjmps);
397 fprintf(fout, "Total of %8u GC livesets\n", emitter::emitTotalIGptrs);
399 fprintf(fout, "Average of %8.1lf insGroup per method\n",
400 (double)emitter::emitTotalIGcnt / emitter::emitTotalIGmcnt);
401 fprintf(fout, "Average of %8.1lf insPhGroup per method\n",
402 (double)emitter::emitTotalPhIGcnt / emitter::emitTotalIGmcnt);
403 fprintf(fout, "Average of %8.1lf instructions per method\n",
404 (double)emitter::emitTotalIGicnt / emitter::emitTotalIGmcnt);
405 fprintf(fout, "Average of %8.1lf desc. bytes per method\n",
406 (double)emitter::emitTotalIGsize / emitter::emitTotalIGmcnt);
407 fprintf(fout, "Average of %8.1lf jumps per method\n",
408 (double)emitter::emitTotalIGjmps / emitter::emitTotalIGmcnt);
409 fprintf(fout, "Average of %8.1lf GC livesets per method\n",
410 (double)emitter::emitTotalIGptrs / emitter::emitTotalIGmcnt);
412 fprintf(fout, "Average of %8.1lf instructions per group \n",
413 (double)emitter::emitTotalIGicnt / emitter::emitTotalIGcnt);
414 fprintf(fout, "Average of %8.1lf desc. bytes per group \n",
415 (double)emitter::emitTotalIGsize / emitter::emitTotalIGcnt);
416 fprintf(fout, "Average of %8.1lf jumps per group \n",
417 (double)emitter::emitTotalIGjmps / emitter::emitTotalIGcnt);
419 fprintf(fout, "Average of %8.1lf bytes per instrDesc\n",
420 (double)emitter::emitTotalIGsize / emitter::emitTotalIGicnt);
422 fprintf(fout, "A total of %8u desc. bytes\n", emitter::emitTotalIGsize);
426 fprintf(fout, "Descriptor size distribution:\n");
427 emitSizeTable.dump(fout);
430 fprintf(fout, "GC ref frame variable counts:\n");
431 GCrefsTable.dump(fout);
434 fprintf(fout, "Max. stack depth distribution:\n");
435 stkDepthTable.dump(fout);
442 if (emitter::emitSmallCnsCnt || emitter::emitLargeCnsCnt)
444 fprintf(fout, "SmallCnsCnt = %6u\n", emitter::emitSmallCnsCnt);
445 fprintf(fout, "LargeCnsCnt = %6u (%3u %% of total)\n", emitter::emitLargeCnsCnt,
446 100 * emitter::emitLargeCnsCnt / (emitter::emitLargeCnsCnt + emitter::emitSmallCnsCnt));
450 // TODO-Cleanup: WHy is this in #if 0 - Is EMITTER_STATS ever used? Fix or delete this.
451 if (emitter::emitSmallCnsCnt)
455 m = emitter::emitSmallCnsCnt/1000 + 1;
457 for (i = ID_MIN_SMALL_CNS; i < ID_MAX_SMALL_CNS; i++)
459 c = emitter::emitSmallCns[i-ID_MIN_SMALL_CNS];
461 fprintf(fout, "cns[%4d] = %u\n", i, c);
466 fprintf(fout, "%8u bytes allocated in the emitter\n", emitter::emitTotMemAlloc);
469 #endif // EMITTER_STATS
471 /*****************************************************************************/
473 const unsigned short emitTypeSizes[] = {
474 #define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) sze,
475 #include "typelist.h"
479 const unsigned short emitTypeActSz[] = {
480 #define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) asze,
481 #include "typelist.h"
485 /*****************************************************************************/
486 /*****************************************************************************
488 * Initialize the emitter - called once, at DLL load time.
491 void emitter::emitInit()
495 /*****************************************************************************
497 * Shut down the emitter - called once, at DLL exit time.
500 void emitter::emitDone()
504 /*****************************************************************************
509 void* emitter::emitGetMem(size_t sz)
511 assert(sz % sizeof(int) == 0);
514 emitTotMemAlloc += sz;
517 return emitComp->compGetMem(sz, CMK_InstDesc);
520 /*****************************************************************************
522 * emitLclVarAddr support methods
524 void emitLclVarAddr::initLclVarAddr(int varNum, unsigned offset)
532 _lvaTag = LVA_STANDARD_ENCODING;
533 _lvaExtra = offset; // offset known to be in [0..32767]
534 _lvaVarNum = (unsigned)varNum; // varNum known to be in [0..32767]
536 else // offset >= 32768
538 // We could support larger local offsets here at the cost of less varNums
541 IMPL_LIMITATION("JIT doesn't support offsets larger than 65535 into valuetypes\n");
544 _lvaTag = LVA_LARGE_OFFSET;
545 _lvaExtra = (offset - 32768); // (offset-32768) is known to be in [0..32767]
546 _lvaVarNum = (unsigned)varNum; // varNum known to be in [0..32767]
549 else // varNum < 0, These are used for Compiler spill temps
553 IMPL_LIMITATION("JIT doesn't support more than 32767 Compiler Spill temps\n");
558 "JIT doesn't support offsets larger than 32767 into valuetypes for Compiler Spill temps\n");
561 _lvaTag = LVA_COMPILER_TEMP;
562 _lvaExtra = offset; // offset known to be in [0..32767]
563 _lvaVarNum = (unsigned)(-varNum); // -varNum known to be in [1..32767]
566 else // varNum >= 32768
570 IMPL_LIMITATION("JIT doesn't support offsets larger than 255 into valuetypes for local vars > 32767\n");
572 if (varNum >= 0x00400000)
573 { // 0x00400000 == 2^22
574 IMPL_LIMITATION("JIT doesn't support more than 2^22 variables\n");
577 _lvaTag = LVA_LARGE_VARNUM;
578 _lvaVarNum = varNum & 0x00007FFF; // varNum bits 14 to 0
579 _lvaExtra = (varNum & 0x003F8000) >> 15; // varNum bits 21 to 15 in _lvaExtra bits 6 to 0, 7 bits total
580 _lvaExtra |= (offset << 7); // offset bits 7 to 0 in _lvaExtra bits 14 to 7, 8 bits total
584 // Returns the variable to access. Note that it returns a negative number for compiler spill temps.
585 int emitLclVarAddr::lvaVarNum()
589 case LVA_COMPILER_TEMP:
590 return -((int)_lvaVarNum);
591 case LVA_LARGE_VARNUM:
592 return (int)(((_lvaExtra & 0x007F) << 15) + _lvaVarNum);
593 default: // LVA_STANDARD_ENCODING or LVA_LARGE_OFFSET
594 assert((_lvaTag == LVA_STANDARD_ENCODING) || (_lvaTag == LVA_LARGE_OFFSET));
595 return (int)_lvaVarNum;
599 unsigned emitLclVarAddr::lvaOffset() // returns the offset into the variable to access
603 case LVA_LARGE_OFFSET:
604 return (32768 + _lvaExtra);
605 case LVA_LARGE_VARNUM:
606 return (_lvaExtra & 0x7F80) >> 7;
607 default: // LVA_STANDARD_ENCODING or LVA_COMPILER_TEMP
608 assert((_lvaTag == LVA_STANDARD_ENCODING) || (_lvaTag == LVA_COMPILER_TEMP));
613 /*****************************************************************************
615 * Record some info about the method about to be emitted.
618 void emitter::emitBegCG(Compiler* comp, COMP_HANDLE cmpHandle)
621 emitCmpHandle = cmpHandle;
624 void emitter::emitEndCG()
628 /*****************************************************************************
630 * Prepare the given IG for emission of code.
633 void emitter::emitGenIG(insGroup* ig)
635 /* Set the "current IG" value */
639 #if EMIT_TRACK_STACK_DEPTH
641 /* Record the stack level on entry to this group */
643 ig->igStkLvl = emitCurStackLvl;
645 // If we don't have enough bits in igStkLvl, refuse to compile
647 if (ig->igStkLvl != emitCurStackLvl)
649 IMPL_LIMITATION("Too many arguments pushed on stack");
652 // printf("Start IG #%02u [stk=%02u]\n", ig->igNum, emitCurStackLvl);
658 ig->igFlags |= IGF_NOGCINTERRUPT;
661 /* Prepare to issue instructions */
666 assert(emitCurIGjmpList == nullptr);
668 /* Allocate the temp instruction buffer if we haven't done so */
670 if (emitCurIGfreeBase == nullptr)
672 emitIGbuffSize = SC_IG_BUFFER_SIZE;
673 emitCurIGfreeBase = (BYTE*)emitGetMem(emitIGbuffSize);
676 emitCurIGfreeNext = emitCurIGfreeBase;
677 emitCurIGfreeEndp = emitCurIGfreeBase + emitIGbuffSize;
680 /*****************************************************************************
682 * Finish and save the current IG.
685 insGroup* emitter::emitSavIG(bool emitAdd)
693 assert(emitCurIGfreeNext <= emitCurIGfreeEndp);
695 /* Get hold of the IG descriptor */
700 /* Compute how much code we've generated */
702 sz = emitCurIGfreeNext - emitCurIGfreeBase;
704 /* Compute the total size we need to allocate */
708 /* Do we need space for GC? */
710 if (!(ig->igFlags & IGF_EMIT_ADD))
712 /* Is the initial set of live GC vars different from the previous one? */
714 if (emitForceStoreGCState || !VarSetOps::Equal(emitComp, emitPrevGCrefVars, emitInitGCrefVars))
716 /* Remember that we will have a new set of live GC variables */
718 ig->igFlags |= IGF_GC_VARS;
724 /* We'll allocate extra space to record the liveset */
726 gs += sizeof(VARSET_TP);
729 /* Is the initial set of live Byref regs different from the previous one? */
731 /* Remember that we will have a new set of live GC variables */
733 ig->igFlags |= IGF_BYREF_REGS;
735 /* We'll allocate extra space (DWORD aligned) to record the GC regs */
740 /* Allocate space for the instructions and optional liveset */
742 id = (BYTE*)emitGetMem(gs);
744 /* Do we need to store the byref regs */
746 if (ig->igFlags & IGF_BYREF_REGS)
748 /* Record the byref regs in front the of the instructions */
750 *castto(id, unsigned*)++ = (unsigned)emitInitByrefRegs;
753 /* Do we need to store the liveset? */
755 if (ig->igFlags & IGF_GC_VARS)
757 /* Record the liveset in front the of the instructions */
758 VarSetOps::AssignNoCopy(emitComp, (*castto(id, VARSET_TP*)), VarSetOps::MakeEmpty(emitComp));
759 VarSetOps::Assign(emitComp, (*castto(id, VARSET_TP*)++), emitInitGCrefVars);
762 /* Record the collected instructions */
764 assert((ig->igFlags & IGF_PLACEHOLDER) == 0);
767 memcpy(id, emitCurIGfreeBase, sz);
770 if (false && emitComp->verbose) // this is not useful in normal dumps (hence it is normally under if (false)
772 // If there's an error during emission, we may want to connect the post-copy address
773 // of an instrDesc with the pre-copy address (the one that was originally created). This
774 // printing enables that.
775 printf("copying instruction group from [0x%x..0x%x) to [0x%x..0x%x).\n", dspPtr(emitCurIGfreeBase),
776 dspPtr(emitCurIGfreeBase + sz), dspPtr(id), dspPtr(id + sz));
780 /* Record how many instructions and bytes of code this group contains */
782 noway_assert((BYTE)emitCurIGinsCnt == emitCurIGinsCnt);
783 noway_assert((unsigned short)emitCurIGsize == emitCurIGsize);
785 ig->igInsCnt = (BYTE)emitCurIGinsCnt;
786 ig->igSize = (unsigned short)emitCurIGsize;
787 emitCurCodeOffset += emitCurIGsize;
788 assert(IsCodeAligned(emitCurCodeOffset));
791 emitTotalIGicnt += emitCurIGinsCnt;
792 emitTotalIGsize += sz;
793 emitSizeMethod += sz;
796 // printf("Group [%08X]%3u has %2u instructions (%4u bytes at %08X)\n", ig, ig->igNum, emitCurIGinsCnt, sz, id);
798 /* Record the live GC register set - if and only if it is not an emitter added block */
800 if (!(ig->igFlags & IGF_EMIT_ADD))
802 ig->igGCregs = (regMaskSmall)emitInitGCrefRegs;
807 /* Update the previous recorded live GC ref sets, but not if
808 if we are starting an "overflow" buffer. Note that this is
809 only used to determine whether we need to store or not store
810 the GC ref sets for the next IG, which is dependent on exactly
811 what the state of the emitter GC ref sets will be when the
812 next IG is processed in the emitter.
815 VarSetOps::Assign(emitComp, emitPrevGCrefVars, emitThisGCrefVars);
816 emitPrevGCrefRegs = emitThisGCrefRegs;
817 emitPrevByrefRegs = emitThisByrefRegs;
819 emitForceStoreGCState = false;
823 if (emitComp->opts.dspCode)
825 printf("\n G_M%03u_IG%02u:", Compiler::s_compMethodsCount, ig->igNum);
826 if (emitComp->verbose)
828 printf(" ; offs=%06XH, funclet=%02u", ig->igOffs, ig->igFuncIdx);
832 printf(" ; funclet=%02u", ig->igFuncIdx);
838 /* Did we have any jumps in this group? */
840 if (emitCurIGjmpList)
842 instrDescJmp* list = nullptr;
843 instrDescJmp* last = nullptr;
845 /* Move jumps to the global list, update their 'next' links */
849 /* Grab the jump and remove it from the list */
851 instrDescJmp* oj = emitCurIGjmpList;
852 emitCurIGjmpList = oj->idjNext;
854 /* Figure out the address of where the jump got copied */
856 size_t of = (BYTE*)oj - emitCurIGfreeBase;
857 instrDescJmp* nj = (instrDescJmp*)(ig->igData + of);
859 // printf("Jump moved from %08X to %08X\n", oj, nj);
860 // printf("jmp [%08X] at %08X + %03u\n", nj, ig, nj->idjOffs);
862 assert(nj->idjIG == ig);
863 assert(nj->idIns() == oj->idIns());
864 assert(nj->idjNext == oj->idjNext);
866 /* Make sure the jumps are correctly ordered */
868 assert(last == nullptr || last->idjOffs > nj->idjOffs);
870 if (ig->igFlags & IGF_FUNCLET_PROLOG)
872 // Our funclet prologs have short jumps, if the prolog would ever have
873 // long jumps, then we'd have to insert the list in sorted order than
874 // just append to the emitJumpList.
875 noway_assert(nj->idjShort);
882 /* Append the new jump to the list */
891 } while (emitCurIGjmpList);
895 /* Append the jump(s) from this IG to the global list */
896 bool prologJump = (ig == emitPrologIG);
897 if ((emitJumpList == nullptr) || prologJump)
899 last->idjNext = emitJumpList;
904 last->idjNext = nullptr;
905 emitJumpLast->idjNext = list;
908 if (!prologJump || (emitJumpLast == nullptr))
915 /* Fix the last instruction field */
919 assert(emitLastIns != nullptr);
920 assert(emitCurIGfreeBase <= (BYTE*)emitLastIns);
921 assert((BYTE*)emitLastIns < emitCurIGfreeBase + sz);
922 emitLastIns = (instrDesc*)((BYTE*)id + ((BYTE*)emitLastIns - (BYTE*)emitCurIGfreeBase));
925 /* Reset the buffer free pointers */
927 emitCurIGfreeNext = emitCurIGfreeBase;
932 /*****************************************************************************
934 * Start generating code to be scheduled; called once per method.
937 void emitter::emitBegFN(bool hasFramePtr
947 /* Assume we won't need the temp instruction buffer */
949 emitCurIGfreeBase = nullptr;
952 /* Record stack frame info (the temp size is just an estimate) */
954 emitHasFramePtr = hasFramePtr;
956 emitMaxTmpSize = maxTmpSize;
959 emitChkAlign = chkAlign;
962 /* We have no epilogs yet */
967 #ifdef _TARGET_XARCH_
968 emitExitSeqBegLoc.Init();
969 emitExitSeqSize = INT_MAX;
970 #endif // _TARGET_XARCH_
972 emitPlaceholderList = emitPlaceholderLast = nullptr;
974 #ifdef JIT32_GCENCODER
975 emitEpilogList = emitEpilogLast = nullptr;
976 #endif // JIT32_GCENCODER
978 /* We don't have any jumps */
980 emitJumpList = emitJumpLast = nullptr;
981 emitCurIGjmpList = nullptr;
983 emitFwdJumps = false;
985 emitForceNewIG = false;
987 /* We have not recorded any live sets */
989 assert(VarSetOps::IsEmpty(emitComp, emitThisGCrefVars));
990 assert(VarSetOps::IsEmpty(emitComp, emitInitGCrefVars));
991 assert(VarSetOps::IsEmpty(emitComp, emitPrevGCrefVars));
992 emitThisGCrefRegs = RBM_NONE;
993 emitInitGCrefRegs = RBM_NONE;
994 emitPrevGCrefRegs = RBM_NONE;
995 emitThisByrefRegs = RBM_NONE;
996 emitInitByrefRegs = RBM_NONE;
997 emitPrevByrefRegs = RBM_NONE;
999 emitForceStoreGCState = false;
1003 emitIssuing = false;
1007 /* Assume there will be no GC ref variables */
1009 emitGCrFrameOffsMin = emitGCrFrameOffsMax = emitGCrFrameOffsCnt = 0;
1011 emitGCrFrameLiveTab = nullptr;
1014 /* We have no groups / code at this point */
1016 emitIGlist = emitIGlast = nullptr;
1018 emitCurCodeOffset = 0;
1019 emitFirstColdIG = nullptr;
1020 emitTotalCodeSize = 0;
1029 /* The stack is empty now */
1031 emitCurStackLvl = 0;
1033 #if EMIT_TRACK_STACK_DEPTH
1034 emitMaxStackDepth = 0;
1035 emitCntStackDepth = sizeof(int);
1038 /* No data sections have been created */
1040 emitDataSecCur = nullptr;
1042 memset(&emitConsDsc, 0, sizeof(emitConsDsc));
1044 #ifdef PSEUDORANDOM_NOP_INSERTION
1045 // for random NOP insertion
1047 emitEnableRandomNops();
1048 emitComp->info.compRNG.Init(emitComp->info.compChecksum);
1049 emitNextNop = emitNextRandomNop();
1050 emitInInstrumentation = false;
1051 #endif // PSEUDORANDOM_NOP_INSERTION
1053 /* Create the first IG, it will be used for the prolog */
1057 emitPrologIG = emitIGlist = emitIGlast = emitCurIG = ig = emitAllocIG();
1059 emitLastIns = nullptr;
1061 ig->igNext = nullptr;
1064 emitScratchSigInfo = nullptr;
1067 /* Append another group, to start generating the method body */
1072 #ifdef PSEUDORANDOM_NOP_INSERTION
1073 int emitter::emitNextRandomNop()
1075 return emitComp->info.compRNG.Next(1, 9);
1079 /*****************************************************************************
1081 * Done generating code to be scheduled; called once per method.
1084 void emitter::emitEndFN()
1088 // member function iiaIsJitDataOffset for idAddrUnion, defers to Compiler::eeIsJitDataOffs
1089 bool emitter::instrDesc::idAddrUnion::iiaIsJitDataOffset() const
1091 return Compiler::eeIsJitDataOffs(iiaFieldHnd);
1094 // member function iiaGetJitDataOffset for idAddrUnion, defers to Compiler::eeGetJitDataOffs
1095 int emitter::instrDesc::idAddrUnion::iiaGetJitDataOffset() const
1097 assert(iiaIsJitDataOffset());
1098 return Compiler::eeGetJitDataOffs(iiaFieldHnd);
1101 void emitter::dispIns(instrDesc* id)
1104 emitInsSanityCheck(id);
1106 if (emitComp->opts.dspCode)
1108 emitDispIns(id, true, false, false);
1111 #if EMIT_TRACK_STACK_DEPTH
1112 assert((int)emitCurStackLvl >= 0);
1114 size_t sz = emitSizeOfInsDsc(id);
1115 assert(id->idDebugOnlyInfo()->idSize == sz);
1119 emitIFcounts[id->idInsFmt()]++;
1123 void emitter::appendToCurIG(instrDesc* id)
1125 emitCurIGsize += id->idCodeSize();
1128 /*****************************************************************************
1130 * Display (optionally) an instruction offset.
1135 void emitter::emitDispInsOffs(unsigned offs, bool doffs)
1139 printf("%06X", offs);
1149 #ifdef JIT32_GCENCODER
1151 /*****************************************************************************
1153 * Call the specified function pointer for each epilog block in the current
1154 * method with the epilog's relative code offset. Returns the sum of the
1155 * values returned by the callback.
1158 size_t emitter::emitGenEpilogLst(size_t (*fp)(void*, unsigned), void* cp)
1163 for (el = emitEpilogList, sz = 0; el != nullptr; el = el->elNext)
1165 assert(el->elLoc.GetIG()->igFlags & IGF_EPILOG);
1167 // The epilog starts at the location recorded in the epilog list.
1168 sz += fp(cp, el->elLoc.CodeOffset(this));
1174 #endif // JIT32_GCENCODER
1176 /*****************************************************************************
1178 * The following series of methods allocates instruction descriptors.
1181 void* emitter::emitAllocInstr(size_t sz, emitAttr opsz)
1186 // Under STRESS_EMITTER, put every instruction in its own instruction group.
1187 // We can't do this for a prolog, epilog, funclet prolog, or funclet epilog,
1188 // because those are generated out of order. We currently have a limitation
1189 // where the jump shortening pass uses the instruction group number to determine
1190 // if something is earlier or later in the code stream. This implies that
1191 // these groups cannot be more than a single instruction group. Note that
1192 // the prolog/epilog placeholder groups ARE generated in order, and are
1193 // re-used. But generating additional groups would not work.
1194 if (emitComp->compStressCompile(Compiler::STRESS_EMITTER, 1) && emitCurIGinsCnt && !emitIGisInProlog(emitCurIG) &&
1195 !emitIGisInEpilog(emitCurIG)
1196 #if FEATURE_EH_FUNCLETS
1197 && !emitIGisInFuncletProlog(emitCurIG) && !emitIGisInFuncletEpilog(emitCurIG)
1198 #endif // FEATURE_EH_FUNCLETS
1205 #ifdef PSEUDORANDOM_NOP_INSERTION
1206 // TODO-ARM-Bug?: PSEUDORANDOM_NOP_INSERTION is not defined for _TARGET_ARM_
1207 // ARM - This is currently broken on _TARGET_ARM_
1208 // When nopSize is odd we misalign emitCurIGsize
1210 if (!emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && !emitInInstrumentation &&
1211 !emitIGisInProlog(emitCurIG) && // don't do this in prolog or epilog
1212 !emitIGisInEpilog(emitCurIG) &&
1213 emitRandomNops // sometimes we turn off where exact codegen is needed (pinvoke inline)
1216 if (emitNextNop == 0)
1219 emitInInstrumentation = true;
1220 instrDesc* idnop = emitNewInstr();
1221 emitInInstrumentation = false;
1222 idnop->idInsFmt(IF_NONE);
1223 idnop->idIns(INS_nop);
1224 #if defined(_TARGET_XARCH_)
1225 idnop->idCodeSize(nopSize);
1227 #error "Undefined target for pseudorandom NOP insertion"
1230 emitCurIGsize += nopSize;
1231 emitNextNop = emitNextRandomNop();
1236 #endif // PSEUDORANDOM_NOP_INSERTION
1238 assert(IsCodeAligned(emitCurIGsize));
1240 /* Make sure we have enough space for the new instruction */
1242 if ((emitCurIGfreeNext + sz >= emitCurIGfreeEndp) || emitForceNewIG)
1247 /* Grab the space for the instruction */
1249 emitLastIns = id = (instrDesc*)emitCurIGfreeNext;
1250 emitCurIGfreeNext += sz;
1252 assert(sz >= sizeof(void*));
1255 // These fields should have been zero-ed by the above
1256 assert(id->idReg1() == regNumber(0));
1257 assert(id->idReg2() == regNumber(0));
1258 #ifdef _TARGET_XARCH_
1259 assert(id->idCodeSize() == 0);
1262 // Make sure that idAddrUnion is just a union of various pointer sized things
1263 C_ASSERT(sizeof(CORINFO_FIELD_HANDLE) <= sizeof(void*));
1264 C_ASSERT(sizeof(CORINFO_METHOD_HANDLE) <= sizeof(void*));
1265 C_ASSERT(sizeof(emitter::emitAddrMode) <= sizeof(void*));
1266 C_ASSERT(sizeof(emitLclVarAddr) <= sizeof(void*));
1267 C_ASSERT(sizeof(emitter::instrDesc) == (SMALL_IDSC_SIZE + sizeof(void*)));
1272 /* In debug mode we clear/set some additional fields */
1274 instrDescDebugInfo* info = (instrDescDebugInfo*)emitGetMem(sizeof(*info));
1276 info->idNum = emitInsCount;
1278 info->idVarRefOffs = 0;
1279 info->idMemCookie = 0;
1280 #ifdef TRANSLATE_PDB
1281 info->idilStart = emitInstrDescILBase;
1283 info->idFinallyCall = false;
1284 info->idCatchRet = false;
1285 info->idCallSig = nullptr;
1287 id->idDebugOnlyInfo(info);
1289 #endif // defined(DEBUG)
1291 /* Store the size and handle the two special values
1292 that indicate GCref and ByRef */
1294 if (EA_IS_GCREF(opsz))
1296 /* A special value indicates a GCref pointer value */
1298 id->idGCref(GCT_GCREF);
1299 id->idOpSize(EA_PTRSIZE);
1301 else if (EA_IS_BYREF(opsz))
1303 /* A special value indicates a Byref pointer value */
1305 id->idGCref(GCT_BYREF);
1306 id->idOpSize(EA_PTRSIZE);
1310 id->idGCref(GCT_NONE);
1311 id->idOpSize(EA_SIZE(opsz));
1314 // Amd64: ip-relative addressing is supported even when not generating relocatable ngen code
1315 if (EA_IS_DSP_RELOC(opsz)
1316 #ifndef _TARGET_AMD64_
1317 && emitComp->opts.compReloc
1318 #endif //_TARGET_AMD64_
1321 /* Mark idInfo()->idDspReloc to remember that the */
1322 /* address mode has a displacement that is relocatable */
1323 id->idSetIsDspReloc();
1326 if (EA_IS_CNS_RELOC(opsz) && emitComp->opts.compReloc)
1328 /* Mark idInfo()->idCnsReloc to remember that the */
1329 /* instruction has an immediate constant that is relocatable */
1330 id->idSetIsCnsReloc();
1337 /* Update the instruction count */
1346 /*****************************************************************************
1348 * Make sure the code offsets of all instruction groups look reasonable.
1350 void emitter::emitCheckIGoffsets()
1355 for (tempIG = emitIGlist, offsIG = 0; tempIG; tempIG = tempIG->igNext)
1357 if (tempIG->igOffs != offsIG)
1359 printf("Block #%u has offset %08X, expected %08X\n", tempIG->igNum, tempIG->igOffs, offsIG);
1360 assert(!"bad block offset");
1363 offsIG += tempIG->igSize;
1366 if (emitTotalCodeSize && emitTotalCodeSize != offsIG)
1368 printf("Total code size is %08X, expected %08X\n", emitTotalCodeSize, offsIG);
1370 assert(!"bad total code size");
1376 /*****************************************************************************
1378 * Begin generating a method prolog.
1381 void emitter::emitBegProlog()
1383 assert(emitComp->compGeneratingProlog);
1385 #if EMIT_TRACK_STACK_DEPTH
1387 /* Don't measure stack depth inside the prolog, it's misleading */
1389 emitCntStackDepth = 0;
1391 assert(emitCurStackLvl == 0);
1396 emitForceNewIG = false;
1398 /* Switch to the pre-allocated prolog IG */
1400 emitGenIG(emitPrologIG);
1402 /* Nothing is live on entry to the prolog */
1404 // These were initialized to Empty at the start of compilation.
1405 VarSetOps::ClearD(emitComp, emitInitGCrefVars);
1406 VarSetOps::ClearD(emitComp, emitPrevGCrefVars);
1407 emitInitGCrefRegs = RBM_NONE;
1408 emitPrevGCrefRegs = RBM_NONE;
1409 emitInitByrefRegs = RBM_NONE;
1410 emitPrevByrefRegs = RBM_NONE;
1413 /*****************************************************************************
1415 * Return the code offset of the current location in the prolog.
1418 unsigned emitter::emitGetPrologOffsetEstimate()
1420 /* For now only allow a single prolog ins group */
1422 assert(emitPrologIG);
1423 assert(emitPrologIG == emitCurIG);
1425 return emitCurIGsize;
1428 /*****************************************************************************
1430 * Mark the code offset of the current location as the end of the prolog,
1431 * so it can be used later to compute the actual size of the prolog.
1434 void emitter::emitMarkPrologEnd()
1436 assert(emitComp->compGeneratingProlog);
1438 /* For now only allow a single prolog ins group */
1440 assert(emitPrologIG);
1441 assert(emitPrologIG == emitCurIG);
1443 emitPrologEndPos = emitCurOffset();
1446 /*****************************************************************************
1448 * Finish generating a method prolog.
1451 void emitter::emitEndProlog()
1453 assert(emitComp->compGeneratingProlog);
1457 /* Save the prolog IG if non-empty or if only one block */
1459 if (emitCurIGnonEmpty() || emitCurIG == emitPrologIG)
1464 #if EMIT_TRACK_STACK_DEPTH
1465 /* Reset the stack depth values */
1467 emitCurStackLvl = 0;
1468 emitCntStackDepth = sizeof(int);
1472 /*****************************************************************************
1474 * Create a placeholder instruction group to be used by a prolog or epilog,
1475 * either for the main function, or a funclet.
1478 void emitter::emitCreatePlaceholderIG(insGroupPlaceholderType igType,
1480 VARSET_VALARG_TP GCvars,
1481 regMaskTP gcrefRegs,
1482 regMaskTP byrefRegs,
1485 assert(igBB != nullptr);
1487 bool emitAdd = false;
1489 if (igType == IGPT_EPILOG
1490 #if FEATURE_EH_FUNCLETS
1491 || igType == IGPT_FUNCLET_EPILOG
1492 #endif // FEATURE_EH_FUNCLETS
1495 #ifdef _TARGET_AMD64_
1496 emitOutputPreEpilogNOP();
1497 #endif // _TARGET_AMD64_
1502 if (emitCurIGnonEmpty())
1507 /* Update GC tracking for the beginning of the placeholder IG */
1511 VarSetOps::Assign(emitComp, emitThisGCrefVars, GCvars);
1512 VarSetOps::Assign(emitComp, emitInitGCrefVars, GCvars);
1513 emitThisGCrefRegs = emitInitGCrefRegs = gcrefRegs;
1514 emitThisByrefRegs = emitInitByrefRegs = byrefRegs;
1517 /* Convert the group to a placeholder group */
1519 insGroup* igPh = emitCurIG;
1521 igPh->igFlags |= IGF_PLACEHOLDER;
1523 /* Note that we might be re-using a previously created but empty IG. In this
1524 * case, we need to make sure any re-used fields, such as igFuncIdx, are correct.
1527 igPh->igFuncIdx = emitComp->compCurrFuncIdx;
1529 /* Create a separate block of memory to store placeholder information.
1530 * We could use unions to put some of this into the insGroup itself, but we don't
1531 * want to grow the insGroup, and it's difficult to make sure the
1532 * insGroup fields are getting set and used elsewhere.
1535 igPh->igPhData = new (emitComp, CMK_InstDesc) insPlaceholderGroupData;
1537 igPh->igPhData->igPhNext = nullptr;
1538 igPh->igPhData->igPhType = igType;
1539 igPh->igPhData->igPhBB = igBB;
1541 VarSetOps::AssignNoCopy(emitComp, igPh->igPhData->igPhPrevGCrefVars, VarSetOps::UninitVal());
1542 VarSetOps::Assign(emitComp, igPh->igPhData->igPhPrevGCrefVars, emitPrevGCrefVars);
1543 igPh->igPhData->igPhPrevGCrefRegs = emitPrevGCrefRegs;
1544 igPh->igPhData->igPhPrevByrefRegs = emitPrevByrefRegs;
1546 VarSetOps::AssignNoCopy(emitComp, igPh->igPhData->igPhInitGCrefVars, VarSetOps::UninitVal());
1547 VarSetOps::Assign(emitComp, igPh->igPhData->igPhInitGCrefVars, emitInitGCrefVars);
1548 igPh->igPhData->igPhInitGCrefRegs = emitInitGCrefRegs;
1549 igPh->igPhData->igPhInitByrefRegs = emitInitByrefRegs;
1552 emitTotalPhIGcnt += 1;
1555 // Mark function prologs and epilogs properly in the igFlags bits. These bits
1556 // will get used and propagated when the placeholder is converted to a non-placeholder
1557 // during prolog/epilog generation.
1559 if (igType == IGPT_EPILOG)
1561 igPh->igFlags |= IGF_EPILOG;
1563 #if FEATURE_EH_FUNCLETS
1564 else if (igType == IGPT_FUNCLET_PROLOG)
1566 igPh->igFlags |= IGF_FUNCLET_PROLOG;
1568 else if (igType == IGPT_FUNCLET_EPILOG)
1570 igPh->igFlags |= IGF_FUNCLET_EPILOG;
1572 #endif // FEATURE_EH_FUNCLETS
1574 /* Link it into the placeholder list */
1576 if (emitPlaceholderList)
1578 emitPlaceholderLast->igPhData->igPhNext = igPh;
1582 emitPlaceholderList = igPh;
1585 emitPlaceholderLast = igPh;
1587 // Give an estimated size of this placeholder IG and
1588 // increment emitCurCodeOffset since we are not calling emitNewIG()
1590 emitCurIGsize += MAX_PLACEHOLDER_IG_SIZE;
1591 emitCurCodeOffset += emitCurIGsize;
1593 #if FEATURE_EH_FUNCLETS
1594 // Add the appropriate IP mapping debugging record for this placeholder
1595 // group. genExitCode() adds the mapping for main function epilogs.
1596 if (emitComp->opts.compDbgInfo)
1598 if (igType == IGPT_FUNCLET_PROLOG)
1600 codeGen->genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::PROLOG, true);
1602 else if (igType == IGPT_FUNCLET_EPILOG)
1604 codeGen->genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::EPILOG, true);
1607 #endif // FEATURE_EH_FUNCLETS
1609 /* Start a new IG if more code follows */
1613 emitCurIG = nullptr;
1617 if (igType == IGPT_EPILOG
1618 #if FEATURE_EH_FUNCLETS
1619 || igType == IGPT_FUNCLET_EPILOG
1620 #endif // FEATURE_EH_FUNCLETS
1623 // If this was an epilog, then assume this is the end of any currently in progress
1624 // no-GC region. If a block after the epilog needs to be no-GC, it needs to call
1625 // emitter::emitDisableGC() directly. This behavior is depended upon by the fast
1626 // tailcall implementation, which disables GC at the beginning of argument setup,
1627 // but assumes that after the epilog it will be re-enabled.
1633 // We don't know what the GC ref state will be at the end of the placeholder
1634 // group. So, force the next IG to store all the GC ref state variables;
1635 // don't omit them because emitPrev* is the same as emitInit*, because emitPrev*
1636 // will be inaccurate. (Note that, currently, GCrefRegs and ByrefRegs are always
1639 // There is no need to re-initialize the emitPrev* variables, as they won't be used
1640 // with emitForceStoreGCState==true, and will be re-initialized just before
1641 // emitForceStoreGCState is set to false;
1643 emitForceStoreGCState = true;
1645 /* The group after the placeholder group doesn't get the "propagate" flags */
1647 emitCurIG->igFlags &= ~IGF_PROPAGATE_MASK;
1651 if (emitComp->verbose)
1653 printf("*************** After placeholder IG creation\n");
1654 emitDispIGlist(false);
1659 /*****************************************************************************
1661 * Generate all prologs and epilogs
1664 void emitter::emitGeneratePrologEpilog()
1667 unsigned prologCnt = 0;
1668 unsigned epilogCnt = 0;
1669 #if FEATURE_EH_FUNCLETS
1670 unsigned funcletPrologCnt = 0;
1671 unsigned funcletEpilogCnt = 0;
1672 #endif // FEATURE_EH_FUNCLETS
1678 // Generating the prolog/epilog is going to destroy the placeholder group,
1679 // so save the "next" pointer before that happens.
1681 for (igPh = emitPlaceholderList; igPh != nullptr; igPh = igPhNext)
1683 assert(igPh->igFlags & IGF_PLACEHOLDER);
1685 igPhNext = igPh->igPhData->igPhNext;
1687 BasicBlock* igPhBB = igPh->igPhData->igPhBB;
1689 switch (igPh->igPhData->igPhType)
1691 case IGPT_PROLOG: // currently unused
1692 INDEBUG(++prologCnt);
1696 INDEBUG(++epilogCnt);
1697 emitBegFnEpilog(igPh);
1698 codeGen->genFnEpilog(igPhBB);
1702 #if FEATURE_EH_FUNCLETS
1704 case IGPT_FUNCLET_PROLOG:
1705 INDEBUG(++funcletPrologCnt);
1706 emitBegFuncletProlog(igPh);
1707 codeGen->genFuncletProlog(igPhBB);
1708 emitEndFuncletProlog();
1711 case IGPT_FUNCLET_EPILOG:
1712 INDEBUG(++funcletEpilogCnt);
1713 emitBegFuncletEpilog(igPh);
1714 codeGen->genFuncletEpilog();
1715 emitEndFuncletEpilog();
1718 #endif // FEATURE_EH_FUNCLETS
1726 if (emitComp->verbose)
1728 printf("%d prologs, %d epilogs", prologCnt, epilogCnt);
1729 #if FEATURE_EH_FUNCLETS
1730 printf(", %d funclet prologs, %d funclet epilogs", funcletPrologCnt, funcletEpilogCnt);
1731 #endif // FEATURE_EH_FUNCLETS
1734 // prolog/epilog code doesn't use this yet
1735 // noway_assert(prologCnt == 1);
1736 // noway_assert(epilogCnt == emitEpilogCnt); // Is this correct?
1737 #if FEATURE_EH_FUNCLETS
1738 assert(funcletPrologCnt == emitComp->ehFuncletCount());
1739 #endif // FEATURE_EH_FUNCLETS
1744 /*****************************************************************************
1746 * Begin all prolog and epilog generation
1749 void emitter::emitStartPrologEpilogGeneration()
1751 /* Save the current IG if it's non-empty */
1753 if (emitCurIGnonEmpty())
1759 assert(emitCurIG == nullptr);
1763 /*****************************************************************************
1765 * Finish all prolog and epilog generation
1768 void emitter::emitFinishPrologEpilogGeneration()
1770 /* Update the offsets of all the blocks */
1772 emitRecomputeIGoffsets();
1774 /* We should not generate any more code after this */
1776 emitCurIG = nullptr;
1779 /*****************************************************************************
1781 * Common code for prolog / epilog beginning. Convert the placeholder group to actual code IG,
1782 * and set it as the current group.
1785 void emitter::emitBegPrologEpilog(insGroup* igPh)
1787 assert(igPh->igFlags & IGF_PLACEHOLDER);
1789 /* Save the current IG if it's non-empty */
1791 if (emitCurIGnonEmpty())
1796 /* Convert the placeholder group to a normal group.
1797 * We need to be very careful to re-initialize the IG properly.
1798 * It turns out, this means we only need to clear the placeholder bit
1799 * and clear the igPhData field, and emitGenIG() will do the rest,
1800 * since in the placeholder IG we didn't touch anything that is set by emitAllocIG().
1803 igPh->igFlags &= ~IGF_PLACEHOLDER;
1805 emitForceNewIG = false;
1807 /* Set up the GC info that we stored in the placeholder */
1809 VarSetOps::Assign(emitComp, emitPrevGCrefVars, igPh->igPhData->igPhPrevGCrefVars);
1810 emitPrevGCrefRegs = igPh->igPhData->igPhPrevGCrefRegs;
1811 emitPrevByrefRegs = igPh->igPhData->igPhPrevByrefRegs;
1813 VarSetOps::Assign(emitComp, emitThisGCrefVars, igPh->igPhData->igPhInitGCrefVars);
1814 VarSetOps::Assign(emitComp, emitInitGCrefVars, igPh->igPhData->igPhInitGCrefVars);
1815 emitThisGCrefRegs = emitInitGCrefRegs = igPh->igPhData->igPhInitGCrefRegs;
1816 emitThisByrefRegs = emitInitByrefRegs = igPh->igPhData->igPhInitByrefRegs;
1818 igPh->igPhData = nullptr;
1820 /* Create a non-placeholder group pointer that we'll now use */
1822 insGroup* ig = igPh;
1824 /* Set the current function using the function index we stored */
1826 emitComp->funSetCurrentFunc(ig->igFuncIdx);
1828 /* Set the new IG as the place to generate code */
1832 #if EMIT_TRACK_STACK_DEPTH
1834 /* Don't measure stack depth inside the prolog / epilog, it's misleading */
1836 emitCntStackDepth = 0;
1838 assert(emitCurStackLvl == 0);
1843 /*****************************************************************************
1845 * Common code for end of prolog / epilog
1848 void emitter::emitEndPrologEpilog()
1852 /* Save the IG if non-empty */
1854 if (emitCurIGnonEmpty())
1859 assert(emitCurIGsize <= MAX_PLACEHOLDER_IG_SIZE);
1861 #if EMIT_TRACK_STACK_DEPTH
1862 /* Reset the stack depth values */
1864 emitCurStackLvl = 0;
1865 emitCntStackDepth = sizeof(int);
1869 /*****************************************************************************
1871 * Begin generating a main function epilog.
1874 void emitter::emitBegFnEpilog(insGroup* igPh)
1878 emitBegPrologEpilog(igPh);
1880 #ifdef JIT32_GCENCODER
1882 EpilogList* el = new (emitComp, CMK_GC) EpilogList();
1884 if (emitEpilogLast != nullptr)
1886 emitEpilogLast->elNext = el;
1890 emitEpilogList = el;
1893 emitEpilogLast = el;
1895 #endif // JIT32_GCENCODER
1898 /*****************************************************************************
1900 * Finish generating a funclet epilog.
1903 void emitter::emitEndFnEpilog()
1905 emitEndPrologEpilog();
1907 #ifdef JIT32_GCENCODER
1908 assert(emitEpilogLast != nullptr);
1910 UNATIVE_OFFSET epilogBegCodeOffset = emitEpilogLast->elLoc.CodeOffset(this);
1911 UNATIVE_OFFSET epilogExitSeqStartCodeOffset = emitExitSeqBegLoc.CodeOffset(this);
1912 UNATIVE_OFFSET newSize = epilogExitSeqStartCodeOffset - epilogBegCodeOffset;
1914 /* Compute total epilog size */
1915 assert(emitEpilogSize == 0 || emitEpilogSize == newSize); // All epilogs must be identical
1916 emitEpilogSize = newSize;
1918 UNATIVE_OFFSET epilogEndCodeOffset = emitCodeOffset(emitCurIG, emitCurOffset());
1919 assert(epilogExitSeqStartCodeOffset != epilogEndCodeOffset);
1921 newSize = epilogEndCodeOffset - epilogExitSeqStartCodeOffset;
1922 if (newSize < emitExitSeqSize)
1924 // We expect either the epilog to be the same every time, or that
1925 // one will be a ret or a ret <n> and others will be a jmp addr or jmp [addr];
1926 // we make the epilogs the minimum of these. Note that this ONLY works
1927 // because the only instruction is the last one and thus a slight
1928 // underestimation of the epilog size is harmless (since the EIP
1929 // can not be between instructions).
1930 assert(emitEpilogCnt == 1 ||
1931 (emitExitSeqSize - newSize) <= 5 // delta between size of various forms of jmp (size is either 6 or 5)
1932 // and various forms of ret (size is either 1 or 3). The combination can
1933 // be anything been 1 and 5.
1935 emitExitSeqSize = newSize;
1937 #endif // JIT32_GCENCODER
1940 #if FEATURE_EH_FUNCLETS
1942 /*****************************************************************************
1944 * Begin generating a funclet prolog.
1947 void emitter::emitBegFuncletProlog(insGroup* igPh)
1949 emitBegPrologEpilog(igPh);
1952 /*****************************************************************************
1954 * Finish generating a funclet prolog.
1957 void emitter::emitEndFuncletProlog()
1959 emitEndPrologEpilog();
1962 /*****************************************************************************
1964 * Begin generating a funclet epilog.
1967 void emitter::emitBegFuncletEpilog(insGroup* igPh)
1969 emitBegPrologEpilog(igPh);
1972 /*****************************************************************************
1974 * Finish generating a funclet epilog.
1977 void emitter::emitEndFuncletEpilog()
1979 emitEndPrologEpilog();
1982 #endif // FEATURE_EH_FUNCLETS
1984 #ifdef JIT32_GCENCODER
1987 // emitter::emitStartEpilog:
1988 // Mark the current position so that we can later compute the total epilog size.
1990 void emitter::emitStartEpilog()
1992 assert(emitEpilogLast != nullptr);
1993 emitEpilogLast->elLoc.CaptureLocation(this);
1996 /*****************************************************************************
1998 * Return non-zero if the current method only has one epilog, which is
1999 * at the very end of the method body.
2002 bool emitter::emitHasEpilogEnd()
2004 if (emitEpilogCnt == 1 && (emitIGlast->igFlags & IGF_EPILOG)) // This wouldn't work for funclets
2010 #endif // JIT32_GCENCODER
2012 #ifdef _TARGET_XARCH_
2014 /*****************************************************************************
2016 * Mark the beginning of the epilog exit sequence by remembering our position.
2019 void emitter::emitStartExitSeq()
2021 assert(emitComp->compGeneratingEpilog);
2023 emitExitSeqBegLoc.CaptureLocation(this);
2026 #endif // _TARGET_XARCH_
2028 /*****************************************************************************
2030 * The code generator tells us the range of GC ref locals through this
2031 * method. Needless to say, locals and temps should be allocated so that
2032 * the size of the range is as small as possible.
2034 * offsLo - The FP offset from which the GC pointer range starts.
2035 * offsHi - The FP offset at which the GC pointer region ends (exclusive).
2038 void emitter::emitSetFrameRangeGCRs(int offsLo, int offsHi)
2040 assert(emitComp->compGeneratingProlog);
2041 assert(offsHi > offsLo);
2045 // A total of 47254 methods compiled.
2047 // GC ref frame variable counts:
2049 // <= 0 ===> 43175 count ( 91% of total)
2050 // 1 .. 1 ===> 2367 count ( 96% of total)
2051 // 2 .. 2 ===> 887 count ( 98% of total)
2052 // 3 .. 5 ===> 579 count ( 99% of total)
2053 // 6 .. 10 ===> 141 count ( 99% of total)
2054 // 11 .. 20 ===> 40 count ( 99% of total)
2055 // 21 .. 50 ===> 42 count ( 99% of total)
2056 // 51 .. 128 ===> 15 count ( 99% of total)
2057 // 129 .. 256 ===> 4 count ( 99% of total)
2058 // 257 .. 512 ===> 4 count (100% of total)
2059 // 513 .. 1024 ===> 0 count (100% of total)
2061 if (emitComp->verbose)
2063 unsigned count = (offsHi - offsLo) / TARGET_POINTER_SIZE;
2064 printf("%u tracked GC refs are at stack offsets ", count);
2068 printf(" %04X ... %04X\n", offsLo, offsHi);
2069 assert(offsHi >= 0);
2072 #if defined(_TARGET_ARM_) && defined(PROFILING_SUPPORTED)
2073 if (!emitComp->compIsProfilerHookNeeded())
2076 #ifdef _TARGET_AMD64_
2077 // doesn't have to be all negative on amd
2078 printf("-%04X ... %04X\n", -offsLo, offsHi);
2080 printf("-%04X ... -%04X\n", -offsLo, -offsHi);
2081 assert(offsHi <= 0);
2084 #if defined(_TARGET_ARM_) && defined(PROFILING_SUPPORTED)
2087 // Under profiler due to prespilling of arguments, offHi need not be < 0
2089 printf("-%04X ... -%04X\n", -offsLo, -offsHi);
2091 printf("-%04X ... %04X\n", -offsLo, offsHi);
2098 assert(((offsHi - offsLo) % TARGET_POINTER_SIZE) == 0);
2099 assert((offsLo % TARGET_POINTER_SIZE) == 0);
2100 assert((offsHi % TARGET_POINTER_SIZE) == 0);
2102 emitGCrFrameOffsMin = offsLo;
2103 emitGCrFrameOffsMax = offsHi;
2104 emitGCrFrameOffsCnt = (offsHi - offsLo) / TARGET_POINTER_SIZE;
2107 /*****************************************************************************
2109 * The code generator tells us the range of local variables through this
2113 void emitter::emitSetFrameRangeLcls(int offsLo, int offsHi)
2117 /*****************************************************************************
2119 * The code generator tells us the range of used arguments through this
2123 void emitter::emitSetFrameRangeArgs(int offsLo, int offsHi)
2127 /*****************************************************************************
2129 * A conversion table used to map an operand size value (in bytes) into its
2130 * small encoding (0 through 3), and vice versa.
2133 const emitter::opSize emitter::emitSizeEncode[] = {
2134 emitter::OPSZ1, emitter::OPSZ2, OPSIZE_INVALID, emitter::OPSZ4, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2135 emitter::OPSZ8, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2136 OPSIZE_INVALID, emitter::OPSZ16, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2137 OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2138 OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, emitter::OPSZ32,
2141 const emitAttr emitter::emitSizeDecode[emitter::OPSZ_COUNT] = {EA_1BYTE, EA_2BYTE, EA_4BYTE,
2142 EA_8BYTE, EA_16BYTE, EA_32BYTE};
2144 /*****************************************************************************
2146 * Allocate an instruction descriptor for an instruction that uses both
2147 * a displacement and a constant.
2150 emitter::instrDesc* emitter::emitNewInstrCnsDsp(emitAttr size, ssize_t cns, int dsp)
2154 if (instrDesc::fitsInSmallCns(cns))
2156 instrDesc* id = emitAllocInstr(size);
2158 id->idSmallCns(cns);
2162 emitSmallCns[cns - ID_MIN_SMALL_CNS]++;
2170 instrDescCns* id = emitAllocInstrCns(size);
2172 id->idSetIsLargeCns();
2173 id->idcCnsVal = cns;
2185 if (instrDesc::fitsInSmallCns(cns))
2187 instrDescDsp* id = emitAllocInstrDsp(size);
2189 id->idSetIsLargeDsp();
2190 id->iddDspVal = dsp;
2192 id->idSmallCns(cns);
2197 emitSmallCns[cns - ID_MIN_SMALL_CNS]++;
2204 instrDescCnsDsp* id = emitAllocInstrCnsDsp(size);
2206 id->idSetIsLargeCns();
2207 id->iddcCnsVal = cns;
2209 id->idSetIsLargeDsp();
2210 id->iddcDspVal = dsp;
2222 /*****************************************************************************
2224 * Returns true if garbage-collection won't happen within the helper call.
2225 * Don't need to record live pointers for such call sites.
2228 bool emitter::emitNoGChelper(unsigned IHX)
2230 // TODO-Throughput: Make this faster (maybe via a simple table of bools?)
2234 case CORINFO_HELP_UNDEF:
2237 case CORINFO_HELP_PROF_FCN_LEAVE:
2238 case CORINFO_HELP_PROF_FCN_ENTER:
2239 #if defined(_TARGET_XARCH_)
2240 case CORINFO_HELP_PROF_FCN_TAILCALL:
2242 case CORINFO_HELP_LLSH:
2243 case CORINFO_HELP_LRSH:
2244 case CORINFO_HELP_LRSZ:
2246 // case CORINFO_HELP_LMUL:
2247 // case CORINFO_HELP_LDIV:
2248 // case CORINFO_HELP_LMOD:
2249 // case CORINFO_HELP_ULDIV:
2250 // case CORINFO_HELP_ULMOD:
2253 case CORINFO_HELP_ASSIGN_REF_EAX:
2254 case CORINFO_HELP_ASSIGN_REF_ECX:
2255 case CORINFO_HELP_ASSIGN_REF_EBX:
2256 case CORINFO_HELP_ASSIGN_REF_EBP:
2257 case CORINFO_HELP_ASSIGN_REF_ESI:
2258 case CORINFO_HELP_ASSIGN_REF_EDI:
2260 case CORINFO_HELP_CHECKED_ASSIGN_REF_EAX:
2261 case CORINFO_HELP_CHECKED_ASSIGN_REF_ECX:
2262 case CORINFO_HELP_CHECKED_ASSIGN_REF_EBX:
2263 case CORINFO_HELP_CHECKED_ASSIGN_REF_EBP:
2264 case CORINFO_HELP_CHECKED_ASSIGN_REF_ESI:
2265 case CORINFO_HELP_CHECKED_ASSIGN_REF_EDI:
2268 case CORINFO_HELP_ASSIGN_REF:
2269 case CORINFO_HELP_CHECKED_ASSIGN_REF:
2270 case CORINFO_HELP_ASSIGN_BYREF:
2272 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
2273 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
2275 case CORINFO_HELP_INIT_PINVOKE_FRAME:
2283 /*****************************************************************************
2285 * Mark the current spot as having a label.
2288 void* emitter::emitAddLabel(VARSET_VALARG_TP GCvars, regMaskTP gcrefRegs, regMaskTP byrefRegs, BOOL isFinallyTarget)
2290 /* Create a new IG if the current one is non-empty */
2292 if (emitCurIGnonEmpty())
2297 VarSetOps::Assign(emitComp, emitThisGCrefVars, GCvars);
2298 VarSetOps::Assign(emitComp, emitInitGCrefVars, GCvars);
2299 emitThisGCrefRegs = emitInitGCrefRegs = gcrefRegs;
2300 emitThisByrefRegs = emitInitByrefRegs = byrefRegs;
2302 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2303 if (isFinallyTarget)
2305 emitCurIG->igFlags |= IGF_FINALLY_TARGET;
2307 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2310 if (EMIT_GC_VERBOSE)
2312 printf("Label: IG%02u, GCvars=%s ", emitCurIG->igNum, VarSetOps::ToString(emitComp, GCvars));
2313 dumpConvertedVarSet(emitComp, GCvars);
2314 printf(", gcrefRegs=");
2315 printRegMaskInt(gcrefRegs);
2316 emitDispRegSet(gcrefRegs);
2317 printf(", byrefRegs=");
2318 printRegMaskInt(byrefRegs);
2319 emitDispRegSet(byrefRegs);
2326 #ifdef _TARGET_ARMARCH_
2328 // Does the argument location point to an IG at the end of a function or funclet?
2329 // We can ignore the codePos part of the location, since it doesn't affect the
2330 // determination. If 'emitLocNextFragment' is non-NULL, it indicates the first
2331 // IG of the next fragment, so it represents a function end.
2332 bool emitter::emitIsFuncEnd(emitLocation* emitLoc, emitLocation* emitLocNextFragment /* = NULL */)
2336 insGroup* ig = emitLoc->GetIG();
2339 // Are we at the end of the IG list?
2340 if ((emitLocNextFragment != NULL) && (ig->igNext == emitLocNextFragment->GetIG()))
2344 if (ig->igNext == NULL)
2347 // Is the next IG the start of a funclet prolog?
2348 if (ig->igNext->igFlags & IGF_FUNCLET_PROLOG)
2351 #if FEATURE_EH_FUNCLETS
2353 // Is the next IG a placeholder group for a funclet prolog?
2354 if ((ig->igNext->igFlags & IGF_PLACEHOLDER) && (ig->igNext->igPhData->igPhType == IGPT_FUNCLET_PROLOG))
2359 #endif // FEATURE_EH_FUNCLETS
2364 /*****************************************************************************
2366 * Split the region from 'startLoc' to 'endLoc' into fragments by calling
2367 * a callback function to indicate the beginning of a fragment. The initial code,
2368 * starting at 'startLoc', doesn't get a callback, but the first code fragment,
2369 * about 'maxSplitSize' bytes out does, as does the beginning of each fragment
2370 * after that. There is no callback for the end (only the beginning of the last
2371 * fragment gets a callback). A fragment must contain at least one instruction
2372 * group. It should be smaller than 'maxSplitSize', although it may be larger to
2373 * satisfy the "at least one instruction group" rule. Do not split prologs or
2374 * epilogs. (Currently, prologs exist in a single instruction group at the main
2375 * function beginning, so they aren't split. Funclets, however, might span IGs,
2376 * so we can't split in between them.)
2378 * Note that the locations must be the start of instruction groups; the part of
2379 * the location indicating offset within a group must be zero.
2381 * If 'startLoc' is NULL, it means the start of the code.
2382 * If 'endLoc' is NULL, it means the end of the code.
2385 void emitter::emitSplit(emitLocation* startLoc,
2386 emitLocation* endLoc,
2387 UNATIVE_OFFSET maxSplitSize,
2389 emitSplitCallbackType callbackFunc)
2391 insGroup* igStart = (startLoc == NULL) ? emitIGlist : startLoc->GetIG();
2392 insGroup* igEnd = (endLoc == NULL) ? NULL : endLoc->GetIG();
2395 insGroup* igLastReported;
2396 insGroup* igLastCandidate;
2397 UNATIVE_OFFSET curSize;
2398 UNATIVE_OFFSET candidateSize;
2400 for (igPrev = NULL, ig = igLastReported = igStart, igLastCandidate = NULL, candidateSize = 0, curSize = 0;
2401 ig != igEnd && ig != NULL; igPrev = ig, ig = ig->igNext)
2403 // Keep looking until we've gone past the maximum split size
2404 if (curSize >= maxSplitSize)
2406 bool reportCandidate = true;
2408 // Is there a candidate?
2409 if (igLastCandidate == NULL)
2413 printf("emitSplit: can't split at IG%02u; we don't have a candidate to report\n", ig->igNum);
2415 reportCandidate = false;
2418 // Don't report the same thing twice (this also happens for the first block, since igLastReported is
2419 // initialized to igStart).
2420 if (igLastCandidate == igLastReported)
2424 printf("emitSplit: can't split at IG%02u; we already reported it\n", igLastCandidate->igNum);
2426 reportCandidate = false;
2430 if (reportCandidate)
2433 if (EMITVERBOSE && (candidateSize >= maxSplitSize))
2434 printf("emitSplit: split at IG%02u is size %d, larger than requested maximum size of %d\n",
2435 igLastCandidate->igNum, candidateSize, maxSplitSize);
2438 // hand memory ownership to the callback function
2439 emitLocation* pEmitLoc = new (emitComp, CMK_Unknown) emitLocation(igLastCandidate);
2440 callbackFunc(context, pEmitLoc);
2441 igLastReported = igLastCandidate;
2442 igLastCandidate = NULL;
2443 curSize -= candidateSize;
2447 // Update the current candidate to be this block, if it isn't in the middle of a
2448 // prolog or epilog, which we can't split. All we know is that certain
2449 // IGs are marked as prolog or epilog. We don't actually know if two adjacent
2450 // IGs are part of the *same* prolog or epilog, so we have to assume they are.
2452 if (igPrev && (((igPrev->igFlags & IGF_FUNCLET_PROLOG) && (ig->igFlags & IGF_FUNCLET_PROLOG)) ||
2453 ((igPrev->igFlags & IGF_EPILOG) && (ig->igFlags & IGF_EPILOG))))
2455 // We can't update the candidate
2459 igLastCandidate = ig;
2460 candidateSize = curSize;
2463 curSize += ig->igSize;
2468 /*****************************************************************************
2470 * Given an instruction group, find the array of instructions (instrDesc) and
2471 * number of instructions in the array. If the IG is the current IG, we assume
2472 * that igData does NOT hold the instructions; they are unsaved and pointed
2473 * to by emitCurIGfreeBase.
2475 * This function can't be called for placeholder groups, which have no instrDescs.
2478 void emitter::emitGetInstrDescs(insGroup* ig, instrDesc** id, int* insCnt)
2480 assert(!(ig->igFlags & IGF_PLACEHOLDER));
2481 if (ig == emitCurIG)
2483 *id = (instrDesc*)emitCurIGfreeBase;
2484 *insCnt = emitCurIGinsCnt;
2488 *id = (instrDesc*)ig->igData;
2489 *insCnt = ig->igInsCnt;
2495 /*****************************************************************************
2497 * Given a location (an 'emitLocation'), find the instruction group (IG) and
2498 * instruction descriptor (instrDesc) corresponding to that location. Returns
2499 * 'true' if there is an instruction, 'false' if there is no instruction
2500 * (i.e., we're at the end of the instruction list). Also, optionally return
2501 * the number of instructions that follow that instruction in the IG (in *pinsRemaining,
2502 * if pinsRemaining is non-NULL), which can be used for iterating over the
2503 * remaining instrDescs in the IG.
2505 * We assume that emitCurIG points to the end of the instructions we care about.
2506 * For the prologs or epilogs, it points to the last IG of the prolog or epilog
2507 * that is being generated. For body code gen, it points to the place we are currently
2508 * adding code, namely, the end of currently generated code.
2511 bool emitter::emitGetLocationInfo(emitLocation* emitLoc,
2514 int* pinsRemaining /* = NULL */)
2516 assert(emitLoc != nullptr);
2517 assert(emitLoc->Valid());
2518 assert(emitLoc->GetIG() != nullptr);
2519 assert(pig != nullptr);
2520 assert(pid != nullptr);
2522 insGroup* ig = emitLoc->GetIG();
2524 int insNum = emitLoc->GetInsNum();
2527 emitGetInstrDescs(ig, &id, &insCnt);
2528 assert(insNum <= insCnt);
2530 // There is a special-case: if the insNum points to the end, then we "wrap" and
2531 // consider that the instruction it is pointing at is actually the first instruction
2532 // of the next non-empty IG (which has its own valid emitLocation). This handles the
2533 // case where you capture a location, then the next instruction creates a new IG.
2535 if (insNum == insCnt)
2537 if (ig == emitCurIG)
2539 // No instructions beyond the current location.
2543 for (ig = ig->igNext; ig; ig = ig->igNext)
2545 emitGetInstrDescs(ig, &id, &insCnt);
2549 insNum = 0; // Pretend the index is 0 -- the first instruction
2553 if (ig == emitCurIG)
2555 // There aren't any instructions in the current IG, and this is
2556 // the current location, so we're at the end.
2563 // 'ig' can't be NULL, or we went past the current IG represented by 'emitCurIG'.
2564 // Perhaps 'loc' was corrupt coming in?
2565 noway_assert(!"corrupt emitter location");
2570 // Now find the instrDesc within this group that corresponds to the location
2572 assert(insNum < insCnt);
2575 for (i = 0; i != insNum; ++i)
2577 castto(id, BYTE*) += emitSizeOfInsDsc(id);
2580 // Return the info we found
2587 *pinsRemaining = insCnt - insNum - 1;
2593 /*****************************************************************************
2595 * Compute the next instrDesc, either in this IG, or in a subsequent IG. 'id'
2596 * will point to this instrDesc. 'ig' and 'insRemaining' will also be updated.
2597 * Returns true if there is an instruction, or false if we've iterated over all
2598 * the instructions up to the current instruction (based on 'emitCurIG').
2601 bool emitter::emitNextID(insGroup*& ig, instrDesc*& id, int& insRemaining)
2603 if (insRemaining > 0)
2605 castto(id, BYTE*) += emitSizeOfInsDsc(id);
2610 // We're out of instrDesc in 'ig'. Is this the current IG? If so, we're done.
2612 if (ig == emitCurIG)
2617 for (ig = ig->igNext; ig; ig = ig->igNext)
2620 emitGetInstrDescs(ig, &id, &insCnt);
2624 insRemaining = insCnt - 1;
2628 if (ig == emitCurIG)
2637 /*****************************************************************************
2639 * Walk instrDesc's from the location given by 'locFrom', up to the current location.
2640 * For each instruction, call the callback function 'processFunc'. 'context' is simply
2641 * passed through to the callback function.
2644 void emitter::emitWalkIDs(emitLocation* locFrom, emitProcessInstrFunc_t processFunc, void* context)
2650 if (!emitGetLocationInfo(locFrom, &ig, &id, &insRemaining))
2651 return; // no instructions at the 'from' location
2656 (*processFunc)(id, context);
2658 } while (emitNextID(ig, id, insRemaining));
2661 /*****************************************************************************
2663 * A callback function for emitWalkIDs() that calls Compiler::unwindNop().
2666 void emitter::emitGenerateUnwindNop(instrDesc* id, void* context)
2668 Compiler* comp = (Compiler*)context;
2669 #if defined(_TARGET_ARM_)
2670 comp->unwindNop(id->idCodeSize());
2671 #elif defined(_TARGET_ARM64_)
2673 #endif // defined(_TARGET_ARM64_)
2676 /*****************************************************************************
2678 * emitUnwindNopPadding: call unwindNop() for every instruction from a given
2679 * location 'emitLoc' up to the current location.
2682 void emitter::emitUnwindNopPadding(emitLocation* locFrom, Compiler* comp)
2684 emitWalkIDs(locFrom, emitGenerateUnwindNop, comp);
2687 #endif // _TARGET_ARMARCH_
2689 #if defined(_TARGET_ARM_)
2691 /*****************************************************************************
2693 * Return the instruction size in bytes for the instruction at the specified location.
2694 * This is used to assert that the unwind code being generated on ARM has the
2695 * same size as the instruction for which it is being generated (since on ARM
2696 * the unwind codes have a one-to-one relationship with instructions, and the
2697 * unwind codes have an implicit instruction size that must match the instruction size.)
2698 * An instruction must exist at the specified location.
2701 unsigned emitter::emitGetInstructionSize(emitLocation* emitLoc)
2706 bool anyInstrs = emitGetLocationInfo(emitLoc, &ig, &id);
2707 assert(anyInstrs); // There better be an instruction at this location (otherwise, we're at the end of the
2708 // instruction list)
2709 return id->idCodeSize();
2712 #endif // defined(_TARGET_ARM_)
2714 /*****************************************************************************/
2716 /*****************************************************************************
2718 * Returns the name for the register to use to access frame based variables
2721 const char* emitter::emitGetFrameReg()
2723 if (emitHasFramePtr)
2733 /*****************************************************************************
2735 * Display a register set in a readable form.
2738 void emitter::emitDispRegSet(regMaskTP regs)
2745 for (reg = REG_FIRST; reg < ACTUAL_REG_COUNT; reg = REG_NEXT(reg))
2747 if ((regs & genRegMask(reg)) == 0)
2761 printf("%s", emitRegName(reg));
2767 /*****************************************************************************
2769 * Display the current GC ref variable set in a readable form.
2772 void emitter::emitDispVarSet()
2778 for (vn = 0, of = emitGCrFrameOffsMin; vn < emitGCrFrameOffsCnt; vn += 1, of += TARGET_POINTER_SIZE)
2780 if (emitGCrFrameLiveTab[vn])
2791 printf("[%s", emitGetFrameReg());
2795 printf("-%02XH", -of);
2799 printf("+%02XH", +of);
2812 /*****************************************************************************/
2815 #if MULTIREG_HAS_SECOND_GC_RET
2816 //------------------------------------------------------------------------
2817 // emitSetSecondRetRegGCType: Sets the GC type of the second return register for instrDescCGCA struct.
2820 // id - The large call instr descriptor to set the second GC return register type on.
2821 // secondRetSize - The EA_SIZE for second return register type.
2827 void emitter::emitSetSecondRetRegGCType(instrDescCGCA* id, emitAttr secondRetSize)
2829 if (EA_IS_GCREF(secondRetSize))
2831 id->idSecondGCref(GCT_GCREF);
2833 else if (EA_IS_BYREF(secondRetSize))
2835 id->idSecondGCref(GCT_BYREF);
2839 id->idSecondGCref(GCT_NONE);
2842 #endif // MULTIREG_HAS_SECOND_GC_RET
2844 /*****************************************************************************
2846 * Allocate an instruction descriptor for an indirect call.
2848 * We use two different descriptors to save space - the common case records
2849 * no GC variables and has both a very small argument count and an address
2850 * mode displacement; the other case records the current GC var set,
2851 * the call scope, and an arbitrarily large argument count and the
2852 * address mode displacement.
2855 emitter::instrDesc* emitter::emitNewInstrCallInd(int argCnt,
2857 VARSET_VALARG_TP GCvars,
2858 regMaskTP gcrefRegs,
2859 regMaskTP byrefRegs,
2861 MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize))
2863 emitAttr retSize = (retSizeIn != EA_UNKNOWN) ? retSizeIn : EA_PTRSIZE;
2865 bool gcRefRegsInScratch = ((gcrefRegs & RBM_CALLEE_TRASH) != 0);
2867 // Allocate a larger descriptor if any GC values need to be saved
2868 // or if we have an absurd number of arguments or a large address
2869 // mode displacement, or we have some byref registers
2871 // On Amd64 System V OSs a larger descriptor is also needed if the
2872 // call returns a two-register-returned struct and the second
2873 // register (RDX) is a GCRef or ByRef pointer.
2875 if (!VarSetOps::IsEmpty(emitComp, GCvars) || // any frame GCvars live
2876 (gcRefRegsInScratch) || // any register gc refs live in scratch regs
2877 (byrefRegs != 0) || // any register byrefs live
2878 (disp < AM_DISP_MIN) || // displacement too negative
2879 (disp > AM_DISP_MAX) || // displacement too positive
2880 (argCnt > ID_MAX_SMALL_CNS) || // too many args
2881 (argCnt < 0) // caller pops arguments
2882 // There is a second ref/byref return register.
2883 MULTIREG_HAS_SECOND_GC_RET_ONLY(|| EA_IS_GCREF_OR_BYREF(secondRetSize)))
2887 id = emitAllocInstrCGCA(retSize);
2889 id->idSetIsLargeCall();
2891 VarSetOps::Assign(emitComp, id->idcGCvars, GCvars);
2892 id->idcGcrefRegs = gcrefRegs;
2893 id->idcByrefRegs = byrefRegs;
2894 id->idcArgCnt = argCnt;
2897 #if MULTIREG_HAS_SECOND_GC_RET
2898 emitSetSecondRetRegGCType(id, secondRetSize);
2899 #endif // MULTIREG_HAS_SECOND_GC_RET
2907 id = emitNewInstrCns(retSize, argCnt);
2909 /* Make sure we didn't waste space unexpectedly */
2910 assert(!id->idIsLargeCns());
2912 /* Store the displacement and make sure the value fit */
2913 id->idAddr()->iiaAddrMode.amDisp = disp;
2914 assert(id->idAddr()->iiaAddrMode.amDisp == disp);
2916 /* Save the the live GC registers in the unused register fields */
2917 emitEncodeCallGCregs(gcrefRegs, id);
2923 /*****************************************************************************
2925 * Allocate an instruction descriptor for a direct call.
2927 * We use two different descriptors to save space - the common case records
2928 * with no GC variables or byrefs and has a very small argument count, and no
2930 * the other case records the current GC var set, the call scope,
2931 * and an arbitrarily large argument count.
2934 emitter::instrDesc* emitter::emitNewInstrCallDir(int argCnt,
2935 VARSET_VALARG_TP GCvars,
2936 regMaskTP gcrefRegs,
2937 regMaskTP byrefRegs,
2939 MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize))
2941 emitAttr retSize = (retSizeIn != EA_UNKNOWN) ? retSizeIn : EA_PTRSIZE;
2943 // Allocate a larger descriptor if new GC values need to be saved
2944 // or if we have an absurd number of arguments or if we need to
2947 // On Amd64 System V OSs a larger descriptor is also needed if the
2948 // call returns a two-register-returned struct and the second
2949 // register (RDX) is a GCRef or ByRef pointer.
2951 bool gcRefRegsInScratch = ((gcrefRegs & RBM_CALLEE_TRASH) != 0);
2953 if (!VarSetOps::IsEmpty(emitComp, GCvars) || // any frame GCvars live
2954 gcRefRegsInScratch || // any register gc refs live in scratch regs
2955 (byrefRegs != 0) || // any register byrefs live
2956 (argCnt > ID_MAX_SMALL_CNS) || // too many args
2957 (argCnt < 0) // caller pops arguments
2958 // There is a second ref/byref return register.
2959 MULTIREG_HAS_SECOND_GC_RET_ONLY(|| EA_IS_GCREF_OR_BYREF(secondRetSize)))
2961 instrDescCGCA* id = emitAllocInstrCGCA(retSize);
2963 // printf("Direct call with GC vars / big arg cnt / explicit scope\n");
2965 id->idSetIsLargeCall();
2967 VarSetOps::Assign(emitComp, id->idcGCvars, GCvars);
2968 id->idcGcrefRegs = gcrefRegs;
2969 id->idcByrefRegs = byrefRegs;
2971 id->idcArgCnt = argCnt;
2973 #if MULTIREG_HAS_SECOND_GC_RET
2974 emitSetSecondRetRegGCType(id, secondRetSize);
2975 #endif // MULTIREG_HAS_SECOND_GC_RET
2981 instrDesc* id = emitNewInstrCns(retSize, argCnt);
2983 // printf("Direct call w/o GC vars / big arg cnt / explicit scope\n");
2985 /* Make sure we didn't waste space unexpectedly */
2986 assert(!id->idIsLargeCns());
2988 /* Save the the live GC registers in the unused register fields */
2989 emitEncodeCallGCregs(gcrefRegs, id);
2995 /*****************************************************************************/
2997 /*****************************************************************************
2999 * Return a string with the name of the given class field (blank string (not
3000 * NULL) is returned when the name isn't available).
3003 const char* emitter::emitFldName(CORINFO_FIELD_HANDLE fieldVal)
3005 if (emitComp->opts.varNames)
3007 const char* memberName;
3008 const char* className;
3010 const int TEMP_BUFFER_LEN = 1024;
3011 static char buff[TEMP_BUFFER_LEN];
3013 memberName = emitComp->eeGetFieldName(fieldVal, &className);
3015 sprintf_s(buff, TEMP_BUFFER_LEN, "'<%s>.%s'", className, memberName);
3024 /*****************************************************************************
3026 * Return a string with the name of the given function (blank string (not
3027 * NULL) is returned when the name isn't available).
3030 const char* emitter::emitFncName(CORINFO_METHOD_HANDLE methHnd)
3032 return emitComp->eeGetMethodFullName(methHnd);
3037 /*****************************************************************************
3039 * Be very careful, some instruction descriptors are allocated as "tiny" and
3040 * don't have some of the tail fields of instrDesc (in particular, "idInfo").
3043 const BYTE emitter::emitFmtToOps[] = {
3044 #define IF_DEF(en, op1, op2) ID_OP_##op2,
3045 #include "emitfmts.h"
3049 const unsigned emitter::emitFmtCount = _countof(emitFmtToOps);
3052 /*****************************************************************************
3054 * Display the current instruction group list.
3059 void emitter::emitDispIGflags(unsigned flags)
3061 if (flags & IGF_GC_VARS)
3065 if (flags & IGF_BYREF_REGS)
3069 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
3070 if (flags & IGF_FINALLY_TARGET)
3072 printf(", ftarget");
3074 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
3075 if (flags & IGF_FUNCLET_PROLOG)
3077 printf(", funclet prolog");
3079 if (flags & IGF_FUNCLET_EPILOG)
3081 printf(", funclet epilog");
3083 if (flags & IGF_EPILOG)
3087 if (flags & IGF_NOGCINTERRUPT)
3091 if (flags & IGF_UPD_ISZ)
3095 if (flags & IGF_EMIT_ADD)
3097 printf(", emitadd");
3101 void emitter::emitDispIG(insGroup* ig, insGroup* igPrev, bool verbose)
3103 const int TEMP_BUFFER_LEN = 40;
3104 char buff[TEMP_BUFFER_LEN];
3106 sprintf_s(buff, TEMP_BUFFER_LEN, "G_M%03u_IG%02u: ", Compiler::s_compMethodsCount, ig->igNum);
3107 printf("%s; ", buff);
3108 if ((igPrev == nullptr) || (igPrev->igFuncIdx != ig->igFuncIdx))
3110 printf("func=%02u, ", ig->igFuncIdx);
3113 if (ig->igFlags & IGF_PLACEHOLDER)
3115 insGroup* igPh = ig;
3117 const char* pszType;
3118 switch (igPh->igPhData->igPhType)
3126 #if FEATURE_EH_FUNCLETS
3127 case IGPT_FUNCLET_PROLOG:
3128 pszType = "funclet prolog";
3130 case IGPT_FUNCLET_EPILOG:
3131 pszType = "funclet epilog";
3133 #endif // FEATURE_EH_FUNCLETS
3135 pszType = "UNKNOWN";
3138 printf("%s placeholder, next placeholder=", pszType);
3139 if (igPh->igPhData->igPhNext)
3141 printf("IG%02u ", igPh->igPhData->igPhNext->igNum);
3148 if (igPh->igPhData->igPhBB != nullptr)
3150 printf(", %s", igPh->igPhData->igPhBB->dspToString());
3153 emitDispIGflags(igPh->igFlags);
3155 if (ig == emitCurIG)
3157 printf(" <-- Current IG");
3159 if (igPh == emitPlaceholderList)
3161 printf(" <-- First placeholder");
3163 if (igPh == emitPlaceholderLast)
3165 printf(" <-- Last placeholder");
3169 printf("%*s; PrevGCVars=%s ", strlen(buff), "",
3170 VarSetOps::ToString(emitComp, igPh->igPhData->igPhPrevGCrefVars));
3171 dumpConvertedVarSet(emitComp, igPh->igPhData->igPhPrevGCrefVars);
3172 printf(", PrevGCrefRegs=");
3173 printRegMaskInt(igPh->igPhData->igPhPrevGCrefRegs);
3174 emitDispRegSet(igPh->igPhData->igPhPrevGCrefRegs);
3175 printf(", PrevByrefRegs=");
3176 printRegMaskInt(igPh->igPhData->igPhPrevByrefRegs);
3177 emitDispRegSet(igPh->igPhData->igPhPrevByrefRegs);
3180 printf("%*s; InitGCVars=%s ", strlen(buff), "",
3181 VarSetOps::ToString(emitComp, igPh->igPhData->igPhInitGCrefVars));
3182 dumpConvertedVarSet(emitComp, igPh->igPhData->igPhInitGCrefVars);
3183 printf(", InitGCrefRegs=");
3184 printRegMaskInt(igPh->igPhData->igPhInitGCrefRegs);
3185 emitDispRegSet(igPh->igPhData->igPhInitGCrefRegs);
3186 printf(", InitByrefRegs=");
3187 printRegMaskInt(igPh->igPhData->igPhInitByrefRegs);
3188 emitDispRegSet(igPh->igPhData->igPhInitByrefRegs);
3191 assert(!(ig->igFlags & IGF_GC_VARS));
3192 assert(!(ig->igFlags & IGF_BYREF_REGS));
3196 printf("offs=%06XH, size=%04XH", ig->igOffs, ig->igSize);
3198 if (ig->igFlags & IGF_GC_VARS)
3200 printf(", gcVars=%s ", VarSetOps::ToString(emitComp, ig->igGCvars()));
3201 dumpConvertedVarSet(emitComp, ig->igGCvars());
3204 if (!(ig->igFlags & IGF_EMIT_ADD))
3206 printf(", gcrefRegs=");
3207 printRegMaskInt(ig->igGCregs);
3208 emitDispRegSet(ig->igGCregs);
3211 if (ig->igFlags & IGF_BYREF_REGS)
3213 printf(", byrefRegs=");
3214 printRegMaskInt(ig->igByrefRegs());
3215 emitDispRegSet(ig->igByrefRegs());
3218 emitDispIGflags(ig->igFlags);
3220 if (ig == emitCurIG)
3222 printf(" <-- Current IG");
3224 if (ig == emitPrologIG)
3226 printf(" <-- Prolog IG");
3232 BYTE* ins = ig->igData;
3233 UNATIVE_OFFSET ofs = ig->igOffs;
3234 unsigned cnt = ig->igInsCnt;
3242 instrDesc* id = (instrDesc*)ins;
3244 emitDispIns(id, false, true, false, ofs, nullptr, 0, ig);
3246 ins += emitSizeOfInsDsc(id);
3247 ofs += emitInstCodeSz(id);
3256 void emitter::emitDispIGlist(bool verbose)
3261 for (igPrev = nullptr, ig = emitIGlist; ig; igPrev = ig, ig = ig->igNext)
3263 emitDispIG(ig, igPrev, verbose);
3267 void emitter::emitDispGCinfo()
3269 printf("Emitter GC tracking info:");
3270 printf("\n emitPrevGCrefVars ");
3271 dumpConvertedVarSet(emitComp, emitPrevGCrefVars);
3272 printf("\n emitPrevGCrefRegs(0x%p)=", dspPtr(&emitPrevGCrefRegs));
3273 printRegMaskInt(emitPrevGCrefRegs);
3274 emitDispRegSet(emitPrevGCrefRegs);
3275 printf("\n emitPrevByrefRegs(0x%p)=", dspPtr(&emitPrevByrefRegs));
3276 printRegMaskInt(emitPrevByrefRegs);
3277 emitDispRegSet(emitPrevByrefRegs);
3278 printf("\n emitInitGCrefVars ");
3279 dumpConvertedVarSet(emitComp, emitInitGCrefVars);
3280 printf("\n emitInitGCrefRegs(0x%p)=", dspPtr(&emitInitGCrefRegs));
3281 printRegMaskInt(emitInitGCrefRegs);
3282 emitDispRegSet(emitInitGCrefRegs);
3283 printf("\n emitInitByrefRegs(0x%p)=", dspPtr(&emitInitByrefRegs));
3284 printRegMaskInt(emitInitByrefRegs);
3285 emitDispRegSet(emitInitByrefRegs);
3286 printf("\n emitThisGCrefVars ");
3287 dumpConvertedVarSet(emitComp, emitThisGCrefVars);
3288 printf("\n emitThisGCrefRegs(0x%p)=", dspPtr(&emitThisGCrefRegs));
3289 printRegMaskInt(emitThisGCrefRegs);
3290 emitDispRegSet(emitThisGCrefRegs);
3291 printf("\n emitThisByrefRegs(0x%p)=", dspPtr(&emitThisByrefRegs));
3292 printRegMaskInt(emitThisByrefRegs);
3293 emitDispRegSet(emitThisByrefRegs);
3299 /*****************************************************************************
3301 * Issue the given instruction. Basically, this is just a thin wrapper around
3302 * emitOutputInstr() that does a few debug checks.
3305 size_t emitter::emitIssue1Instr(insGroup* ig, instrDesc* id, BYTE** dp)
3309 /* Record the beginning offset of the instruction */
3311 BYTE* curInsAdr = *dp;
3313 /* Issue the next instruction */
3315 // printf("[S=%02u] " , emitCurStackLvl);
3317 is = emitOutputInstr(ig, id, dp);
3319 // printf("[S=%02u]\n", emitCurStackLvl);
3321 #if EMIT_TRACK_STACK_DEPTH
3324 If we're generating a full pointer map and the stack
3325 is empty, there better not be any "pending" argument
3329 assert(emitFullGCinfo == false || emitCurStackLvl != 0 || u2.emitGcArgTrackCnt == 0);
3333 /* Did the size of the instruction match our expectations? */
3335 UNATIVE_OFFSET csz = (UNATIVE_OFFSET)(*dp - curInsAdr);
3337 if (csz != id->idCodeSize())
3339 /* It is fatal to under-estimate the instruction size */
3340 noway_assert(emitInstCodeSz(id) >= csz);
3345 printf("Instruction predicted size = %u, actual = %u\n", emitInstCodeSz(id), csz);
3347 #endif // DEBUG_EMIT
3349 /* The instruction size estimate wasn't accurate; remember this */
3351 ig->igFlags |= IGF_UPD_ISZ;
3352 #if defined(_TARGET_XARCH_)
3353 id->idCodeSize(csz);
3354 #elif defined(_TARGET_ARM_)
3355 // This is done as part of emitSetShortJump();
3356 // insSize isz = emitInsSize(id->idInsFmt());
3357 // id->idInsSize(isz);
3359 /* It is fatal to over-estimate the instruction size */
3360 IMPL_LIMITATION("Over-estimated instruction size");
3365 /* Make sure the instruction descriptor size also matches our expectations */
3366 if (is != emitSizeOfInsDsc(id))
3368 printf("%s at %u: Expected size = %u , actual size = %u\n", emitIfName(id->idInsFmt()),
3369 id->idDebugOnlyInfo()->idNum, is, emitSizeOfInsDsc(id));
3370 assert(is == emitSizeOfInsDsc(id));
3377 /*****************************************************************************
3379 * Update the offsets of all the instruction groups (note: please don't be
3380 * lazy and call this routine frequently, it walks the list of instruction
3381 * groups and thus it isn't cheap).
3384 void emitter::emitRecomputeIGoffsets()
3386 UNATIVE_OFFSET offs;
3389 for (ig = emitIGlist, offs = 0; ig; ig = ig->igNext)
3392 assert(IsCodeAligned(ig->igOffs));
3396 /* Set the total code size */
3398 emitTotalCodeSize = offs;
3401 emitCheckIGoffsets();
3405 /*****************************************************************************
3406 * Bind targets of relative jumps to choose the smallest possible encoding.
3407 * X86 and AMD64 have a small and large encoding.
3408 * ARM has a small, medium, and large encoding. The large encoding is a pseudo-op
3409 * to handle greater range than the conditional branch instructions can handle.
3410 * ARM64 has a small and large encoding for both conditional branch and loading label addresses.
3411 * The large encodings are pseudo-ops that represent a multiple instruction sequence, similar to ARM. (Currently
3415 void emitter::emitJumpDistBind()
3418 if (emitComp->verbose)
3420 printf("*************** In emitJumpDistBind()\n");
3422 if (EMIT_INSTLIST_VERBOSE)
3424 printf("\nInstruction list before jump distance binding:\n\n");
3425 emitDispIGlist(true);
3431 UNATIVE_OFFSET minShortExtra; // The smallest offset greater than that required for a jump to be converted
3432 // to a small jump. If it is small enough, we will iterate in hopes of
3433 // converting those jumps we missed converting the first (or second...) time.
3435 #if defined(_TARGET_ARM_)
3436 UNATIVE_OFFSET minMediumExtra; // Same as 'minShortExtra', but for medium-sized jumps.
3437 #endif // _TARGET_ARM_
3439 UNATIVE_OFFSET adjIG;
3440 UNATIVE_OFFSET adjLJ;
3443 insGroup* prologIG = emitPrologIG;
3446 int jmp_iteration = 1;
3448 /*****************************************************************************/
3449 /* If we iterate to look for more jumps to shorten, we start again here. */
3450 /*****************************************************************************/
3455 emitCheckIGoffsets();
3459 In the following loop we convert all jump targets from "BasicBlock *"
3460 to "insGroup *" values. We also estimate which jumps will be short.
3464 insGroup* lastIG = nullptr;
3465 instrDescJmp* lastLJ = nullptr;
3471 minShortExtra = (UNATIVE_OFFSET)-1;
3473 #if defined(_TARGET_ARM_)
3474 minMediumExtra = (UNATIVE_OFFSET)-1;
3475 #endif // _TARGET_ARM_
3477 for (jmp = emitJumpList; jmp; jmp = jmp->idjNext)
3482 UNATIVE_OFFSET jsz; // size of the jump instruction in bytes
3484 UNATIVE_OFFSET ssz = 0; // small jump size
3485 NATIVE_OFFSET nsd = 0; // small jump max. neg distance
3486 NATIVE_OFFSET psd = 0; // small jump max. pos distance
3488 #if defined(_TARGET_ARM_)
3489 UNATIVE_OFFSET msz = 0; // medium jump size
3490 NATIVE_OFFSET nmd = 0; // medium jump max. neg distance
3491 NATIVE_OFFSET pmd = 0; // medium jump max. pos distance
3492 NATIVE_OFFSET mextra; // How far beyond the medium jump range is this jump offset?
3493 #endif // _TARGET_ARM_
3495 NATIVE_OFFSET extra; // How far beyond the short jump range is this jump offset?
3496 UNATIVE_OFFSET srcInstrOffs; // offset of the source instruction of the jump
3497 UNATIVE_OFFSET srcEncodingOffs; // offset of the source used by the instruction set to calculate the relative
3498 // offset of the jump
3499 UNATIVE_OFFSET dstOffs;
3500 NATIVE_OFFSET jmpDist; // the relative jump distance, as it will be encoded
3501 UNATIVE_OFFSET oldSize;
3502 UNATIVE_OFFSET sizeDif;
3504 #ifdef _TARGET_XARCH_
3505 assert(jmp->idInsFmt() == IF_LABEL || jmp->idInsFmt() == IF_RWR_LABEL || jmp->idInsFmt() == IF_SWR_LABEL);
3507 /* Figure out the smallest size we can end up with */
3509 if (jmp->idInsFmt() == IF_LABEL)
3511 if (emitIsCondJump(jmp))
3513 ssz = JCC_SIZE_SMALL;
3514 nsd = JCC_DIST_SMALL_MAX_NEG;
3515 psd = JCC_DIST_SMALL_MAX_POS;
3519 ssz = JMP_SIZE_SMALL;
3520 nsd = JMP_DIST_SMALL_MAX_NEG;
3521 psd = JMP_DIST_SMALL_MAX_POS;
3524 #endif // _TARGET_XARCH_
3527 assert((jmp->idInsFmt() == IF_T2_J1) || (jmp->idInsFmt() == IF_T2_J2) || (jmp->idInsFmt() == IF_T1_I) ||
3528 (jmp->idInsFmt() == IF_T1_K) || (jmp->idInsFmt() == IF_T1_M) || (jmp->idInsFmt() == IF_T2_M1) ||
3529 (jmp->idInsFmt() == IF_T2_N1) || (jmp->idInsFmt() == IF_T1_J3) || (jmp->idInsFmt() == IF_LARGEJMP));
3531 /* Figure out the smallest size we can end up with */
3533 if (emitIsCondJump(jmp))
3535 ssz = JCC_SIZE_SMALL;
3536 nsd = JCC_DIST_SMALL_MAX_NEG;
3537 psd = JCC_DIST_SMALL_MAX_POS;
3539 msz = JCC_SIZE_MEDIUM;
3540 nmd = JCC_DIST_MEDIUM_MAX_NEG;
3541 pmd = JCC_DIST_MEDIUM_MAX_POS;
3543 else if (emitIsCmpJump(jmp))
3545 ssz = JMP_SIZE_SMALL;
3549 else if (emitIsUncondJump(jmp))
3551 ssz = JMP_SIZE_SMALL;
3552 nsd = JMP_DIST_SMALL_MAX_NEG;
3553 psd = JMP_DIST_SMALL_MAX_POS;
3555 else if (emitIsLoadLabel(jmp))
3557 ssz = LBL_SIZE_SMALL;
3558 nsd = LBL_DIST_SMALL_MAX_NEG;
3559 psd = LBL_DIST_SMALL_MAX_POS;
3563 assert(!"Unknown jump instruction");
3565 #endif // _TARGET_ARM_
3567 #ifdef _TARGET_ARM64_
3568 /* Figure out the smallest size we can end up with */
3570 if (emitIsCondJump(jmp))
3572 ssz = JCC_SIZE_SMALL;
3573 bool isTest = (jmp->idIns() == INS_tbz) || (jmp->idIns() == INS_tbnz);
3575 nsd = (isTest) ? TB_DIST_SMALL_MAX_NEG : JCC_DIST_SMALL_MAX_NEG;
3576 psd = (isTest) ? TB_DIST_SMALL_MAX_POS : JCC_DIST_SMALL_MAX_POS;
3578 else if (emitIsUncondJump(jmp))
3580 // Nothing to do; we don't shrink these.
3581 assert(jmp->idjShort);
3582 ssz = JMP_SIZE_SMALL;
3584 else if (emitIsLoadLabel(jmp))
3586 ssz = LBL_SIZE_SMALL;
3587 nsd = LBL_DIST_SMALL_MAX_NEG;
3588 psd = LBL_DIST_SMALL_MAX_POS;
3590 else if (emitIsLoadConstant(jmp))
3592 ssz = LDC_SIZE_SMALL;
3593 nsd = LDC_DIST_SMALL_MAX_NEG;
3594 psd = LDC_DIST_SMALL_MAX_POS;
3598 assert(!"Unknown jump instruction");
3600 #endif // _TARGET_ARM64_
3602 /* Make sure the jumps are properly ordered */
3605 assert(lastLJ == nullptr || lastIG != jmp->idjIG || lastLJ->idjOffs < jmp->idjOffs);
3606 lastLJ = (lastIG == jmp->idjIG) ? jmp : nullptr;
3608 assert(lastIG == nullptr || lastIG->igNum <= jmp->idjIG->igNum || jmp->idjIG == prologIG ||
3609 emitNxtIGnum > unsigned(0xFFFF)); // igNum might overflow
3610 lastIG = jmp->idjIG;
3613 /* Get hold of the current jump size */
3615 jsz = emitSizeOfJump(jmp);
3617 /* Get the group the jump is in */
3621 /* Are we in a group different from the previous jump? */
3625 /* Were there any jumps before this one? */
3629 /* Adjust the offsets of the intervening blocks */
3633 lstIG = lstIG->igNext;
3635 // printf("Adjusted offset of block %02u from %04X to %04X\n", lstIG->igNum, lstIG->igOffs,
3636 // lstIG->igOffs - adjIG);
3637 lstIG->igOffs -= adjIG;
3638 assert(IsCodeAligned(lstIG->igOffs));
3639 } while (lstIG != jmpIG);
3642 /* We've got the first jump in a new group */
3648 /* Apply any local size adjustment to the jump's relative offset */
3650 jmp->idjOffs -= adjLJ;
3652 // If this is a jump via register, the instruction size does not change, so we are done.
3653 CLANG_FORMAT_COMMENT_ANCHOR;
3655 #if defined(_TARGET_ARM64_)
3656 // JIT code and data will be allocated together for arm64 so the relative offset to JIT data is known.
3657 // In case such offset can be encodeable for `ldr` (+-1MB), shorten it.
3658 if (jmp->idAddr()->iiaIsJitDataOffset())
3660 // Reference to JIT data
3661 assert(jmp->idIsBound());
3662 UNATIVE_OFFSET srcOffs = jmpIG->igOffs + jmp->idjOffs;
3664 int doff = jmp->idAddr()->iiaGetJitDataOffset();
3666 ssize_t imm = emitGetInsSC(jmp);
3667 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
3669 unsigned dataOffs = (unsigned)(doff + imm);
3670 assert(dataOffs < emitDataSize());
3672 // Conservately assume JIT data starts after the entire code size.
3673 // TODO-ARM64: we might consider only hot code size which will be computed later in emitComputeCodeSizes().
3674 assert(emitTotalCodeSize > 0);
3675 UNATIVE_OFFSET maxDstOffs = emitTotalCodeSize + dataOffs;
3677 // Check if the distance is within the encoding length.
3678 jmpDist = maxDstOffs - srcOffs;
3679 extra = jmpDist - psd;
3685 // Keep the large form.
3690 /* Have we bound this jump's target already? */
3692 if (jmp->idIsBound())
3694 /* Does the jump already have the smallest size? */
3698 assert(emitSizeOfJump(jmp) == ssz);
3700 // We should not be jumping/branching across funclets/functions
3701 emitCheckFuncletBranch(jmp, jmpIG);
3706 tgtIG = jmp->idAddr()->iiaIGlabel;
3710 /* First time we've seen this label, convert its target */
3711 CLANG_FORMAT_COMMENT_ANCHOR;
3716 printf("Binding: ");
3717 emitDispIns(jmp, false, false, false);
3718 printf("Binding L_M%03u_BB%02u ", Compiler::s_compMethodsCount, jmp->idAddr()->iiaBBlabel->bbNum);
3722 tgtIG = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel);
3729 printf("to G_M%03u_IG%02u\n", Compiler::s_compMethodsCount, tgtIG->igNum);
3733 printf("-- ERROR, no emitter cookie for BB%02u; it is probably missing BBF_JMP_TARGET or "
3735 jmp->idAddr()->iiaBBlabel->bbNum);
3741 /* Record the bound target */
3743 jmp->idAddr()->iiaIGlabel = tgtIG;
3744 jmp->idSetIsBound();
3747 // We should not be jumping/branching across funclets/functions
3748 emitCheckFuncletBranch(jmp, jmpIG);
3750 #ifdef _TARGET_XARCH_
3751 /* Done if this is not a variable-sized jump */
3753 if ((jmp->idIns() == INS_push) || (jmp->idIns() == INS_mov) || (jmp->idIns() == INS_call) ||
3754 (jmp->idIns() == INS_push_hide))
3760 if ((jmp->idIns() == INS_push) || (jmp->idIns() == INS_mov) || (jmp->idIns() == INS_movt) ||
3761 (jmp->idIns() == INS_movw))
3766 #ifdef _TARGET_ARM64_
3767 // There is only one size of unconditional branch; we don't support functions larger than 2^28 bytes (our branch
3769 if (emitIsUncondJump(jmp))
3776 In the following distance calculations, if we're not actually
3777 scheduling the code (i.e. reordering instructions), we can
3778 use the actual offset of the jump (rather than the beg/end of
3779 the instruction group) since the jump will not be moved around
3780 and thus its offset is accurate.
3782 First we need to figure out whether this jump is a forward or
3783 backward one; to do this we simply look at the ordinals of the
3784 group that contains the jump and the target.
3787 srcInstrOffs = jmpIG->igOffs + jmp->idjOffs;
3789 /* Note that the destination is always the beginning of an IG, so no need for an offset inside it */
3790 dstOffs = tgtIG->igOffs;
3792 #if defined(_TARGET_ARM_)
3794 srcInstrOffs + 4; // For relative branches, ARM PC is always considered to be the instruction address + 4
3795 #elif defined(_TARGET_ARM64_)
3797 srcInstrOffs; // For relative branches, ARM64 PC is always considered to be the instruction address
3799 srcEncodingOffs = srcInstrOffs + ssz; // Encoding offset of relative offset for small branch
3802 if (jmpIG->igNum < tgtIG->igNum)
3806 /* Adjust the target offset by the current delta. This is a worst-case estimate, as jumps between
3807 here and the target could be shortened, causing the actual distance to shrink.
3812 /* Compute the distance estimate */
3814 jmpDist = dstOffs - srcEncodingOffs;
3816 /* How much beyond the max. short distance does the jump go? */
3818 extra = jmpDist - psd;
3821 assert(jmp->idDebugOnlyInfo() != nullptr);
3822 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3824 if (INTERESTING_JUMP_NUM == 0)
3826 printf("[1] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3828 printf("[1] Jump block is at %08X\n", jmpIG->igOffs);
3829 printf("[1] Jump reloffset is %04X\n", jmp->idjOffs);
3830 printf("[1] Jump source is at %08X\n", srcEncodingOffs);
3831 printf("[1] Label block is at %08X\n", dstOffs);
3832 printf("[1] Jump dist. is %04X\n", jmpDist);
3835 printf("[1] Dist excess [S] = %d \n", extra);
3840 printf("Estimate of fwd jump [%08X/%03u]: %04X -> %04X = %04X\n", dspPtr(jmp),
3841 jmp->idDebugOnlyInfo()->idNum, srcInstrOffs, dstOffs, jmpDist);
3843 #endif // DEBUG_EMIT
3847 /* This jump will be a short one */
3855 /* Compute the distance estimate */
3857 jmpDist = srcEncodingOffs - dstOffs;
3859 /* How much beyond the max. short distance does the jump go? */
3861 extra = jmpDist + nsd;
3864 assert(jmp->idDebugOnlyInfo() != nullptr);
3865 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3867 if (INTERESTING_JUMP_NUM == 0)
3869 printf("[2] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3871 printf("[2] Jump block is at %08X\n", jmpIG->igOffs);
3872 printf("[2] Jump reloffset is %04X\n", jmp->idjOffs);
3873 printf("[2] Jump source is at %08X\n", srcEncodingOffs);
3874 printf("[2] Label block is at %08X\n", dstOffs);
3875 printf("[2] Jump dist. is %04X\n", jmpDist);
3878 printf("[2] Dist excess [S] = %d \n", extra);
3883 printf("Estimate of bwd jump [%08X/%03u]: %04X -> %04X = %04X\n", dspPtr(jmp),
3884 jmp->idDebugOnlyInfo()->idNum, srcInstrOffs, dstOffs, jmpDist);
3886 #endif // DEBUG_EMIT
3890 /* This jump will be a short one */
3895 /* We arrive here if the jump couldn't be made short, at least for now */
3897 /* We had better not have eagerly marked the jump as short
3898 * in emitIns_J(). If we did, then it has to be able to stay short
3899 * as emitIns_J() uses the worst case scenario, and blocks can
3900 * only move closer together after that.
3902 assert(jmp->idjShort == 0);
3904 /* Keep track of the closest distance we got */
3906 if (minShortExtra > (unsigned)extra)
3908 minShortExtra = (unsigned)extra;
3911 #if defined(_TARGET_ARM_)
3913 // If we're here, we couldn't convert to a small jump.
3914 // Handle conversion to medium-sized conditional jumps.
3915 // 'srcInstrOffs', 'srcEncodingOffs', 'dstOffs', 'jmpDist' have already been computed
3916 // and don't need to be recomputed.
3918 if (emitIsCondJump(jmp))
3920 if (jmpIG->igNum < tgtIG->igNum)
3924 /* How much beyond the max. medium distance does the jump go? */
3926 mextra = jmpDist - pmd;
3929 assert(jmp->idDebugOnlyInfo() != NULL);
3930 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3934 if (INTERESTING_JUMP_NUM == 0)
3935 printf("[6] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3936 printf("[6] Dist excess [S] = %d \n", mextra);
3939 #endif // DEBUG_EMIT
3943 /* This jump will be a medium one */
3951 /* How much beyond the max. medium distance does the jump go? */
3953 mextra = jmpDist + nmd;
3956 assert(jmp->idDebugOnlyInfo() != NULL);
3957 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3961 if (INTERESTING_JUMP_NUM == 0)
3962 printf("[7] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3963 printf("[7] Dist excess [S] = %d \n", mextra);
3966 #endif // DEBUG_EMIT
3970 /* This jump will be a medium one */
3975 /* We arrive here if the jump couldn't be made medium, at least for now */
3977 /* Keep track of the closest distance we got */
3979 if (minMediumExtra > (unsigned)mextra)
3980 minMediumExtra = (unsigned)mextra;
3983 #endif // _TARGET_ARM_
3985 /*****************************************************************************
3986 * We arrive here if the jump must stay long, at least for now.
3987 * Go try the next one.
3992 /*****************************************************************************/
3993 /* Handle conversion to short jump */
3994 /*****************************************************************************/
3998 /* Try to make this jump a short one */
4000 emitSetShortJump(jmp);
4004 continue; // This jump must be kept long
4007 /* This jump is becoming either short or medium */
4011 assert(oldSize >= jsz);
4012 sizeDif = oldSize - jsz;
4014 #if defined(_TARGET_XARCH_)
4015 jmp->idCodeSize(jsz);
4016 #elif defined(_TARGET_ARM_)
4018 // This is done as part of emitSetShortJump():
4019 insSize isz = emitInsSize(jmp->idInsFmt());
4020 jmp->idInsSize(isz);
4022 #elif defined(_TARGET_ARM64_)
4023 // The size of IF_LARGEJMP/IF_LARGEADR/IF_LARGELDC are 8 or 12.
4024 // All other code size is 4.
4025 assert((sizeDif == 4) || (sizeDif == 8));
4027 #error Unsupported or unset target architecture
4032 #if defined(_TARGET_ARM_)
4034 /*****************************************************************************/
4035 /* Handle conversion to medium jump */
4036 /*****************************************************************************/
4040 /* Try to make this jump a medium one */
4042 emitSetMediumJump(jmp);
4044 if (jmp->idCodeSize() > msz)
4046 continue; // This jump wasn't shortened
4048 assert(jmp->idCodeSize() == msz);
4050 /* This jump is becoming medium */
4054 assert(oldSize >= jsz);
4055 sizeDif = oldSize - jsz;
4059 #endif // _TARGET_ARM_
4061 /*****************************************************************************/
4065 /* Make sure the size of the jump is marked correctly */
4067 assert((0 == (jsz | jmpDist)) || (jsz == emitSizeOfJump(jmp)));
4072 printf("Shrinking jump [%08X/%03u]\n", dspPtr(jmp), jmp->idDebugOnlyInfo()->idNum);
4075 noway_assert((unsigned short)sizeDif == sizeDif);
4079 jmpIG->igSize -= (unsigned short)sizeDif;
4080 emitTotalCodeSize -= sizeDif;
4082 /* The jump size estimate wasn't accurate; flag its group */
4084 jmpIG->igFlags |= IGF_UPD_ISZ;
4086 } // end for each jump
4088 /* Did we shorten any jumps? */
4092 /* Adjust offsets of any remaining blocks */
4098 lstIG = lstIG->igNext;
4103 // printf("Adjusted offset of block %02u from %04X to %04X\n", lstIG->igNum, lstIG->igOffs,
4104 // lstIG->igOffs - adjIG);
4105 lstIG->igOffs -= adjIG;
4106 assert(IsCodeAligned(lstIG->igOffs));
4110 emitCheckIGoffsets();
4113 /* Is there a chance of other jumps becoming short? */
4114 CLANG_FORMAT_COMMENT_ANCHOR;
4116 #if defined(_TARGET_ARM_)
4118 printf("Total shrinkage = %3u, min extra short jump size = %3u, min extra medium jump size = %u\n", adjIG,
4119 minShortExtra, minMediumExtra);
4123 printf("Total shrinkage = %3u, min extra jump size = %3u\n", adjIG, minShortExtra);
4128 if ((minShortExtra <= adjIG)
4129 #if defined(_TARGET_ARM_)
4130 || (minMediumExtra <= adjIG)
4131 #endif // _TARGET_ARM_
4139 printf("Iterating branch shortening. Iteration = %d\n", jmp_iteration);
4148 void emitter::emitCheckFuncletBranch(instrDesc* jmp, insGroup* jmpIG)
4151 // We should not be jumping/branching across funclets/functions
4152 // Except possibly a 'call' to a finally funclet for a local unwind
4153 // or a 'return' from a catch handler (that can go just about anywhere)
4154 // This routine attempts to validate that any branches across funclets
4155 // meets one of those criteria...
4156 assert(jmp->idIsBound());
4158 #ifdef _TARGET_XARCH_
4159 // An lea of a code address (for constant data stored with the code)
4160 // is treated like a jump for emission purposes but is not really a jump so
4161 // we don't have to check anything here.
4162 if (jmp->idIns() == INS_lea)
4168 #ifdef _TARGET_ARMARCH_
4169 if (jmp->idAddr()->iiaHasInstrCount())
4171 // Too hard to figure out funclets from just an instruction count
4172 // You're on your own!
4175 #endif // _TARGET_ARMARCH_
4177 #ifdef _TARGET_ARM64_
4178 // No interest if it's not jmp.
4179 if (emitIsLoadLabel(jmp) || emitIsLoadConstant(jmp))
4183 #endif // _TARGET_ARM64_
4185 insGroup* tgtIG = jmp->idAddr()->iiaIGlabel;
4187 if (tgtIG->igFuncIdx != jmpIG->igFuncIdx)
4189 if (jmp->idDebugOnlyInfo()->idFinallyCall)
4191 // We don't record enough information to determine this accurately, so instead
4192 // we assume that any branch to the very start of a finally is OK.
4194 // No branches back to the root method
4195 assert(tgtIG->igFuncIdx > 0);
4196 FuncInfoDsc* tgtFunc = emitComp->funGetFunc(tgtIG->igFuncIdx);
4197 assert(tgtFunc->funKind == FUNC_HANDLER);
4198 EHblkDsc* tgtEH = emitComp->ehGetDsc(tgtFunc->funEHIndex);
4200 // Only branches to finallys (not faults, catches, filters, etc.)
4201 assert(tgtEH->HasFinallyHandler());
4203 // Only to the first block of the finally (which is properly marked)
4204 BasicBlock* tgtBlk = tgtEH->ebdHndBeg;
4205 assert(tgtBlk->bbFlags & BBF_FUNCLET_BEG);
4207 // And now we made it back to where we started
4208 assert(tgtIG == emitCodeGetCookie(tgtBlk));
4209 assert(tgtIG->igFuncIdx == emitComp->funGetFuncIdx(tgtBlk));
4211 else if (jmp->idDebugOnlyInfo()->idCatchRet)
4213 // Again there isn't enough information to prove this correct
4214 // so just allow a 'branch' to any other 'parent' funclet
4216 FuncInfoDsc* jmpFunc = emitComp->funGetFunc(jmpIG->igFuncIdx);
4217 assert(jmpFunc->funKind == FUNC_HANDLER);
4218 EHblkDsc* jmpEH = emitComp->ehGetDsc(jmpFunc->funEHIndex);
4220 // Only branches out of catches
4221 assert(jmpEH->HasCatchHandler());
4223 FuncInfoDsc* tgtFunc = emitComp->funGetFunc(tgtIG->igFuncIdx);
4225 if (tgtFunc->funKind == FUNC_HANDLER)
4227 // An outward chain to the containing funclet/EH handler
4228 // Note that it might be anywhere within nested try bodies
4229 assert(jmpEH->ebdEnclosingHndIndex == tgtFunc->funEHIndex);
4233 // This funclet is 'top level' and so it is branching back to the
4234 // root function, and should have no containing EH handlers
4235 // but it could be nested within try bodies...
4236 assert(tgtFunc->funKind == FUNC_ROOT);
4237 assert(jmpEH->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX);
4242 printf("Hit an illegal branch between funclets!");
4243 assert(tgtIG->igFuncIdx == jmpIG->igFuncIdx);
4249 /*****************************************************************************
4251 * Compute the code sizes that we're going to use to allocate the code buffers.
4255 * emitTotalHotCodeSize
4256 * emitTotalColdCodeSize
4257 * Compiler::info.compTotalHotCodeSize
4258 * Compiler::info.compTotalColdCodeSize
4261 void emitter::emitComputeCodeSizes()
4263 assert((emitComp->fgFirstColdBlock == nullptr) == (emitFirstColdIG == nullptr));
4265 if (emitFirstColdIG)
4267 emitTotalHotCodeSize = emitFirstColdIG->igOffs;
4268 emitTotalColdCodeSize = emitTotalCodeSize - emitTotalHotCodeSize;
4272 emitTotalHotCodeSize = emitTotalCodeSize;
4273 emitTotalColdCodeSize = 0;
4276 emitComp->info.compTotalHotCodeSize = emitTotalHotCodeSize;
4277 emitComp->info.compTotalColdCodeSize = emitTotalColdCodeSize;
4280 if (emitComp->verbose)
4282 printf("\nHot code size = 0x%X bytes\n", emitTotalHotCodeSize);
4283 printf("Cold code size = 0x%X bytes\n", emitTotalColdCodeSize);
4288 /*****************************************************************************
4290 * Called at the end of code generation, this method creates the code, data
4291 * and GC info blocks for the method. Returns the size of the method (which must fit in an unsigned).
4294 unsigned emitter::emitEndCodeGen(Compiler* comp,
4295 bool contTrkPtrLcls,
4299 unsigned xcptnsCount,
4300 unsigned* prologSize,
4301 unsigned* epilogSize,
4303 void** coldCodeAddr,
4307 if (emitComp->verbose)
4309 printf("*************** In emitEndCodeGen()\n");
4317 BYTE* coldCodeBlock;
4320 assert(emitCurIG == nullptr);
4322 emitCodeBlock = nullptr;
4323 emitConsBlock = nullptr;
4325 /* Tell everyone whether we have fully interruptible code or not */
4327 emitFullyInt = fullyInt;
4328 emitFullGCinfo = fullPtrMap;
4330 #ifndef UNIX_X86_ABI
4331 emitFullArgInfo = !emitHasFramePtr;
4333 emitFullArgInfo = fullPtrMap;
4337 GCrefsTable.record(emitGCrFrameOffsCnt);
4338 emitSizeTable.record(static_cast<unsigned>(emitSizeMethod));
4339 stkDepthTable.record(emitMaxStackDepth);
4340 #endif // EMITTER_STATS
4342 // Default values, correct even if EMIT_TRACK_STACK_DEPTH is 0.
4343 emitSimpleStkUsed = true;
4344 u1.emitSimpleStkMask = 0;
4345 u1.emitSimpleByrefStkMask = 0;
4347 #if EMIT_TRACK_STACK_DEPTH
4348 /* Convert max. stack depth from # of bytes to # of entries */
4350 unsigned maxStackDepthIn4ByteElements = emitMaxStackDepth / sizeof(int);
4351 JITDUMP("Converting emitMaxStackDepth from bytes (%d) to elements (%d)\n", emitMaxStackDepth,
4352 maxStackDepthIn4ByteElements);
4353 emitMaxStackDepth = maxStackDepthIn4ByteElements;
4355 /* Should we use the simple stack */
4357 if (emitMaxStackDepth > MAX_SIMPLE_STK_DEPTH || emitFullGCinfo)
4359 /* We won't use the "simple" argument table */
4361 emitSimpleStkUsed = false;
4363 /* Allocate the argument tracking table */
4365 if (emitMaxStackDepth <= sizeof(u2.emitArgTrackLcl))
4367 u2.emitArgTrackTab = (BYTE*)u2.emitArgTrackLcl;
4371 u2.emitArgTrackTab = (BYTE*)emitGetMem(roundUp(emitMaxStackDepth));
4374 u2.emitArgTrackTop = u2.emitArgTrackTab;
4375 u2.emitGcArgTrackCnt = 0;
4379 if (emitEpilogCnt == 0)
4381 /* No epilogs, make sure the epilog size is set to 0 */
4385 #ifdef _TARGET_XARCH_
4386 emitExitSeqSize = 0;
4387 #endif // _TARGET_XARCH_
4390 /* Return the size of the epilog to the caller */
4392 *epilogSize = emitEpilogSize;
4394 #ifdef _TARGET_XARCH_
4395 *epilogSize += emitExitSeqSize;
4396 #endif // _TARGET_XARCH_
4399 if (EMIT_INSTLIST_VERBOSE)
4401 printf("\nInstruction list before instruction issue:\n\n");
4402 emitDispIGlist(true);
4405 emitCheckIGoffsets();
4408 /* Allocate the code block (and optionally the data blocks) */
4410 // If we're doing procedure splitting and we found cold blocks, then
4411 // allocate hot and cold buffers. Otherwise only allocate a hot
4414 coldCodeBlock = nullptr;
4416 CorJitAllocMemFlag allocMemFlag = CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN;
4420 // These are the heuristics we use to decide whether or not to force the
4421 // code to be 16-byte aligned.
4423 // 1. For ngen code with IBC data, use 16-byte alignment if the method
4424 // has been called more than BB_VERY_HOT_WEIGHT times.
4425 // 2. For JITed code and ngen code without IBC data, use 16-byte alignment
4426 // when the code is 16 bytes or smaller. We align small getters/setters
4427 // because of they are penalized heavily on certain hardware when not 16-byte
4428 // aligned (VSWhidbey #373938). To minimize size impact of this optimization,
4429 // we do not align large methods because of the penalty is amortized for them.
4431 if (emitComp->fgHaveProfileData())
4433 if (emitComp->fgCalledCount > (BB_VERY_HOT_WEIGHT * emitComp->fgProfileRunsCount()))
4435 allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN;
4440 if (emitTotalHotCodeSize <= 16)
4442 allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN;
4447 #ifdef _TARGET_ARM64_
4448 // For arm64, we want to allocate JIT data always adjacent to code similar to what native compiler does.
4449 // This way allows us to use a single `ldr` to access such data like float constant/jmp table.
4450 if (emitTotalColdCodeSize > 0)
4452 // JIT data might be far away from the cold code.
4453 NYI_ARM64("Need to handle fix-up to data from cold code.");
4456 UNATIVE_OFFSET roDataAlignmentDelta = 0;
4457 if (emitConsDsc.dsdOffs)
4459 UNATIVE_OFFSET roDataAlignment = TARGET_POINTER_SIZE; // 8 Byte align by default.
4460 roDataAlignmentDelta = (UNATIVE_OFFSET)ALIGN_UP(emitTotalHotCodeSize, roDataAlignment) - emitTotalHotCodeSize;
4461 assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4));
4463 emitCmpHandle->allocMem(emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs, emitTotalColdCodeSize, 0,
4464 xcptnsCount, allocMemFlag, (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock);
4466 consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta;
4469 emitCmpHandle->allocMem(emitTotalHotCodeSize, emitTotalColdCodeSize, emitConsDsc.dsdOffs, xcptnsCount, allocMemFlag,
4470 (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock);
4473 // if (emitConsDsc.dsdOffs)
4474 // printf("Cons=%08X\n", consBlock);
4476 /* Give the block addresses to the caller and other functions here */
4478 *codeAddr = emitCodeBlock = codeBlock;
4479 *coldCodeAddr = emitColdCodeBlock = coldCodeBlock;
4480 *consAddr = emitConsBlock = consBlock;
4482 /* Nothing has been pushed on the stack */
4483 CLANG_FORMAT_COMMENT_ANCHOR;
4485 #if EMIT_TRACK_STACK_DEPTH
4486 emitCurStackLvl = 0;
4489 /* Assume no live GC ref variables on entry */
4491 VarSetOps::ClearD(emitComp, emitThisGCrefVars); // This is initialized to Empty at the start of codegen.
4492 emitThisGCrefRegs = emitThisByrefRegs = RBM_NONE;
4493 emitThisGCrefVset = true;
4499 // We don't use these after this point
4501 VarSetOps::AssignNoCopy(emitComp, emitPrevGCrefVars, VarSetOps::UninitVal());
4502 emitPrevGCrefRegs = emitPrevByrefRegs = 0xBAADFEED;
4504 VarSetOps::AssignNoCopy(emitComp, emitInitGCrefVars, VarSetOps::UninitVal());
4505 emitInitGCrefRegs = emitInitByrefRegs = 0xBAADFEED;
4509 /* Initialize the GC ref variable lifetime tracking logic */
4511 codeGen->gcInfo.gcVarPtrSetInit();
4513 emitSyncThisObjOffs = -1; /* -1 means no offset set */
4514 emitSyncThisObjReg = REG_NA; /* REG_NA means not set */
4516 #ifdef JIT32_GCENCODER
4517 if (emitComp->lvaKeepAliveAndReportThis())
4519 assert(emitComp->lvaIsOriginalThisArg(0));
4520 LclVarDsc* thisDsc = &emitComp->lvaTable[0];
4522 /* If "this" (which is passed in as a register argument in REG_ARG_0)
4523 is enregistered, we normally spot the "mov REG_ARG_0 -> thisReg"
4524 in the prolog and note the location of "this" at that point.
4525 However, if 'this' is enregistered into REG_ARG_0 itself, no code
4526 will be generated in the prolog, so we explicitly need to note
4527 the location of "this" here.
4528 NOTE that we can do this even if "this" is not enregistered in
4529 REG_ARG_0, and it will result in more accurate "this" info over the
4530 prolog. However, as methods are not interruptible over the prolog,
4531 we try to save space by avoiding that.
4534 if (thisDsc->lvRegister)
4536 emitSyncThisObjReg = thisDsc->lvRegNum;
4538 if (emitSyncThisObjReg == (int)REG_ARG_0 &&
4539 (codeGen->intRegState.rsCalleeRegArgMaskLiveIn & genRegMask(REG_ARG_0)))
4543 emitGCregLiveSet(GCT_GCREF, genRegMask(REG_ARG_0),
4544 emitCodeBlock, // from offset 0
4549 /* If emitFullGCinfo==false, the we don't use any
4550 regPtrDsc's and so explictly note the location
4551 of "this" in GCEncode.cpp
4557 #endif // JIT32_GCENCODER
4559 emitContTrkPtrLcls = contTrkPtrLcls;
4561 /* Are there any GC ref variables on the stack? */
4563 if (emitGCrFrameOffsCnt)
4571 /* Allocate and clear emitGCrFrameLiveTab[]. This is the table
4572 mapping "stkOffs -> varPtrDsc". It holds a pointer to
4573 the liveness descriptor that was created when the
4574 variable became alive. When the variable becomes dead, the
4575 descriptor will be appended to the liveness descriptor list, and
4576 the entry in emitGCrFrameLiveTab[] will be made NULL.
4578 Note that if all GC refs are assigned consecutively,
4579 emitGCrFrameLiveTab[] can be only as big as the number of GC refs
4580 present, instead of lvaTrackedCount.
4583 siz = emitGCrFrameOffsCnt * sizeof(*emitGCrFrameLiveTab);
4584 emitGCrFrameLiveTab = (varPtrDsc**)emitGetMem(roundUp(siz));
4585 memset(emitGCrFrameLiveTab, 0, siz);
4587 /* Allocate and fill in emitGCrFrameOffsTab[]. This is the table
4588 mapping "varIndex -> stkOffs".
4589 Non-ptrs or reg vars have entries of -1.
4590 Entries of Tracked stack byrefs have the lower bit set to 1.
4593 emitTrkVarCnt = cnt = emitComp->lvaTrackedCount;
4595 emitGCrFrameOffsTab = tab = (int*)emitGetMem(cnt * sizeof(int));
4597 memset(emitGCrFrameOffsTab, -1, cnt * sizeof(int));
4599 /* Now fill in all the actual used entries */
4601 for (num = 0, dsc = emitComp->lvaTable, cnt = emitComp->lvaCount; num < cnt; num++, dsc++)
4603 if (!dsc->lvOnFrame || (dsc->lvIsParam && !dsc->lvIsRegArg))
4608 #if FEATURE_FIXED_OUT_ARGS
4609 if (num == emitComp->lvaOutgoingArgSpaceVar)
4613 #endif // FEATURE_FIXED_OUT_ARGS
4615 int offs = dsc->lvStkOffs;
4617 /* Is it within the interesting range of offsets */
4619 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
4621 /* Are tracked stack ptr locals laid out contiguously?
4622 If not, skip non-ptrs. The emitter is optimized to work
4623 with contiguous ptrs, but for EditNContinue, the variables
4624 are laid out in the order they occur in the local-sig.
4627 if (!emitContTrkPtrLcls)
4629 if (!emitComp->lvaIsGCTracked(dsc))
4635 unsigned indx = dsc->lvVarIndex;
4637 assert(!dsc->lvRegister);
4638 assert(dsc->lvTracked);
4639 assert(dsc->lvRefCnt != 0);
4641 assert(dsc->TypeGet() == TYP_REF || dsc->TypeGet() == TYP_BYREF);
4643 assert(indx < emitComp->lvaTrackedCount);
4645 // printf("Variable #%2u/%2u is at stack offset %d\n", num, indx, offs);
4647 #ifdef JIT32_GCENCODER
4648 #ifndef WIN64EXCEPTIONS
4649 /* Remember the frame offset of the "this" argument for synchronized methods */
4650 if (emitComp->lvaIsOriginalThisArg(num) && emitComp->lvaKeepAliveAndReportThis())
4652 emitSyncThisObjOffs = offs;
4653 offs |= this_OFFSET_FLAG;
4656 #endif // JIT32_GCENCODER
4658 if (dsc->TypeGet() == TYP_BYREF)
4660 offs |= byref_OFFSET_FLAG;
4670 emitGCrFrameOffsTab = nullptr;
4675 if (emitComp->verbose)
4677 printf("\n***************************************************************************\n");
4678 printf("Instructions as they come out of the scheduler\n\n");
4682 /* Issue all instruction groups in order */
4685 #define DEFAULT_CODE_BUFFER_INIT 0xcc
4687 for (ig = emitIGlist; ig; ig = ig->igNext)
4689 assert(!(ig->igFlags & IGF_PLACEHOLDER)); // There better not be any placeholder groups left
4691 /* Is this the first cold block? */
4692 if (ig == emitFirstColdIG)
4694 unsigned actualHotCodeSize = emitCurCodeOffs(cp);
4696 /* Fill in eventual unused space */
4697 while (emitCurCodeOffs(cp) < emitTotalHotCodeSize)
4699 *cp++ = DEFAULT_CODE_BUFFER_INIT;
4702 assert(coldCodeBlock);
4705 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
4707 printf("\n************** Beginning of cold code **************\n");
4712 /* Are we overflowing? */
4713 if (ig->igNext && ig->igNum + 1 != ig->igNext->igNum)
4715 NO_WAY("Too many instruction groups");
4718 // If this instruction group is returned to from a funclet implementing a finally,
4719 // on architectures where it is necessary generate GC info for the current instruction as
4720 // if it were the instruction following a call.
4721 emitGenGCInfoIfFuncletRetTarget(ig, cp);
4723 instrDesc* id = (instrDesc*)ig->igData;
4727 /* Print the IG label, but only if it is a branch label */
4729 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
4731 if (emitComp->verbose)
4734 emitDispIG(ig); // Display the flags, IG data, etc.
4738 printf("\nG_M%03u_IG%02u:\n", Compiler::s_compMethodsCount, ig->igNum);
4746 /* Record the actual offset of the block, noting the difference */
4748 emitOffsAdj = ig->igOffs - emitCurCodeOffs(cp);
4749 assert(emitOffsAdj >= 0);
4752 if ((emitOffsAdj != 0) && emitComp->verbose)
4754 printf("Block predicted offs = %08X, actual = %08X -> size adj = %d\n", ig->igOffs, emitCurCodeOffs(cp),
4757 #endif // DEBUG_EMIT
4759 ig->igOffs = emitCurCodeOffs(cp);
4760 assert(IsCodeAligned(ig->igOffs));
4762 #if EMIT_TRACK_STACK_DEPTH
4764 /* Set the proper stack level if appropriate */
4766 if (ig->igStkLvl != emitCurStackLvl)
4768 /* We are pushing stuff implicitly at this label */
4770 assert((unsigned)ig->igStkLvl > (unsigned)emitCurStackLvl);
4771 emitStackPushN(cp, (ig->igStkLvl - (unsigned)emitCurStackLvl) / sizeof(int));
4776 /* Update current GC information for non-overflow IG (not added implicitly by the emitter) */
4778 if (!(ig->igFlags & IGF_EMIT_ADD))
4780 /* Is there a new set of live GC ref variables? */
4782 if (ig->igFlags & IGF_GC_VARS)
4784 emitUpdateLiveGCvars(ig->igGCvars(), cp);
4786 else if (!emitThisGCrefVset)
4788 emitUpdateLiveGCvars(emitThisGCrefVars, cp);
4791 /* Update the set of live GC ref registers */
4794 regMaskTP GCregs = ig->igGCregs;
4796 if (GCregs != emitThisGCrefRegs)
4798 emitUpdateLiveGCregs(GCT_GCREF, GCregs, cp);
4802 /* Is there a new set of live byref registers? */
4804 if (ig->igFlags & IGF_BYREF_REGS)
4806 unsigned byrefRegs = ig->igByrefRegs();
4808 if (byrefRegs != emitThisByrefRegs)
4810 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, cp);
4816 // These are not set for "overflow" groups
4817 assert(!(ig->igFlags & IGF_GC_VARS));
4818 assert(!(ig->igFlags & IGF_BYREF_REGS));
4821 /* Issue each instruction in order */
4825 for (unsigned cnt = ig->igInsCnt; cnt; cnt--)
4827 castto(id, BYTE*) += emitIssue1Instr(ig, id, &cp);
4830 emitCurIG = nullptr;
4832 assert(ig->igSize >= cp - bp);
4833 ig->igSize = (unsigned short)(cp - bp);
4836 #if EMIT_TRACK_STACK_DEPTH
4837 assert(emitCurStackLvl == 0);
4840 /* Output any initialized data we may have */
4842 if (emitConsDsc.dsdOffs)
4844 emitOutputDataSec(&emitConsDsc, consBlock);
4847 /* Make sure all GC ref variables are marked as dead */
4849 if (emitGCrFrameOffsCnt)
4855 for (vn = 0, of = emitGCrFrameOffsMin, dp = emitGCrFrameLiveTab; vn < emitGCrFrameOffsCnt;
4856 vn++, of += TARGET_POINTER_SIZE, dp++)
4860 emitGCvarDeadSet(of, cp, vn);
4865 /* No GC registers are live any more */
4867 if (emitThisByrefRegs)
4869 emitUpdateLiveGCregs(GCT_BYREF, RBM_NONE, cp);
4871 if (emitThisGCrefRegs)
4873 emitUpdateLiveGCregs(GCT_GCREF, RBM_NONE, cp);
4876 /* Patch any forward jumps */
4882 for (jmp = emitJumpList; jmp; jmp = jmp->idjNext)
4885 #ifdef _TARGET_XARCH_
4886 assert(jmp->idInsFmt() == IF_LABEL || jmp->idInsFmt() == IF_RWR_LABEL || jmp->idInsFmt() == IF_SWR_LABEL);
4888 tgt = jmp->idAddr()->iiaIGlabel;
4890 if (jmp->idjTemp.idjAddr == nullptr)
4895 if (jmp->idjOffs != tgt->igOffs)
4897 BYTE* adr = jmp->idjTemp.idjAddr;
4898 int adj = jmp->idjOffs - tgt->igOffs;
4900 // On Arm, the offset is encoded in unit of 2 bytes.
4905 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4908 printf("[5] This output is broken for ARM, since it doesn't properly decode the jump offsets of "
4909 "the instruction at adr\n");
4912 if (INTERESTING_JUMP_NUM == 0)
4914 printf("[5] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
4919 printf("[5] Jump is at %08X\n", (adr + 1 - emitCodeBlock));
4920 printf("[5] Jump distance is %02X - %02X = %02X\n", *(BYTE*)adr, adj, *(BYTE*)adr - adj);
4924 printf("[5] Jump is at %08X\n", (adr + 4 - emitCodeBlock));
4925 printf("[5] Jump distance is %08X - %02X = %08X\n", *(int*)adr, adj, *(int*)adr - adj);
4928 #endif // DEBUG_EMIT
4932 // Patch Forward Short Jump
4933 CLANG_FORMAT_COMMENT_ANCHOR;
4934 #if defined(_TARGET_XARCH_)
4935 *(BYTE*)adr -= (BYTE)adj;
4936 #elif defined(_TARGET_ARM_)
4937 // The following works because the jump offset is in the low order bits of the instruction.
4938 // Presumably we could also just call "emitOutputLJ(NULL, adr, jmp)", like for long jumps?
4939 *(short int*)adr -= (short)adj;
4940 #elif defined(_TARGET_ARM64_)
4941 assert(!jmp->idAddr()->iiaHasInstrCount());
4942 emitOutputLJ(NULL, adr, jmp);
4944 #error Unsupported or unset target architecture
4949 // Patch Forward non-Short Jump
4950 CLANG_FORMAT_COMMENT_ANCHOR;
4951 #if defined(_TARGET_XARCH_)
4953 #elif defined(_TARGET_ARMARCH_)
4954 assert(!jmp->idAddr()->iiaHasInstrCount());
4955 emitOutputLJ(NULL, adr, jmp);
4957 #error Unsupported or unset target architecture
4965 if (emitComp->opts.disAsm)
4970 if (emitComp->verbose)
4972 printf("Allocated method code size = %4u , actual size = %4u\n", emitTotalCodeSize, cp - codeBlock);
4976 unsigned actualCodeSize = emitCurCodeOffs(cp);
4978 /* Fill in eventual unused space */
4979 while (emitCurCodeOffs(cp) < emitTotalCodeSize)
4981 *cp++ = DEFAULT_CODE_BUFFER_INIT;
4985 totAllocdSize += emitTotalCodeSize;
4986 totActualSize += actualCodeSize;
4991 // Make sure these didn't change during the "issuing" phase
4993 assert(VarSetOps::MayBeUninit(emitPrevGCrefVars));
4994 assert(emitPrevGCrefRegs == 0xBAADFEED);
4995 assert(emitPrevByrefRegs == 0xBAADFEED);
4997 assert(VarSetOps::MayBeUninit(emitInitGCrefVars));
4998 assert(emitInitGCrefRegs == 0xBAADFEED);
4999 assert(emitInitByrefRegs == 0xBAADFEED);
5003 // Assign the real prolog size
5004 *prologSize = emitCodeOffset(emitPrologIG, emitPrologEndPos);
5006 /* Return the amount of code we've generated */
5008 return actualCodeSize;
5011 // See specification comment at the declaration.
5012 void emitter::emitGenGCInfoIfFuncletRetTarget(insGroup* ig, BYTE* cp)
5014 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
5015 // We only emit this GC information on targets where finally's are implemented via funclets,
5016 // and the finally is invoked, during non-exceptional execution, via a branch with a predefined
5017 // link register, rather than a "true call" for which we would already generate GC info. Currently,
5018 // this means precisely ARM.
5019 if (ig->igFlags & IGF_FINALLY_TARGET)
5021 // We don't actually have a call instruction in this case, so we don't have
5022 // a real size for that instruction. We'll use 1.
5023 emitStackPop(cp, /*isCall*/ true, /*callInstrSize*/ 1, /*args*/ 0);
5025 /* Do we need to record a call location for GC purposes? */
5026 if (!emitFullGCinfo)
5028 emitRecordGCcall(cp, /*callInstrSize*/ 1);
5031 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
5034 /*****************************************************************************
5036 * We have an instruction in an insGroup and we need to know the
5037 * instruction number for this instruction
5040 unsigned emitter::emitFindInsNum(insGroup* ig, instrDesc* idMatch)
5042 instrDesc* id = (instrDesc*)ig->igData;
5044 // Check if we are the first instruction in the group
5050 /* Walk the list of instructions until we find a match */
5051 unsigned insNum = 0;
5052 unsigned insRemaining = ig->igInsCnt;
5054 while (insRemaining > 0)
5056 castto(id, BYTE*) += emitSizeOfInsDsc(id);
5065 assert(!"emitFindInsNum failed");
5069 /*****************************************************************************
5071 * We've been asked for the code offset of an instruction but alas one or
5072 * more instruction sizes in the block have been mis-predicted, so we have
5073 * to find the true offset by looking for the instruction within the group.
5076 UNATIVE_OFFSET emitter::emitFindOffset(insGroup* ig, unsigned insNum)
5078 instrDesc* id = (instrDesc*)ig->igData;
5079 UNATIVE_OFFSET of = 0;
5082 /* Make sure we were passed reasonable arguments */
5083 assert(ig && ig->igSelf == ig);
5084 assert(ig->igInsCnt >= insNum);
5087 /* Walk the instruction list until all are counted */
5091 of += emitInstCodeSz(id);
5093 castto(id, BYTE*) += emitSizeOfInsDsc(id);
5101 /*****************************************************************************
5103 * Start generating a constant data section for the current
5104 * function. Returns the offset of the section in the appropriate data
5108 UNATIVE_OFFSET emitter::emitDataGenBeg(UNATIVE_OFFSET size, bool dblAlign, bool codeLtab)
5111 dataSection* secDesc;
5113 assert(emitDataSecCur == nullptr);
5115 /* The size better not be some kind of an odd thing */
5117 assert(size && size % sizeof(int) == 0);
5119 /* Get hold of the current offset */
5121 secOffs = emitConsDsc.dsdOffs;
5123 /* Are we require to align this request on an eight byte boundry? */
5124 if (dblAlign && (secOffs % sizeof(double) != 0))
5126 /* Need to skip 4 bytes to honor dblAlign */
5127 /* Must allocate a dummy 4 byte integer */
5129 emitDataGenBeg(4, false, false);
5130 emitDataGenData(0, &zero, 4);
5133 /* Get the new secOffs */
5134 secOffs = emitConsDsc.dsdOffs;
5135 /* Now it should be a multiple of 8 */
5136 assert(secOffs % sizeof(double) == 0);
5139 /* Advance the current offset */
5141 emitConsDsc.dsdOffs += size;
5143 /* Allocate a data section descriptor and add it to the list */
5145 secDesc = emitDataSecCur = (dataSection*)emitGetMem(roundUp(sizeof(*secDesc) + size));
5147 secDesc->dsSize = size;
5149 secDesc->dsType = dataSection::data;
5151 secDesc->dsNext = nullptr;
5153 if (emitConsDsc.dsdLast)
5155 emitConsDsc.dsdLast->dsNext = secDesc;
5159 emitConsDsc.dsdList = secDesc;
5161 emitConsDsc.dsdLast = secDesc;
5166 // Start generating a constant data section for the current function
5167 // populated with BasicBlock references.
5168 // You can choose the references to be either absolute pointers, or
5169 // 4-byte relative addresses.
5170 // Currently the relative references are relative to the start of the
5171 // first block (this is somewhat arbitrary)
5173 UNATIVE_OFFSET emitter::emitBBTableDataGenBeg(unsigned numEntries, bool relativeAddr)
5176 dataSection* secDesc;
5178 assert(emitDataSecCur == nullptr);
5180 UNATIVE_OFFSET emittedSize;
5184 emittedSize = numEntries * 4;
5188 emittedSize = numEntries * TARGET_POINTER_SIZE;
5191 /* Get hold of the current offset */
5193 secOffs = emitConsDsc.dsdOffs;
5195 /* Advance the current offset */
5197 emitConsDsc.dsdOffs += emittedSize;
5199 /* Allocate a data section descriptor and add it to the list */
5201 secDesc = emitDataSecCur = (dataSection*)emitGetMem(roundUp(sizeof(*secDesc) + numEntries * sizeof(BasicBlock*)));
5203 secDesc->dsSize = emittedSize;
5205 secDesc->dsType = relativeAddr ? dataSection::blockRelative32 : dataSection::blockAbsoluteAddr;
5207 secDesc->dsNext = nullptr;
5209 if (emitConsDsc.dsdLast)
5211 emitConsDsc.dsdLast->dsNext = secDesc;
5215 emitConsDsc.dsdList = secDesc;
5218 emitConsDsc.dsdLast = secDesc;
5223 /*****************************************************************************
5225 * Emit the given block of bits into the current data section.
5228 void emitter::emitDataGenData(unsigned offs, const void* data, size_t size)
5230 assert(emitDataSecCur && (emitDataSecCur->dsSize >= offs + size));
5232 assert(emitDataSecCur->dsType == dataSection::data);
5234 memcpy(emitDataSecCur->dsCont + offs, data, size);
5237 /*****************************************************************************
5239 * Emit the address of the given basic block into the current data section.
5242 void emitter::emitDataGenData(unsigned index, BasicBlock* label)
5244 assert(emitDataSecCur != nullptr);
5245 assert(emitDataSecCur->dsType == dataSection::blockAbsoluteAddr ||
5246 emitDataSecCur->dsType == dataSection::blockRelative32);
5248 unsigned emittedElemSize = emitDataSecCur->dsType == dataSection::blockAbsoluteAddr ? TARGET_POINTER_SIZE : 4;
5250 assert(emitDataSecCur->dsSize >= emittedElemSize * (index + 1));
5252 ((BasicBlock**)(emitDataSecCur->dsCont))[index] = label;
5255 /*****************************************************************************
5257 * We're done generating a data section.
5260 void emitter::emitDataGenEnd()
5264 assert(emitDataSecCur);
5265 emitDataSecCur = nullptr;
5269 /********************************************************************************
5270 * Generates a data section constant
5273 * cnsAddr - memory location containing constant value
5274 * cnsSize - size of constant in bytes
5275 * dblAlign - whether to double align the data section constant
5277 * Returns constant number as offset into data section.
5279 UNATIVE_OFFSET emitter::emitDataConst(const void* cnsAddr, unsigned cnsSize, bool dblAlign)
5281 // When generating SMALL_CODE, we don't bother with dblAlign
5282 if (dblAlign && (emitComp->compCodeOpt() == Compiler::SMALL_CODE))
5287 UNATIVE_OFFSET cnum = emitDataGenBeg(cnsSize, dblAlign, false);
5288 emitDataGenData(0, cnsAddr, cnsSize);
5294 //------------------------------------------------------------------------
5295 // emitAnyConst: Create a data section constant of arbitrary size.
5298 // cnsAddr - pointer to the data to be placed in the data section
5299 // cnsSize - size of the data
5300 // dblAlign - whether to align the data section to an 8 byte boundary
5303 // A field handle representing the data offset to access the constant.
5305 CORINFO_FIELD_HANDLE emitter::emitAnyConst(const void* cnsAddr, unsigned cnsSize, bool dblAlign)
5307 UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
5308 return emitComp->eeFindJitDataOffs(cnum);
5311 //------------------------------------------------------------------------
5312 // emitFltOrDblConst: Create a float or double data section constant.
5315 // constValue - constant value
5316 // attr - constant size
5319 // A field handle representing the data offset to access the constant.
5322 // If attr is EA_4BYTE then the double value is converted to a float value.
5323 // If attr is EA_8BYTE then 8 byte alignment is automatically requested.
5325 CORINFO_FIELD_HANDLE emitter::emitFltOrDblConst(double constValue, emitAttr attr)
5327 assert((attr == EA_4BYTE) || (attr == EA_8BYTE));
5333 if (attr == EA_4BYTE)
5335 f = forceCastToFloat(constValue);
5341 cnsAddr = &constValue;
5345 // Access to inline data is 'abstracted' by a special type of static member
5346 // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
5347 // to constant data, not a real static field.
5349 UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
5350 UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
5351 return emitComp->eeFindJitDataOffs(cnum);
5354 /*****************************************************************************
5356 * Output the given data section at the specified address.
5359 void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst)
5364 printf("\nEmitting data sections: %u total bytes\n", sec->dsdOffs);
5367 unsigned secNum = 0;
5371 assert(sec->dsdOffs);
5372 assert(sec->dsdList);
5374 /* Walk and emit the contents of all the data blocks */
5378 for (dsc = sec->dsdList; dsc; dsc = dsc->dsNext)
5380 size_t dscSize = dsc->dsSize;
5382 // absolute label table
5383 if (dsc->dsType == dataSection::blockAbsoluteAddr)
5385 JITDUMP(" section %u, size %u, block absolute addr\n", secNum++, dscSize);
5387 assert(dscSize && dscSize % TARGET_POINTER_SIZE == 0);
5388 size_t numElems = dscSize / TARGET_POINTER_SIZE;
5389 target_size_t* bDst = (target_size_t*)dst;
5390 for (unsigned i = 0; i < numElems; i++)
5392 BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i];
5394 // Convert the BasicBlock* value to an IG address
5395 insGroup* lab = (insGroup*)emitCodeGetCookie(block);
5397 // Append the appropriate address to the destination
5398 BYTE* target = emitOffsetToPtr(lab->igOffs);
5401 target = (BYTE*)((size_t)target | 1); // Or in thumb bit
5403 bDst[i] = (target_size_t)target;
5404 if (emitComp->opts.compReloc)
5406 emitRecordRelocation(&(bDst[i]), target, IMAGE_REL_BASED_HIGHLOW);
5409 JITDUMP(" BB%02u: 0x%p\n", block->bbNum, bDst[i]);
5412 // relative label table
5413 else if (dsc->dsType == dataSection::blockRelative32)
5415 JITDUMP(" section %u, size %u, block relative addr\n", secNum++, dscSize);
5417 unsigned elemSize = 4;
5418 size_t numElems = dscSize / 4;
5419 unsigned* uDst = (unsigned*)dst;
5420 insGroup* labFirst = (insGroup*)emitCodeGetCookie(emitComp->fgFirstBB);
5422 for (unsigned i = 0; i < numElems; i++)
5424 BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i];
5426 // Convert the BasicBlock* value to an IG address
5427 insGroup* lab = (insGroup*)emitCodeGetCookie(block);
5429 assert(FitsIn<uint32_t>(lab->igOffs - labFirst->igOffs));
5430 uDst[i] = lab->igOffs - labFirst->igOffs;
5432 JITDUMP(" BB%02u: 0x%x\n", block->bbNum, uDst[i]);
5437 JITDUMP(" section %u, size %u, raw data\n", secNum++, dscSize);
5439 // Simple binary data: copy the bytes to the target
5440 assert(dsc->dsType == dataSection::data);
5442 memcpy(dst, dsc->dsCont, dscSize);
5448 for (size_t i = 0; i < dscSize; i++)
5450 printf("%02x ", dsc->dsCont[i]);
5451 if ((((i + 1) % 16) == 0) && (i + 1 != dscSize))
5464 /*****************************************************************************/
5465 /*****************************************************************************
5467 * Record the fact that the given variable now contains a live GC ref.
5470 void emitter::emitGCvarLiveSet(int offs, GCtype gcType, BYTE* addr, ssize_t disp)
5472 assert(emitIssuing);
5476 assert((abs(offs) % TARGET_POINTER_SIZE) == 0);
5477 assert(needsGC(gcType));
5479 /* Compute the index into the GC frame table if the caller didn't do it */
5483 disp = (offs - emitGCrFrameOffsMin) / TARGET_POINTER_SIZE;
5486 assert((size_t)disp < emitGCrFrameOffsCnt);
5488 /* Allocate a lifetime record */
5490 desc = new (emitComp, CMK_GC) varPtrDsc;
5492 desc->vpdBegOfs = emitCurCodeOffs(addr);
5494 desc->vpdEndOfs = 0xFACEDEAD;
5497 desc->vpdVarNum = offs;
5499 desc->vpdNext = nullptr;
5501 #if !defined(JIT32_GCENCODER) || !defined(WIN64EXCEPTIONS)
5502 /* the lower 2 bits encode props about the stk ptr */
5504 if (offs == emitSyncThisObjOffs)
5506 desc->vpdVarNum |= this_OFFSET_FLAG;
5510 if (gcType == GCT_BYREF)
5512 desc->vpdVarNum |= byref_OFFSET_FLAG;
5515 /* Append the new entry to the end of the list */
5516 if (codeGen->gcInfo.gcVarPtrLast == nullptr)
5518 assert(codeGen->gcInfo.gcVarPtrList == nullptr);
5519 codeGen->gcInfo.gcVarPtrList = codeGen->gcInfo.gcVarPtrLast = desc;
5523 assert(codeGen->gcInfo.gcVarPtrList != nullptr);
5524 codeGen->gcInfo.gcVarPtrLast->vpdNext = desc;
5525 codeGen->gcInfo.gcVarPtrLast = desc;
5528 /* Record the variable descriptor in the table */
5530 assert(emitGCrFrameLiveTab[disp] == nullptr);
5531 emitGCrFrameLiveTab[disp] = desc;
5536 printf("[%08X] %s var born at [%s", dspPtr(desc), GCtypeStr(gcType), emitGetFrameReg());
5540 printf("-%02XH", -offs);
5544 printf("+%02XH", +offs);
5551 /* The "global" live GC variable mask is no longer up-to-date */
5553 emitThisGCrefVset = false;
5556 /*****************************************************************************
5558 * Record the fact that the given variable no longer contains a live GC ref.
5561 void emitter::emitGCvarDeadSet(int offs, BYTE* addr, ssize_t disp)
5563 assert(emitIssuing);
5567 assert(abs(offs) % sizeof(int) == 0);
5569 /* Compute the index into the GC frame table if the caller didn't do it */
5573 disp = (offs - emitGCrFrameOffsMin) / TARGET_POINTER_SIZE;
5576 assert((unsigned)disp < emitGCrFrameOffsCnt);
5578 /* Get hold of the lifetime descriptor and clear the entry */
5580 desc = emitGCrFrameLiveTab[disp];
5581 emitGCrFrameLiveTab[disp] = nullptr;
5584 assert((desc->vpdVarNum & ~OFFSET_MASK) == (unsigned)offs);
5586 /* Record the death code offset */
5588 assert(desc->vpdEndOfs == 0xFACEDEAD);
5589 desc->vpdEndOfs = emitCurCodeOffs(addr);
5594 GCtype gcType = (desc->vpdVarNum & byref_OFFSET_FLAG) ? GCT_BYREF : GCT_GCREF;
5595 #if !defined(JIT32_GCENCODER) || !defined(WIN64EXCEPTIONS)
5596 bool isThis = (desc->vpdVarNum & this_OFFSET_FLAG) != 0;
5598 printf("[%08X] %s%s var died at [%s", dspPtr(desc), GCtypeStr(gcType), isThis ? "this-ptr" : "",
5601 bool isPinned = (desc->vpdVarNum & pinned_OFFSET_FLAG) != 0;
5603 printf("[%08X] %s%s var died at [%s", dspPtr(desc), GCtypeStr(gcType), isPinned ? "pinned" : "",
5609 printf("-%02XH", -offs);
5613 printf("+%02XH", +offs);
5620 /* The "global" live GC variable mask is no longer up-to-date */
5622 emitThisGCrefVset = false;
5625 /*****************************************************************************
5627 * Record a new set of live GC ref variables.
5630 void emitter::emitUpdateLiveGCvars(VARSET_VALARG_TP vars, BYTE* addr)
5632 assert(emitIssuing);
5634 // Don't track GC changes in epilogs
5635 if (emitIGisInEpilog(emitCurIG))
5640 /* Is the current set accurate and unchanged? */
5642 if (emitThisGCrefVset && VarSetOps::Equal(emitComp, emitThisGCrefVars, vars))
5648 if (EMIT_GC_VERBOSE)
5650 printf("New GC ref live vars=%s ", VarSetOps::ToString(emitComp, vars));
5651 dumpConvertedVarSet(emitComp, vars);
5656 VarSetOps::Assign(emitComp, emitThisGCrefVars, vars);
5658 /* Are there any GC ref variables on the stack? */
5660 if (emitGCrFrameOffsCnt)
5663 unsigned cnt = emitTrkVarCnt;
5666 /* Test all the tracked variable bits in the mask */
5668 for (num = 0, tab = emitGCrFrameOffsTab; num < cnt; num++, tab++)
5674 // byref_OFFSET_FLAG and this_OFFSET_FLAG are set
5675 // in the table-offsets for byrefs and this-ptr
5677 int offs = val & ~OFFSET_MASK;
5679 // printf("var #%2u at %3d is now %s\n", num, offs, (vars & 1) ? "live" : "dead");
5681 if (VarSetOps::IsMember(emitComp, vars, num))
5683 GCtype gcType = (val & byref_OFFSET_FLAG) ? GCT_BYREF : GCT_GCREF;
5684 emitGCvarLiveUpd(offs, INT_MAX, gcType, addr);
5688 emitGCvarDeadUpd(offs, addr);
5694 emitThisGCrefVset = true;
5697 /*****************************************************************************
5699 * Record a call location for GC purposes (we know that this is a method that
5700 * will not be fully interruptible).
5703 void emitter::emitRecordGCcall(BYTE* codePos, unsigned char callInstrSize)
5705 assert(emitIssuing);
5706 assert(!emitFullGCinfo);
5708 unsigned offs = emitCurCodeOffs(codePos);
5709 unsigned regs = (emitThisGCrefRegs | emitThisByrefRegs) & ~RBM_INTRET;
5712 #ifdef JIT32_GCENCODER
5713 // The JIT32 GCInfo encoder allows us to (as the comment previously here said):
5714 // "Bail if this is a totally boring call", but the GCInfoEncoder/Decoder interface
5715 // requires a definition for every call site, so we skip these "early outs" when we're
5716 // using the general encoder.
5719 #if EMIT_TRACK_STACK_DEPTH
5720 if (emitCurStackLvl == 0)
5723 /* Nope, only interesting calls get recorded */
5725 if (emitSimpleStkUsed)
5727 if (!u1.emitSimpleStkMask)
5732 if (u2.emitGcArgTrackCnt == 0)
5736 #endif // JIT32_GCENCODER
5740 if (EMIT_GC_VERBOSE)
5742 printf("; Call at %04X [stk=%u], GCvars=", offs - callInstrSize, emitCurStackLvl);
5744 printf(", gcrefRegs=");
5745 printRegMaskInt(emitThisGCrefRegs);
5746 emitDispRegSet(emitThisGCrefRegs);
5747 // printRegMaskInt(emitThisGCrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5748 // emitDispRegSet (emitThisGCrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5749 printf(", byrefRegs=");
5750 printRegMaskInt(emitThisByrefRegs);
5751 emitDispRegSet(emitThisByrefRegs);
5752 // printRegMaskInt(emitThisByrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5753 // emitDispRegSet (emitThisByrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5759 /* Allocate a 'call site' descriptor and start filling it in */
5761 call = new (emitComp, CMK_GC) callDsc;
5763 call->cdBlock = nullptr;
5764 call->cdOffs = offs;
5765 #ifndef JIT32_GCENCODER
5766 call->cdCallInstrSize = callInstrSize;
5768 call->cdNext = nullptr;
5770 call->cdGCrefRegs = (regMaskSmall)emitThisGCrefRegs;
5771 call->cdByrefRegs = (regMaskSmall)emitThisByrefRegs;
5773 #if EMIT_TRACK_STACK_DEPTH
5774 #ifndef UNIX_AMD64_ABI
5775 noway_assert(FitsIn<USHORT>(emitCurStackLvl / ((unsigned)sizeof(unsigned))));
5776 #endif // UNIX_AMD64_ABI
5779 // Append the call descriptor to the list */
5780 if (codeGen->gcInfo.gcCallDescLast == nullptr)
5782 assert(codeGen->gcInfo.gcCallDescList == nullptr);
5783 codeGen->gcInfo.gcCallDescList = codeGen->gcInfo.gcCallDescLast = call;
5787 assert(codeGen->gcInfo.gcCallDescList != nullptr);
5788 codeGen->gcInfo.gcCallDescLast->cdNext = call;
5789 codeGen->gcInfo.gcCallDescLast = call;
5792 /* Record the current "pending" argument list */
5794 if (emitSimpleStkUsed)
5796 /* The biggest call is less than MAX_SIMPLE_STK_DEPTH. So use
5799 call->u1.cdArgMask = u1.emitSimpleStkMask;
5800 call->u1.cdByrefArgMask = u1.emitSimpleByrefStkMask;
5805 /* The current call has too many arguments, so we need to report the
5806 offsets of each individual GC arg. */
5808 call->cdArgCnt = u2.emitGcArgTrackCnt;
5809 if (call->cdArgCnt == 0)
5811 call->u1.cdArgMask = call->u1.cdByrefArgMask = 0;
5815 call->cdArgTable = new (emitComp, CMK_GC) unsigned[u2.emitGcArgTrackCnt];
5817 unsigned gcArgs = 0;
5818 unsigned stkLvl = emitCurStackLvl / sizeof(int);
5820 for (unsigned i = 0; i < stkLvl; i++)
5822 GCtype gcType = (GCtype)u2.emitArgTrackTab[stkLvl - i - 1];
5824 if (needsGC(gcType))
5826 call->cdArgTable[gcArgs] = i * TARGET_POINTER_SIZE;
5828 if (gcType == GCT_BYREF)
5830 call->cdArgTable[gcArgs] |= byref_OFFSET_FLAG;
5837 assert(gcArgs == u2.emitGcArgTrackCnt);
5841 /*****************************************************************************
5843 * Record a new set of live GC ref registers.
5846 void emitter::emitUpdateLiveGCregs(GCtype gcType, regMaskTP regs, BYTE* addr)
5848 assert(emitIssuing);
5850 // Don't track GC changes in epilogs
5851 if (emitIGisInEpilog(emitCurIG))
5861 if (EMIT_GC_VERBOSE)
5863 printf("New %sReg live regs=", GCtypeStr(gcType));
5864 printRegMaskInt(regs);
5865 emitDispRegSet(regs);
5870 assert(needsGC(gcType));
5872 regMaskTP& emitThisXXrefRegs = (gcType == GCT_GCREF) ? emitThisGCrefRegs : emitThisByrefRegs;
5873 regMaskTP& emitThisYYrefRegs = (gcType == GCT_GCREF) ? emitThisByrefRegs : emitThisGCrefRegs;
5874 assert(emitThisXXrefRegs != regs);
5878 /* Figure out which GC registers are becoming live/dead at this point */
5880 dead = (emitThisXXrefRegs & ~regs);
5881 life = (~emitThisXXrefRegs & regs);
5883 /* Can't simultaneously become live and dead at the same time */
5885 assert((dead | life) != 0);
5886 assert((dead & life) == 0);
5888 /* Compute the 'changing state' mask */
5890 chg = (dead | life);
5894 regMaskTP bit = genFindLowestBit(chg);
5895 regNumber reg = genRegNumFromMask(bit);
5899 emitGCregLiveUpd(gcType, reg, addr);
5903 emitGCregDeadUpd(reg, addr);
5909 assert(emitThisXXrefRegs == regs);
5913 emitThisYYrefRegs &= ~regs; // Kill the regs from the other GC type (if live)
5914 emitThisXXrefRegs = regs; // Mark them as live in the requested GC type
5917 // The 2 GC reg masks can't be overlapping
5919 assert((emitThisGCrefRegs & emitThisByrefRegs) == 0);
5922 /*****************************************************************************
5924 * Record the fact that the given register now contains a live GC ref.
5927 void emitter::emitGCregLiveSet(GCtype gcType, regMaskTP regMask, BYTE* addr, bool isThis)
5929 assert(emitIssuing);
5930 assert(needsGC(gcType));
5932 regPtrDsc* regPtrNext;
5934 assert(!isThis || emitComp->lvaKeepAliveAndReportThis());
5935 // assert(emitFullyInt || isThis);
5936 assert(emitFullGCinfo);
5938 assert(((emitThisGCrefRegs | emitThisByrefRegs) & regMask) == 0);
5940 /* Allocate a new regptr entry and fill it in */
5942 regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
5943 regPtrNext->rpdGCtype = gcType;
5945 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
5946 regPtrNext->rpdArg = FALSE;
5947 regPtrNext->rpdCall = FALSE;
5948 regPtrNext->rpdIsThis = isThis;
5949 regPtrNext->rpdCompiler.rpdAdd = (regMaskSmall)regMask;
5950 regPtrNext->rpdCompiler.rpdDel = 0;
5953 /*****************************************************************************
5955 * Record the fact that the given register no longer contains a live GC ref.
5958 void emitter::emitGCregDeadSet(GCtype gcType, regMaskTP regMask, BYTE* addr)
5960 assert(emitIssuing);
5961 assert(needsGC(gcType));
5963 regPtrDsc* regPtrNext;
5965 // assert(emitFullyInt);
5966 assert(emitFullGCinfo);
5968 assert(((emitThisGCrefRegs | emitThisByrefRegs) & regMask) != 0);
5970 /* Allocate a new regptr entry and fill it in */
5972 regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
5973 regPtrNext->rpdGCtype = gcType;
5975 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
5976 regPtrNext->rpdCall = FALSE;
5977 regPtrNext->rpdIsThis = FALSE;
5978 regPtrNext->rpdArg = FALSE;
5979 regPtrNext->rpdCompiler.rpdAdd = 0;
5980 regPtrNext->rpdCompiler.rpdDel = (regMaskSmall)regMask;
5983 /*****************************************************************************
5985 * Emit an 8-bit integer as code.
5988 unsigned char emitter::emitOutputByte(BYTE* dst, ssize_t val)
5990 *castto(dst, unsigned char*) = (unsigned char)val;
5993 if (emitComp->opts.dspEmit)
5995 printf("; emit_byte 0%02XH\n", val & 0xFF);
5997 #ifdef _TARGET_AMD64_
5998 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
5999 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6000 #endif // _TARGET_AMD64_
6003 return sizeof(unsigned char);
6006 /*****************************************************************************
6008 * Emit a 16-bit integer as code.
6011 unsigned char emitter::emitOutputWord(BYTE* dst, ssize_t val)
6013 MISALIGNED_WR_I2(dst, (short)val);
6016 if (emitComp->opts.dspEmit)
6018 printf("; emit_word 0%02XH,0%02XH\n", (val & 0xFF), (val >> 8) & 0xFF);
6020 #ifdef _TARGET_AMD64_
6021 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6022 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6023 #endif // _TARGET_AMD64_
6026 return sizeof(short);
6029 /*****************************************************************************
6031 * Emit a 32-bit integer as code.
6034 unsigned char emitter::emitOutputLong(BYTE* dst, ssize_t val)
6036 MISALIGNED_WR_I4(dst, (int)val);
6039 if (emitComp->opts.dspEmit)
6041 printf("; emit_long 0%08XH\n", (int)val);
6043 #ifdef _TARGET_AMD64_
6044 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6045 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6046 #endif // _TARGET_AMD64_
6052 /*****************************************************************************
6054 * Emit a pointer-sized integer as code.
6057 unsigned char emitter::emitOutputSizeT(BYTE* dst, ssize_t val)
6059 MISALIGNED_WR_ST(dst, val);
6062 if (emitComp->opts.dspEmit)
6064 #ifdef _TARGET_AMD64_
6065 printf("; emit_size_t 0%016llXH\n", val);
6066 #else // _TARGET_AMD64_
6067 printf("; emit_size_t 0%08XH\n", val);
6068 #endif // _TARGET_AMD64_
6072 return TARGET_POINTER_SIZE;
6075 //------------------------------------------------------------------------
6076 // Wrappers to emitOutputByte, emitOutputWord, emitOutputLong, emitOutputSizeT
6077 // that take unsigned __int64 or size_t type instead of ssize_t. Used on RyuJIT/x86.
6080 // dst - passed through
6081 // val - passed through
6084 // Same as wrapped function.
6087 #if defined(_TARGET_X86_)
6088 unsigned char emitter::emitOutputByte(BYTE* dst, size_t val)
6090 return emitOutputByte(dst, (ssize_t)val);
6093 unsigned char emitter::emitOutputWord(BYTE* dst, size_t val)
6095 return emitOutputWord(dst, (ssize_t)val);
6098 unsigned char emitter::emitOutputLong(BYTE* dst, size_t val)
6100 return emitOutputLong(dst, (ssize_t)val);
6103 unsigned char emitter::emitOutputSizeT(BYTE* dst, size_t val)
6105 return emitOutputSizeT(dst, (ssize_t)val);
6108 unsigned char emitter::emitOutputByte(BYTE* dst, unsigned __int64 val)
6110 return emitOutputByte(dst, (ssize_t)val);
6113 unsigned char emitter::emitOutputWord(BYTE* dst, unsigned __int64 val)
6115 return emitOutputWord(dst, (ssize_t)val);
6118 unsigned char emitter::emitOutputLong(BYTE* dst, unsigned __int64 val)
6120 return emitOutputLong(dst, (ssize_t)val);
6123 unsigned char emitter::emitOutputSizeT(BYTE* dst, unsigned __int64 val)
6125 return emitOutputSizeT(dst, (ssize_t)val);
6127 #endif // defined(_TARGET_X86_)
6129 /*****************************************************************************
6131 * Given a block cookie and a code position, return the actual code offset;
6132 * this can only be called at the end of code generation.
6135 UNATIVE_OFFSET emitter::emitCodeOffset(void* blockPtr, unsigned codePos)
6140 unsigned no = emitGetInsNumFromCodePos(codePos);
6142 /* Make sure we weren't passed some kind of a garbage thing */
6144 ig = (insGroup*)blockPtr;
6146 assert(ig && ig->igSelf == ig);
6149 /* The first and last offsets are always easy */
6155 else if (no == ig->igInsCnt)
6159 else if (ig->igFlags & IGF_UPD_ISZ)
6162 Some instruction sizes have changed, so we'll have to figure
6163 out the instruction offset "the hard way".
6166 of = emitFindOffset(ig, no);
6170 /* All instructions correctly predicted, the offset stays the same */
6172 of = emitGetInsOfsFromCodePos(codePos);
6174 // printf("[IG=%02u;ID=%03u;OF=%04X] <= %08X\n", ig->igNum, emitGetInsNumFromCodePos(codePos), of, codePos);
6176 /* Make sure the offset estimate is accurate */
6178 assert(of == emitFindOffset(ig, emitGetInsNumFromCodePos(codePos)));
6181 return ig->igOffs + of;
6184 /*****************************************************************************
6186 * Record the fact that the given register now contains a live GC ref.
6189 void emitter::emitGCregLiveUpd(GCtype gcType, regNumber reg, BYTE* addr)
6191 assert(emitIssuing);
6193 // Don't track GC changes in epilogs
6194 if (emitIGisInEpilog(emitCurIG))
6199 assert(needsGC(gcType));
6201 regMaskTP regMask = genRegMask(reg);
6203 regMaskTP& emitThisXXrefRegs = (gcType == GCT_GCREF) ? emitThisGCrefRegs : emitThisByrefRegs;
6204 regMaskTP& emitThisYYrefRegs = (gcType == GCT_GCREF) ? emitThisByrefRegs : emitThisGCrefRegs;
6206 if ((emitThisXXrefRegs & regMask) == 0)
6208 // If the register was holding the other GC type, that type should
6211 if (emitThisYYrefRegs & regMask)
6213 emitGCregDeadUpd(reg, addr);
6216 // For synchronized methods, "this" is always alive and in the same register.
6217 // However, if we generate any code after the epilog block (where "this"
6218 // goes dead), "this" will come alive again. We need to notice that.
6219 // Note that we only expect isThis to be true at an insGroup boundary.
6221 bool isThis = (reg == emitSyncThisObjReg) ? true : false;
6225 emitGCregLiveSet(gcType, regMask, addr, isThis);
6228 emitThisXXrefRegs |= regMask;
6231 if (EMIT_GC_VERBOSE)
6233 printf("%sReg +[%s]\n", GCtypeStr(gcType), emitRegName(reg));
6238 // The 2 GC reg masks can't be overlapping
6240 assert((emitThisGCrefRegs & emitThisByrefRegs) == 0);
6243 /*****************************************************************************
6245 * Record the fact that the given set of registers no longer contain live GC refs.
6248 void emitter::emitGCregDeadUpdMask(regMaskTP regs, BYTE* addr)
6250 assert(emitIssuing);
6252 // Don't track GC changes in epilogs
6253 if (emitIGisInEpilog(emitCurIG))
6258 // First, handle the gcref regs going dead
6260 regMaskTP gcrefRegs = emitThisGCrefRegs & regs;
6262 // "this" can never go dead in synchronized methods, except in the epilog
6263 // after the call to CORINFO_HELP_MON_EXIT.
6264 assert(emitSyncThisObjReg == REG_NA || (genRegMask(emitSyncThisObjReg) & regs) == 0);
6268 assert((emitThisByrefRegs & gcrefRegs) == 0);
6272 emitGCregDeadSet(GCT_GCREF, gcrefRegs, addr);
6275 emitThisGCrefRegs &= ~gcrefRegs;
6278 if (EMIT_GC_VERBOSE)
6281 printRegMaskInt(gcrefRegs);
6283 emitDispRegSet(gcrefRegs);
6289 // Second, handle the byref regs going dead
6291 regMaskTP byrefRegs = emitThisByrefRegs & regs;
6295 assert((emitThisGCrefRegs & byrefRegs) == 0);
6299 emitGCregDeadSet(GCT_BYREF, byrefRegs, addr);
6302 emitThisByrefRegs &= ~byrefRegs;
6305 if (EMIT_GC_VERBOSE)
6308 printRegMaskInt(byrefRegs);
6310 emitDispRegSet(byrefRegs);
6317 /*****************************************************************************
6319 * Record the fact that the given register no longer contains a live GC ref.
6322 void emitter::emitGCregDeadUpd(regNumber reg, BYTE* addr)
6324 assert(emitIssuing);
6326 // Don't track GC changes in epilogs
6327 if (emitIGisInEpilog(emitCurIG))
6332 regMaskTP regMask = genRegMask(reg);
6334 if ((emitThisGCrefRegs & regMask) != 0)
6336 assert((emitThisByrefRegs & regMask) == 0);
6340 emitGCregDeadSet(GCT_GCREF, regMask, addr);
6343 emitThisGCrefRegs &= ~regMask;
6346 if (EMIT_GC_VERBOSE)
6348 printf("%s -[%s]\n", "gcrReg", emitRegName(reg));
6352 else if ((emitThisByrefRegs & regMask) != 0)
6356 emitGCregDeadSet(GCT_BYREF, regMask, addr);
6359 emitThisByrefRegs &= ~regMask;
6362 if (EMIT_GC_VERBOSE)
6364 printf("%s -[%s]\n", "byrReg", emitRegName(reg));
6370 /*****************************************************************************
6372 * Record the fact that the given variable now contains a live GC ref.
6373 * varNum may be INT_MAX or negative (indicating a spill temp) only if
6374 * offs is guaranteed to be the offset of a tracked GC ref. Else we
6375 * need a valid value to check if the variable is tracked or not.
6378 void emitter::emitGCvarLiveUpd(int offs, int varNum, GCtype gcType, BYTE* addr)
6380 assert(abs(offs) % sizeof(int) == 0);
6381 assert(needsGC(gcType));
6383 #if FEATURE_FIXED_OUT_ARGS
6384 if ((unsigned)varNum == emitComp->lvaOutgoingArgSpaceVar)
6388 /* Append an "arg push" entry to track a GC written to the
6389 outgoing argument space.
6390 Allocate a new ptr arg entry and fill it in */
6392 regPtrDsc* regPtrNext = gcInfo->gcRegPtrAllocDsc();
6393 regPtrNext->rpdGCtype = gcType;
6394 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6395 regPtrNext->rpdArg = TRUE;
6396 regPtrNext->rpdCall = FALSE;
6397 noway_assert(FitsIn<unsigned short>(offs));
6398 regPtrNext->rpdPtrArg = (unsigned short)offs;
6399 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_PUSH;
6400 regPtrNext->rpdIsThis = FALSE;
6403 if (EMIT_GC_VERBOSE)
6405 printf("[%04X] %s arg write\n", offs, GCtypeStr(gcType));
6411 #endif // FEATURE_FIXED_OUT_ARGS
6413 /* Is the frame offset within the "interesting" range? */
6415 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
6417 /* Normally all variables in this range must be tracked stack
6418 pointers. However, for EnC, we relax this condition. So we
6419 must check if this is not such a variable.
6420 Note that varNum might be negative, indicating a spill temp.
6423 if (varNum != INT_MAX)
6425 bool isTracked = false;
6428 // This is NOT a spill temp
6429 LclVarDsc* varDsc = &emitComp->lvaTable[varNum];
6430 isTracked = emitComp->lvaIsGCTracked(varDsc);
6434 // Is it an untracked spill temp?
6435 isTracked = TRACK_GC_TEMP_LIFETIMES;
6440 assert(!emitContTrkPtrLcls ||
6441 // EBP based variables in the double-aligned frames are indeed input arguments.
6442 // and we don't require them to fall into the "interesting" range.
6443 ((emitComp->rpFrameType == FT_DOUBLE_ALIGN_FRAME) && (varNum >= 0) &&
6444 (emitComp->lvaTable[varNum].lvFramePointerBased == 1)));
6446 assert(!emitContTrkPtrLcls);
6454 /* Compute the index into the GC frame table */
6456 disp = (offs - emitGCrFrameOffsMin) / TARGET_POINTER_SIZE;
6457 assert(disp < emitGCrFrameOffsCnt);
6459 /* If the variable is currently dead, mark it as live */
6461 if (emitGCrFrameLiveTab[disp] == nullptr)
6463 emitGCvarLiveSet(offs, gcType, addr, disp);
6469 /*****************************************************************************
6471 * Record the fact that the given variable no longer contains a live GC ref.
6474 void emitter::emitGCvarDeadUpd(int offs, BYTE* addr)
6476 assert(emitIssuing);
6477 assert(abs(offs) % sizeof(int) == 0);
6479 /* Is the frame offset within the "interesting" range? */
6481 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
6485 /* Compute the index into the GC frame table */
6487 disp = (offs - emitGCrFrameOffsMin) / TARGET_POINTER_SIZE;
6488 assert(disp < emitGCrFrameOffsCnt);
6490 /* If the variable is currently live, mark it as dead */
6492 if (emitGCrFrameLiveTab[disp] != nullptr)
6494 emitGCvarDeadSet(offs, addr, disp);
6499 /*****************************************************************************
6501 * Allocate a new IG and link it in to the global list after the current IG
6504 insGroup* emitter::emitAllocAndLinkIG()
6506 insGroup* ig = emitAllocIG();
6510 emitInsertIGAfter(emitCurIG, ig);
6512 /* Propagate some IG flags from the current group to the new group */
6514 ig->igFlags |= (emitCurIG->igFlags & IGF_PROPAGATE_MASK);
6516 /* Set the new IG as the current IG */
6523 /*****************************************************************************
6525 * Allocate an instruction group descriptor and assign it the next index.
6528 insGroup* emitter::emitAllocIG()
6532 /* Allocate a group descriptor */
6534 size_t sz = sizeof(insGroup);
6535 ig = (insGroup*)emitGetMem(sz);
6542 emitTotalIGcnt += 1;
6543 emitTotalIGsize += sz;
6544 emitSizeMethod += sz;
6547 /* Do basic initialization */
6554 /*****************************************************************************
6556 * Initialize an instruction group
6559 void emitter::emitInitIG(insGroup* ig)
6561 /* Assign the next available index to the instruction group */
6563 ig->igNum = emitNxtIGnum;
6567 /* Record the (estimated) code offset of the group */
6569 ig->igOffs = emitCurCodeOffset;
6570 assert(IsCodeAligned(ig->igOffs));
6572 /* Set the current function index */
6574 ig->igFuncIdx = emitComp->compCurrFuncIdx;
6578 /* Zero out some fields to avoid printing garbage in JitDumps. These
6579 really only need to be set in DEBUG, but do it in all cases to make
6580 sure we act the same in non-DEBUG builds.
6584 ig->igGCregs = RBM_NONE;
6588 /*****************************************************************************
6590 * Insert instruction group 'ig' after 'igInsertAfterIG'
6593 void emitter::emitInsertIGAfter(insGroup* insertAfterIG, insGroup* ig)
6598 ig->igNext = insertAfterIG->igNext;
6599 insertAfterIG->igNext = ig;
6601 if (emitIGlast == insertAfterIG)
6603 // If we are inserting at the end, then update the 'last' pointer
6608 /*****************************************************************************
6610 * Save the current IG and start a new one.
6613 void emitter::emitNxtIG(bool emitAdd)
6615 /* Right now we don't allow multi-IG prologs */
6617 assert(emitCurIG != emitPrologIG);
6619 /* First save the current group */
6623 /* Update the GC live sets for the group's start
6624 * Do it only if not an emitter added block */
6628 VarSetOps::Assign(emitComp, emitInitGCrefVars, emitThisGCrefVars);
6629 emitInitGCrefRegs = emitThisGCrefRegs;
6630 emitInitByrefRegs = emitThisByrefRegs;
6633 /* Start generating the new group */
6637 /* If this is an emitter added block, flag it */
6641 emitCurIG->igFlags |= IGF_EMIT_ADD;
6644 // We've created a new IG; no need to force another one.
6645 emitForceNewIG = false;
6648 /*****************************************************************************
6650 * emitGetInsSC: Get the instruction's constant value.
6653 ssize_t emitter::emitGetInsSC(instrDesc* id)
6655 #ifdef _TARGET_ARM_ // should it be _TARGET_ARMARCH_? Why do we need this? Note that on ARM64 we store scaled immediates
6657 if (id->idIsLclVar())
6659 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
6662 int offs = id->idAddr()->iiaLclVar.lvaOffset();
6663 #if defined(_TARGET_ARM_)
6664 int adr = emitComp->lvaFrameAddress(varNum, id->idIsLclFPBase(), &baseReg, offs);
6665 int dsp = adr + offs;
6666 if ((id->idIns() == INS_sub) || (id->idIns() == INS_subw))
6668 #elif defined(_TARGET_ARM64_)
6669 // TODO-ARM64-Cleanup: this is currently unreachable. Do we need it?
6671 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
6672 int dsp = adr + offs;
6673 if (id->idIns() == INS_sub)
6679 #endif // _TARGET_ARM_
6680 if (id->idIsLargeCns())
6682 return ((instrDescCns*)id)->idcCnsVal;
6686 return id->idSmallCns();
6690 /*****************************************************************************/
6691 #if EMIT_TRACK_STACK_DEPTH
6692 /*****************************************************************************
6694 * Record a push of a single dword on the stack.
6697 void emitter::emitStackPush(BYTE* addr, GCtype gcType)
6700 assert(IsValidGCtype(gcType));
6703 if (emitSimpleStkUsed)
6705 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6706 assert(emitCurStackLvl / sizeof(int) < MAX_SIMPLE_STK_DEPTH);
6708 u1.emitSimpleStkMask <<= 1;
6709 u1.emitSimpleStkMask |= (unsigned)needsGC(gcType);
6711 u1.emitSimpleByrefStkMask <<= 1;
6712 u1.emitSimpleByrefStkMask |= (gcType == GCT_BYREF);
6714 assert((u1.emitSimpleStkMask & u1.emitSimpleByrefStkMask) == u1.emitSimpleByrefStkMask);
6718 emitStackPushLargeStk(addr, gcType);
6721 emitCurStackLvl += sizeof(int);
6724 /*****************************************************************************
6726 * Record a push of a bunch of non-GC dwords on the stack.
6729 void emitter::emitStackPushN(BYTE* addr, unsigned count)
6733 if (emitSimpleStkUsed)
6735 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6737 u1.emitSimpleStkMask <<= count;
6738 u1.emitSimpleByrefStkMask <<= count;
6742 emitStackPushLargeStk(addr, GCT_NONE, count);
6745 emitCurStackLvl += count * sizeof(int);
6748 /*****************************************************************************
6750 * Record a pop of the given number of dwords from the stack.
6753 void emitter::emitStackPop(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count)
6755 assert(emitCurStackLvl / sizeof(int) >= count);
6756 assert(!isCall || callInstrSize > 0);
6760 if (emitSimpleStkUsed)
6762 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6764 unsigned cnt = count;
6768 u1.emitSimpleStkMask >>= 1;
6769 u1.emitSimpleByrefStkMask >>= 1;
6774 emitStackPopLargeStk(addr, isCall, callInstrSize, count);
6777 emitCurStackLvl -= count * sizeof(int);
6783 // For the general encoder we do the call below always when it's a call, to ensure that the call is
6784 // recorded (when we're doing the ptr reg map for a non-fully-interruptible method).
6786 #ifndef JIT32_GCENCODER
6787 || (emitComp->genFullPtrRegMap && (!emitComp->genInterruptible) && isCall)
6788 #endif // JIT32_GCENCODER
6791 emitStackPopLargeStk(addr, isCall, callInstrSize, 0);
6796 /*****************************************************************************
6798 * Record a push of a single word on the stack for a full pointer map.
6801 void emitter::emitStackPushLargeStk(BYTE* addr, GCtype gcType, unsigned count)
6803 S_UINT32 level(emitCurStackLvl / sizeof(int));
6805 assert(IsValidGCtype(gcType));
6807 assert(!emitSimpleStkUsed);
6811 /* Push an entry for this argument on the tracking stack */
6813 // printf("Pushed [%d] at lvl %2u [max=%u]\n", isGCref, emitArgTrackTop - emitArgTrackTab, emitMaxStackDepth);
6815 assert(level.IsOverflow() || u2.emitArgTrackTop == u2.emitArgTrackTab + level.Value());
6816 *u2.emitArgTrackTop++ = (BYTE)gcType;
6817 assert(u2.emitArgTrackTop <= u2.emitArgTrackTab + emitMaxStackDepth);
6819 if (emitFullArgInfo || needsGC(gcType))
6823 /* Append an "arg push" entry if this is a GC ref or
6824 FPO method. Allocate a new ptr arg entry and fill it in */
6826 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6827 regPtrNext->rpdGCtype = gcType;
6829 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6830 regPtrNext->rpdArg = TRUE;
6831 regPtrNext->rpdCall = FALSE;
6832 if (level.IsOverflow() || !FitsIn<unsigned short>(level.Value()))
6834 IMPL_LIMITATION("Too many/too big arguments to encode GC information");
6836 regPtrNext->rpdPtrArg = (unsigned short)level.Value();
6837 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_PUSH;
6838 regPtrNext->rpdIsThis = FALSE;
6841 if (EMIT_GC_VERBOSE)
6843 printf("[%08X] %s arg push %u\n", dspPtr(regPtrNext), GCtypeStr(gcType), level.Value());
6848 /* This is an "interesting" argument push */
6850 u2.emitGcArgTrackCnt++;
6853 assert(!level.IsOverflow());
6857 /*****************************************************************************
6859 * Record a pop of the given number of words from the stack for a full ptr
6863 void emitter::emitStackPopLargeStk(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count)
6865 assert(emitIssuing);
6868 S_UINT16 argRecCnt(0); // arg count for ESP, ptr-arg count for EBP
6869 unsigned gcrefRegs, byrefRegs;
6871 #ifdef JIT32_GCENCODER
6872 // For the general encoder, we always need to record calls, so we make this call
6873 // even when emitSimpleStkUsed is true.
6874 assert(!emitSimpleStkUsed);
6877 /* Count how many pointer records correspond to this "pop" */
6879 for (argStkCnt = count; argStkCnt; argStkCnt--)
6881 assert(u2.emitArgTrackTop > u2.emitArgTrackTab);
6883 GCtype gcType = (GCtype)(*--u2.emitArgTrackTop);
6885 assert(IsValidGCtype(gcType));
6887 // printf("Popped [%d] at lvl %u\n", GCtypeStr(gcType), emitArgTrackTop - emitArgTrackTab);
6889 // This is an "interesting" argument
6891 if (emitFullArgInfo || needsGC(gcType))
6897 assert(u2.emitArgTrackTop >= u2.emitArgTrackTab);
6898 assert(u2.emitArgTrackTop == u2.emitArgTrackTab + emitCurStackLvl / sizeof(int) - count);
6899 noway_assert(!argRecCnt.IsOverflow());
6901 /* We're about to pop the corresponding arg records */
6903 u2.emitGcArgTrackCnt -= argRecCnt.Value();
6905 #ifdef JIT32_GCENCODER
6906 // For the general encoder, we always have to record calls, so we don't take this early return.
6907 if (!emitFullGCinfo)
6911 // Do we have any interesting (i.e., callee-saved) registers live here?
6913 gcrefRegs = byrefRegs = 0;
6915 // We make a bitmask whose bits correspond to callee-saved register indices (in the sequence
6916 // of callee-saved registers only).
6917 for (unsigned calleeSavedRegIdx = 0; calleeSavedRegIdx < CNT_CALLEE_SAVED; calleeSavedRegIdx++)
6919 regMaskTP calleeSavedRbm = raRbmCalleeSaveOrder[calleeSavedRegIdx];
6920 if (emitThisGCrefRegs & calleeSavedRbm)
6922 gcrefRegs |= (1 << calleeSavedRegIdx);
6924 if (emitThisByrefRegs & calleeSavedRbm)
6926 byrefRegs |= (1 << calleeSavedRegIdx);
6930 #ifdef JIT32_GCENCODER
6931 // For the general encoder, we always have to record calls, so we don't take this early return. /* Are there any
6932 // args to pop at this call site?
6934 if (argRecCnt.Value() == 0)
6937 Or do we have a partially interruptible EBP-less frame, and any
6938 of EDI,ESI,EBX,EBP are live, or is there an outer/pending call?
6940 CLANG_FORMAT_COMMENT_ANCHOR;
6942 #if !FPO_INTERRUPTIBLE
6943 if (emitFullyInt || (gcrefRegs == 0 && byrefRegs == 0 && u2.emitGcArgTrackCnt == 0))
6947 #endif // JIT32_GCENCODER
6949 /* Only calls may pop more than one value */
6951 // _cdecl calls accomplish this popping via a post-call-instruction SP adjustment.
6952 // The "rpdCall" field below should be interpreted as "the instruction accomplishes
6953 // call-related popping, even if it's not itself a call". Therefore, we don't just
6954 // use the "isCall" input argument, which means that the instruction actually is a call --
6955 // we use the OR of "isCall" or the "pops more than one value."
6957 bool isCallRelatedPop = (argRecCnt.Value() > 1);
6959 /* Allocate a new ptr arg entry and fill it in */
6961 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6962 regPtrNext->rpdGCtype = GCT_GCREF; // Pops need a non-0 value (??)
6964 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6965 regPtrNext->rpdCall = (isCall || isCallRelatedPop);
6966 #ifndef JIT32_GCENCODER
6967 if (regPtrNext->rpdCall)
6969 assert(isCall || callInstrSize == 0);
6970 regPtrNext->rpdCallInstrSize = callInstrSize;
6973 regPtrNext->rpdCallGCrefRegs = gcrefRegs;
6974 regPtrNext->rpdCallByrefRegs = byrefRegs;
6975 regPtrNext->rpdArg = TRUE;
6976 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_POP;
6977 regPtrNext->rpdPtrArg = argRecCnt.Value();
6980 if (EMIT_GC_VERBOSE)
6982 printf("[%08X] ptr arg pop %u\n", dspPtr(regPtrNext), count);
6987 /*****************************************************************************
6988 * For caller-pop arguments, we report the arguments as pending arguments.
6989 * However, any GC arguments are now dead, so we need to report them
6993 void emitter::emitStackKillArgs(BYTE* addr, unsigned count, unsigned char callInstrSize)
6997 if (emitSimpleStkUsed)
6999 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCInfo
7001 /* We don't need to report this to the GC info, but we do need
7002 to kill mark the ptrs on the stack as non-GC */
7004 assert(emitCurStackLvl / sizeof(int) >= count);
7006 for (unsigned lvl = 0; lvl < count; lvl++)
7008 u1.emitSimpleStkMask &= ~(1 << lvl);
7009 u1.emitSimpleByrefStkMask &= ~(1 << lvl);
7014 BYTE* argTrackTop = u2.emitArgTrackTop;
7017 for (unsigned i = 0; i < count; i++)
7019 assert(argTrackTop > u2.emitArgTrackTab);
7023 GCtype gcType = (GCtype)(*argTrackTop);
7024 assert(IsValidGCtype(gcType));
7026 if (needsGC(gcType))
7028 // printf("Killed %s at lvl %u\n", GCtypeStr(gcType), argTrackTop - emitArgTrackTab);
7030 *argTrackTop = GCT_NONE;
7035 noway_assert(!gcCnt.IsOverflow());
7037 /* We're about to kill the corresponding (pointer) arg records */
7039 if (!emitFullArgInfo)
7041 u2.emitGcArgTrackCnt -= gcCnt.Value();
7044 if (!emitFullGCinfo)
7049 /* Right after the call, the arguments are still sitting on the
7050 stack, but they are effectively dead. For fully-interruptible
7051 methods, we need to report that */
7053 if (emitFullGCinfo && gcCnt.Value())
7055 /* Allocate a new ptr arg entry and fill it in */
7057 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
7058 regPtrNext->rpdGCtype = GCT_GCREF; // Kills need a non-0 value (??)
7060 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
7062 regPtrNext->rpdArg = TRUE;
7063 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_KILL;
7064 regPtrNext->rpdPtrArg = gcCnt.Value();
7067 if (EMIT_GC_VERBOSE)
7069 printf("[%08X] ptr arg kill %u\n", dspPtr(regPtrNext), count);
7074 /* Now that ptr args have been marked as non-ptrs, we need to record
7075 the call itself as one that has no arguments. */
7077 emitStackPopLargeStk(addr, true, callInstrSize, 0);
7081 /*****************************************************************************
7082 * A helper for recording a relocation with the EE.
7084 void emitter::emitRecordRelocation(void* location, /* IN */
7085 void* target, /* IN */
7086 WORD fRelocType, /* IN */
7087 WORD slotNum /* = 0 */, /* IN */
7088 INT32 addlDelta /* = 0 */) /* IN */
7090 // If we're an unmatched altjit, don't tell the VM anything. We still record the relocation for
7091 // late disassembly; maybe we'll need it?
7092 if (emitComp->info.compMatchedVM)
7094 emitCmpHandle->recordRelocation(location, target, fRelocType, slotNum, addlDelta);
7096 #if defined(LATE_DISASM)
7097 codeGen->getDisAssembler().disRecordRelocation((size_t)location, (size_t)target);
7098 #endif // defined(LATE_DISASM)
7102 /*****************************************************************************
7103 * A helper for handling a Thumb-Mov32 of position-independent (PC-relative) value
7105 * This routine either records relocation for the location with the EE,
7106 * or creates a virtual relocation entry to perform offset fixup during
7107 * compilation without recording it with EE - depending on which of
7108 * absolute/relocative relocations mode are used for code section.
7110 void emitter::emitHandlePCRelativeMov32(void* location, /* IN */
7111 void* target) /* IN */
7113 if (emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_RELATIVE_CODE_RELOCS))
7115 emitRecordRelocation(location, target, IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL);
7119 emitRecordRelocation(location, target, IMAGE_REL_BASED_THUMB_MOV32);
7122 #endif // _TARGET_ARM_
7124 /*****************************************************************************
7125 * A helper for recording a call site with the EE.
7127 void emitter::emitRecordCallSite(ULONG instrOffset, /* IN */
7128 CORINFO_SIG_INFO* callSig, /* IN */
7129 CORINFO_METHOD_HANDLE methodHandle) /* IN */
7132 // Since CORINFO_SIG_INFO is a heavyweight structure, in most cases we can
7133 // lazily obtain it here using the given method handle (we only save the sig
7134 // info when we explicitly need it, i.e. for CALLI calls, vararg calls, and
7136 if (callSig == nullptr)
7138 assert(methodHandle != nullptr);
7140 if (Compiler::eeGetHelperNum(methodHandle) == CORINFO_HELP_UNDEF)
7142 if (emitScratchSigInfo == nullptr)
7144 emitScratchSigInfo = new (emitComp, CMK_CorSig) CORINFO_SIG_INFO;
7147 emitComp->eeGetMethodSig(methodHandle, emitScratchSigInfo);
7148 callSig = emitScratchSigInfo;
7152 emitCmpHandle->recordCallSite(instrOffset, callSig, methodHandle);
7153 #endif // defined(DEBUG)
7156 /*****************************************************************************/
7157 #endif // EMIT_TRACK_STACK_DEPTH
7158 /*****************************************************************************/
7159 /*****************************************************************************/
7163 /*****************************************************************************
7164 * Given a code offset, return a string representing a label for that offset.
7165 * If the code offset is just after the end of the code of the function, the
7166 * label will be "END". If the code offset doesn't correspond to any known
7167 * offset, the label will be "UNKNOWN". The strings are returned from static
7168 * buffers. This function rotates amongst four such static buffers (there are
7169 * cases where this function is called four times to provide data for a single
7173 const char* emitter::emitOffsetToLabel(unsigned offs)
7175 const size_t TEMP_BUFFER_LEN = 40;
7176 static unsigned curBuf = 0;
7177 static char buf[4][TEMP_BUFFER_LEN];
7181 UNATIVE_OFFSET nextof = 0;
7183 for (ig = emitIGlist; ig != nullptr; ig = ig->igNext)
7185 assert(nextof == ig->igOffs);
7187 if (ig->igOffs == offs)
7190 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "G_M%03u_IG%02u", Compiler::s_compMethodsCount, ig->igNum);
7191 retbuf = buf[curBuf];
7192 curBuf = (curBuf + 1) % 4;
7195 else if (ig->igOffs > offs)
7197 // We went past the requested offset but didn't find it.
7198 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "UNKNOWN");
7199 retbuf = buf[curBuf];
7200 curBuf = (curBuf + 1) % 4;
7204 nextof = ig->igOffs + ig->igSize;
7209 // It's a pseudo-label to the end.
7210 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "END");
7211 retbuf = buf[curBuf];
7212 curBuf = (curBuf + 1) % 4;
7217 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "UNKNOWN");
7218 retbuf = buf[curBuf];
7219 curBuf = (curBuf + 1) % 4;