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 < sizeof(ifNames) / sizeof(*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(HostAllocator::getHostAllocator(), emitSizeBuckets);
262 static unsigned GCrefsBuckets[] = {0, 1, 2, 5, 10, 20, 50, 128, 256, 512, 1024, 0};
263 static Histogram GCrefsTable(HostAllocator::getHostAllocator(), GCrefsBuckets);
265 static unsigned stkDepthBuckets[] = {0, 1, 2, 5, 10, 16, 32, 128, 1024, 0};
266 static Histogram stkDepthTable(HostAllocator::getHostAllocator(), 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::OldStyleClearD(emitComp, emitInitGCrefVars);
1475 VarSetOps::OldStyleClearD(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) / sizeof(void*);
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) % sizeof(void*)) == 0);
2168 assert((offsLo % sizeof(void*)) == 0);
2169 assert((offsHi % sizeof(void*)) == 0);
2171 emitGCrFrameOffsMin = offsLo;
2172 emitGCrFrameOffsMax = offsHi;
2173 emitGCrFrameOffsCnt = (offsHi - offsLo) / sizeof(void*);
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:
2339 case CORINFO_HELP_CHECKED_ASSIGN_REF:
2341 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
2343 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
2345 case CORINFO_HELP_ASSIGN_BYREF:
2347 case CORINFO_HELP_INIT_PINVOKE_FRAME:
2355 /*****************************************************************************
2357 * Mark the current spot as having a label.
2360 void* emitter::emitAddLabel(VARSET_VALARG_TP GCvars, regMaskTP gcrefRegs, regMaskTP byrefRegs, BOOL isFinallyTarget)
2362 /* Create a new IG if the current one is non-empty */
2364 if (emitCurIGnonEmpty())
2369 VarSetOps::Assign(emitComp, emitThisGCrefVars, GCvars);
2370 VarSetOps::Assign(emitComp, emitInitGCrefVars, GCvars);
2371 emitThisGCrefRegs = emitInitGCrefRegs = gcrefRegs;
2372 emitThisByrefRegs = emitInitByrefRegs = byrefRegs;
2374 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2375 if (isFinallyTarget)
2377 emitCurIG->igFlags |= IGF_FINALLY_TARGET;
2379 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2382 if (EMIT_GC_VERBOSE)
2384 printf("Label: IG%02u, GCvars=%s ", emitCurIG->igNum, VarSetOps::ToString(emitComp, GCvars));
2385 dumpConvertedVarSet(emitComp, GCvars);
2386 printf(", gcrefRegs=");
2387 printRegMaskInt(gcrefRegs);
2388 emitDispRegSet(gcrefRegs);
2389 printf(", byrefRegs=");
2390 printRegMaskInt(byrefRegs);
2391 emitDispRegSet(byrefRegs);
2398 #ifdef _TARGET_ARMARCH_
2400 // Does the argument location point to an IG at the end of a function or funclet?
2401 // We can ignore the codePos part of the location, since it doesn't affect the
2402 // determination. If 'emitLocNextFragment' is non-NULL, it indicates the first
2403 // IG of the next fragment, so it represents a function end.
2404 bool emitter::emitIsFuncEnd(emitLocation* emitLoc, emitLocation* emitLocNextFragment /* = NULL */)
2408 insGroup* ig = emitLoc->GetIG();
2411 // Are we at the end of the IG list?
2412 if ((emitLocNextFragment != NULL) && (ig->igNext == emitLocNextFragment->GetIG()))
2416 if (ig->igNext == NULL)
2419 // Is the next IG the start of a funclet prolog?
2420 if (ig->igNext->igFlags & IGF_FUNCLET_PROLOG)
2423 #if FEATURE_EH_FUNCLETS
2425 // Is the next IG a placeholder group for a funclet prolog?
2426 if ((ig->igNext->igFlags & IGF_PLACEHOLDER) && (ig->igNext->igPhData->igPhType == IGPT_FUNCLET_PROLOG))
2431 #endif // FEATURE_EH_FUNCLETS
2436 /*****************************************************************************
2438 * Split the region from 'startLoc' to 'endLoc' into fragments by calling
2439 * a callback function to indicate the beginning of a fragment. The initial code,
2440 * starting at 'startLoc', doesn't get a callback, but the first code fragment,
2441 * about 'maxSplitSize' bytes out does, as does the beginning of each fragment
2442 * after that. There is no callback for the end (only the beginning of the last
2443 * fragment gets a callback). A fragment must contain at least one instruction
2444 * group. It should be smaller than 'maxSplitSize', although it may be larger to
2445 * satisfy the "at least one instruction group" rule. Do not split prologs or
2446 * epilogs. (Currently, prologs exist in a single instruction group at the main
2447 * function beginning, so they aren't split. Funclets, however, might span IGs,
2448 * so we can't split in between them.)
2450 * Note that the locations must be the start of instruction groups; the part of
2451 * the location indicating offset within a group must be zero.
2453 * If 'startLoc' is NULL, it means the start of the code.
2454 * If 'endLoc' is NULL, it means the end of the code.
2457 void emitter::emitSplit(emitLocation* startLoc,
2458 emitLocation* endLoc,
2459 UNATIVE_OFFSET maxSplitSize,
2461 emitSplitCallbackType callbackFunc)
2463 insGroup* igStart = (startLoc == NULL) ? emitIGlist : startLoc->GetIG();
2464 insGroup* igEnd = (endLoc == NULL) ? NULL : endLoc->GetIG();
2467 insGroup* igLastReported;
2468 insGroup* igLastCandidate;
2469 UNATIVE_OFFSET curSize;
2470 UNATIVE_OFFSET candidateSize;
2472 for (igPrev = NULL, ig = igLastReported = igStart, igLastCandidate = NULL, candidateSize = 0, curSize = 0;
2473 ig != igEnd && ig != NULL; igPrev = ig, ig = ig->igNext)
2475 // Keep looking until we've gone past the maximum split size
2476 if (curSize >= maxSplitSize)
2478 bool reportCandidate = true;
2480 // Is there a candidate?
2481 if (igLastCandidate == NULL)
2485 printf("emitSplit: can't split at IG%02u; we don't have a candidate to report\n", ig->igNum);
2487 reportCandidate = false;
2490 // Don't report the same thing twice (this also happens for the first block, since igLastReported is
2491 // initialized to igStart).
2492 if (igLastCandidate == igLastReported)
2496 printf("emitSplit: can't split at IG%02u; we already reported it\n", igLastCandidate->igNum);
2498 reportCandidate = false;
2502 if (reportCandidate)
2505 if (EMITVERBOSE && (candidateSize >= maxSplitSize))
2506 printf("emitSplit: split at IG%02u is size %d, larger than requested maximum size of %d\n",
2507 igLastCandidate->igNum, candidateSize, maxSplitSize);
2510 // hand memory ownership to the callback function
2511 emitLocation* pEmitLoc = new (emitComp, CMK_Unknown) emitLocation(igLastCandidate);
2512 callbackFunc(context, pEmitLoc);
2513 igLastReported = igLastCandidate;
2514 igLastCandidate = NULL;
2515 curSize -= candidateSize;
2519 // Update the current candidate to be this block, if it isn't in the middle of a
2520 // prolog or epilog, which we can't split. All we know is that certain
2521 // IGs are marked as prolog or epilog. We don't actually know if two adjacent
2522 // IGs are part of the *same* prolog or epilog, so we have to assume they are.
2524 if (igPrev && (((igPrev->igFlags & IGF_FUNCLET_PROLOG) && (ig->igFlags & IGF_FUNCLET_PROLOG)) ||
2525 ((igPrev->igFlags & IGF_EPILOG) && (ig->igFlags & IGF_EPILOG))))
2527 // We can't update the candidate
2531 igLastCandidate = ig;
2532 candidateSize = curSize;
2535 curSize += ig->igSize;
2540 /*****************************************************************************
2542 * Given an instruction group, find the array of instructions (instrDesc) and
2543 * number of instructions in the array. If the IG is the current IG, we assume
2544 * that igData does NOT hold the instructions; they are unsaved and pointed
2545 * to by emitCurIGfreeBase.
2547 * This function can't be called for placeholder groups, which have no instrDescs.
2550 void emitter::emitGetInstrDescs(insGroup* ig, instrDesc** id, int* insCnt)
2552 assert(!(ig->igFlags & IGF_PLACEHOLDER));
2553 if (ig == emitCurIG)
2555 *id = (instrDesc*)emitCurIGfreeBase;
2556 *insCnt = emitCurIGinsCnt;
2560 *id = (instrDesc*)ig->igData;
2561 *insCnt = ig->igInsCnt;
2567 /*****************************************************************************
2569 * Given a location (an 'emitLocation'), find the instruction group (IG) and
2570 * instruction descriptor (instrDesc) corresponding to that location. Returns
2571 * 'true' if there is an instruction, 'false' if there is no instruction
2572 * (i.e., we're at the end of the instruction list). Also, optionally return
2573 * the number of instructions that follow that instruction in the IG (in *pinsRemaining,
2574 * if pinsRemaining is non-NULL), which can be used for iterating over the
2575 * remaining instrDescs in the IG.
2577 * We assume that emitCurIG points to the end of the instructions we care about.
2578 * For the prologs or epilogs, it points to the last IG of the prolog or epilog
2579 * that is being generated. For body code gen, it points to the place we are currently
2580 * adding code, namely, the end of currently generated code.
2583 bool emitter::emitGetLocationInfo(emitLocation* emitLoc,
2586 int* pinsRemaining /* = NULL */)
2588 assert(emitLoc != nullptr);
2589 assert(emitLoc->Valid());
2590 assert(emitLoc->GetIG() != nullptr);
2591 assert(pig != nullptr);
2592 assert(pid != nullptr);
2594 insGroup* ig = emitLoc->GetIG();
2596 int insNum = emitLoc->GetInsNum();
2599 emitGetInstrDescs(ig, &id, &insCnt);
2600 assert(insNum <= insCnt);
2602 // There is a special-case: if the insNum points to the end, then we "wrap" and
2603 // consider that the instruction it is pointing at is actually the first instruction
2604 // of the next non-empty IG (which has its own valid emitLocation). This handles the
2605 // case where you capture a location, then the next instruction creates a new IG.
2607 if (insNum == insCnt)
2609 if (ig == emitCurIG)
2611 // No instructions beyond the current location.
2615 for (ig = ig->igNext; ig; ig = ig->igNext)
2617 emitGetInstrDescs(ig, &id, &insCnt);
2621 insNum = 0; // Pretend the index is 0 -- the first instruction
2625 if (ig == emitCurIG)
2627 // There aren't any instructions in the current IG, and this is
2628 // the current location, so we're at the end.
2635 // 'ig' can't be NULL, or we went past the current IG represented by 'emitCurIG'.
2636 // Perhaps 'loc' was corrupt coming in?
2637 noway_assert(!"corrupt emitter location");
2642 // Now find the instrDesc within this group that corresponds to the location
2644 assert(insNum < insCnt);
2647 for (i = 0; i != insNum; ++i)
2649 castto(id, BYTE*) += emitSizeOfInsDsc(id);
2652 // Return the info we found
2659 *pinsRemaining = insCnt - insNum - 1;
2665 /*****************************************************************************
2667 * Compute the next instrDesc, either in this IG, or in a subsequent IG. 'id'
2668 * will point to this instrDesc. 'ig' and 'insRemaining' will also be updated.
2669 * Returns true if there is an instruction, or false if we've iterated over all
2670 * the instructions up to the current instruction (based on 'emitCurIG').
2673 bool emitter::emitNextID(insGroup*& ig, instrDesc*& id, int& insRemaining)
2675 if (insRemaining > 0)
2677 castto(id, BYTE*) += emitSizeOfInsDsc(id);
2682 // We're out of instrDesc in 'ig'. Is this the current IG? If so, we're done.
2684 if (ig == emitCurIG)
2689 for (ig = ig->igNext; ig; ig = ig->igNext)
2692 emitGetInstrDescs(ig, &id, &insCnt);
2696 insRemaining = insCnt - 1;
2700 if (ig == emitCurIG)
2709 /*****************************************************************************
2711 * Walk instrDesc's from the location given by 'locFrom', up to the current location.
2712 * For each instruction, call the callback function 'processFunc'. 'context' is simply
2713 * passed through to the callback function.
2716 void emitter::emitWalkIDs(emitLocation* locFrom, emitProcessInstrFunc_t processFunc, void* context)
2722 if (!emitGetLocationInfo(locFrom, &ig, &id, &insRemaining))
2723 return; // no instructions at the 'from' location
2728 (*processFunc)(id, context);
2730 } while (emitNextID(ig, id, insRemaining));
2733 /*****************************************************************************
2735 * A callback function for emitWalkIDs() that calls Compiler::unwindNop().
2738 void emitter::emitGenerateUnwindNop(instrDesc* id, void* context)
2740 Compiler* comp = (Compiler*)context;
2741 #if defined(_TARGET_ARM_)
2742 comp->unwindNop(id->idCodeSize());
2743 #elif defined(_TARGET_ARM64_)
2745 #endif // defined(_TARGET_ARM64_)
2748 /*****************************************************************************
2750 * emitUnwindNopPadding: call unwindNop() for every instruction from a given
2751 * location 'emitLoc' up to the current location.
2754 void emitter::emitUnwindNopPadding(emitLocation* locFrom, Compiler* comp)
2756 emitWalkIDs(locFrom, emitGenerateUnwindNop, comp);
2759 #endif // _TARGET_ARMARCH_
2761 #if defined(_TARGET_ARM_)
2763 /*****************************************************************************
2765 * Return the instruction size in bytes for the instruction at the specified location.
2766 * This is used to assert that the unwind code being generated on ARM has the
2767 * same size as the instruction for which it is being generated (since on ARM
2768 * the unwind codes have a one-to-one relationship with instructions, and the
2769 * unwind codes have an implicit instruction size that must match the instruction size.)
2770 * An instruction must exist at the specified location.
2773 unsigned emitter::emitGetInstructionSize(emitLocation* emitLoc)
2778 bool anyInstrs = emitGetLocationInfo(emitLoc, &ig, &id);
2779 assert(anyInstrs); // There better be an instruction at this location (otherwise, we're at the end of the
2780 // instruction list)
2781 return id->idCodeSize();
2784 #endif // defined(_TARGET_ARM_)
2786 /*****************************************************************************/
2788 /*****************************************************************************
2790 * Returns the name for the register to use to access frame based variables
2793 const char* emitter::emitGetFrameReg()
2795 if (emitHasFramePtr)
2805 /*****************************************************************************
2807 * Display a register set in a readable form.
2810 void emitter::emitDispRegSet(regMaskTP regs)
2817 for (reg = REG_FIRST; reg < ACTUAL_REG_COUNT; reg = REG_NEXT(reg))
2819 if ((regs & genRegMask(reg)) == 0)
2833 printf("%s", emitRegName(reg));
2839 /*****************************************************************************
2841 * Display the current GC ref variable set in a readable form.
2844 void emitter::emitDispVarSet()
2850 for (vn = 0, of = emitGCrFrameOffsMin; vn < emitGCrFrameOffsCnt; vn += 1, of += sizeof(void*))
2852 if (emitGCrFrameLiveTab[vn])
2863 printf("[%s", emitGetFrameReg());
2867 printf("-%02XH", -of);
2871 printf("+%02XH", +of);
2884 /*****************************************************************************/
2887 #if MULTIREG_HAS_SECOND_GC_RET
2888 //------------------------------------------------------------------------
2889 // emitSetSecondRetRegGCType: Sets the GC type of the second return register for instrDescCGCA struct.
2892 // id - The large call instr descriptor to set the second GC return register type on.
2893 // secondRetSize - The EA_SIZE for second return register type.
2899 void emitter::emitSetSecondRetRegGCType(instrDescCGCA* id, emitAttr secondRetSize)
2901 if (EA_IS_GCREF(secondRetSize))
2903 id->idSecondGCref(GCT_GCREF);
2905 else if (EA_IS_BYREF(secondRetSize))
2907 id->idSecondGCref(GCT_BYREF);
2911 id->idSecondGCref(GCT_NONE);
2914 #endif // MULTIREG_HAS_SECOND_GC_RET
2916 /*****************************************************************************
2918 * Allocate an instruction descriptor for an indirect call.
2920 * We use two different descriptors to save space - the common case records
2921 * no GC variables and has both a very small argument count and an address
2922 * mode displacement; the other case records the current GC var set,
2923 * the call scope, and an arbitrarily large argument count and the
2924 * address mode displacement.
2927 emitter::instrDesc* emitter::emitNewInstrCallInd(int argCnt,
2929 VARSET_VALARG_TP GCvars,
2930 regMaskTP gcrefRegs,
2931 regMaskTP byrefRegs,
2933 MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize))
2935 emitAttr retSize = (retSizeIn != EA_UNKNOWN) ? retSizeIn : EA_PTRSIZE;
2937 bool gcRefRegsInScratch = ((gcrefRegs & RBM_CALLEE_TRASH) != 0);
2939 // Allocate a larger descriptor if any GC values need to be saved
2940 // or if we have an absurd number of arguments or a large address
2941 // mode displacement, or we have some byref registers
2943 // On Amd64 System V OSs a larger descriptor is also needed if the
2944 // call returns a two-register-returned struct and the second
2945 // register (RDX) is a GCRef or ByRef pointer.
2947 if (!VarSetOps::IsEmpty(emitComp, GCvars) || // any frame GCvars live
2948 (gcRefRegsInScratch) || // any register gc refs live in scratch regs
2949 (byrefRegs != 0) || // any register byrefs live
2950 (disp < AM_DISP_MIN) || // displacement too negative
2951 (disp > AM_DISP_MAX) || // displacement too positive
2952 (argCnt > ID_MAX_SMALL_CNS) || // too many args
2953 (argCnt < 0) // caller pops arguments
2954 // There is a second ref/byref return register.
2955 MULTIREG_HAS_SECOND_GC_RET_ONLY(|| EA_IS_GCREF_OR_BYREF(secondRetSize)))
2959 id = emitAllocInstrCGCA(retSize);
2961 id->idSetIsLargeCall();
2963 VarSetOps::Assign(emitComp, id->idcGCvars, GCvars);
2964 id->idcGcrefRegs = gcrefRegs;
2965 id->idcByrefRegs = byrefRegs;
2966 id->idcArgCnt = argCnt;
2969 #if MULTIREG_HAS_SECOND_GC_RET
2970 emitSetSecondRetRegGCType(id, secondRetSize);
2971 #endif // MULTIREG_HAS_SECOND_GC_RET
2979 id = emitNewInstrCns(retSize, argCnt);
2981 /* Make sure we didn't waste space unexpectedly */
2982 assert(!id->idIsLargeCns());
2984 /* Store the displacement and make sure the value fit */
2985 id->idAddr()->iiaAddrMode.amDisp = disp;
2986 assert(id->idAddr()->iiaAddrMode.amDisp == disp);
2988 /* Save the the live GC registers in the unused register fields */
2989 emitEncodeCallGCregs(gcrefRegs, id);
2995 /*****************************************************************************
2997 * Allocate an instruction descriptor for a direct call.
2999 * We use two different descriptors to save space - the common case records
3000 * with no GC variables or byrefs and has a very small argument count, and no
3002 * the other case records the current GC var set, the call scope,
3003 * and an arbitrarily large argument count.
3006 emitter::instrDesc* emitter::emitNewInstrCallDir(int argCnt,
3007 VARSET_VALARG_TP GCvars,
3008 regMaskTP gcrefRegs,
3009 regMaskTP byrefRegs,
3011 MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize))
3013 emitAttr retSize = (retSizeIn != EA_UNKNOWN) ? retSizeIn : EA_PTRSIZE;
3015 // Allocate a larger descriptor if new GC values need to be saved
3016 // or if we have an absurd number of arguments or if we need to
3019 // On Amd64 System V OSs a larger descriptor is also needed if the
3020 // call returns a two-register-returned struct and the second
3021 // register (RDX) is a GCRef or ByRef pointer.
3023 bool gcRefRegsInScratch = ((gcrefRegs & RBM_CALLEE_TRASH) != 0);
3025 if (!VarSetOps::IsEmpty(emitComp, GCvars) || // any frame GCvars live
3026 gcRefRegsInScratch || // any register gc refs live in scratch regs
3027 (byrefRegs != 0) || // any register byrefs live
3028 (argCnt > ID_MAX_SMALL_CNS) || // too many args
3029 (argCnt < 0) // caller pops arguments
3030 // There is a second ref/byref return register.
3031 MULTIREG_HAS_SECOND_GC_RET_ONLY(|| EA_IS_GCREF_OR_BYREF(secondRetSize)))
3033 instrDescCGCA* id = emitAllocInstrCGCA(retSize);
3035 // printf("Direct call with GC vars / big arg cnt / explicit scope\n");
3037 id->idSetIsLargeCall();
3039 VarSetOps::Assign(emitComp, id->idcGCvars, GCvars);
3040 id->idcGcrefRegs = gcrefRegs;
3041 id->idcByrefRegs = byrefRegs;
3043 id->idcArgCnt = argCnt;
3045 #if MULTIREG_HAS_SECOND_GC_RET
3046 emitSetSecondRetRegGCType(id, secondRetSize);
3047 #endif // MULTIREG_HAS_SECOND_GC_RET
3053 instrDesc* id = emitNewInstrCns(retSize, argCnt);
3055 // printf("Direct call w/o GC vars / big arg cnt / explicit scope\n");
3057 /* Make sure we didn't waste space unexpectedly */
3058 assert(!id->idIsLargeCns());
3060 /* Save the the live GC registers in the unused register fields */
3061 emitEncodeCallGCregs(gcrefRegs, id);
3067 /*****************************************************************************/
3069 /*****************************************************************************
3071 * Return a string with the name of the given class field (blank string (not
3072 * NULL) is returned when the name isn't available).
3075 const char* emitter::emitFldName(CORINFO_FIELD_HANDLE fieldVal)
3077 if (emitComp->opts.varNames)
3079 const char* memberName;
3080 const char* className;
3082 const int TEMP_BUFFER_LEN = 1024;
3083 static char buff[TEMP_BUFFER_LEN];
3085 memberName = emitComp->eeGetFieldName(fieldVal, &className);
3087 sprintf_s(buff, TEMP_BUFFER_LEN, "'<%s>.%s'", className, memberName);
3096 /*****************************************************************************
3098 * Return a string with the name of the given function (blank string (not
3099 * NULL) is returned when the name isn't available).
3102 const char* emitter::emitFncName(CORINFO_METHOD_HANDLE methHnd)
3104 return emitComp->eeGetMethodFullName(methHnd);
3109 /*****************************************************************************
3111 * Be very careful, some instruction descriptors are allocated as "tiny" and
3112 * don't have some of the tail fields of instrDesc (in particular, "idInfo").
3115 const BYTE emitter::emitFmtToOps[] = {
3116 #define IF_DEF(en, op1, op2) ID_OP_##op2,
3117 #include "emitfmts.h"
3121 const unsigned emitter::emitFmtCount = sizeof(emitFmtToOps) / sizeof(emitFmtToOps[0]);
3124 /*****************************************************************************
3126 * Display the current instruction group list.
3131 void emitter::emitDispIGflags(unsigned flags)
3133 if (flags & IGF_GC_VARS)
3137 if (flags & IGF_BYREF_REGS)
3141 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
3142 if (flags & IGF_FINALLY_TARGET)
3144 printf(", ftarget");
3146 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
3147 if (flags & IGF_FUNCLET_PROLOG)
3149 printf(", funclet prolog");
3151 if (flags & IGF_FUNCLET_EPILOG)
3153 printf(", funclet epilog");
3155 if (flags & IGF_EPILOG)
3159 if (flags & IGF_NOGCINTERRUPT)
3163 if (flags & IGF_UPD_ISZ)
3167 if (flags & IGF_EMIT_ADD)
3169 printf(", emitadd");
3173 void emitter::emitDispIG(insGroup* ig, insGroup* igPrev, bool verbose)
3175 const int TEMP_BUFFER_LEN = 40;
3176 char buff[TEMP_BUFFER_LEN];
3178 sprintf_s(buff, TEMP_BUFFER_LEN, "G_M%03u_IG%02u: ", Compiler::s_compMethodsCount, ig->igNum);
3179 printf("%s; ", buff);
3180 if ((igPrev == nullptr) || (igPrev->igFuncIdx != ig->igFuncIdx))
3182 printf("func=%02u, ", ig->igFuncIdx);
3185 if (ig->igFlags & IGF_PLACEHOLDER)
3187 insGroup* igPh = ig;
3189 const char* pszType;
3190 switch (igPh->igPhData->igPhType)
3198 #if FEATURE_EH_FUNCLETS
3199 case IGPT_FUNCLET_PROLOG:
3200 pszType = "funclet prolog";
3202 case IGPT_FUNCLET_EPILOG:
3203 pszType = "funclet epilog";
3205 #endif // FEATURE_EH_FUNCLETS
3207 pszType = "UNKNOWN";
3210 printf("%s placeholder, next placeholder=", pszType);
3211 if (igPh->igPhData->igPhNext)
3213 printf("IG%02u ", igPh->igPhData->igPhNext->igNum);
3220 if (igPh->igPhData->igPhBB != nullptr)
3222 printf(", %s", igPh->igPhData->igPhBB->dspToString());
3225 emitDispIGflags(igPh->igFlags);
3227 if (ig == emitCurIG)
3229 printf(" <-- Current IG");
3231 if (igPh == emitPlaceholderList)
3233 printf(" <-- First placeholder");
3235 if (igPh == emitPlaceholderLast)
3237 printf(" <-- Last placeholder");
3241 printf("%*s; PrevGCVars=%s ", strlen(buff), "",
3242 VarSetOps::ToString(emitComp, igPh->igPhData->igPhPrevGCrefVars));
3243 dumpConvertedVarSet(emitComp, igPh->igPhData->igPhPrevGCrefVars);
3244 printf(", PrevGCrefRegs=");
3245 printRegMaskInt(igPh->igPhData->igPhPrevGCrefRegs);
3246 emitDispRegSet(igPh->igPhData->igPhPrevGCrefRegs);
3247 printf(", PrevByrefRegs=");
3248 printRegMaskInt(igPh->igPhData->igPhPrevByrefRegs);
3249 emitDispRegSet(igPh->igPhData->igPhPrevByrefRegs);
3252 printf("%*s; InitGCVars=%s ", strlen(buff), "",
3253 VarSetOps::ToString(emitComp, igPh->igPhData->igPhInitGCrefVars));
3254 dumpConvertedVarSet(emitComp, igPh->igPhData->igPhInitGCrefVars);
3255 printf(", InitGCrefRegs=");
3256 printRegMaskInt(igPh->igPhData->igPhInitGCrefRegs);
3257 emitDispRegSet(igPh->igPhData->igPhInitGCrefRegs);
3258 printf(", InitByrefRegs=");
3259 printRegMaskInt(igPh->igPhData->igPhInitByrefRegs);
3260 emitDispRegSet(igPh->igPhData->igPhInitByrefRegs);
3263 assert(!(ig->igFlags & IGF_GC_VARS));
3264 assert(!(ig->igFlags & IGF_BYREF_REGS));
3268 printf("offs=%06XH, size=%04XH", ig->igOffs, ig->igSize);
3270 if (ig->igFlags & IGF_GC_VARS)
3272 printf(", gcVars=%s ", VarSetOps::ToString(emitComp, ig->igGCvars()));
3273 dumpConvertedVarSet(emitComp, ig->igGCvars());
3276 if (!(ig->igFlags & IGF_EMIT_ADD))
3278 printf(", gcrefRegs=");
3279 printRegMaskInt(ig->igGCregs);
3280 emitDispRegSet(ig->igGCregs);
3283 if (ig->igFlags & IGF_BYREF_REGS)
3285 printf(", byrefRegs=");
3286 printRegMaskInt(ig->igByrefRegs());
3287 emitDispRegSet(ig->igByrefRegs());
3290 emitDispIGflags(ig->igFlags);
3292 if (ig == emitCurIG)
3294 printf(" <-- Current IG");
3296 if (ig == emitPrologIG)
3298 printf(" <-- Prolog IG");
3304 BYTE* ins = ig->igData;
3305 UNATIVE_OFFSET ofs = ig->igOffs;
3306 unsigned cnt = ig->igInsCnt;
3314 instrDesc* id = (instrDesc*)ins;
3316 emitDispIns(id, false, true, false, ofs, nullptr, 0, ig);
3318 ins += emitSizeOfInsDsc(id);
3319 ofs += emitInstCodeSz(id);
3328 void emitter::emitDispIGlist(bool verbose)
3333 for (igPrev = nullptr, ig = emitIGlist; ig; igPrev = ig, ig = ig->igNext)
3335 emitDispIG(ig, igPrev, verbose);
3339 void emitter::emitDispGCinfo()
3341 printf("Emitter GC tracking info:");
3342 printf("\n emitPrevGCrefVars ");
3343 dumpConvertedVarSet(emitComp, emitPrevGCrefVars);
3344 printf("\n emitPrevGCrefRegs(0x%p)=", dspPtr(&emitPrevGCrefRegs));
3345 printRegMaskInt(emitPrevGCrefRegs);
3346 emitDispRegSet(emitPrevGCrefRegs);
3347 printf("\n emitPrevByrefRegs(0x%p)=", dspPtr(&emitPrevByrefRegs));
3348 printRegMaskInt(emitPrevByrefRegs);
3349 emitDispRegSet(emitPrevByrefRegs);
3350 printf("\n emitInitGCrefVars ");
3351 dumpConvertedVarSet(emitComp, emitInitGCrefVars);
3352 printf("\n emitInitGCrefRegs(0x%p)=", dspPtr(&emitInitGCrefRegs));
3353 printRegMaskInt(emitInitGCrefRegs);
3354 emitDispRegSet(emitInitGCrefRegs);
3355 printf("\n emitInitByrefRegs(0x%p)=", dspPtr(&emitInitByrefRegs));
3356 printRegMaskInt(emitInitByrefRegs);
3357 emitDispRegSet(emitInitByrefRegs);
3358 printf("\n emitThisGCrefVars ");
3359 dumpConvertedVarSet(emitComp, emitThisGCrefVars);
3360 printf("\n emitThisGCrefRegs(0x%p)=", dspPtr(&emitThisGCrefRegs));
3361 printRegMaskInt(emitThisGCrefRegs);
3362 emitDispRegSet(emitThisGCrefRegs);
3363 printf("\n emitThisByrefRegs(0x%p)=", dspPtr(&emitThisByrefRegs));
3364 printRegMaskInt(emitThisByrefRegs);
3365 emitDispRegSet(emitThisByrefRegs);
3371 /*****************************************************************************
3373 * Issue the given instruction. Basically, this is just a thin wrapper around
3374 * emitOutputInstr() that does a few debug checks.
3377 size_t emitter::emitIssue1Instr(insGroup* ig, instrDesc* id, BYTE** dp)
3381 /* Record the beginning offset of the instruction */
3383 BYTE* curInsAdr = *dp;
3385 /* Issue the next instruction */
3387 // printf("[S=%02u] " , emitCurStackLvl);
3389 is = emitOutputInstr(ig, id, dp);
3391 // printf("[S=%02u]\n", emitCurStackLvl);
3393 #if EMIT_TRACK_STACK_DEPTH
3396 If we're generating a full pointer map and the stack
3397 is empty, there better not be any "pending" argument
3401 assert(emitFullGCinfo == false || emitCurStackLvl != 0 || u2.emitGcArgTrackCnt == 0);
3405 /* Did the size of the instruction match our expectations? */
3407 UNATIVE_OFFSET csz = (UNATIVE_OFFSET)(*dp - curInsAdr);
3409 if (csz != id->idCodeSize())
3411 /* It is fatal to under-estimate the instruction size */
3412 noway_assert(emitInstCodeSz(id) >= csz);
3417 printf("Instruction predicted size = %u, actual = %u\n", emitInstCodeSz(id), csz);
3419 #endif // DEBUG_EMIT
3421 /* The instruction size estimate wasn't accurate; remember this */
3423 ig->igFlags |= IGF_UPD_ISZ;
3424 #if defined(_TARGET_XARCH_)
3425 id->idCodeSize(csz);
3426 #elif defined(_TARGET_ARM_)
3427 // This is done as part of emitSetShortJump();
3428 // insSize isz = emitInsSize(id->idInsFmt());
3429 // id->idInsSize(isz);
3431 /* It is fatal to over-estimate the instruction size */
3432 IMPL_LIMITATION("Over-estimated instruction size");
3437 /* Make sure the instruction descriptor size also matches our expectations */
3438 if (is != emitSizeOfInsDsc(id))
3440 printf("%s at %u: Expected size = %u , actual size = %u\n", emitIfName(id->idInsFmt()),
3441 id->idDebugOnlyInfo()->idNum, is, emitSizeOfInsDsc(id));
3442 assert(is == emitSizeOfInsDsc(id));
3449 /*****************************************************************************
3451 * Update the offsets of all the instruction groups (note: please don't be
3452 * lazy and call this routine frequently, it walks the list of instruction
3453 * groups and thus it isn't cheap).
3456 void emitter::emitRecomputeIGoffsets()
3458 UNATIVE_OFFSET offs;
3461 for (ig = emitIGlist, offs = 0; ig; ig = ig->igNext)
3464 assert(IsCodeAligned(ig->igOffs));
3468 /* Set the total code size */
3470 emitTotalCodeSize = offs;
3473 emitCheckIGoffsets();
3477 /*****************************************************************************
3478 * Bind targets of relative jumps to choose the smallest possible encoding.
3479 * X86 and AMD64 have a small and large encoding.
3480 * ARM has a small, medium, and large encoding. The large encoding is a pseudo-op
3481 * to handle greater range than the conditional branch instructions can handle.
3482 * ARM64 has a small and large encoding for both conditional branch and loading label addresses.
3483 * The large encodings are pseudo-ops that represent a multiple instruction sequence, similar to ARM. (Currently
3487 void emitter::emitJumpDistBind()
3490 if (emitComp->verbose)
3492 printf("*************** In emitJumpDistBind()\n");
3494 if (EMIT_INSTLIST_VERBOSE)
3496 printf("\nInstruction list before jump distance binding:\n\n");
3497 emitDispIGlist(true);
3503 UNATIVE_OFFSET minShortExtra; // The smallest offset greater than that required for a jump to be converted
3504 // to a small jump. If it is small enough, we will iterate in hopes of
3505 // converting those jumps we missed converting the first (or second...) time.
3507 #if defined(_TARGET_ARM_)
3508 UNATIVE_OFFSET minMediumExtra; // Same as 'minShortExtra', but for medium-sized jumps.
3509 #endif // _TARGET_ARM_
3511 UNATIVE_OFFSET adjIG;
3512 UNATIVE_OFFSET adjLJ;
3515 insGroup* prologIG = emitPrologIG;
3518 int jmp_iteration = 1;
3520 /*****************************************************************************/
3521 /* If we iterate to look for more jumps to shorten, we start again here. */
3522 /*****************************************************************************/
3527 emitCheckIGoffsets();
3531 In the following loop we convert all jump targets from "BasicBlock *"
3532 to "insGroup *" values. We also estimate which jumps will be short.
3536 insGroup* lastIG = nullptr;
3537 instrDescJmp* lastLJ = nullptr;
3543 minShortExtra = (UNATIVE_OFFSET)-1;
3545 #if defined(_TARGET_ARM_)
3546 minMediumExtra = (UNATIVE_OFFSET)-1;
3547 #endif // _TARGET_ARM_
3549 for (jmp = emitJumpList; jmp; jmp = jmp->idjNext)
3554 UNATIVE_OFFSET jsz; // size of the jump instruction in bytes
3556 UNATIVE_OFFSET ssz = 0; // small jump size
3557 NATIVE_OFFSET nsd = 0; // small jump max. neg distance
3558 NATIVE_OFFSET psd = 0; // small jump max. pos distance
3560 #if defined(_TARGET_ARM_)
3561 UNATIVE_OFFSET msz = 0; // medium jump size
3562 NATIVE_OFFSET nmd = 0; // medium jump max. neg distance
3563 NATIVE_OFFSET pmd = 0; // medium jump max. pos distance
3564 NATIVE_OFFSET mextra; // How far beyond the medium jump range is this jump offset?
3565 #endif // _TARGET_ARM_
3567 NATIVE_OFFSET extra; // How far beyond the short jump range is this jump offset?
3568 UNATIVE_OFFSET srcInstrOffs; // offset of the source instruction of the jump
3569 UNATIVE_OFFSET srcEncodingOffs; // offset of the source used by the instruction set to calculate the relative
3570 // offset of the jump
3571 UNATIVE_OFFSET dstOffs;
3572 NATIVE_OFFSET jmpDist; // the relative jump distance, as it will be encoded
3573 UNATIVE_OFFSET oldSize;
3574 UNATIVE_OFFSET sizeDif;
3576 #ifdef _TARGET_XARCH_
3577 assert(jmp->idInsFmt() == IF_LABEL || jmp->idInsFmt() == IF_RWR_LABEL || jmp->idInsFmt() == IF_SWR_LABEL);
3579 /* Figure out the smallest size we can end up with */
3581 if (jmp->idInsFmt() == IF_LABEL)
3583 if (emitIsCondJump(jmp))
3585 ssz = JCC_SIZE_SMALL;
3586 nsd = JCC_DIST_SMALL_MAX_NEG;
3587 psd = JCC_DIST_SMALL_MAX_POS;
3591 ssz = JMP_SIZE_SMALL;
3592 nsd = JMP_DIST_SMALL_MAX_NEG;
3593 psd = JMP_DIST_SMALL_MAX_POS;
3596 #endif // _TARGET_XARCH_
3599 assert((jmp->idInsFmt() == IF_T2_J1) || (jmp->idInsFmt() == IF_T2_J2) || (jmp->idInsFmt() == IF_T1_I) ||
3600 (jmp->idInsFmt() == IF_T1_K) || (jmp->idInsFmt() == IF_T1_M) || (jmp->idInsFmt() == IF_T2_M1) ||
3601 (jmp->idInsFmt() == IF_T2_N1) || (jmp->idInsFmt() == IF_T1_J3) || (jmp->idInsFmt() == IF_LARGEJMP));
3603 /* Figure out the smallest size we can end up with */
3605 if (emitIsCondJump(jmp))
3607 ssz = JCC_SIZE_SMALL;
3608 nsd = JCC_DIST_SMALL_MAX_NEG;
3609 psd = JCC_DIST_SMALL_MAX_POS;
3611 msz = JCC_SIZE_MEDIUM;
3612 nmd = JCC_DIST_MEDIUM_MAX_NEG;
3613 pmd = JCC_DIST_MEDIUM_MAX_POS;
3615 else if (emitIsCmpJump(jmp))
3617 ssz = JMP_SIZE_SMALL;
3621 else if (emitIsUncondJump(jmp))
3623 ssz = JMP_SIZE_SMALL;
3624 nsd = JMP_DIST_SMALL_MAX_NEG;
3625 psd = JMP_DIST_SMALL_MAX_POS;
3627 else if (emitIsLoadLabel(jmp))
3629 ssz = LBL_SIZE_SMALL;
3630 nsd = LBL_DIST_SMALL_MAX_NEG;
3631 psd = LBL_DIST_SMALL_MAX_POS;
3635 assert(!"Unknown jump instruction");
3637 #endif // _TARGET_ARM_
3639 #ifdef _TARGET_ARM64_
3640 /* Figure out the smallest size we can end up with */
3642 if (emitIsCondJump(jmp))
3644 ssz = JCC_SIZE_SMALL;
3645 bool isTest = (jmp->idIns() == INS_tbz) || (jmp->idIns() == INS_tbnz);
3647 nsd = (isTest) ? TB_DIST_SMALL_MAX_NEG : JCC_DIST_SMALL_MAX_NEG;
3648 psd = (isTest) ? TB_DIST_SMALL_MAX_POS : JCC_DIST_SMALL_MAX_POS;
3650 else if (emitIsUncondJump(jmp))
3652 // Nothing to do; we don't shrink these.
3653 assert(jmp->idjShort);
3654 ssz = JMP_SIZE_SMALL;
3656 else if (emitIsLoadLabel(jmp))
3658 ssz = LBL_SIZE_SMALL;
3659 nsd = LBL_DIST_SMALL_MAX_NEG;
3660 psd = LBL_DIST_SMALL_MAX_POS;
3662 else if (emitIsLoadConstant(jmp))
3664 ssz = LDC_SIZE_SMALL;
3665 nsd = LDC_DIST_SMALL_MAX_NEG;
3666 psd = LDC_DIST_SMALL_MAX_POS;
3670 assert(!"Unknown jump instruction");
3672 #endif // _TARGET_ARM64_
3674 /* Make sure the jumps are properly ordered */
3677 assert(lastLJ == nullptr || lastIG != jmp->idjIG || lastLJ->idjOffs < jmp->idjOffs);
3678 lastLJ = (lastIG == jmp->idjIG) ? jmp : nullptr;
3680 assert(lastIG == nullptr || lastIG->igNum <= jmp->idjIG->igNum || jmp->idjIG == prologIG ||
3681 emitNxtIGnum > unsigned(0xFFFF)); // igNum might overflow
3682 lastIG = jmp->idjIG;
3685 /* Get hold of the current jump size */
3687 jsz = emitSizeOfJump(jmp);
3689 /* Get the group the jump is in */
3693 /* Are we in a group different from the previous jump? */
3697 /* Were there any jumps before this one? */
3701 /* Adjust the offsets of the intervening blocks */
3705 lstIG = lstIG->igNext;
3707 // printf("Adjusted offset of block %02u from %04X to %04X\n", lstIG->igNum, lstIG->igOffs,
3708 // lstIG->igOffs - adjIG);
3709 lstIG->igOffs -= adjIG;
3710 assert(IsCodeAligned(lstIG->igOffs));
3711 } while (lstIG != jmpIG);
3714 /* We've got the first jump in a new group */
3720 /* Apply any local size adjustment to the jump's relative offset */
3722 jmp->idjOffs -= adjLJ;
3724 // If this is a jump via register, the instruction size does not change, so we are done.
3725 CLANG_FORMAT_COMMENT_ANCHOR;
3727 #if defined(_TARGET_ARM64_)
3728 // JIT code and data will be allocated together for arm64 so the relative offset to JIT data is known.
3729 // In case such offset can be encodeable for `ldr` (+-1MB), shorten it.
3730 if (jmp->idAddr()->iiaIsJitDataOffset())
3732 // Reference to JIT data
3733 assert(jmp->idIsBound());
3734 UNATIVE_OFFSET srcOffs = jmpIG->igOffs + jmp->idjOffs;
3736 int doff = jmp->idAddr()->iiaGetJitDataOffset();
3738 ssize_t imm = emitGetInsSC(jmp);
3739 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
3741 unsigned dataOffs = (unsigned)(doff + imm);
3742 assert(dataOffs < emitDataSize());
3744 // Conservately assume JIT data starts after the entire code size.
3745 // TODO-ARM64: we might consider only hot code size which will be computed later in emitComputeCodeSizes().
3746 assert(emitTotalCodeSize > 0);
3747 UNATIVE_OFFSET maxDstOffs = emitTotalCodeSize + dataOffs;
3749 // Check if the distance is within the encoding length.
3750 jmpDist = maxDstOffs - srcOffs;
3751 extra = jmpDist - psd;
3757 // Keep the large form.
3762 /* Have we bound this jump's target already? */
3764 if (jmp->idIsBound())
3766 /* Does the jump already have the smallest size? */
3770 assert(emitSizeOfJump(jmp) == ssz);
3772 // We should not be jumping/branching across funclets/functions
3773 emitCheckFuncletBranch(jmp, jmpIG);
3778 tgtIG = jmp->idAddr()->iiaIGlabel;
3782 /* First time we've seen this label, convert its target */
3783 CLANG_FORMAT_COMMENT_ANCHOR;
3788 printf("Binding: ");
3789 emitDispIns(jmp, false, false, false);
3790 printf("Binding L_M%03u_BB%02u ", Compiler::s_compMethodsCount, jmp->idAddr()->iiaBBlabel->bbNum);
3794 tgtIG = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel);
3801 printf("to G_M%03u_IG%02u\n", Compiler::s_compMethodsCount, tgtIG->igNum);
3805 printf("-- ERROR, no emitter cookie for BB%02u; it is probably missing BBF_JMP_TARGET or "
3807 jmp->idAddr()->iiaBBlabel->bbNum);
3813 /* Record the bound target */
3815 jmp->idAddr()->iiaIGlabel = tgtIG;
3816 jmp->idSetIsBound();
3819 // We should not be jumping/branching across funclets/functions
3820 emitCheckFuncletBranch(jmp, jmpIG);
3822 #ifdef _TARGET_XARCH_
3823 /* Done if this is not a variable-sized jump */
3825 if ((jmp->idIns() == INS_push) || (jmp->idIns() == INS_mov) || (jmp->idIns() == INS_call) ||
3826 (jmp->idIns() == INS_push_hide))
3832 if ((jmp->idIns() == INS_push) || (jmp->idIns() == INS_mov) || (jmp->idIns() == INS_movt) ||
3833 (jmp->idIns() == INS_movw))
3838 #ifdef _TARGET_ARM64_
3839 // There is only one size of unconditional branch; we don't support functions larger than 2^28 bytes (our branch
3841 if (emitIsUncondJump(jmp))
3848 In the following distance calculations, if we're not actually
3849 scheduling the code (i.e. reordering instructions), we can
3850 use the actual offset of the jump (rather than the beg/end of
3851 the instruction group) since the jump will not be moved around
3852 and thus its offset is accurate.
3854 First we need to figure out whether this jump is a forward or
3855 backward one; to do this we simply look at the ordinals of the
3856 group that contains the jump and the target.
3859 srcInstrOffs = jmpIG->igOffs + jmp->idjOffs;
3861 /* Note that the destination is always the beginning of an IG, so no need for an offset inside it */
3862 dstOffs = tgtIG->igOffs;
3864 #if defined(_TARGET_ARM_)
3866 srcInstrOffs + 4; // For relative branches, ARM PC is always considered to be the instruction address + 4
3867 #elif defined(_TARGET_ARM64_)
3869 srcInstrOffs; // For relative branches, ARM64 PC is always considered to be the instruction address
3871 srcEncodingOffs = srcInstrOffs + ssz; // Encoding offset of relative offset for small branch
3874 if (jmpIG->igNum < tgtIG->igNum)
3878 /* Adjust the target offset by the current delta. This is a worst-case estimate, as jumps between
3879 here and the target could be shortened, causing the actual distance to shrink.
3884 /* Compute the distance estimate */
3886 jmpDist = dstOffs - srcEncodingOffs;
3888 /* How much beyond the max. short distance does the jump go? */
3890 extra = jmpDist - psd;
3893 assert(jmp->idDebugOnlyInfo() != nullptr);
3894 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3896 if (INTERESTING_JUMP_NUM == 0)
3898 printf("[1] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3900 printf("[1] Jump block is at %08X\n", jmpIG->igOffs);
3901 printf("[1] Jump reloffset is %04X\n", jmp->idjOffs);
3902 printf("[1] Jump source is at %08X\n", srcEncodingOffs);
3903 printf("[1] Label block is at %08X\n", dstOffs);
3904 printf("[1] Jump dist. is %04X\n", jmpDist);
3907 printf("[1] Dist excess [S] = %d \n", extra);
3912 printf("Estimate of fwd jump [%08X/%03u]: %04X -> %04X = %04X\n", dspPtr(jmp),
3913 jmp->idDebugOnlyInfo()->idNum, srcInstrOffs, dstOffs, jmpDist);
3915 #endif // DEBUG_EMIT
3919 /* This jump will be a short one */
3927 /* Compute the distance estimate */
3929 jmpDist = srcEncodingOffs - dstOffs;
3931 /* How much beyond the max. short distance does the jump go? */
3933 extra = jmpDist + nsd;
3936 assert(jmp->idDebugOnlyInfo() != nullptr);
3937 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3939 if (INTERESTING_JUMP_NUM == 0)
3941 printf("[2] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3943 printf("[2] Jump block is at %08X\n", jmpIG->igOffs);
3944 printf("[2] Jump reloffset is %04X\n", jmp->idjOffs);
3945 printf("[2] Jump source is at %08X\n", srcEncodingOffs);
3946 printf("[2] Label block is at %08X\n", dstOffs);
3947 printf("[2] Jump dist. is %04X\n", jmpDist);
3950 printf("[2] Dist excess [S] = %d \n", extra);
3955 printf("Estimate of bwd jump [%08X/%03u]: %04X -> %04X = %04X\n", dspPtr(jmp),
3956 jmp->idDebugOnlyInfo()->idNum, srcInstrOffs, dstOffs, jmpDist);
3958 #endif // DEBUG_EMIT
3962 /* This jump will be a short one */
3967 /* We arrive here if the jump couldn't be made short, at least for now */
3969 /* We had better not have eagerly marked the jump as short
3970 * in emitIns_J(). If we did, then it has to be able to stay short
3971 * as emitIns_J() uses the worst case scenario, and blocks can
3972 * only move closer together after that.
3974 assert(jmp->idjShort == 0);
3976 /* Keep track of the closest distance we got */
3978 if (minShortExtra > (unsigned)extra)
3980 minShortExtra = (unsigned)extra;
3983 #if defined(_TARGET_ARM_)
3985 // If we're here, we couldn't convert to a small jump.
3986 // Handle conversion to medium-sized conditional jumps.
3987 // 'srcInstrOffs', 'srcEncodingOffs', 'dstOffs', 'jmpDist' have already been computed
3988 // and don't need to be recomputed.
3990 if (emitIsCondJump(jmp))
3992 if (jmpIG->igNum < tgtIG->igNum)
3996 /* How much beyond the max. medium distance does the jump go? */
3998 mextra = jmpDist - pmd;
4001 assert(jmp->idDebugOnlyInfo() != NULL);
4002 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4006 if (INTERESTING_JUMP_NUM == 0)
4007 printf("[6] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
4008 printf("[6] Dist excess [S] = %d \n", mextra);
4011 #endif // DEBUG_EMIT
4015 /* This jump will be a medium one */
4023 /* How much beyond the max. medium distance does the jump go? */
4025 mextra = jmpDist + nmd;
4028 assert(jmp->idDebugOnlyInfo() != NULL);
4029 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4033 if (INTERESTING_JUMP_NUM == 0)
4034 printf("[7] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
4035 printf("[7] Dist excess [S] = %d \n", mextra);
4038 #endif // DEBUG_EMIT
4042 /* This jump will be a medium one */
4047 /* We arrive here if the jump couldn't be made medium, at least for now */
4049 /* Keep track of the closest distance we got */
4051 if (minMediumExtra > (unsigned)mextra)
4052 minMediumExtra = (unsigned)mextra;
4055 #endif // _TARGET_ARM_
4057 /*****************************************************************************
4058 * We arrive here if the jump must stay long, at least for now.
4059 * Go try the next one.
4064 /*****************************************************************************/
4065 /* Handle conversion to short jump */
4066 /*****************************************************************************/
4070 /* Try to make this jump a short one */
4072 emitSetShortJump(jmp);
4076 continue; // This jump must be kept long
4079 /* This jump is becoming either short or medium */
4083 assert(oldSize >= jsz);
4084 sizeDif = oldSize - jsz;
4086 #if defined(_TARGET_XARCH_)
4087 jmp->idCodeSize(jsz);
4088 #elif defined(_TARGET_ARM_)
4090 // This is done as part of emitSetShortJump():
4091 insSize isz = emitInsSize(jmp->idInsFmt());
4092 jmp->idInsSize(isz);
4094 #elif defined(_TARGET_ARM64_)
4095 // The size of IF_LARGEJMP/IF_LARGEADR/IF_LARGELDC are 8 or 12.
4096 // All other code size is 4.
4097 assert((sizeDif == 4) || (sizeDif == 8));
4099 #error Unsupported or unset target architecture
4104 #if defined(_TARGET_ARM_)
4106 /*****************************************************************************/
4107 /* Handle conversion to medium jump */
4108 /*****************************************************************************/
4112 /* Try to make this jump a medium one */
4114 emitSetMediumJump(jmp);
4116 if (jmp->idCodeSize() > msz)
4118 continue; // This jump wasn't shortened
4120 assert(jmp->idCodeSize() == msz);
4122 /* This jump is becoming medium */
4126 assert(oldSize >= jsz);
4127 sizeDif = oldSize - jsz;
4131 #endif // _TARGET_ARM_
4133 /*****************************************************************************/
4137 /* Make sure the size of the jump is marked correctly */
4139 assert((0 == (jsz | jmpDist)) || (jsz == emitSizeOfJump(jmp)));
4144 printf("Shrinking jump [%08X/%03u]\n", dspPtr(jmp), jmp->idDebugOnlyInfo()->idNum);
4147 noway_assert((unsigned short)sizeDif == sizeDif);
4151 jmpIG->igSize -= (unsigned short)sizeDif;
4152 emitTotalCodeSize -= sizeDif;
4154 /* The jump size estimate wasn't accurate; flag its group */
4156 jmpIG->igFlags |= IGF_UPD_ISZ;
4158 } // end for each jump
4160 /* Did we shorten any jumps? */
4164 /* Adjust offsets of any remaining blocks */
4170 lstIG = lstIG->igNext;
4175 // printf("Adjusted offset of block %02u from %04X to %04X\n", lstIG->igNum, lstIG->igOffs,
4176 // lstIG->igOffs - adjIG);
4177 lstIG->igOffs -= adjIG;
4178 assert(IsCodeAligned(lstIG->igOffs));
4182 emitCheckIGoffsets();
4185 /* Is there a chance of other jumps becoming short? */
4186 CLANG_FORMAT_COMMENT_ANCHOR;
4188 #if defined(_TARGET_ARM_)
4190 printf("Total shrinkage = %3u, min extra short jump size = %3u, min extra medium jump size = %u\n", adjIG,
4191 minShortExtra, minMediumExtra);
4195 printf("Total shrinkage = %3u, min extra jump size = %3u\n", adjIG, minShortExtra);
4200 if ((minShortExtra <= adjIG)
4201 #if defined(_TARGET_ARM_)
4202 || (minMediumExtra <= adjIG)
4203 #endif // _TARGET_ARM_
4211 printf("Iterating branch shortening. Iteration = %d\n", jmp_iteration);
4220 void emitter::emitCheckFuncletBranch(instrDesc* jmp, insGroup* jmpIG)
4223 // We should not be jumping/branching across funclets/functions
4224 // Except possibly a 'call' to a finally funclet for a local unwind
4225 // or a 'return' from a catch handler (that can go just about anywhere)
4226 // This routine attempts to validate that any branches across funclets
4227 // meets one of those criteria...
4228 assert(jmp->idIsBound());
4230 #ifdef _TARGET_XARCH_
4231 // An lea of a code address (for constant data stored with the code)
4232 // is treated like a jump for emission purposes but is not really a jump so
4233 // we don't have to check anything here.
4234 if (jmp->idIns() == INS_lea)
4240 #ifdef _TARGET_ARMARCH_
4241 if (jmp->idAddr()->iiaHasInstrCount())
4243 // Too hard to figure out funclets from just an instruction count
4244 // You're on your own!
4247 #endif // _TARGET_ARMARCH_
4249 #ifdef _TARGET_ARM64_
4250 // No interest if it's not jmp.
4251 if (emitIsLoadLabel(jmp) || emitIsLoadConstant(jmp))
4255 #endif // _TARGET_ARM64_
4257 insGroup* tgtIG = jmp->idAddr()->iiaIGlabel;
4259 if (tgtIG->igFuncIdx != jmpIG->igFuncIdx)
4261 if (jmp->idDebugOnlyInfo()->idFinallyCall)
4263 // We don't record enough information to determine this accurately, so instead
4264 // we assume that any branch to the very start of a finally is OK.
4266 // No branches back to the root method
4267 assert(tgtIG->igFuncIdx > 0);
4268 FuncInfoDsc* tgtFunc = emitComp->funGetFunc(tgtIG->igFuncIdx);
4269 assert(tgtFunc->funKind == FUNC_HANDLER);
4270 EHblkDsc* tgtEH = emitComp->ehGetDsc(tgtFunc->funEHIndex);
4272 // Only branches to finallys (not faults, catches, filters, etc.)
4273 assert(tgtEH->HasFinallyHandler());
4275 // Only to the first block of the finally (which is properly marked)
4276 BasicBlock* tgtBlk = tgtEH->ebdHndBeg;
4277 assert(tgtBlk->bbFlags & BBF_FUNCLET_BEG);
4279 // And now we made it back to where we started
4280 assert(tgtIG == emitCodeGetCookie(tgtBlk));
4281 assert(tgtIG->igFuncIdx == emitComp->funGetFuncIdx(tgtBlk));
4283 else if (jmp->idDebugOnlyInfo()->idCatchRet)
4285 // Again there isn't enough information to prove this correct
4286 // so just allow a 'branch' to any other 'parent' funclet
4288 FuncInfoDsc* jmpFunc = emitComp->funGetFunc(jmpIG->igFuncIdx);
4289 assert(jmpFunc->funKind == FUNC_HANDLER);
4290 EHblkDsc* jmpEH = emitComp->ehGetDsc(jmpFunc->funEHIndex);
4292 // Only branches out of catches
4293 assert(jmpEH->HasCatchHandler());
4295 FuncInfoDsc* tgtFunc = emitComp->funGetFunc(tgtIG->igFuncIdx);
4297 if (tgtFunc->funKind == FUNC_HANDLER)
4299 // An outward chain to the containing funclet/EH handler
4300 // Note that it might be anywhere within nested try bodies
4301 assert(jmpEH->ebdEnclosingHndIndex == tgtFunc->funEHIndex);
4305 // This funclet is 'top level' and so it is branching back to the
4306 // root function, and should have no containing EH handlers
4307 // but it could be nested within try bodies...
4308 assert(tgtFunc->funKind == FUNC_ROOT);
4309 assert(jmpEH->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX);
4314 printf("Hit an illegal branch between funclets!");
4315 assert(tgtIG->igFuncIdx == jmpIG->igFuncIdx);
4321 /*****************************************************************************
4323 * Compute the code sizes that we're going to use to allocate the code buffers.
4327 * emitTotalHotCodeSize
4328 * emitTotalColdCodeSize
4329 * Compiler::info.compTotalHotCodeSize
4330 * Compiler::info.compTotalColdCodeSize
4333 void emitter::emitComputeCodeSizes()
4335 assert((emitComp->fgFirstColdBlock == nullptr) == (emitFirstColdIG == nullptr));
4337 if (emitFirstColdIG)
4339 emitTotalHotCodeSize = emitFirstColdIG->igOffs;
4340 emitTotalColdCodeSize = emitTotalCodeSize - emitTotalHotCodeSize;
4344 emitTotalHotCodeSize = emitTotalCodeSize;
4345 emitTotalColdCodeSize = 0;
4348 emitComp->info.compTotalHotCodeSize = emitTotalHotCodeSize;
4349 emitComp->info.compTotalColdCodeSize = emitTotalColdCodeSize;
4352 if (emitComp->verbose)
4354 printf("\nHot code size = 0x%X bytes\n", emitTotalHotCodeSize);
4355 printf("Cold code size = 0x%X bytes\n", emitTotalColdCodeSize);
4360 /*****************************************************************************
4362 * Called at the end of code generation, this method creates the code, data
4363 * and GC info blocks for the method. Returns the size of the method (which must fit in an unsigned).
4366 unsigned emitter::emitEndCodeGen(Compiler* comp,
4367 bool contTrkPtrLcls,
4371 unsigned xcptnsCount,
4372 unsigned* prologSize,
4373 unsigned* epilogSize,
4375 void** coldCodeAddr,
4379 if (emitComp->verbose)
4381 printf("*************** In emitEndCodeGen()\n");
4389 BYTE* coldCodeBlock;
4392 assert(emitCurIG == nullptr);
4394 emitCodeBlock = nullptr;
4395 emitConsBlock = nullptr;
4397 /* Tell everyone whether we have fully interruptible code or not */
4399 emitFullyInt = fullyInt;
4400 emitFullGCinfo = fullPtrMap;
4402 #ifndef UNIX_X86_ABI
4403 emitFullArgInfo = !emitHasFramePtr;
4405 emitFullArgInfo = fullPtrMap;
4409 GCrefsTable.record(emitGCrFrameOffsCnt);
4410 emitSizeTable.record(static_cast<unsigned>(emitSizeMethod));
4411 stkDepthTable.record(emitMaxStackDepth);
4412 #endif // EMITTER_STATS
4414 // Default values, correct even if EMIT_TRACK_STACK_DEPTH is 0.
4415 emitSimpleStkUsed = true;
4416 u1.emitSimpleStkMask = 0;
4417 u1.emitSimpleByrefStkMask = 0;
4419 #if EMIT_TRACK_STACK_DEPTH
4420 /* Convert max. stack depth from # of bytes to # of entries */
4422 unsigned maxStackDepthIn4ByteElements = emitMaxStackDepth / sizeof(int);
4423 JITDUMP("Converting emitMaxStackDepth from bytes (%d) to elements (%d)\n", emitMaxStackDepth,
4424 maxStackDepthIn4ByteElements);
4425 emitMaxStackDepth = maxStackDepthIn4ByteElements;
4427 /* Should we use the simple stack */
4429 if (emitMaxStackDepth > MAX_SIMPLE_STK_DEPTH || emitFullGCinfo)
4431 /* We won't use the "simple" argument table */
4433 emitSimpleStkUsed = false;
4435 /* Allocate the argument tracking table */
4437 if (emitMaxStackDepth <= sizeof(u2.emitArgTrackLcl))
4439 u2.emitArgTrackTab = (BYTE*)u2.emitArgTrackLcl;
4443 u2.emitArgTrackTab = (BYTE*)emitGetMem(roundUp(emitMaxStackDepth));
4446 u2.emitArgTrackTop = u2.emitArgTrackTab;
4447 u2.emitGcArgTrackCnt = 0;
4451 if (emitEpilogCnt == 0)
4453 /* No epilogs, make sure the epilog size is set to 0 */
4457 #ifdef _TARGET_XARCH_
4458 emitExitSeqSize = 0;
4459 #endif // _TARGET_XARCH_
4462 /* Return the size of the epilog to the caller */
4464 *epilogSize = emitEpilogSize;
4466 #ifdef _TARGET_XARCH_
4467 *epilogSize += emitExitSeqSize;
4468 #endif // _TARGET_XARCH_
4471 if (EMIT_INSTLIST_VERBOSE)
4473 printf("\nInstruction list before instruction issue:\n\n");
4474 emitDispIGlist(true);
4477 emitCheckIGoffsets();
4480 /* Allocate the code block (and optionally the data blocks) */
4482 // If we're doing procedure splitting and we found cold blocks, then
4483 // allocate hot and cold buffers. Otherwise only allocate a hot
4486 coldCodeBlock = nullptr;
4488 CorJitAllocMemFlag allocMemFlag = CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN;
4492 // These are the heuristics we use to decide whether or not to force the
4493 // code to be 16-byte aligned.
4495 // 1. For ngen code with IBC data, use 16-byte alignment if the method
4496 // has been called more than BB_VERY_HOT_WEIGHT times.
4497 // 2. For JITed code and ngen code without IBC data, use 16-byte alignment
4498 // when the code is 16 bytes or smaller. We align small getters/setters
4499 // because of they are penalized heavily on certain hardware when not 16-byte
4500 // aligned (VSWhidbey #373938). To minimize size impact of this optimization,
4501 // we do not align large methods because of the penalty is amortized for them.
4503 if (emitComp->fgHaveProfileData())
4505 if (emitComp->fgCalledCount > (BB_VERY_HOT_WEIGHT * emitComp->fgProfileRunsCount()))
4507 allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN;
4512 if (emitTotalHotCodeSize <= 16)
4514 allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN;
4519 #ifdef _TARGET_ARM64_
4520 // For arm64, we want to allocate JIT data always adjacent to code similar to what native compiler does.
4521 // This way allows us to use a single `ldr` to access such data like float constant/jmp table.
4522 if (emitTotalColdCodeSize > 0)
4524 // JIT data might be far away from the cold code.
4525 NYI_ARM64("Need to handle fix-up to data from cold code.");
4528 UNATIVE_OFFSET roDataAlignmentDelta = 0;
4529 if (emitConsDsc.dsdOffs)
4531 UNATIVE_OFFSET roDataAlignment = sizeof(void*); // 8 Byte align by default.
4532 roDataAlignmentDelta = (UNATIVE_OFFSET)ALIGN_UP(emitTotalHotCodeSize, roDataAlignment) - emitTotalHotCodeSize;
4533 assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4));
4535 emitCmpHandle->allocMem(emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs, emitTotalColdCodeSize, 0,
4536 xcptnsCount, allocMemFlag, (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock);
4538 consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta;
4541 emitCmpHandle->allocMem(emitTotalHotCodeSize, emitTotalColdCodeSize, emitConsDsc.dsdOffs, xcptnsCount, allocMemFlag,
4542 (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock);
4545 // if (emitConsDsc.dsdOffs)
4546 // printf("Cons=%08X\n", consBlock);
4548 /* Give the block addresses to the caller and other functions here */
4550 *codeAddr = emitCodeBlock = codeBlock;
4551 *coldCodeAddr = emitColdCodeBlock = coldCodeBlock;
4552 *consAddr = emitConsBlock = consBlock;
4554 /* Nothing has been pushed on the stack */
4555 CLANG_FORMAT_COMMENT_ANCHOR;
4557 #if EMIT_TRACK_STACK_DEPTH
4558 emitCurStackLvl = 0;
4561 /* Assume no live GC ref variables on entry */
4563 VarSetOps::OldStyleClearD(emitComp, emitThisGCrefVars); // This is initialized to Empty at the start of codegen.
4564 emitThisGCrefRegs = emitThisByrefRegs = RBM_NONE;
4565 emitThisGCrefVset = true;
4571 // We don't use these after this point
4573 VarSetOps::AssignNoCopy(emitComp, emitPrevGCrefVars, VarSetOps::UninitVal());
4574 emitPrevGCrefRegs = emitPrevByrefRegs = 0xBAADFEED;
4576 VarSetOps::AssignNoCopy(emitComp, emitInitGCrefVars, VarSetOps::UninitVal());
4577 emitInitGCrefRegs = emitInitByrefRegs = 0xBAADFEED;
4581 /* Initialize the GC ref variable lifetime tracking logic */
4583 codeGen->gcInfo.gcVarPtrSetInit();
4585 emitSyncThisObjOffs = -1; /* -1 means no offset set */
4586 emitSyncThisObjReg = REG_NA; /* REG_NA means not set */
4588 #ifdef JIT32_GCENCODER
4589 if (emitComp->lvaKeepAliveAndReportThis())
4591 assert(emitComp->lvaIsOriginalThisArg(0));
4592 LclVarDsc* thisDsc = &emitComp->lvaTable[0];
4594 /* If "this" (which is passed in as a register argument in REG_ARG_0)
4595 is enregistered, we normally spot the "mov REG_ARG_0 -> thisReg"
4596 in the prolog and note the location of "this" at that point.
4597 However, if 'this' is enregistered into REG_ARG_0 itself, no code
4598 will be generated in the prolog, so we explicitly need to note
4599 the location of "this" here.
4600 NOTE that we can do this even if "this" is not enregistered in
4601 REG_ARG_0, and it will result in more accurate "this" info over the
4602 prolog. However, as methods are not interruptible over the prolog,
4603 we try to save space by avoiding that.
4606 if (thisDsc->lvRegister)
4608 emitSyncThisObjReg = thisDsc->lvRegNum;
4610 if (emitSyncThisObjReg == (int)REG_ARG_0 &&
4611 (codeGen->intRegState.rsCalleeRegArgMaskLiveIn & genRegMask(REG_ARG_0)))
4615 emitGCregLiveSet(GCT_GCREF, genRegMask(REG_ARG_0),
4616 emitCodeBlock, // from offset 0
4621 /* If emitFullGCinfo==false, the we don't use any
4622 regPtrDsc's and so explictly note the location
4623 of "this" in GCEncode.cpp
4629 #endif // JIT32_GCENCODER
4631 emitContTrkPtrLcls = contTrkPtrLcls;
4633 /* Are there any GC ref variables on the stack? */
4635 if (emitGCrFrameOffsCnt)
4643 /* Allocate and clear emitGCrFrameLiveTab[]. This is the table
4644 mapping "stkOffs -> varPtrDsc". It holds a pointer to
4645 the liveness descriptor that was created when the
4646 variable became alive. When the variable becomes dead, the
4647 descriptor will be appended to the liveness descriptor list, and
4648 the entry in emitGCrFrameLiveTab[] will be made NULL.
4650 Note that if all GC refs are assigned consecutively,
4651 emitGCrFrameLiveTab[] can be only as big as the number of GC refs
4652 present, instead of lvaTrackedCount.
4655 siz = emitGCrFrameOffsCnt * sizeof(*emitGCrFrameLiveTab);
4656 emitGCrFrameLiveTab = (varPtrDsc**)emitGetMem(roundUp(siz));
4657 memset(emitGCrFrameLiveTab, 0, siz);
4659 /* Allocate and fill in emitGCrFrameOffsTab[]. This is the table
4660 mapping "varIndex -> stkOffs".
4661 Non-ptrs or reg vars have entries of -1.
4662 Entries of Tracked stack byrefs have the lower bit set to 1.
4665 emitTrkVarCnt = cnt = emitComp->lvaTrackedCount;
4667 emitGCrFrameOffsTab = tab = (int*)emitGetMem(cnt * sizeof(int));
4669 memset(emitGCrFrameOffsTab, -1, cnt * sizeof(int));
4671 /* Now fill in all the actual used entries */
4673 for (num = 0, dsc = emitComp->lvaTable, cnt = emitComp->lvaCount; num < cnt; num++, dsc++)
4675 if (!dsc->lvOnFrame || (dsc->lvIsParam && !dsc->lvIsRegArg))
4680 #if FEATURE_FIXED_OUT_ARGS
4681 if (num == emitComp->lvaOutgoingArgSpaceVar)
4685 #endif // FEATURE_FIXED_OUT_ARGS
4687 int offs = dsc->lvStkOffs;
4689 /* Is it within the interesting range of offsets */
4691 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
4693 /* Are tracked stack ptr locals laid out contiguously?
4694 If not, skip non-ptrs. The emitter is optimized to work
4695 with contiguous ptrs, but for EditNContinue, the variables
4696 are laid out in the order they occur in the local-sig.
4699 if (!emitContTrkPtrLcls)
4701 if (!emitComp->lvaIsGCTracked(dsc))
4707 unsigned indx = dsc->lvVarIndex;
4709 assert(!dsc->lvRegister);
4710 assert(dsc->lvTracked);
4711 assert(dsc->lvRefCnt != 0);
4713 assert(dsc->TypeGet() == TYP_REF || dsc->TypeGet() == TYP_BYREF);
4715 assert(indx < emitComp->lvaTrackedCount);
4717 // printf("Variable #%2u/%2u is at stack offset %d\n", num, indx, offs);
4719 #ifdef JIT32_GCENCODER
4720 #ifndef WIN64EXCEPTIONS
4721 /* Remember the frame offset of the "this" argument for synchronized methods */
4722 if (emitComp->lvaIsOriginalThisArg(num) && emitComp->lvaKeepAliveAndReportThis())
4724 emitSyncThisObjOffs = offs;
4725 offs |= this_OFFSET_FLAG;
4728 #endif // JIT32_GCENCODER
4730 if (dsc->TypeGet() == TYP_BYREF)
4732 offs |= byref_OFFSET_FLAG;
4742 emitGCrFrameOffsTab = nullptr;
4747 if (emitComp->verbose)
4749 printf("\n***************************************************************************\n");
4750 printf("Instructions as they come out of the scheduler\n\n");
4754 /* Issue all instruction groups in order */
4757 #define DEFAULT_CODE_BUFFER_INIT 0xcc
4759 for (ig = emitIGlist; ig; ig = ig->igNext)
4761 assert(!(ig->igFlags & IGF_PLACEHOLDER)); // There better not be any placeholder groups left
4763 /* Is this the first cold block? */
4764 if (ig == emitFirstColdIG)
4766 unsigned actualHotCodeSize = emitCurCodeOffs(cp);
4768 /* Fill in eventual unused space */
4769 while (emitCurCodeOffs(cp) < emitTotalHotCodeSize)
4771 *cp++ = DEFAULT_CODE_BUFFER_INIT;
4774 assert(coldCodeBlock);
4777 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
4779 printf("\n************** Beginning of cold code **************\n");
4784 /* Are we overflowing? */
4785 if (ig->igNext && ig->igNum + 1 != ig->igNext->igNum)
4787 NO_WAY("Too many instruction groups");
4790 // If this instruction group is returned to from a funclet implementing a finally,
4791 // on architectures where it is necessary generate GC info for the current instruction as
4792 // if it were the instruction following a call.
4793 emitGenGCInfoIfFuncletRetTarget(ig, cp);
4795 instrDesc* id = (instrDesc*)ig->igData;
4799 /* Print the IG label, but only if it is a branch label */
4801 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
4803 if (emitComp->verbose)
4806 emitDispIG(ig); // Display the flags, IG data, etc.
4810 printf("\nG_M%03u_IG%02u:\n", Compiler::s_compMethodsCount, ig->igNum);
4818 /* Record the actual offset of the block, noting the difference */
4820 emitOffsAdj = ig->igOffs - emitCurCodeOffs(cp);
4821 assert(emitOffsAdj >= 0);
4824 if ((emitOffsAdj != 0) && emitComp->verbose)
4826 printf("Block predicted offs = %08X, actual = %08X -> size adj = %d\n", ig->igOffs, emitCurCodeOffs(cp),
4829 #endif // DEBUG_EMIT
4831 ig->igOffs = emitCurCodeOffs(cp);
4832 assert(IsCodeAligned(ig->igOffs));
4834 #if EMIT_TRACK_STACK_DEPTH
4836 /* Set the proper stack level if appropriate */
4838 if (ig->igStkLvl != emitCurStackLvl)
4840 /* We are pushing stuff implicitly at this label */
4842 assert((unsigned)ig->igStkLvl > (unsigned)emitCurStackLvl);
4843 emitStackPushN(cp, (ig->igStkLvl - (unsigned)emitCurStackLvl) / sizeof(int));
4848 /* Update current GC information for non-overflow IG (not added implicitly by the emitter) */
4850 if (!(ig->igFlags & IGF_EMIT_ADD))
4852 /* Is there a new set of live GC ref variables? */
4854 if (ig->igFlags & IGF_GC_VARS)
4856 emitUpdateLiveGCvars(ig->igGCvars(), cp);
4858 else if (!emitThisGCrefVset)
4860 emitUpdateLiveGCvars(emitThisGCrefVars, cp);
4863 /* Update the set of live GC ref registers */
4866 regMaskTP GCregs = ig->igGCregs;
4868 if (GCregs != emitThisGCrefRegs)
4870 emitUpdateLiveGCregs(GCT_GCREF, GCregs, cp);
4874 /* Is there a new set of live byref registers? */
4876 if (ig->igFlags & IGF_BYREF_REGS)
4878 unsigned byrefRegs = ig->igByrefRegs();
4880 if (byrefRegs != emitThisByrefRegs)
4882 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, cp);
4888 // These are not set for "overflow" groups
4889 assert(!(ig->igFlags & IGF_GC_VARS));
4890 assert(!(ig->igFlags & IGF_BYREF_REGS));
4893 /* Issue each instruction in order */
4897 for (unsigned cnt = ig->igInsCnt; cnt; cnt--)
4899 castto(id, BYTE*) += emitIssue1Instr(ig, id, &cp);
4902 emitCurIG = nullptr;
4904 assert(ig->igSize >= cp - bp);
4905 ig->igSize = (unsigned short)(cp - bp);
4908 #if EMIT_TRACK_STACK_DEPTH
4909 assert(emitCurStackLvl == 0);
4912 /* Output any initialized data we may have */
4914 if (emitConsDsc.dsdOffs)
4916 emitOutputDataSec(&emitConsDsc, consBlock);
4919 /* Make sure all GC ref variables are marked as dead */
4921 if (emitGCrFrameOffsCnt)
4927 for (vn = 0, of = emitGCrFrameOffsMin, dp = emitGCrFrameLiveTab; vn < emitGCrFrameOffsCnt;
4928 vn++, of += sizeof(void*), dp++)
4932 emitGCvarDeadSet(of, cp, vn);
4937 /* No GC registers are live any more */
4939 if (emitThisByrefRegs)
4941 emitUpdateLiveGCregs(GCT_BYREF, RBM_NONE, cp);
4943 if (emitThisGCrefRegs)
4945 emitUpdateLiveGCregs(GCT_GCREF, RBM_NONE, cp);
4948 /* Patch any forward jumps */
4954 for (jmp = emitJumpList; jmp; jmp = jmp->idjNext)
4957 #ifdef _TARGET_XARCH_
4958 assert(jmp->idInsFmt() == IF_LABEL || jmp->idInsFmt() == IF_RWR_LABEL || jmp->idInsFmt() == IF_SWR_LABEL);
4960 tgt = jmp->idAddr()->iiaIGlabel;
4962 if (jmp->idjTemp.idjAddr == nullptr)
4967 if (jmp->idjOffs != tgt->igOffs)
4969 BYTE* adr = jmp->idjTemp.idjAddr;
4970 int adj = jmp->idjOffs - tgt->igOffs;
4972 // On Arm, the offset is encoded in unit of 2 bytes.
4977 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4980 printf("[5] This output is broken for ARM, since it doesn't properly decode the jump offsets of "
4981 "the instruction at adr\n");
4984 if (INTERESTING_JUMP_NUM == 0)
4986 printf("[5] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
4991 printf("[5] Jump is at %08X\n", (adr + 1 - emitCodeBlock));
4992 printf("[5] Jump distance is %02X - %02X = %02X\n", *(BYTE*)adr, adj, *(BYTE*)adr - adj);
4996 printf("[5] Jump is at %08X\n", (adr + 4 - emitCodeBlock));
4997 printf("[5] Jump distance is %08X - %02X = %08X\n", *(int*)adr, adj, *(int*)adr - adj);
5000 #endif // DEBUG_EMIT
5004 // Patch Forward Short Jump
5005 CLANG_FORMAT_COMMENT_ANCHOR;
5006 #if defined(_TARGET_XARCH_)
5007 *(BYTE*)adr -= (BYTE)adj;
5008 #elif defined(_TARGET_ARM_)
5009 // The following works because the jump offset is in the low order bits of the instruction.
5010 // Presumably we could also just call "emitOutputLJ(NULL, adr, jmp)", like for long jumps?
5011 *(short int*)adr -= (short)adj;
5012 #elif defined(_TARGET_ARM64_)
5013 assert(!jmp->idAddr()->iiaHasInstrCount());
5014 emitOutputLJ(NULL, adr, jmp);
5016 #error Unsupported or unset target architecture
5021 // Patch Forward non-Short Jump
5022 CLANG_FORMAT_COMMENT_ANCHOR;
5023 #if defined(_TARGET_XARCH_)
5025 #elif defined(_TARGET_ARMARCH_)
5026 assert(!jmp->idAddr()->iiaHasInstrCount());
5027 emitOutputLJ(NULL, adr, jmp);
5029 #error Unsupported or unset target architecture
5037 if (emitComp->opts.disAsm)
5042 if (emitComp->verbose)
5044 printf("Allocated method code size = %4u , actual size = %4u\n", emitTotalCodeSize, cp - codeBlock);
5048 unsigned actualCodeSize = emitCurCodeOffs(cp);
5050 /* Fill in eventual unused space */
5051 while (emitCurCodeOffs(cp) < emitTotalCodeSize)
5053 *cp++ = DEFAULT_CODE_BUFFER_INIT;
5057 totAllocdSize += emitTotalCodeSize;
5058 totActualSize += actualCodeSize;
5063 // Make sure these didn't change during the "issuing" phase
5065 assert(VarSetOps::MayBeUninit(emitPrevGCrefVars));
5066 assert(emitPrevGCrefRegs == 0xBAADFEED);
5067 assert(emitPrevByrefRegs == 0xBAADFEED);
5069 assert(VarSetOps::MayBeUninit(emitInitGCrefVars));
5070 assert(emitInitGCrefRegs == 0xBAADFEED);
5071 assert(emitInitByrefRegs == 0xBAADFEED);
5075 // Assign the real prolog size
5076 *prologSize = emitCodeOffset(emitPrologIG, emitPrologEndPos);
5078 /* Return the amount of code we've generated */
5080 return actualCodeSize;
5083 // See specification comment at the declaration.
5084 void emitter::emitGenGCInfoIfFuncletRetTarget(insGroup* ig, BYTE* cp)
5086 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
5087 // We only emit this GC information on targets where finally's are implemented via funclets,
5088 // and the finally is invoked, during non-exceptional execution, via a branch with a predefined
5089 // link register, rather than a "true call" for which we would already generate GC info. Currently,
5090 // this means precisely ARM.
5091 if (ig->igFlags & IGF_FINALLY_TARGET)
5093 // We don't actually have a call instruction in this case, so we don't have
5094 // a real size for that instruction. We'll use 1.
5095 emitStackPop(cp, /*isCall*/ true, /*callInstrSize*/ 1, /*args*/ 0);
5097 /* Do we need to record a call location for GC purposes? */
5098 if (!emitFullGCinfo)
5100 emitRecordGCcall(cp, /*callInstrSize*/ 1);
5103 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
5106 /*****************************************************************************
5108 * We have an instruction in an insGroup and we need to know the
5109 * instruction number for this instruction
5112 unsigned emitter::emitFindInsNum(insGroup* ig, instrDesc* idMatch)
5114 instrDesc* id = (instrDesc*)ig->igData;
5116 // Check if we are the first instruction in the group
5122 /* Walk the list of instructions until we find a match */
5123 unsigned insNum = 0;
5124 unsigned insRemaining = ig->igInsCnt;
5126 while (insRemaining > 0)
5128 castto(id, BYTE*) += emitSizeOfInsDsc(id);
5137 assert(!"emitFindInsNum failed");
5141 /*****************************************************************************
5143 * We've been asked for the code offset of an instruction but alas one or
5144 * more instruction sizes in the block have been mis-predicted, so we have
5145 * to find the true offset by looking for the instruction within the group.
5148 UNATIVE_OFFSET emitter::emitFindOffset(insGroup* ig, unsigned insNum)
5150 instrDesc* id = (instrDesc*)ig->igData;
5151 UNATIVE_OFFSET of = 0;
5154 /* Make sure we were passed reasonable arguments */
5155 assert(ig && ig->igSelf == ig);
5156 assert(ig->igInsCnt >= insNum);
5159 /* Walk the instruction list until all are counted */
5163 of += emitInstCodeSz(id);
5165 castto(id, BYTE*) += emitSizeOfInsDsc(id);
5173 /*****************************************************************************
5175 * Start generating a constant data section for the current
5176 * function. Returns the offset of the section in the appropriate data
5180 UNATIVE_OFFSET emitter::emitDataGenBeg(UNATIVE_OFFSET size, bool dblAlign, bool codeLtab)
5183 dataSection* secDesc;
5185 assert(emitDataSecCur == nullptr);
5187 /* The size better not be some kind of an odd thing */
5189 assert(size && size % sizeof(int) == 0);
5191 /* Get hold of the current offset */
5193 secOffs = emitConsDsc.dsdOffs;
5195 /* Are we require to align this request on an eight byte boundry? */
5196 if (dblAlign && (secOffs % sizeof(double) != 0))
5198 /* Need to skip 4 bytes to honor dblAlign */
5199 /* Must allocate a dummy 4 byte integer */
5201 emitDataGenBeg(4, false, false);
5202 emitDataGenData(0, &zero, 4);
5205 /* Get the new secOffs */
5206 secOffs = emitConsDsc.dsdOffs;
5207 /* Now it should be a multiple of 8 */
5208 assert(secOffs % sizeof(double) == 0);
5211 /* Advance the current offset */
5213 emitConsDsc.dsdOffs += size;
5215 /* Allocate a data section descriptor and add it to the list */
5217 secDesc = emitDataSecCur = (dataSection*)emitGetMem(roundUp(sizeof(*secDesc) + size));
5219 secDesc->dsSize = size;
5221 secDesc->dsType = dataSection::data;
5223 secDesc->dsNext = nullptr;
5225 if (emitConsDsc.dsdLast)
5227 emitConsDsc.dsdLast->dsNext = secDesc;
5231 emitConsDsc.dsdList = secDesc;
5233 emitConsDsc.dsdLast = secDesc;
5238 // Start generating a constant data section for the current function
5239 // populated with BasicBlock references.
5240 // You can choose the references to be either absolute pointers, or
5241 // 4-byte relative addresses.
5242 // Currently the relative references are relative to the start of the
5243 // first block (this is somewhat arbitrary)
5245 UNATIVE_OFFSET emitter::emitBBTableDataGenBeg(unsigned numEntries, bool relativeAddr)
5248 dataSection* secDesc;
5250 assert(emitDataSecCur == nullptr);
5252 UNATIVE_OFFSET emittedSize;
5256 emittedSize = numEntries * 4;
5260 emittedSize = numEntries * TARGET_POINTER_SIZE;
5263 /* Get hold of the current offset */
5265 secOffs = emitConsDsc.dsdOffs;
5267 /* Advance the current offset */
5269 emitConsDsc.dsdOffs += emittedSize;
5271 /* Allocate a data section descriptor and add it to the list */
5273 secDesc = emitDataSecCur = (dataSection*)emitGetMem(roundUp(sizeof(*secDesc) + numEntries * sizeof(BasicBlock*)));
5275 secDesc->dsSize = emittedSize;
5277 secDesc->dsType = relativeAddr ? dataSection::blockRelative32 : dataSection::blockAbsoluteAddr;
5279 secDesc->dsNext = nullptr;
5281 if (emitConsDsc.dsdLast)
5283 emitConsDsc.dsdLast->dsNext = secDesc;
5287 emitConsDsc.dsdList = secDesc;
5290 emitConsDsc.dsdLast = secDesc;
5295 /*****************************************************************************
5297 * Emit the given block of bits into the current data section.
5300 void emitter::emitDataGenData(unsigned offs, const void* data, size_t size)
5302 assert(emitDataSecCur && (emitDataSecCur->dsSize >= offs + size));
5304 assert(emitDataSecCur->dsType == dataSection::data);
5306 memcpy(emitDataSecCur->dsCont + offs, data, size);
5309 /*****************************************************************************
5311 * Emit the address of the given basic block into the current data section.
5314 void emitter::emitDataGenData(unsigned index, BasicBlock* label)
5316 assert(emitDataSecCur != nullptr);
5317 assert(emitDataSecCur->dsType == dataSection::blockAbsoluteAddr ||
5318 emitDataSecCur->dsType == dataSection::blockRelative32);
5320 unsigned emittedElemSize = emitDataSecCur->dsType == dataSection::blockAbsoluteAddr ? TARGET_POINTER_SIZE : 4;
5322 assert(emitDataSecCur->dsSize >= emittedElemSize * (index + 1));
5324 ((BasicBlock**)(emitDataSecCur->dsCont))[index] = label;
5327 /*****************************************************************************
5329 * We're done generating a data section.
5332 void emitter::emitDataGenEnd()
5336 assert(emitDataSecCur);
5337 emitDataSecCur = nullptr;
5341 /********************************************************************************
5342 * Generates a data section constant
5345 * cnsAddr - memory location containing constant value
5346 * cnsSize - size of constant in bytes
5347 * dblAlign - whether to double align the data section constant
5349 * Returns constant number as offset into data section.
5351 UNATIVE_OFFSET emitter::emitDataConst(const void* cnsAddr, unsigned cnsSize, bool dblAlign)
5353 // When generating SMALL_CODE, we don't bother with dblAlign
5354 if (dblAlign && (emitComp->compCodeOpt() == Compiler::SMALL_CODE))
5359 UNATIVE_OFFSET cnum = emitDataGenBeg(cnsSize, dblAlign, false);
5360 emitDataGenData(0, cnsAddr, cnsSize);
5366 #ifndef LEGACY_BACKEND
5368 //------------------------------------------------------------------------
5369 // emitAnyConst: Create a data section constant of arbitrary size.
5372 // cnsAddr - pointer to the data to be placed in the data section
5373 // cnsSize - size of the data
5374 // dblAlign - whether to align the data section to an 8 byte boundary
5377 // A field handle representing the data offset to access the constant.
5379 CORINFO_FIELD_HANDLE emitter::emitAnyConst(const void* cnsAddr, unsigned cnsSize, bool dblAlign)
5381 UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
5382 return emitComp->eeFindJitDataOffs(cnum);
5385 //------------------------------------------------------------------------
5386 // emitFltOrDblConst: Create a float or double data section constant.
5389 // constValue - constant value
5390 // attr - constant size
5393 // A field handle representing the data offset to access the constant.
5396 // If attr is EA_4BYTE then the double value is converted to a float value.
5397 // If attr is EA_8BYTE then 8 byte alignment is automatically requested.
5399 CORINFO_FIELD_HANDLE emitter::emitFltOrDblConst(double constValue, emitAttr attr)
5401 assert((attr == EA_4BYTE) || (attr == EA_8BYTE));
5407 if (attr == EA_4BYTE)
5409 f = forceCastToFloat(constValue);
5415 cnsAddr = &constValue;
5419 // Access to inline data is 'abstracted' by a special type of static member
5420 // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
5421 // to constant data, not a real static field.
5423 UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
5424 UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
5425 return emitComp->eeFindJitDataOffs(cnum);
5429 /*****************************************************************************
5431 * Output the given data section at the specified address.
5434 void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst)
5439 printf("\nEmitting data sections: %u total bytes\n", sec->dsdOffs);
5442 unsigned secNum = 0;
5446 assert(sec->dsdOffs);
5447 assert(sec->dsdList);
5449 /* Walk and emit the contents of all the data blocks */
5453 for (dsc = sec->dsdList; dsc; dsc = dsc->dsNext)
5455 size_t dscSize = dsc->dsSize;
5457 // absolute label table
5458 if (dsc->dsType == dataSection::blockAbsoluteAddr)
5460 JITDUMP(" section %u, size %u, block absolute addr\n", secNum++, dscSize);
5462 assert(dscSize && dscSize % sizeof(BasicBlock*) == 0);
5463 size_t numElems = dscSize / TARGET_POINTER_SIZE;
5464 BYTE** bDst = (BYTE**)dst;
5465 for (unsigned i = 0; i < numElems; i++)
5467 BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i];
5469 // Convert the BasicBlock* value to an IG address
5470 insGroup* lab = (insGroup*)emitCodeGetCookie(block);
5472 // Append the appropriate address to the destination
5473 BYTE* target = emitOffsetToPtr(lab->igOffs);
5476 target = (BYTE*)((size_t)target | 1); // Or in thumb bit
5479 if (emitComp->opts.compReloc)
5481 emitRecordRelocation(&(bDst[i]), target, IMAGE_REL_BASED_HIGHLOW);
5484 JITDUMP(" BB%02u: 0x%p\n", block->bbNum, bDst[i]);
5487 // relative label table
5488 else if (dsc->dsType == dataSection::blockRelative32)
5490 JITDUMP(" section %u, size %u, block relative addr\n", secNum++, dscSize);
5492 unsigned elemSize = 4;
5493 size_t numElems = dscSize / 4;
5494 unsigned* uDst = (unsigned*)dst;
5495 insGroup* labFirst = (insGroup*)emitCodeGetCookie(emitComp->fgFirstBB);
5497 for (unsigned i = 0; i < numElems; i++)
5499 BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i];
5501 // Convert the BasicBlock* value to an IG address
5502 insGroup* lab = (insGroup*)emitCodeGetCookie(block);
5504 assert(FitsIn<uint32_t>(lab->igOffs - labFirst->igOffs));
5505 uDst[i] = lab->igOffs - labFirst->igOffs;
5507 JITDUMP(" BB%02u: 0x%x\n", block->bbNum, uDst[i]);
5512 JITDUMP(" section %u, size %u, raw data\n", secNum++, dscSize);
5514 // Simple binary data: copy the bytes to the target
5515 assert(dsc->dsType == dataSection::data);
5517 memcpy(dst, dsc->dsCont, dscSize);
5523 for (size_t i = 0; i < dscSize; i++)
5525 printf("%02x ", dsc->dsCont[i]);
5526 if ((((i + 1) % 16) == 0) && (i + 1 != dscSize))
5539 /*****************************************************************************/
5540 /*****************************************************************************
5542 * Record the fact that the given variable now contains a live GC ref.
5545 void emitter::emitGCvarLiveSet(int offs, GCtype gcType, BYTE* addr, ssize_t disp)
5547 assert(emitIssuing);
5551 assert((abs(offs) % sizeof(ssize_t)) == 0);
5552 assert(needsGC(gcType));
5554 /* Compute the index into the GC frame table if the caller didn't do it */
5558 disp = (offs - emitGCrFrameOffsMin) / sizeof(void*);
5561 assert((size_t)disp < emitGCrFrameOffsCnt);
5563 /* Allocate a lifetime record */
5565 desc = new (emitComp, CMK_GC) varPtrDsc;
5567 desc->vpdBegOfs = emitCurCodeOffs(addr);
5569 desc->vpdEndOfs = 0xFACEDEAD;
5572 desc->vpdVarNum = offs;
5574 desc->vpdNext = nullptr;
5576 #if !defined(JIT32_GCENCODER) || !defined(WIN64EXCEPTIONS)
5577 /* the lower 2 bits encode props about the stk ptr */
5579 if (offs == emitSyncThisObjOffs)
5581 desc->vpdVarNum |= this_OFFSET_FLAG;
5585 if (gcType == GCT_BYREF)
5587 desc->vpdVarNum |= byref_OFFSET_FLAG;
5590 /* Append the new entry to the end of the list */
5591 if (codeGen->gcInfo.gcVarPtrLast == nullptr)
5593 assert(codeGen->gcInfo.gcVarPtrList == nullptr);
5594 codeGen->gcInfo.gcVarPtrList = codeGen->gcInfo.gcVarPtrLast = desc;
5598 assert(codeGen->gcInfo.gcVarPtrList != nullptr);
5599 codeGen->gcInfo.gcVarPtrLast->vpdNext = desc;
5600 codeGen->gcInfo.gcVarPtrLast = desc;
5603 /* Record the variable descriptor in the table */
5605 assert(emitGCrFrameLiveTab[disp] == nullptr);
5606 emitGCrFrameLiveTab[disp] = desc;
5611 printf("[%08X] %s var born at [%s", dspPtr(desc), GCtypeStr(gcType), emitGetFrameReg());
5615 printf("-%02XH", -offs);
5619 printf("+%02XH", +offs);
5626 /* The "global" live GC variable mask is no longer up-to-date */
5628 emitThisGCrefVset = false;
5631 /*****************************************************************************
5633 * Record the fact that the given variable no longer contains a live GC ref.
5636 void emitter::emitGCvarDeadSet(int offs, BYTE* addr, ssize_t disp)
5638 assert(emitIssuing);
5642 assert(abs(offs) % sizeof(int) == 0);
5644 /* Compute the index into the GC frame table if the caller didn't do it */
5648 disp = (offs - emitGCrFrameOffsMin) / sizeof(void*);
5651 assert((unsigned)disp < emitGCrFrameOffsCnt);
5653 /* Get hold of the lifetime descriptor and clear the entry */
5655 desc = emitGCrFrameLiveTab[disp];
5656 emitGCrFrameLiveTab[disp] = nullptr;
5659 assert((desc->vpdVarNum & ~OFFSET_MASK) == (unsigned)offs);
5661 /* Record the death code offset */
5663 assert(desc->vpdEndOfs == 0xFACEDEAD);
5664 desc->vpdEndOfs = emitCurCodeOffs(addr);
5669 GCtype gcType = (desc->vpdVarNum & byref_OFFSET_FLAG) ? GCT_BYREF : GCT_GCREF;
5670 #if !defined(JIT32_GCENCODER) || !defined(WIN64EXCEPTIONS)
5671 bool isThis = (desc->vpdVarNum & this_OFFSET_FLAG) != 0;
5673 printf("[%08X] %s%s var died at [%s", dspPtr(desc), GCtypeStr(gcType), isThis ? "this-ptr" : "",
5676 bool isPinned = (desc->vpdVarNum & pinned_OFFSET_FLAG) != 0;
5678 printf("[%08X] %s%s var died at [%s", dspPtr(desc), GCtypeStr(gcType), isPinned ? "pinned" : "",
5684 printf("-%02XH", -offs);
5688 printf("+%02XH", +offs);
5695 /* The "global" live GC variable mask is no longer up-to-date */
5697 emitThisGCrefVset = false;
5700 /*****************************************************************************
5702 * Record a new set of live GC ref variables.
5705 void emitter::emitUpdateLiveGCvars(VARSET_VALARG_TP vars, BYTE* addr)
5707 assert(emitIssuing);
5709 // Don't track GC changes in epilogs
5710 if (emitIGisInEpilog(emitCurIG))
5715 /* Is the current set accurate and unchanged? */
5717 if (emitThisGCrefVset && VarSetOps::Equal(emitComp, emitThisGCrefVars, vars))
5723 if (EMIT_GC_VERBOSE)
5725 printf("New GC ref live vars=%s ", VarSetOps::ToString(emitComp, vars));
5726 dumpConvertedVarSet(emitComp, vars);
5731 VarSetOps::Assign(emitComp, emitThisGCrefVars, vars);
5733 /* Are there any GC ref variables on the stack? */
5735 if (emitGCrFrameOffsCnt)
5738 unsigned cnt = emitTrkVarCnt;
5741 /* Test all the tracked variable bits in the mask */
5743 for (num = 0, tab = emitGCrFrameOffsTab; num < cnt; num++, tab++)
5749 // byref_OFFSET_FLAG and this_OFFSET_FLAG are set
5750 // in the table-offsets for byrefs and this-ptr
5752 int offs = val & ~OFFSET_MASK;
5754 // printf("var #%2u at %3d is now %s\n", num, offs, (vars & 1) ? "live" : "dead");
5756 if (VarSetOps::IsMember(emitComp, vars, num))
5758 GCtype gcType = (val & byref_OFFSET_FLAG) ? GCT_BYREF : GCT_GCREF;
5759 emitGCvarLiveUpd(offs, INT_MAX, gcType, addr);
5763 emitGCvarDeadUpd(offs, addr);
5769 emitThisGCrefVset = true;
5772 /*****************************************************************************
5774 * Record a call location for GC purposes (we know that this is a method that
5775 * will not be fully interruptible).
5778 void emitter::emitRecordGCcall(BYTE* codePos, unsigned char callInstrSize)
5780 assert(emitIssuing);
5781 assert(!emitFullGCinfo);
5783 unsigned offs = emitCurCodeOffs(codePos);
5784 unsigned regs = (emitThisGCrefRegs | emitThisByrefRegs) & ~RBM_INTRET;
5787 #ifdef JIT32_GCENCODER
5788 // The JIT32 GCInfo encoder allows us to (as the comment previously here said):
5789 // "Bail if this is a totally boring call", but the GCInfoEncoder/Decoder interface
5790 // requires a definition for every call site, so we skip these "early outs" when we're
5791 // using the general encoder.
5794 #if EMIT_TRACK_STACK_DEPTH
5795 if (emitCurStackLvl == 0)
5798 /* Nope, only interesting calls get recorded */
5800 if (emitSimpleStkUsed)
5802 if (!u1.emitSimpleStkMask)
5807 if (u2.emitGcArgTrackCnt == 0)
5811 #endif // JIT32_GCENCODER
5815 if (EMIT_GC_VERBOSE)
5817 printf("; Call at %04X [stk=%u], GCvars=", offs - callInstrSize, emitCurStackLvl);
5819 printf(", gcrefRegs=");
5820 printRegMaskInt(emitThisGCrefRegs);
5821 emitDispRegSet(emitThisGCrefRegs);
5822 // printRegMaskInt(emitThisGCrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5823 // emitDispRegSet (emitThisGCrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5824 printf(", byrefRegs=");
5825 printRegMaskInt(emitThisByrefRegs);
5826 emitDispRegSet(emitThisByrefRegs);
5827 // printRegMaskInt(emitThisByrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5828 // emitDispRegSet (emitThisByrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5834 /* Allocate a 'call site' descriptor and start filling it in */
5836 call = new (emitComp, CMK_GC) callDsc;
5838 call->cdBlock = nullptr;
5839 call->cdOffs = offs;
5840 #ifndef JIT32_GCENCODER
5841 call->cdCallInstrSize = callInstrSize;
5843 call->cdNext = nullptr;
5845 call->cdGCrefRegs = (regMaskSmall)emitThisGCrefRegs;
5846 call->cdByrefRegs = (regMaskSmall)emitThisByrefRegs;
5848 #if EMIT_TRACK_STACK_DEPTH
5849 #ifndef FEATURE_UNIX_AMD64_STRUCT_PASSING
5850 noway_assert(FitsIn<USHORT>(emitCurStackLvl / ((unsigned)sizeof(unsigned))));
5851 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
5854 // Append the call descriptor to the list */
5855 if (codeGen->gcInfo.gcCallDescLast == nullptr)
5857 assert(codeGen->gcInfo.gcCallDescList == nullptr);
5858 codeGen->gcInfo.gcCallDescList = codeGen->gcInfo.gcCallDescLast = call;
5862 assert(codeGen->gcInfo.gcCallDescList != nullptr);
5863 codeGen->gcInfo.gcCallDescLast->cdNext = call;
5864 codeGen->gcInfo.gcCallDescLast = call;
5867 /* Record the current "pending" argument list */
5869 if (emitSimpleStkUsed)
5871 /* The biggest call is less than MAX_SIMPLE_STK_DEPTH. So use
5874 call->u1.cdArgMask = u1.emitSimpleStkMask;
5875 call->u1.cdByrefArgMask = u1.emitSimpleByrefStkMask;
5880 /* The current call has too many arguments, so we need to report the
5881 offsets of each individual GC arg. */
5883 call->cdArgCnt = u2.emitGcArgTrackCnt;
5884 if (call->cdArgCnt == 0)
5886 call->u1.cdArgMask = call->u1.cdByrefArgMask = 0;
5890 call->cdArgTable = new (emitComp, CMK_GC) unsigned[u2.emitGcArgTrackCnt];
5892 unsigned gcArgs = 0;
5893 unsigned stkLvl = emitCurStackLvl / sizeof(int);
5895 for (unsigned i = 0; i < stkLvl; i++)
5897 GCtype gcType = (GCtype)u2.emitArgTrackTab[stkLvl - i - 1];
5899 if (needsGC(gcType))
5901 call->cdArgTable[gcArgs] = i * sizeof(void*);
5903 if (gcType == GCT_BYREF)
5905 call->cdArgTable[gcArgs] |= byref_OFFSET_FLAG;
5912 assert(gcArgs == u2.emitGcArgTrackCnt);
5916 /*****************************************************************************
5918 * Record a new set of live GC ref registers.
5921 void emitter::emitUpdateLiveGCregs(GCtype gcType, regMaskTP regs, BYTE* addr)
5923 assert(emitIssuing);
5925 // Don't track GC changes in epilogs
5926 if (emitIGisInEpilog(emitCurIG))
5936 if (EMIT_GC_VERBOSE)
5938 printf("New %sReg live regs=", GCtypeStr(gcType));
5939 printRegMaskInt(regs);
5940 emitDispRegSet(regs);
5945 assert(needsGC(gcType));
5947 regMaskTP& emitThisXXrefRegs = (gcType == GCT_GCREF) ? emitThisGCrefRegs : emitThisByrefRegs;
5948 regMaskTP& emitThisYYrefRegs = (gcType == GCT_GCREF) ? emitThisByrefRegs : emitThisGCrefRegs;
5949 assert(emitThisXXrefRegs != regs);
5953 /* Figure out which GC registers are becoming live/dead at this point */
5955 dead = (emitThisXXrefRegs & ~regs);
5956 life = (~emitThisXXrefRegs & regs);
5958 /* Can't simultaneously become live and dead at the same time */
5960 assert((dead | life) != 0);
5961 assert((dead & life) == 0);
5963 /* Compute the 'changing state' mask */
5965 chg = (dead | life);
5969 regMaskTP bit = genFindLowestBit(chg);
5970 regNumber reg = genRegNumFromMask(bit);
5974 emitGCregLiveUpd(gcType, reg, addr);
5978 emitGCregDeadUpd(reg, addr);
5984 assert(emitThisXXrefRegs == regs);
5988 emitThisYYrefRegs &= ~regs; // Kill the regs from the other GC type (if live)
5989 emitThisXXrefRegs = regs; // Mark them as live in the requested GC type
5992 // The 2 GC reg masks can't be overlapping
5994 assert((emitThisGCrefRegs & emitThisByrefRegs) == 0);
5997 /*****************************************************************************
5999 * Record the fact that the given register now contains a live GC ref.
6002 void emitter::emitGCregLiveSet(GCtype gcType, regMaskTP regMask, BYTE* addr, bool isThis)
6004 assert(emitIssuing);
6005 assert(needsGC(gcType));
6007 regPtrDsc* regPtrNext;
6009 assert(!isThis || emitComp->lvaKeepAliveAndReportThis());
6010 // assert(emitFullyInt || isThis);
6011 assert(emitFullGCinfo);
6013 assert(((emitThisGCrefRegs | emitThisByrefRegs) & regMask) == 0);
6015 /* Allocate a new regptr entry and fill it in */
6017 regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6018 regPtrNext->rpdGCtype = gcType;
6020 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6021 regPtrNext->rpdArg = FALSE;
6022 regPtrNext->rpdCall = FALSE;
6023 regPtrNext->rpdIsThis = isThis;
6024 regPtrNext->rpdCompiler.rpdAdd = (regMaskSmall)regMask;
6025 regPtrNext->rpdCompiler.rpdDel = 0;
6028 /*****************************************************************************
6030 * Record the fact that the given register no longer contains a live GC ref.
6033 void emitter::emitGCregDeadSet(GCtype gcType, regMaskTP regMask, BYTE* addr)
6035 assert(emitIssuing);
6036 assert(needsGC(gcType));
6038 regPtrDsc* regPtrNext;
6040 // assert(emitFullyInt);
6041 assert(emitFullGCinfo);
6043 assert(((emitThisGCrefRegs | emitThisByrefRegs) & regMask) != 0);
6045 /* Allocate a new regptr entry and fill it in */
6047 regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6048 regPtrNext->rpdGCtype = gcType;
6050 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6051 regPtrNext->rpdCall = FALSE;
6052 regPtrNext->rpdIsThis = FALSE;
6053 regPtrNext->rpdArg = FALSE;
6054 regPtrNext->rpdCompiler.rpdAdd = 0;
6055 regPtrNext->rpdCompiler.rpdDel = (regMaskSmall)regMask;
6058 /*****************************************************************************
6060 * Emit an 8-bit integer as code.
6063 unsigned char emitter::emitOutputByte(BYTE* dst, ssize_t val)
6065 *castto(dst, unsigned char*) = (unsigned char)val;
6068 if (emitComp->opts.dspEmit)
6070 printf("; emit_byte 0%02XH\n", val & 0xFF);
6072 #ifdef _TARGET_AMD64_
6073 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6074 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6075 #endif // _TARGET_AMD64_
6078 return sizeof(unsigned char);
6081 /*****************************************************************************
6083 * Emit a 16-bit integer as code.
6086 unsigned char emitter::emitOutputWord(BYTE* dst, ssize_t val)
6088 MISALIGNED_WR_I2(dst, (short)val);
6091 if (emitComp->opts.dspEmit)
6093 printf("; emit_word 0%02XH,0%02XH\n", (val & 0xFF), (val >> 8) & 0xFF);
6095 #ifdef _TARGET_AMD64_
6096 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6097 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6098 #endif // _TARGET_AMD64_
6101 return sizeof(short);
6104 /*****************************************************************************
6106 * Emit a 32-bit integer as code.
6109 unsigned char emitter::emitOutputLong(BYTE* dst, ssize_t val)
6111 MISALIGNED_WR_I4(dst, (int)val);
6114 if (emitComp->opts.dspEmit)
6116 printf("; emit_long 0%08XH\n", (int)val);
6118 #ifdef _TARGET_AMD64_
6119 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6120 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6121 #endif // _TARGET_AMD64_
6127 /*****************************************************************************
6129 * Emit a pointer-sized integer as code.
6132 unsigned char emitter::emitOutputSizeT(BYTE* dst, ssize_t val)
6134 MISALIGNED_WR_ST(dst, val);
6137 if (emitComp->opts.dspEmit)
6139 #ifdef _TARGET_AMD64_
6140 printf("; emit_size_t 0%016llXH\n", val);
6141 #else // _TARGET_AMD64_
6142 printf("; emit_size_t 0%08XH\n", val);
6143 #endif // _TARGET_AMD64_
6147 return sizeof(size_t);
6150 //------------------------------------------------------------------------
6151 // Wrappers to emitOutputByte, emitOutputWord, emitOutputLong, emitOutputSizeT
6152 // that take unsigned __int64 or size_t type instead of ssize_t. Used on RyuJIT/x86.
6155 // dst - passed through
6156 // val - passed through
6159 // Same as wrapped function.
6162 #if !defined(LEGACY_BACKEND) && defined(_TARGET_X86_)
6163 unsigned char emitter::emitOutputByte(BYTE* dst, size_t val)
6165 return emitOutputByte(dst, (ssize_t)val);
6168 unsigned char emitter::emitOutputWord(BYTE* dst, size_t val)
6170 return emitOutputWord(dst, (ssize_t)val);
6173 unsigned char emitter::emitOutputLong(BYTE* dst, size_t val)
6175 return emitOutputLong(dst, (ssize_t)val);
6178 unsigned char emitter::emitOutputSizeT(BYTE* dst, size_t val)
6180 return emitOutputSizeT(dst, (ssize_t)val);
6183 unsigned char emitter::emitOutputByte(BYTE* dst, unsigned __int64 val)
6185 return emitOutputByte(dst, (ssize_t)val);
6188 unsigned char emitter::emitOutputWord(BYTE* dst, unsigned __int64 val)
6190 return emitOutputWord(dst, (ssize_t)val);
6193 unsigned char emitter::emitOutputLong(BYTE* dst, unsigned __int64 val)
6195 return emitOutputLong(dst, (ssize_t)val);
6198 unsigned char emitter::emitOutputSizeT(BYTE* dst, unsigned __int64 val)
6200 return emitOutputSizeT(dst, (ssize_t)val);
6202 #endif // !defined(LEGACY_BACKEND) && defined(_TARGET_X86_)
6204 /*****************************************************************************
6206 * Given a block cookie and a code position, return the actual code offset;
6207 * this can only be called at the end of code generation.
6210 UNATIVE_OFFSET emitter::emitCodeOffset(void* blockPtr, unsigned codePos)
6215 unsigned no = emitGetInsNumFromCodePos(codePos);
6217 /* Make sure we weren't passed some kind of a garbage thing */
6219 ig = (insGroup*)blockPtr;
6221 assert(ig && ig->igSelf == ig);
6224 /* The first and last offsets are always easy */
6230 else if (no == ig->igInsCnt)
6234 else if (ig->igFlags & IGF_UPD_ISZ)
6237 Some instruction sizes have changed, so we'll have to figure
6238 out the instruction offset "the hard way".
6241 of = emitFindOffset(ig, no);
6245 /* All instructions correctly predicted, the offset stays the same */
6247 of = emitGetInsOfsFromCodePos(codePos);
6249 // printf("[IG=%02u;ID=%03u;OF=%04X] <= %08X\n", ig->igNum, emitGetInsNumFromCodePos(codePos), of, codePos);
6251 /* Make sure the offset estimate is accurate */
6253 assert(of == emitFindOffset(ig, emitGetInsNumFromCodePos(codePos)));
6256 return ig->igOffs + of;
6259 /*****************************************************************************
6261 * Record the fact that the given register now contains a live GC ref.
6264 void emitter::emitGCregLiveUpd(GCtype gcType, regNumber reg, BYTE* addr)
6266 assert(emitIssuing);
6268 // Don't track GC changes in epilogs
6269 if (emitIGisInEpilog(emitCurIG))
6274 assert(needsGC(gcType));
6276 regMaskTP regMask = genRegMask(reg);
6278 regMaskTP& emitThisXXrefRegs = (gcType == GCT_GCREF) ? emitThisGCrefRegs : emitThisByrefRegs;
6279 regMaskTP& emitThisYYrefRegs = (gcType == GCT_GCREF) ? emitThisByrefRegs : emitThisGCrefRegs;
6281 if ((emitThisXXrefRegs & regMask) == 0)
6283 // If the register was holding the other GC type, that type should
6286 if (emitThisYYrefRegs & regMask)
6288 emitGCregDeadUpd(reg, addr);
6291 // For synchronized methods, "this" is always alive and in the same register.
6292 // However, if we generate any code after the epilog block (where "this"
6293 // goes dead), "this" will come alive again. We need to notice that.
6294 // Note that we only expect isThis to be true at an insGroup boundary.
6296 bool isThis = (reg == emitSyncThisObjReg) ? true : false;
6300 emitGCregLiveSet(gcType, regMask, addr, isThis);
6303 emitThisXXrefRegs |= regMask;
6306 if (EMIT_GC_VERBOSE)
6308 printf("%sReg +[%s]\n", GCtypeStr(gcType), emitRegName(reg));
6313 // The 2 GC reg masks can't be overlapping
6315 assert((emitThisGCrefRegs & emitThisByrefRegs) == 0);
6318 /*****************************************************************************
6320 * Record the fact that the given set of registers no longer contain live GC refs.
6323 void emitter::emitGCregDeadUpdMask(regMaskTP regs, BYTE* addr)
6325 assert(emitIssuing);
6327 // Don't track GC changes in epilogs
6328 if (emitIGisInEpilog(emitCurIG))
6333 // First, handle the gcref regs going dead
6335 regMaskTP gcrefRegs = emitThisGCrefRegs & regs;
6337 // "this" can never go dead in synchronized methods, except in the epilog
6338 // after the call to CORINFO_HELP_MON_EXIT.
6339 assert(emitSyncThisObjReg == REG_NA || (genRegMask(emitSyncThisObjReg) & regs) == 0);
6343 assert((emitThisByrefRegs & gcrefRegs) == 0);
6347 emitGCregDeadSet(GCT_GCREF, gcrefRegs, addr);
6350 emitThisGCrefRegs &= ~gcrefRegs;
6353 if (EMIT_GC_VERBOSE)
6356 printRegMaskInt(gcrefRegs);
6358 emitDispRegSet(gcrefRegs);
6364 // Second, handle the byref regs going dead
6366 regMaskTP byrefRegs = emitThisByrefRegs & regs;
6370 assert((emitThisGCrefRegs & byrefRegs) == 0);
6374 emitGCregDeadSet(GCT_BYREF, byrefRegs, addr);
6377 emitThisByrefRegs &= ~byrefRegs;
6380 if (EMIT_GC_VERBOSE)
6383 printRegMaskInt(byrefRegs);
6385 emitDispRegSet(byrefRegs);
6392 /*****************************************************************************
6394 * Record the fact that the given register no longer contains a live GC ref.
6397 void emitter::emitGCregDeadUpd(regNumber reg, BYTE* addr)
6399 assert(emitIssuing);
6401 // Don't track GC changes in epilogs
6402 if (emitIGisInEpilog(emitCurIG))
6407 regMaskTP regMask = genRegMask(reg);
6409 if ((emitThisGCrefRegs & regMask) != 0)
6411 assert((emitThisByrefRegs & regMask) == 0);
6415 emitGCregDeadSet(GCT_GCREF, regMask, addr);
6418 emitThisGCrefRegs &= ~regMask;
6421 if (EMIT_GC_VERBOSE)
6423 printf("%s -[%s]\n", "gcrReg", emitRegName(reg));
6427 else if ((emitThisByrefRegs & regMask) != 0)
6431 emitGCregDeadSet(GCT_BYREF, regMask, addr);
6434 emitThisByrefRegs &= ~regMask;
6437 if (EMIT_GC_VERBOSE)
6439 printf("%s -[%s]\n", "byrReg", emitRegName(reg));
6445 /*****************************************************************************
6447 * Record the fact that the given variable now contains a live GC ref.
6448 * varNum may be INT_MAX or negative (indicating a spill temp) only if
6449 * offs is guaranteed to be the offset of a tracked GC ref. Else we
6450 * need a valid value to check if the variable is tracked or not.
6453 void emitter::emitGCvarLiveUpd(int offs, int varNum, GCtype gcType, BYTE* addr)
6455 assert(abs(offs) % sizeof(int) == 0);
6456 assert(needsGC(gcType));
6458 #if FEATURE_FIXED_OUT_ARGS
6459 if ((unsigned)varNum == emitComp->lvaOutgoingArgSpaceVar)
6463 /* Append an "arg push" entry to track a GC written to the
6464 outgoing argument space.
6465 Allocate a new ptr arg entry and fill it in */
6467 regPtrDsc* regPtrNext = gcInfo->gcRegPtrAllocDsc();
6468 regPtrNext->rpdGCtype = gcType;
6469 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6470 regPtrNext->rpdArg = TRUE;
6471 regPtrNext->rpdCall = FALSE;
6472 noway_assert(FitsIn<unsigned short>(offs));
6473 regPtrNext->rpdPtrArg = (unsigned short)offs;
6474 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_PUSH;
6475 regPtrNext->rpdIsThis = FALSE;
6478 if (EMIT_GC_VERBOSE)
6480 printf("[%04X] %s arg write\n", offs, GCtypeStr(gcType));
6486 #endif // FEATURE_FIXED_OUT_ARGS
6488 /* Is the frame offset within the "interesting" range? */
6490 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
6492 /* Normally all variables in this range must be tracked stack
6493 pointers. However, for EnC, we relax this condition. So we
6494 must check if this is not such a variable.
6495 Note that varNum might be negative, indicating a spill temp.
6498 if (varNum != INT_MAX)
6500 bool isTracked = false;
6503 // This is NOT a spill temp
6504 LclVarDsc* varDsc = &emitComp->lvaTable[varNum];
6505 isTracked = emitComp->lvaIsGCTracked(varDsc);
6509 // Is it an untracked spill temp?
6510 isTracked = TRACK_GC_TEMP_LIFETIMES;
6515 assert(!emitContTrkPtrLcls ||
6516 // EBP based variables in the double-aligned frames are indeed input arguments.
6517 // and we don't require them to fall into the "interesting" range.
6518 ((emitComp->rpFrameType == FT_DOUBLE_ALIGN_FRAME) && (varNum >= 0) &&
6519 (emitComp->lvaTable[varNum].lvFramePointerBased == 1)));
6521 assert(!emitContTrkPtrLcls);
6529 /* Compute the index into the GC frame table */
6531 disp = (offs - emitGCrFrameOffsMin) / sizeof(void*);
6532 assert(disp < emitGCrFrameOffsCnt);
6534 /* If the variable is currently dead, mark it as live */
6536 if (emitGCrFrameLiveTab[disp] == nullptr)
6538 emitGCvarLiveSet(offs, gcType, addr, disp);
6544 /*****************************************************************************
6546 * Record the fact that the given variable no longer contains a live GC ref.
6549 void emitter::emitGCvarDeadUpd(int offs, BYTE* addr)
6551 assert(emitIssuing);
6552 assert(abs(offs) % sizeof(int) == 0);
6554 /* Is the frame offset within the "interesting" range? */
6556 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
6560 /* Compute the index into the GC frame table */
6562 disp = (offs - emitGCrFrameOffsMin) / sizeof(void*);
6563 assert(disp < emitGCrFrameOffsCnt);
6565 /* If the variable is currently live, mark it as dead */
6567 if (emitGCrFrameLiveTab[disp] != nullptr)
6569 emitGCvarDeadSet(offs, addr, disp);
6574 /*****************************************************************************
6576 * Allocate a new IG and link it in to the global list after the current IG
6579 insGroup* emitter::emitAllocAndLinkIG()
6581 insGroup* ig = emitAllocIG();
6585 emitInsertIGAfter(emitCurIG, ig);
6587 /* Propagate some IG flags from the current group to the new group */
6589 ig->igFlags |= (emitCurIG->igFlags & IGF_PROPAGATE_MASK);
6591 /* Set the new IG as the current IG */
6598 /*****************************************************************************
6600 * Allocate an instruction group descriptor and assign it the next index.
6603 insGroup* emitter::emitAllocIG()
6607 /* Allocate a group descriptor */
6609 size_t sz = sizeof(insGroup);
6610 ig = (insGroup*)emitGetMem(sz);
6617 emitTotalIGcnt += 1;
6618 emitTotalIGsize += sz;
6619 emitSizeMethod += sz;
6622 /* Do basic initialization */
6629 /*****************************************************************************
6631 * Initialize an instruction group
6634 void emitter::emitInitIG(insGroup* ig)
6636 /* Assign the next available index to the instruction group */
6638 ig->igNum = emitNxtIGnum;
6642 /* Record the (estimated) code offset of the group */
6644 ig->igOffs = emitCurCodeOffset;
6645 assert(IsCodeAligned(ig->igOffs));
6647 /* Set the current function index */
6649 ig->igFuncIdx = emitComp->compCurrFuncIdx;
6653 /* Zero out some fields to avoid printing garbage in JitDumps. These
6654 really only need to be set in DEBUG, but do it in all cases to make
6655 sure we act the same in non-DEBUG builds.
6659 ig->igGCregs = RBM_NONE;
6663 /*****************************************************************************
6665 * Insert instruction group 'ig' after 'igInsertAfterIG'
6668 void emitter::emitInsertIGAfter(insGroup* insertAfterIG, insGroup* ig)
6673 ig->igNext = insertAfterIG->igNext;
6674 insertAfterIG->igNext = ig;
6676 if (emitIGlast == insertAfterIG)
6678 // If we are inserting at the end, then update the 'last' pointer
6683 /*****************************************************************************
6685 * Save the current IG and start a new one.
6688 void emitter::emitNxtIG(bool emitAdd)
6690 /* Right now we don't allow multi-IG prologs */
6692 assert(emitCurIG != emitPrologIG);
6694 /* First save the current group */
6698 /* Update the GC live sets for the group's start
6699 * Do it only if not an emitter added block */
6703 VarSetOps::Assign(emitComp, emitInitGCrefVars, emitThisGCrefVars);
6704 emitInitGCrefRegs = emitThisGCrefRegs;
6705 emitInitByrefRegs = emitThisByrefRegs;
6708 /* Start generating the new group */
6712 /* If this is an emitter added block, flag it */
6716 emitCurIG->igFlags |= IGF_EMIT_ADD;
6719 // We've created a new IG; no need to force another one.
6720 emitForceNewIG = false;
6723 /*****************************************************************************
6725 * emitGetInsSC: Get the instruction's constant value.
6728 ssize_t emitter::emitGetInsSC(instrDesc* id)
6730 #ifdef _TARGET_ARM_ // should it be _TARGET_ARMARCH_? Why do we need this? Note that on ARM64 we store scaled immediates
6732 if (id->idIsLclVar())
6734 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
6737 int offs = id->idAddr()->iiaLclVar.lvaOffset();
6738 #if defined(_TARGET_ARM_)
6739 int adr = emitComp->lvaFrameAddress(varNum, id->idIsLclFPBase(), &baseReg, offs);
6740 int dsp = adr + offs;
6741 if ((id->idIns() == INS_sub) || (id->idIns() == INS_subw))
6743 #elif defined(_TARGET_ARM64_)
6744 // TODO-ARM64-Cleanup: this is currently unreachable. Do we need it?
6746 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
6747 int dsp = adr + offs;
6748 if (id->idIns() == INS_sub)
6754 #endif // _TARGET_ARM_
6755 if (id->idIsLargeCns())
6757 return ((instrDescCns*)id)->idcCnsVal;
6761 return id->idSmallCns();
6765 /*****************************************************************************/
6766 #if EMIT_TRACK_STACK_DEPTH
6767 /*****************************************************************************
6769 * Record a push of a single dword on the stack.
6772 void emitter::emitStackPush(BYTE* addr, GCtype gcType)
6775 assert(IsValidGCtype(gcType));
6778 if (emitSimpleStkUsed)
6780 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6781 assert(emitCurStackLvl / sizeof(int) < MAX_SIMPLE_STK_DEPTH);
6783 u1.emitSimpleStkMask <<= 1;
6784 u1.emitSimpleStkMask |= (unsigned)needsGC(gcType);
6786 u1.emitSimpleByrefStkMask <<= 1;
6787 u1.emitSimpleByrefStkMask |= (gcType == GCT_BYREF);
6789 assert((u1.emitSimpleStkMask & u1.emitSimpleByrefStkMask) == u1.emitSimpleByrefStkMask);
6793 emitStackPushLargeStk(addr, gcType);
6796 emitCurStackLvl += sizeof(int);
6799 /*****************************************************************************
6801 * Record a push of a bunch of non-GC dwords on the stack.
6804 void emitter::emitStackPushN(BYTE* addr, unsigned count)
6808 if (emitSimpleStkUsed)
6810 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6812 u1.emitSimpleStkMask <<= count;
6813 u1.emitSimpleByrefStkMask <<= count;
6817 emitStackPushLargeStk(addr, GCT_NONE, count);
6820 emitCurStackLvl += count * sizeof(int);
6823 /*****************************************************************************
6825 * Record a pop of the given number of dwords from the stack.
6828 void emitter::emitStackPop(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count)
6830 assert(emitCurStackLvl / sizeof(int) >= count);
6831 assert(!isCall || callInstrSize > 0);
6835 if (emitSimpleStkUsed)
6837 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6839 unsigned cnt = count;
6843 u1.emitSimpleStkMask >>= 1;
6844 u1.emitSimpleByrefStkMask >>= 1;
6849 emitStackPopLargeStk(addr, isCall, callInstrSize, count);
6852 emitCurStackLvl -= count * sizeof(int);
6858 // For the general encoder we do the call below always when it's a call, to ensure that the call is
6859 // recorded (when we're doing the ptr reg map for a non-fully-interruptible method).
6861 #ifndef JIT32_GCENCODER
6862 || (emitComp->genFullPtrRegMap && (!emitComp->genInterruptible) && isCall)
6863 #endif // JIT32_GCENCODER
6866 emitStackPopLargeStk(addr, isCall, callInstrSize, 0);
6871 /*****************************************************************************
6873 * Record a push of a single word on the stack for a full pointer map.
6876 void emitter::emitStackPushLargeStk(BYTE* addr, GCtype gcType, unsigned count)
6878 S_UINT32 level(emitCurStackLvl / sizeof(int));
6880 assert(IsValidGCtype(gcType));
6882 assert(!emitSimpleStkUsed);
6886 /* Push an entry for this argument on the tracking stack */
6888 // printf("Pushed [%d] at lvl %2u [max=%u]\n", isGCref, emitArgTrackTop - emitArgTrackTab, emitMaxStackDepth);
6890 assert(level.IsOverflow() || u2.emitArgTrackTop == u2.emitArgTrackTab + level.Value());
6891 *u2.emitArgTrackTop++ = (BYTE)gcType;
6892 assert(u2.emitArgTrackTop <= u2.emitArgTrackTab + emitMaxStackDepth);
6894 if (emitFullArgInfo || needsGC(gcType))
6898 /* Append an "arg push" entry if this is a GC ref or
6899 FPO method. Allocate a new ptr arg entry and fill it in */
6901 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6902 regPtrNext->rpdGCtype = gcType;
6904 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6905 regPtrNext->rpdArg = TRUE;
6906 regPtrNext->rpdCall = FALSE;
6907 if (level.IsOverflow() || !FitsIn<unsigned short>(level.Value()))
6909 IMPL_LIMITATION("Too many/too big arguments to encode GC information");
6911 regPtrNext->rpdPtrArg = (unsigned short)level.Value();
6912 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_PUSH;
6913 regPtrNext->rpdIsThis = FALSE;
6916 if (EMIT_GC_VERBOSE)
6918 printf("[%08X] %s arg push %u\n", dspPtr(regPtrNext), GCtypeStr(gcType), level.Value());
6923 /* This is an "interesting" argument push */
6925 u2.emitGcArgTrackCnt++;
6928 assert(!level.IsOverflow());
6932 /*****************************************************************************
6934 * Record a pop of the given number of words from the stack for a full ptr
6938 void emitter::emitStackPopLargeStk(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count)
6940 assert(emitIssuing);
6943 S_UINT16 argRecCnt(0); // arg count for ESP, ptr-arg count for EBP
6944 unsigned gcrefRegs, byrefRegs;
6946 #ifdef JIT32_GCENCODER
6947 // For the general encoder, we always need to record calls, so we make this call
6948 // even when emitSimpleStkUsed is true.
6949 assert(!emitSimpleStkUsed);
6952 /* Count how many pointer records correspond to this "pop" */
6954 for (argStkCnt = count; argStkCnt; argStkCnt--)
6956 assert(u2.emitArgTrackTop > u2.emitArgTrackTab);
6958 GCtype gcType = (GCtype)(*--u2.emitArgTrackTop);
6960 assert(IsValidGCtype(gcType));
6962 // printf("Popped [%d] at lvl %u\n", GCtypeStr(gcType), emitArgTrackTop - emitArgTrackTab);
6964 // This is an "interesting" argument
6966 if (emitFullArgInfo || needsGC(gcType))
6972 assert(u2.emitArgTrackTop >= u2.emitArgTrackTab);
6973 assert(u2.emitArgTrackTop == u2.emitArgTrackTab + emitCurStackLvl / sizeof(int) - count);
6974 noway_assert(!argRecCnt.IsOverflow());
6976 /* We're about to pop the corresponding arg records */
6978 u2.emitGcArgTrackCnt -= argRecCnt.Value();
6980 #ifdef JIT32_GCENCODER
6981 // For the general encoder, we always have to record calls, so we don't take this early return.
6982 if (!emitFullGCinfo)
6986 // Do we have any interesting (i.e., callee-saved) registers live here?
6988 gcrefRegs = byrefRegs = 0;
6990 // We make a bitmask whose bits correspond to callee-saved register indices (in the sequence
6991 // of callee-saved registers only).
6992 for (unsigned calleeSavedRegIdx = 0; calleeSavedRegIdx < CNT_CALLEE_SAVED; calleeSavedRegIdx++)
6994 regMaskTP calleeSavedRbm = raRbmCalleeSaveOrder[calleeSavedRegIdx];
6995 if (emitThisGCrefRegs & calleeSavedRbm)
6997 gcrefRegs |= (1 << calleeSavedRegIdx);
6999 if (emitThisByrefRegs & calleeSavedRbm)
7001 byrefRegs |= (1 << calleeSavedRegIdx);
7005 #ifdef JIT32_GCENCODER
7006 // For the general encoder, we always have to record calls, so we don't take this early return. /* Are there any
7007 // args to pop at this call site?
7009 if (argRecCnt.Value() == 0)
7012 Or do we have a partially interruptible EBP-less frame, and any
7013 of EDI,ESI,EBX,EBP are live, or is there an outer/pending call?
7015 CLANG_FORMAT_COMMENT_ANCHOR;
7017 #if !FPO_INTERRUPTIBLE
7018 if (emitFullyInt || (gcrefRegs == 0 && byrefRegs == 0 && u2.emitGcArgTrackCnt == 0))
7022 #endif // JIT32_GCENCODER
7024 /* Only calls may pop more than one value */
7026 // _cdecl calls accomplish this popping via a post-call-instruction SP adjustment.
7027 // The "rpdCall" field below should be interpreted as "the instruction accomplishes
7028 // call-related popping, even if it's not itself a call". Therefore, we don't just
7029 // use the "isCall" input argument, which means that the instruction actually is a call --
7030 // we use the OR of "isCall" or the "pops more than one value."
7032 bool isCallRelatedPop = (argRecCnt.Value() > 1);
7034 /* Allocate a new ptr arg entry and fill it in */
7036 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
7037 regPtrNext->rpdGCtype = GCT_GCREF; // Pops need a non-0 value (??)
7039 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
7040 regPtrNext->rpdCall = (isCall || isCallRelatedPop);
7041 #ifndef JIT32_GCENCODER
7042 if (regPtrNext->rpdCall)
7044 assert(isCall || callInstrSize == 0);
7045 regPtrNext->rpdCallInstrSize = callInstrSize;
7048 regPtrNext->rpdCallGCrefRegs = gcrefRegs;
7049 regPtrNext->rpdCallByrefRegs = byrefRegs;
7050 regPtrNext->rpdArg = TRUE;
7051 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_POP;
7052 regPtrNext->rpdPtrArg = argRecCnt.Value();
7055 if (EMIT_GC_VERBOSE)
7057 printf("[%08X] ptr arg pop %u\n", dspPtr(regPtrNext), count);
7062 /*****************************************************************************
7063 * For caller-pop arguments, we report the arguments as pending arguments.
7064 * However, any GC arguments are now dead, so we need to report them
7068 void emitter::emitStackKillArgs(BYTE* addr, unsigned count, unsigned char callInstrSize)
7072 if (emitSimpleStkUsed)
7074 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCInfo
7076 /* We don't need to report this to the GC info, but we do need
7077 to kill mark the ptrs on the stack as non-GC */
7079 assert(emitCurStackLvl / sizeof(int) >= count);
7081 for (unsigned lvl = 0; lvl < count; lvl++)
7083 u1.emitSimpleStkMask &= ~(1 << lvl);
7084 u1.emitSimpleByrefStkMask &= ~(1 << lvl);
7089 BYTE* argTrackTop = u2.emitArgTrackTop;
7092 for (unsigned i = 0; i < count; i++)
7094 assert(argTrackTop > u2.emitArgTrackTab);
7098 GCtype gcType = (GCtype)(*argTrackTop);
7099 assert(IsValidGCtype(gcType));
7101 if (needsGC(gcType))
7103 // printf("Killed %s at lvl %u\n", GCtypeStr(gcType), argTrackTop - emitArgTrackTab);
7105 *argTrackTop = GCT_NONE;
7110 noway_assert(!gcCnt.IsOverflow());
7112 /* We're about to kill the corresponding (pointer) arg records */
7114 if (!emitFullArgInfo)
7116 u2.emitGcArgTrackCnt -= gcCnt.Value();
7119 if (!emitFullGCinfo)
7124 /* Right after the call, the arguments are still sitting on the
7125 stack, but they are effectively dead. For fully-interruptible
7126 methods, we need to report that */
7128 if (emitFullGCinfo && gcCnt.Value())
7130 /* Allocate a new ptr arg entry and fill it in */
7132 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
7133 regPtrNext->rpdGCtype = GCT_GCREF; // Kills need a non-0 value (??)
7135 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
7137 regPtrNext->rpdArg = TRUE;
7138 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_KILL;
7139 regPtrNext->rpdPtrArg = gcCnt.Value();
7142 if (EMIT_GC_VERBOSE)
7144 printf("[%08X] ptr arg kill %u\n", dspPtr(regPtrNext), count);
7149 /* Now that ptr args have been marked as non-ptrs, we need to record
7150 the call itself as one that has no arguments. */
7152 emitStackPopLargeStk(addr, true, callInstrSize, 0);
7156 /*****************************************************************************
7157 * A helper for recording a relocation with the EE.
7159 void emitter::emitRecordRelocation(void* location, /* IN */
7160 void* target, /* IN */
7161 WORD fRelocType, /* IN */
7162 WORD slotNum /* = 0 */, /* IN */
7163 INT32 addlDelta /* = 0 */) /* IN */
7165 // If we're an unmatched altjit, don't tell the VM anything. We still record the relocation for
7166 // late disassembly; maybe we'll need it?
7167 if (emitComp->info.compMatchedVM)
7169 emitCmpHandle->recordRelocation(location, target, fRelocType, slotNum, addlDelta);
7171 #if defined(LATE_DISASM)
7172 codeGen->getDisAssembler().disRecordRelocation((size_t)location, (size_t)target);
7173 #endif // defined(LATE_DISASM)
7177 /*****************************************************************************
7178 * A helper for handling a Thumb-Mov32 of position-independent (PC-relative) value
7180 * This routine either records relocation for the location with the EE,
7181 * or creates a virtual relocation entry to perform offset fixup during
7182 * compilation without recording it with EE - depending on which of
7183 * absolute/relocative relocations mode are used for code section.
7185 void emitter::emitHandlePCRelativeMov32(void* location, /* IN */
7186 void* target) /* IN */
7188 if (emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_RELATIVE_CODE_RELOCS))
7190 emitRecordRelocation(location, target, IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL);
7194 emitRecordRelocation(location, target, IMAGE_REL_BASED_THUMB_MOV32);
7197 #endif // _TARGET_ARM_
7199 /*****************************************************************************
7200 * A helper for recording a call site with the EE.
7202 void emitter::emitRecordCallSite(ULONG instrOffset, /* IN */
7203 CORINFO_SIG_INFO* callSig, /* IN */
7204 CORINFO_METHOD_HANDLE methodHandle) /* IN */
7207 // Since CORINFO_SIG_INFO is a heavyweight structure, in most cases we can
7208 // lazily obtain it here using the given method handle (we only save the sig
7209 // info when we explicitly need it, i.e. for CALLI calls, vararg calls, and
7211 if (callSig == nullptr)
7213 assert(methodHandle != nullptr);
7215 if (Compiler::eeGetHelperNum(methodHandle) == CORINFO_HELP_UNDEF)
7217 if (emitScratchSigInfo == nullptr)
7219 emitScratchSigInfo = new (emitComp, CMK_CorSig) CORINFO_SIG_INFO;
7222 emitComp->eeGetMethodSig(methodHandle, emitScratchSigInfo);
7223 callSig = emitScratchSigInfo;
7227 emitCmpHandle->recordCallSite(instrOffset, callSig, methodHandle);
7228 #endif // defined(DEBUG)
7231 /*****************************************************************************/
7232 #endif // EMIT_TRACK_STACK_DEPTH
7233 /*****************************************************************************/
7234 /*****************************************************************************/
7238 /*****************************************************************************
7239 * Given a code offset, return a string representing a label for that offset.
7240 * If the code offset is just after the end of the code of the function, the
7241 * label will be "END". If the code offset doesn't correspond to any known
7242 * offset, the label will be "UNKNOWN". The strings are returned from static
7243 * buffers. This function rotates amongst four such static buffers (there are
7244 * cases where this function is called four times to provide data for a single
7248 const char* emitter::emitOffsetToLabel(unsigned offs)
7250 const size_t TEMP_BUFFER_LEN = 40;
7251 static unsigned curBuf = 0;
7252 static char buf[4][TEMP_BUFFER_LEN];
7256 UNATIVE_OFFSET nextof = 0;
7258 for (ig = emitIGlist; ig != nullptr; ig = ig->igNext)
7260 assert(nextof == ig->igOffs);
7262 if (ig->igOffs == offs)
7265 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "G_M%03u_IG%02u", Compiler::s_compMethodsCount, ig->igNum);
7266 retbuf = buf[curBuf];
7267 curBuf = (curBuf + 1) % 4;
7270 else if (ig->igOffs > offs)
7272 // We went past the requested offset but didn't find it.
7273 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "UNKNOWN");
7274 retbuf = buf[curBuf];
7275 curBuf = (curBuf + 1) % 4;
7279 nextof = ig->igOffs + ig->igSize;
7284 // It's a pseudo-label to the end.
7285 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "END");
7286 retbuf = buf[curBuf];
7287 curBuf = (curBuf + 1) % 4;
7292 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "UNKNOWN");
7293 retbuf = buf[curBuf];
7294 curBuf = (curBuf + 1) % 4;