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 tinyID = %2u\n", TINY_IDSC_SIZE);
327 fprintf(fout, "Size of instrDesc = %2u\n", sizeof(emitter::instrDesc));
328 // fprintf(fout, "Offset of _idIns = %2u\n", offsetof(emitter::instrDesc, _idIns ));
329 // fprintf(fout, "Offset of _idInsFmt = %2u\n", offsetof(emitter::instrDesc, _idInsFmt ));
330 // fprintf(fout, "Offset of _idOpSize = %2u\n", offsetof(emitter::instrDesc, _idOpSize ));
331 // fprintf(fout, "Offset of idSmallCns = %2u\n", offsetof(emitter::instrDesc, idSmallCns ));
332 // fprintf(fout, "Offset of _idAddrUnion= %2u\n", offsetof(emitter::instrDesc, _idAddrUnion));
333 // fprintf(fout, "\n");
334 // fprintf(fout, "Size of _idAddrUnion= %2u\n", sizeof(((emitter::instrDesc*)0)->_idAddrUnion));
337 fprintf(fout, "GCInfo::regPtrDsc:\n");
338 fprintf(fout, "Offset of rpdNext = %2u\n", offsetof(GCInfo::regPtrDsc, rpdNext));
339 fprintf(fout, "Offset of rpdOffs = %2u\n", offsetof(GCInfo::regPtrDsc, rpdOffs));
340 fprintf(fout, "Offset of <union> = %2u\n", offsetof(GCInfo::regPtrDsc, rpdPtrArg));
341 fprintf(fout, "Size of GCInfo::regPtrDsc = %2u\n", sizeof(GCInfo::regPtrDsc));
346 void emitterStats(FILE* fout)
348 if (totAllocdSize > 0)
350 assert(totActualSize <= totAllocdSize);
352 fprintf(fout, "\nTotal allocated code size = %u\n", totAllocdSize);
354 if (totActualSize < totAllocdSize)
356 fprintf(fout, "Total generated code size = %u ", totActualSize);
358 fprintf(fout, "(%4.3f%% waste)", 100 * ((totAllocdSize - totActualSize) / (double)totActualSize));
362 assert(emitter::emitTotalInsCnt);
364 fprintf(fout, "Average of %4.2f bytes of code generated per instruction\n",
365 (double)totActualSize / emitter::emitTotalInsCnt);
368 fprintf(fout, "\nInstruction format frequency table:\n\n");
370 unsigned f, ic = 0, dc = 0;
372 for (f = 0; f < emitter::IF_COUNT; f++)
374 ic += emitter::emitIFcounts[f];
377 for (f = 0; f < emitter::IF_COUNT; f++)
379 unsigned c = emitter::emitIFcounts[f];
381 if ((c > 0) && (1000 * c >= ic))
384 fprintf(fout, " %-13s %8u (%5.2f%%)\n", emitter::emitIfName(f), c, 100.0 * c / ic);
388 fprintf(fout, " --------------------------------\n");
389 fprintf(fout, " %-13s %8u (%5.2f%%)\n", "Total shown", dc, 100.0 * dc / ic);
391 if (emitter::emitTotalIGmcnt)
393 fprintf(fout, "Total of %8u methods\n", emitter::emitTotalIGmcnt);
394 fprintf(fout, "Total of %8u insGroup\n", emitter::emitTotalIGcnt);
395 fprintf(fout, "Total of %8u insPlaceholderGroupData\n", emitter::emitTotalPhIGcnt);
396 fprintf(fout, "Total of %8u instructions\n", emitter::emitTotalIGicnt);
397 fprintf(fout, "Total of %8u jumps\n", emitter::emitTotalIGjmps);
398 fprintf(fout, "Total of %8u GC livesets\n", emitter::emitTotalIGptrs);
400 fprintf(fout, "Average of %8.1lf insGroup per method\n",
401 (double)emitter::emitTotalIGcnt / emitter::emitTotalIGmcnt);
402 fprintf(fout, "Average of %8.1lf insPhGroup per method\n",
403 (double)emitter::emitTotalPhIGcnt / emitter::emitTotalIGmcnt);
404 fprintf(fout, "Average of %8.1lf instructions per method\n",
405 (double)emitter::emitTotalIGicnt / emitter::emitTotalIGmcnt);
406 fprintf(fout, "Average of %8.1lf desc. bytes per method\n",
407 (double)emitter::emitTotalIGsize / emitter::emitTotalIGmcnt);
408 fprintf(fout, "Average of %8.1lf jumps per method\n",
409 (double)emitter::emitTotalIGjmps / emitter::emitTotalIGmcnt);
410 fprintf(fout, "Average of %8.1lf GC livesets per method\n",
411 (double)emitter::emitTotalIGptrs / emitter::emitTotalIGmcnt);
413 fprintf(fout, "Average of %8.1lf instructions per group \n",
414 (double)emitter::emitTotalIGicnt / emitter::emitTotalIGcnt);
415 fprintf(fout, "Average of %8.1lf desc. bytes per group \n",
416 (double)emitter::emitTotalIGsize / emitter::emitTotalIGcnt);
417 fprintf(fout, "Average of %8.1lf jumps per group \n",
418 (double)emitter::emitTotalIGjmps / emitter::emitTotalIGcnt);
420 fprintf(fout, "Average of %8.1lf bytes per instrDesc\n",
421 (double)emitter::emitTotalIGsize / emitter::emitTotalIGicnt);
423 fprintf(fout, "A total of %8u desc. bytes\n", emitter::emitTotalIGsize);
427 fprintf(fout, "Descriptor size distribution:\n");
428 emitSizeTable.dump(fout);
431 fprintf(fout, "GC ref frame variable counts:\n");
432 GCrefsTable.dump(fout);
435 fprintf(fout, "Max. stack depth distribution:\n");
436 stkDepthTable.dump(fout);
443 if (emitter::emitSmallCnsCnt || emitter::emitLargeCnsCnt)
445 fprintf(fout, "SmallCnsCnt = %6u\n", emitter::emitSmallCnsCnt);
446 fprintf(fout, "LargeCnsCnt = %6u (%3u %% of total)\n", emitter::emitLargeCnsCnt,
447 100 * emitter::emitLargeCnsCnt / (emitter::emitLargeCnsCnt + emitter::emitSmallCnsCnt));
451 // TODO-Cleanup: WHy is this in #if 0 - Is EMITTER_STATS ever used? Fix or delete this.
452 if (emitter::emitSmallCnsCnt)
456 m = emitter::emitSmallCnsCnt/1000 + 1;
458 for (i = ID_MIN_SMALL_CNS; i < ID_MAX_SMALL_CNS; i++)
460 c = emitter::emitSmallCns[i-ID_MIN_SMALL_CNS];
462 fprintf(fout, "cns[%4d] = %u\n", i, c);
467 fprintf(fout, "%8u bytes allocated in the emitter\n", emitter::emitTotMemAlloc);
470 #endif // EMITTER_STATS
472 /*****************************************************************************/
474 const unsigned short emitTypeSizes[] = {
475 #define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) sze,
476 #include "typelist.h"
480 const unsigned short emitTypeActSz[] = {
481 #define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) asze,
482 #include "typelist.h"
486 /*****************************************************************************/
487 /*****************************************************************************
489 * Initialize the emitter - called once, at DLL load time.
492 void emitter::emitInit()
496 /*****************************************************************************
498 * Shut down the emitter - called once, at DLL exit time.
501 void emitter::emitDone()
505 /*****************************************************************************
510 void* emitter::emitGetMem(size_t sz)
512 assert(sz % sizeof(int) == 0);
515 emitTotMemAlloc += sz;
518 return emitComp->compGetMem(sz, CMK_InstDesc);
521 /*****************************************************************************
523 * emitLclVarAddr support methods
525 void emitLclVarAddr::initLclVarAddr(int varNum, unsigned offset)
533 _lvaTag = LVA_STANDARD_ENCODING;
534 _lvaExtra = offset; // offset known to be in [0..32767]
535 _lvaVarNum = (unsigned)varNum; // varNum known to be in [0..32767]
537 else // offset >= 32768
539 // We could support larger local offsets here at the cost of less varNums
542 IMPL_LIMITATION("JIT doesn't support offsets larger than 65535 into valuetypes\n");
545 _lvaTag = LVA_LARGE_OFFSET;
546 _lvaExtra = (offset - 32768); // (offset-32768) is known to be in [0..32767]
547 _lvaVarNum = (unsigned)varNum; // varNum known to be in [0..32767]
550 else // varNum < 0, These are used for Compiler spill temps
554 IMPL_LIMITATION("JIT doesn't support more than 32767 Compiler Spill temps\n");
559 "JIT doesn't support offsets larger than 32767 into valuetypes for Compiler Spill temps\n");
562 _lvaTag = LVA_COMPILER_TEMP;
563 _lvaExtra = offset; // offset known to be in [0..32767]
564 _lvaVarNum = (unsigned)(-varNum); // -varNum known to be in [1..32767]
567 else // varNum >= 32768
571 IMPL_LIMITATION("JIT doesn't support offsets larger than 255 into valuetypes for local vars > 32767\n");
573 if (varNum >= 0x00400000)
574 { // 0x00400000 == 2^22
575 IMPL_LIMITATION("JIT doesn't support more than 2^22 variables\n");
578 _lvaTag = LVA_LARGE_VARNUM;
579 _lvaVarNum = varNum & 0x00007FFF; // varNum bits 14 to 0
580 _lvaExtra = (varNum & 0x003F8000) >> 15; // varNum bits 21 to 15 in _lvaExtra bits 6 to 0, 7 bits total
581 _lvaExtra |= (offset << 7); // offset bits 7 to 0 in _lvaExtra bits 14 to 7, 8 bits total
585 // Returns the variable to access. Note that it returns a negative number for compiler spill temps.
586 int emitLclVarAddr::lvaVarNum()
590 case LVA_COMPILER_TEMP:
591 return -((int)_lvaVarNum);
592 case LVA_LARGE_VARNUM:
593 return (int)(((_lvaExtra & 0x007F) << 15) + _lvaVarNum);
594 default: // LVA_STANDARD_ENCODING or LVA_LARGE_OFFSET
595 assert((_lvaTag == LVA_STANDARD_ENCODING) || (_lvaTag == LVA_LARGE_OFFSET));
596 return (int)_lvaVarNum;
600 unsigned emitLclVarAddr::lvaOffset() // returns the offset into the variable to access
604 case LVA_LARGE_OFFSET:
605 return (32768 + _lvaExtra);
606 case LVA_LARGE_VARNUM:
607 return (_lvaExtra & 0x7F80) >> 7;
608 default: // LVA_STANDARD_ENCODING or LVA_COMPILER_TEMP
609 assert((_lvaTag == LVA_STANDARD_ENCODING) || (_lvaTag == LVA_COMPILER_TEMP));
614 /*****************************************************************************
616 * Record some info about the method about to be emitted.
619 void emitter::emitBegCG(Compiler* comp, COMP_HANDLE cmpHandle)
622 emitCmpHandle = cmpHandle;
625 void emitter::emitEndCG()
629 /*****************************************************************************
631 * Prepare the given IG for emission of code.
634 void emitter::emitGenIG(insGroup* ig)
636 /* Set the "current IG" value */
640 #if EMIT_TRACK_STACK_DEPTH
642 /* Record the stack level on entry to this group */
644 ig->igStkLvl = emitCurStackLvl;
646 // If we don't have enough bits in igStkLvl, refuse to compile
648 if (ig->igStkLvl != emitCurStackLvl)
650 IMPL_LIMITATION("Too many arguments pushed on stack");
653 // printf("Start IG #%02u [stk=%02u]\n", ig->igNum, emitCurStackLvl);
659 ig->igFlags |= IGF_NOGCINTERRUPT;
662 /* Prepare to issue instructions */
667 assert(emitCurIGjmpList == nullptr);
669 /* Allocate the temp instruction buffer if we haven't done so */
671 if (emitCurIGfreeBase == nullptr)
673 emitIGbuffSize = SC_IG_BUFFER_SIZE;
674 emitCurIGfreeBase = (BYTE*)emitGetMem(emitIGbuffSize);
677 emitCurIGfreeNext = emitCurIGfreeBase;
678 emitCurIGfreeEndp = emitCurIGfreeBase + emitIGbuffSize;
681 /*****************************************************************************
683 * Finish and save the current IG.
686 insGroup* emitter::emitSavIG(bool emitAdd)
694 assert(emitCurIGfreeNext <= emitCurIGfreeEndp);
696 /* Get hold of the IG descriptor */
701 /* Compute how much code we've generated */
703 sz = emitCurIGfreeNext - emitCurIGfreeBase;
705 /* Compute the total size we need to allocate */
709 /* Do we need space for GC? */
711 if (!(ig->igFlags & IGF_EMIT_ADD))
713 /* Is the initial set of live GC vars different from the previous one? */
715 if (emitForceStoreGCState || !VarSetOps::Equal(emitComp, emitPrevGCrefVars, emitInitGCrefVars))
717 /* Remember that we will have a new set of live GC variables */
719 ig->igFlags |= IGF_GC_VARS;
725 /* We'll allocate extra space to record the liveset */
727 gs += sizeof(VARSET_TP);
730 /* Is the initial set of live Byref regs different from the previous one? */
732 /* Remember that we will have a new set of live GC variables */
734 ig->igFlags |= IGF_BYREF_REGS;
736 /* We'll allocate extra space (DWORD aligned) to record the GC regs */
741 /* Allocate space for the instructions and optional liveset */
743 id = (BYTE*)emitGetMem(gs);
745 /* Do we need to store the byref regs */
747 if (ig->igFlags & IGF_BYREF_REGS)
749 /* Record the byref regs in front the of the instructions */
751 *castto(id, unsigned*)++ = (unsigned)emitInitByrefRegs;
754 /* Do we need to store the liveset? */
756 if (ig->igFlags & IGF_GC_VARS)
758 /* Record the liveset in front the of the instructions */
759 VarSetOps::AssignNoCopy(emitComp, (*castto(id, VARSET_TP*)), VarSetOps::MakeEmpty(emitComp));
760 VarSetOps::Assign(emitComp, (*castto(id, VARSET_TP*)++), emitInitGCrefVars);
763 /* Record the collected instructions */
765 assert((ig->igFlags & IGF_PLACEHOLDER) == 0);
768 memcpy(id, emitCurIGfreeBase, sz);
771 if (false && emitComp->verbose) // this is not useful in normal dumps (hence it is normally under if (false)
773 // If there's an error during emission, we may want to connect the post-copy address
774 // of an instrDesc with the pre-copy address (the one that was originally created). This
775 // printing enables that.
776 printf("copying instruction group from [0x%x..0x%x) to [0x%x..0x%x).\n", dspPtr(emitCurIGfreeBase),
777 dspPtr(emitCurIGfreeBase + sz), dspPtr(id), dspPtr(id + sz));
781 /* Record how many instructions and bytes of code this group contains */
783 noway_assert((BYTE)emitCurIGinsCnt == emitCurIGinsCnt);
784 noway_assert((unsigned short)emitCurIGsize == emitCurIGsize);
786 ig->igInsCnt = (BYTE)emitCurIGinsCnt;
787 ig->igSize = (unsigned short)emitCurIGsize;
788 emitCurCodeOffset += emitCurIGsize;
789 assert(IsCodeAligned(emitCurCodeOffset));
792 emitTotalIGicnt += emitCurIGinsCnt;
793 emitTotalIGsize += sz;
794 emitSizeMethod += sz;
797 // printf("Group [%08X]%3u has %2u instructions (%4u bytes at %08X)\n", ig, ig->igNum, emitCurIGinsCnt, sz, id);
799 /* Record the live GC register set - if and only if it is not an emitter added block */
801 if (!(ig->igFlags & IGF_EMIT_ADD))
803 ig->igGCregs = (regMaskSmall)emitInitGCrefRegs;
808 /* Update the previous recorded live GC ref sets, but not if
809 if we are starting an "overflow" buffer. Note that this is
810 only used to determine whether we need to store or not store
811 the GC ref sets for the next IG, which is dependent on exactly
812 what the state of the emitter GC ref sets will be when the
813 next IG is processed in the emitter.
816 VarSetOps::Assign(emitComp, emitPrevGCrefVars, emitThisGCrefVars);
817 emitPrevGCrefRegs = emitThisGCrefRegs;
818 emitPrevByrefRegs = emitThisByrefRegs;
820 emitForceStoreGCState = false;
824 if (emitComp->opts.dspCode)
826 printf("\n G_M%03u_IG%02u:", Compiler::s_compMethodsCount, ig->igNum);
827 if (emitComp->verbose)
829 printf(" ; offs=%06XH, funclet=%02u", ig->igOffs, ig->igFuncIdx);
833 printf(" ; funclet=%02u", ig->igFuncIdx);
839 /* Did we have any jumps in this group? */
841 if (emitCurIGjmpList)
843 instrDescJmp* list = nullptr;
844 instrDescJmp* last = nullptr;
846 /* Move jumps to the global list, update their 'next' links */
850 /* Grab the jump and remove it from the list */
852 instrDescJmp* oj = emitCurIGjmpList;
853 emitCurIGjmpList = oj->idjNext;
855 /* Figure out the address of where the jump got copied */
857 size_t of = (BYTE*)oj - emitCurIGfreeBase;
858 instrDescJmp* nj = (instrDescJmp*)(ig->igData + of);
860 // printf("Jump moved from %08X to %08X\n", oj, nj);
861 // printf("jmp [%08X] at %08X + %03u\n", nj, ig, nj->idjOffs);
863 assert(nj->idjIG == ig);
864 assert(nj->idIns() == oj->idIns());
865 assert(nj->idjNext == oj->idjNext);
867 /* Make sure the jumps are correctly ordered */
869 assert(last == nullptr || last->idjOffs > nj->idjOffs);
871 if (ig->igFlags & IGF_FUNCLET_PROLOG)
873 // Our funclet prologs have short jumps, if the prolog would ever have
874 // long jumps, then we'd have to insert the list in sorted order than
875 // just append to the emitJumpList.
876 noway_assert(nj->idjShort);
883 /* Append the new jump to the list */
892 } while (emitCurIGjmpList);
896 /* Append the jump(s) from this IG to the global list */
897 bool prologJump = (ig == emitPrologIG);
898 if ((emitJumpList == nullptr) || prologJump)
900 last->idjNext = emitJumpList;
905 last->idjNext = nullptr;
906 emitJumpLast->idjNext = list;
909 if (!prologJump || (emitJumpLast == nullptr))
916 /* Fix the last instruction field */
920 assert(emitLastIns != nullptr);
921 assert(emitCurIGfreeBase <= (BYTE*)emitLastIns);
922 assert((BYTE*)emitLastIns < emitCurIGfreeBase + sz);
923 emitLastIns = (instrDesc*)((BYTE*)id + ((BYTE*)emitLastIns - (BYTE*)emitCurIGfreeBase));
926 /* Reset the buffer free pointers */
928 emitCurIGfreeNext = emitCurIGfreeBase;
933 #ifdef LEGACY_BACKEND
934 void emitter::emitTmpSizeChanged(unsigned tmpSize)
936 assert(emitGrowableMaxByteOffs <= SCHAR_MAX);
939 // Workaround for FP code
940 bool bAssert = JitConfig.JitMaxTempAssert() ? true : false;
942 if (tmpSize > emitMaxTmpSize && bAssert)
944 // TODO-Review: We have a known issue involving floating point code and this assert.
945 // The generated code will be ok, This is only a warning.
946 // To not receive this assert again you can set the registry key: JITMaxTempAssert=0.
948 assert(!"Incorrect max tmp size set.");
952 if (tmpSize <= emitMaxTmpSize)
955 unsigned change = tmpSize - emitMaxTmpSize;
957 /* If we have used a small offset to access a variable, growing the
958 temp size is a problem if we should have used a large offset instead.
959 Detect if such a situation happens and bail */
961 if (emitGrowableMaxByteOffs <= SCHAR_MAX && (emitGrowableMaxByteOffs + change) > SCHAR_MAX)
964 if (emitComp->verbose)
965 printf("Under-estimated var offset encoding size for ins #%Xh\n", emitMaxByteOffsIdNum);
967 IMPL_LIMITATION("Should have used large offset to access var");
970 emitMaxTmpSize = tmpSize;
971 emitGrowableMaxByteOffs += change;
973 #endif // LEGACY_BACKEND
975 /*****************************************************************************
977 * Start generating code to be scheduled; called once per method.
980 void emitter::emitBegFN(bool hasFramePtr
985 #ifdef LEGACY_BACKEND
988 #endif // LEGACY_BACKEND
994 /* Assume we won't need the temp instruction buffer */
996 emitCurIGfreeBase = nullptr;
999 /* Record stack frame info (the temp size is just an estimate) */
1001 emitHasFramePtr = hasFramePtr;
1003 emitMaxTmpSize = maxTmpSize;
1005 #ifdef LEGACY_BACKEND
1006 emitLclSize = lclSize;
1007 emitGrowableMaxByteOffs = 0;
1009 emitMaxByteOffsIdNum = (unsigned)-1;
1011 #endif // LEGACY_BACKEND
1014 emitChkAlign = chkAlign;
1017 /* We have no epilogs yet */
1022 #ifdef _TARGET_XARCH_
1023 emitExitSeqBegLoc.Init();
1024 emitExitSeqSize = INT_MAX;
1025 #endif // _TARGET_XARCH_
1027 emitPlaceholderList = emitPlaceholderLast = nullptr;
1029 #ifdef JIT32_GCENCODER
1030 emitEpilogList = emitEpilogLast = nullptr;
1031 #endif // JIT32_GCENCODER
1033 /* We don't have any jumps */
1035 emitJumpList = emitJumpLast = nullptr;
1036 emitCurIGjmpList = nullptr;
1038 emitFwdJumps = false;
1040 emitForceNewIG = false;
1042 /* We have not recorded any live sets */
1044 assert(VarSetOps::IsEmpty(emitComp, emitThisGCrefVars));
1045 assert(VarSetOps::IsEmpty(emitComp, emitInitGCrefVars));
1046 assert(VarSetOps::IsEmpty(emitComp, emitPrevGCrefVars));
1047 emitThisGCrefRegs = RBM_NONE;
1048 emitInitGCrefRegs = RBM_NONE;
1049 emitPrevGCrefRegs = RBM_NONE;
1050 emitThisByrefRegs = RBM_NONE;
1051 emitInitByrefRegs = RBM_NONE;
1052 emitPrevByrefRegs = RBM_NONE;
1054 emitForceStoreGCState = false;
1058 emitIssuing = false;
1062 /* Assume there will be no GC ref variables */
1064 emitGCrFrameOffsMin = emitGCrFrameOffsMax = emitGCrFrameOffsCnt = 0;
1066 emitGCrFrameLiveTab = nullptr;
1069 /* We have no groups / code at this point */
1071 emitIGlist = emitIGlast = nullptr;
1073 emitCurCodeOffset = 0;
1074 emitFirstColdIG = nullptr;
1075 emitTotalCodeSize = 0;
1084 /* The stack is empty now */
1086 emitCurStackLvl = 0;
1088 #if EMIT_TRACK_STACK_DEPTH
1089 emitMaxStackDepth = 0;
1090 emitCntStackDepth = sizeof(int);
1093 /* No data sections have been created */
1095 emitDataSecCur = nullptr;
1097 memset(&emitConsDsc, 0, sizeof(emitConsDsc));
1099 #ifdef PSEUDORANDOM_NOP_INSERTION
1100 // for random NOP insertion
1102 emitEnableRandomNops();
1103 emitComp->info.compRNG.Init(emitComp->info.compChecksum);
1104 emitNextNop = emitNextRandomNop();
1105 emitInInstrumentation = false;
1106 #endif // PSEUDORANDOM_NOP_INSERTION
1108 /* Create the first IG, it will be used for the prolog */
1112 emitPrologIG = emitIGlist = emitIGlast = emitCurIG = ig = emitAllocIG();
1114 emitLastIns = nullptr;
1116 ig->igNext = nullptr;
1119 emitScratchSigInfo = nullptr;
1122 /* Append another group, to start generating the method body */
1127 #ifdef PSEUDORANDOM_NOP_INSERTION
1128 int emitter::emitNextRandomNop()
1130 return emitComp->info.compRNG.Next(1, 9);
1134 /*****************************************************************************
1136 * Done generating code to be scheduled; called once per method.
1139 void emitter::emitEndFN()
1143 // member function iiaIsJitDataOffset for idAddrUnion, defers to Compiler::eeIsJitDataOffs
1144 bool emitter::instrDesc::idAddrUnion::iiaIsJitDataOffset() const
1146 return Compiler::eeIsJitDataOffs(iiaFieldHnd);
1149 // member function iiaGetJitDataOffset for idAddrUnion, defers to Compiler::eeGetJitDataOffs
1150 int emitter::instrDesc::idAddrUnion::iiaGetJitDataOffset() const
1152 assert(iiaIsJitDataOffset());
1153 return Compiler::eeGetJitDataOffs(iiaFieldHnd);
1156 void emitter::dispIns(instrDesc* id)
1159 emitInsSanityCheck(id);
1161 if (emitComp->opts.dspCode)
1163 emitDispIns(id, true, false, false);
1166 #if EMIT_TRACK_STACK_DEPTH
1167 assert((int)emitCurStackLvl >= 0);
1169 size_t sz = emitSizeOfInsDsc(id);
1170 assert(id->idDebugOnlyInfo()->idSize == sz);
1174 emitIFcounts[id->idInsFmt()]++;
1178 void emitter::appendToCurIG(instrDesc* id)
1180 emitCurIGsize += id->idCodeSize();
1183 /*****************************************************************************
1185 * Display (optionally) an instruction offset.
1190 void emitter::emitDispInsOffs(unsigned offs, bool doffs)
1194 printf("%06X", offs);
1204 #ifdef JIT32_GCENCODER
1206 /*****************************************************************************
1208 * Call the specified function pointer for each epilog block in the current
1209 * method with the epilog's relative code offset. Returns the sum of the
1210 * values returned by the callback.
1213 size_t emitter::emitGenEpilogLst(size_t (*fp)(void*, unsigned), void* cp)
1218 for (el = emitEpilogList, sz = 0; el != nullptr; el = el->elNext)
1220 assert(el->elLoc.GetIG()->igFlags & IGF_EPILOG);
1222 // The epilog starts at the location recorded in the epilog list.
1223 sz += fp(cp, el->elLoc.CodeOffset(this));
1229 #endif // JIT32_GCENCODER
1231 /*****************************************************************************
1233 * The following series of methods allocates instruction descriptors.
1236 void* emitter::emitAllocInstr(size_t sz, emitAttr opsz)
1241 // Under STRESS_EMITTER, put every instruction in its own instruction group.
1242 // We can't do this for a prolog, epilog, funclet prolog, or funclet epilog,
1243 // because those are generated out of order. We currently have a limitation
1244 // where the jump shortening pass uses the instruction group number to determine
1245 // if something is earlier or later in the code stream. This implies that
1246 // these groups cannot be more than a single instruction group. Note that
1247 // the prolog/epilog placeholder groups ARE generated in order, and are
1248 // re-used. But generating additional groups would not work.
1249 if (emitComp->compStressCompile(Compiler::STRESS_EMITTER, 1) && emitCurIGinsCnt && !emitIGisInProlog(emitCurIG) &&
1250 !emitIGisInEpilog(emitCurIG)
1251 #if FEATURE_EH_FUNCLETS
1252 && !emitIGisInFuncletProlog(emitCurIG) && !emitIGisInFuncletEpilog(emitCurIG)
1253 #endif // FEATURE_EH_FUNCLETS
1260 #ifdef PSEUDORANDOM_NOP_INSERTION
1261 // TODO-ARM-Bug?: PSEUDORANDOM_NOP_INSERTION is not defined for _TARGET_ARM_
1262 // ARM - This is currently broken on _TARGET_ARM_
1263 // When nopSize is odd we misalign emitCurIGsize
1265 if (!emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && !emitInInstrumentation &&
1266 !emitIGisInProlog(emitCurIG) && // don't do this in prolog or epilog
1267 !emitIGisInEpilog(emitCurIG) &&
1268 emitRandomNops // sometimes we turn off where exact codegen is needed (pinvoke inline)
1271 if (emitNextNop == 0)
1274 emitInInstrumentation = true;
1275 instrDesc* idnop = emitNewInstr();
1276 emitInInstrumentation = false;
1277 idnop->idInsFmt(IF_NONE);
1278 idnop->idIns(INS_nop);
1279 #if defined(_TARGET_XARCH_)
1280 idnop->idCodeSize(nopSize);
1282 #error "Undefined target for pseudorandom NOP insertion"
1285 emitCurIGsize += nopSize;
1286 emitNextNop = emitNextRandomNop();
1291 #endif // PSEUDORANDOM_NOP_INSERTION
1293 assert(IsCodeAligned(emitCurIGsize));
1295 /* Make sure we have enough space for the new instruction */
1297 if ((emitCurIGfreeNext + sz >= emitCurIGfreeEndp) || emitForceNewIG)
1302 /* Grab the space for the instruction */
1304 emitLastIns = id = (instrDesc*)emitCurIGfreeNext;
1305 emitCurIGfreeNext += sz;
1307 assert(sz >= sizeof(void*));
1310 // These fields should have been zero-ed by the above
1311 assert(id->idReg1() == regNumber(0));
1312 assert(id->idReg2() == regNumber(0));
1313 #ifdef _TARGET_XARCH_
1314 assert(id->idCodeSize() == 0);
1318 /* Is the second area to be cleared actually present? */
1319 if (sz >= SMALL_IDSC_SIZE)
1321 /* Clear the second 4 bytes, or the 'SMALL' part */
1322 *(int*)((BYTE*)id + (SMALL_IDSC_SIZE - sizeof(int))) = 0;
1324 // These fields should have been zero-ed by the above
1325 assert(id->idIsLargeCns() == false);
1326 assert(id->idIsLargeDsp() == false);
1327 assert(id->idIsLargeCall() == false);
1331 // Make sure that idAddrUnion is just a union of various pointer sized things
1332 C_ASSERT(sizeof(CORINFO_FIELD_HANDLE) <= sizeof(void*));
1333 C_ASSERT(sizeof(CORINFO_METHOD_HANDLE) <= sizeof(void*));
1334 C_ASSERT(sizeof(emitter::emitAddrMode) <= sizeof(void*));
1335 C_ASSERT(sizeof(emitLclVarAddr) <= sizeof(void*));
1336 C_ASSERT(sizeof(emitter::instrDesc) == (SMALL_IDSC_SIZE + sizeof(void*)));
1341 /* In debug mode we clear/set some additional fields */
1343 instrDescDebugInfo* info = (instrDescDebugInfo*)emitGetMem(sizeof(*info));
1345 info->idNum = emitInsCount;
1347 info->idVarRefOffs = 0;
1348 info->idMemCookie = 0;
1349 #ifdef TRANSLATE_PDB
1350 info->idilStart = emitInstrDescILBase;
1352 info->idFinallyCall = false;
1353 info->idCatchRet = false;
1354 info->idCallSig = nullptr;
1356 id->idDebugOnlyInfo(info);
1358 #endif // defined(DEBUG)
1360 /* Store the size and handle the two special values
1361 that indicate GCref and ByRef */
1363 if (EA_IS_GCREF(opsz))
1365 /* A special value indicates a GCref pointer value */
1367 id->idGCref(GCT_GCREF);
1368 id->idOpSize(EA_PTRSIZE);
1370 else if (EA_IS_BYREF(opsz))
1372 /* A special value indicates a Byref pointer value */
1374 id->idGCref(GCT_BYREF);
1375 id->idOpSize(EA_PTRSIZE);
1379 id->idGCref(GCT_NONE);
1380 id->idOpSize(EA_SIZE(opsz));
1383 // Amd64: ip-relative addressing is supported even when not generating relocatable ngen code
1384 if (EA_IS_DSP_RELOC(opsz)
1385 #ifndef _TARGET_AMD64_
1386 && emitComp->opts.compReloc
1387 #endif //_TARGET_AMD64_
1390 /* Mark idInfo()->idDspReloc to remember that the */
1391 /* address mode has a displacement that is relocatable */
1392 id->idSetIsDspReloc();
1395 if (EA_IS_CNS_RELOC(opsz) && emitComp->opts.compReloc)
1397 /* Mark idInfo()->idCnsReloc to remember that the */
1398 /* instruction has an immediate constant that is relocatable */
1399 id->idSetIsCnsReloc();
1406 /* Update the instruction count */
1415 /*****************************************************************************
1417 * Make sure the code offsets of all instruction groups look reasonable.
1419 void emitter::emitCheckIGoffsets()
1424 for (tempIG = emitIGlist, offsIG = 0; tempIG; tempIG = tempIG->igNext)
1426 if (tempIG->igOffs != offsIG)
1428 printf("Block #%u has offset %08X, expected %08X\n", tempIG->igNum, tempIG->igOffs, offsIG);
1429 assert(!"bad block offset");
1432 offsIG += tempIG->igSize;
1435 if (emitTotalCodeSize && emitTotalCodeSize != offsIG)
1437 printf("Total code size is %08X, expected %08X\n", emitTotalCodeSize, offsIG);
1439 assert(!"bad total code size");
1445 /*****************************************************************************
1447 * Begin generating a method prolog.
1450 void emitter::emitBegProlog()
1452 assert(emitComp->compGeneratingProlog);
1454 #if EMIT_TRACK_STACK_DEPTH
1456 /* Don't measure stack depth inside the prolog, it's misleading */
1458 emitCntStackDepth = 0;
1460 assert(emitCurStackLvl == 0);
1465 emitForceNewIG = false;
1467 /* Switch to the pre-allocated prolog IG */
1469 emitGenIG(emitPrologIG);
1471 /* Nothing is live on entry to the prolog */
1473 // These were initialized to Empty at the start of compilation.
1474 VarSetOps::ClearD(emitComp, emitInitGCrefVars);
1475 VarSetOps::ClearD(emitComp, emitPrevGCrefVars);
1476 emitInitGCrefRegs = RBM_NONE;
1477 emitPrevGCrefRegs = RBM_NONE;
1478 emitInitByrefRegs = RBM_NONE;
1479 emitPrevByrefRegs = RBM_NONE;
1482 /*****************************************************************************
1484 * Return the code offset of the current location in the prolog.
1487 unsigned emitter::emitGetPrologOffsetEstimate()
1489 /* For now only allow a single prolog ins group */
1491 assert(emitPrologIG);
1492 assert(emitPrologIG == emitCurIG);
1494 return emitCurIGsize;
1497 /*****************************************************************************
1499 * Mark the code offset of the current location as the end of the prolog,
1500 * so it can be used later to compute the actual size of the prolog.
1503 void emitter::emitMarkPrologEnd()
1505 assert(emitComp->compGeneratingProlog);
1507 /* For now only allow a single prolog ins group */
1509 assert(emitPrologIG);
1510 assert(emitPrologIG == emitCurIG);
1512 emitPrologEndPos = emitCurOffset();
1515 /*****************************************************************************
1517 * Finish generating a method prolog.
1520 void emitter::emitEndProlog()
1522 assert(emitComp->compGeneratingProlog);
1526 /* Save the prolog IG if non-empty or if only one block */
1528 if (emitCurIGnonEmpty() || emitCurIG == emitPrologIG)
1533 #if EMIT_TRACK_STACK_DEPTH
1534 /* Reset the stack depth values */
1536 emitCurStackLvl = 0;
1537 emitCntStackDepth = sizeof(int);
1541 /*****************************************************************************
1543 * Create a placeholder instruction group to be used by a prolog or epilog,
1544 * either for the main function, or a funclet.
1547 void emitter::emitCreatePlaceholderIG(insGroupPlaceholderType igType,
1549 VARSET_VALARG_TP GCvars,
1550 regMaskTP gcrefRegs,
1551 regMaskTP byrefRegs,
1554 assert(igBB != nullptr);
1556 bool emitAdd = false;
1558 if (igType == IGPT_EPILOG
1559 #if FEATURE_EH_FUNCLETS
1560 || igType == IGPT_FUNCLET_EPILOG
1561 #endif // FEATURE_EH_FUNCLETS
1564 #ifdef _TARGET_AMD64_
1565 emitOutputPreEpilogNOP();
1566 #endif // _TARGET_AMD64_
1571 if (emitCurIGnonEmpty())
1576 /* Update GC tracking for the beginning of the placeholder IG */
1580 VarSetOps::Assign(emitComp, emitThisGCrefVars, GCvars);
1581 VarSetOps::Assign(emitComp, emitInitGCrefVars, GCvars);
1582 emitThisGCrefRegs = emitInitGCrefRegs = gcrefRegs;
1583 emitThisByrefRegs = emitInitByrefRegs = byrefRegs;
1586 /* Convert the group to a placeholder group */
1588 insGroup* igPh = emitCurIG;
1590 igPh->igFlags |= IGF_PLACEHOLDER;
1592 /* Note that we might be re-using a previously created but empty IG. In this
1593 * case, we need to make sure any re-used fields, such as igFuncIdx, are correct.
1596 igPh->igFuncIdx = emitComp->compCurrFuncIdx;
1598 /* Create a separate block of memory to store placeholder information.
1599 * We could use unions to put some of this into the insGroup itself, but we don't
1600 * want to grow the insGroup, and it's difficult to make sure the
1601 * insGroup fields are getting set and used elsewhere.
1604 igPh->igPhData = new (emitComp, CMK_InstDesc) insPlaceholderGroupData;
1606 igPh->igPhData->igPhNext = nullptr;
1607 igPh->igPhData->igPhType = igType;
1608 igPh->igPhData->igPhBB = igBB;
1610 VarSetOps::AssignNoCopy(emitComp, igPh->igPhData->igPhPrevGCrefVars, VarSetOps::UninitVal());
1611 VarSetOps::Assign(emitComp, igPh->igPhData->igPhPrevGCrefVars, emitPrevGCrefVars);
1612 igPh->igPhData->igPhPrevGCrefRegs = emitPrevGCrefRegs;
1613 igPh->igPhData->igPhPrevByrefRegs = emitPrevByrefRegs;
1615 VarSetOps::AssignNoCopy(emitComp, igPh->igPhData->igPhInitGCrefVars, VarSetOps::UninitVal());
1616 VarSetOps::Assign(emitComp, igPh->igPhData->igPhInitGCrefVars, emitInitGCrefVars);
1617 igPh->igPhData->igPhInitGCrefRegs = emitInitGCrefRegs;
1618 igPh->igPhData->igPhInitByrefRegs = emitInitByrefRegs;
1621 emitTotalPhIGcnt += 1;
1624 // Mark function prologs and epilogs properly in the igFlags bits. These bits
1625 // will get used and propagated when the placeholder is converted to a non-placeholder
1626 // during prolog/epilog generation.
1628 if (igType == IGPT_EPILOG)
1630 igPh->igFlags |= IGF_EPILOG;
1632 #if FEATURE_EH_FUNCLETS
1633 else if (igType == IGPT_FUNCLET_PROLOG)
1635 igPh->igFlags |= IGF_FUNCLET_PROLOG;
1637 else if (igType == IGPT_FUNCLET_EPILOG)
1639 igPh->igFlags |= IGF_FUNCLET_EPILOG;
1641 #endif // FEATURE_EH_FUNCLETS
1643 /* Link it into the placeholder list */
1645 if (emitPlaceholderList)
1647 emitPlaceholderLast->igPhData->igPhNext = igPh;
1651 emitPlaceholderList = igPh;
1654 emitPlaceholderLast = igPh;
1656 // Give an estimated size of this placeholder IG and
1657 // increment emitCurCodeOffset since we are not calling emitNewIG()
1659 emitCurIGsize += MAX_PLACEHOLDER_IG_SIZE;
1660 emitCurCodeOffset += emitCurIGsize;
1662 #if FEATURE_EH_FUNCLETS
1663 // Add the appropriate IP mapping debugging record for this placeholder
1664 // group. genExitCode() adds the mapping for main function epilogs.
1665 if (emitComp->opts.compDbgInfo)
1667 if (igType == IGPT_FUNCLET_PROLOG)
1669 codeGen->genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::PROLOG, true);
1671 else if (igType == IGPT_FUNCLET_EPILOG)
1673 codeGen->genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::EPILOG, true);
1676 #endif // FEATURE_EH_FUNCLETS
1678 /* Start a new IG if more code follows */
1682 emitCurIG = nullptr;
1686 if (igType == IGPT_EPILOG
1687 #if FEATURE_EH_FUNCLETS
1688 || igType == IGPT_FUNCLET_EPILOG
1689 #endif // FEATURE_EH_FUNCLETS
1692 // If this was an epilog, then assume this is the end of any currently in progress
1693 // no-GC region. If a block after the epilog needs to be no-GC, it needs to call
1694 // emitter::emitDisableGC() directly. This behavior is depended upon by the fast
1695 // tailcall implementation, which disables GC at the beginning of argument setup,
1696 // but assumes that after the epilog it will be re-enabled.
1702 // We don't know what the GC ref state will be at the end of the placeholder
1703 // group. So, force the next IG to store all the GC ref state variables;
1704 // don't omit them because emitPrev* is the same as emitInit*, because emitPrev*
1705 // will be inaccurate. (Note that, currently, GCrefRegs and ByrefRegs are always
1708 // There is no need to re-initialize the emitPrev* variables, as they won't be used
1709 // with emitForceStoreGCState==true, and will be re-initialized just before
1710 // emitForceStoreGCState is set to false;
1712 emitForceStoreGCState = true;
1714 /* The group after the placeholder group doesn't get the "propagate" flags */
1716 emitCurIG->igFlags &= ~IGF_PROPAGATE_MASK;
1720 if (emitComp->verbose)
1722 printf("*************** After placeholder IG creation\n");
1723 emitDispIGlist(false);
1728 /*****************************************************************************
1730 * Generate all prologs and epilogs
1733 void emitter::emitGeneratePrologEpilog()
1736 unsigned prologCnt = 0;
1737 unsigned epilogCnt = 0;
1738 #if FEATURE_EH_FUNCLETS
1739 unsigned funcletPrologCnt = 0;
1740 unsigned funcletEpilogCnt = 0;
1741 #endif // FEATURE_EH_FUNCLETS
1747 // Generating the prolog/epilog is going to destroy the placeholder group,
1748 // so save the "next" pointer before that happens.
1750 for (igPh = emitPlaceholderList; igPh != nullptr; igPh = igPhNext)
1752 assert(igPh->igFlags & IGF_PLACEHOLDER);
1754 igPhNext = igPh->igPhData->igPhNext;
1756 BasicBlock* igPhBB = igPh->igPhData->igPhBB;
1758 switch (igPh->igPhData->igPhType)
1760 case IGPT_PROLOG: // currently unused
1761 INDEBUG(++prologCnt);
1765 INDEBUG(++epilogCnt);
1766 emitBegFnEpilog(igPh);
1767 codeGen->genFnEpilog(igPhBB);
1771 #if FEATURE_EH_FUNCLETS
1773 case IGPT_FUNCLET_PROLOG:
1774 INDEBUG(++funcletPrologCnt);
1775 emitBegFuncletProlog(igPh);
1776 codeGen->genFuncletProlog(igPhBB);
1777 emitEndFuncletProlog();
1780 case IGPT_FUNCLET_EPILOG:
1781 INDEBUG(++funcletEpilogCnt);
1782 emitBegFuncletEpilog(igPh);
1783 codeGen->genFuncletEpilog();
1784 emitEndFuncletEpilog();
1787 #endif // FEATURE_EH_FUNCLETS
1795 if (emitComp->verbose)
1797 printf("%d prologs, %d epilogs", prologCnt, epilogCnt);
1798 #if FEATURE_EH_FUNCLETS
1799 printf(", %d funclet prologs, %d funclet epilogs", funcletPrologCnt, funcletEpilogCnt);
1800 #endif // FEATURE_EH_FUNCLETS
1803 // prolog/epilog code doesn't use this yet
1804 // noway_assert(prologCnt == 1);
1805 // noway_assert(epilogCnt == emitEpilogCnt); // Is this correct?
1806 #if FEATURE_EH_FUNCLETS
1807 assert(funcletPrologCnt == emitComp->ehFuncletCount());
1808 #endif // FEATURE_EH_FUNCLETS
1813 /*****************************************************************************
1815 * Begin all prolog and epilog generation
1818 void emitter::emitStartPrologEpilogGeneration()
1820 /* Save the current IG if it's non-empty */
1822 if (emitCurIGnonEmpty())
1828 assert(emitCurIG == nullptr);
1832 /*****************************************************************************
1834 * Finish all prolog and epilog generation
1837 void emitter::emitFinishPrologEpilogGeneration()
1839 /* Update the offsets of all the blocks */
1841 emitRecomputeIGoffsets();
1843 /* We should not generate any more code after this */
1845 emitCurIG = nullptr;
1848 /*****************************************************************************
1850 * Common code for prolog / epilog beginning. Convert the placeholder group to actual code IG,
1851 * and set it as the current group.
1854 void emitter::emitBegPrologEpilog(insGroup* igPh)
1856 assert(igPh->igFlags & IGF_PLACEHOLDER);
1858 /* Save the current IG if it's non-empty */
1860 if (emitCurIGnonEmpty())
1865 /* Convert the placeholder group to a normal group.
1866 * We need to be very careful to re-initialize the IG properly.
1867 * It turns out, this means we only need to clear the placeholder bit
1868 * and clear the igPhData field, and emitGenIG() will do the rest,
1869 * since in the placeholder IG we didn't touch anything that is set by emitAllocIG().
1872 igPh->igFlags &= ~IGF_PLACEHOLDER;
1874 emitForceNewIG = false;
1876 /* Set up the GC info that we stored in the placeholder */
1878 VarSetOps::Assign(emitComp, emitPrevGCrefVars, igPh->igPhData->igPhPrevGCrefVars);
1879 emitPrevGCrefRegs = igPh->igPhData->igPhPrevGCrefRegs;
1880 emitPrevByrefRegs = igPh->igPhData->igPhPrevByrefRegs;
1882 VarSetOps::Assign(emitComp, emitThisGCrefVars, igPh->igPhData->igPhInitGCrefVars);
1883 VarSetOps::Assign(emitComp, emitInitGCrefVars, igPh->igPhData->igPhInitGCrefVars);
1884 emitThisGCrefRegs = emitInitGCrefRegs = igPh->igPhData->igPhInitGCrefRegs;
1885 emitThisByrefRegs = emitInitByrefRegs = igPh->igPhData->igPhInitByrefRegs;
1887 igPh->igPhData = nullptr;
1889 /* Create a non-placeholder group pointer that we'll now use */
1891 insGroup* ig = igPh;
1893 /* Set the current function using the function index we stored */
1895 emitComp->funSetCurrentFunc(ig->igFuncIdx);
1897 /* Set the new IG as the place to generate code */
1901 #if EMIT_TRACK_STACK_DEPTH
1903 /* Don't measure stack depth inside the prolog / epilog, it's misleading */
1905 emitCntStackDepth = 0;
1907 assert(emitCurStackLvl == 0);
1912 /*****************************************************************************
1914 * Common code for end of prolog / epilog
1917 void emitter::emitEndPrologEpilog()
1921 /* Save the IG if non-empty */
1923 if (emitCurIGnonEmpty())
1928 assert(emitCurIGsize <= MAX_PLACEHOLDER_IG_SIZE);
1930 #if EMIT_TRACK_STACK_DEPTH
1931 /* Reset the stack depth values */
1933 emitCurStackLvl = 0;
1934 emitCntStackDepth = sizeof(int);
1938 /*****************************************************************************
1940 * Begin generating a main function epilog.
1943 void emitter::emitBegFnEpilog(insGroup* igPh)
1947 emitBegPrologEpilog(igPh);
1949 #ifdef JIT32_GCENCODER
1951 EpilogList* el = new (emitComp, CMK_GC) EpilogList();
1953 if (emitEpilogLast != nullptr)
1955 emitEpilogLast->elNext = el;
1959 emitEpilogList = el;
1962 emitEpilogLast = el;
1964 #endif // JIT32_GCENCODER
1967 /*****************************************************************************
1969 * Finish generating a funclet epilog.
1972 void emitter::emitEndFnEpilog()
1974 emitEndPrologEpilog();
1976 #ifdef JIT32_GCENCODER
1977 assert(emitEpilogLast != nullptr);
1979 UNATIVE_OFFSET epilogBegCodeOffset = emitEpilogLast->elLoc.CodeOffset(this);
1980 UNATIVE_OFFSET epilogExitSeqStartCodeOffset = emitExitSeqBegLoc.CodeOffset(this);
1981 UNATIVE_OFFSET newSize = epilogExitSeqStartCodeOffset - epilogBegCodeOffset;
1983 /* Compute total epilog size */
1984 assert(emitEpilogSize == 0 || emitEpilogSize == newSize); // All epilogs must be identical
1985 emitEpilogSize = newSize;
1987 UNATIVE_OFFSET epilogEndCodeOffset = emitCodeOffset(emitCurIG, emitCurOffset());
1988 assert(epilogExitSeqStartCodeOffset != epilogEndCodeOffset);
1990 newSize = epilogEndCodeOffset - epilogExitSeqStartCodeOffset;
1991 if (newSize < emitExitSeqSize)
1993 // We expect either the epilog to be the same every time, or that
1994 // one will be a ret or a ret <n> and others will be a jmp addr or jmp [addr];
1995 // we make the epilogs the minimum of these. Note that this ONLY works
1996 // because the only instruction is the last one and thus a slight
1997 // underestimation of the epilog size is harmless (since the EIP
1998 // can not be between instructions).
1999 assert(emitEpilogCnt == 1 ||
2000 (emitExitSeqSize - newSize) <= 5 // delta between size of various forms of jmp (size is either 6 or 5)
2001 // and various forms of ret (size is either 1 or 3). The combination can
2002 // be anything been 1 and 5.
2004 emitExitSeqSize = newSize;
2006 #endif // JIT32_GCENCODER
2009 #if FEATURE_EH_FUNCLETS
2011 /*****************************************************************************
2013 * Begin generating a funclet prolog.
2016 void emitter::emitBegFuncletProlog(insGroup* igPh)
2018 emitBegPrologEpilog(igPh);
2021 /*****************************************************************************
2023 * Finish generating a funclet prolog.
2026 void emitter::emitEndFuncletProlog()
2028 emitEndPrologEpilog();
2031 /*****************************************************************************
2033 * Begin generating a funclet epilog.
2036 void emitter::emitBegFuncletEpilog(insGroup* igPh)
2038 emitBegPrologEpilog(igPh);
2041 /*****************************************************************************
2043 * Finish generating a funclet epilog.
2046 void emitter::emitEndFuncletEpilog()
2048 emitEndPrologEpilog();
2051 #endif // FEATURE_EH_FUNCLETS
2053 #ifdef JIT32_GCENCODER
2056 // emitter::emitStartEpilog:
2057 // Mark the current position so that we can later compute the total epilog size.
2059 void emitter::emitStartEpilog()
2061 assert(emitEpilogLast != nullptr);
2062 emitEpilogLast->elLoc.CaptureLocation(this);
2065 /*****************************************************************************
2067 * Return non-zero if the current method only has one epilog, which is
2068 * at the very end of the method body.
2071 bool emitter::emitHasEpilogEnd()
2073 if (emitEpilogCnt == 1 && (emitIGlast->igFlags & IGF_EPILOG)) // This wouldn't work for funclets
2079 #endif // JIT32_GCENCODER
2081 #ifdef _TARGET_XARCH_
2083 /*****************************************************************************
2085 * Mark the beginning of the epilog exit sequence by remembering our position.
2088 void emitter::emitStartExitSeq()
2090 assert(emitComp->compGeneratingEpilog);
2092 emitExitSeqBegLoc.CaptureLocation(this);
2095 #endif // _TARGET_XARCH_
2097 /*****************************************************************************
2099 * The code generator tells us the range of GC ref locals through this
2100 * method. Needless to say, locals and temps should be allocated so that
2101 * the size of the range is as small as possible.
2103 * offsLo - The FP offset from which the GC pointer range starts.
2104 * offsHi - The FP offset at which the GC pointer region ends (exclusive).
2107 void emitter::emitSetFrameRangeGCRs(int offsLo, int offsHi)
2109 assert(emitComp->compGeneratingProlog);
2110 assert(offsHi > offsLo);
2114 // A total of 47254 methods compiled.
2116 // GC ref frame variable counts:
2118 // <= 0 ===> 43175 count ( 91% of total)
2119 // 1 .. 1 ===> 2367 count ( 96% of total)
2120 // 2 .. 2 ===> 887 count ( 98% of total)
2121 // 3 .. 5 ===> 579 count ( 99% of total)
2122 // 6 .. 10 ===> 141 count ( 99% of total)
2123 // 11 .. 20 ===> 40 count ( 99% of total)
2124 // 21 .. 50 ===> 42 count ( 99% of total)
2125 // 51 .. 128 ===> 15 count ( 99% of total)
2126 // 129 .. 256 ===> 4 count ( 99% of total)
2127 // 257 .. 512 ===> 4 count (100% of total)
2128 // 513 .. 1024 ===> 0 count (100% of total)
2130 if (emitComp->verbose)
2132 unsigned count = (offsHi - offsLo) / TARGET_POINTER_SIZE;
2133 printf("%u tracked GC refs are at stack offsets ", count);
2137 printf(" %04X ... %04X\n", offsLo, offsHi);
2138 assert(offsHi >= 0);
2141 #if defined(_TARGET_ARM_) && defined(PROFILING_SUPPORTED)
2142 if (!emitComp->compIsProfilerHookNeeded())
2145 #ifdef _TARGET_AMD64_
2146 // doesn't have to be all negative on amd
2147 printf("-%04X ... %04X\n", -offsLo, offsHi);
2149 printf("-%04X ... -%04X\n", -offsLo, -offsHi);
2150 assert(offsHi <= 0);
2153 #if defined(_TARGET_ARM_) && defined(PROFILING_SUPPORTED)
2156 // Under profiler due to prespilling of arguments, offHi need not be < 0
2158 printf("-%04X ... -%04X\n", -offsLo, -offsHi);
2160 printf("-%04X ... %04X\n", -offsLo, offsHi);
2167 assert(((offsHi - offsLo) % TARGET_POINTER_SIZE) == 0);
2168 assert((offsLo % TARGET_POINTER_SIZE) == 0);
2169 assert((offsHi % TARGET_POINTER_SIZE) == 0);
2171 emitGCrFrameOffsMin = offsLo;
2172 emitGCrFrameOffsMax = offsHi;
2173 emitGCrFrameOffsCnt = (offsHi - offsLo) / TARGET_POINTER_SIZE;
2176 /*****************************************************************************
2178 * The code generator tells us the range of local variables through this
2182 void emitter::emitSetFrameRangeLcls(int offsLo, int offsHi)
2186 /*****************************************************************************
2188 * The code generator tells us the range of used arguments through this
2192 void emitter::emitSetFrameRangeArgs(int offsLo, int offsHi)
2196 /*****************************************************************************
2198 * A conversion table used to map an operand size value (in bytes) into its
2199 * small encoding (0 through 3), and vice versa.
2202 const emitter::opSize emitter::emitSizeEncode[] = {
2203 emitter::OPSZ1, emitter::OPSZ2, OPSIZE_INVALID, emitter::OPSZ4, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2204 emitter::OPSZ8, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2205 OPSIZE_INVALID, emitter::OPSZ16, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2206 OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2207 OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, emitter::OPSZ32,
2210 const emitAttr emitter::emitSizeDecode[emitter::OPSZ_COUNT] = {EA_1BYTE, EA_2BYTE, EA_4BYTE,
2211 EA_8BYTE, EA_16BYTE, EA_32BYTE};
2213 /*****************************************************************************
2215 * Allocate an instruction descriptor for an instruction that uses both
2216 * a displacement and a constant.
2219 emitter::instrDesc* emitter::emitNewInstrCnsDsp(emitAttr size, ssize_t cns, int dsp)
2223 if (instrDesc::fitsInSmallCns(cns))
2225 instrDesc* id = emitAllocInstr(size);
2227 id->idSmallCns(cns);
2231 emitSmallCns[cns - ID_MIN_SMALL_CNS]++;
2239 instrDescCns* id = emitAllocInstrCns(size);
2241 id->idSetIsLargeCns();
2242 id->idcCnsVal = cns;
2254 if (instrDesc::fitsInSmallCns(cns))
2256 instrDescDsp* id = emitAllocInstrDsp(size);
2258 id->idSetIsLargeDsp();
2259 id->iddDspVal = dsp;
2261 id->idSmallCns(cns);
2266 emitSmallCns[cns - ID_MIN_SMALL_CNS]++;
2273 instrDescCnsDsp* id = emitAllocInstrCnsDsp(size);
2275 id->idSetIsLargeCns();
2276 id->iddcCnsVal = cns;
2278 id->idSetIsLargeDsp();
2279 id->iddcDspVal = dsp;
2291 /*****************************************************************************
2293 * Returns true if garbage-collection won't happen within the helper call.
2294 * Don't need to record live pointers for such call sites.
2297 bool emitter::emitNoGChelper(unsigned IHX)
2299 // TODO-Throughput: Make this faster (maybe via a simple table of bools?)
2303 case CORINFO_HELP_UNDEF:
2306 case CORINFO_HELP_PROF_FCN_LEAVE:
2307 case CORINFO_HELP_PROF_FCN_ENTER:
2308 #if defined(_TARGET_AMD64_) || (defined(_TARGET_X86_) && !defined(LEGACY_BACKEND))
2309 case CORINFO_HELP_PROF_FCN_TAILCALL:
2311 case CORINFO_HELP_LLSH:
2312 case CORINFO_HELP_LRSH:
2313 case CORINFO_HELP_LRSZ:
2315 // case CORINFO_HELP_LMUL:
2316 // case CORINFO_HELP_LDIV:
2317 // case CORINFO_HELP_LMOD:
2318 // case CORINFO_HELP_ULDIV:
2319 // case CORINFO_HELP_ULMOD:
2322 case CORINFO_HELP_ASSIGN_REF_EAX:
2323 case CORINFO_HELP_ASSIGN_REF_ECX:
2324 case CORINFO_HELP_ASSIGN_REF_EBX:
2325 case CORINFO_HELP_ASSIGN_REF_EBP:
2326 case CORINFO_HELP_ASSIGN_REF_ESI:
2327 case CORINFO_HELP_ASSIGN_REF_EDI:
2329 case CORINFO_HELP_CHECKED_ASSIGN_REF_EAX:
2330 case CORINFO_HELP_CHECKED_ASSIGN_REF_ECX:
2331 case CORINFO_HELP_CHECKED_ASSIGN_REF_EBX:
2332 case CORINFO_HELP_CHECKED_ASSIGN_REF_EBP:
2333 case CORINFO_HELP_CHECKED_ASSIGN_REF_ESI:
2334 case CORINFO_HELP_CHECKED_ASSIGN_REF_EDI:
2337 case CORINFO_HELP_ASSIGN_REF:
2338 case CORINFO_HELP_CHECKED_ASSIGN_REF:
2339 case CORINFO_HELP_ASSIGN_BYREF:
2341 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
2342 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
2344 case CORINFO_HELP_INIT_PINVOKE_FRAME:
2352 /*****************************************************************************
2354 * Mark the current spot as having a label.
2357 void* emitter::emitAddLabel(VARSET_VALARG_TP GCvars, regMaskTP gcrefRegs, regMaskTP byrefRegs, BOOL isFinallyTarget)
2359 /* Create a new IG if the current one is non-empty */
2361 if (emitCurIGnonEmpty())
2366 VarSetOps::Assign(emitComp, emitThisGCrefVars, GCvars);
2367 VarSetOps::Assign(emitComp, emitInitGCrefVars, GCvars);
2368 emitThisGCrefRegs = emitInitGCrefRegs = gcrefRegs;
2369 emitThisByrefRegs = emitInitByrefRegs = byrefRegs;
2371 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2372 if (isFinallyTarget)
2374 emitCurIG->igFlags |= IGF_FINALLY_TARGET;
2376 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2379 if (EMIT_GC_VERBOSE)
2381 printf("Label: IG%02u, GCvars=%s ", emitCurIG->igNum, VarSetOps::ToString(emitComp, GCvars));
2382 dumpConvertedVarSet(emitComp, GCvars);
2383 printf(", gcrefRegs=");
2384 printRegMaskInt(gcrefRegs);
2385 emitDispRegSet(gcrefRegs);
2386 printf(", byrefRegs=");
2387 printRegMaskInt(byrefRegs);
2388 emitDispRegSet(byrefRegs);
2395 #ifdef _TARGET_ARMARCH_
2397 // Does the argument location point to an IG at the end of a function or funclet?
2398 // We can ignore the codePos part of the location, since it doesn't affect the
2399 // determination. If 'emitLocNextFragment' is non-NULL, it indicates the first
2400 // IG of the next fragment, so it represents a function end.
2401 bool emitter::emitIsFuncEnd(emitLocation* emitLoc, emitLocation* emitLocNextFragment /* = NULL */)
2405 insGroup* ig = emitLoc->GetIG();
2408 // Are we at the end of the IG list?
2409 if ((emitLocNextFragment != NULL) && (ig->igNext == emitLocNextFragment->GetIG()))
2413 if (ig->igNext == NULL)
2416 // Is the next IG the start of a funclet prolog?
2417 if (ig->igNext->igFlags & IGF_FUNCLET_PROLOG)
2420 #if FEATURE_EH_FUNCLETS
2422 // Is the next IG a placeholder group for a funclet prolog?
2423 if ((ig->igNext->igFlags & IGF_PLACEHOLDER) && (ig->igNext->igPhData->igPhType == IGPT_FUNCLET_PROLOG))
2428 #endif // FEATURE_EH_FUNCLETS
2433 /*****************************************************************************
2435 * Split the region from 'startLoc' to 'endLoc' into fragments by calling
2436 * a callback function to indicate the beginning of a fragment. The initial code,
2437 * starting at 'startLoc', doesn't get a callback, but the first code fragment,
2438 * about 'maxSplitSize' bytes out does, as does the beginning of each fragment
2439 * after that. There is no callback for the end (only the beginning of the last
2440 * fragment gets a callback). A fragment must contain at least one instruction
2441 * group. It should be smaller than 'maxSplitSize', although it may be larger to
2442 * satisfy the "at least one instruction group" rule. Do not split prologs or
2443 * epilogs. (Currently, prologs exist in a single instruction group at the main
2444 * function beginning, so they aren't split. Funclets, however, might span IGs,
2445 * so we can't split in between them.)
2447 * Note that the locations must be the start of instruction groups; the part of
2448 * the location indicating offset within a group must be zero.
2450 * If 'startLoc' is NULL, it means the start of the code.
2451 * If 'endLoc' is NULL, it means the end of the code.
2454 void emitter::emitSplit(emitLocation* startLoc,
2455 emitLocation* endLoc,
2456 UNATIVE_OFFSET maxSplitSize,
2458 emitSplitCallbackType callbackFunc)
2460 insGroup* igStart = (startLoc == NULL) ? emitIGlist : startLoc->GetIG();
2461 insGroup* igEnd = (endLoc == NULL) ? NULL : endLoc->GetIG();
2464 insGroup* igLastReported;
2465 insGroup* igLastCandidate;
2466 UNATIVE_OFFSET curSize;
2467 UNATIVE_OFFSET candidateSize;
2469 for (igPrev = NULL, ig = igLastReported = igStart, igLastCandidate = NULL, candidateSize = 0, curSize = 0;
2470 ig != igEnd && ig != NULL; igPrev = ig, ig = ig->igNext)
2472 // Keep looking until we've gone past the maximum split size
2473 if (curSize >= maxSplitSize)
2475 bool reportCandidate = true;
2477 // Is there a candidate?
2478 if (igLastCandidate == NULL)
2482 printf("emitSplit: can't split at IG%02u; we don't have a candidate to report\n", ig->igNum);
2484 reportCandidate = false;
2487 // Don't report the same thing twice (this also happens for the first block, since igLastReported is
2488 // initialized to igStart).
2489 if (igLastCandidate == igLastReported)
2493 printf("emitSplit: can't split at IG%02u; we already reported it\n", igLastCandidate->igNum);
2495 reportCandidate = false;
2499 if (reportCandidate)
2502 if (EMITVERBOSE && (candidateSize >= maxSplitSize))
2503 printf("emitSplit: split at IG%02u is size %d, larger than requested maximum size of %d\n",
2504 igLastCandidate->igNum, candidateSize, maxSplitSize);
2507 // hand memory ownership to the callback function
2508 emitLocation* pEmitLoc = new (emitComp, CMK_Unknown) emitLocation(igLastCandidate);
2509 callbackFunc(context, pEmitLoc);
2510 igLastReported = igLastCandidate;
2511 igLastCandidate = NULL;
2512 curSize -= candidateSize;
2516 // Update the current candidate to be this block, if it isn't in the middle of a
2517 // prolog or epilog, which we can't split. All we know is that certain
2518 // IGs are marked as prolog or epilog. We don't actually know if two adjacent
2519 // IGs are part of the *same* prolog or epilog, so we have to assume they are.
2521 if (igPrev && (((igPrev->igFlags & IGF_FUNCLET_PROLOG) && (ig->igFlags & IGF_FUNCLET_PROLOG)) ||
2522 ((igPrev->igFlags & IGF_EPILOG) && (ig->igFlags & IGF_EPILOG))))
2524 // We can't update the candidate
2528 igLastCandidate = ig;
2529 candidateSize = curSize;
2532 curSize += ig->igSize;
2537 /*****************************************************************************
2539 * Given an instruction group, find the array of instructions (instrDesc) and
2540 * number of instructions in the array. If the IG is the current IG, we assume
2541 * that igData does NOT hold the instructions; they are unsaved and pointed
2542 * to by emitCurIGfreeBase.
2544 * This function can't be called for placeholder groups, which have no instrDescs.
2547 void emitter::emitGetInstrDescs(insGroup* ig, instrDesc** id, int* insCnt)
2549 assert(!(ig->igFlags & IGF_PLACEHOLDER));
2550 if (ig == emitCurIG)
2552 *id = (instrDesc*)emitCurIGfreeBase;
2553 *insCnt = emitCurIGinsCnt;
2557 *id = (instrDesc*)ig->igData;
2558 *insCnt = ig->igInsCnt;
2564 /*****************************************************************************
2566 * Given a location (an 'emitLocation'), find the instruction group (IG) and
2567 * instruction descriptor (instrDesc) corresponding to that location. Returns
2568 * 'true' if there is an instruction, 'false' if there is no instruction
2569 * (i.e., we're at the end of the instruction list). Also, optionally return
2570 * the number of instructions that follow that instruction in the IG (in *pinsRemaining,
2571 * if pinsRemaining is non-NULL), which can be used for iterating over the
2572 * remaining instrDescs in the IG.
2574 * We assume that emitCurIG points to the end of the instructions we care about.
2575 * For the prologs or epilogs, it points to the last IG of the prolog or epilog
2576 * that is being generated. For body code gen, it points to the place we are currently
2577 * adding code, namely, the end of currently generated code.
2580 bool emitter::emitGetLocationInfo(emitLocation* emitLoc,
2583 int* pinsRemaining /* = NULL */)
2585 assert(emitLoc != nullptr);
2586 assert(emitLoc->Valid());
2587 assert(emitLoc->GetIG() != nullptr);
2588 assert(pig != nullptr);
2589 assert(pid != nullptr);
2591 insGroup* ig = emitLoc->GetIG();
2593 int insNum = emitLoc->GetInsNum();
2596 emitGetInstrDescs(ig, &id, &insCnt);
2597 assert(insNum <= insCnt);
2599 // There is a special-case: if the insNum points to the end, then we "wrap" and
2600 // consider that the instruction it is pointing at is actually the first instruction
2601 // of the next non-empty IG (which has its own valid emitLocation). This handles the
2602 // case where you capture a location, then the next instruction creates a new IG.
2604 if (insNum == insCnt)
2606 if (ig == emitCurIG)
2608 // No instructions beyond the current location.
2612 for (ig = ig->igNext; ig; ig = ig->igNext)
2614 emitGetInstrDescs(ig, &id, &insCnt);
2618 insNum = 0; // Pretend the index is 0 -- the first instruction
2622 if (ig == emitCurIG)
2624 // There aren't any instructions in the current IG, and this is
2625 // the current location, so we're at the end.
2632 // 'ig' can't be NULL, or we went past the current IG represented by 'emitCurIG'.
2633 // Perhaps 'loc' was corrupt coming in?
2634 noway_assert(!"corrupt emitter location");
2639 // Now find the instrDesc within this group that corresponds to the location
2641 assert(insNum < insCnt);
2644 for (i = 0; i != insNum; ++i)
2646 castto(id, BYTE*) += emitSizeOfInsDsc(id);
2649 // Return the info we found
2656 *pinsRemaining = insCnt - insNum - 1;
2662 /*****************************************************************************
2664 * Compute the next instrDesc, either in this IG, or in a subsequent IG. 'id'
2665 * will point to this instrDesc. 'ig' and 'insRemaining' will also be updated.
2666 * Returns true if there is an instruction, or false if we've iterated over all
2667 * the instructions up to the current instruction (based on 'emitCurIG').
2670 bool emitter::emitNextID(insGroup*& ig, instrDesc*& id, int& insRemaining)
2672 if (insRemaining > 0)
2674 castto(id, BYTE*) += emitSizeOfInsDsc(id);
2679 // We're out of instrDesc in 'ig'. Is this the current IG? If so, we're done.
2681 if (ig == emitCurIG)
2686 for (ig = ig->igNext; ig; ig = ig->igNext)
2689 emitGetInstrDescs(ig, &id, &insCnt);
2693 insRemaining = insCnt - 1;
2697 if (ig == emitCurIG)
2706 /*****************************************************************************
2708 * Walk instrDesc's from the location given by 'locFrom', up to the current location.
2709 * For each instruction, call the callback function 'processFunc'. 'context' is simply
2710 * passed through to the callback function.
2713 void emitter::emitWalkIDs(emitLocation* locFrom, emitProcessInstrFunc_t processFunc, void* context)
2719 if (!emitGetLocationInfo(locFrom, &ig, &id, &insRemaining))
2720 return; // no instructions at the 'from' location
2725 (*processFunc)(id, context);
2727 } while (emitNextID(ig, id, insRemaining));
2730 /*****************************************************************************
2732 * A callback function for emitWalkIDs() that calls Compiler::unwindNop().
2735 void emitter::emitGenerateUnwindNop(instrDesc* id, void* context)
2737 Compiler* comp = (Compiler*)context;
2738 #if defined(_TARGET_ARM_)
2739 comp->unwindNop(id->idCodeSize());
2740 #elif defined(_TARGET_ARM64_)
2742 #endif // defined(_TARGET_ARM64_)
2745 /*****************************************************************************
2747 * emitUnwindNopPadding: call unwindNop() for every instruction from a given
2748 * location 'emitLoc' up to the current location.
2751 void emitter::emitUnwindNopPadding(emitLocation* locFrom, Compiler* comp)
2753 emitWalkIDs(locFrom, emitGenerateUnwindNop, comp);
2756 #endif // _TARGET_ARMARCH_
2758 #if defined(_TARGET_ARM_)
2760 /*****************************************************************************
2762 * Return the instruction size in bytes for the instruction at the specified location.
2763 * This is used to assert that the unwind code being generated on ARM has the
2764 * same size as the instruction for which it is being generated (since on ARM
2765 * the unwind codes have a one-to-one relationship with instructions, and the
2766 * unwind codes have an implicit instruction size that must match the instruction size.)
2767 * An instruction must exist at the specified location.
2770 unsigned emitter::emitGetInstructionSize(emitLocation* emitLoc)
2775 bool anyInstrs = emitGetLocationInfo(emitLoc, &ig, &id);
2776 assert(anyInstrs); // There better be an instruction at this location (otherwise, we're at the end of the
2777 // instruction list)
2778 return id->idCodeSize();
2781 #endif // defined(_TARGET_ARM_)
2783 /*****************************************************************************/
2785 /*****************************************************************************
2787 * Returns the name for the register to use to access frame based variables
2790 const char* emitter::emitGetFrameReg()
2792 if (emitHasFramePtr)
2802 /*****************************************************************************
2804 * Display a register set in a readable form.
2807 void emitter::emitDispRegSet(regMaskTP regs)
2814 for (reg = REG_FIRST; reg < ACTUAL_REG_COUNT; reg = REG_NEXT(reg))
2816 if ((regs & genRegMask(reg)) == 0)
2830 printf("%s", emitRegName(reg));
2836 /*****************************************************************************
2838 * Display the current GC ref variable set in a readable form.
2841 void emitter::emitDispVarSet()
2847 for (vn = 0, of = emitGCrFrameOffsMin; vn < emitGCrFrameOffsCnt; vn += 1, of += TARGET_POINTER_SIZE)
2849 if (emitGCrFrameLiveTab[vn])
2860 printf("[%s", emitGetFrameReg());
2864 printf("-%02XH", -of);
2868 printf("+%02XH", +of);
2881 /*****************************************************************************/
2884 #if MULTIREG_HAS_SECOND_GC_RET
2885 //------------------------------------------------------------------------
2886 // emitSetSecondRetRegGCType: Sets the GC type of the second return register for instrDescCGCA struct.
2889 // id - The large call instr descriptor to set the second GC return register type on.
2890 // secondRetSize - The EA_SIZE for second return register type.
2896 void emitter::emitSetSecondRetRegGCType(instrDescCGCA* id, emitAttr secondRetSize)
2898 if (EA_IS_GCREF(secondRetSize))
2900 id->idSecondGCref(GCT_GCREF);
2902 else if (EA_IS_BYREF(secondRetSize))
2904 id->idSecondGCref(GCT_BYREF);
2908 id->idSecondGCref(GCT_NONE);
2911 #endif // MULTIREG_HAS_SECOND_GC_RET
2913 /*****************************************************************************
2915 * Allocate an instruction descriptor for an indirect call.
2917 * We use two different descriptors to save space - the common case records
2918 * no GC variables and has both a very small argument count and an address
2919 * mode displacement; the other case records the current GC var set,
2920 * the call scope, and an arbitrarily large argument count and the
2921 * address mode displacement.
2924 emitter::instrDesc* emitter::emitNewInstrCallInd(int argCnt,
2926 VARSET_VALARG_TP GCvars,
2927 regMaskTP gcrefRegs,
2928 regMaskTP byrefRegs,
2930 MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize))
2932 emitAttr retSize = (retSizeIn != EA_UNKNOWN) ? retSizeIn : EA_PTRSIZE;
2934 bool gcRefRegsInScratch = ((gcrefRegs & RBM_CALLEE_TRASH) != 0);
2936 // Allocate a larger descriptor if any GC values need to be saved
2937 // or if we have an absurd number of arguments or a large address
2938 // mode displacement, or we have some byref registers
2940 // On Amd64 System V OSs a larger descriptor is also needed if the
2941 // call returns a two-register-returned struct and the second
2942 // register (RDX) is a GCRef or ByRef pointer.
2944 if (!VarSetOps::IsEmpty(emitComp, GCvars) || // any frame GCvars live
2945 (gcRefRegsInScratch) || // any register gc refs live in scratch regs
2946 (byrefRegs != 0) || // any register byrefs live
2947 (disp < AM_DISP_MIN) || // displacement too negative
2948 (disp > AM_DISP_MAX) || // displacement too positive
2949 (argCnt > ID_MAX_SMALL_CNS) || // too many args
2950 (argCnt < 0) // caller pops arguments
2951 // There is a second ref/byref return register.
2952 MULTIREG_HAS_SECOND_GC_RET_ONLY(|| EA_IS_GCREF_OR_BYREF(secondRetSize)))
2956 id = emitAllocInstrCGCA(retSize);
2958 id->idSetIsLargeCall();
2960 VarSetOps::Assign(emitComp, id->idcGCvars, GCvars);
2961 id->idcGcrefRegs = gcrefRegs;
2962 id->idcByrefRegs = byrefRegs;
2963 id->idcArgCnt = argCnt;
2966 #if MULTIREG_HAS_SECOND_GC_RET
2967 emitSetSecondRetRegGCType(id, secondRetSize);
2968 #endif // MULTIREG_HAS_SECOND_GC_RET
2976 id = emitNewInstrCns(retSize, argCnt);
2978 /* Make sure we didn't waste space unexpectedly */
2979 assert(!id->idIsLargeCns());
2981 /* Store the displacement and make sure the value fit */
2982 id->idAddr()->iiaAddrMode.amDisp = disp;
2983 assert(id->idAddr()->iiaAddrMode.amDisp == disp);
2985 /* Save the the live GC registers in the unused register fields */
2986 emitEncodeCallGCregs(gcrefRegs, id);
2992 /*****************************************************************************
2994 * Allocate an instruction descriptor for a direct call.
2996 * We use two different descriptors to save space - the common case records
2997 * with no GC variables or byrefs and has a very small argument count, and no
2999 * the other case records the current GC var set, the call scope,
3000 * and an arbitrarily large argument count.
3003 emitter::instrDesc* emitter::emitNewInstrCallDir(int argCnt,
3004 VARSET_VALARG_TP GCvars,
3005 regMaskTP gcrefRegs,
3006 regMaskTP byrefRegs,
3008 MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize))
3010 emitAttr retSize = (retSizeIn != EA_UNKNOWN) ? retSizeIn : EA_PTRSIZE;
3012 // Allocate a larger descriptor if new GC values need to be saved
3013 // or if we have an absurd number of arguments or if we need to
3016 // On Amd64 System V OSs a larger descriptor is also needed if the
3017 // call returns a two-register-returned struct and the second
3018 // register (RDX) is a GCRef or ByRef pointer.
3020 bool gcRefRegsInScratch = ((gcrefRegs & RBM_CALLEE_TRASH) != 0);
3022 if (!VarSetOps::IsEmpty(emitComp, GCvars) || // any frame GCvars live
3023 gcRefRegsInScratch || // any register gc refs live in scratch regs
3024 (byrefRegs != 0) || // any register byrefs live
3025 (argCnt > ID_MAX_SMALL_CNS) || // too many args
3026 (argCnt < 0) // caller pops arguments
3027 // There is a second ref/byref return register.
3028 MULTIREG_HAS_SECOND_GC_RET_ONLY(|| EA_IS_GCREF_OR_BYREF(secondRetSize)))
3030 instrDescCGCA* id = emitAllocInstrCGCA(retSize);
3032 // printf("Direct call with GC vars / big arg cnt / explicit scope\n");
3034 id->idSetIsLargeCall();
3036 VarSetOps::Assign(emitComp, id->idcGCvars, GCvars);
3037 id->idcGcrefRegs = gcrefRegs;
3038 id->idcByrefRegs = byrefRegs;
3040 id->idcArgCnt = argCnt;
3042 #if MULTIREG_HAS_SECOND_GC_RET
3043 emitSetSecondRetRegGCType(id, secondRetSize);
3044 #endif // MULTIREG_HAS_SECOND_GC_RET
3050 instrDesc* id = emitNewInstrCns(retSize, argCnt);
3052 // printf("Direct call w/o GC vars / big arg cnt / explicit scope\n");
3054 /* Make sure we didn't waste space unexpectedly */
3055 assert(!id->idIsLargeCns());
3057 /* Save the the live GC registers in the unused register fields */
3058 emitEncodeCallGCregs(gcrefRegs, id);
3064 /*****************************************************************************/
3066 /*****************************************************************************
3068 * Return a string with the name of the given class field (blank string (not
3069 * NULL) is returned when the name isn't available).
3072 const char* emitter::emitFldName(CORINFO_FIELD_HANDLE fieldVal)
3074 if (emitComp->opts.varNames)
3076 const char* memberName;
3077 const char* className;
3079 const int TEMP_BUFFER_LEN = 1024;
3080 static char buff[TEMP_BUFFER_LEN];
3082 memberName = emitComp->eeGetFieldName(fieldVal, &className);
3084 sprintf_s(buff, TEMP_BUFFER_LEN, "'<%s>.%s'", className, memberName);
3093 /*****************************************************************************
3095 * Return a string with the name of the given function (blank string (not
3096 * NULL) is returned when the name isn't available).
3099 const char* emitter::emitFncName(CORINFO_METHOD_HANDLE methHnd)
3101 return emitComp->eeGetMethodFullName(methHnd);
3106 /*****************************************************************************
3108 * Be very careful, some instruction descriptors are allocated as "tiny" and
3109 * don't have some of the tail fields of instrDesc (in particular, "idInfo").
3112 const BYTE emitter::emitFmtToOps[] = {
3113 #define IF_DEF(en, op1, op2) ID_OP_##op2,
3114 #include "emitfmts.h"
3118 const unsigned emitter::emitFmtCount = _countof(emitFmtToOps);
3121 /*****************************************************************************
3123 * Display the current instruction group list.
3128 void emitter::emitDispIGflags(unsigned flags)
3130 if (flags & IGF_GC_VARS)
3134 if (flags & IGF_BYREF_REGS)
3138 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
3139 if (flags & IGF_FINALLY_TARGET)
3141 printf(", ftarget");
3143 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
3144 if (flags & IGF_FUNCLET_PROLOG)
3146 printf(", funclet prolog");
3148 if (flags & IGF_FUNCLET_EPILOG)
3150 printf(", funclet epilog");
3152 if (flags & IGF_EPILOG)
3156 if (flags & IGF_NOGCINTERRUPT)
3160 if (flags & IGF_UPD_ISZ)
3164 if (flags & IGF_EMIT_ADD)
3166 printf(", emitadd");
3170 void emitter::emitDispIG(insGroup* ig, insGroup* igPrev, bool verbose)
3172 const int TEMP_BUFFER_LEN = 40;
3173 char buff[TEMP_BUFFER_LEN];
3175 sprintf_s(buff, TEMP_BUFFER_LEN, "G_M%03u_IG%02u: ", Compiler::s_compMethodsCount, ig->igNum);
3176 printf("%s; ", buff);
3177 if ((igPrev == nullptr) || (igPrev->igFuncIdx != ig->igFuncIdx))
3179 printf("func=%02u, ", ig->igFuncIdx);
3182 if (ig->igFlags & IGF_PLACEHOLDER)
3184 insGroup* igPh = ig;
3186 const char* pszType;
3187 switch (igPh->igPhData->igPhType)
3195 #if FEATURE_EH_FUNCLETS
3196 case IGPT_FUNCLET_PROLOG:
3197 pszType = "funclet prolog";
3199 case IGPT_FUNCLET_EPILOG:
3200 pszType = "funclet epilog";
3202 #endif // FEATURE_EH_FUNCLETS
3204 pszType = "UNKNOWN";
3207 printf("%s placeholder, next placeholder=", pszType);
3208 if (igPh->igPhData->igPhNext)
3210 printf("IG%02u ", igPh->igPhData->igPhNext->igNum);
3217 if (igPh->igPhData->igPhBB != nullptr)
3219 printf(", %s", igPh->igPhData->igPhBB->dspToString());
3222 emitDispIGflags(igPh->igFlags);
3224 if (ig == emitCurIG)
3226 printf(" <-- Current IG");
3228 if (igPh == emitPlaceholderList)
3230 printf(" <-- First placeholder");
3232 if (igPh == emitPlaceholderLast)
3234 printf(" <-- Last placeholder");
3238 printf("%*s; PrevGCVars=%s ", strlen(buff), "",
3239 VarSetOps::ToString(emitComp, igPh->igPhData->igPhPrevGCrefVars));
3240 dumpConvertedVarSet(emitComp, igPh->igPhData->igPhPrevGCrefVars);
3241 printf(", PrevGCrefRegs=");
3242 printRegMaskInt(igPh->igPhData->igPhPrevGCrefRegs);
3243 emitDispRegSet(igPh->igPhData->igPhPrevGCrefRegs);
3244 printf(", PrevByrefRegs=");
3245 printRegMaskInt(igPh->igPhData->igPhPrevByrefRegs);
3246 emitDispRegSet(igPh->igPhData->igPhPrevByrefRegs);
3249 printf("%*s; InitGCVars=%s ", strlen(buff), "",
3250 VarSetOps::ToString(emitComp, igPh->igPhData->igPhInitGCrefVars));
3251 dumpConvertedVarSet(emitComp, igPh->igPhData->igPhInitGCrefVars);
3252 printf(", InitGCrefRegs=");
3253 printRegMaskInt(igPh->igPhData->igPhInitGCrefRegs);
3254 emitDispRegSet(igPh->igPhData->igPhInitGCrefRegs);
3255 printf(", InitByrefRegs=");
3256 printRegMaskInt(igPh->igPhData->igPhInitByrefRegs);
3257 emitDispRegSet(igPh->igPhData->igPhInitByrefRegs);
3260 assert(!(ig->igFlags & IGF_GC_VARS));
3261 assert(!(ig->igFlags & IGF_BYREF_REGS));
3265 printf("offs=%06XH, size=%04XH", ig->igOffs, ig->igSize);
3267 if (ig->igFlags & IGF_GC_VARS)
3269 printf(", gcVars=%s ", VarSetOps::ToString(emitComp, ig->igGCvars()));
3270 dumpConvertedVarSet(emitComp, ig->igGCvars());
3273 if (!(ig->igFlags & IGF_EMIT_ADD))
3275 printf(", gcrefRegs=");
3276 printRegMaskInt(ig->igGCregs);
3277 emitDispRegSet(ig->igGCregs);
3280 if (ig->igFlags & IGF_BYREF_REGS)
3282 printf(", byrefRegs=");
3283 printRegMaskInt(ig->igByrefRegs());
3284 emitDispRegSet(ig->igByrefRegs());
3287 emitDispIGflags(ig->igFlags);
3289 if (ig == emitCurIG)
3291 printf(" <-- Current IG");
3293 if (ig == emitPrologIG)
3295 printf(" <-- Prolog IG");
3301 BYTE* ins = ig->igData;
3302 UNATIVE_OFFSET ofs = ig->igOffs;
3303 unsigned cnt = ig->igInsCnt;
3311 instrDesc* id = (instrDesc*)ins;
3313 emitDispIns(id, false, true, false, ofs, nullptr, 0, ig);
3315 ins += emitSizeOfInsDsc(id);
3316 ofs += emitInstCodeSz(id);
3325 void emitter::emitDispIGlist(bool verbose)
3330 for (igPrev = nullptr, ig = emitIGlist; ig; igPrev = ig, ig = ig->igNext)
3332 emitDispIG(ig, igPrev, verbose);
3336 void emitter::emitDispGCinfo()
3338 printf("Emitter GC tracking info:");
3339 printf("\n emitPrevGCrefVars ");
3340 dumpConvertedVarSet(emitComp, emitPrevGCrefVars);
3341 printf("\n emitPrevGCrefRegs(0x%p)=", dspPtr(&emitPrevGCrefRegs));
3342 printRegMaskInt(emitPrevGCrefRegs);
3343 emitDispRegSet(emitPrevGCrefRegs);
3344 printf("\n emitPrevByrefRegs(0x%p)=", dspPtr(&emitPrevByrefRegs));
3345 printRegMaskInt(emitPrevByrefRegs);
3346 emitDispRegSet(emitPrevByrefRegs);
3347 printf("\n emitInitGCrefVars ");
3348 dumpConvertedVarSet(emitComp, emitInitGCrefVars);
3349 printf("\n emitInitGCrefRegs(0x%p)=", dspPtr(&emitInitGCrefRegs));
3350 printRegMaskInt(emitInitGCrefRegs);
3351 emitDispRegSet(emitInitGCrefRegs);
3352 printf("\n emitInitByrefRegs(0x%p)=", dspPtr(&emitInitByrefRegs));
3353 printRegMaskInt(emitInitByrefRegs);
3354 emitDispRegSet(emitInitByrefRegs);
3355 printf("\n emitThisGCrefVars ");
3356 dumpConvertedVarSet(emitComp, emitThisGCrefVars);
3357 printf("\n emitThisGCrefRegs(0x%p)=", dspPtr(&emitThisGCrefRegs));
3358 printRegMaskInt(emitThisGCrefRegs);
3359 emitDispRegSet(emitThisGCrefRegs);
3360 printf("\n emitThisByrefRegs(0x%p)=", dspPtr(&emitThisByrefRegs));
3361 printRegMaskInt(emitThisByrefRegs);
3362 emitDispRegSet(emitThisByrefRegs);
3368 /*****************************************************************************
3370 * Issue the given instruction. Basically, this is just a thin wrapper around
3371 * emitOutputInstr() that does a few debug checks.
3374 size_t emitter::emitIssue1Instr(insGroup* ig, instrDesc* id, BYTE** dp)
3378 /* Record the beginning offset of the instruction */
3380 BYTE* curInsAdr = *dp;
3382 /* Issue the next instruction */
3384 // printf("[S=%02u] " , emitCurStackLvl);
3386 is = emitOutputInstr(ig, id, dp);
3388 // printf("[S=%02u]\n", emitCurStackLvl);
3390 #if EMIT_TRACK_STACK_DEPTH
3393 If we're generating a full pointer map and the stack
3394 is empty, there better not be any "pending" argument
3398 assert(emitFullGCinfo == false || emitCurStackLvl != 0 || u2.emitGcArgTrackCnt == 0);
3402 /* Did the size of the instruction match our expectations? */
3404 UNATIVE_OFFSET csz = (UNATIVE_OFFSET)(*dp - curInsAdr);
3406 if (csz != id->idCodeSize())
3408 /* It is fatal to under-estimate the instruction size */
3409 noway_assert(emitInstCodeSz(id) >= csz);
3414 printf("Instruction predicted size = %u, actual = %u\n", emitInstCodeSz(id), csz);
3416 #endif // DEBUG_EMIT
3418 /* The instruction size estimate wasn't accurate; remember this */
3420 ig->igFlags |= IGF_UPD_ISZ;
3421 #if defined(_TARGET_XARCH_)
3422 id->idCodeSize(csz);
3423 #elif defined(_TARGET_ARM_)
3424 // This is done as part of emitSetShortJump();
3425 // insSize isz = emitInsSize(id->idInsFmt());
3426 // id->idInsSize(isz);
3428 /* It is fatal to over-estimate the instruction size */
3429 IMPL_LIMITATION("Over-estimated instruction size");
3434 /* Make sure the instruction descriptor size also matches our expectations */
3435 if (is != emitSizeOfInsDsc(id))
3437 printf("%s at %u: Expected size = %u , actual size = %u\n", emitIfName(id->idInsFmt()),
3438 id->idDebugOnlyInfo()->idNum, is, emitSizeOfInsDsc(id));
3439 assert(is == emitSizeOfInsDsc(id));
3446 /*****************************************************************************
3448 * Update the offsets of all the instruction groups (note: please don't be
3449 * lazy and call this routine frequently, it walks the list of instruction
3450 * groups and thus it isn't cheap).
3453 void emitter::emitRecomputeIGoffsets()
3455 UNATIVE_OFFSET offs;
3458 for (ig = emitIGlist, offs = 0; ig; ig = ig->igNext)
3461 assert(IsCodeAligned(ig->igOffs));
3465 /* Set the total code size */
3467 emitTotalCodeSize = offs;
3470 emitCheckIGoffsets();
3474 /*****************************************************************************
3475 * Bind targets of relative jumps to choose the smallest possible encoding.
3476 * X86 and AMD64 have a small and large encoding.
3477 * ARM has a small, medium, and large encoding. The large encoding is a pseudo-op
3478 * to handle greater range than the conditional branch instructions can handle.
3479 * ARM64 has a small and large encoding for both conditional branch and loading label addresses.
3480 * The large encodings are pseudo-ops that represent a multiple instruction sequence, similar to ARM. (Currently
3484 void emitter::emitJumpDistBind()
3487 if (emitComp->verbose)
3489 printf("*************** In emitJumpDistBind()\n");
3491 if (EMIT_INSTLIST_VERBOSE)
3493 printf("\nInstruction list before jump distance binding:\n\n");
3494 emitDispIGlist(true);
3500 UNATIVE_OFFSET minShortExtra; // The smallest offset greater than that required for a jump to be converted
3501 // to a small jump. If it is small enough, we will iterate in hopes of
3502 // converting those jumps we missed converting the first (or second...) time.
3504 #if defined(_TARGET_ARM_)
3505 UNATIVE_OFFSET minMediumExtra; // Same as 'minShortExtra', but for medium-sized jumps.
3506 #endif // _TARGET_ARM_
3508 UNATIVE_OFFSET adjIG;
3509 UNATIVE_OFFSET adjLJ;
3512 insGroup* prologIG = emitPrologIG;
3515 int jmp_iteration = 1;
3517 /*****************************************************************************/
3518 /* If we iterate to look for more jumps to shorten, we start again here. */
3519 /*****************************************************************************/
3524 emitCheckIGoffsets();
3528 In the following loop we convert all jump targets from "BasicBlock *"
3529 to "insGroup *" values. We also estimate which jumps will be short.
3533 insGroup* lastIG = nullptr;
3534 instrDescJmp* lastLJ = nullptr;
3540 minShortExtra = (UNATIVE_OFFSET)-1;
3542 #if defined(_TARGET_ARM_)
3543 minMediumExtra = (UNATIVE_OFFSET)-1;
3544 #endif // _TARGET_ARM_
3546 for (jmp = emitJumpList; jmp; jmp = jmp->idjNext)
3551 UNATIVE_OFFSET jsz; // size of the jump instruction in bytes
3553 UNATIVE_OFFSET ssz = 0; // small jump size
3554 NATIVE_OFFSET nsd = 0; // small jump max. neg distance
3555 NATIVE_OFFSET psd = 0; // small jump max. pos distance
3557 #if defined(_TARGET_ARM_)
3558 UNATIVE_OFFSET msz = 0; // medium jump size
3559 NATIVE_OFFSET nmd = 0; // medium jump max. neg distance
3560 NATIVE_OFFSET pmd = 0; // medium jump max. pos distance
3561 NATIVE_OFFSET mextra; // How far beyond the medium jump range is this jump offset?
3562 #endif // _TARGET_ARM_
3564 NATIVE_OFFSET extra; // How far beyond the short jump range is this jump offset?
3565 UNATIVE_OFFSET srcInstrOffs; // offset of the source instruction of the jump
3566 UNATIVE_OFFSET srcEncodingOffs; // offset of the source used by the instruction set to calculate the relative
3567 // offset of the jump
3568 UNATIVE_OFFSET dstOffs;
3569 NATIVE_OFFSET jmpDist; // the relative jump distance, as it will be encoded
3570 UNATIVE_OFFSET oldSize;
3571 UNATIVE_OFFSET sizeDif;
3573 #ifdef _TARGET_XARCH_
3574 assert(jmp->idInsFmt() == IF_LABEL || jmp->idInsFmt() == IF_RWR_LABEL || jmp->idInsFmt() == IF_SWR_LABEL);
3576 /* Figure out the smallest size we can end up with */
3578 if (jmp->idInsFmt() == IF_LABEL)
3580 if (emitIsCondJump(jmp))
3582 ssz = JCC_SIZE_SMALL;
3583 nsd = JCC_DIST_SMALL_MAX_NEG;
3584 psd = JCC_DIST_SMALL_MAX_POS;
3588 ssz = JMP_SIZE_SMALL;
3589 nsd = JMP_DIST_SMALL_MAX_NEG;
3590 psd = JMP_DIST_SMALL_MAX_POS;
3593 #endif // _TARGET_XARCH_
3596 assert((jmp->idInsFmt() == IF_T2_J1) || (jmp->idInsFmt() == IF_T2_J2) || (jmp->idInsFmt() == IF_T1_I) ||
3597 (jmp->idInsFmt() == IF_T1_K) || (jmp->idInsFmt() == IF_T1_M) || (jmp->idInsFmt() == IF_T2_M1) ||
3598 (jmp->idInsFmt() == IF_T2_N1) || (jmp->idInsFmt() == IF_T1_J3) || (jmp->idInsFmt() == IF_LARGEJMP));
3600 /* Figure out the smallest size we can end up with */
3602 if (emitIsCondJump(jmp))
3604 ssz = JCC_SIZE_SMALL;
3605 nsd = JCC_DIST_SMALL_MAX_NEG;
3606 psd = JCC_DIST_SMALL_MAX_POS;
3608 msz = JCC_SIZE_MEDIUM;
3609 nmd = JCC_DIST_MEDIUM_MAX_NEG;
3610 pmd = JCC_DIST_MEDIUM_MAX_POS;
3612 else if (emitIsCmpJump(jmp))
3614 ssz = JMP_SIZE_SMALL;
3618 else if (emitIsUncondJump(jmp))
3620 ssz = JMP_SIZE_SMALL;
3621 nsd = JMP_DIST_SMALL_MAX_NEG;
3622 psd = JMP_DIST_SMALL_MAX_POS;
3624 else if (emitIsLoadLabel(jmp))
3626 ssz = LBL_SIZE_SMALL;
3627 nsd = LBL_DIST_SMALL_MAX_NEG;
3628 psd = LBL_DIST_SMALL_MAX_POS;
3632 assert(!"Unknown jump instruction");
3634 #endif // _TARGET_ARM_
3636 #ifdef _TARGET_ARM64_
3637 /* Figure out the smallest size we can end up with */
3639 if (emitIsCondJump(jmp))
3641 ssz = JCC_SIZE_SMALL;
3642 bool isTest = (jmp->idIns() == INS_tbz) || (jmp->idIns() == INS_tbnz);
3644 nsd = (isTest) ? TB_DIST_SMALL_MAX_NEG : JCC_DIST_SMALL_MAX_NEG;
3645 psd = (isTest) ? TB_DIST_SMALL_MAX_POS : JCC_DIST_SMALL_MAX_POS;
3647 else if (emitIsUncondJump(jmp))
3649 // Nothing to do; we don't shrink these.
3650 assert(jmp->idjShort);
3651 ssz = JMP_SIZE_SMALL;
3653 else if (emitIsLoadLabel(jmp))
3655 ssz = LBL_SIZE_SMALL;
3656 nsd = LBL_DIST_SMALL_MAX_NEG;
3657 psd = LBL_DIST_SMALL_MAX_POS;
3659 else if (emitIsLoadConstant(jmp))
3661 ssz = LDC_SIZE_SMALL;
3662 nsd = LDC_DIST_SMALL_MAX_NEG;
3663 psd = LDC_DIST_SMALL_MAX_POS;
3667 assert(!"Unknown jump instruction");
3669 #endif // _TARGET_ARM64_
3671 /* Make sure the jumps are properly ordered */
3674 assert(lastLJ == nullptr || lastIG != jmp->idjIG || lastLJ->idjOffs < jmp->idjOffs);
3675 lastLJ = (lastIG == jmp->idjIG) ? jmp : nullptr;
3677 assert(lastIG == nullptr || lastIG->igNum <= jmp->idjIG->igNum || jmp->idjIG == prologIG ||
3678 emitNxtIGnum > unsigned(0xFFFF)); // igNum might overflow
3679 lastIG = jmp->idjIG;
3682 /* Get hold of the current jump size */
3684 jsz = emitSizeOfJump(jmp);
3686 /* Get the group the jump is in */
3690 /* Are we in a group different from the previous jump? */
3694 /* Were there any jumps before this one? */
3698 /* Adjust the offsets of the intervening blocks */
3702 lstIG = lstIG->igNext;
3704 // printf("Adjusted offset of block %02u from %04X to %04X\n", lstIG->igNum, lstIG->igOffs,
3705 // lstIG->igOffs - adjIG);
3706 lstIG->igOffs -= adjIG;
3707 assert(IsCodeAligned(lstIG->igOffs));
3708 } while (lstIG != jmpIG);
3711 /* We've got the first jump in a new group */
3717 /* Apply any local size adjustment to the jump's relative offset */
3719 jmp->idjOffs -= adjLJ;
3721 // If this is a jump via register, the instruction size does not change, so we are done.
3722 CLANG_FORMAT_COMMENT_ANCHOR;
3724 #if defined(_TARGET_ARM64_)
3725 // JIT code and data will be allocated together for arm64 so the relative offset to JIT data is known.
3726 // In case such offset can be encodeable for `ldr` (+-1MB), shorten it.
3727 if (jmp->idAddr()->iiaIsJitDataOffset())
3729 // Reference to JIT data
3730 assert(jmp->idIsBound());
3731 UNATIVE_OFFSET srcOffs = jmpIG->igOffs + jmp->idjOffs;
3733 int doff = jmp->idAddr()->iiaGetJitDataOffset();
3735 ssize_t imm = emitGetInsSC(jmp);
3736 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
3738 unsigned dataOffs = (unsigned)(doff + imm);
3739 assert(dataOffs < emitDataSize());
3741 // Conservately assume JIT data starts after the entire code size.
3742 // TODO-ARM64: we might consider only hot code size which will be computed later in emitComputeCodeSizes().
3743 assert(emitTotalCodeSize > 0);
3744 UNATIVE_OFFSET maxDstOffs = emitTotalCodeSize + dataOffs;
3746 // Check if the distance is within the encoding length.
3747 jmpDist = maxDstOffs - srcOffs;
3748 extra = jmpDist - psd;
3754 // Keep the large form.
3759 /* Have we bound this jump's target already? */
3761 if (jmp->idIsBound())
3763 /* Does the jump already have the smallest size? */
3767 assert(emitSizeOfJump(jmp) == ssz);
3769 // We should not be jumping/branching across funclets/functions
3770 emitCheckFuncletBranch(jmp, jmpIG);
3775 tgtIG = jmp->idAddr()->iiaIGlabel;
3779 /* First time we've seen this label, convert its target */
3780 CLANG_FORMAT_COMMENT_ANCHOR;
3785 printf("Binding: ");
3786 emitDispIns(jmp, false, false, false);
3787 printf("Binding L_M%03u_BB%02u ", Compiler::s_compMethodsCount, jmp->idAddr()->iiaBBlabel->bbNum);
3791 tgtIG = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel);
3798 printf("to G_M%03u_IG%02u\n", Compiler::s_compMethodsCount, tgtIG->igNum);
3802 printf("-- ERROR, no emitter cookie for BB%02u; it is probably missing BBF_JMP_TARGET or "
3804 jmp->idAddr()->iiaBBlabel->bbNum);
3810 /* Record the bound target */
3812 jmp->idAddr()->iiaIGlabel = tgtIG;
3813 jmp->idSetIsBound();
3816 // We should not be jumping/branching across funclets/functions
3817 emitCheckFuncletBranch(jmp, jmpIG);
3819 #ifdef _TARGET_XARCH_
3820 /* Done if this is not a variable-sized jump */
3822 if ((jmp->idIns() == INS_push) || (jmp->idIns() == INS_mov) || (jmp->idIns() == INS_call) ||
3823 (jmp->idIns() == INS_push_hide))
3829 if ((jmp->idIns() == INS_push) || (jmp->idIns() == INS_mov) || (jmp->idIns() == INS_movt) ||
3830 (jmp->idIns() == INS_movw))
3835 #ifdef _TARGET_ARM64_
3836 // There is only one size of unconditional branch; we don't support functions larger than 2^28 bytes (our branch
3838 if (emitIsUncondJump(jmp))
3845 In the following distance calculations, if we're not actually
3846 scheduling the code (i.e. reordering instructions), we can
3847 use the actual offset of the jump (rather than the beg/end of
3848 the instruction group) since the jump will not be moved around
3849 and thus its offset is accurate.
3851 First we need to figure out whether this jump is a forward or
3852 backward one; to do this we simply look at the ordinals of the
3853 group that contains the jump and the target.
3856 srcInstrOffs = jmpIG->igOffs + jmp->idjOffs;
3858 /* Note that the destination is always the beginning of an IG, so no need for an offset inside it */
3859 dstOffs = tgtIG->igOffs;
3861 #if defined(_TARGET_ARM_)
3863 srcInstrOffs + 4; // For relative branches, ARM PC is always considered to be the instruction address + 4
3864 #elif defined(_TARGET_ARM64_)
3866 srcInstrOffs; // For relative branches, ARM64 PC is always considered to be the instruction address
3868 srcEncodingOffs = srcInstrOffs + ssz; // Encoding offset of relative offset for small branch
3871 if (jmpIG->igNum < tgtIG->igNum)
3875 /* Adjust the target offset by the current delta. This is a worst-case estimate, as jumps between
3876 here and the target could be shortened, causing the actual distance to shrink.
3881 /* Compute the distance estimate */
3883 jmpDist = dstOffs - srcEncodingOffs;
3885 /* How much beyond the max. short distance does the jump go? */
3887 extra = jmpDist - psd;
3890 assert(jmp->idDebugOnlyInfo() != nullptr);
3891 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3893 if (INTERESTING_JUMP_NUM == 0)
3895 printf("[1] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3897 printf("[1] Jump block is at %08X\n", jmpIG->igOffs);
3898 printf("[1] Jump reloffset is %04X\n", jmp->idjOffs);
3899 printf("[1] Jump source is at %08X\n", srcEncodingOffs);
3900 printf("[1] Label block is at %08X\n", dstOffs);
3901 printf("[1] Jump dist. is %04X\n", jmpDist);
3904 printf("[1] Dist excess [S] = %d \n", extra);
3909 printf("Estimate of fwd jump [%08X/%03u]: %04X -> %04X = %04X\n", dspPtr(jmp),
3910 jmp->idDebugOnlyInfo()->idNum, srcInstrOffs, dstOffs, jmpDist);
3912 #endif // DEBUG_EMIT
3916 /* This jump will be a short one */
3924 /* Compute the distance estimate */
3926 jmpDist = srcEncodingOffs - dstOffs;
3928 /* How much beyond the max. short distance does the jump go? */
3930 extra = jmpDist + nsd;
3933 assert(jmp->idDebugOnlyInfo() != nullptr);
3934 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3936 if (INTERESTING_JUMP_NUM == 0)
3938 printf("[2] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3940 printf("[2] Jump block is at %08X\n", jmpIG->igOffs);
3941 printf("[2] Jump reloffset is %04X\n", jmp->idjOffs);
3942 printf("[2] Jump source is at %08X\n", srcEncodingOffs);
3943 printf("[2] Label block is at %08X\n", dstOffs);
3944 printf("[2] Jump dist. is %04X\n", jmpDist);
3947 printf("[2] Dist excess [S] = %d \n", extra);
3952 printf("Estimate of bwd jump [%08X/%03u]: %04X -> %04X = %04X\n", dspPtr(jmp),
3953 jmp->idDebugOnlyInfo()->idNum, srcInstrOffs, dstOffs, jmpDist);
3955 #endif // DEBUG_EMIT
3959 /* This jump will be a short one */
3964 /* We arrive here if the jump couldn't be made short, at least for now */
3966 /* We had better not have eagerly marked the jump as short
3967 * in emitIns_J(). If we did, then it has to be able to stay short
3968 * as emitIns_J() uses the worst case scenario, and blocks can
3969 * only move closer together after that.
3971 assert(jmp->idjShort == 0);
3973 /* Keep track of the closest distance we got */
3975 if (minShortExtra > (unsigned)extra)
3977 minShortExtra = (unsigned)extra;
3980 #if defined(_TARGET_ARM_)
3982 // If we're here, we couldn't convert to a small jump.
3983 // Handle conversion to medium-sized conditional jumps.
3984 // 'srcInstrOffs', 'srcEncodingOffs', 'dstOffs', 'jmpDist' have already been computed
3985 // and don't need to be recomputed.
3987 if (emitIsCondJump(jmp))
3989 if (jmpIG->igNum < tgtIG->igNum)
3993 /* How much beyond the max. medium distance does the jump go? */
3995 mextra = jmpDist - pmd;
3998 assert(jmp->idDebugOnlyInfo() != NULL);
3999 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4003 if (INTERESTING_JUMP_NUM == 0)
4004 printf("[6] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
4005 printf("[6] Dist excess [S] = %d \n", mextra);
4008 #endif // DEBUG_EMIT
4012 /* This jump will be a medium one */
4020 /* How much beyond the max. medium distance does the jump go? */
4022 mextra = jmpDist + nmd;
4025 assert(jmp->idDebugOnlyInfo() != NULL);
4026 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4030 if (INTERESTING_JUMP_NUM == 0)
4031 printf("[7] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
4032 printf("[7] Dist excess [S] = %d \n", mextra);
4035 #endif // DEBUG_EMIT
4039 /* This jump will be a medium one */
4044 /* We arrive here if the jump couldn't be made medium, at least for now */
4046 /* Keep track of the closest distance we got */
4048 if (minMediumExtra > (unsigned)mextra)
4049 minMediumExtra = (unsigned)mextra;
4052 #endif // _TARGET_ARM_
4054 /*****************************************************************************
4055 * We arrive here if the jump must stay long, at least for now.
4056 * Go try the next one.
4061 /*****************************************************************************/
4062 /* Handle conversion to short jump */
4063 /*****************************************************************************/
4067 /* Try to make this jump a short one */
4069 emitSetShortJump(jmp);
4073 continue; // This jump must be kept long
4076 /* This jump is becoming either short or medium */
4080 assert(oldSize >= jsz);
4081 sizeDif = oldSize - jsz;
4083 #if defined(_TARGET_XARCH_)
4084 jmp->idCodeSize(jsz);
4085 #elif defined(_TARGET_ARM_)
4087 // This is done as part of emitSetShortJump():
4088 insSize isz = emitInsSize(jmp->idInsFmt());
4089 jmp->idInsSize(isz);
4091 #elif defined(_TARGET_ARM64_)
4092 // The size of IF_LARGEJMP/IF_LARGEADR/IF_LARGELDC are 8 or 12.
4093 // All other code size is 4.
4094 assert((sizeDif == 4) || (sizeDif == 8));
4096 #error Unsupported or unset target architecture
4101 #if defined(_TARGET_ARM_)
4103 /*****************************************************************************/
4104 /* Handle conversion to medium jump */
4105 /*****************************************************************************/
4109 /* Try to make this jump a medium one */
4111 emitSetMediumJump(jmp);
4113 if (jmp->idCodeSize() > msz)
4115 continue; // This jump wasn't shortened
4117 assert(jmp->idCodeSize() == msz);
4119 /* This jump is becoming medium */
4123 assert(oldSize >= jsz);
4124 sizeDif = oldSize - jsz;
4128 #endif // _TARGET_ARM_
4130 /*****************************************************************************/
4134 /* Make sure the size of the jump is marked correctly */
4136 assert((0 == (jsz | jmpDist)) || (jsz == emitSizeOfJump(jmp)));
4141 printf("Shrinking jump [%08X/%03u]\n", dspPtr(jmp), jmp->idDebugOnlyInfo()->idNum);
4144 noway_assert((unsigned short)sizeDif == sizeDif);
4148 jmpIG->igSize -= (unsigned short)sizeDif;
4149 emitTotalCodeSize -= sizeDif;
4151 /* The jump size estimate wasn't accurate; flag its group */
4153 jmpIG->igFlags |= IGF_UPD_ISZ;
4155 } // end for each jump
4157 /* Did we shorten any jumps? */
4161 /* Adjust offsets of any remaining blocks */
4167 lstIG = lstIG->igNext;
4172 // printf("Adjusted offset of block %02u from %04X to %04X\n", lstIG->igNum, lstIG->igOffs,
4173 // lstIG->igOffs - adjIG);
4174 lstIG->igOffs -= adjIG;
4175 assert(IsCodeAligned(lstIG->igOffs));
4179 emitCheckIGoffsets();
4182 /* Is there a chance of other jumps becoming short? */
4183 CLANG_FORMAT_COMMENT_ANCHOR;
4185 #if defined(_TARGET_ARM_)
4187 printf("Total shrinkage = %3u, min extra short jump size = %3u, min extra medium jump size = %u\n", adjIG,
4188 minShortExtra, minMediumExtra);
4192 printf("Total shrinkage = %3u, min extra jump size = %3u\n", adjIG, minShortExtra);
4197 if ((minShortExtra <= adjIG)
4198 #if defined(_TARGET_ARM_)
4199 || (minMediumExtra <= adjIG)
4200 #endif // _TARGET_ARM_
4208 printf("Iterating branch shortening. Iteration = %d\n", jmp_iteration);
4217 void emitter::emitCheckFuncletBranch(instrDesc* jmp, insGroup* jmpIG)
4220 // We should not be jumping/branching across funclets/functions
4221 // Except possibly a 'call' to a finally funclet for a local unwind
4222 // or a 'return' from a catch handler (that can go just about anywhere)
4223 // This routine attempts to validate that any branches across funclets
4224 // meets one of those criteria...
4225 assert(jmp->idIsBound());
4227 #ifdef _TARGET_XARCH_
4228 // An lea of a code address (for constant data stored with the code)
4229 // is treated like a jump for emission purposes but is not really a jump so
4230 // we don't have to check anything here.
4231 if (jmp->idIns() == INS_lea)
4237 #ifdef _TARGET_ARMARCH_
4238 if (jmp->idAddr()->iiaHasInstrCount())
4240 // Too hard to figure out funclets from just an instruction count
4241 // You're on your own!
4244 #endif // _TARGET_ARMARCH_
4246 #ifdef _TARGET_ARM64_
4247 // No interest if it's not jmp.
4248 if (emitIsLoadLabel(jmp) || emitIsLoadConstant(jmp))
4252 #endif // _TARGET_ARM64_
4254 insGroup* tgtIG = jmp->idAddr()->iiaIGlabel;
4256 if (tgtIG->igFuncIdx != jmpIG->igFuncIdx)
4258 if (jmp->idDebugOnlyInfo()->idFinallyCall)
4260 // We don't record enough information to determine this accurately, so instead
4261 // we assume that any branch to the very start of a finally is OK.
4263 // No branches back to the root method
4264 assert(tgtIG->igFuncIdx > 0);
4265 FuncInfoDsc* tgtFunc = emitComp->funGetFunc(tgtIG->igFuncIdx);
4266 assert(tgtFunc->funKind == FUNC_HANDLER);
4267 EHblkDsc* tgtEH = emitComp->ehGetDsc(tgtFunc->funEHIndex);
4269 // Only branches to finallys (not faults, catches, filters, etc.)
4270 assert(tgtEH->HasFinallyHandler());
4272 // Only to the first block of the finally (which is properly marked)
4273 BasicBlock* tgtBlk = tgtEH->ebdHndBeg;
4274 assert(tgtBlk->bbFlags & BBF_FUNCLET_BEG);
4276 // And now we made it back to where we started
4277 assert(tgtIG == emitCodeGetCookie(tgtBlk));
4278 assert(tgtIG->igFuncIdx == emitComp->funGetFuncIdx(tgtBlk));
4280 else if (jmp->idDebugOnlyInfo()->idCatchRet)
4282 // Again there isn't enough information to prove this correct
4283 // so just allow a 'branch' to any other 'parent' funclet
4285 FuncInfoDsc* jmpFunc = emitComp->funGetFunc(jmpIG->igFuncIdx);
4286 assert(jmpFunc->funKind == FUNC_HANDLER);
4287 EHblkDsc* jmpEH = emitComp->ehGetDsc(jmpFunc->funEHIndex);
4289 // Only branches out of catches
4290 assert(jmpEH->HasCatchHandler());
4292 FuncInfoDsc* tgtFunc = emitComp->funGetFunc(tgtIG->igFuncIdx);
4294 if (tgtFunc->funKind == FUNC_HANDLER)
4296 // An outward chain to the containing funclet/EH handler
4297 // Note that it might be anywhere within nested try bodies
4298 assert(jmpEH->ebdEnclosingHndIndex == tgtFunc->funEHIndex);
4302 // This funclet is 'top level' and so it is branching back to the
4303 // root function, and should have no containing EH handlers
4304 // but it could be nested within try bodies...
4305 assert(tgtFunc->funKind == FUNC_ROOT);
4306 assert(jmpEH->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX);
4311 printf("Hit an illegal branch between funclets!");
4312 assert(tgtIG->igFuncIdx == jmpIG->igFuncIdx);
4318 /*****************************************************************************
4320 * Compute the code sizes that we're going to use to allocate the code buffers.
4324 * emitTotalHotCodeSize
4325 * emitTotalColdCodeSize
4326 * Compiler::info.compTotalHotCodeSize
4327 * Compiler::info.compTotalColdCodeSize
4330 void emitter::emitComputeCodeSizes()
4332 assert((emitComp->fgFirstColdBlock == nullptr) == (emitFirstColdIG == nullptr));
4334 if (emitFirstColdIG)
4336 emitTotalHotCodeSize = emitFirstColdIG->igOffs;
4337 emitTotalColdCodeSize = emitTotalCodeSize - emitTotalHotCodeSize;
4341 emitTotalHotCodeSize = emitTotalCodeSize;
4342 emitTotalColdCodeSize = 0;
4345 emitComp->info.compTotalHotCodeSize = emitTotalHotCodeSize;
4346 emitComp->info.compTotalColdCodeSize = emitTotalColdCodeSize;
4349 if (emitComp->verbose)
4351 printf("\nHot code size = 0x%X bytes\n", emitTotalHotCodeSize);
4352 printf("Cold code size = 0x%X bytes\n", emitTotalColdCodeSize);
4357 /*****************************************************************************
4359 * Called at the end of code generation, this method creates the code, data
4360 * and GC info blocks for the method. Returns the size of the method (which must fit in an unsigned).
4363 unsigned emitter::emitEndCodeGen(Compiler* comp,
4364 bool contTrkPtrLcls,
4368 unsigned xcptnsCount,
4369 unsigned* prologSize,
4370 unsigned* epilogSize,
4372 void** coldCodeAddr,
4376 if (emitComp->verbose)
4378 printf("*************** In emitEndCodeGen()\n");
4386 BYTE* coldCodeBlock;
4389 assert(emitCurIG == nullptr);
4391 emitCodeBlock = nullptr;
4392 emitConsBlock = nullptr;
4394 /* Tell everyone whether we have fully interruptible code or not */
4396 emitFullyInt = fullyInt;
4397 emitFullGCinfo = fullPtrMap;
4399 #ifndef UNIX_X86_ABI
4400 emitFullArgInfo = !emitHasFramePtr;
4402 emitFullArgInfo = fullPtrMap;
4406 GCrefsTable.record(emitGCrFrameOffsCnt);
4407 emitSizeTable.record(static_cast<unsigned>(emitSizeMethod));
4408 stkDepthTable.record(emitMaxStackDepth);
4409 #endif // EMITTER_STATS
4411 // Default values, correct even if EMIT_TRACK_STACK_DEPTH is 0.
4412 emitSimpleStkUsed = true;
4413 u1.emitSimpleStkMask = 0;
4414 u1.emitSimpleByrefStkMask = 0;
4416 #if EMIT_TRACK_STACK_DEPTH
4417 /* Convert max. stack depth from # of bytes to # of entries */
4419 unsigned maxStackDepthIn4ByteElements = emitMaxStackDepth / sizeof(int);
4420 JITDUMP("Converting emitMaxStackDepth from bytes (%d) to elements (%d)\n", emitMaxStackDepth,
4421 maxStackDepthIn4ByteElements);
4422 emitMaxStackDepth = maxStackDepthIn4ByteElements;
4424 /* Should we use the simple stack */
4426 if (emitMaxStackDepth > MAX_SIMPLE_STK_DEPTH || emitFullGCinfo)
4428 /* We won't use the "simple" argument table */
4430 emitSimpleStkUsed = false;
4432 /* Allocate the argument tracking table */
4434 if (emitMaxStackDepth <= sizeof(u2.emitArgTrackLcl))
4436 u2.emitArgTrackTab = (BYTE*)u2.emitArgTrackLcl;
4440 u2.emitArgTrackTab = (BYTE*)emitGetMem(roundUp(emitMaxStackDepth));
4443 u2.emitArgTrackTop = u2.emitArgTrackTab;
4444 u2.emitGcArgTrackCnt = 0;
4448 if (emitEpilogCnt == 0)
4450 /* No epilogs, make sure the epilog size is set to 0 */
4454 #ifdef _TARGET_XARCH_
4455 emitExitSeqSize = 0;
4456 #endif // _TARGET_XARCH_
4459 /* Return the size of the epilog to the caller */
4461 *epilogSize = emitEpilogSize;
4463 #ifdef _TARGET_XARCH_
4464 *epilogSize += emitExitSeqSize;
4465 #endif // _TARGET_XARCH_
4468 if (EMIT_INSTLIST_VERBOSE)
4470 printf("\nInstruction list before instruction issue:\n\n");
4471 emitDispIGlist(true);
4474 emitCheckIGoffsets();
4477 /* Allocate the code block (and optionally the data blocks) */
4479 // If we're doing procedure splitting and we found cold blocks, then
4480 // allocate hot and cold buffers. Otherwise only allocate a hot
4483 coldCodeBlock = nullptr;
4485 CorJitAllocMemFlag allocMemFlag = CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN;
4489 // These are the heuristics we use to decide whether or not to force the
4490 // code to be 16-byte aligned.
4492 // 1. For ngen code with IBC data, use 16-byte alignment if the method
4493 // has been called more than BB_VERY_HOT_WEIGHT times.
4494 // 2. For JITed code and ngen code without IBC data, use 16-byte alignment
4495 // when the code is 16 bytes or smaller. We align small getters/setters
4496 // because of they are penalized heavily on certain hardware when not 16-byte
4497 // aligned (VSWhidbey #373938). To minimize size impact of this optimization,
4498 // we do not align large methods because of the penalty is amortized for them.
4500 if (emitComp->fgHaveProfileData())
4502 if (emitComp->fgCalledCount > (BB_VERY_HOT_WEIGHT * emitComp->fgProfileRunsCount()))
4504 allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN;
4509 if (emitTotalHotCodeSize <= 16)
4511 allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN;
4516 #ifdef _TARGET_ARM64_
4517 // For arm64, we want to allocate JIT data always adjacent to code similar to what native compiler does.
4518 // This way allows us to use a single `ldr` to access such data like float constant/jmp table.
4519 if (emitTotalColdCodeSize > 0)
4521 // JIT data might be far away from the cold code.
4522 NYI_ARM64("Need to handle fix-up to data from cold code.");
4525 UNATIVE_OFFSET roDataAlignmentDelta = 0;
4526 if (emitConsDsc.dsdOffs)
4528 UNATIVE_OFFSET roDataAlignment = TARGET_POINTER_SIZE; // 8 Byte align by default.
4529 roDataAlignmentDelta = (UNATIVE_OFFSET)ALIGN_UP(emitTotalHotCodeSize, roDataAlignment) - emitTotalHotCodeSize;
4530 assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4));
4532 emitCmpHandle->allocMem(emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs, emitTotalColdCodeSize, 0,
4533 xcptnsCount, allocMemFlag, (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock);
4535 consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta;
4538 emitCmpHandle->allocMem(emitTotalHotCodeSize, emitTotalColdCodeSize, emitConsDsc.dsdOffs, xcptnsCount, allocMemFlag,
4539 (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock);
4542 // if (emitConsDsc.dsdOffs)
4543 // printf("Cons=%08X\n", consBlock);
4545 /* Give the block addresses to the caller and other functions here */
4547 *codeAddr = emitCodeBlock = codeBlock;
4548 *coldCodeAddr = emitColdCodeBlock = coldCodeBlock;
4549 *consAddr = emitConsBlock = consBlock;
4551 /* Nothing has been pushed on the stack */
4552 CLANG_FORMAT_COMMENT_ANCHOR;
4554 #if EMIT_TRACK_STACK_DEPTH
4555 emitCurStackLvl = 0;
4558 /* Assume no live GC ref variables on entry */
4560 VarSetOps::ClearD(emitComp, emitThisGCrefVars); // This is initialized to Empty at the start of codegen.
4561 emitThisGCrefRegs = emitThisByrefRegs = RBM_NONE;
4562 emitThisGCrefVset = true;
4568 // We don't use these after this point
4570 VarSetOps::AssignNoCopy(emitComp, emitPrevGCrefVars, VarSetOps::UninitVal());
4571 emitPrevGCrefRegs = emitPrevByrefRegs = 0xBAADFEED;
4573 VarSetOps::AssignNoCopy(emitComp, emitInitGCrefVars, VarSetOps::UninitVal());
4574 emitInitGCrefRegs = emitInitByrefRegs = 0xBAADFEED;
4578 /* Initialize the GC ref variable lifetime tracking logic */
4580 codeGen->gcInfo.gcVarPtrSetInit();
4582 emitSyncThisObjOffs = -1; /* -1 means no offset set */
4583 emitSyncThisObjReg = REG_NA; /* REG_NA means not set */
4585 #ifdef JIT32_GCENCODER
4586 if (emitComp->lvaKeepAliveAndReportThis())
4588 assert(emitComp->lvaIsOriginalThisArg(0));
4589 LclVarDsc* thisDsc = &emitComp->lvaTable[0];
4591 /* If "this" (which is passed in as a register argument in REG_ARG_0)
4592 is enregistered, we normally spot the "mov REG_ARG_0 -> thisReg"
4593 in the prolog and note the location of "this" at that point.
4594 However, if 'this' is enregistered into REG_ARG_0 itself, no code
4595 will be generated in the prolog, so we explicitly need to note
4596 the location of "this" here.
4597 NOTE that we can do this even if "this" is not enregistered in
4598 REG_ARG_0, and it will result in more accurate "this" info over the
4599 prolog. However, as methods are not interruptible over the prolog,
4600 we try to save space by avoiding that.
4603 if (thisDsc->lvRegister)
4605 emitSyncThisObjReg = thisDsc->lvRegNum;
4607 if (emitSyncThisObjReg == (int)REG_ARG_0 &&
4608 (codeGen->intRegState.rsCalleeRegArgMaskLiveIn & genRegMask(REG_ARG_0)))
4612 emitGCregLiveSet(GCT_GCREF, genRegMask(REG_ARG_0),
4613 emitCodeBlock, // from offset 0
4618 /* If emitFullGCinfo==false, the we don't use any
4619 regPtrDsc's and so explictly note the location
4620 of "this" in GCEncode.cpp
4626 #endif // JIT32_GCENCODER
4628 emitContTrkPtrLcls = contTrkPtrLcls;
4630 /* Are there any GC ref variables on the stack? */
4632 if (emitGCrFrameOffsCnt)
4640 /* Allocate and clear emitGCrFrameLiveTab[]. This is the table
4641 mapping "stkOffs -> varPtrDsc". It holds a pointer to
4642 the liveness descriptor that was created when the
4643 variable became alive. When the variable becomes dead, the
4644 descriptor will be appended to the liveness descriptor list, and
4645 the entry in emitGCrFrameLiveTab[] will be made NULL.
4647 Note that if all GC refs are assigned consecutively,
4648 emitGCrFrameLiveTab[] can be only as big as the number of GC refs
4649 present, instead of lvaTrackedCount.
4652 siz = emitGCrFrameOffsCnt * sizeof(*emitGCrFrameLiveTab);
4653 emitGCrFrameLiveTab = (varPtrDsc**)emitGetMem(roundUp(siz));
4654 memset(emitGCrFrameLiveTab, 0, siz);
4656 /* Allocate and fill in emitGCrFrameOffsTab[]. This is the table
4657 mapping "varIndex -> stkOffs".
4658 Non-ptrs or reg vars have entries of -1.
4659 Entries of Tracked stack byrefs have the lower bit set to 1.
4662 emitTrkVarCnt = cnt = emitComp->lvaTrackedCount;
4664 emitGCrFrameOffsTab = tab = (int*)emitGetMem(cnt * sizeof(int));
4666 memset(emitGCrFrameOffsTab, -1, cnt * sizeof(int));
4668 /* Now fill in all the actual used entries */
4670 for (num = 0, dsc = emitComp->lvaTable, cnt = emitComp->lvaCount; num < cnt; num++, dsc++)
4672 if (!dsc->lvOnFrame || (dsc->lvIsParam && !dsc->lvIsRegArg))
4677 #if FEATURE_FIXED_OUT_ARGS
4678 if (num == emitComp->lvaOutgoingArgSpaceVar)
4682 #endif // FEATURE_FIXED_OUT_ARGS
4684 int offs = dsc->lvStkOffs;
4686 /* Is it within the interesting range of offsets */
4688 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
4690 /* Are tracked stack ptr locals laid out contiguously?
4691 If not, skip non-ptrs. The emitter is optimized to work
4692 with contiguous ptrs, but for EditNContinue, the variables
4693 are laid out in the order they occur in the local-sig.
4696 if (!emitContTrkPtrLcls)
4698 if (!emitComp->lvaIsGCTracked(dsc))
4704 unsigned indx = dsc->lvVarIndex;
4706 assert(!dsc->lvRegister);
4707 assert(dsc->lvTracked);
4708 assert(dsc->lvRefCnt != 0);
4710 assert(dsc->TypeGet() == TYP_REF || dsc->TypeGet() == TYP_BYREF);
4712 assert(indx < emitComp->lvaTrackedCount);
4714 // printf("Variable #%2u/%2u is at stack offset %d\n", num, indx, offs);
4716 #ifdef JIT32_GCENCODER
4717 #ifndef WIN64EXCEPTIONS
4718 /* Remember the frame offset of the "this" argument for synchronized methods */
4719 if (emitComp->lvaIsOriginalThisArg(num) && emitComp->lvaKeepAliveAndReportThis())
4721 emitSyncThisObjOffs = offs;
4722 offs |= this_OFFSET_FLAG;
4725 #endif // JIT32_GCENCODER
4727 if (dsc->TypeGet() == TYP_BYREF)
4729 offs |= byref_OFFSET_FLAG;
4739 emitGCrFrameOffsTab = nullptr;
4744 if (emitComp->verbose)
4746 printf("\n***************************************************************************\n");
4747 printf("Instructions as they come out of the scheduler\n\n");
4751 /* Issue all instruction groups in order */
4754 #define DEFAULT_CODE_BUFFER_INIT 0xcc
4756 for (ig = emitIGlist; ig; ig = ig->igNext)
4758 assert(!(ig->igFlags & IGF_PLACEHOLDER)); // There better not be any placeholder groups left
4760 /* Is this the first cold block? */
4761 if (ig == emitFirstColdIG)
4763 unsigned actualHotCodeSize = emitCurCodeOffs(cp);
4765 /* Fill in eventual unused space */
4766 while (emitCurCodeOffs(cp) < emitTotalHotCodeSize)
4768 *cp++ = DEFAULT_CODE_BUFFER_INIT;
4771 assert(coldCodeBlock);
4774 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
4776 printf("\n************** Beginning of cold code **************\n");
4781 /* Are we overflowing? */
4782 if (ig->igNext && ig->igNum + 1 != ig->igNext->igNum)
4784 NO_WAY("Too many instruction groups");
4787 // If this instruction group is returned to from a funclet implementing a finally,
4788 // on architectures where it is necessary generate GC info for the current instruction as
4789 // if it were the instruction following a call.
4790 emitGenGCInfoIfFuncletRetTarget(ig, cp);
4792 instrDesc* id = (instrDesc*)ig->igData;
4796 /* Print the IG label, but only if it is a branch label */
4798 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
4800 if (emitComp->verbose)
4803 emitDispIG(ig); // Display the flags, IG data, etc.
4807 printf("\nG_M%03u_IG%02u:\n", Compiler::s_compMethodsCount, ig->igNum);
4815 /* Record the actual offset of the block, noting the difference */
4817 emitOffsAdj = ig->igOffs - emitCurCodeOffs(cp);
4818 assert(emitOffsAdj >= 0);
4821 if ((emitOffsAdj != 0) && emitComp->verbose)
4823 printf("Block predicted offs = %08X, actual = %08X -> size adj = %d\n", ig->igOffs, emitCurCodeOffs(cp),
4826 #endif // DEBUG_EMIT
4828 ig->igOffs = emitCurCodeOffs(cp);
4829 assert(IsCodeAligned(ig->igOffs));
4831 #if EMIT_TRACK_STACK_DEPTH
4833 /* Set the proper stack level if appropriate */
4835 if (ig->igStkLvl != emitCurStackLvl)
4837 /* We are pushing stuff implicitly at this label */
4839 assert((unsigned)ig->igStkLvl > (unsigned)emitCurStackLvl);
4840 emitStackPushN(cp, (ig->igStkLvl - (unsigned)emitCurStackLvl) / sizeof(int));
4845 /* Update current GC information for non-overflow IG (not added implicitly by the emitter) */
4847 if (!(ig->igFlags & IGF_EMIT_ADD))
4849 /* Is there a new set of live GC ref variables? */
4851 if (ig->igFlags & IGF_GC_VARS)
4853 emitUpdateLiveGCvars(ig->igGCvars(), cp);
4855 else if (!emitThisGCrefVset)
4857 emitUpdateLiveGCvars(emitThisGCrefVars, cp);
4860 /* Update the set of live GC ref registers */
4863 regMaskTP GCregs = ig->igGCregs;
4865 if (GCregs != emitThisGCrefRegs)
4867 emitUpdateLiveGCregs(GCT_GCREF, GCregs, cp);
4871 /* Is there a new set of live byref registers? */
4873 if (ig->igFlags & IGF_BYREF_REGS)
4875 unsigned byrefRegs = ig->igByrefRegs();
4877 if (byrefRegs != emitThisByrefRegs)
4879 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, cp);
4885 // These are not set for "overflow" groups
4886 assert(!(ig->igFlags & IGF_GC_VARS));
4887 assert(!(ig->igFlags & IGF_BYREF_REGS));
4890 /* Issue each instruction in order */
4894 for (unsigned cnt = ig->igInsCnt; cnt; cnt--)
4896 castto(id, BYTE*) += emitIssue1Instr(ig, id, &cp);
4899 emitCurIG = nullptr;
4901 assert(ig->igSize >= cp - bp);
4902 ig->igSize = (unsigned short)(cp - bp);
4905 #if EMIT_TRACK_STACK_DEPTH
4906 assert(emitCurStackLvl == 0);
4909 /* Output any initialized data we may have */
4911 if (emitConsDsc.dsdOffs)
4913 emitOutputDataSec(&emitConsDsc, consBlock);
4916 /* Make sure all GC ref variables are marked as dead */
4918 if (emitGCrFrameOffsCnt)
4924 for (vn = 0, of = emitGCrFrameOffsMin, dp = emitGCrFrameLiveTab; vn < emitGCrFrameOffsCnt;
4925 vn++, of += TARGET_POINTER_SIZE, dp++)
4929 emitGCvarDeadSet(of, cp, vn);
4934 /* No GC registers are live any more */
4936 if (emitThisByrefRegs)
4938 emitUpdateLiveGCregs(GCT_BYREF, RBM_NONE, cp);
4940 if (emitThisGCrefRegs)
4942 emitUpdateLiveGCregs(GCT_GCREF, RBM_NONE, cp);
4945 /* Patch any forward jumps */
4951 for (jmp = emitJumpList; jmp; jmp = jmp->idjNext)
4954 #ifdef _TARGET_XARCH_
4955 assert(jmp->idInsFmt() == IF_LABEL || jmp->idInsFmt() == IF_RWR_LABEL || jmp->idInsFmt() == IF_SWR_LABEL);
4957 tgt = jmp->idAddr()->iiaIGlabel;
4959 if (jmp->idjTemp.idjAddr == nullptr)
4964 if (jmp->idjOffs != tgt->igOffs)
4966 BYTE* adr = jmp->idjTemp.idjAddr;
4967 int adj = jmp->idjOffs - tgt->igOffs;
4969 // On Arm, the offset is encoded in unit of 2 bytes.
4974 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4977 printf("[5] This output is broken for ARM, since it doesn't properly decode the jump offsets of "
4978 "the instruction at adr\n");
4981 if (INTERESTING_JUMP_NUM == 0)
4983 printf("[5] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
4988 printf("[5] Jump is at %08X\n", (adr + 1 - emitCodeBlock));
4989 printf("[5] Jump distance is %02X - %02X = %02X\n", *(BYTE*)adr, adj, *(BYTE*)adr - adj);
4993 printf("[5] Jump is at %08X\n", (adr + 4 - emitCodeBlock));
4994 printf("[5] Jump distance is %08X - %02X = %08X\n", *(int*)adr, adj, *(int*)adr - adj);
4997 #endif // DEBUG_EMIT
5001 // Patch Forward Short Jump
5002 CLANG_FORMAT_COMMENT_ANCHOR;
5003 #if defined(_TARGET_XARCH_)
5004 *(BYTE*)adr -= (BYTE)adj;
5005 #elif defined(_TARGET_ARM_)
5006 // The following works because the jump offset is in the low order bits of the instruction.
5007 // Presumably we could also just call "emitOutputLJ(NULL, adr, jmp)", like for long jumps?
5008 *(short int*)adr -= (short)adj;
5009 #elif defined(_TARGET_ARM64_)
5010 assert(!jmp->idAddr()->iiaHasInstrCount());
5011 emitOutputLJ(NULL, adr, jmp);
5013 #error Unsupported or unset target architecture
5018 // Patch Forward non-Short Jump
5019 CLANG_FORMAT_COMMENT_ANCHOR;
5020 #if defined(_TARGET_XARCH_)
5022 #elif defined(_TARGET_ARMARCH_)
5023 assert(!jmp->idAddr()->iiaHasInstrCount());
5024 emitOutputLJ(NULL, adr, jmp);
5026 #error Unsupported or unset target architecture
5034 if (emitComp->opts.disAsm)
5039 if (emitComp->verbose)
5041 printf("Allocated method code size = %4u , actual size = %4u\n", emitTotalCodeSize, cp - codeBlock);
5045 unsigned actualCodeSize = emitCurCodeOffs(cp);
5047 /* Fill in eventual unused space */
5048 while (emitCurCodeOffs(cp) < emitTotalCodeSize)
5050 *cp++ = DEFAULT_CODE_BUFFER_INIT;
5054 totAllocdSize += emitTotalCodeSize;
5055 totActualSize += actualCodeSize;
5060 // Make sure these didn't change during the "issuing" phase
5062 assert(VarSetOps::MayBeUninit(emitPrevGCrefVars));
5063 assert(emitPrevGCrefRegs == 0xBAADFEED);
5064 assert(emitPrevByrefRegs == 0xBAADFEED);
5066 assert(VarSetOps::MayBeUninit(emitInitGCrefVars));
5067 assert(emitInitGCrefRegs == 0xBAADFEED);
5068 assert(emitInitByrefRegs == 0xBAADFEED);
5072 // Assign the real prolog size
5073 *prologSize = emitCodeOffset(emitPrologIG, emitPrologEndPos);
5075 /* Return the amount of code we've generated */
5077 return actualCodeSize;
5080 // See specification comment at the declaration.
5081 void emitter::emitGenGCInfoIfFuncletRetTarget(insGroup* ig, BYTE* cp)
5083 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
5084 // We only emit this GC information on targets where finally's are implemented via funclets,
5085 // and the finally is invoked, during non-exceptional execution, via a branch with a predefined
5086 // link register, rather than a "true call" for which we would already generate GC info. Currently,
5087 // this means precisely ARM.
5088 if (ig->igFlags & IGF_FINALLY_TARGET)
5090 // We don't actually have a call instruction in this case, so we don't have
5091 // a real size for that instruction. We'll use 1.
5092 emitStackPop(cp, /*isCall*/ true, /*callInstrSize*/ 1, /*args*/ 0);
5094 /* Do we need to record a call location for GC purposes? */
5095 if (!emitFullGCinfo)
5097 emitRecordGCcall(cp, /*callInstrSize*/ 1);
5100 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
5103 /*****************************************************************************
5105 * We have an instruction in an insGroup and we need to know the
5106 * instruction number for this instruction
5109 unsigned emitter::emitFindInsNum(insGroup* ig, instrDesc* idMatch)
5111 instrDesc* id = (instrDesc*)ig->igData;
5113 // Check if we are the first instruction in the group
5119 /* Walk the list of instructions until we find a match */
5120 unsigned insNum = 0;
5121 unsigned insRemaining = ig->igInsCnt;
5123 while (insRemaining > 0)
5125 castto(id, BYTE*) += emitSizeOfInsDsc(id);
5134 assert(!"emitFindInsNum failed");
5138 /*****************************************************************************
5140 * We've been asked for the code offset of an instruction but alas one or
5141 * more instruction sizes in the block have been mis-predicted, so we have
5142 * to find the true offset by looking for the instruction within the group.
5145 UNATIVE_OFFSET emitter::emitFindOffset(insGroup* ig, unsigned insNum)
5147 instrDesc* id = (instrDesc*)ig->igData;
5148 UNATIVE_OFFSET of = 0;
5151 /* Make sure we were passed reasonable arguments */
5152 assert(ig && ig->igSelf == ig);
5153 assert(ig->igInsCnt >= insNum);
5156 /* Walk the instruction list until all are counted */
5160 of += emitInstCodeSz(id);
5162 castto(id, BYTE*) += emitSizeOfInsDsc(id);
5170 /*****************************************************************************
5172 * Start generating a constant data section for the current
5173 * function. Returns the offset of the section in the appropriate data
5177 UNATIVE_OFFSET emitter::emitDataGenBeg(UNATIVE_OFFSET size, bool dblAlign, bool codeLtab)
5180 dataSection* secDesc;
5182 assert(emitDataSecCur == nullptr);
5184 /* The size better not be some kind of an odd thing */
5186 assert(size && size % sizeof(int) == 0);
5188 /* Get hold of the current offset */
5190 secOffs = emitConsDsc.dsdOffs;
5192 /* Are we require to align this request on an eight byte boundry? */
5193 if (dblAlign && (secOffs % sizeof(double) != 0))
5195 /* Need to skip 4 bytes to honor dblAlign */
5196 /* Must allocate a dummy 4 byte integer */
5198 emitDataGenBeg(4, false, false);
5199 emitDataGenData(0, &zero, 4);
5202 /* Get the new secOffs */
5203 secOffs = emitConsDsc.dsdOffs;
5204 /* Now it should be a multiple of 8 */
5205 assert(secOffs % sizeof(double) == 0);
5208 /* Advance the current offset */
5210 emitConsDsc.dsdOffs += size;
5212 /* Allocate a data section descriptor and add it to the list */
5214 secDesc = emitDataSecCur = (dataSection*)emitGetMem(roundUp(sizeof(*secDesc) + size));
5216 secDesc->dsSize = size;
5218 secDesc->dsType = dataSection::data;
5220 secDesc->dsNext = nullptr;
5222 if (emitConsDsc.dsdLast)
5224 emitConsDsc.dsdLast->dsNext = secDesc;
5228 emitConsDsc.dsdList = secDesc;
5230 emitConsDsc.dsdLast = secDesc;
5235 // Start generating a constant data section for the current function
5236 // populated with BasicBlock references.
5237 // You can choose the references to be either absolute pointers, or
5238 // 4-byte relative addresses.
5239 // Currently the relative references are relative to the start of the
5240 // first block (this is somewhat arbitrary)
5242 UNATIVE_OFFSET emitter::emitBBTableDataGenBeg(unsigned numEntries, bool relativeAddr)
5245 dataSection* secDesc;
5247 assert(emitDataSecCur == nullptr);
5249 UNATIVE_OFFSET emittedSize;
5253 emittedSize = numEntries * 4;
5257 emittedSize = numEntries * TARGET_POINTER_SIZE;
5260 /* Get hold of the current offset */
5262 secOffs = emitConsDsc.dsdOffs;
5264 /* Advance the current offset */
5266 emitConsDsc.dsdOffs += emittedSize;
5268 /* Allocate a data section descriptor and add it to the list */
5270 secDesc = emitDataSecCur = (dataSection*)emitGetMem(roundUp(sizeof(*secDesc) + numEntries * sizeof(BasicBlock*)));
5272 secDesc->dsSize = emittedSize;
5274 secDesc->dsType = relativeAddr ? dataSection::blockRelative32 : dataSection::blockAbsoluteAddr;
5276 secDesc->dsNext = nullptr;
5278 if (emitConsDsc.dsdLast)
5280 emitConsDsc.dsdLast->dsNext = secDesc;
5284 emitConsDsc.dsdList = secDesc;
5287 emitConsDsc.dsdLast = secDesc;
5292 /*****************************************************************************
5294 * Emit the given block of bits into the current data section.
5297 void emitter::emitDataGenData(unsigned offs, const void* data, size_t size)
5299 assert(emitDataSecCur && (emitDataSecCur->dsSize >= offs + size));
5301 assert(emitDataSecCur->dsType == dataSection::data);
5303 memcpy(emitDataSecCur->dsCont + offs, data, size);
5306 /*****************************************************************************
5308 * Emit the address of the given basic block into the current data section.
5311 void emitter::emitDataGenData(unsigned index, BasicBlock* label)
5313 assert(emitDataSecCur != nullptr);
5314 assert(emitDataSecCur->dsType == dataSection::blockAbsoluteAddr ||
5315 emitDataSecCur->dsType == dataSection::blockRelative32);
5317 unsigned emittedElemSize = emitDataSecCur->dsType == dataSection::blockAbsoluteAddr ? TARGET_POINTER_SIZE : 4;
5319 assert(emitDataSecCur->dsSize >= emittedElemSize * (index + 1));
5321 ((BasicBlock**)(emitDataSecCur->dsCont))[index] = label;
5324 /*****************************************************************************
5326 * We're done generating a data section.
5329 void emitter::emitDataGenEnd()
5333 assert(emitDataSecCur);
5334 emitDataSecCur = nullptr;
5338 /********************************************************************************
5339 * Generates a data section constant
5342 * cnsAddr - memory location containing constant value
5343 * cnsSize - size of constant in bytes
5344 * dblAlign - whether to double align the data section constant
5346 * Returns constant number as offset into data section.
5348 UNATIVE_OFFSET emitter::emitDataConst(const void* cnsAddr, unsigned cnsSize, bool dblAlign)
5350 // When generating SMALL_CODE, we don't bother with dblAlign
5351 if (dblAlign && (emitComp->compCodeOpt() == Compiler::SMALL_CODE))
5356 UNATIVE_OFFSET cnum = emitDataGenBeg(cnsSize, dblAlign, false);
5357 emitDataGenData(0, cnsAddr, cnsSize);
5363 #ifndef LEGACY_BACKEND
5365 //------------------------------------------------------------------------
5366 // emitAnyConst: Create a data section constant of arbitrary size.
5369 // cnsAddr - pointer to the data to be placed in the data section
5370 // cnsSize - size of the data
5371 // dblAlign - whether to align the data section to an 8 byte boundary
5374 // A field handle representing the data offset to access the constant.
5376 CORINFO_FIELD_HANDLE emitter::emitAnyConst(const void* cnsAddr, unsigned cnsSize, bool dblAlign)
5378 UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
5379 return emitComp->eeFindJitDataOffs(cnum);
5382 //------------------------------------------------------------------------
5383 // emitFltOrDblConst: Create a float or double data section constant.
5386 // constValue - constant value
5387 // attr - constant size
5390 // A field handle representing the data offset to access the constant.
5393 // If attr is EA_4BYTE then the double value is converted to a float value.
5394 // If attr is EA_8BYTE then 8 byte alignment is automatically requested.
5396 CORINFO_FIELD_HANDLE emitter::emitFltOrDblConst(double constValue, emitAttr attr)
5398 assert((attr == EA_4BYTE) || (attr == EA_8BYTE));
5404 if (attr == EA_4BYTE)
5406 f = forceCastToFloat(constValue);
5412 cnsAddr = &constValue;
5416 // Access to inline data is 'abstracted' by a special type of static member
5417 // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
5418 // to constant data, not a real static field.
5420 UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
5421 UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
5422 return emitComp->eeFindJitDataOffs(cnum);
5426 /*****************************************************************************
5428 * Output the given data section at the specified address.
5431 void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst)
5436 printf("\nEmitting data sections: %u total bytes\n", sec->dsdOffs);
5439 unsigned secNum = 0;
5443 assert(sec->dsdOffs);
5444 assert(sec->dsdList);
5446 /* Walk and emit the contents of all the data blocks */
5450 for (dsc = sec->dsdList; dsc; dsc = dsc->dsNext)
5452 size_t dscSize = dsc->dsSize;
5454 // absolute label table
5455 if (dsc->dsType == dataSection::blockAbsoluteAddr)
5457 JITDUMP(" section %u, size %u, block absolute addr\n", secNum++, dscSize);
5459 assert(dscSize && dscSize % TARGET_POINTER_SIZE == 0);
5460 size_t numElems = dscSize / TARGET_POINTER_SIZE;
5461 target_size_t* bDst = (target_size_t*)dst;
5462 for (unsigned i = 0; i < numElems; i++)
5464 BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i];
5466 // Convert the BasicBlock* value to an IG address
5467 insGroup* lab = (insGroup*)emitCodeGetCookie(block);
5469 // Append the appropriate address to the destination
5470 BYTE* target = emitOffsetToPtr(lab->igOffs);
5473 target = (BYTE*)((size_t)target | 1); // Or in thumb bit
5475 bDst[i] = (target_size_t)target;
5476 if (emitComp->opts.compReloc)
5478 emitRecordRelocation(&(bDst[i]), target, IMAGE_REL_BASED_HIGHLOW);
5481 JITDUMP(" BB%02u: 0x%p\n", block->bbNum, bDst[i]);
5484 // relative label table
5485 else if (dsc->dsType == dataSection::blockRelative32)
5487 JITDUMP(" section %u, size %u, block relative addr\n", secNum++, dscSize);
5489 unsigned elemSize = 4;
5490 size_t numElems = dscSize / 4;
5491 unsigned* uDst = (unsigned*)dst;
5492 insGroup* labFirst = (insGroup*)emitCodeGetCookie(emitComp->fgFirstBB);
5494 for (unsigned i = 0; i < numElems; i++)
5496 BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i];
5498 // Convert the BasicBlock* value to an IG address
5499 insGroup* lab = (insGroup*)emitCodeGetCookie(block);
5501 assert(FitsIn<uint32_t>(lab->igOffs - labFirst->igOffs));
5502 uDst[i] = lab->igOffs - labFirst->igOffs;
5504 JITDUMP(" BB%02u: 0x%x\n", block->bbNum, uDst[i]);
5509 JITDUMP(" section %u, size %u, raw data\n", secNum++, dscSize);
5511 // Simple binary data: copy the bytes to the target
5512 assert(dsc->dsType == dataSection::data);
5514 memcpy(dst, dsc->dsCont, dscSize);
5520 for (size_t i = 0; i < dscSize; i++)
5522 printf("%02x ", dsc->dsCont[i]);
5523 if ((((i + 1) % 16) == 0) && (i + 1 != dscSize))
5536 /*****************************************************************************/
5537 /*****************************************************************************
5539 * Record the fact that the given variable now contains a live GC ref.
5542 void emitter::emitGCvarLiveSet(int offs, GCtype gcType, BYTE* addr, ssize_t disp)
5544 assert(emitIssuing);
5548 assert((abs(offs) % TARGET_POINTER_SIZE) == 0);
5549 assert(needsGC(gcType));
5551 /* Compute the index into the GC frame table if the caller didn't do it */
5555 disp = (offs - emitGCrFrameOffsMin) / TARGET_POINTER_SIZE;
5558 assert((size_t)disp < emitGCrFrameOffsCnt);
5560 /* Allocate a lifetime record */
5562 desc = new (emitComp, CMK_GC) varPtrDsc;
5564 desc->vpdBegOfs = emitCurCodeOffs(addr);
5566 desc->vpdEndOfs = 0xFACEDEAD;
5569 desc->vpdVarNum = offs;
5571 desc->vpdNext = nullptr;
5573 #if !defined(JIT32_GCENCODER) || !defined(WIN64EXCEPTIONS)
5574 /* the lower 2 bits encode props about the stk ptr */
5576 if (offs == emitSyncThisObjOffs)
5578 desc->vpdVarNum |= this_OFFSET_FLAG;
5582 if (gcType == GCT_BYREF)
5584 desc->vpdVarNum |= byref_OFFSET_FLAG;
5587 /* Append the new entry to the end of the list */
5588 if (codeGen->gcInfo.gcVarPtrLast == nullptr)
5590 assert(codeGen->gcInfo.gcVarPtrList == nullptr);
5591 codeGen->gcInfo.gcVarPtrList = codeGen->gcInfo.gcVarPtrLast = desc;
5595 assert(codeGen->gcInfo.gcVarPtrList != nullptr);
5596 codeGen->gcInfo.gcVarPtrLast->vpdNext = desc;
5597 codeGen->gcInfo.gcVarPtrLast = desc;
5600 /* Record the variable descriptor in the table */
5602 assert(emitGCrFrameLiveTab[disp] == nullptr);
5603 emitGCrFrameLiveTab[disp] = desc;
5608 printf("[%08X] %s var born at [%s", dspPtr(desc), GCtypeStr(gcType), emitGetFrameReg());
5612 printf("-%02XH", -offs);
5616 printf("+%02XH", +offs);
5623 /* The "global" live GC variable mask is no longer up-to-date */
5625 emitThisGCrefVset = false;
5628 /*****************************************************************************
5630 * Record the fact that the given variable no longer contains a live GC ref.
5633 void emitter::emitGCvarDeadSet(int offs, BYTE* addr, ssize_t disp)
5635 assert(emitIssuing);
5639 assert(abs(offs) % sizeof(int) == 0);
5641 /* Compute the index into the GC frame table if the caller didn't do it */
5645 disp = (offs - emitGCrFrameOffsMin) / TARGET_POINTER_SIZE;
5648 assert((unsigned)disp < emitGCrFrameOffsCnt);
5650 /* Get hold of the lifetime descriptor and clear the entry */
5652 desc = emitGCrFrameLiveTab[disp];
5653 emitGCrFrameLiveTab[disp] = nullptr;
5656 assert((desc->vpdVarNum & ~OFFSET_MASK) == (unsigned)offs);
5658 /* Record the death code offset */
5660 assert(desc->vpdEndOfs == 0xFACEDEAD);
5661 desc->vpdEndOfs = emitCurCodeOffs(addr);
5666 GCtype gcType = (desc->vpdVarNum & byref_OFFSET_FLAG) ? GCT_BYREF : GCT_GCREF;
5667 #if !defined(JIT32_GCENCODER) || !defined(WIN64EXCEPTIONS)
5668 bool isThis = (desc->vpdVarNum & this_OFFSET_FLAG) != 0;
5670 printf("[%08X] %s%s var died at [%s", dspPtr(desc), GCtypeStr(gcType), isThis ? "this-ptr" : "",
5673 bool isPinned = (desc->vpdVarNum & pinned_OFFSET_FLAG) != 0;
5675 printf("[%08X] %s%s var died at [%s", dspPtr(desc), GCtypeStr(gcType), isPinned ? "pinned" : "",
5681 printf("-%02XH", -offs);
5685 printf("+%02XH", +offs);
5692 /* The "global" live GC variable mask is no longer up-to-date */
5694 emitThisGCrefVset = false;
5697 /*****************************************************************************
5699 * Record a new set of live GC ref variables.
5702 void emitter::emitUpdateLiveGCvars(VARSET_VALARG_TP vars, BYTE* addr)
5704 assert(emitIssuing);
5706 // Don't track GC changes in epilogs
5707 if (emitIGisInEpilog(emitCurIG))
5712 /* Is the current set accurate and unchanged? */
5714 if (emitThisGCrefVset && VarSetOps::Equal(emitComp, emitThisGCrefVars, vars))
5720 if (EMIT_GC_VERBOSE)
5722 printf("New GC ref live vars=%s ", VarSetOps::ToString(emitComp, vars));
5723 dumpConvertedVarSet(emitComp, vars);
5728 VarSetOps::Assign(emitComp, emitThisGCrefVars, vars);
5730 /* Are there any GC ref variables on the stack? */
5732 if (emitGCrFrameOffsCnt)
5735 unsigned cnt = emitTrkVarCnt;
5738 /* Test all the tracked variable bits in the mask */
5740 for (num = 0, tab = emitGCrFrameOffsTab; num < cnt; num++, tab++)
5746 // byref_OFFSET_FLAG and this_OFFSET_FLAG are set
5747 // in the table-offsets for byrefs and this-ptr
5749 int offs = val & ~OFFSET_MASK;
5751 // printf("var #%2u at %3d is now %s\n", num, offs, (vars & 1) ? "live" : "dead");
5753 if (VarSetOps::IsMember(emitComp, vars, num))
5755 GCtype gcType = (val & byref_OFFSET_FLAG) ? GCT_BYREF : GCT_GCREF;
5756 emitGCvarLiveUpd(offs, INT_MAX, gcType, addr);
5760 emitGCvarDeadUpd(offs, addr);
5766 emitThisGCrefVset = true;
5769 /*****************************************************************************
5771 * Record a call location for GC purposes (we know that this is a method that
5772 * will not be fully interruptible).
5775 void emitter::emitRecordGCcall(BYTE* codePos, unsigned char callInstrSize)
5777 assert(emitIssuing);
5778 assert(!emitFullGCinfo);
5780 unsigned offs = emitCurCodeOffs(codePos);
5781 unsigned regs = (emitThisGCrefRegs | emitThisByrefRegs) & ~RBM_INTRET;
5784 #ifdef JIT32_GCENCODER
5785 // The JIT32 GCInfo encoder allows us to (as the comment previously here said):
5786 // "Bail if this is a totally boring call", but the GCInfoEncoder/Decoder interface
5787 // requires a definition for every call site, so we skip these "early outs" when we're
5788 // using the general encoder.
5791 #if EMIT_TRACK_STACK_DEPTH
5792 if (emitCurStackLvl == 0)
5795 /* Nope, only interesting calls get recorded */
5797 if (emitSimpleStkUsed)
5799 if (!u1.emitSimpleStkMask)
5804 if (u2.emitGcArgTrackCnt == 0)
5808 #endif // JIT32_GCENCODER
5812 if (EMIT_GC_VERBOSE)
5814 printf("; Call at %04X [stk=%u], GCvars=", offs - callInstrSize, emitCurStackLvl);
5816 printf(", gcrefRegs=");
5817 printRegMaskInt(emitThisGCrefRegs);
5818 emitDispRegSet(emitThisGCrefRegs);
5819 // printRegMaskInt(emitThisGCrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5820 // emitDispRegSet (emitThisGCrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5821 printf(", byrefRegs=");
5822 printRegMaskInt(emitThisByrefRegs);
5823 emitDispRegSet(emitThisByrefRegs);
5824 // printRegMaskInt(emitThisByrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5825 // emitDispRegSet (emitThisByrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5831 /* Allocate a 'call site' descriptor and start filling it in */
5833 call = new (emitComp, CMK_GC) callDsc;
5835 call->cdBlock = nullptr;
5836 call->cdOffs = offs;
5837 #ifndef JIT32_GCENCODER
5838 call->cdCallInstrSize = callInstrSize;
5840 call->cdNext = nullptr;
5842 call->cdGCrefRegs = (regMaskSmall)emitThisGCrefRegs;
5843 call->cdByrefRegs = (regMaskSmall)emitThisByrefRegs;
5845 #if EMIT_TRACK_STACK_DEPTH
5846 #ifndef FEATURE_UNIX_AMD64_STRUCT_PASSING
5847 noway_assert(FitsIn<USHORT>(emitCurStackLvl / ((unsigned)sizeof(unsigned))));
5848 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
5851 // Append the call descriptor to the list */
5852 if (codeGen->gcInfo.gcCallDescLast == nullptr)
5854 assert(codeGen->gcInfo.gcCallDescList == nullptr);
5855 codeGen->gcInfo.gcCallDescList = codeGen->gcInfo.gcCallDescLast = call;
5859 assert(codeGen->gcInfo.gcCallDescList != nullptr);
5860 codeGen->gcInfo.gcCallDescLast->cdNext = call;
5861 codeGen->gcInfo.gcCallDescLast = call;
5864 /* Record the current "pending" argument list */
5866 if (emitSimpleStkUsed)
5868 /* The biggest call is less than MAX_SIMPLE_STK_DEPTH. So use
5871 call->u1.cdArgMask = u1.emitSimpleStkMask;
5872 call->u1.cdByrefArgMask = u1.emitSimpleByrefStkMask;
5877 /* The current call has too many arguments, so we need to report the
5878 offsets of each individual GC arg. */
5880 call->cdArgCnt = u2.emitGcArgTrackCnt;
5881 if (call->cdArgCnt == 0)
5883 call->u1.cdArgMask = call->u1.cdByrefArgMask = 0;
5887 call->cdArgTable = new (emitComp, CMK_GC) unsigned[u2.emitGcArgTrackCnt];
5889 unsigned gcArgs = 0;
5890 unsigned stkLvl = emitCurStackLvl / sizeof(int);
5892 for (unsigned i = 0; i < stkLvl; i++)
5894 GCtype gcType = (GCtype)u2.emitArgTrackTab[stkLvl - i - 1];
5896 if (needsGC(gcType))
5898 call->cdArgTable[gcArgs] = i * TARGET_POINTER_SIZE;
5900 if (gcType == GCT_BYREF)
5902 call->cdArgTable[gcArgs] |= byref_OFFSET_FLAG;
5909 assert(gcArgs == u2.emitGcArgTrackCnt);
5913 /*****************************************************************************
5915 * Record a new set of live GC ref registers.
5918 void emitter::emitUpdateLiveGCregs(GCtype gcType, regMaskTP regs, BYTE* addr)
5920 assert(emitIssuing);
5922 // Don't track GC changes in epilogs
5923 if (emitIGisInEpilog(emitCurIG))
5933 if (EMIT_GC_VERBOSE)
5935 printf("New %sReg live regs=", GCtypeStr(gcType));
5936 printRegMaskInt(regs);
5937 emitDispRegSet(regs);
5942 assert(needsGC(gcType));
5944 regMaskTP& emitThisXXrefRegs = (gcType == GCT_GCREF) ? emitThisGCrefRegs : emitThisByrefRegs;
5945 regMaskTP& emitThisYYrefRegs = (gcType == GCT_GCREF) ? emitThisByrefRegs : emitThisGCrefRegs;
5946 assert(emitThisXXrefRegs != regs);
5950 /* Figure out which GC registers are becoming live/dead at this point */
5952 dead = (emitThisXXrefRegs & ~regs);
5953 life = (~emitThisXXrefRegs & regs);
5955 /* Can't simultaneously become live and dead at the same time */
5957 assert((dead | life) != 0);
5958 assert((dead & life) == 0);
5960 /* Compute the 'changing state' mask */
5962 chg = (dead | life);
5966 regMaskTP bit = genFindLowestBit(chg);
5967 regNumber reg = genRegNumFromMask(bit);
5971 emitGCregLiveUpd(gcType, reg, addr);
5975 emitGCregDeadUpd(reg, addr);
5981 assert(emitThisXXrefRegs == regs);
5985 emitThisYYrefRegs &= ~regs; // Kill the regs from the other GC type (if live)
5986 emitThisXXrefRegs = regs; // Mark them as live in the requested GC type
5989 // The 2 GC reg masks can't be overlapping
5991 assert((emitThisGCrefRegs & emitThisByrefRegs) == 0);
5994 /*****************************************************************************
5996 * Record the fact that the given register now contains a live GC ref.
5999 void emitter::emitGCregLiveSet(GCtype gcType, regMaskTP regMask, BYTE* addr, bool isThis)
6001 assert(emitIssuing);
6002 assert(needsGC(gcType));
6004 regPtrDsc* regPtrNext;
6006 assert(!isThis || emitComp->lvaKeepAliveAndReportThis());
6007 // assert(emitFullyInt || isThis);
6008 assert(emitFullGCinfo);
6010 assert(((emitThisGCrefRegs | emitThisByrefRegs) & regMask) == 0);
6012 /* Allocate a new regptr entry and fill it in */
6014 regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6015 regPtrNext->rpdGCtype = gcType;
6017 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6018 regPtrNext->rpdArg = FALSE;
6019 regPtrNext->rpdCall = FALSE;
6020 regPtrNext->rpdIsThis = isThis;
6021 regPtrNext->rpdCompiler.rpdAdd = (regMaskSmall)regMask;
6022 regPtrNext->rpdCompiler.rpdDel = 0;
6025 /*****************************************************************************
6027 * Record the fact that the given register no longer contains a live GC ref.
6030 void emitter::emitGCregDeadSet(GCtype gcType, regMaskTP regMask, BYTE* addr)
6032 assert(emitIssuing);
6033 assert(needsGC(gcType));
6035 regPtrDsc* regPtrNext;
6037 // assert(emitFullyInt);
6038 assert(emitFullGCinfo);
6040 assert(((emitThisGCrefRegs | emitThisByrefRegs) & regMask) != 0);
6042 /* Allocate a new regptr entry and fill it in */
6044 regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6045 regPtrNext->rpdGCtype = gcType;
6047 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6048 regPtrNext->rpdCall = FALSE;
6049 regPtrNext->rpdIsThis = FALSE;
6050 regPtrNext->rpdArg = FALSE;
6051 regPtrNext->rpdCompiler.rpdAdd = 0;
6052 regPtrNext->rpdCompiler.rpdDel = (regMaskSmall)regMask;
6055 /*****************************************************************************
6057 * Emit an 8-bit integer as code.
6060 unsigned char emitter::emitOutputByte(BYTE* dst, ssize_t val)
6062 *castto(dst, unsigned char*) = (unsigned char)val;
6065 if (emitComp->opts.dspEmit)
6067 printf("; emit_byte 0%02XH\n", val & 0xFF);
6069 #ifdef _TARGET_AMD64_
6070 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6071 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6072 #endif // _TARGET_AMD64_
6075 return sizeof(unsigned char);
6078 /*****************************************************************************
6080 * Emit a 16-bit integer as code.
6083 unsigned char emitter::emitOutputWord(BYTE* dst, ssize_t val)
6085 MISALIGNED_WR_I2(dst, (short)val);
6088 if (emitComp->opts.dspEmit)
6090 printf("; emit_word 0%02XH,0%02XH\n", (val & 0xFF), (val >> 8) & 0xFF);
6092 #ifdef _TARGET_AMD64_
6093 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6094 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6095 #endif // _TARGET_AMD64_
6098 return sizeof(short);
6101 /*****************************************************************************
6103 * Emit a 32-bit integer as code.
6106 unsigned char emitter::emitOutputLong(BYTE* dst, ssize_t val)
6108 MISALIGNED_WR_I4(dst, (int)val);
6111 if (emitComp->opts.dspEmit)
6113 printf("; emit_long 0%08XH\n", (int)val);
6115 #ifdef _TARGET_AMD64_
6116 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6117 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6118 #endif // _TARGET_AMD64_
6124 /*****************************************************************************
6126 * Emit a pointer-sized integer as code.
6129 unsigned char emitter::emitOutputSizeT(BYTE* dst, ssize_t val)
6131 MISALIGNED_WR_ST(dst, val);
6134 if (emitComp->opts.dspEmit)
6136 #ifdef _TARGET_AMD64_
6137 printf("; emit_size_t 0%016llXH\n", val);
6138 #else // _TARGET_AMD64_
6139 printf("; emit_size_t 0%08XH\n", val);
6140 #endif // _TARGET_AMD64_
6144 return TARGET_POINTER_SIZE;
6147 //------------------------------------------------------------------------
6148 // Wrappers to emitOutputByte, emitOutputWord, emitOutputLong, emitOutputSizeT
6149 // that take unsigned __int64 or size_t type instead of ssize_t. Used on RyuJIT/x86.
6152 // dst - passed through
6153 // val - passed through
6156 // Same as wrapped function.
6159 #if !defined(LEGACY_BACKEND) && defined(_TARGET_X86_)
6160 unsigned char emitter::emitOutputByte(BYTE* dst, size_t val)
6162 return emitOutputByte(dst, (ssize_t)val);
6165 unsigned char emitter::emitOutputWord(BYTE* dst, size_t val)
6167 return emitOutputWord(dst, (ssize_t)val);
6170 unsigned char emitter::emitOutputLong(BYTE* dst, size_t val)
6172 return emitOutputLong(dst, (ssize_t)val);
6175 unsigned char emitter::emitOutputSizeT(BYTE* dst, size_t val)
6177 return emitOutputSizeT(dst, (ssize_t)val);
6180 unsigned char emitter::emitOutputByte(BYTE* dst, unsigned __int64 val)
6182 return emitOutputByte(dst, (ssize_t)val);
6185 unsigned char emitter::emitOutputWord(BYTE* dst, unsigned __int64 val)
6187 return emitOutputWord(dst, (ssize_t)val);
6190 unsigned char emitter::emitOutputLong(BYTE* dst, unsigned __int64 val)
6192 return emitOutputLong(dst, (ssize_t)val);
6195 unsigned char emitter::emitOutputSizeT(BYTE* dst, unsigned __int64 val)
6197 return emitOutputSizeT(dst, (ssize_t)val);
6199 #endif // !defined(LEGACY_BACKEND) && defined(_TARGET_X86_)
6201 /*****************************************************************************
6203 * Given a block cookie and a code position, return the actual code offset;
6204 * this can only be called at the end of code generation.
6207 UNATIVE_OFFSET emitter::emitCodeOffset(void* blockPtr, unsigned codePos)
6212 unsigned no = emitGetInsNumFromCodePos(codePos);
6214 /* Make sure we weren't passed some kind of a garbage thing */
6216 ig = (insGroup*)blockPtr;
6218 assert(ig && ig->igSelf == ig);
6221 /* The first and last offsets are always easy */
6227 else if (no == ig->igInsCnt)
6231 else if (ig->igFlags & IGF_UPD_ISZ)
6234 Some instruction sizes have changed, so we'll have to figure
6235 out the instruction offset "the hard way".
6238 of = emitFindOffset(ig, no);
6242 /* All instructions correctly predicted, the offset stays the same */
6244 of = emitGetInsOfsFromCodePos(codePos);
6246 // printf("[IG=%02u;ID=%03u;OF=%04X] <= %08X\n", ig->igNum, emitGetInsNumFromCodePos(codePos), of, codePos);
6248 /* Make sure the offset estimate is accurate */
6250 assert(of == emitFindOffset(ig, emitGetInsNumFromCodePos(codePos)));
6253 return ig->igOffs + of;
6256 /*****************************************************************************
6258 * Record the fact that the given register now contains a live GC ref.
6261 void emitter::emitGCregLiveUpd(GCtype gcType, regNumber reg, BYTE* addr)
6263 assert(emitIssuing);
6265 // Don't track GC changes in epilogs
6266 if (emitIGisInEpilog(emitCurIG))
6271 assert(needsGC(gcType));
6273 regMaskTP regMask = genRegMask(reg);
6275 regMaskTP& emitThisXXrefRegs = (gcType == GCT_GCREF) ? emitThisGCrefRegs : emitThisByrefRegs;
6276 regMaskTP& emitThisYYrefRegs = (gcType == GCT_GCREF) ? emitThisByrefRegs : emitThisGCrefRegs;
6278 if ((emitThisXXrefRegs & regMask) == 0)
6280 // If the register was holding the other GC type, that type should
6283 if (emitThisYYrefRegs & regMask)
6285 emitGCregDeadUpd(reg, addr);
6288 // For synchronized methods, "this" is always alive and in the same register.
6289 // However, if we generate any code after the epilog block (where "this"
6290 // goes dead), "this" will come alive again. We need to notice that.
6291 // Note that we only expect isThis to be true at an insGroup boundary.
6293 bool isThis = (reg == emitSyncThisObjReg) ? true : false;
6297 emitGCregLiveSet(gcType, regMask, addr, isThis);
6300 emitThisXXrefRegs |= regMask;
6303 if (EMIT_GC_VERBOSE)
6305 printf("%sReg +[%s]\n", GCtypeStr(gcType), emitRegName(reg));
6310 // The 2 GC reg masks can't be overlapping
6312 assert((emitThisGCrefRegs & emitThisByrefRegs) == 0);
6315 /*****************************************************************************
6317 * Record the fact that the given set of registers no longer contain live GC refs.
6320 void emitter::emitGCregDeadUpdMask(regMaskTP regs, BYTE* addr)
6322 assert(emitIssuing);
6324 // Don't track GC changes in epilogs
6325 if (emitIGisInEpilog(emitCurIG))
6330 // First, handle the gcref regs going dead
6332 regMaskTP gcrefRegs = emitThisGCrefRegs & regs;
6334 // "this" can never go dead in synchronized methods, except in the epilog
6335 // after the call to CORINFO_HELP_MON_EXIT.
6336 assert(emitSyncThisObjReg == REG_NA || (genRegMask(emitSyncThisObjReg) & regs) == 0);
6340 assert((emitThisByrefRegs & gcrefRegs) == 0);
6344 emitGCregDeadSet(GCT_GCREF, gcrefRegs, addr);
6347 emitThisGCrefRegs &= ~gcrefRegs;
6350 if (EMIT_GC_VERBOSE)
6353 printRegMaskInt(gcrefRegs);
6355 emitDispRegSet(gcrefRegs);
6361 // Second, handle the byref regs going dead
6363 regMaskTP byrefRegs = emitThisByrefRegs & regs;
6367 assert((emitThisGCrefRegs & byrefRegs) == 0);
6371 emitGCregDeadSet(GCT_BYREF, byrefRegs, addr);
6374 emitThisByrefRegs &= ~byrefRegs;
6377 if (EMIT_GC_VERBOSE)
6380 printRegMaskInt(byrefRegs);
6382 emitDispRegSet(byrefRegs);
6389 /*****************************************************************************
6391 * Record the fact that the given register no longer contains a live GC ref.
6394 void emitter::emitGCregDeadUpd(regNumber reg, BYTE* addr)
6396 assert(emitIssuing);
6398 // Don't track GC changes in epilogs
6399 if (emitIGisInEpilog(emitCurIG))
6404 regMaskTP regMask = genRegMask(reg);
6406 if ((emitThisGCrefRegs & regMask) != 0)
6408 assert((emitThisByrefRegs & regMask) == 0);
6412 emitGCregDeadSet(GCT_GCREF, regMask, addr);
6415 emitThisGCrefRegs &= ~regMask;
6418 if (EMIT_GC_VERBOSE)
6420 printf("%s -[%s]\n", "gcrReg", emitRegName(reg));
6424 else if ((emitThisByrefRegs & regMask) != 0)
6428 emitGCregDeadSet(GCT_BYREF, regMask, addr);
6431 emitThisByrefRegs &= ~regMask;
6434 if (EMIT_GC_VERBOSE)
6436 printf("%s -[%s]\n", "byrReg", emitRegName(reg));
6442 /*****************************************************************************
6444 * Record the fact that the given variable now contains a live GC ref.
6445 * varNum may be INT_MAX or negative (indicating a spill temp) only if
6446 * offs is guaranteed to be the offset of a tracked GC ref. Else we
6447 * need a valid value to check if the variable is tracked or not.
6450 void emitter::emitGCvarLiveUpd(int offs, int varNum, GCtype gcType, BYTE* addr)
6452 assert(abs(offs) % sizeof(int) == 0);
6453 assert(needsGC(gcType));
6455 #if FEATURE_FIXED_OUT_ARGS
6456 if ((unsigned)varNum == emitComp->lvaOutgoingArgSpaceVar)
6460 /* Append an "arg push" entry to track a GC written to the
6461 outgoing argument space.
6462 Allocate a new ptr arg entry and fill it in */
6464 regPtrDsc* regPtrNext = gcInfo->gcRegPtrAllocDsc();
6465 regPtrNext->rpdGCtype = gcType;
6466 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6467 regPtrNext->rpdArg = TRUE;
6468 regPtrNext->rpdCall = FALSE;
6469 noway_assert(FitsIn<unsigned short>(offs));
6470 regPtrNext->rpdPtrArg = (unsigned short)offs;
6471 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_PUSH;
6472 regPtrNext->rpdIsThis = FALSE;
6475 if (EMIT_GC_VERBOSE)
6477 printf("[%04X] %s arg write\n", offs, GCtypeStr(gcType));
6483 #endif // FEATURE_FIXED_OUT_ARGS
6485 /* Is the frame offset within the "interesting" range? */
6487 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
6489 /* Normally all variables in this range must be tracked stack
6490 pointers. However, for EnC, we relax this condition. So we
6491 must check if this is not such a variable.
6492 Note that varNum might be negative, indicating a spill temp.
6495 if (varNum != INT_MAX)
6497 bool isTracked = false;
6500 // This is NOT a spill temp
6501 LclVarDsc* varDsc = &emitComp->lvaTable[varNum];
6502 isTracked = emitComp->lvaIsGCTracked(varDsc);
6506 // Is it an untracked spill temp?
6507 isTracked = TRACK_GC_TEMP_LIFETIMES;
6512 assert(!emitContTrkPtrLcls ||
6513 // EBP based variables in the double-aligned frames are indeed input arguments.
6514 // and we don't require them to fall into the "interesting" range.
6515 ((emitComp->rpFrameType == FT_DOUBLE_ALIGN_FRAME) && (varNum >= 0) &&
6516 (emitComp->lvaTable[varNum].lvFramePointerBased == 1)));
6518 assert(!emitContTrkPtrLcls);
6526 /* Compute the index into the GC frame table */
6528 disp = (offs - emitGCrFrameOffsMin) / TARGET_POINTER_SIZE;
6529 assert(disp < emitGCrFrameOffsCnt);
6531 /* If the variable is currently dead, mark it as live */
6533 if (emitGCrFrameLiveTab[disp] == nullptr)
6535 emitGCvarLiveSet(offs, gcType, addr, disp);
6541 /*****************************************************************************
6543 * Record the fact that the given variable no longer contains a live GC ref.
6546 void emitter::emitGCvarDeadUpd(int offs, BYTE* addr)
6548 assert(emitIssuing);
6549 assert(abs(offs) % sizeof(int) == 0);
6551 /* Is the frame offset within the "interesting" range? */
6553 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
6557 /* Compute the index into the GC frame table */
6559 disp = (offs - emitGCrFrameOffsMin) / TARGET_POINTER_SIZE;
6560 assert(disp < emitGCrFrameOffsCnt);
6562 /* If the variable is currently live, mark it as dead */
6564 if (emitGCrFrameLiveTab[disp] != nullptr)
6566 emitGCvarDeadSet(offs, addr, disp);
6571 /*****************************************************************************
6573 * Allocate a new IG and link it in to the global list after the current IG
6576 insGroup* emitter::emitAllocAndLinkIG()
6578 insGroup* ig = emitAllocIG();
6582 emitInsertIGAfter(emitCurIG, ig);
6584 /* Propagate some IG flags from the current group to the new group */
6586 ig->igFlags |= (emitCurIG->igFlags & IGF_PROPAGATE_MASK);
6588 /* Set the new IG as the current IG */
6595 /*****************************************************************************
6597 * Allocate an instruction group descriptor and assign it the next index.
6600 insGroup* emitter::emitAllocIG()
6604 /* Allocate a group descriptor */
6606 size_t sz = sizeof(insGroup);
6607 ig = (insGroup*)emitGetMem(sz);
6614 emitTotalIGcnt += 1;
6615 emitTotalIGsize += sz;
6616 emitSizeMethod += sz;
6619 /* Do basic initialization */
6626 /*****************************************************************************
6628 * Initialize an instruction group
6631 void emitter::emitInitIG(insGroup* ig)
6633 /* Assign the next available index to the instruction group */
6635 ig->igNum = emitNxtIGnum;
6639 /* Record the (estimated) code offset of the group */
6641 ig->igOffs = emitCurCodeOffset;
6642 assert(IsCodeAligned(ig->igOffs));
6644 /* Set the current function index */
6646 ig->igFuncIdx = emitComp->compCurrFuncIdx;
6650 /* Zero out some fields to avoid printing garbage in JitDumps. These
6651 really only need to be set in DEBUG, but do it in all cases to make
6652 sure we act the same in non-DEBUG builds.
6656 ig->igGCregs = RBM_NONE;
6660 /*****************************************************************************
6662 * Insert instruction group 'ig' after 'igInsertAfterIG'
6665 void emitter::emitInsertIGAfter(insGroup* insertAfterIG, insGroup* ig)
6670 ig->igNext = insertAfterIG->igNext;
6671 insertAfterIG->igNext = ig;
6673 if (emitIGlast == insertAfterIG)
6675 // If we are inserting at the end, then update the 'last' pointer
6680 /*****************************************************************************
6682 * Save the current IG and start a new one.
6685 void emitter::emitNxtIG(bool emitAdd)
6687 /* Right now we don't allow multi-IG prologs */
6689 assert(emitCurIG != emitPrologIG);
6691 /* First save the current group */
6695 /* Update the GC live sets for the group's start
6696 * Do it only if not an emitter added block */
6700 VarSetOps::Assign(emitComp, emitInitGCrefVars, emitThisGCrefVars);
6701 emitInitGCrefRegs = emitThisGCrefRegs;
6702 emitInitByrefRegs = emitThisByrefRegs;
6705 /* Start generating the new group */
6709 /* If this is an emitter added block, flag it */
6713 emitCurIG->igFlags |= IGF_EMIT_ADD;
6716 // We've created a new IG; no need to force another one.
6717 emitForceNewIG = false;
6720 /*****************************************************************************
6722 * emitGetInsSC: Get the instruction's constant value.
6725 ssize_t emitter::emitGetInsSC(instrDesc* id)
6727 #ifdef _TARGET_ARM_ // should it be _TARGET_ARMARCH_? Why do we need this? Note that on ARM64 we store scaled immediates
6729 if (id->idIsLclVar())
6731 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
6734 int offs = id->idAddr()->iiaLclVar.lvaOffset();
6735 #if defined(_TARGET_ARM_)
6736 int adr = emitComp->lvaFrameAddress(varNum, id->idIsLclFPBase(), &baseReg, offs);
6737 int dsp = adr + offs;
6738 if ((id->idIns() == INS_sub) || (id->idIns() == INS_subw))
6740 #elif defined(_TARGET_ARM64_)
6741 // TODO-ARM64-Cleanup: this is currently unreachable. Do we need it?
6743 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
6744 int dsp = adr + offs;
6745 if (id->idIns() == INS_sub)
6751 #endif // _TARGET_ARM_
6752 if (id->idIsLargeCns())
6754 return ((instrDescCns*)id)->idcCnsVal;
6758 return id->idSmallCns();
6762 /*****************************************************************************/
6763 #if EMIT_TRACK_STACK_DEPTH
6764 /*****************************************************************************
6766 * Record a push of a single dword on the stack.
6769 void emitter::emitStackPush(BYTE* addr, GCtype gcType)
6772 assert(IsValidGCtype(gcType));
6775 if (emitSimpleStkUsed)
6777 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6778 assert(emitCurStackLvl / sizeof(int) < MAX_SIMPLE_STK_DEPTH);
6780 u1.emitSimpleStkMask <<= 1;
6781 u1.emitSimpleStkMask |= (unsigned)needsGC(gcType);
6783 u1.emitSimpleByrefStkMask <<= 1;
6784 u1.emitSimpleByrefStkMask |= (gcType == GCT_BYREF);
6786 assert((u1.emitSimpleStkMask & u1.emitSimpleByrefStkMask) == u1.emitSimpleByrefStkMask);
6790 emitStackPushLargeStk(addr, gcType);
6793 emitCurStackLvl += sizeof(int);
6796 /*****************************************************************************
6798 * Record a push of a bunch of non-GC dwords on the stack.
6801 void emitter::emitStackPushN(BYTE* addr, unsigned count)
6805 if (emitSimpleStkUsed)
6807 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6809 u1.emitSimpleStkMask <<= count;
6810 u1.emitSimpleByrefStkMask <<= count;
6814 emitStackPushLargeStk(addr, GCT_NONE, count);
6817 emitCurStackLvl += count * sizeof(int);
6820 /*****************************************************************************
6822 * Record a pop of the given number of dwords from the stack.
6825 void emitter::emitStackPop(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count)
6827 assert(emitCurStackLvl / sizeof(int) >= count);
6828 assert(!isCall || callInstrSize > 0);
6832 if (emitSimpleStkUsed)
6834 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6836 unsigned cnt = count;
6840 u1.emitSimpleStkMask >>= 1;
6841 u1.emitSimpleByrefStkMask >>= 1;
6846 emitStackPopLargeStk(addr, isCall, callInstrSize, count);
6849 emitCurStackLvl -= count * sizeof(int);
6855 // For the general encoder we do the call below always when it's a call, to ensure that the call is
6856 // recorded (when we're doing the ptr reg map for a non-fully-interruptible method).
6858 #ifndef JIT32_GCENCODER
6859 || (emitComp->genFullPtrRegMap && (!emitComp->genInterruptible) && isCall)
6860 #endif // JIT32_GCENCODER
6863 emitStackPopLargeStk(addr, isCall, callInstrSize, 0);
6868 /*****************************************************************************
6870 * Record a push of a single word on the stack for a full pointer map.
6873 void emitter::emitStackPushLargeStk(BYTE* addr, GCtype gcType, unsigned count)
6875 S_UINT32 level(emitCurStackLvl / sizeof(int));
6877 assert(IsValidGCtype(gcType));
6879 assert(!emitSimpleStkUsed);
6883 /* Push an entry for this argument on the tracking stack */
6885 // printf("Pushed [%d] at lvl %2u [max=%u]\n", isGCref, emitArgTrackTop - emitArgTrackTab, emitMaxStackDepth);
6887 assert(level.IsOverflow() || u2.emitArgTrackTop == u2.emitArgTrackTab + level.Value());
6888 *u2.emitArgTrackTop++ = (BYTE)gcType;
6889 assert(u2.emitArgTrackTop <= u2.emitArgTrackTab + emitMaxStackDepth);
6891 if (emitFullArgInfo || needsGC(gcType))
6895 /* Append an "arg push" entry if this is a GC ref or
6896 FPO method. Allocate a new ptr arg entry and fill it in */
6898 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6899 regPtrNext->rpdGCtype = gcType;
6901 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6902 regPtrNext->rpdArg = TRUE;
6903 regPtrNext->rpdCall = FALSE;
6904 if (level.IsOverflow() || !FitsIn<unsigned short>(level.Value()))
6906 IMPL_LIMITATION("Too many/too big arguments to encode GC information");
6908 regPtrNext->rpdPtrArg = (unsigned short)level.Value();
6909 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_PUSH;
6910 regPtrNext->rpdIsThis = FALSE;
6913 if (EMIT_GC_VERBOSE)
6915 printf("[%08X] %s arg push %u\n", dspPtr(regPtrNext), GCtypeStr(gcType), level.Value());
6920 /* This is an "interesting" argument push */
6922 u2.emitGcArgTrackCnt++;
6925 assert(!level.IsOverflow());
6929 /*****************************************************************************
6931 * Record a pop of the given number of words from the stack for a full ptr
6935 void emitter::emitStackPopLargeStk(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count)
6937 assert(emitIssuing);
6940 S_UINT16 argRecCnt(0); // arg count for ESP, ptr-arg count for EBP
6941 unsigned gcrefRegs, byrefRegs;
6943 #ifdef JIT32_GCENCODER
6944 // For the general encoder, we always need to record calls, so we make this call
6945 // even when emitSimpleStkUsed is true.
6946 assert(!emitSimpleStkUsed);
6949 /* Count how many pointer records correspond to this "pop" */
6951 for (argStkCnt = count; argStkCnt; argStkCnt--)
6953 assert(u2.emitArgTrackTop > u2.emitArgTrackTab);
6955 GCtype gcType = (GCtype)(*--u2.emitArgTrackTop);
6957 assert(IsValidGCtype(gcType));
6959 // printf("Popped [%d] at lvl %u\n", GCtypeStr(gcType), emitArgTrackTop - emitArgTrackTab);
6961 // This is an "interesting" argument
6963 if (emitFullArgInfo || needsGC(gcType))
6969 assert(u2.emitArgTrackTop >= u2.emitArgTrackTab);
6970 assert(u2.emitArgTrackTop == u2.emitArgTrackTab + emitCurStackLvl / sizeof(int) - count);
6971 noway_assert(!argRecCnt.IsOverflow());
6973 /* We're about to pop the corresponding arg records */
6975 u2.emitGcArgTrackCnt -= argRecCnt.Value();
6977 #ifdef JIT32_GCENCODER
6978 // For the general encoder, we always have to record calls, so we don't take this early return.
6979 if (!emitFullGCinfo)
6983 // Do we have any interesting (i.e., callee-saved) registers live here?
6985 gcrefRegs = byrefRegs = 0;
6987 // We make a bitmask whose bits correspond to callee-saved register indices (in the sequence
6988 // of callee-saved registers only).
6989 for (unsigned calleeSavedRegIdx = 0; calleeSavedRegIdx < CNT_CALLEE_SAVED; calleeSavedRegIdx++)
6991 regMaskTP calleeSavedRbm = raRbmCalleeSaveOrder[calleeSavedRegIdx];
6992 if (emitThisGCrefRegs & calleeSavedRbm)
6994 gcrefRegs |= (1 << calleeSavedRegIdx);
6996 if (emitThisByrefRegs & calleeSavedRbm)
6998 byrefRegs |= (1 << calleeSavedRegIdx);
7002 #ifdef JIT32_GCENCODER
7003 // For the general encoder, we always have to record calls, so we don't take this early return. /* Are there any
7004 // args to pop at this call site?
7006 if (argRecCnt.Value() == 0)
7009 Or do we have a partially interruptible EBP-less frame, and any
7010 of EDI,ESI,EBX,EBP are live, or is there an outer/pending call?
7012 CLANG_FORMAT_COMMENT_ANCHOR;
7014 #if !FPO_INTERRUPTIBLE
7015 if (emitFullyInt || (gcrefRegs == 0 && byrefRegs == 0 && u2.emitGcArgTrackCnt == 0))
7019 #endif // JIT32_GCENCODER
7021 /* Only calls may pop more than one value */
7023 // _cdecl calls accomplish this popping via a post-call-instruction SP adjustment.
7024 // The "rpdCall" field below should be interpreted as "the instruction accomplishes
7025 // call-related popping, even if it's not itself a call". Therefore, we don't just
7026 // use the "isCall" input argument, which means that the instruction actually is a call --
7027 // we use the OR of "isCall" or the "pops more than one value."
7029 bool isCallRelatedPop = (argRecCnt.Value() > 1);
7031 /* Allocate a new ptr arg entry and fill it in */
7033 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
7034 regPtrNext->rpdGCtype = GCT_GCREF; // Pops need a non-0 value (??)
7036 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
7037 regPtrNext->rpdCall = (isCall || isCallRelatedPop);
7038 #ifndef JIT32_GCENCODER
7039 if (regPtrNext->rpdCall)
7041 assert(isCall || callInstrSize == 0);
7042 regPtrNext->rpdCallInstrSize = callInstrSize;
7045 regPtrNext->rpdCallGCrefRegs = gcrefRegs;
7046 regPtrNext->rpdCallByrefRegs = byrefRegs;
7047 regPtrNext->rpdArg = TRUE;
7048 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_POP;
7049 regPtrNext->rpdPtrArg = argRecCnt.Value();
7052 if (EMIT_GC_VERBOSE)
7054 printf("[%08X] ptr arg pop %u\n", dspPtr(regPtrNext), count);
7059 /*****************************************************************************
7060 * For caller-pop arguments, we report the arguments as pending arguments.
7061 * However, any GC arguments are now dead, so we need to report them
7065 void emitter::emitStackKillArgs(BYTE* addr, unsigned count, unsigned char callInstrSize)
7069 if (emitSimpleStkUsed)
7071 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCInfo
7073 /* We don't need to report this to the GC info, but we do need
7074 to kill mark the ptrs on the stack as non-GC */
7076 assert(emitCurStackLvl / sizeof(int) >= count);
7078 for (unsigned lvl = 0; lvl < count; lvl++)
7080 u1.emitSimpleStkMask &= ~(1 << lvl);
7081 u1.emitSimpleByrefStkMask &= ~(1 << lvl);
7086 BYTE* argTrackTop = u2.emitArgTrackTop;
7089 for (unsigned i = 0; i < count; i++)
7091 assert(argTrackTop > u2.emitArgTrackTab);
7095 GCtype gcType = (GCtype)(*argTrackTop);
7096 assert(IsValidGCtype(gcType));
7098 if (needsGC(gcType))
7100 // printf("Killed %s at lvl %u\n", GCtypeStr(gcType), argTrackTop - emitArgTrackTab);
7102 *argTrackTop = GCT_NONE;
7107 noway_assert(!gcCnt.IsOverflow());
7109 /* We're about to kill the corresponding (pointer) arg records */
7111 if (!emitFullArgInfo)
7113 u2.emitGcArgTrackCnt -= gcCnt.Value();
7116 if (!emitFullGCinfo)
7121 /* Right after the call, the arguments are still sitting on the
7122 stack, but they are effectively dead. For fully-interruptible
7123 methods, we need to report that */
7125 if (emitFullGCinfo && gcCnt.Value())
7127 /* Allocate a new ptr arg entry and fill it in */
7129 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
7130 regPtrNext->rpdGCtype = GCT_GCREF; // Kills need a non-0 value (??)
7132 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
7134 regPtrNext->rpdArg = TRUE;
7135 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_KILL;
7136 regPtrNext->rpdPtrArg = gcCnt.Value();
7139 if (EMIT_GC_VERBOSE)
7141 printf("[%08X] ptr arg kill %u\n", dspPtr(regPtrNext), count);
7146 /* Now that ptr args have been marked as non-ptrs, we need to record
7147 the call itself as one that has no arguments. */
7149 emitStackPopLargeStk(addr, true, callInstrSize, 0);
7153 /*****************************************************************************
7154 * A helper for recording a relocation with the EE.
7156 void emitter::emitRecordRelocation(void* location, /* IN */
7157 void* target, /* IN */
7158 WORD fRelocType, /* IN */
7159 WORD slotNum /* = 0 */, /* IN */
7160 INT32 addlDelta /* = 0 */) /* IN */
7162 // If we're an unmatched altjit, don't tell the VM anything. We still record the relocation for
7163 // late disassembly; maybe we'll need it?
7164 if (emitComp->info.compMatchedVM)
7166 emitCmpHandle->recordRelocation(location, target, fRelocType, slotNum, addlDelta);
7168 #if defined(LATE_DISASM)
7169 codeGen->getDisAssembler().disRecordRelocation((size_t)location, (size_t)target);
7170 #endif // defined(LATE_DISASM)
7174 /*****************************************************************************
7175 * A helper for handling a Thumb-Mov32 of position-independent (PC-relative) value
7177 * This routine either records relocation for the location with the EE,
7178 * or creates a virtual relocation entry to perform offset fixup during
7179 * compilation without recording it with EE - depending on which of
7180 * absolute/relocative relocations mode are used for code section.
7182 void emitter::emitHandlePCRelativeMov32(void* location, /* IN */
7183 void* target) /* IN */
7185 if (emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_RELATIVE_CODE_RELOCS))
7187 emitRecordRelocation(location, target, IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL);
7191 emitRecordRelocation(location, target, IMAGE_REL_BASED_THUMB_MOV32);
7194 #endif // _TARGET_ARM_
7196 /*****************************************************************************
7197 * A helper for recording a call site with the EE.
7199 void emitter::emitRecordCallSite(ULONG instrOffset, /* IN */
7200 CORINFO_SIG_INFO* callSig, /* IN */
7201 CORINFO_METHOD_HANDLE methodHandle) /* IN */
7204 // Since CORINFO_SIG_INFO is a heavyweight structure, in most cases we can
7205 // lazily obtain it here using the given method handle (we only save the sig
7206 // info when we explicitly need it, i.e. for CALLI calls, vararg calls, and
7208 if (callSig == nullptr)
7210 assert(methodHandle != nullptr);
7212 if (Compiler::eeGetHelperNum(methodHandle) == CORINFO_HELP_UNDEF)
7214 if (emitScratchSigInfo == nullptr)
7216 emitScratchSigInfo = new (emitComp, CMK_CorSig) CORINFO_SIG_INFO;
7219 emitComp->eeGetMethodSig(methodHandle, emitScratchSigInfo);
7220 callSig = emitScratchSigInfo;
7224 emitCmpHandle->recordCallSite(instrOffset, callSig, methodHandle);
7225 #endif // defined(DEBUG)
7228 /*****************************************************************************/
7229 #endif // EMIT_TRACK_STACK_DEPTH
7230 /*****************************************************************************/
7231 /*****************************************************************************/
7235 /*****************************************************************************
7236 * Given a code offset, return a string representing a label for that offset.
7237 * If the code offset is just after the end of the code of the function, the
7238 * label will be "END". If the code offset doesn't correspond to any known
7239 * offset, the label will be "UNKNOWN". The strings are returned from static
7240 * buffers. This function rotates amongst four such static buffers (there are
7241 * cases where this function is called four times to provide data for a single
7245 const char* emitter::emitOffsetToLabel(unsigned offs)
7247 const size_t TEMP_BUFFER_LEN = 40;
7248 static unsigned curBuf = 0;
7249 static char buf[4][TEMP_BUFFER_LEN];
7253 UNATIVE_OFFSET nextof = 0;
7255 for (ig = emitIGlist; ig != nullptr; ig = ig->igNext)
7257 assert(nextof == ig->igOffs);
7259 if (ig->igOffs == offs)
7262 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "G_M%03u_IG%02u", Compiler::s_compMethodsCount, ig->igNum);
7263 retbuf = buf[curBuf];
7264 curBuf = (curBuf + 1) % 4;
7267 else if (ig->igOffs > offs)
7269 // We went past the requested offset but didn't find it.
7270 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "UNKNOWN");
7271 retbuf = buf[curBuf];
7272 curBuf = (curBuf + 1) % 4;
7276 nextof = ig->igOffs + ig->igSize;
7281 // It's a pseudo-label to the end.
7282 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "END");
7283 retbuf = buf[curBuf];
7284 curBuf = (curBuf + 1) % 4;
7289 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "UNKNOWN");
7290 retbuf = buf[curBuf];
7291 curBuf = (curBuf + 1) % 4;