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*)));
1340 #if defined(DEBUG) || defined(LATE_DISASM)
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 info->idClsCookie = nullptr;
1350 #ifdef TRANSLATE_PDB
1351 info->idilStart = emitInstrDescILBase;
1353 info->idFinallyCall = false;
1354 info->idCatchRet = false;
1355 info->idCallSig = nullptr;
1357 id->idDebugOnlyInfo(info);
1359 #endif // defined(DEBUG) || defined(LATE_DISASM)
1361 /* Store the size and handle the two special values
1362 that indicate GCref and ByRef */
1364 if (EA_IS_GCREF(opsz))
1366 /* A special value indicates a GCref pointer value */
1368 id->idGCref(GCT_GCREF);
1369 id->idOpSize(EA_PTRSIZE);
1371 else if (EA_IS_BYREF(opsz))
1373 /* A special value indicates a Byref pointer value */
1375 id->idGCref(GCT_BYREF);
1376 id->idOpSize(EA_PTRSIZE);
1380 id->idGCref(GCT_NONE);
1381 id->idOpSize(EA_SIZE(opsz));
1384 // Amd64: ip-relative addressing is supported even when not generating relocatable ngen code
1385 if (EA_IS_DSP_RELOC(opsz)
1386 #ifndef _TARGET_AMD64_
1387 && emitComp->opts.compReloc
1388 #endif //_TARGET_AMD64_
1391 /* Mark idInfo()->idDspReloc to remember that the */
1392 /* address mode has a displacement that is relocatable */
1393 id->idSetIsDspReloc();
1396 if (EA_IS_CNS_RELOC(opsz) && emitComp->opts.compReloc)
1398 /* Mark idInfo()->idCnsReloc to remember that the */
1399 /* instruction has an immediate constant that is relocatable */
1400 id->idSetIsCnsReloc();
1407 /* Update the instruction count */
1416 /*****************************************************************************
1418 * Make sure the code offsets of all instruction groups look reasonable.
1420 void emitter::emitCheckIGoffsets()
1425 for (tempIG = emitIGlist, offsIG = 0; tempIG; tempIG = tempIG->igNext)
1427 if (tempIG->igOffs != offsIG)
1429 printf("Block #%u has offset %08X, expected %08X\n", tempIG->igNum, tempIG->igOffs, offsIG);
1430 assert(!"bad block offset");
1433 offsIG += tempIG->igSize;
1436 if (emitTotalCodeSize && emitTotalCodeSize != offsIG)
1438 printf("Total code size is %08X, expected %08X\n", emitTotalCodeSize, offsIG);
1440 assert(!"bad total code size");
1446 /*****************************************************************************
1448 * Begin generating a method prolog.
1451 void emitter::emitBegProlog()
1453 assert(emitComp->compGeneratingProlog);
1455 #if EMIT_TRACK_STACK_DEPTH
1457 /* Don't measure stack depth inside the prolog, it's misleading */
1459 emitCntStackDepth = 0;
1461 assert(emitCurStackLvl == 0);
1466 emitForceNewIG = false;
1468 /* Switch to the pre-allocated prolog IG */
1470 emitGenIG(emitPrologIG);
1472 /* Nothing is live on entry to the prolog */
1474 // These were initialized to Empty at the start of compilation.
1475 VarSetOps::OldStyleClearD(emitComp, emitInitGCrefVars);
1476 VarSetOps::OldStyleClearD(emitComp, emitPrevGCrefVars);
1477 emitInitGCrefRegs = RBM_NONE;
1478 emitPrevGCrefRegs = RBM_NONE;
1479 emitInitByrefRegs = RBM_NONE;
1480 emitPrevByrefRegs = RBM_NONE;
1483 /*****************************************************************************
1485 * Return the code offset of the current location in the prolog.
1488 unsigned emitter::emitGetPrologOffsetEstimate()
1490 /* For now only allow a single prolog ins group */
1492 assert(emitPrologIG);
1493 assert(emitPrologIG == emitCurIG);
1495 return emitCurIGsize;
1498 /*****************************************************************************
1500 * Mark the code offset of the current location as the end of the prolog,
1501 * so it can be used later to compute the actual size of the prolog.
1504 void emitter::emitMarkPrologEnd()
1506 assert(emitComp->compGeneratingProlog);
1508 /* For now only allow a single prolog ins group */
1510 assert(emitPrologIG);
1511 assert(emitPrologIG == emitCurIG);
1513 emitPrologEndPos = emitCurOffset();
1516 /*****************************************************************************
1518 * Finish generating a method prolog.
1521 void emitter::emitEndProlog()
1523 assert(emitComp->compGeneratingProlog);
1531 /* Save the prolog IG if non-empty or if only one block */
1533 if (emitCurIGnonEmpty() || emitCurIG == emitPrologIG)
1538 #if EMIT_TRACK_STACK_DEPTH
1539 /* Reset the stack depth values */
1541 emitCurStackLvl = 0;
1542 emitCntStackDepth = sizeof(int);
1546 /*****************************************************************************
1548 * Create a placeholder instruction group to be used by a prolog or epilog,
1549 * either for the main function, or a funclet.
1552 void emitter::emitCreatePlaceholderIG(insGroupPlaceholderType igType,
1554 VARSET_VALARG_TP GCvars,
1555 regMaskTP gcrefRegs,
1556 regMaskTP byrefRegs,
1559 assert(igBB != nullptr);
1561 bool emitAdd = false;
1563 if (igType == IGPT_EPILOG
1564 #if FEATURE_EH_FUNCLETS
1565 || igType == IGPT_FUNCLET_EPILOG
1566 #endif // FEATURE_EH_FUNCLETS
1569 #ifdef _TARGET_AMD64_
1570 emitOutputPreEpilogNOP();
1571 #endif // _TARGET_AMD64_
1576 if (emitCurIGnonEmpty())
1581 /* Update GC tracking for the beginning of the placeholder IG */
1585 VarSetOps::Assign(emitComp, emitThisGCrefVars, GCvars);
1586 VarSetOps::Assign(emitComp, emitInitGCrefVars, GCvars);
1587 emitThisGCrefRegs = emitInitGCrefRegs = gcrefRegs;
1588 emitThisByrefRegs = emitInitByrefRegs = byrefRegs;
1591 /* Convert the group to a placeholder group */
1593 insGroup* igPh = emitCurIG;
1595 igPh->igFlags |= IGF_PLACEHOLDER;
1597 /* Note that we might be re-using a previously created but empty IG. In this
1598 * case, we need to make sure any re-used fields, such as igFuncIdx, are correct.
1601 igPh->igFuncIdx = emitComp->compCurrFuncIdx;
1603 /* Create a separate block of memory to store placeholder information.
1604 * We could use unions to put some of this into the insGroup itself, but we don't
1605 * want to grow the insGroup, and it's difficult to make sure the
1606 * insGroup fields are getting set and used elsewhere.
1609 igPh->igPhData = new (emitComp, CMK_InstDesc) insPlaceholderGroupData;
1611 igPh->igPhData->igPhNext = nullptr;
1612 igPh->igPhData->igPhType = igType;
1613 igPh->igPhData->igPhBB = igBB;
1615 VarSetOps::AssignNoCopy(emitComp, igPh->igPhData->igPhPrevGCrefVars, VarSetOps::UninitVal());
1616 VarSetOps::Assign(emitComp, igPh->igPhData->igPhPrevGCrefVars, emitPrevGCrefVars);
1617 igPh->igPhData->igPhPrevGCrefRegs = emitPrevGCrefRegs;
1618 igPh->igPhData->igPhPrevByrefRegs = emitPrevByrefRegs;
1620 VarSetOps::AssignNoCopy(emitComp, igPh->igPhData->igPhInitGCrefVars, VarSetOps::UninitVal());
1621 VarSetOps::Assign(emitComp, igPh->igPhData->igPhInitGCrefVars, emitInitGCrefVars);
1622 igPh->igPhData->igPhInitGCrefRegs = emitInitGCrefRegs;
1623 igPh->igPhData->igPhInitByrefRegs = emitInitByrefRegs;
1626 emitTotalPhIGcnt += 1;
1629 // Mark function prologs and epilogs properly in the igFlags bits. These bits
1630 // will get used and propagated when the placeholder is converted to a non-placeholder
1631 // during prolog/epilog generation.
1633 if (igType == IGPT_EPILOG)
1635 igPh->igFlags |= IGF_EPILOG;
1637 #if FEATURE_EH_FUNCLETS
1638 else if (igType == IGPT_FUNCLET_PROLOG)
1640 igPh->igFlags |= IGF_FUNCLET_PROLOG;
1642 else if (igType == IGPT_FUNCLET_EPILOG)
1644 igPh->igFlags |= IGF_FUNCLET_EPILOG;
1646 #endif // FEATURE_EH_FUNCLETS
1648 /* Link it into the placeholder list */
1650 if (emitPlaceholderList)
1652 emitPlaceholderLast->igPhData->igPhNext = igPh;
1656 emitPlaceholderList = igPh;
1659 emitPlaceholderLast = igPh;
1661 // Give an estimated size of this placeholder IG and
1662 // increment emitCurCodeOffset since we are not calling emitNewIG()
1664 emitCurIGsize += MAX_PLACEHOLDER_IG_SIZE;
1665 emitCurCodeOffset += emitCurIGsize;
1667 #if FEATURE_EH_FUNCLETS
1668 // Add the appropriate IP mapping debugging record for this placeholder
1669 // group. genExitCode() adds the mapping for main function epilogs.
1670 if (emitComp->opts.compDbgInfo)
1672 if (igType == IGPT_FUNCLET_PROLOG)
1674 codeGen->genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::PROLOG, true);
1676 else if (igType == IGPT_FUNCLET_EPILOG)
1678 codeGen->genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::EPILOG, true);
1681 #endif // FEATURE_EH_FUNCLETS
1683 /* Start a new IG if more code follows */
1687 emitCurIG = nullptr;
1691 if (igType == IGPT_EPILOG
1692 #if FEATURE_EH_FUNCLETS
1693 || igType == IGPT_FUNCLET_EPILOG
1694 #endif // FEATURE_EH_FUNCLETS
1697 // If this was an epilog, then assume this is the end of any currently in progress
1698 // no-GC region. If a block after the epilog needs to be no-GC, it needs to call
1699 // emitter::emitDisableGC() directly. This behavior is depended upon by the fast
1700 // tailcall implementation, which disables GC at the beginning of argument setup,
1701 // but assumes that after the epilog it will be re-enabled.
1707 // We don't know what the GC ref state will be at the end of the placeholder
1708 // group. So, force the next IG to store all the GC ref state variables;
1709 // don't omit them because emitPrev* is the same as emitInit*, because emitPrev*
1710 // will be inaccurate. (Note that, currently, GCrefRegs and ByrefRegs are always
1713 // There is no need to re-initialize the emitPrev* variables, as they won't be used
1714 // with emitForceStoreGCState==true, and will be re-initialized just before
1715 // emitForceStoreGCState is set to false;
1717 emitForceStoreGCState = true;
1719 /* The group after the placeholder group doesn't get the "propagate" flags */
1721 emitCurIG->igFlags &= ~IGF_PROPAGATE_MASK;
1725 if (emitComp->verbose)
1727 printf("*************** After placeholder IG creation\n");
1728 emitDispIGlist(false);
1733 /*****************************************************************************
1735 * Generate all prologs and epilogs
1738 void emitter::emitGeneratePrologEpilog()
1741 unsigned prologCnt = 0;
1742 unsigned epilogCnt = 0;
1743 #if FEATURE_EH_FUNCLETS
1744 unsigned funcletPrologCnt = 0;
1745 unsigned funcletEpilogCnt = 0;
1746 #endif // FEATURE_EH_FUNCLETS
1752 // Generating the prolog/epilog is going to destroy the placeholder group,
1753 // so save the "next" pointer before that happens.
1755 for (igPh = emitPlaceholderList; igPh != nullptr; igPh = igPhNext)
1757 assert(igPh->igFlags & IGF_PLACEHOLDER);
1759 igPhNext = igPh->igPhData->igPhNext;
1761 BasicBlock* igPhBB = igPh->igPhData->igPhBB;
1763 switch (igPh->igPhData->igPhType)
1765 case IGPT_PROLOG: // currently unused
1766 INDEBUG(++prologCnt);
1770 INDEBUG(++epilogCnt);
1771 emitBegFnEpilog(igPh);
1772 codeGen->genFnEpilog(igPhBB);
1776 #if FEATURE_EH_FUNCLETS
1778 case IGPT_FUNCLET_PROLOG:
1779 INDEBUG(++funcletPrologCnt);
1780 emitBegFuncletProlog(igPh);
1781 codeGen->genFuncletProlog(igPhBB);
1782 emitEndFuncletProlog();
1785 case IGPT_FUNCLET_EPILOG:
1786 INDEBUG(++funcletEpilogCnt);
1787 emitBegFuncletEpilog(igPh);
1788 codeGen->genFuncletEpilog();
1789 emitEndFuncletEpilog();
1792 #endif // FEATURE_EH_FUNCLETS
1800 if (emitComp->verbose)
1802 printf("%d prologs, %d epilogs", prologCnt, epilogCnt);
1803 #if FEATURE_EH_FUNCLETS
1804 printf(", %d funclet prologs, %d funclet epilogs", funcletPrologCnt, funcletEpilogCnt);
1805 #endif // FEATURE_EH_FUNCLETS
1808 // prolog/epilog code doesn't use this yet
1809 // noway_assert(prologCnt == 1);
1810 // noway_assert(epilogCnt == emitEpilogCnt); // Is this correct?
1811 #if FEATURE_EH_FUNCLETS
1812 assert(funcletPrologCnt == emitComp->ehFuncletCount());
1813 #endif // FEATURE_EH_FUNCLETS
1818 /*****************************************************************************
1820 * Begin all prolog and epilog generation
1823 void emitter::emitStartPrologEpilogGeneration()
1825 /* Save the current IG if it's non-empty */
1827 if (emitCurIGnonEmpty())
1833 assert(emitCurIG == nullptr);
1837 /*****************************************************************************
1839 * Finish all prolog and epilog generation
1842 void emitter::emitFinishPrologEpilogGeneration()
1844 /* Update the offsets of all the blocks */
1846 emitRecomputeIGoffsets();
1848 /* We should not generate any more code after this */
1850 emitCurIG = nullptr;
1853 /*****************************************************************************
1855 * Common code for prolog / epilog beginning. Convert the placeholder group to actual code IG,
1856 * and set it as the current group.
1859 void emitter::emitBegPrologEpilog(insGroup* igPh)
1861 assert(igPh->igFlags & IGF_PLACEHOLDER);
1863 /* Save the current IG if it's non-empty */
1865 if (emitCurIGnonEmpty())
1870 /* Convert the placeholder group to a normal group.
1871 * We need to be very careful to re-initialize the IG properly.
1872 * It turns out, this means we only need to clear the placeholder bit
1873 * and clear the igPhData field, and emitGenIG() will do the rest,
1874 * since in the placeholder IG we didn't touch anything that is set by emitAllocIG().
1877 igPh->igFlags &= ~IGF_PLACEHOLDER;
1879 emitForceNewIG = false;
1881 /* Set up the GC info that we stored in the placeholder */
1883 VarSetOps::Assign(emitComp, emitPrevGCrefVars, igPh->igPhData->igPhPrevGCrefVars);
1884 emitPrevGCrefRegs = igPh->igPhData->igPhPrevGCrefRegs;
1885 emitPrevByrefRegs = igPh->igPhData->igPhPrevByrefRegs;
1887 VarSetOps::Assign(emitComp, emitThisGCrefVars, igPh->igPhData->igPhInitGCrefVars);
1888 VarSetOps::Assign(emitComp, emitInitGCrefVars, igPh->igPhData->igPhInitGCrefVars);
1889 emitThisGCrefRegs = emitInitGCrefRegs = igPh->igPhData->igPhInitGCrefRegs;
1890 emitThisByrefRegs = emitInitByrefRegs = igPh->igPhData->igPhInitByrefRegs;
1892 igPh->igPhData = nullptr;
1894 /* Create a non-placeholder group pointer that we'll now use */
1896 insGroup* ig = igPh;
1898 /* Set the current function using the function index we stored */
1900 emitComp->funSetCurrentFunc(ig->igFuncIdx);
1902 /* Set the new IG as the place to generate code */
1906 #if EMIT_TRACK_STACK_DEPTH
1908 /* Don't measure stack depth inside the prolog / epilog, it's misleading */
1910 emitCntStackDepth = 0;
1912 assert(emitCurStackLvl == 0);
1917 /*****************************************************************************
1919 * Common code for end of prolog / epilog
1922 void emitter::emitEndPrologEpilog()
1926 /* Save the IG if non-empty */
1928 if (emitCurIGnonEmpty())
1933 assert(emitCurIGsize <= MAX_PLACEHOLDER_IG_SIZE);
1935 #if EMIT_TRACK_STACK_DEPTH
1936 /* Reset the stack depth values */
1938 emitCurStackLvl = 0;
1939 emitCntStackDepth = sizeof(int);
1943 /*****************************************************************************
1945 * Begin generating a main function epilog.
1948 void emitter::emitBegFnEpilog(insGroup* igPh)
1952 emitBegPrologEpilog(igPh);
1954 #ifdef JIT32_GCENCODER
1956 EpilogList* el = new (emitComp, CMK_GC) EpilogList();
1958 if (emitEpilogLast != nullptr)
1960 emitEpilogLast->elNext = el;
1964 emitEpilogList = el;
1967 emitEpilogLast = el;
1969 #endif // JIT32_GCENCODER
1972 /*****************************************************************************
1974 * Finish generating a funclet epilog.
1977 void emitter::emitEndFnEpilog()
1979 emitEndPrologEpilog();
1981 #ifdef JIT32_GCENCODER
1982 assert(emitEpilogLast != nullptr);
1984 UNATIVE_OFFSET epilogBegCodeOffset = emitEpilogLast->elLoc.CodeOffset(this);
1985 UNATIVE_OFFSET epilogExitSeqStartCodeOffset = emitExitSeqBegLoc.CodeOffset(this);
1986 UNATIVE_OFFSET newSize = epilogExitSeqStartCodeOffset - epilogBegCodeOffset;
1988 /* Compute total epilog size */
1989 assert(emitEpilogSize == 0 || emitEpilogSize == newSize); // All epilogs must be identical
1990 emitEpilogSize = newSize;
1992 UNATIVE_OFFSET epilogEndCodeOffset = emitCodeOffset(emitCurIG, emitCurOffset());
1993 assert(epilogExitSeqStartCodeOffset != epilogEndCodeOffset);
1995 newSize = epilogEndCodeOffset - epilogExitSeqStartCodeOffset;
1996 if (newSize < emitExitSeqSize)
1998 // We expect either the epilog to be the same every time, or that
1999 // one will be a ret or a ret <n> and others will be a jmp addr or jmp [addr];
2000 // we make the epilogs the minimum of these. Note that this ONLY works
2001 // because the only instruction is the last one and thus a slight
2002 // underestimation of the epilog size is harmless (since the EIP
2003 // can not be between instructions).
2004 assert(emitEpilogCnt == 1 ||
2005 (emitExitSeqSize - newSize) <= 5 // delta between size of various forms of jmp (size is either 6 or 5)
2006 // and various forms of ret (size is either 1 or 3). The combination can
2007 // be anything been 1 and 5.
2009 emitExitSeqSize = newSize;
2011 #endif // JIT32_GCENCODER
2014 #if FEATURE_EH_FUNCLETS
2016 /*****************************************************************************
2018 * Begin generating a funclet prolog.
2021 void emitter::emitBegFuncletProlog(insGroup* igPh)
2023 emitBegPrologEpilog(igPh);
2026 /*****************************************************************************
2028 * Finish generating a funclet prolog.
2031 void emitter::emitEndFuncletProlog()
2033 emitEndPrologEpilog();
2036 /*****************************************************************************
2038 * Begin generating a funclet epilog.
2041 void emitter::emitBegFuncletEpilog(insGroup* igPh)
2043 emitBegPrologEpilog(igPh);
2046 /*****************************************************************************
2048 * Finish generating a funclet epilog.
2051 void emitter::emitEndFuncletEpilog()
2053 emitEndPrologEpilog();
2056 #endif // FEATURE_EH_FUNCLETS
2058 #ifdef JIT32_GCENCODER
2061 // emitter::emitStartEpilog:
2062 // Mark the current position so that we can later compute the total epilog size.
2064 void emitter::emitStartEpilog()
2066 assert(emitEpilogLast != nullptr);
2067 emitEpilogLast->elLoc.CaptureLocation(this);
2070 /*****************************************************************************
2072 * Return non-zero if the current method only has one epilog, which is
2073 * at the very end of the method body.
2076 bool emitter::emitHasEpilogEnd()
2078 if (emitEpilogCnt == 1 && (emitIGlast->igFlags & IGF_EPILOG)) // This wouldn't work for funclets
2084 #endif // JIT32_GCENCODER
2086 #ifdef _TARGET_XARCH_
2088 /*****************************************************************************
2090 * Mark the beginning of the epilog exit sequence by remembering our position.
2093 void emitter::emitStartExitSeq()
2095 assert(emitComp->compGeneratingEpilog);
2097 emitExitSeqBegLoc.CaptureLocation(this);
2100 #endif // _TARGET_XARCH_
2102 /*****************************************************************************
2104 * The code generator tells us the range of GC ref locals through this
2105 * method. Needless to say, locals and temps should be allocated so that
2106 * the size of the range is as small as possible.
2108 * offsLo - The FP offset from which the GC pointer range starts.
2109 * offsHi - The FP offset at which the GC pointer region ends (exclusive).
2112 void emitter::emitSetFrameRangeGCRs(int offsLo, int offsHi)
2114 assert(emitComp->compGeneratingProlog);
2115 assert(offsHi > offsLo);
2119 // A total of 47254 methods compiled.
2121 // GC ref frame variable counts:
2123 // <= 0 ===> 43175 count ( 91% of total)
2124 // 1 .. 1 ===> 2367 count ( 96% of total)
2125 // 2 .. 2 ===> 887 count ( 98% of total)
2126 // 3 .. 5 ===> 579 count ( 99% of total)
2127 // 6 .. 10 ===> 141 count ( 99% of total)
2128 // 11 .. 20 ===> 40 count ( 99% of total)
2129 // 21 .. 50 ===> 42 count ( 99% of total)
2130 // 51 .. 128 ===> 15 count ( 99% of total)
2131 // 129 .. 256 ===> 4 count ( 99% of total)
2132 // 257 .. 512 ===> 4 count (100% of total)
2133 // 513 .. 1024 ===> 0 count (100% of total)
2135 if (emitComp->verbose)
2137 unsigned count = (offsHi - offsLo) / sizeof(void*);
2138 printf("%u tracked GC refs are at stack offsets ", count);
2142 printf(" %04X ... %04X\n", offsLo, offsHi);
2143 assert(offsHi >= 0);
2146 #if defined(_TARGET_ARM_) && defined(PROFILING_SUPPORTED)
2147 if (!emitComp->compIsProfilerHookNeeded())
2150 #ifdef _TARGET_AMD64_
2151 // doesn't have to be all negative on amd
2152 printf("-%04X ... %04X\n", -offsLo, offsHi);
2154 printf("-%04X ... -%04X\n", -offsLo, -offsHi);
2155 assert(offsHi <= 0);
2158 #if defined(_TARGET_ARM_) && defined(PROFILING_SUPPORTED)
2161 // Under profiler due to prespilling of arguments, offHi need not be < 0
2163 printf("-%04X ... -%04X\n", -offsLo, -offsHi);
2165 printf("-%04X ... %04X\n", -offsLo, offsHi);
2172 assert(((offsHi - offsLo) % sizeof(void*)) == 0);
2173 assert((offsLo % sizeof(void*)) == 0);
2174 assert((offsHi % sizeof(void*)) == 0);
2176 emitGCrFrameOffsMin = offsLo;
2177 emitGCrFrameOffsMax = offsHi;
2178 emitGCrFrameOffsCnt = (offsHi - offsLo) / sizeof(void*);
2181 /*****************************************************************************
2183 * The code generator tells us the range of local variables through this
2187 void emitter::emitSetFrameRangeLcls(int offsLo, int offsHi)
2191 /*****************************************************************************
2193 * The code generator tells us the range of used arguments through this
2197 void emitter::emitSetFrameRangeArgs(int offsLo, int offsHi)
2201 /*****************************************************************************
2203 * A conversion table used to map an operand size value (in bytes) into its
2204 * small encoding (0 through 3), and vice versa.
2207 const emitter::opSize emitter::emitSizeEncode[] = {
2208 emitter::OPSZ1, emitter::OPSZ2, OPSIZE_INVALID, emitter::OPSZ4, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2209 emitter::OPSZ8, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2210 OPSIZE_INVALID, emitter::OPSZ16, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2211 OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2212 OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, emitter::OPSZ32,
2215 const emitAttr emitter::emitSizeDecode[emitter::OPSZ_COUNT] = {EA_1BYTE, EA_2BYTE, EA_4BYTE,
2216 EA_8BYTE, EA_16BYTE, EA_32BYTE};
2218 /*****************************************************************************
2220 * Allocate an instruction descriptor for an instruction that uses both
2221 * a displacement and a constant.
2224 emitter::instrDesc* emitter::emitNewInstrCnsDsp(emitAttr size, ssize_t cns, int dsp)
2228 if (instrDesc::fitsInSmallCns(cns))
2230 instrDesc* id = emitAllocInstr(size);
2232 id->idSmallCns(cns);
2236 emitSmallCns[cns - ID_MIN_SMALL_CNS]++;
2244 instrDescCns* id = emitAllocInstrCns(size);
2246 id->idSetIsLargeCns();
2247 id->idcCnsVal = cns;
2259 if (instrDesc::fitsInSmallCns(cns))
2261 instrDescDsp* id = emitAllocInstrDsp(size);
2263 id->idSetIsLargeDsp();
2264 id->iddDspVal = dsp;
2266 id->idSmallCns(cns);
2271 emitSmallCns[cns - ID_MIN_SMALL_CNS]++;
2278 instrDescCnsDsp* id = emitAllocInstrCnsDsp(size);
2280 id->idSetIsLargeCns();
2281 id->iddcCnsVal = cns;
2283 id->idSetIsLargeDsp();
2284 id->iddcDspVal = dsp;
2296 /*****************************************************************************
2298 * Returns true if garbage-collection won't happen within the helper call.
2299 * Don't need to record live pointers for such call sites.
2302 bool emitter::emitNoGChelper(unsigned IHX)
2304 // TODO-Throughput: Make this faster (maybe via a simple table of bools?)
2308 case CORINFO_HELP_UNDEF:
2311 case CORINFO_HELP_PROF_FCN_LEAVE:
2312 case CORINFO_HELP_PROF_FCN_ENTER:
2313 #if defined(_TARGET_AMD64_) || (defined(_TARGET_X86_) && !defined(LEGACY_BACKEND))
2314 case CORINFO_HELP_PROF_FCN_TAILCALL:
2316 case CORINFO_HELP_LLSH:
2317 case CORINFO_HELP_LRSH:
2318 case CORINFO_HELP_LRSZ:
2320 // case CORINFO_HELP_LMUL:
2321 // case CORINFO_HELP_LDIV:
2322 // case CORINFO_HELP_LMOD:
2323 // case CORINFO_HELP_ULDIV:
2324 // case CORINFO_HELP_ULMOD:
2327 case CORINFO_HELP_ASSIGN_REF_EAX:
2328 case CORINFO_HELP_ASSIGN_REF_ECX:
2329 case CORINFO_HELP_ASSIGN_REF_EBX:
2330 case CORINFO_HELP_ASSIGN_REF_EBP:
2331 case CORINFO_HELP_ASSIGN_REF_ESI:
2332 case CORINFO_HELP_ASSIGN_REF_EDI:
2334 case CORINFO_HELP_CHECKED_ASSIGN_REF_EAX:
2335 case CORINFO_HELP_CHECKED_ASSIGN_REF_ECX:
2336 case CORINFO_HELP_CHECKED_ASSIGN_REF_EBX:
2337 case CORINFO_HELP_CHECKED_ASSIGN_REF_EBP:
2338 case CORINFO_HELP_CHECKED_ASSIGN_REF_ESI:
2339 case CORINFO_HELP_CHECKED_ASSIGN_REF_EDI:
2342 case CORINFO_HELP_ASSIGN_REF:
2344 case CORINFO_HELP_CHECKED_ASSIGN_REF:
2346 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
2348 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
2350 case CORINFO_HELP_ASSIGN_BYREF:
2352 case CORINFO_HELP_INIT_PINVOKE_FRAME:
2360 /*****************************************************************************
2362 * Mark the current spot as having a label.
2365 void* emitter::emitAddLabel(VARSET_VALARG_TP GCvars, regMaskTP gcrefRegs, regMaskTP byrefRegs, BOOL isFinallyTarget)
2367 /* Create a new IG if the current one is non-empty */
2369 if (emitCurIGnonEmpty())
2374 VarSetOps::Assign(emitComp, emitThisGCrefVars, GCvars);
2375 VarSetOps::Assign(emitComp, emitInitGCrefVars, GCvars);
2376 emitThisGCrefRegs = emitInitGCrefRegs = gcrefRegs;
2377 emitThisByrefRegs = emitInitByrefRegs = byrefRegs;
2379 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2380 if (isFinallyTarget)
2382 emitCurIG->igFlags |= IGF_FINALLY_TARGET;
2384 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2387 if (EMIT_GC_VERBOSE)
2389 printf("Label: IG%02u, GCvars=%s ", emitCurIG->igNum, VarSetOps::ToString(emitComp, GCvars));
2390 dumpConvertedVarSet(emitComp, GCvars);
2391 printf(", gcrefRegs=");
2392 printRegMaskInt(gcrefRegs);
2393 emitDispRegSet(gcrefRegs);
2394 printf(", byrefRegs=");
2395 printRegMaskInt(byrefRegs);
2396 emitDispRegSet(byrefRegs);
2403 #ifdef _TARGET_ARMARCH_
2405 // Does the argument location point to an IG at the end of a function or funclet?
2406 // We can ignore the codePos part of the location, since it doesn't affect the
2407 // determination. If 'emitLocNextFragment' is non-NULL, it indicates the first
2408 // IG of the next fragment, so it represents a function end.
2409 bool emitter::emitIsFuncEnd(emitLocation* emitLoc, emitLocation* emitLocNextFragment /* = NULL */)
2413 insGroup* ig = emitLoc->GetIG();
2416 // Are we at the end of the IG list?
2417 if ((emitLocNextFragment != NULL) && (ig->igNext == emitLocNextFragment->GetIG()))
2421 if (ig->igNext == NULL)
2424 // Is the next IG the start of a funclet prolog?
2425 if (ig->igNext->igFlags & IGF_FUNCLET_PROLOG)
2428 #if FEATURE_EH_FUNCLETS
2430 // Is the next IG a placeholder group for a funclet prolog?
2431 if ((ig->igNext->igFlags & IGF_PLACEHOLDER) && (ig->igNext->igPhData->igPhType == IGPT_FUNCLET_PROLOG))
2436 #endif // FEATURE_EH_FUNCLETS
2441 /*****************************************************************************
2443 * Split the region from 'startLoc' to 'endLoc' into fragments by calling
2444 * a callback function to indicate the beginning of a fragment. The initial code,
2445 * starting at 'startLoc', doesn't get a callback, but the first code fragment,
2446 * about 'maxSplitSize' bytes out does, as does the beginning of each fragment
2447 * after that. There is no callback for the end (only the beginning of the last
2448 * fragment gets a callback). A fragment must contain at least one instruction
2449 * group. It should be smaller than 'maxSplitSize', although it may be larger to
2450 * satisfy the "at least one instruction group" rule. Do not split prologs or
2451 * epilogs. (Currently, prologs exist in a single instruction group at the main
2452 * function beginning, so they aren't split. Funclets, however, might span IGs,
2453 * so we can't split in between them.)
2455 * Note that the locations must be the start of instruction groups; the part of
2456 * the location indicating offset within a group must be zero.
2458 * If 'startLoc' is NULL, it means the start of the code.
2459 * If 'endLoc' is NULL, it means the end of the code.
2462 void emitter::emitSplit(emitLocation* startLoc,
2463 emitLocation* endLoc,
2464 UNATIVE_OFFSET maxSplitSize,
2466 emitSplitCallbackType callbackFunc)
2468 insGroup* igStart = (startLoc == NULL) ? emitIGlist : startLoc->GetIG();
2469 insGroup* igEnd = (endLoc == NULL) ? NULL : endLoc->GetIG();
2472 insGroup* igLastReported;
2473 insGroup* igLastCandidate;
2474 UNATIVE_OFFSET curSize;
2475 UNATIVE_OFFSET candidateSize;
2477 for (igPrev = NULL, ig = igLastReported = igStart, igLastCandidate = NULL, candidateSize = 0, curSize = 0;
2478 ig != igEnd && ig != NULL; igPrev = ig, ig = ig->igNext)
2480 // Keep looking until we've gone past the maximum split size
2481 if (curSize >= maxSplitSize)
2483 bool reportCandidate = true;
2485 // Is there a candidate?
2486 if (igLastCandidate == NULL)
2490 printf("emitSplit: can't split at IG%02u; we don't have a candidate to report\n", ig->igNum);
2492 reportCandidate = false;
2495 // Don't report the same thing twice (this also happens for the first block, since igLastReported is
2496 // initialized to igStart).
2497 if (igLastCandidate == igLastReported)
2501 printf("emitSplit: can't split at IG%02u; we already reported it\n", igLastCandidate->igNum);
2503 reportCandidate = false;
2507 if (reportCandidate)
2510 if (EMITVERBOSE && (candidateSize >= maxSplitSize))
2511 printf("emitSplit: split at IG%02u is size %d, larger than requested maximum size of %d\n",
2512 igLastCandidate->igNum, candidateSize, maxSplitSize);
2515 // hand memory ownership to the callback function
2516 emitLocation* pEmitLoc = new (emitComp, CMK_Unknown) emitLocation(igLastCandidate);
2517 callbackFunc(context, pEmitLoc);
2518 igLastReported = igLastCandidate;
2519 igLastCandidate = NULL;
2520 curSize -= candidateSize;
2524 // Update the current candidate to be this block, if it isn't in the middle of a
2525 // prolog or epilog, which we can't split. All we know is that certain
2526 // IGs are marked as prolog or epilog. We don't actually know if two adjacent
2527 // IGs are part of the *same* prolog or epilog, so we have to assume they are.
2529 if (igPrev && (((igPrev->igFlags & IGF_FUNCLET_PROLOG) && (ig->igFlags & IGF_FUNCLET_PROLOG)) ||
2530 ((igPrev->igFlags & IGF_EPILOG) && (ig->igFlags & IGF_EPILOG))))
2532 // We can't update the candidate
2536 igLastCandidate = ig;
2537 candidateSize = curSize;
2540 curSize += ig->igSize;
2545 /*****************************************************************************
2547 * Given an instruction group, find the array of instructions (instrDesc) and
2548 * number of instructions in the array. If the IG is the current IG, we assume
2549 * that igData does NOT hold the instructions; they are unsaved and pointed
2550 * to by emitCurIGfreeBase.
2552 * This function can't be called for placeholder groups, which have no instrDescs.
2555 void emitter::emitGetInstrDescs(insGroup* ig, instrDesc** id, int* insCnt)
2557 assert(!(ig->igFlags & IGF_PLACEHOLDER));
2558 if (ig == emitCurIG)
2560 *id = (instrDesc*)emitCurIGfreeBase;
2561 *insCnt = emitCurIGinsCnt;
2565 *id = (instrDesc*)ig->igData;
2566 *insCnt = ig->igInsCnt;
2572 /*****************************************************************************
2574 * Given a location (an 'emitLocation'), find the instruction group (IG) and
2575 * instruction descriptor (instrDesc) corresponding to that location. Returns
2576 * 'true' if there is an instruction, 'false' if there is no instruction
2577 * (i.e., we're at the end of the instruction list). Also, optionally return
2578 * the number of instructions that follow that instruction in the IG (in *pinsRemaining,
2579 * if pinsRemaining is non-NULL), which can be used for iterating over the
2580 * remaining instrDescs in the IG.
2582 * We assume that emitCurIG points to the end of the instructions we care about.
2583 * For the prologs or epilogs, it points to the last IG of the prolog or epilog
2584 * that is being generated. For body code gen, it points to the place we are currently
2585 * adding code, namely, the end of currently generated code.
2588 bool emitter::emitGetLocationInfo(emitLocation* emitLoc,
2591 int* pinsRemaining /* = NULL */)
2593 assert(emitLoc != nullptr);
2594 assert(emitLoc->Valid());
2595 assert(emitLoc->GetIG() != nullptr);
2596 assert(pig != nullptr);
2597 assert(pid != nullptr);
2599 insGroup* ig = emitLoc->GetIG();
2601 int insNum = emitLoc->GetInsNum();
2604 emitGetInstrDescs(ig, &id, &insCnt);
2605 assert(insNum <= insCnt);
2607 // There is a special-case: if the insNum points to the end, then we "wrap" and
2608 // consider that the instruction it is pointing at is actually the first instruction
2609 // of the next non-empty IG (which has its own valid emitLocation). This handles the
2610 // case where you capture a location, then the next instruction creates a new IG.
2612 if (insNum == insCnt)
2614 if (ig == emitCurIG)
2616 // No instructions beyond the current location.
2620 for (ig = ig->igNext; ig; ig = ig->igNext)
2622 emitGetInstrDescs(ig, &id, &insCnt);
2626 insNum = 0; // Pretend the index is 0 -- the first instruction
2630 if (ig == emitCurIG)
2632 // There aren't any instructions in the current IG, and this is
2633 // the current location, so we're at the end.
2640 // 'ig' can't be NULL, or we went past the current IG represented by 'emitCurIG'.
2641 // Perhaps 'loc' was corrupt coming in?
2642 noway_assert(!"corrupt emitter location");
2647 // Now find the instrDesc within this group that corresponds to the location
2649 assert(insNum < insCnt);
2652 for (i = 0; i != insNum; ++i)
2654 castto(id, BYTE*) += emitSizeOfInsDsc(id);
2657 // Return the info we found
2664 *pinsRemaining = insCnt - insNum - 1;
2670 /*****************************************************************************
2672 * Compute the next instrDesc, either in this IG, or in a subsequent IG. 'id'
2673 * will point to this instrDesc. 'ig' and 'insRemaining' will also be updated.
2674 * Returns true if there is an instruction, or false if we've iterated over all
2675 * the instructions up to the current instruction (based on 'emitCurIG').
2678 bool emitter::emitNextID(insGroup*& ig, instrDesc*& id, int& insRemaining)
2680 if (insRemaining > 0)
2682 castto(id, BYTE*) += emitSizeOfInsDsc(id);
2687 // We're out of instrDesc in 'ig'. Is this the current IG? If so, we're done.
2689 if (ig == emitCurIG)
2694 for (ig = ig->igNext; ig; ig = ig->igNext)
2697 emitGetInstrDescs(ig, &id, &insCnt);
2701 insRemaining = insCnt - 1;
2705 if (ig == emitCurIG)
2714 /*****************************************************************************
2716 * Walk instrDesc's from the location given by 'locFrom', up to the current location.
2717 * For each instruction, call the callback function 'processFunc'. 'context' is simply
2718 * passed through to the callback function.
2721 void emitter::emitWalkIDs(emitLocation* locFrom, emitProcessInstrFunc_t processFunc, void* context)
2727 if (!emitGetLocationInfo(locFrom, &ig, &id, &insRemaining))
2728 return; // no instructions at the 'from' location
2733 (*processFunc)(id, context);
2735 } while (emitNextID(ig, id, insRemaining));
2738 /*****************************************************************************
2740 * A callback function for emitWalkIDs() that calls Compiler::unwindNop().
2743 void emitter::emitGenerateUnwindNop(instrDesc* id, void* context)
2745 Compiler* comp = (Compiler*)context;
2746 #if defined(_TARGET_ARM_)
2747 comp->unwindNop(id->idCodeSize());
2748 #elif defined(_TARGET_ARM64_)
2750 #endif // defined(_TARGET_ARM64_)
2753 /*****************************************************************************
2755 * emitUnwindNopPadding: call unwindNop() for every instruction from a given
2756 * location 'emitLoc' up to the current location.
2759 void emitter::emitUnwindNopPadding(emitLocation* locFrom, Compiler* comp)
2761 emitWalkIDs(locFrom, emitGenerateUnwindNop, comp);
2764 #endif // _TARGET_ARMARCH_
2766 #if defined(_TARGET_ARM_)
2768 /*****************************************************************************
2770 * Return the instruction size in bytes for the instruction at the specified location.
2771 * This is used to assert that the unwind code being generated on ARM has the
2772 * same size as the instruction for which it is being generated (since on ARM
2773 * the unwind codes have a one-to-one relationship with instructions, and the
2774 * unwind codes have an implicit instruction size that must match the instruction size.)
2775 * An instruction must exist at the specified location.
2778 unsigned emitter::emitGetInstructionSize(emitLocation* emitLoc)
2783 bool anyInstrs = emitGetLocationInfo(emitLoc, &ig, &id);
2784 assert(anyInstrs); // There better be an instruction at this location (otherwise, we're at the end of the
2785 // instruction list)
2786 return id->idCodeSize();
2789 #endif // defined(_TARGET_ARM_)
2791 /*****************************************************************************/
2793 /*****************************************************************************
2795 * Returns the name for the register to use to access frame based variables
2798 const char* emitter::emitGetFrameReg()
2800 if (emitHasFramePtr)
2810 /*****************************************************************************
2812 * Display a register set in a readable form.
2815 void emitter::emitDispRegSet(regMaskTP regs)
2822 for (reg = REG_FIRST; reg < ACTUAL_REG_COUNT; reg = REG_NEXT(reg))
2824 if ((regs & genRegMask(reg)) == 0)
2838 printf("%s", emitRegName(reg));
2844 /*****************************************************************************
2846 * Display the current GC ref variable set in a readable form.
2849 void emitter::emitDispVarSet()
2855 for (vn = 0, of = emitGCrFrameOffsMin; vn < emitGCrFrameOffsCnt; vn += 1, of += sizeof(void*))
2857 if (emitGCrFrameLiveTab[vn])
2868 printf("[%s", emitGetFrameReg());
2872 printf("-%02XH", -of);
2876 printf("+%02XH", +of);
2889 /*****************************************************************************/
2892 #if MULTIREG_HAS_SECOND_GC_RET
2893 //------------------------------------------------------------------------
2894 // emitSetSecondRetRegGCType: Sets the GC type of the second return register for instrDescCGCA struct.
2897 // id - The large call instr descriptor to set the second GC return register type on.
2898 // secondRetSize - The EA_SIZE for second return register type.
2904 void emitter::emitSetSecondRetRegGCType(instrDescCGCA* id, emitAttr secondRetSize)
2906 if (EA_IS_GCREF(secondRetSize))
2908 id->idSecondGCref(GCT_GCREF);
2910 else if (EA_IS_BYREF(secondRetSize))
2912 id->idSecondGCref(GCT_BYREF);
2916 id->idSecondGCref(GCT_NONE);
2919 #endif // MULTIREG_HAS_SECOND_GC_RET
2921 /*****************************************************************************
2923 * Allocate an instruction descriptor for an indirect call.
2925 * We use two different descriptors to save space - the common case records
2926 * no GC variables and has both a very small argument count and an address
2927 * mode displacement; the other case records the current GC var set,
2928 * the call scope, and an arbitrarily large argument count and the
2929 * address mode displacement.
2932 emitter::instrDesc* emitter::emitNewInstrCallInd(int argCnt,
2934 VARSET_VALARG_TP GCvars,
2935 regMaskTP gcrefRegs,
2936 regMaskTP byrefRegs,
2938 MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize))
2940 emitAttr retSize = (retSizeIn != EA_UNKNOWN) ? retSizeIn : EA_PTRSIZE;
2942 bool gcRefRegsInScratch = ((gcrefRegs & RBM_CALLEE_TRASH) != 0);
2944 // Allocate a larger descriptor if any GC values need to be saved
2945 // or if we have an absurd number of arguments or a large address
2946 // mode displacement, or we have some byref registers
2948 // On Amd64 System V OSs a larger descriptor is also needed if the
2949 // call returns a two-register-returned struct and the second
2950 // register (RDX) is a GCRef or ByRef pointer.
2952 if (!VarSetOps::IsEmpty(emitComp, GCvars) || // any frame GCvars live
2953 (gcRefRegsInScratch) || // any register gc refs live in scratch regs
2954 (byrefRegs != 0) || // any register byrefs live
2955 (disp < AM_DISP_MIN) || // displacement too negative
2956 (disp > AM_DISP_MAX) || // displacement too positive
2957 (argCnt > ID_MAX_SMALL_CNS) || // too many args
2958 (argCnt < 0) // caller pops arguments
2959 // There is a second ref/byref return register.
2960 MULTIREG_HAS_SECOND_GC_RET_ONLY(|| EA_IS_GCREF_OR_BYREF(secondRetSize)))
2964 id = emitAllocInstrCGCA(retSize);
2966 id->idSetIsLargeCall();
2968 VarSetOps::Assign(emitComp, id->idcGCvars, GCvars);
2969 id->idcGcrefRegs = gcrefRegs;
2970 id->idcByrefRegs = byrefRegs;
2971 id->idcArgCnt = argCnt;
2974 #if MULTIREG_HAS_SECOND_GC_RET
2975 emitSetSecondRetRegGCType(id, secondRetSize);
2976 #endif // MULTIREG_HAS_SECOND_GC_RET
2984 id = emitNewInstrCns(retSize, argCnt);
2986 /* Make sure we didn't waste space unexpectedly */
2987 assert(!id->idIsLargeCns());
2989 /* Store the displacement and make sure the value fit */
2990 id->idAddr()->iiaAddrMode.amDisp = disp;
2991 assert(id->idAddr()->iiaAddrMode.amDisp == disp);
2993 /* Save the the live GC registers in the unused register fields */
2994 emitEncodeCallGCregs(gcrefRegs, id);
3000 /*****************************************************************************
3002 * Allocate an instruction descriptor for a direct call.
3004 * We use two different descriptors to save space - the common case records
3005 * with no GC variables or byrefs and has a very small argument count, and no
3007 * the other case records the current GC var set, the call scope,
3008 * and an arbitrarily large argument count.
3011 emitter::instrDesc* emitter::emitNewInstrCallDir(int argCnt,
3012 VARSET_VALARG_TP GCvars,
3013 regMaskTP gcrefRegs,
3014 regMaskTP byrefRegs,
3016 MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize))
3018 emitAttr retSize = (retSizeIn != EA_UNKNOWN) ? retSizeIn : EA_PTRSIZE;
3020 // Allocate a larger descriptor if new GC values need to be saved
3021 // or if we have an absurd number of arguments or if we need to
3024 // On Amd64 System V OSs a larger descriptor is also needed if the
3025 // call returns a two-register-returned struct and the second
3026 // register (RDX) is a GCRef or ByRef pointer.
3028 bool gcRefRegsInScratch = ((gcrefRegs & RBM_CALLEE_TRASH) != 0);
3030 if (!VarSetOps::IsEmpty(emitComp, GCvars) || // any frame GCvars live
3031 gcRefRegsInScratch || // any register gc refs live in scratch regs
3032 (byrefRegs != 0) || // any register byrefs live
3033 (argCnt > ID_MAX_SMALL_CNS) || // too many args
3034 (argCnt < 0) // caller pops arguments
3035 // There is a second ref/byref return register.
3036 MULTIREG_HAS_SECOND_GC_RET_ONLY(|| EA_IS_GCREF_OR_BYREF(secondRetSize)))
3038 instrDescCGCA* id = emitAllocInstrCGCA(retSize);
3040 // printf("Direct call with GC vars / big arg cnt / explicit scope\n");
3042 id->idSetIsLargeCall();
3044 VarSetOps::Assign(emitComp, id->idcGCvars, GCvars);
3045 id->idcGcrefRegs = gcrefRegs;
3046 id->idcByrefRegs = byrefRegs;
3048 id->idcArgCnt = argCnt;
3050 #if MULTIREG_HAS_SECOND_GC_RET
3051 emitSetSecondRetRegGCType(id, secondRetSize);
3052 #endif // MULTIREG_HAS_SECOND_GC_RET
3058 instrDesc* id = emitNewInstrCns(retSize, argCnt);
3060 // printf("Direct call w/o GC vars / big arg cnt / explicit scope\n");
3062 /* Make sure we didn't waste space unexpectedly */
3063 assert(!id->idIsLargeCns());
3065 /* Save the the live GC registers in the unused register fields */
3066 emitEncodeCallGCregs(gcrefRegs, id);
3072 /*****************************************************************************/
3074 /*****************************************************************************
3076 * Return a string with the name of the given class field (blank string (not
3077 * NULL) is returned when the name isn't available).
3080 const char* emitter::emitFldName(CORINFO_FIELD_HANDLE fieldVal)
3082 if (emitComp->opts.varNames)
3084 const char* memberName;
3085 const char* className;
3087 const int TEMP_BUFFER_LEN = 1024;
3088 static char buff[TEMP_BUFFER_LEN];
3090 memberName = emitComp->eeGetFieldName(fieldVal, &className);
3092 sprintf_s(buff, TEMP_BUFFER_LEN, "'<%s>.%s'", className, memberName);
3101 /*****************************************************************************
3103 * Return a string with the name of the given function (blank string (not
3104 * NULL) is returned when the name isn't available).
3107 const char* emitter::emitFncName(CORINFO_METHOD_HANDLE methHnd)
3109 return emitComp->eeGetMethodFullName(methHnd);
3114 /*****************************************************************************
3116 * Be very careful, some instruction descriptors are allocated as "tiny" and
3117 * don't have some of the tail fields of instrDesc (in particular, "idInfo").
3120 const BYTE emitter::emitFmtToOps[] = {
3121 #define IF_DEF(en, op1, op2) ID_OP_##op2,
3122 #include "emitfmts.h"
3126 const unsigned emitter::emitFmtCount = sizeof(emitFmtToOps) / sizeof(emitFmtToOps[0]);
3129 /*****************************************************************************
3131 * Display the current instruction group list.
3136 void emitter::emitDispIGflags(unsigned flags)
3138 if (flags & IGF_GC_VARS)
3142 if (flags & IGF_BYREF_REGS)
3146 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
3147 if (flags & IGF_FINALLY_TARGET)
3149 printf(", ftarget");
3151 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
3152 if (flags & IGF_FUNCLET_PROLOG)
3154 printf(", funclet prolog");
3156 if (flags & IGF_FUNCLET_EPILOG)
3158 printf(", funclet epilog");
3160 if (flags & IGF_EPILOG)
3164 if (flags & IGF_NOGCINTERRUPT)
3168 if (flags & IGF_UPD_ISZ)
3172 if (flags & IGF_EMIT_ADD)
3174 printf(", emitadd");
3178 void emitter::emitDispIG(insGroup* ig, insGroup* igPrev, bool verbose)
3180 const int TEMP_BUFFER_LEN = 40;
3181 char buff[TEMP_BUFFER_LEN];
3183 sprintf_s(buff, TEMP_BUFFER_LEN, "G_M%03u_IG%02u: ", Compiler::s_compMethodsCount, ig->igNum);
3184 printf("%s; ", buff);
3185 if ((igPrev == nullptr) || (igPrev->igFuncIdx != ig->igFuncIdx))
3187 printf("func=%02u, ", ig->igFuncIdx);
3190 if (ig->igFlags & IGF_PLACEHOLDER)
3192 insGroup* igPh = ig;
3194 const char* pszType;
3195 switch (igPh->igPhData->igPhType)
3203 #if FEATURE_EH_FUNCLETS
3204 case IGPT_FUNCLET_PROLOG:
3205 pszType = "funclet prolog";
3207 case IGPT_FUNCLET_EPILOG:
3208 pszType = "funclet epilog";
3210 #endif // FEATURE_EH_FUNCLETS
3212 pszType = "UNKNOWN";
3215 printf("%s placeholder, next placeholder=", pszType);
3216 if (igPh->igPhData->igPhNext)
3218 printf("IG%02u ", igPh->igPhData->igPhNext->igNum);
3225 if (igPh->igPhData->igPhBB != nullptr)
3227 printf(", %s", igPh->igPhData->igPhBB->dspToString());
3230 emitDispIGflags(igPh->igFlags);
3232 if (ig == emitCurIG)
3234 printf(" <-- Current IG");
3236 if (igPh == emitPlaceholderList)
3238 printf(" <-- First placeholder");
3240 if (igPh == emitPlaceholderLast)
3242 printf(" <-- Last placeholder");
3246 printf("%*s; PrevGCVars=%s ", strlen(buff), "",
3247 VarSetOps::ToString(emitComp, igPh->igPhData->igPhPrevGCrefVars));
3248 dumpConvertedVarSet(emitComp, igPh->igPhData->igPhPrevGCrefVars);
3249 printf(", PrevGCrefRegs=");
3250 printRegMaskInt(igPh->igPhData->igPhPrevGCrefRegs);
3251 emitDispRegSet(igPh->igPhData->igPhPrevGCrefRegs);
3252 printf(", PrevByrefRegs=");
3253 printRegMaskInt(igPh->igPhData->igPhPrevByrefRegs);
3254 emitDispRegSet(igPh->igPhData->igPhPrevByrefRegs);
3257 printf("%*s; InitGCVars=%s ", strlen(buff), "",
3258 VarSetOps::ToString(emitComp, igPh->igPhData->igPhInitGCrefVars));
3259 dumpConvertedVarSet(emitComp, igPh->igPhData->igPhInitGCrefVars);
3260 printf(", InitGCrefRegs=");
3261 printRegMaskInt(igPh->igPhData->igPhInitGCrefRegs);
3262 emitDispRegSet(igPh->igPhData->igPhInitGCrefRegs);
3263 printf(", InitByrefRegs=");
3264 printRegMaskInt(igPh->igPhData->igPhInitByrefRegs);
3265 emitDispRegSet(igPh->igPhData->igPhInitByrefRegs);
3268 assert(!(ig->igFlags & IGF_GC_VARS));
3269 assert(!(ig->igFlags & IGF_BYREF_REGS));
3273 printf("offs=%06XH, size=%04XH", ig->igOffs, ig->igSize);
3275 if (ig->igFlags & IGF_GC_VARS)
3277 printf(", gcVars=%s ", VarSetOps::ToString(emitComp, ig->igGCvars()));
3278 dumpConvertedVarSet(emitComp, ig->igGCvars());
3281 if (!(ig->igFlags & IGF_EMIT_ADD))
3283 printf(", gcrefRegs=");
3284 printRegMaskInt(ig->igGCregs);
3285 emitDispRegSet(ig->igGCregs);
3288 if (ig->igFlags & IGF_BYREF_REGS)
3290 printf(", byrefRegs=");
3291 printRegMaskInt(ig->igByrefRegs());
3292 emitDispRegSet(ig->igByrefRegs());
3295 emitDispIGflags(ig->igFlags);
3297 if (ig == emitCurIG)
3299 printf(" <-- Current IG");
3301 if (ig == emitPrologIG)
3303 printf(" <-- Prolog IG");
3309 BYTE* ins = ig->igData;
3310 UNATIVE_OFFSET ofs = ig->igOffs;
3311 unsigned cnt = ig->igInsCnt;
3319 instrDesc* id = (instrDesc*)ins;
3321 emitDispIns(id, false, true, false, ofs, nullptr, 0, ig);
3323 ins += emitSizeOfInsDsc(id);
3324 ofs += emitInstCodeSz(id);
3333 void emitter::emitDispIGlist(bool verbose)
3338 for (igPrev = nullptr, ig = emitIGlist; ig; igPrev = ig, ig = ig->igNext)
3340 emitDispIG(ig, igPrev, verbose);
3344 void emitter::emitDispGCinfo()
3346 printf("Emitter GC tracking info:");
3347 printf("\n emitPrevGCrefVars ");
3348 dumpConvertedVarSet(emitComp, emitPrevGCrefVars);
3349 printf("\n emitPrevGCrefRegs(0x%p)=", dspPtr(&emitPrevGCrefRegs));
3350 printRegMaskInt(emitPrevGCrefRegs);
3351 emitDispRegSet(emitPrevGCrefRegs);
3352 printf("\n emitPrevByrefRegs(0x%p)=", dspPtr(&emitPrevByrefRegs));
3353 printRegMaskInt(emitPrevByrefRegs);
3354 emitDispRegSet(emitPrevByrefRegs);
3355 printf("\n emitInitGCrefVars ");
3356 dumpConvertedVarSet(emitComp, emitInitGCrefVars);
3357 printf("\n emitInitGCrefRegs(0x%p)=", dspPtr(&emitInitGCrefRegs));
3358 printRegMaskInt(emitInitGCrefRegs);
3359 emitDispRegSet(emitInitGCrefRegs);
3360 printf("\n emitInitByrefRegs(0x%p)=", dspPtr(&emitInitByrefRegs));
3361 printRegMaskInt(emitInitByrefRegs);
3362 emitDispRegSet(emitInitByrefRegs);
3363 printf("\n emitThisGCrefVars ");
3364 dumpConvertedVarSet(emitComp, emitThisGCrefVars);
3365 printf("\n emitThisGCrefRegs(0x%p)=", dspPtr(&emitThisGCrefRegs));
3366 printRegMaskInt(emitThisGCrefRegs);
3367 emitDispRegSet(emitThisGCrefRegs);
3368 printf("\n emitThisByrefRegs(0x%p)=", dspPtr(&emitThisByrefRegs));
3369 printRegMaskInt(emitThisByrefRegs);
3370 emitDispRegSet(emitThisByrefRegs);
3376 /*****************************************************************************
3378 * Issue the given instruction. Basically, this is just a thin wrapper around
3379 * emitOutputInstr() that does a few debug checks.
3382 size_t emitter::emitIssue1Instr(insGroup* ig, instrDesc* id, BYTE** dp)
3386 /* Record the beginning offset of the instruction */
3388 BYTE* curInsAdr = *dp;
3390 /* Issue the next instruction */
3392 // printf("[S=%02u] " , emitCurStackLvl);
3394 is = emitOutputInstr(ig, id, dp);
3396 // printf("[S=%02u]\n", emitCurStackLvl);
3398 #if EMIT_TRACK_STACK_DEPTH
3401 If we're generating a full pointer map and the stack
3402 is empty, there better not be any "pending" argument
3406 assert(emitFullGCinfo == false || emitCurStackLvl != 0 || u2.emitGcArgTrackCnt == 0);
3410 /* Did the size of the instruction match our expectations? */
3412 UNATIVE_OFFSET csz = (UNATIVE_OFFSET)(*dp - curInsAdr);
3414 if (csz != id->idCodeSize())
3416 /* It is fatal to under-estimate the instruction size */
3417 noway_assert(emitInstCodeSz(id) >= csz);
3422 printf("Instruction predicted size = %u, actual = %u\n", emitInstCodeSz(id), csz);
3424 #endif // DEBUG_EMIT
3426 /* The instruction size estimate wasn't accurate; remember this */
3428 ig->igFlags |= IGF_UPD_ISZ;
3429 #if defined(_TARGET_XARCH_)
3430 id->idCodeSize(csz);
3431 #elif defined(_TARGET_ARM_)
3432 // This is done as part of emitSetShortJump();
3433 // insSize isz = emitInsSize(id->idInsFmt());
3434 // id->idInsSize(isz);
3436 /* It is fatal to over-estimate the instruction size */
3437 IMPL_LIMITATION("Over-estimated instruction size");
3442 /* Make sure the instruction descriptor size also matches our expectations */
3443 if (is != emitSizeOfInsDsc(id))
3445 printf("%s at %u: Expected size = %u , actual size = %u\n", emitIfName(id->idInsFmt()),
3446 id->idDebugOnlyInfo()->idNum, is, emitSizeOfInsDsc(id));
3447 assert(is == emitSizeOfInsDsc(id));
3454 /*****************************************************************************
3456 * Update the offsets of all the instruction groups (note: please don't be
3457 * lazy and call this routine frequently, it walks the list of instruction
3458 * groups and thus it isn't cheap).
3461 void emitter::emitRecomputeIGoffsets()
3463 UNATIVE_OFFSET offs;
3466 for (ig = emitIGlist, offs = 0; ig; ig = ig->igNext)
3469 assert(IsCodeAligned(ig->igOffs));
3473 /* Set the total code size */
3475 emitTotalCodeSize = offs;
3478 emitCheckIGoffsets();
3482 /*****************************************************************************
3483 * Bind targets of relative jumps to choose the smallest possible encoding.
3484 * X86 and AMD64 have a small and large encoding.
3485 * ARM has a small, medium, and large encoding. The large encoding is a pseudo-op
3486 * to handle greater range than the conditional branch instructions can handle.
3487 * ARM64 has a small and large encoding for both conditional branch and loading label addresses.
3488 * The large encodings are pseudo-ops that represent a multiple instruction sequence, similar to ARM. (Currently
3492 void emitter::emitJumpDistBind()
3495 if (emitComp->verbose)
3497 printf("*************** In emitJumpDistBind()\n");
3499 if (EMIT_INSTLIST_VERBOSE)
3501 printf("\nInstruction list before jump distance binding:\n\n");
3502 emitDispIGlist(true);
3508 UNATIVE_OFFSET minShortExtra; // The smallest offset greater than that required for a jump to be converted
3509 // to a small jump. If it is small enough, we will iterate in hopes of
3510 // converting those jumps we missed converting the first (or second...) time.
3512 #if defined(_TARGET_ARM_)
3513 UNATIVE_OFFSET minMediumExtra; // Same as 'minShortExtra', but for medium-sized jumps.
3514 #endif // _TARGET_ARM_
3516 UNATIVE_OFFSET adjIG;
3517 UNATIVE_OFFSET adjLJ;
3520 insGroup* prologIG = emitPrologIG;
3523 int jmp_iteration = 1;
3525 /*****************************************************************************/
3526 /* If we iterate to look for more jumps to shorten, we start again here. */
3527 /*****************************************************************************/
3532 emitCheckIGoffsets();
3536 In the following loop we convert all jump targets from "BasicBlock *"
3537 to "insGroup *" values. We also estimate which jumps will be short.
3541 insGroup* lastIG = nullptr;
3542 instrDescJmp* lastLJ = nullptr;
3548 minShortExtra = (UNATIVE_OFFSET)-1;
3550 #if defined(_TARGET_ARM_)
3551 minMediumExtra = (UNATIVE_OFFSET)-1;
3552 #endif // _TARGET_ARM_
3554 for (jmp = emitJumpList; jmp; jmp = jmp->idjNext)
3559 UNATIVE_OFFSET jsz; // size of the jump instruction in bytes
3561 UNATIVE_OFFSET ssz = 0; // small jump size
3562 NATIVE_OFFSET nsd = 0; // small jump max. neg distance
3563 NATIVE_OFFSET psd = 0; // small jump max. pos distance
3565 #if defined(_TARGET_ARM_)
3566 UNATIVE_OFFSET msz = 0; // medium jump size
3567 NATIVE_OFFSET nmd = 0; // medium jump max. neg distance
3568 NATIVE_OFFSET pmd = 0; // medium jump max. pos distance
3569 NATIVE_OFFSET mextra; // How far beyond the medium jump range is this jump offset?
3570 #endif // _TARGET_ARM_
3572 NATIVE_OFFSET extra; // How far beyond the short jump range is this jump offset?
3573 UNATIVE_OFFSET srcInstrOffs; // offset of the source instruction of the jump
3574 UNATIVE_OFFSET srcEncodingOffs; // offset of the source used by the instruction set to calculate the relative
3575 // offset of the jump
3576 UNATIVE_OFFSET dstOffs;
3577 NATIVE_OFFSET jmpDist; // the relative jump distance, as it will be encoded
3578 UNATIVE_OFFSET oldSize;
3579 UNATIVE_OFFSET sizeDif;
3581 #ifdef _TARGET_XARCH_
3582 assert(jmp->idInsFmt() == IF_LABEL || jmp->idInsFmt() == IF_RWR_LABEL || jmp->idInsFmt() == IF_SWR_LABEL);
3584 /* Figure out the smallest size we can end up with */
3586 if (jmp->idInsFmt() == IF_LABEL)
3588 if (emitIsCondJump(jmp))
3590 ssz = JCC_SIZE_SMALL;
3591 nsd = JCC_DIST_SMALL_MAX_NEG;
3592 psd = JCC_DIST_SMALL_MAX_POS;
3596 ssz = JMP_SIZE_SMALL;
3597 nsd = JMP_DIST_SMALL_MAX_NEG;
3598 psd = JMP_DIST_SMALL_MAX_POS;
3601 #endif // _TARGET_XARCH_
3604 assert((jmp->idInsFmt() == IF_T2_J1) || (jmp->idInsFmt() == IF_T2_J2) || (jmp->idInsFmt() == IF_T1_I) ||
3605 (jmp->idInsFmt() == IF_T1_K) || (jmp->idInsFmt() == IF_T1_M) || (jmp->idInsFmt() == IF_T2_M1) ||
3606 (jmp->idInsFmt() == IF_T2_N1) || (jmp->idInsFmt() == IF_T1_J3) || (jmp->idInsFmt() == IF_LARGEJMP));
3608 /* Figure out the smallest size we can end up with */
3610 if (emitIsCondJump(jmp))
3612 ssz = JCC_SIZE_SMALL;
3613 nsd = JCC_DIST_SMALL_MAX_NEG;
3614 psd = JCC_DIST_SMALL_MAX_POS;
3616 msz = JCC_SIZE_MEDIUM;
3617 nmd = JCC_DIST_MEDIUM_MAX_NEG;
3618 pmd = JCC_DIST_MEDIUM_MAX_POS;
3620 else if (emitIsCmpJump(jmp))
3622 ssz = JMP_SIZE_SMALL;
3626 else if (emitIsUncondJump(jmp))
3628 ssz = JMP_SIZE_SMALL;
3629 nsd = JMP_DIST_SMALL_MAX_NEG;
3630 psd = JMP_DIST_SMALL_MAX_POS;
3632 else if (emitIsLoadLabel(jmp))
3634 ssz = LBL_SIZE_SMALL;
3635 nsd = LBL_DIST_SMALL_MAX_NEG;
3636 psd = LBL_DIST_SMALL_MAX_POS;
3640 assert(!"Unknown jump instruction");
3642 #endif // _TARGET_ARM_
3644 #ifdef _TARGET_ARM64_
3645 /* Figure out the smallest size we can end up with */
3647 if (emitIsCondJump(jmp))
3649 ssz = JCC_SIZE_SMALL;
3650 bool isTest = (jmp->idIns() == INS_tbz) || (jmp->idIns() == INS_tbnz);
3652 nsd = (isTest) ? TB_DIST_SMALL_MAX_NEG : JCC_DIST_SMALL_MAX_NEG;
3653 psd = (isTest) ? TB_DIST_SMALL_MAX_POS : JCC_DIST_SMALL_MAX_POS;
3655 else if (emitIsUncondJump(jmp))
3657 // Nothing to do; we don't shrink these.
3658 assert(jmp->idjShort);
3659 ssz = JMP_SIZE_SMALL;
3661 else if (emitIsLoadLabel(jmp))
3663 ssz = LBL_SIZE_SMALL;
3664 nsd = LBL_DIST_SMALL_MAX_NEG;
3665 psd = LBL_DIST_SMALL_MAX_POS;
3667 else if (emitIsLoadConstant(jmp))
3669 ssz = LDC_SIZE_SMALL;
3670 nsd = LDC_DIST_SMALL_MAX_NEG;
3671 psd = LDC_DIST_SMALL_MAX_POS;
3675 assert(!"Unknown jump instruction");
3677 #endif // _TARGET_ARM64_
3679 /* Make sure the jumps are properly ordered */
3682 assert(lastLJ == nullptr || lastIG != jmp->idjIG || lastLJ->idjOffs < jmp->idjOffs);
3683 lastLJ = (lastIG == jmp->idjIG) ? jmp : nullptr;
3685 assert(lastIG == nullptr || lastIG->igNum <= jmp->idjIG->igNum || jmp->idjIG == prologIG ||
3686 emitNxtIGnum > unsigned(0xFFFF)); // igNum might overflow
3687 lastIG = jmp->idjIG;
3690 /* Get hold of the current jump size */
3692 jsz = emitSizeOfJump(jmp);
3694 /* Get the group the jump is in */
3698 /* Are we in a group different from the previous jump? */
3702 /* Were there any jumps before this one? */
3706 /* Adjust the offsets of the intervening blocks */
3710 lstIG = lstIG->igNext;
3712 // printf("Adjusted offset of block %02u from %04X to %04X\n", lstIG->igNum, lstIG->igOffs,
3713 // lstIG->igOffs - adjIG);
3714 lstIG->igOffs -= adjIG;
3715 assert(IsCodeAligned(lstIG->igOffs));
3716 } while (lstIG != jmpIG);
3719 /* We've got the first jump in a new group */
3725 /* Apply any local size adjustment to the jump's relative offset */
3727 jmp->idjOffs -= adjLJ;
3729 // If this is a jump via register, the instruction size does not change, so we are done.
3730 CLANG_FORMAT_COMMENT_ANCHOR;
3732 #if defined(_TARGET_ARM64_)
3733 // JIT code and data will be allocated together for arm64 so the relative offset to JIT data is known.
3734 // In case such offset can be encodeable for `ldr` (+-1MB), shorten it.
3735 if (jmp->idAddr()->iiaIsJitDataOffset())
3737 // Reference to JIT data
3738 assert(jmp->idIsBound());
3739 UNATIVE_OFFSET srcOffs = jmpIG->igOffs + jmp->idjOffs;
3741 int doff = jmp->idAddr()->iiaGetJitDataOffset();
3743 ssize_t imm = emitGetInsSC(jmp);
3744 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
3746 unsigned dataOffs = (unsigned)(doff + imm);
3747 assert(dataOffs < emitDataSize());
3749 // Conservately assume JIT data starts after the entire code size.
3750 // TODO-ARM64: we might consider only hot code size which will be computed later in emitComputeCodeSizes().
3751 assert(emitTotalCodeSize > 0);
3752 UNATIVE_OFFSET maxDstOffs = emitTotalCodeSize + dataOffs;
3754 // Check if the distance is within the encoding length.
3755 jmpDist = maxDstOffs - srcOffs;
3756 extra = jmpDist - psd;
3762 // Keep the large form.
3767 /* Have we bound this jump's target already? */
3769 if (jmp->idIsBound())
3771 /* Does the jump already have the smallest size? */
3775 assert(emitSizeOfJump(jmp) == ssz);
3777 // We should not be jumping/branching across funclets/functions
3778 emitCheckFuncletBranch(jmp, jmpIG);
3783 tgtIG = jmp->idAddr()->iiaIGlabel;
3787 /* First time we've seen this label, convert its target */
3788 CLANG_FORMAT_COMMENT_ANCHOR;
3793 printf("Binding: ");
3794 emitDispIns(jmp, false, false, false);
3795 printf("Binding L_M%03u_BB%02u ", Compiler::s_compMethodsCount, jmp->idAddr()->iiaBBlabel->bbNum);
3799 tgtIG = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel);
3806 printf("to G_M%03u_IG%02u\n", Compiler::s_compMethodsCount, tgtIG->igNum);
3810 printf("-- ERROR, no emitter cookie for BB%02u; it is probably missing BBF_JMP_TARGET or "
3812 jmp->idAddr()->iiaBBlabel->bbNum);
3818 /* Record the bound target */
3820 jmp->idAddr()->iiaIGlabel = tgtIG;
3821 jmp->idSetIsBound();
3824 // We should not be jumping/branching across funclets/functions
3825 emitCheckFuncletBranch(jmp, jmpIG);
3827 #ifdef _TARGET_XARCH_
3828 /* Done if this is not a variable-sized jump */
3830 if ((jmp->idIns() == INS_push) || (jmp->idIns() == INS_mov) || (jmp->idIns() == INS_call) ||
3831 (jmp->idIns() == INS_push_hide))
3837 if ((jmp->idIns() == INS_push) || (jmp->idIns() == INS_mov) || (jmp->idIns() == INS_movt) ||
3838 (jmp->idIns() == INS_movw))
3843 #ifdef _TARGET_ARM64_
3844 // There is only one size of unconditional branch; we don't support functions larger than 2^28 bytes (our branch
3846 if (emitIsUncondJump(jmp))
3853 In the following distance calculations, if we're not actually
3854 scheduling the code (i.e. reordering instructions), we can
3855 use the actual offset of the jump (rather than the beg/end of
3856 the instruction group) since the jump will not be moved around
3857 and thus its offset is accurate.
3859 First we need to figure out whether this jump is a forward or
3860 backward one; to do this we simply look at the ordinals of the
3861 group that contains the jump and the target.
3864 srcInstrOffs = jmpIG->igOffs + jmp->idjOffs;
3866 /* Note that the destination is always the beginning of an IG, so no need for an offset inside it */
3867 dstOffs = tgtIG->igOffs;
3869 #if defined(_TARGET_ARM_)
3871 srcInstrOffs + 4; // For relative branches, ARM PC is always considered to be the instruction address + 4
3872 #elif defined(_TARGET_ARM64_)
3874 srcInstrOffs; // For relative branches, ARM64 PC is always considered to be the instruction address
3876 srcEncodingOffs = srcInstrOffs + ssz; // Encoding offset of relative offset for small branch
3879 if (jmpIG->igNum < tgtIG->igNum)
3883 /* Adjust the target offset by the current delta. This is a worst-case estimate, as jumps between
3884 here and the target could be shortened, causing the actual distance to shrink.
3889 /* Compute the distance estimate */
3891 jmpDist = dstOffs - srcEncodingOffs;
3893 /* How much beyond the max. short distance does the jump go? */
3895 extra = jmpDist - psd;
3898 assert(jmp->idDebugOnlyInfo() != nullptr);
3899 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3901 if (INTERESTING_JUMP_NUM == 0)
3903 printf("[1] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3905 printf("[1] Jump block is at %08X\n", jmpIG->igOffs);
3906 printf("[1] Jump reloffset is %04X\n", jmp->idjOffs);
3907 printf("[1] Jump source is at %08X\n", srcEncodingOffs);
3908 printf("[1] Label block is at %08X\n", dstOffs);
3909 printf("[1] Jump dist. is %04X\n", jmpDist);
3912 printf("[1] Dist excess [S] = %d \n", extra);
3917 printf("Estimate of fwd jump [%08X/%03u]: %04X -> %04X = %04X\n", dspPtr(jmp),
3918 jmp->idDebugOnlyInfo()->idNum, srcInstrOffs, dstOffs, jmpDist);
3920 #endif // DEBUG_EMIT
3924 /* This jump will be a short one */
3932 /* Compute the distance estimate */
3934 jmpDist = srcEncodingOffs - dstOffs;
3936 /* How much beyond the max. short distance does the jump go? */
3938 extra = jmpDist + nsd;
3941 assert(jmp->idDebugOnlyInfo() != nullptr);
3942 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3944 if (INTERESTING_JUMP_NUM == 0)
3946 printf("[2] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3948 printf("[2] Jump block is at %08X\n", jmpIG->igOffs);
3949 printf("[2] Jump reloffset is %04X\n", jmp->idjOffs);
3950 printf("[2] Jump source is at %08X\n", srcEncodingOffs);
3951 printf("[2] Label block is at %08X\n", dstOffs);
3952 printf("[2] Jump dist. is %04X\n", jmpDist);
3955 printf("[2] Dist excess [S] = %d \n", extra);
3960 printf("Estimate of bwd jump [%08X/%03u]: %04X -> %04X = %04X\n", dspPtr(jmp),
3961 jmp->idDebugOnlyInfo()->idNum, srcInstrOffs, dstOffs, jmpDist);
3963 #endif // DEBUG_EMIT
3967 /* This jump will be a short one */
3972 /* We arrive here if the jump couldn't be made short, at least for now */
3974 /* We had better not have eagerly marked the jump as short
3975 * in emitIns_J(). If we did, then it has to be able to stay short
3976 * as emitIns_J() uses the worst case scenario, and blocks can
3977 * only move closer together after that.
3979 assert(jmp->idjShort == 0);
3981 /* Keep track of the closest distance we got */
3983 if (minShortExtra > (unsigned)extra)
3985 minShortExtra = (unsigned)extra;
3988 #if defined(_TARGET_ARM_)
3990 // If we're here, we couldn't convert to a small jump.
3991 // Handle conversion to medium-sized conditional jumps.
3992 // 'srcInstrOffs', 'srcEncodingOffs', 'dstOffs', 'jmpDist' have already been computed
3993 // and don't need to be recomputed.
3995 if (emitIsCondJump(jmp))
3997 if (jmpIG->igNum < tgtIG->igNum)
4001 /* How much beyond the max. medium distance does the jump go? */
4003 mextra = jmpDist - pmd;
4006 assert(jmp->idDebugOnlyInfo() != NULL);
4007 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4011 if (INTERESTING_JUMP_NUM == 0)
4012 printf("[6] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
4013 printf("[6] Dist excess [S] = %d \n", mextra);
4016 #endif // DEBUG_EMIT
4020 /* This jump will be a medium one */
4028 /* How much beyond the max. medium distance does the jump go? */
4030 mextra = jmpDist + nmd;
4033 assert(jmp->idDebugOnlyInfo() != NULL);
4034 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4038 if (INTERESTING_JUMP_NUM == 0)
4039 printf("[7] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
4040 printf("[7] Dist excess [S] = %d \n", mextra);
4043 #endif // DEBUG_EMIT
4047 /* This jump will be a medium one */
4052 /* We arrive here if the jump couldn't be made medium, at least for now */
4054 /* Keep track of the closest distance we got */
4056 if (minMediumExtra > (unsigned)mextra)
4057 minMediumExtra = (unsigned)mextra;
4060 #endif // _TARGET_ARM_
4062 /*****************************************************************************
4063 * We arrive here if the jump must stay long, at least for now.
4064 * Go try the next one.
4069 /*****************************************************************************/
4070 /* Handle conversion to short jump */
4071 /*****************************************************************************/
4075 /* Try to make this jump a short one */
4077 emitSetShortJump(jmp);
4081 continue; // This jump must be kept long
4084 /* This jump is becoming either short or medium */
4088 assert(oldSize >= jsz);
4089 sizeDif = oldSize - jsz;
4091 #if defined(_TARGET_XARCH_)
4092 jmp->idCodeSize(jsz);
4093 #elif defined(_TARGET_ARM_)
4095 // This is done as part of emitSetShortJump():
4096 insSize isz = emitInsSize(jmp->idInsFmt());
4097 jmp->idInsSize(isz);
4099 #elif defined(_TARGET_ARM64_)
4100 // The size of IF_LARGEJMP/IF_LARGEADR/IF_LARGELDC are 8 or 12.
4101 // All other code size is 4.
4102 assert((sizeDif == 4) || (sizeDif == 8));
4104 #error Unsupported or unset target architecture
4109 #if defined(_TARGET_ARM_)
4111 /*****************************************************************************/
4112 /* Handle conversion to medium jump */
4113 /*****************************************************************************/
4117 /* Try to make this jump a medium one */
4119 emitSetMediumJump(jmp);
4121 if (jmp->idCodeSize() > msz)
4123 continue; // This jump wasn't shortened
4125 assert(jmp->idCodeSize() == msz);
4127 /* This jump is becoming medium */
4131 assert(oldSize >= jsz);
4132 sizeDif = oldSize - jsz;
4136 #endif // _TARGET_ARM_
4138 /*****************************************************************************/
4142 /* Make sure the size of the jump is marked correctly */
4144 assert((0 == (jsz | jmpDist)) || (jsz == emitSizeOfJump(jmp)));
4149 printf("Shrinking jump [%08X/%03u]\n", dspPtr(jmp), jmp->idDebugOnlyInfo()->idNum);
4152 noway_assert((unsigned short)sizeDif == sizeDif);
4156 jmpIG->igSize -= (unsigned short)sizeDif;
4157 emitTotalCodeSize -= sizeDif;
4159 /* The jump size estimate wasn't accurate; flag its group */
4161 jmpIG->igFlags |= IGF_UPD_ISZ;
4163 } // end for each jump
4165 /* Did we shorten any jumps? */
4169 /* Adjust offsets of any remaining blocks */
4175 lstIG = lstIG->igNext;
4180 // printf("Adjusted offset of block %02u from %04X to %04X\n", lstIG->igNum, lstIG->igOffs,
4181 // lstIG->igOffs - adjIG);
4182 lstIG->igOffs -= adjIG;
4183 assert(IsCodeAligned(lstIG->igOffs));
4187 emitCheckIGoffsets();
4190 /* Is there a chance of other jumps becoming short? */
4191 CLANG_FORMAT_COMMENT_ANCHOR;
4193 #if defined(_TARGET_ARM_)
4195 printf("Total shrinkage = %3u, min extra short jump size = %3u, min extra medium jump size = %u\n", adjIG,
4196 minShortExtra, minMediumExtra);
4200 printf("Total shrinkage = %3u, min extra jump size = %3u\n", adjIG, minShortExtra);
4205 if ((minShortExtra <= adjIG)
4206 #if defined(_TARGET_ARM_)
4207 || (minMediumExtra <= adjIG)
4208 #endif // _TARGET_ARM_
4216 printf("Iterating branch shortening. Iteration = %d\n", jmp_iteration);
4225 void emitter::emitCheckFuncletBranch(instrDesc* jmp, insGroup* jmpIG)
4228 // We should not be jumping/branching across funclets/functions
4229 // Except possibly a 'call' to a finally funclet for a local unwind
4230 // or a 'return' from a catch handler (that can go just about anywhere)
4231 // This routine attempts to validate that any branches across funclets
4232 // meets one of those criteria...
4233 assert(jmp->idIsBound());
4235 #ifdef _TARGET_XARCH_
4236 // An lea of a code address (for constant data stored with the code)
4237 // is treated like a jump for emission purposes but is not really a jump so
4238 // we don't have to check anything here.
4239 if (jmp->idIns() == INS_lea)
4245 #ifdef _TARGET_ARMARCH_
4246 if (jmp->idAddr()->iiaHasInstrCount())
4248 // Too hard to figure out funclets from just an instruction count
4249 // You're on your own!
4252 #endif // _TARGET_ARMARCH_
4254 #ifdef _TARGET_ARM64_
4255 // No interest if it's not jmp.
4256 if (emitIsLoadLabel(jmp) || emitIsLoadConstant(jmp))
4260 #endif // _TARGET_ARM64_
4262 insGroup* tgtIG = jmp->idAddr()->iiaIGlabel;
4264 if (tgtIG->igFuncIdx != jmpIG->igFuncIdx)
4266 if (jmp->idDebugOnlyInfo()->idFinallyCall)
4268 // We don't record enough information to determine this accurately, so instead
4269 // we assume that any branch to the very start of a finally is OK.
4271 // No branches back to the root method
4272 assert(tgtIG->igFuncIdx > 0);
4273 FuncInfoDsc* tgtFunc = emitComp->funGetFunc(tgtIG->igFuncIdx);
4274 assert(tgtFunc->funKind == FUNC_HANDLER);
4275 EHblkDsc* tgtEH = emitComp->ehGetDsc(tgtFunc->funEHIndex);
4277 // Only branches to finallys (not faults, catches, filters, etc.)
4278 assert(tgtEH->HasFinallyHandler());
4280 // Only to the first block of the finally (which is properly marked)
4281 BasicBlock* tgtBlk = tgtEH->ebdHndBeg;
4282 assert(tgtBlk->bbFlags & BBF_FUNCLET_BEG);
4284 // And now we made it back to where we started
4285 assert(tgtIG == emitCodeGetCookie(tgtBlk));
4286 assert(tgtIG->igFuncIdx == emitComp->funGetFuncIdx(tgtBlk));
4288 else if (jmp->idDebugOnlyInfo()->idCatchRet)
4290 // Again there isn't enough information to prove this correct
4291 // so just allow a 'branch' to any other 'parent' funclet
4293 FuncInfoDsc* jmpFunc = emitComp->funGetFunc(jmpIG->igFuncIdx);
4294 assert(jmpFunc->funKind == FUNC_HANDLER);
4295 EHblkDsc* jmpEH = emitComp->ehGetDsc(jmpFunc->funEHIndex);
4297 // Only branches out of catches
4298 assert(jmpEH->HasCatchHandler());
4300 FuncInfoDsc* tgtFunc = emitComp->funGetFunc(tgtIG->igFuncIdx);
4302 if (tgtFunc->funKind == FUNC_HANDLER)
4304 // An outward chain to the containing funclet/EH handler
4305 // Note that it might be anywhere within nested try bodies
4306 assert(jmpEH->ebdEnclosingHndIndex == tgtFunc->funEHIndex);
4310 // This funclet is 'top level' and so it is branching back to the
4311 // root function, and should have no containing EH handlers
4312 // but it could be nested within try bodies...
4313 assert(tgtFunc->funKind == FUNC_ROOT);
4314 assert(jmpEH->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX);
4319 printf("Hit an illegal branch between funclets!");
4320 assert(tgtIG->igFuncIdx == jmpIG->igFuncIdx);
4326 /*****************************************************************************
4328 * Compute the code sizes that we're going to use to allocate the code buffers.
4332 * emitTotalHotCodeSize
4333 * emitTotalColdCodeSize
4334 * Compiler::info.compTotalHotCodeSize
4335 * Compiler::info.compTotalColdCodeSize
4338 void emitter::emitComputeCodeSizes()
4340 assert((emitComp->fgFirstColdBlock == nullptr) == (emitFirstColdIG == nullptr));
4342 if (emitFirstColdIG)
4344 emitTotalHotCodeSize = emitFirstColdIG->igOffs;
4345 emitTotalColdCodeSize = emitTotalCodeSize - emitTotalHotCodeSize;
4349 emitTotalHotCodeSize = emitTotalCodeSize;
4350 emitTotalColdCodeSize = 0;
4353 emitComp->info.compTotalHotCodeSize = emitTotalHotCodeSize;
4354 emitComp->info.compTotalColdCodeSize = emitTotalColdCodeSize;
4357 if (emitComp->verbose)
4359 printf("\nHot code size = 0x%X bytes\n", emitTotalHotCodeSize);
4360 printf("Cold code size = 0x%X bytes\n", emitTotalColdCodeSize);
4365 /*****************************************************************************
4367 * Called at the end of code generation, this method creates the code, data
4368 * and GC info blocks for the method. Returns the size of the method (which must fit in an unsigned).
4371 unsigned emitter::emitEndCodeGen(Compiler* comp,
4372 bool contTrkPtrLcls,
4376 unsigned xcptnsCount,
4377 unsigned* prologSize,
4378 unsigned* epilogSize,
4380 void** coldCodeAddr,
4384 if (emitComp->verbose)
4386 printf("*************** In emitEndCodeGen()\n");
4394 BYTE* coldCodeBlock;
4397 assert(emitCurIG == nullptr);
4399 emitCodeBlock = nullptr;
4400 emitConsBlock = nullptr;
4402 /* Tell everyone whether we have fully interruptible code or not */
4404 emitFullyInt = fullyInt;
4405 emitFullGCinfo = fullPtrMap;
4407 #ifndef UNIX_X86_ABI
4408 emitFullArgInfo = !emitHasFramePtr;
4410 emitFullArgInfo = fullPtrMap;
4414 GCrefsTable.record(emitGCrFrameOffsCnt);
4415 emitSizeTable.record(static_cast<unsigned>(emitSizeMethod));
4416 stkDepthTable.record(emitMaxStackDepth);
4417 #endif // EMITTER_STATS
4419 // Default values, correct even if EMIT_TRACK_STACK_DEPTH is 0.
4420 emitSimpleStkUsed = true;
4421 u1.emitSimpleStkMask = 0;
4422 u1.emitSimpleByrefStkMask = 0;
4424 #if EMIT_TRACK_STACK_DEPTH
4425 /* Convert max. stack depth from # of bytes to # of entries */
4427 unsigned maxStackDepthIn4ByteElements = emitMaxStackDepth / sizeof(int);
4428 JITDUMP("Converting emitMaxStackDepth from bytes (%d) to elements (%d)\n", emitMaxStackDepth,
4429 maxStackDepthIn4ByteElements);
4430 emitMaxStackDepth = maxStackDepthIn4ByteElements;
4432 /* Should we use the simple stack */
4434 if (emitMaxStackDepth > MAX_SIMPLE_STK_DEPTH || emitFullGCinfo)
4436 /* We won't use the "simple" argument table */
4438 emitSimpleStkUsed = false;
4440 /* Allocate the argument tracking table */
4442 if (emitMaxStackDepth <= sizeof(u2.emitArgTrackLcl))
4444 u2.emitArgTrackTab = (BYTE*)u2.emitArgTrackLcl;
4448 u2.emitArgTrackTab = (BYTE*)emitGetMem(roundUp(emitMaxStackDepth));
4451 u2.emitArgTrackTop = u2.emitArgTrackTab;
4452 u2.emitGcArgTrackCnt = 0;
4456 if (emitEpilogCnt == 0)
4458 /* No epilogs, make sure the epilog size is set to 0 */
4462 #ifdef _TARGET_XARCH_
4463 emitExitSeqSize = 0;
4464 #endif // _TARGET_XARCH_
4467 /* Return the size of the epilog to the caller */
4469 *epilogSize = emitEpilogSize;
4471 #ifdef _TARGET_XARCH_
4472 *epilogSize += emitExitSeqSize;
4473 #endif // _TARGET_XARCH_
4476 if (EMIT_INSTLIST_VERBOSE)
4478 printf("\nInstruction list before instruction issue:\n\n");
4479 emitDispIGlist(true);
4482 emitCheckIGoffsets();
4485 /* Allocate the code block (and optionally the data blocks) */
4487 // If we're doing procedure splitting and we found cold blocks, then
4488 // allocate hot and cold buffers. Otherwise only allocate a hot
4491 coldCodeBlock = nullptr;
4493 CorJitAllocMemFlag allocMemFlag = CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN;
4497 // These are the heuristics we use to decide whether or not to force the
4498 // code to be 16-byte aligned.
4500 // 1. For ngen code with IBC data, use 16-byte alignment if the method
4501 // has been called more than BB_VERY_HOT_WEIGHT times.
4502 // 2. For JITed code and ngen code without IBC data, use 16-byte alignment
4503 // when the code is 16 bytes or smaller. We align small getters/setters
4504 // because of they are penalized heavily on certain hardware when not 16-byte
4505 // aligned (VSWhidbey #373938). To minimize size impact of this optimization,
4506 // we do not align large methods because of the penalty is amortized for them.
4508 if (emitComp->fgHaveProfileData())
4510 if (emitComp->fgCalledCount > (BB_VERY_HOT_WEIGHT * emitComp->fgProfileRunsCount()))
4512 allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN;
4517 if (emitTotalHotCodeSize <= 16)
4519 allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN;
4524 #ifdef _TARGET_ARM64_
4525 // For arm64, we want to allocate JIT data always adjacent to code similar to what native compiler does.
4526 // This way allows us to use a single `ldr` to access such data like float constant/jmp table.
4527 if (emitTotalColdCodeSize > 0)
4529 // JIT data might be far away from the cold code.
4530 NYI_ARM64("Need to handle fix-up to data from cold code.");
4533 UNATIVE_OFFSET roDataAlignmentDelta = 0;
4534 if (emitConsDsc.dsdOffs)
4536 UNATIVE_OFFSET roDataAlignment = sizeof(void*); // 8 Byte align by default.
4537 roDataAlignmentDelta = (UNATIVE_OFFSET)ALIGN_UP(emitTotalHotCodeSize, roDataAlignment) - emitTotalHotCodeSize;
4538 assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4));
4540 emitCmpHandle->allocMem(emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs, emitTotalColdCodeSize, 0,
4541 xcptnsCount, allocMemFlag, (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock);
4543 consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta;
4546 emitCmpHandle->allocMem(emitTotalHotCodeSize, emitTotalColdCodeSize, emitConsDsc.dsdOffs, xcptnsCount, allocMemFlag,
4547 (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock);
4550 // if (emitConsDsc.dsdOffs)
4551 // printf("Cons=%08X\n", consBlock);
4553 /* Give the block addresses to the caller and other functions here */
4555 *codeAddr = emitCodeBlock = codeBlock;
4556 *coldCodeAddr = emitColdCodeBlock = coldCodeBlock;
4557 *consAddr = emitConsBlock = consBlock;
4559 /* Nothing has been pushed on the stack */
4560 CLANG_FORMAT_COMMENT_ANCHOR;
4562 #if EMIT_TRACK_STACK_DEPTH
4563 emitCurStackLvl = 0;
4566 /* Assume no live GC ref variables on entry */
4568 VarSetOps::OldStyleClearD(emitComp, emitThisGCrefVars); // This is initialized to Empty at the start of codegen.
4569 emitThisGCrefRegs = emitThisByrefRegs = RBM_NONE;
4570 emitThisGCrefVset = true;
4576 // We don't use these after this point
4578 VarSetOps::AssignNoCopy(emitComp, emitPrevGCrefVars, VarSetOps::UninitVal());
4579 emitPrevGCrefRegs = emitPrevByrefRegs = 0xBAADFEED;
4581 VarSetOps::AssignNoCopy(emitComp, emitInitGCrefVars, VarSetOps::UninitVal());
4582 emitInitGCrefRegs = emitInitByrefRegs = 0xBAADFEED;
4586 /* Initialize the GC ref variable lifetime tracking logic */
4588 codeGen->gcInfo.gcVarPtrSetInit();
4590 emitSyncThisObjOffs = -1; /* -1 means no offset set */
4591 emitSyncThisObjReg = REG_NA; /* REG_NA means not set */
4593 #ifdef JIT32_GCENCODER
4594 if (emitComp->lvaKeepAliveAndReportThis())
4596 assert(emitComp->lvaIsOriginalThisArg(0));
4597 LclVarDsc* thisDsc = &emitComp->lvaTable[0];
4599 /* If "this" (which is passed in as a register argument in REG_ARG_0)
4600 is enregistered, we normally spot the "mov REG_ARG_0 -> thisReg"
4601 in the prolog and note the location of "this" at that point.
4602 However, if 'this' is enregistered into REG_ARG_0 itself, no code
4603 will be generated in the prolog, so we explicitly need to note
4604 the location of "this" here.
4605 NOTE that we can do this even if "this" is not enregistered in
4606 REG_ARG_0, and it will result in more accurate "this" info over the
4607 prolog. However, as methods are not interruptible over the prolog,
4608 we try to save space by avoiding that.
4611 if (thisDsc->lvRegister)
4613 emitSyncThisObjReg = thisDsc->lvRegNum;
4615 if (emitSyncThisObjReg == (int)REG_ARG_0 &&
4616 (codeGen->intRegState.rsCalleeRegArgMaskLiveIn & genRegMask(REG_ARG_0)))
4620 emitGCregLiveSet(GCT_GCREF, genRegMask(REG_ARG_0),
4621 emitCodeBlock, // from offset 0
4626 /* If emitFullGCinfo==false, the we don't use any
4627 regPtrDsc's and so explictly note the location
4628 of "this" in GCEncode.cpp
4634 #endif // JIT32_GCENCODER
4636 emitContTrkPtrLcls = contTrkPtrLcls;
4638 /* Are there any GC ref variables on the stack? */
4640 if (emitGCrFrameOffsCnt)
4648 /* Allocate and clear emitGCrFrameLiveTab[]. This is the table
4649 mapping "stkOffs -> varPtrDsc". It holds a pointer to
4650 the liveness descriptor that was created when the
4651 variable became alive. When the variable becomes dead, the
4652 descriptor will be appended to the liveness descriptor list, and
4653 the entry in emitGCrFrameLiveTab[] will be made NULL.
4655 Note that if all GC refs are assigned consecutively,
4656 emitGCrFrameLiveTab[] can be only as big as the number of GC refs
4657 present, instead of lvaTrackedCount.
4660 siz = emitGCrFrameOffsCnt * sizeof(*emitGCrFrameLiveTab);
4661 emitGCrFrameLiveTab = (varPtrDsc**)emitGetMem(roundUp(siz));
4662 memset(emitGCrFrameLiveTab, 0, siz);
4664 /* Allocate and fill in emitGCrFrameOffsTab[]. This is the table
4665 mapping "varIndex -> stkOffs".
4666 Non-ptrs or reg vars have entries of -1.
4667 Entries of Tracked stack byrefs have the lower bit set to 1.
4670 emitTrkVarCnt = cnt = emitComp->lvaTrackedCount;
4672 emitGCrFrameOffsTab = tab = (int*)emitGetMem(cnt * sizeof(int));
4674 memset(emitGCrFrameOffsTab, -1, cnt * sizeof(int));
4676 /* Now fill in all the actual used entries */
4678 for (num = 0, dsc = emitComp->lvaTable, cnt = emitComp->lvaCount; num < cnt; num++, dsc++)
4680 if (!dsc->lvOnFrame || (dsc->lvIsParam && !dsc->lvIsRegArg))
4685 #if FEATURE_FIXED_OUT_ARGS
4686 if (num == emitComp->lvaOutgoingArgSpaceVar)
4690 #endif // FEATURE_FIXED_OUT_ARGS
4692 int offs = dsc->lvStkOffs;
4694 /* Is it within the interesting range of offsets */
4696 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
4698 /* Are tracked stack ptr locals laid out contiguously?
4699 If not, skip non-ptrs. The emitter is optimized to work
4700 with contiguous ptrs, but for EditNContinue, the variables
4701 are laid out in the order they occur in the local-sig.
4704 if (!emitContTrkPtrLcls)
4706 if (!emitComp->lvaIsGCTracked(dsc))
4712 unsigned indx = dsc->lvVarIndex;
4714 assert(!dsc->lvRegister);
4715 assert(dsc->lvTracked);
4716 assert(dsc->lvRefCnt != 0);
4718 assert(dsc->TypeGet() == TYP_REF || dsc->TypeGet() == TYP_BYREF);
4720 assert(indx < emitComp->lvaTrackedCount);
4722 // printf("Variable #%2u/%2u is at stack offset %d\n", num, indx, offs);
4724 #ifdef JIT32_GCENCODER
4725 #ifndef WIN64EXCEPTIONS
4726 /* Remember the frame offset of the "this" argument for synchronized methods */
4727 if (emitComp->lvaIsOriginalThisArg(num) && emitComp->lvaKeepAliveAndReportThis())
4729 emitSyncThisObjOffs = offs;
4730 offs |= this_OFFSET_FLAG;
4733 #endif // JIT32_GCENCODER
4735 if (dsc->TypeGet() == TYP_BYREF)
4737 offs |= byref_OFFSET_FLAG;
4747 emitGCrFrameOffsTab = nullptr;
4752 if (emitComp->verbose)
4754 printf("\n***************************************************************************\n");
4755 printf("Instructions as they come out of the scheduler\n\n");
4759 /* Issue all instruction groups in order */
4762 #define DEFAULT_CODE_BUFFER_INIT 0xcc
4764 for (ig = emitIGlist; ig; ig = ig->igNext)
4766 assert(!(ig->igFlags & IGF_PLACEHOLDER)); // There better not be any placeholder groups left
4768 /* Is this the first cold block? */
4769 if (ig == emitFirstColdIG)
4771 unsigned actualHotCodeSize = emitCurCodeOffs(cp);
4773 /* Fill in eventual unused space */
4774 while (emitCurCodeOffs(cp) < emitTotalHotCodeSize)
4776 *cp++ = DEFAULT_CODE_BUFFER_INIT;
4779 assert(coldCodeBlock);
4782 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
4784 printf("\n************** Beginning of cold code **************\n");
4789 /* Are we overflowing? */
4790 if (ig->igNext && ig->igNum + 1 != ig->igNext->igNum)
4792 NO_WAY("Too many instruction groups");
4795 // If this instruction group is returned to from a funclet implementing a finally,
4796 // on architectures where it is necessary generate GC info for the current instruction as
4797 // if it were the instruction following a call.
4798 emitGenGCInfoIfFuncletRetTarget(ig, cp);
4800 instrDesc* id = (instrDesc*)ig->igData;
4804 /* Print the IG label, but only if it is a branch label */
4806 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
4808 if (emitComp->verbose)
4811 emitDispIG(ig); // Display the flags, IG data, etc.
4815 printf("\nG_M%03u_IG%02u:\n", Compiler::s_compMethodsCount, ig->igNum);
4823 /* Record the actual offset of the block, noting the difference */
4825 emitOffsAdj = ig->igOffs - emitCurCodeOffs(cp);
4826 assert(emitOffsAdj >= 0);
4829 if ((emitOffsAdj != 0) && emitComp->verbose)
4831 printf("Block predicted offs = %08X, actual = %08X -> size adj = %d\n", ig->igOffs, emitCurCodeOffs(cp),
4834 #endif // DEBUG_EMIT
4836 ig->igOffs = emitCurCodeOffs(cp);
4837 assert(IsCodeAligned(ig->igOffs));
4839 #if EMIT_TRACK_STACK_DEPTH
4841 /* Set the proper stack level if appropriate */
4843 if (ig->igStkLvl != emitCurStackLvl)
4845 /* We are pushing stuff implicitly at this label */
4847 assert((unsigned)ig->igStkLvl > (unsigned)emitCurStackLvl);
4848 emitStackPushN(cp, (ig->igStkLvl - (unsigned)emitCurStackLvl) / sizeof(int));
4853 /* Update current GC information for non-overflow IG (not added implicitly by the emitter) */
4855 if (!(ig->igFlags & IGF_EMIT_ADD))
4857 /* Is there a new set of live GC ref variables? */
4859 if (ig->igFlags & IGF_GC_VARS)
4861 emitUpdateLiveGCvars(ig->igGCvars(), cp);
4863 else if (!emitThisGCrefVset)
4865 emitUpdateLiveGCvars(emitThisGCrefVars, cp);
4868 /* Update the set of live GC ref registers */
4871 regMaskTP GCregs = ig->igGCregs;
4873 if (GCregs != emitThisGCrefRegs)
4875 emitUpdateLiveGCregs(GCT_GCREF, GCregs, cp);
4879 /* Is there a new set of live byref registers? */
4881 if (ig->igFlags & IGF_BYREF_REGS)
4883 unsigned byrefRegs = ig->igByrefRegs();
4885 if (byrefRegs != emitThisByrefRegs)
4887 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, cp);
4893 // These are not set for "overflow" groups
4894 assert(!(ig->igFlags & IGF_GC_VARS));
4895 assert(!(ig->igFlags & IGF_BYREF_REGS));
4898 /* Issue each instruction in order */
4902 for (unsigned cnt = ig->igInsCnt; cnt; cnt--)
4904 castto(id, BYTE*) += emitIssue1Instr(ig, id, &cp);
4907 emitCurIG = nullptr;
4909 assert(ig->igSize >= cp - bp);
4910 ig->igSize = (unsigned short)(cp - bp);
4913 #if EMIT_TRACK_STACK_DEPTH
4914 assert(emitCurStackLvl == 0);
4917 /* Output any initialized data we may have */
4919 if (emitConsDsc.dsdOffs)
4921 emitOutputDataSec(&emitConsDsc, consBlock);
4924 /* Make sure all GC ref variables are marked as dead */
4926 if (emitGCrFrameOffsCnt)
4932 for (vn = 0, of = emitGCrFrameOffsMin, dp = emitGCrFrameLiveTab; vn < emitGCrFrameOffsCnt;
4933 vn++, of += sizeof(void*), dp++)
4937 emitGCvarDeadSet(of, cp, vn);
4942 /* No GC registers are live any more */
4944 if (emitThisByrefRegs)
4946 emitUpdateLiveGCregs(GCT_BYREF, RBM_NONE, cp);
4948 if (emitThisGCrefRegs)
4950 emitUpdateLiveGCregs(GCT_GCREF, RBM_NONE, cp);
4953 /* Patch any forward jumps */
4959 for (jmp = emitJumpList; jmp; jmp = jmp->idjNext)
4962 #ifdef _TARGET_XARCH_
4963 assert(jmp->idInsFmt() == IF_LABEL || jmp->idInsFmt() == IF_RWR_LABEL || jmp->idInsFmt() == IF_SWR_LABEL);
4965 tgt = jmp->idAddr()->iiaIGlabel;
4967 if (jmp->idjTemp.idjAddr == nullptr)
4972 if (jmp->idjOffs != tgt->igOffs)
4974 BYTE* adr = jmp->idjTemp.idjAddr;
4975 int adj = jmp->idjOffs - tgt->igOffs;
4977 // On Arm, the offset is encoded in unit of 2 bytes.
4982 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4985 printf("[5] This output is broken for ARM, since it doesn't properly decode the jump offsets of "
4986 "the instruction at adr\n");
4989 if (INTERESTING_JUMP_NUM == 0)
4991 printf("[5] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
4996 printf("[5] Jump is at %08X\n", (adr + 1 - emitCodeBlock));
4997 printf("[5] Jump distance is %02X - %02X = %02X\n", *(BYTE*)adr, adj, *(BYTE*)adr - adj);
5001 printf("[5] Jump is at %08X\n", (adr + 4 - emitCodeBlock));
5002 printf("[5] Jump distance is %08X - %02X = %08X\n", *(int*)adr, adj, *(int*)adr - adj);
5005 #endif // DEBUG_EMIT
5009 // Patch Forward Short Jump
5010 CLANG_FORMAT_COMMENT_ANCHOR;
5011 #if defined(_TARGET_XARCH_)
5012 *(BYTE*)adr -= (BYTE)adj;
5013 #elif defined(_TARGET_ARM_)
5014 // The following works because the jump offset is in the low order bits of the instruction.
5015 // Presumably we could also just call "emitOutputLJ(NULL, adr, jmp)", like for long jumps?
5016 *(short int*)adr -= (short)adj;
5017 #elif defined(_TARGET_ARM64_)
5018 assert(!jmp->idAddr()->iiaHasInstrCount());
5019 emitOutputLJ(NULL, adr, jmp);
5021 #error Unsupported or unset target architecture
5026 // Patch Forward non-Short Jump
5027 CLANG_FORMAT_COMMENT_ANCHOR;
5028 #if defined(_TARGET_XARCH_)
5030 #elif defined(_TARGET_ARMARCH_)
5031 assert(!jmp->idAddr()->iiaHasInstrCount());
5032 emitOutputLJ(NULL, adr, jmp);
5034 #error Unsupported or unset target architecture
5042 if (emitComp->opts.disAsm)
5047 if (emitComp->verbose)
5049 printf("Allocated method code size = %4u , actual size = %4u\n", emitTotalCodeSize, cp - codeBlock);
5053 unsigned actualCodeSize = emitCurCodeOffs(cp);
5055 /* Fill in eventual unused space */
5056 while (emitCurCodeOffs(cp) < emitTotalCodeSize)
5058 *cp++ = DEFAULT_CODE_BUFFER_INIT;
5062 totAllocdSize += emitTotalCodeSize;
5063 totActualSize += actualCodeSize;
5068 // Make sure these didn't change during the "issuing" phase
5070 assert(VarSetOps::MayBeUninit(emitPrevGCrefVars));
5071 assert(emitPrevGCrefRegs == 0xBAADFEED);
5072 assert(emitPrevByrefRegs == 0xBAADFEED);
5074 assert(VarSetOps::MayBeUninit(emitInitGCrefVars));
5075 assert(emitInitGCrefRegs == 0xBAADFEED);
5076 assert(emitInitByrefRegs == 0xBAADFEED);
5080 // Assign the real prolog size
5081 *prologSize = emitCodeOffset(emitPrologIG, emitPrologEndPos);
5083 /* Return the amount of code we've generated */
5085 return actualCodeSize;
5088 // See specification comment at the declaration.
5089 void emitter::emitGenGCInfoIfFuncletRetTarget(insGroup* ig, BYTE* cp)
5091 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
5092 // We only emit this GC information on targets where finally's are implemented via funclets,
5093 // and the finally is invoked, during non-exceptional execution, via a branch with a predefined
5094 // link register, rather than a "true call" for which we would already generate GC info. Currently,
5095 // this means precisely ARM.
5096 if (ig->igFlags & IGF_FINALLY_TARGET)
5098 // We don't actually have a call instruction in this case, so we don't have
5099 // a real size for that instruction. We'll use 1.
5100 emitStackPop(cp, /*isCall*/ true, /*callInstrSize*/ 1, /*args*/ 0);
5102 /* Do we need to record a call location for GC purposes? */
5103 if (!emitFullGCinfo)
5105 emitRecordGCcall(cp, /*callInstrSize*/ 1);
5108 #endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
5111 /*****************************************************************************
5113 * We have an instruction in an insGroup and we need to know the
5114 * instruction number for this instruction
5117 unsigned emitter::emitFindInsNum(insGroup* ig, instrDesc* idMatch)
5119 instrDesc* id = (instrDesc*)ig->igData;
5121 // Check if we are the first instruction in the group
5127 /* Walk the list of instructions until we find a match */
5128 unsigned insNum = 0;
5129 unsigned insRemaining = ig->igInsCnt;
5131 while (insRemaining > 0)
5133 castto(id, BYTE*) += emitSizeOfInsDsc(id);
5142 assert(!"emitFindInsNum failed");
5146 /*****************************************************************************
5148 * We've been asked for the code offset of an instruction but alas one or
5149 * more instruction sizes in the block have been mis-predicted, so we have
5150 * to find the true offset by looking for the instruction within the group.
5153 UNATIVE_OFFSET emitter::emitFindOffset(insGroup* ig, unsigned insNum)
5155 instrDesc* id = (instrDesc*)ig->igData;
5156 UNATIVE_OFFSET of = 0;
5159 /* Make sure we were passed reasonable arguments */
5160 assert(ig && ig->igSelf == ig);
5161 assert(ig->igInsCnt >= insNum);
5164 /* Walk the instruction list until all are counted */
5168 of += emitInstCodeSz(id);
5170 castto(id, BYTE*) += emitSizeOfInsDsc(id);
5178 /*****************************************************************************
5180 * Start generating a constant data section for the current
5181 * function. Returns the offset of the section in the appropriate data
5185 UNATIVE_OFFSET emitter::emitDataGenBeg(UNATIVE_OFFSET size, bool dblAlign, bool codeLtab)
5188 dataSection* secDesc;
5190 assert(emitDataSecCur == nullptr);
5192 /* The size better not be some kind of an odd thing */
5194 assert(size && size % sizeof(int) == 0);
5196 /* Get hold of the current offset */
5198 secOffs = emitConsDsc.dsdOffs;
5200 /* Are we require to align this request on an eight byte boundry? */
5201 if (dblAlign && (secOffs % sizeof(double) != 0))
5203 /* Need to skip 4 bytes to honor dblAlign */
5204 /* Must allocate a dummy 4 byte integer */
5206 emitDataGenBeg(4, false, false);
5207 emitDataGenData(0, &zero, 4);
5210 /* Get the new secOffs */
5211 secOffs = emitConsDsc.dsdOffs;
5212 /* Now it should be a multiple of 8 */
5213 assert(secOffs % sizeof(double) == 0);
5216 /* Advance the current offset */
5218 emitConsDsc.dsdOffs += size;
5220 /* Allocate a data section descriptor and add it to the list */
5222 secDesc = emitDataSecCur = (dataSection*)emitGetMem(roundUp(sizeof(*secDesc) + size));
5224 secDesc->dsSize = size;
5226 secDesc->dsType = dataSection::data;
5228 secDesc->dsNext = nullptr;
5230 if (emitConsDsc.dsdLast)
5232 emitConsDsc.dsdLast->dsNext = secDesc;
5236 emitConsDsc.dsdList = secDesc;
5238 emitConsDsc.dsdLast = secDesc;
5243 // Start generating a constant data section for the current function
5244 // populated with BasicBlock references.
5245 // You can choose the references to be either absolute pointers, or
5246 // 4-byte relative addresses.
5247 // Currently the relative references are relative to the start of the
5248 // first block (this is somewhat arbitrary)
5250 UNATIVE_OFFSET emitter::emitBBTableDataGenBeg(unsigned numEntries, bool relativeAddr)
5253 dataSection* secDesc;
5255 assert(emitDataSecCur == nullptr);
5257 UNATIVE_OFFSET emittedSize;
5261 emittedSize = numEntries * 4;
5265 emittedSize = numEntries * TARGET_POINTER_SIZE;
5268 /* Get hold of the current offset */
5270 secOffs = emitConsDsc.dsdOffs;
5272 /* Advance the current offset */
5274 emitConsDsc.dsdOffs += emittedSize;
5276 /* Allocate a data section descriptor and add it to the list */
5278 secDesc = emitDataSecCur = (dataSection*)emitGetMem(roundUp(sizeof(*secDesc) + numEntries * sizeof(BasicBlock*)));
5280 secDesc->dsSize = emittedSize;
5282 secDesc->dsType = relativeAddr ? dataSection::blockRelative32 : dataSection::blockAbsoluteAddr;
5284 secDesc->dsNext = nullptr;
5286 if (emitConsDsc.dsdLast)
5288 emitConsDsc.dsdLast->dsNext = secDesc;
5292 emitConsDsc.dsdList = secDesc;
5295 emitConsDsc.dsdLast = secDesc;
5300 /*****************************************************************************
5302 * Emit the given block of bits into the current data section.
5305 void emitter::emitDataGenData(unsigned offs, const void* data, size_t size)
5307 assert(emitDataSecCur && (emitDataSecCur->dsSize >= offs + size));
5309 assert(emitDataSecCur->dsType == dataSection::data);
5311 memcpy(emitDataSecCur->dsCont + offs, data, size);
5314 /*****************************************************************************
5316 * Emit the address of the given basic block into the current data section.
5319 void emitter::emitDataGenData(unsigned index, BasicBlock* label)
5321 assert(emitDataSecCur != nullptr);
5322 assert(emitDataSecCur->dsType == dataSection::blockAbsoluteAddr ||
5323 emitDataSecCur->dsType == dataSection::blockRelative32);
5325 unsigned emittedElemSize = emitDataSecCur->dsType == dataSection::blockAbsoluteAddr ? TARGET_POINTER_SIZE : 4;
5327 assert(emitDataSecCur->dsSize >= emittedElemSize * (index + 1));
5329 ((BasicBlock**)(emitDataSecCur->dsCont))[index] = label;
5332 /*****************************************************************************
5334 * We're done generating a data section.
5337 void emitter::emitDataGenEnd()
5341 assert(emitDataSecCur);
5342 emitDataSecCur = nullptr;
5346 /********************************************************************************
5347 * Generates a data section constant
5350 * cnsAddr - memory location containing constant value
5351 * cnsSize - size of constant in bytes
5352 * dblAlign - whether to double align the data section constant
5354 * Returns constant number as offset into data section.
5356 UNATIVE_OFFSET emitter::emitDataConst(const void* cnsAddr, unsigned cnsSize, bool dblAlign)
5358 // When generating SMALL_CODE, we don't bother with dblAlign
5359 if (dblAlign && (emitComp->compCodeOpt() == Compiler::SMALL_CODE))
5364 UNATIVE_OFFSET cnum = emitDataGenBeg(cnsSize, dblAlign, false);
5365 emitDataGenData(0, cnsAddr, cnsSize);
5371 /*****************************************************************************
5373 * Output the given data section at the specified address.
5376 void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst)
5381 printf("\nEmitting data sections: %u total bytes\n", sec->dsdOffs);
5384 unsigned secNum = 0;
5388 assert(sec->dsdOffs);
5389 assert(sec->dsdList);
5391 /* Walk and emit the contents of all the data blocks */
5395 for (dsc = sec->dsdList; dsc; dsc = dsc->dsNext)
5397 size_t dscSize = dsc->dsSize;
5399 // absolute label table
5400 if (dsc->dsType == dataSection::blockAbsoluteAddr)
5402 JITDUMP(" section %u, size %u, block absolute addr\n", secNum++, dscSize);
5404 assert(dscSize && dscSize % sizeof(BasicBlock*) == 0);
5405 size_t numElems = dscSize / TARGET_POINTER_SIZE;
5406 BYTE** bDst = (BYTE**)dst;
5407 for (unsigned i = 0; i < numElems; i++)
5409 BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i];
5411 // Convert the BasicBlock* value to an IG address
5412 insGroup* lab = (insGroup*)emitCodeGetCookie(block);
5414 // Append the appropriate address to the destination
5415 BYTE* target = emitOffsetToPtr(lab->igOffs);
5418 target = (BYTE*)((size_t)target | 1); // Or in thumb bit
5421 if (emitComp->opts.compReloc)
5423 emitRecordRelocation(&(bDst[i]), target, IMAGE_REL_BASED_HIGHLOW);
5426 JITDUMP(" BB%02u: 0x%p\n", block->bbNum, bDst[i]);
5429 // relative label table
5430 else if (dsc->dsType == dataSection::blockRelative32)
5432 JITDUMP(" section %u, size %u, block relative addr\n", secNum++, dscSize);
5434 unsigned elemSize = 4;
5435 size_t numElems = dscSize / 4;
5436 unsigned* uDst = (unsigned*)dst;
5437 insGroup* labFirst = (insGroup*)emitCodeGetCookie(emitComp->fgFirstBB);
5439 for (unsigned i = 0; i < numElems; i++)
5441 BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i];
5443 // Convert the BasicBlock* value to an IG address
5444 insGroup* lab = (insGroup*)emitCodeGetCookie(block);
5446 assert(FitsIn<uint32_t>(lab->igOffs - labFirst->igOffs));
5447 uDst[i] = lab->igOffs - labFirst->igOffs;
5449 JITDUMP(" BB%02u: 0x%x\n", block->bbNum, uDst[i]);
5454 JITDUMP(" section %u, size %u, raw data\n", secNum++, dscSize);
5456 // Simple binary data: copy the bytes to the target
5457 assert(dsc->dsType == dataSection::data);
5459 memcpy(dst, dsc->dsCont, dscSize);
5465 for (size_t i = 0; i < dscSize; i++)
5467 printf("%02x ", dsc->dsCont[i]);
5468 if ((((i + 1) % 16) == 0) && (i + 1 != dscSize))
5481 /*****************************************************************************/
5482 /*****************************************************************************
5484 * Record the fact that the given variable now contains a live GC ref.
5487 void emitter::emitGCvarLiveSet(int offs, GCtype gcType, BYTE* addr, ssize_t disp)
5489 assert(emitIssuing);
5493 assert((abs(offs) % sizeof(ssize_t)) == 0);
5494 assert(needsGC(gcType));
5496 /* Compute the index into the GC frame table if the caller didn't do it */
5500 disp = (offs - emitGCrFrameOffsMin) / sizeof(void*);
5503 assert((size_t)disp < emitGCrFrameOffsCnt);
5505 /* Allocate a lifetime record */
5507 desc = new (emitComp, CMK_GC) varPtrDsc;
5509 desc->vpdBegOfs = emitCurCodeOffs(addr);
5511 desc->vpdEndOfs = 0xFACEDEAD;
5514 desc->vpdVarNum = offs;
5516 desc->vpdNext = nullptr;
5518 #if !defined(JIT32_GCENCODER) || !defined(WIN64EXCEPTIONS)
5519 /* the lower 2 bits encode props about the stk ptr */
5521 if (offs == emitSyncThisObjOffs)
5523 desc->vpdVarNum |= this_OFFSET_FLAG;
5527 if (gcType == GCT_BYREF)
5529 desc->vpdVarNum |= byref_OFFSET_FLAG;
5532 /* Append the new entry to the end of the list */
5533 if (codeGen->gcInfo.gcVarPtrLast == nullptr)
5535 assert(codeGen->gcInfo.gcVarPtrList == nullptr);
5536 codeGen->gcInfo.gcVarPtrList = codeGen->gcInfo.gcVarPtrLast = desc;
5540 assert(codeGen->gcInfo.gcVarPtrList != nullptr);
5541 codeGen->gcInfo.gcVarPtrLast->vpdNext = desc;
5542 codeGen->gcInfo.gcVarPtrLast = desc;
5545 /* Record the variable descriptor in the table */
5547 assert(emitGCrFrameLiveTab[disp] == nullptr);
5548 emitGCrFrameLiveTab[disp] = desc;
5553 printf("[%08X] %s var born at [%s", dspPtr(desc), GCtypeStr(gcType), emitGetFrameReg());
5557 printf("-%02XH", -offs);
5561 printf("+%02XH", +offs);
5568 /* The "global" live GC variable mask is no longer up-to-date */
5570 emitThisGCrefVset = false;
5573 /*****************************************************************************
5575 * Record the fact that the given variable no longer contains a live GC ref.
5578 void emitter::emitGCvarDeadSet(int offs, BYTE* addr, ssize_t disp)
5580 assert(emitIssuing);
5584 assert(abs(offs) % sizeof(int) == 0);
5586 /* Compute the index into the GC frame table if the caller didn't do it */
5590 disp = (offs - emitGCrFrameOffsMin) / sizeof(void*);
5593 assert((unsigned)disp < emitGCrFrameOffsCnt);
5595 /* Get hold of the lifetime descriptor and clear the entry */
5597 desc = emitGCrFrameLiveTab[disp];
5598 emitGCrFrameLiveTab[disp] = nullptr;
5601 assert((desc->vpdVarNum & ~OFFSET_MASK) == (unsigned)offs);
5603 /* Record the death code offset */
5605 assert(desc->vpdEndOfs == 0xFACEDEAD);
5606 desc->vpdEndOfs = emitCurCodeOffs(addr);
5611 GCtype gcType = (desc->vpdVarNum & byref_OFFSET_FLAG) ? GCT_BYREF : GCT_GCREF;
5612 #if !defined(JIT32_GCENCODER) || !defined(WIN64EXCEPTIONS)
5613 bool isThis = (desc->vpdVarNum & this_OFFSET_FLAG) != 0;
5615 printf("[%08X] %s%s var died at [%s", dspPtr(desc), GCtypeStr(gcType), isThis ? "this-ptr" : "",
5618 bool isPinned = (desc->vpdVarNum & pinned_OFFSET_FLAG) != 0;
5620 printf("[%08X] %s%s var died at [%s", dspPtr(desc), GCtypeStr(gcType), isPinned ? "pinned" : "",
5626 printf("-%02XH", -offs);
5630 printf("+%02XH", +offs);
5637 /* The "global" live GC variable mask is no longer up-to-date */
5639 emitThisGCrefVset = false;
5642 /*****************************************************************************
5644 * Record a new set of live GC ref variables.
5647 void emitter::emitUpdateLiveGCvars(VARSET_VALARG_TP vars, BYTE* addr)
5649 assert(emitIssuing);
5651 // Don't track GC changes in epilogs
5652 if (emitIGisInEpilog(emitCurIG))
5657 /* Is the current set accurate and unchanged? */
5659 if (emitThisGCrefVset && VarSetOps::Equal(emitComp, emitThisGCrefVars, vars))
5665 if (EMIT_GC_VERBOSE)
5667 printf("New GC ref live vars=%s ", VarSetOps::ToString(emitComp, vars));
5668 dumpConvertedVarSet(emitComp, vars);
5673 VarSetOps::Assign(emitComp, emitThisGCrefVars, vars);
5675 /* Are there any GC ref variables on the stack? */
5677 if (emitGCrFrameOffsCnt)
5680 unsigned cnt = emitTrkVarCnt;
5683 /* Test all the tracked variable bits in the mask */
5685 for (num = 0, tab = emitGCrFrameOffsTab; num < cnt; num++, tab++)
5691 // byref_OFFSET_FLAG and this_OFFSET_FLAG are set
5692 // in the table-offsets for byrefs and this-ptr
5694 int offs = val & ~OFFSET_MASK;
5696 // printf("var #%2u at %3d is now %s\n", num, offs, (vars & 1) ? "live" : "dead");
5698 if (VarSetOps::IsMember(emitComp, vars, num))
5700 GCtype gcType = (val & byref_OFFSET_FLAG) ? GCT_BYREF : GCT_GCREF;
5701 emitGCvarLiveUpd(offs, INT_MAX, gcType, addr);
5705 emitGCvarDeadUpd(offs, addr);
5711 emitThisGCrefVset = true;
5714 /*****************************************************************************
5716 * Record a call location for GC purposes (we know that this is a method that
5717 * will not be fully interruptible).
5720 void emitter::emitRecordGCcall(BYTE* codePos, unsigned char callInstrSize)
5722 assert(emitIssuing);
5723 assert(!emitFullGCinfo);
5725 unsigned offs = emitCurCodeOffs(codePos);
5726 unsigned regs = (emitThisGCrefRegs | emitThisByrefRegs) & ~RBM_INTRET;
5729 #ifdef JIT32_GCENCODER
5730 // The JIT32 GCInfo encoder allows us to (as the comment previously here said):
5731 // "Bail if this is a totally boring call", but the GCInfoEncoder/Decoder interface
5732 // requires a definition for every call site, so we skip these "early outs" when we're
5733 // using the general encoder.
5736 #if EMIT_TRACK_STACK_DEPTH
5737 if (emitCurStackLvl == 0)
5740 /* Nope, only interesting calls get recorded */
5742 if (emitSimpleStkUsed)
5744 if (!u1.emitSimpleStkMask)
5749 if (u2.emitGcArgTrackCnt == 0)
5753 #endif // JIT32_GCENCODER
5757 if (EMIT_GC_VERBOSE)
5759 printf("; Call at %04X [stk=%u], GCvars=", offs - callInstrSize, emitCurStackLvl);
5761 printf(", gcrefRegs=");
5762 printRegMaskInt(emitThisGCrefRegs);
5763 emitDispRegSet(emitThisGCrefRegs);
5764 // printRegMaskInt(emitThisGCrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5765 // emitDispRegSet (emitThisGCrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5766 printf(", byrefRegs=");
5767 printRegMaskInt(emitThisByrefRegs);
5768 emitDispRegSet(emitThisByrefRegs);
5769 // printRegMaskInt(emitThisByrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5770 // emitDispRegSet (emitThisByrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5776 /* Allocate a 'call site' descriptor and start filling it in */
5778 call = new (emitComp, CMK_GC) callDsc;
5780 call->cdBlock = nullptr;
5781 call->cdOffs = offs;
5782 #ifndef JIT32_GCENCODER
5783 call->cdCallInstrSize = callInstrSize;
5785 call->cdNext = nullptr;
5787 call->cdGCrefRegs = (regMaskSmall)emitThisGCrefRegs;
5788 call->cdByrefRegs = (regMaskSmall)emitThisByrefRegs;
5790 #if EMIT_TRACK_STACK_DEPTH
5791 #ifndef FEATURE_UNIX_AMD64_STRUCT_PASSING
5792 noway_assert(FitsIn<USHORT>(emitCurStackLvl / ((unsigned)sizeof(unsigned))));
5793 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
5796 // Append the call descriptor to the list */
5797 if (codeGen->gcInfo.gcCallDescLast == nullptr)
5799 assert(codeGen->gcInfo.gcCallDescList == nullptr);
5800 codeGen->gcInfo.gcCallDescList = codeGen->gcInfo.gcCallDescLast = call;
5804 assert(codeGen->gcInfo.gcCallDescList != nullptr);
5805 codeGen->gcInfo.gcCallDescLast->cdNext = call;
5806 codeGen->gcInfo.gcCallDescLast = call;
5809 /* Record the current "pending" argument list */
5811 if (emitSimpleStkUsed)
5813 /* The biggest call is less than MAX_SIMPLE_STK_DEPTH. So use
5816 call->u1.cdArgMask = u1.emitSimpleStkMask;
5817 call->u1.cdByrefArgMask = u1.emitSimpleByrefStkMask;
5822 /* The current call has too many arguments, so we need to report the
5823 offsets of each individual GC arg. */
5825 call->cdArgCnt = u2.emitGcArgTrackCnt;
5826 if (call->cdArgCnt == 0)
5828 call->u1.cdArgMask = call->u1.cdByrefArgMask = 0;
5832 call->cdArgTable = new (emitComp, CMK_GC) unsigned[u2.emitGcArgTrackCnt];
5834 unsigned gcArgs = 0;
5835 unsigned stkLvl = emitCurStackLvl / sizeof(int);
5837 for (unsigned i = 0; i < stkLvl; i++)
5839 GCtype gcType = (GCtype)u2.emitArgTrackTab[stkLvl - i - 1];
5841 if (needsGC(gcType))
5843 call->cdArgTable[gcArgs] = i * sizeof(void*);
5845 if (gcType == GCT_BYREF)
5847 call->cdArgTable[gcArgs] |= byref_OFFSET_FLAG;
5854 assert(gcArgs == u2.emitGcArgTrackCnt);
5858 /*****************************************************************************
5860 * Record a new set of live GC ref registers.
5863 void emitter::emitUpdateLiveGCregs(GCtype gcType, regMaskTP regs, BYTE* addr)
5865 assert(emitIssuing);
5867 // Don't track GC changes in epilogs
5868 if (emitIGisInEpilog(emitCurIG))
5878 if (EMIT_GC_VERBOSE)
5880 printf("New %sReg live regs=", GCtypeStr(gcType));
5881 printRegMaskInt(regs);
5882 emitDispRegSet(regs);
5887 assert(needsGC(gcType));
5889 regMaskTP& emitThisXXrefRegs = (gcType == GCT_GCREF) ? emitThisGCrefRegs : emitThisByrefRegs;
5890 regMaskTP& emitThisYYrefRegs = (gcType == GCT_GCREF) ? emitThisByrefRegs : emitThisGCrefRegs;
5891 assert(emitThisXXrefRegs != regs);
5895 /* Figure out which GC registers are becoming live/dead at this point */
5897 dead = (emitThisXXrefRegs & ~regs);
5898 life = (~emitThisXXrefRegs & regs);
5900 /* Can't simultaneously become live and dead at the same time */
5902 assert((dead | life) != 0);
5903 assert((dead & life) == 0);
5905 /* Compute the 'changing state' mask */
5907 chg = (dead | life);
5911 regMaskTP bit = genFindLowestBit(chg);
5912 regNumber reg = genRegNumFromMask(bit);
5916 emitGCregLiveUpd(gcType, reg, addr);
5920 emitGCregDeadUpd(reg, addr);
5926 assert(emitThisXXrefRegs == regs);
5930 emitThisYYrefRegs &= ~regs; // Kill the regs from the other GC type (if live)
5931 emitThisXXrefRegs = regs; // Mark them as live in the requested GC type
5934 // The 2 GC reg masks can't be overlapping
5936 assert((emitThisGCrefRegs & emitThisByrefRegs) == 0);
5939 /*****************************************************************************
5941 * Record the fact that the given register now contains a live GC ref.
5944 void emitter::emitGCregLiveSet(GCtype gcType, regMaskTP regMask, BYTE* addr, bool isThis)
5946 assert(emitIssuing);
5947 assert(needsGC(gcType));
5949 regPtrDsc* regPtrNext;
5951 assert(!isThis || emitComp->lvaKeepAliveAndReportThis());
5952 // assert(emitFullyInt || isThis);
5953 assert(emitFullGCinfo);
5955 assert(((emitThisGCrefRegs | emitThisByrefRegs) & regMask) == 0);
5957 /* Allocate a new regptr entry and fill it in */
5959 regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
5960 regPtrNext->rpdGCtype = gcType;
5962 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
5963 regPtrNext->rpdArg = FALSE;
5964 regPtrNext->rpdCall = FALSE;
5965 regPtrNext->rpdIsThis = isThis;
5966 regPtrNext->rpdCompiler.rpdAdd = (regMaskSmall)regMask;
5967 regPtrNext->rpdCompiler.rpdDel = 0;
5970 /*****************************************************************************
5972 * Record the fact that the given register no longer contains a live GC ref.
5975 void emitter::emitGCregDeadSet(GCtype gcType, regMaskTP regMask, BYTE* addr)
5977 assert(emitIssuing);
5978 assert(needsGC(gcType));
5980 regPtrDsc* regPtrNext;
5982 // assert(emitFullyInt);
5983 assert(emitFullGCinfo);
5985 assert(((emitThisGCrefRegs | emitThisByrefRegs) & regMask) != 0);
5987 /* Allocate a new regptr entry and fill it in */
5989 regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
5990 regPtrNext->rpdGCtype = gcType;
5992 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
5993 regPtrNext->rpdCall = FALSE;
5994 regPtrNext->rpdIsThis = FALSE;
5995 regPtrNext->rpdArg = FALSE;
5996 regPtrNext->rpdCompiler.rpdAdd = 0;
5997 regPtrNext->rpdCompiler.rpdDel = (regMaskSmall)regMask;
6000 /*****************************************************************************
6002 * Emit an 8-bit integer as code.
6005 unsigned char emitter::emitOutputByte(BYTE* dst, ssize_t val)
6007 *castto(dst, unsigned char*) = (unsigned char)val;
6010 if (emitComp->opts.dspEmit)
6012 printf("; emit_byte 0%02XH\n", val & 0xFF);
6014 #ifdef _TARGET_AMD64_
6015 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6016 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6017 #endif // _TARGET_AMD64_
6020 return sizeof(unsigned char);
6023 /*****************************************************************************
6025 * Emit a 16-bit integer as code.
6028 unsigned char emitter::emitOutputWord(BYTE* dst, ssize_t val)
6030 MISALIGNED_WR_I2(dst, (short)val);
6033 if (emitComp->opts.dspEmit)
6035 printf("; emit_word 0%02XH,0%02XH\n", (val & 0xFF), (val >> 8) & 0xFF);
6037 #ifdef _TARGET_AMD64_
6038 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6039 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6040 #endif // _TARGET_AMD64_
6043 return sizeof(short);
6046 /*****************************************************************************
6048 * Emit a 32-bit integer as code.
6051 unsigned char emitter::emitOutputLong(BYTE* dst, ssize_t val)
6053 MISALIGNED_WR_I4(dst, (int)val);
6056 if (emitComp->opts.dspEmit)
6058 printf("; emit_long 0%08XH\n", (int)val);
6060 #ifdef _TARGET_AMD64_
6061 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6062 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6063 #endif // _TARGET_AMD64_
6069 /*****************************************************************************
6071 * Emit a pointer-sized integer as code.
6074 unsigned char emitter::emitOutputSizeT(BYTE* dst, ssize_t val)
6076 MISALIGNED_WR_ST(dst, val);
6079 if (emitComp->opts.dspEmit)
6081 #ifdef _TARGET_AMD64_
6082 printf("; emit_size_t 0%016llXH\n", val);
6083 #else // _TARGET_AMD64_
6084 printf("; emit_size_t 0%08XH\n", val);
6085 #endif // _TARGET_AMD64_
6089 return sizeof(size_t);
6092 //------------------------------------------------------------------------
6093 // Wrappers to emitOutputByte, emitOutputWord, emitOutputLong, emitOutputSizeT
6094 // that take unsigned __int64 or size_t type instead of ssize_t. Used on RyuJIT/x86.
6097 // dst - passed through
6098 // val - passed through
6101 // Same as wrapped function.
6104 #if !defined(LEGACY_BACKEND) && defined(_TARGET_X86_)
6105 unsigned char emitter::emitOutputByte(BYTE* dst, size_t val)
6107 return emitOutputByte(dst, (ssize_t)val);
6110 unsigned char emitter::emitOutputWord(BYTE* dst, size_t val)
6112 return emitOutputWord(dst, (ssize_t)val);
6115 unsigned char emitter::emitOutputLong(BYTE* dst, size_t val)
6117 return emitOutputLong(dst, (ssize_t)val);
6120 unsigned char emitter::emitOutputSizeT(BYTE* dst, size_t val)
6122 return emitOutputSizeT(dst, (ssize_t)val);
6125 unsigned char emitter::emitOutputByte(BYTE* dst, unsigned __int64 val)
6127 return emitOutputByte(dst, (ssize_t)val);
6130 unsigned char emitter::emitOutputWord(BYTE* dst, unsigned __int64 val)
6132 return emitOutputWord(dst, (ssize_t)val);
6135 unsigned char emitter::emitOutputLong(BYTE* dst, unsigned __int64 val)
6137 return emitOutputLong(dst, (ssize_t)val);
6140 unsigned char emitter::emitOutputSizeT(BYTE* dst, unsigned __int64 val)
6142 return emitOutputSizeT(dst, (ssize_t)val);
6144 #endif // !defined(LEGACY_BACKEND) && defined(_TARGET_X86_)
6146 /*****************************************************************************
6148 * Given a block cookie and a code position, return the actual code offset;
6149 * this can only be called at the end of code generation.
6152 UNATIVE_OFFSET emitter::emitCodeOffset(void* blockPtr, unsigned codePos)
6157 unsigned no = emitGetInsNumFromCodePos(codePos);
6159 /* Make sure we weren't passed some kind of a garbage thing */
6161 ig = (insGroup*)blockPtr;
6163 assert(ig && ig->igSelf == ig);
6166 /* The first and last offsets are always easy */
6172 else if (no == ig->igInsCnt)
6176 else if (ig->igFlags & IGF_UPD_ISZ)
6179 Some instruction sizes have changed, so we'll have to figure
6180 out the instruction offset "the hard way".
6183 of = emitFindOffset(ig, no);
6187 /* All instructions correctly predicted, the offset stays the same */
6189 of = emitGetInsOfsFromCodePos(codePos);
6191 // printf("[IG=%02u;ID=%03u;OF=%04X] <= %08X\n", ig->igNum, emitGetInsNumFromCodePos(codePos), of, codePos);
6193 /* Make sure the offset estimate is accurate */
6195 assert(of == emitFindOffset(ig, emitGetInsNumFromCodePos(codePos)));
6198 return ig->igOffs + of;
6201 /*****************************************************************************
6203 * Record the fact that the given register now contains a live GC ref.
6206 void emitter::emitGCregLiveUpd(GCtype gcType, regNumber reg, BYTE* addr)
6208 assert(emitIssuing);
6210 // Don't track GC changes in epilogs
6211 if (emitIGisInEpilog(emitCurIG))
6216 assert(needsGC(gcType));
6218 regMaskTP regMask = genRegMask(reg);
6220 regMaskTP& emitThisXXrefRegs = (gcType == GCT_GCREF) ? emitThisGCrefRegs : emitThisByrefRegs;
6221 regMaskTP& emitThisYYrefRegs = (gcType == GCT_GCREF) ? emitThisByrefRegs : emitThisGCrefRegs;
6223 if ((emitThisXXrefRegs & regMask) == 0)
6225 // If the register was holding the other GC type, that type should
6228 if (emitThisYYrefRegs & regMask)
6230 emitGCregDeadUpd(reg, addr);
6233 // For synchronized methods, "this" is always alive and in the same register.
6234 // However, if we generate any code after the epilog block (where "this"
6235 // goes dead), "this" will come alive again. We need to notice that.
6236 // Note that we only expect isThis to be true at an insGroup boundary.
6238 bool isThis = (reg == emitSyncThisObjReg) ? true : false;
6242 emitGCregLiveSet(gcType, regMask, addr, isThis);
6245 emitThisXXrefRegs |= regMask;
6248 if (EMIT_GC_VERBOSE)
6250 printf("%sReg +[%s]\n", GCtypeStr(gcType), emitRegName(reg));
6255 // The 2 GC reg masks can't be overlapping
6257 assert((emitThisGCrefRegs & emitThisByrefRegs) == 0);
6260 /*****************************************************************************
6262 * Record the fact that the given set of registers no longer contain live GC refs.
6265 void emitter::emitGCregDeadUpdMask(regMaskTP regs, BYTE* addr)
6267 assert(emitIssuing);
6269 // Don't track GC changes in epilogs
6270 if (emitIGisInEpilog(emitCurIG))
6275 // First, handle the gcref regs going dead
6277 regMaskTP gcrefRegs = emitThisGCrefRegs & regs;
6279 // "this" can never go dead in synchronized methods, except in the epilog
6280 // after the call to CORINFO_HELP_MON_EXIT.
6281 assert(emitSyncThisObjReg == REG_NA || (genRegMask(emitSyncThisObjReg) & regs) == 0);
6285 assert((emitThisByrefRegs & gcrefRegs) == 0);
6289 emitGCregDeadSet(GCT_GCREF, gcrefRegs, addr);
6292 emitThisGCrefRegs &= ~gcrefRegs;
6295 if (EMIT_GC_VERBOSE)
6298 printRegMaskInt(gcrefRegs);
6300 emitDispRegSet(gcrefRegs);
6306 // Second, handle the byref regs going dead
6308 regMaskTP byrefRegs = emitThisByrefRegs & regs;
6312 assert((emitThisGCrefRegs & byrefRegs) == 0);
6316 emitGCregDeadSet(GCT_BYREF, byrefRegs, addr);
6319 emitThisByrefRegs &= ~byrefRegs;
6322 if (EMIT_GC_VERBOSE)
6325 printRegMaskInt(byrefRegs);
6327 emitDispRegSet(byrefRegs);
6334 /*****************************************************************************
6336 * Record the fact that the given register no longer contains a live GC ref.
6339 void emitter::emitGCregDeadUpd(regNumber reg, BYTE* addr)
6341 assert(emitIssuing);
6343 // Don't track GC changes in epilogs
6344 if (emitIGisInEpilog(emitCurIG))
6349 regMaskTP regMask = genRegMask(reg);
6351 if ((emitThisGCrefRegs & regMask) != 0)
6353 assert((emitThisByrefRegs & regMask) == 0);
6357 emitGCregDeadSet(GCT_GCREF, regMask, addr);
6360 emitThisGCrefRegs &= ~regMask;
6363 if (EMIT_GC_VERBOSE)
6365 printf("%s -[%s]\n", "gcrReg", emitRegName(reg));
6369 else if ((emitThisByrefRegs & regMask) != 0)
6373 emitGCregDeadSet(GCT_BYREF, regMask, addr);
6376 emitThisByrefRegs &= ~regMask;
6379 if (EMIT_GC_VERBOSE)
6381 printf("%s -[%s]\n", "byrReg", emitRegName(reg));
6387 /*****************************************************************************
6389 * Record the fact that the given variable now contains a live GC ref.
6390 * varNum may be INT_MAX or negative (indicating a spill temp) only if
6391 * offs is guaranteed to be the offset of a tracked GC ref. Else we
6392 * need a valid value to check if the variable is tracked or not.
6395 void emitter::emitGCvarLiveUpd(int offs, int varNum, GCtype gcType, BYTE* addr)
6397 assert(abs(offs) % sizeof(int) == 0);
6398 assert(needsGC(gcType));
6400 #if FEATURE_FIXED_OUT_ARGS
6401 if ((unsigned)varNum == emitComp->lvaOutgoingArgSpaceVar)
6405 /* Append an "arg push" entry to track a GC written to the
6406 outgoing argument space.
6407 Allocate a new ptr arg entry and fill it in */
6409 regPtrDsc* regPtrNext = gcInfo->gcRegPtrAllocDsc();
6410 regPtrNext->rpdGCtype = gcType;
6411 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6412 regPtrNext->rpdArg = TRUE;
6413 regPtrNext->rpdCall = FALSE;
6414 noway_assert(FitsIn<unsigned short>(offs));
6415 regPtrNext->rpdPtrArg = (unsigned short)offs;
6416 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_PUSH;
6417 regPtrNext->rpdIsThis = FALSE;
6420 if (EMIT_GC_VERBOSE)
6422 printf("[%04X] %s arg write\n", offs, GCtypeStr(gcType));
6428 #endif // FEATURE_FIXED_OUT_ARGS
6430 /* Is the frame offset within the "interesting" range? */
6432 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
6434 /* Normally all variables in this range must be tracked stack
6435 pointers. However, for EnC, we relax this condition. So we
6436 must check if this is not such a variable.
6437 Note that varNum might be negative, indicating a spill temp.
6440 if (varNum != INT_MAX)
6442 bool isTracked = false;
6445 // This is NOT a spill temp
6446 LclVarDsc* varDsc = &emitComp->lvaTable[varNum];
6447 isTracked = emitComp->lvaIsGCTracked(varDsc);
6451 // Is it an untracked spill temp?
6452 isTracked = TRACK_GC_TEMP_LIFETIMES;
6457 assert(!emitContTrkPtrLcls ||
6458 // EBP based variables in the double-aligned frames are indeed input arguments.
6459 // and we don't require them to fall into the "interesting" range.
6460 ((emitComp->rpFrameType == FT_DOUBLE_ALIGN_FRAME) && (varNum >= 0) &&
6461 (emitComp->lvaTable[varNum].lvFramePointerBased == 1)));
6463 assert(!emitContTrkPtrLcls);
6471 /* Compute the index into the GC frame table */
6473 disp = (offs - emitGCrFrameOffsMin) / sizeof(void*);
6474 assert(disp < emitGCrFrameOffsCnt);
6476 /* If the variable is currently dead, mark it as live */
6478 if (emitGCrFrameLiveTab[disp] == nullptr)
6480 emitGCvarLiveSet(offs, gcType, addr, disp);
6486 /*****************************************************************************
6488 * Record the fact that the given variable no longer contains a live GC ref.
6491 void emitter::emitGCvarDeadUpd(int offs, BYTE* addr)
6493 assert(emitIssuing);
6494 assert(abs(offs) % sizeof(int) == 0);
6496 /* Is the frame offset within the "interesting" range? */
6498 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
6502 /* Compute the index into the GC frame table */
6504 disp = (offs - emitGCrFrameOffsMin) / sizeof(void*);
6505 assert(disp < emitGCrFrameOffsCnt);
6507 /* If the variable is currently live, mark it as dead */
6509 if (emitGCrFrameLiveTab[disp] != nullptr)
6511 emitGCvarDeadSet(offs, addr, disp);
6516 /*****************************************************************************
6518 * Allocate a new IG and link it in to the global list after the current IG
6521 insGroup* emitter::emitAllocAndLinkIG()
6523 insGroup* ig = emitAllocIG();
6527 emitInsertIGAfter(emitCurIG, ig);
6529 /* Propagate some IG flags from the current group to the new group */
6531 ig->igFlags |= (emitCurIG->igFlags & IGF_PROPAGATE_MASK);
6533 /* Set the new IG as the current IG */
6540 /*****************************************************************************
6542 * Allocate an instruction group descriptor and assign it the next index.
6545 insGroup* emitter::emitAllocIG()
6549 /* Allocate a group descriptor */
6551 size_t sz = sizeof(insGroup);
6552 ig = (insGroup*)emitGetMem(sz);
6559 emitTotalIGcnt += 1;
6560 emitTotalIGsize += sz;
6561 emitSizeMethod += sz;
6564 /* Do basic initialization */
6571 /*****************************************************************************
6573 * Initialize an instruction group
6576 void emitter::emitInitIG(insGroup* ig)
6578 /* Assign the next available index to the instruction group */
6580 ig->igNum = emitNxtIGnum;
6584 /* Record the (estimated) code offset of the group */
6586 ig->igOffs = emitCurCodeOffset;
6587 assert(IsCodeAligned(ig->igOffs));
6589 /* Set the current function index */
6591 ig->igFuncIdx = emitComp->compCurrFuncIdx;
6595 /* Zero out some fields to avoid printing garbage in JitDumps. These
6596 really only need to be set in DEBUG, but do it in all cases to make
6597 sure we act the same in non-DEBUG builds.
6601 ig->igGCregs = RBM_NONE;
6605 /*****************************************************************************
6607 * Insert instruction group 'ig' after 'igInsertAfterIG'
6610 void emitter::emitInsertIGAfter(insGroup* insertAfterIG, insGroup* ig)
6615 ig->igNext = insertAfterIG->igNext;
6616 insertAfterIG->igNext = ig;
6618 if (emitIGlast == insertAfterIG)
6620 // If we are inserting at the end, then update the 'last' pointer
6625 /*****************************************************************************
6627 * Save the current IG and start a new one.
6630 void emitter::emitNxtIG(bool emitAdd)
6632 /* Right now we don't allow multi-IG prologs */
6634 assert(emitCurIG != emitPrologIG);
6636 /* First save the current group */
6640 /* Update the GC live sets for the group's start
6641 * Do it only if not an emitter added block */
6645 VarSetOps::Assign(emitComp, emitInitGCrefVars, emitThisGCrefVars);
6646 emitInitGCrefRegs = emitThisGCrefRegs;
6647 emitInitByrefRegs = emitThisByrefRegs;
6650 /* Start generating the new group */
6654 /* If this is an emitter added block, flag it */
6658 emitCurIG->igFlags |= IGF_EMIT_ADD;
6661 // We've created a new IG; no need to force another one.
6662 emitForceNewIG = false;
6665 /*****************************************************************************
6667 * emitGetInsSC: Get the instruction's constant value.
6670 ssize_t emitter::emitGetInsSC(instrDesc* id)
6672 #ifdef _TARGET_ARM_ // should it be _TARGET_ARMARCH_? Why do we need this? Note that on ARM64 we store scaled immediates
6674 if (id->idIsLclVar())
6676 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
6679 int offs = id->idAddr()->iiaLclVar.lvaOffset();
6680 #if defined(_TARGET_ARM_)
6681 int adr = emitComp->lvaFrameAddress(varNum, id->idIsLclFPBase(), &baseReg, offs);
6682 int dsp = adr + offs;
6683 if ((id->idIns() == INS_sub) || (id->idIns() == INS_subw))
6685 #elif defined(_TARGET_ARM64_)
6686 // TODO-ARM64-Cleanup: this is currently unreachable. Do we need it?
6688 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
6689 int dsp = adr + offs;
6690 if (id->idIns() == INS_sub)
6696 #endif // _TARGET_ARM_
6697 if (id->idIsLargeCns())
6699 return ((instrDescCns*)id)->idcCnsVal;
6703 return id->idSmallCns();
6707 /*****************************************************************************/
6708 #if EMIT_TRACK_STACK_DEPTH
6709 /*****************************************************************************
6711 * Record a push of a single dword on the stack.
6714 void emitter::emitStackPush(BYTE* addr, GCtype gcType)
6717 assert(IsValidGCtype(gcType));
6720 if (emitSimpleStkUsed)
6722 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6723 assert(emitCurStackLvl / sizeof(int) < MAX_SIMPLE_STK_DEPTH);
6725 u1.emitSimpleStkMask <<= 1;
6726 u1.emitSimpleStkMask |= (unsigned)needsGC(gcType);
6728 u1.emitSimpleByrefStkMask <<= 1;
6729 u1.emitSimpleByrefStkMask |= (gcType == GCT_BYREF);
6731 assert((u1.emitSimpleStkMask & u1.emitSimpleByrefStkMask) == u1.emitSimpleByrefStkMask);
6735 emitStackPushLargeStk(addr, gcType);
6738 emitCurStackLvl += sizeof(int);
6741 /*****************************************************************************
6743 * Record a push of a bunch of non-GC dwords on the stack.
6746 void emitter::emitStackPushN(BYTE* addr, unsigned count)
6750 if (emitSimpleStkUsed)
6752 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6754 u1.emitSimpleStkMask <<= count;
6755 u1.emitSimpleByrefStkMask <<= count;
6759 emitStackPushLargeStk(addr, GCT_NONE, count);
6762 emitCurStackLvl += count * sizeof(int);
6765 /*****************************************************************************
6767 * Record a pop of the given number of dwords from the stack.
6770 void emitter::emitStackPop(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count)
6772 assert(emitCurStackLvl / sizeof(int) >= count);
6773 assert(!isCall || callInstrSize > 0);
6777 if (emitSimpleStkUsed)
6779 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6781 unsigned cnt = count;
6785 u1.emitSimpleStkMask >>= 1;
6786 u1.emitSimpleByrefStkMask >>= 1;
6791 emitStackPopLargeStk(addr, isCall, callInstrSize, count);
6794 emitCurStackLvl -= count * sizeof(int);
6800 // For the general encoder we do the call below always when it's a call, to ensure that the call is
6801 // recorded (when we're doing the ptr reg map for a non-fully-interruptible method).
6803 #ifndef JIT32_GCENCODER
6804 || (emitComp->genFullPtrRegMap && (!emitComp->genInterruptible) && isCall)
6805 #endif // JIT32_GCENCODER
6808 emitStackPopLargeStk(addr, isCall, callInstrSize, 0);
6813 /*****************************************************************************
6815 * Record a push of a single word on the stack for a full pointer map.
6818 void emitter::emitStackPushLargeStk(BYTE* addr, GCtype gcType, unsigned count)
6820 S_UINT32 level(emitCurStackLvl / sizeof(int));
6822 assert(IsValidGCtype(gcType));
6824 assert(!emitSimpleStkUsed);
6828 /* Push an entry for this argument on the tracking stack */
6830 // printf("Pushed [%d] at lvl %2u [max=%u]\n", isGCref, emitArgTrackTop - emitArgTrackTab, emitMaxStackDepth);
6832 assert(level.IsOverflow() || u2.emitArgTrackTop == u2.emitArgTrackTab + level.Value());
6833 *u2.emitArgTrackTop++ = (BYTE)gcType;
6834 assert(u2.emitArgTrackTop <= u2.emitArgTrackTab + emitMaxStackDepth);
6836 if (emitFullArgInfo || needsGC(gcType))
6840 /* Append an "arg push" entry if this is a GC ref or
6841 FPO method. Allocate a new ptr arg entry and fill it in */
6843 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6844 regPtrNext->rpdGCtype = gcType;
6846 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6847 regPtrNext->rpdArg = TRUE;
6848 regPtrNext->rpdCall = FALSE;
6849 if (level.IsOverflow() || !FitsIn<unsigned short>(level.Value()))
6851 IMPL_LIMITATION("Too many/too big arguments to encode GC information");
6853 regPtrNext->rpdPtrArg = (unsigned short)level.Value();
6854 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_PUSH;
6855 regPtrNext->rpdIsThis = FALSE;
6858 if (EMIT_GC_VERBOSE)
6860 printf("[%08X] %s arg push %u\n", dspPtr(regPtrNext), GCtypeStr(gcType), level.Value());
6865 /* This is an "interesting" argument push */
6867 u2.emitGcArgTrackCnt++;
6870 assert(!level.IsOverflow());
6874 /*****************************************************************************
6876 * Record a pop of the given number of words from the stack for a full ptr
6880 void emitter::emitStackPopLargeStk(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count)
6882 assert(emitIssuing);
6885 S_UINT16 argRecCnt(0); // arg count for ESP, ptr-arg count for EBP
6886 unsigned gcrefRegs, byrefRegs;
6888 #ifdef JIT32_GCENCODER
6889 // For the general encoder, we always need to record calls, so we make this call
6890 // even when emitSimpleStkUsed is true.
6891 assert(!emitSimpleStkUsed);
6894 /* Count how many pointer records correspond to this "pop" */
6896 for (argStkCnt = count; argStkCnt; argStkCnt--)
6898 assert(u2.emitArgTrackTop > u2.emitArgTrackTab);
6900 GCtype gcType = (GCtype)(*--u2.emitArgTrackTop);
6902 assert(IsValidGCtype(gcType));
6904 // printf("Popped [%d] at lvl %u\n", GCtypeStr(gcType), emitArgTrackTop - emitArgTrackTab);
6906 // This is an "interesting" argument
6908 if (emitFullArgInfo || needsGC(gcType))
6914 assert(u2.emitArgTrackTop >= u2.emitArgTrackTab);
6915 assert(u2.emitArgTrackTop == u2.emitArgTrackTab + emitCurStackLvl / sizeof(int) - count);
6916 noway_assert(!argRecCnt.IsOverflow());
6918 /* We're about to pop the corresponding arg records */
6920 u2.emitGcArgTrackCnt -= argRecCnt.Value();
6922 #ifdef JIT32_GCENCODER
6923 // For the general encoder, we always have to record calls, so we don't take this early return.
6924 if (!emitFullGCinfo)
6928 // Do we have any interesting (i.e., callee-saved) registers live here?
6930 gcrefRegs = byrefRegs = 0;
6932 // We make a bitmask whose bits correspond to callee-saved register indices (in the sequence
6933 // of callee-saved registers only).
6934 for (unsigned calleeSavedRegIdx = 0; calleeSavedRegIdx < CNT_CALLEE_SAVED; calleeSavedRegIdx++)
6936 regMaskTP calleeSavedRbm = raRbmCalleeSaveOrder[calleeSavedRegIdx];
6937 if (emitThisGCrefRegs & calleeSavedRbm)
6939 gcrefRegs |= (1 << calleeSavedRegIdx);
6941 if (emitThisByrefRegs & calleeSavedRbm)
6943 byrefRegs |= (1 << calleeSavedRegIdx);
6947 #ifdef JIT32_GCENCODER
6948 // For the general encoder, we always have to record calls, so we don't take this early return. /* Are there any
6949 // args to pop at this call site?
6951 if (argRecCnt.Value() == 0)
6954 Or do we have a partially interruptible EBP-less frame, and any
6955 of EDI,ESI,EBX,EBP are live, or is there an outer/pending call?
6957 CLANG_FORMAT_COMMENT_ANCHOR;
6959 #if !FPO_INTERRUPTIBLE
6960 if (emitFullyInt || (gcrefRegs == 0 && byrefRegs == 0 && u2.emitGcArgTrackCnt == 0))
6964 #endif // JIT32_GCENCODER
6966 /* Only calls may pop more than one value */
6968 // _cdecl calls accomplish this popping via a post-call-instruction SP adjustment.
6969 // The "rpdCall" field below should be interpreted as "the instruction accomplishes
6970 // call-related popping, even if it's not itself a call". Therefore, we don't just
6971 // use the "isCall" input argument, which means that the instruction actually is a call --
6972 // we use the OR of "isCall" or the "pops more than one value."
6974 bool isCallRelatedPop = (argRecCnt.Value() > 1);
6976 /* Allocate a new ptr arg entry and fill it in */
6978 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6979 regPtrNext->rpdGCtype = GCT_GCREF; // Pops need a non-0 value (??)
6981 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6982 regPtrNext->rpdCall = (isCall || isCallRelatedPop);
6983 #ifndef JIT32_GCENCODER
6984 if (regPtrNext->rpdCall)
6986 assert(isCall || callInstrSize == 0);
6987 regPtrNext->rpdCallInstrSize = callInstrSize;
6990 regPtrNext->rpdCallGCrefRegs = gcrefRegs;
6991 regPtrNext->rpdCallByrefRegs = byrefRegs;
6992 regPtrNext->rpdArg = TRUE;
6993 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_POP;
6994 regPtrNext->rpdPtrArg = argRecCnt.Value();
6997 if (EMIT_GC_VERBOSE)
6999 printf("[%08X] ptr arg pop %u\n", dspPtr(regPtrNext), count);
7004 /*****************************************************************************
7005 * For caller-pop arguments, we report the arguments as pending arguments.
7006 * However, any GC arguments are now dead, so we need to report them
7010 void emitter::emitStackKillArgs(BYTE* addr, unsigned count, unsigned char callInstrSize)
7014 if (emitSimpleStkUsed)
7016 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCInfo
7018 /* We don't need to report this to the GC info, but we do need
7019 to kill mark the ptrs on the stack as non-GC */
7021 assert(emitCurStackLvl / sizeof(int) >= count);
7023 for (unsigned lvl = 0; lvl < count; lvl++)
7025 u1.emitSimpleStkMask &= ~(1 << lvl);
7026 u1.emitSimpleByrefStkMask &= ~(1 << lvl);
7031 BYTE* argTrackTop = u2.emitArgTrackTop;
7034 for (unsigned i = 0; i < count; i++)
7036 assert(argTrackTop > u2.emitArgTrackTab);
7040 GCtype gcType = (GCtype)(*argTrackTop);
7041 assert(IsValidGCtype(gcType));
7043 if (needsGC(gcType))
7045 // printf("Killed %s at lvl %u\n", GCtypeStr(gcType), argTrackTop - emitArgTrackTab);
7047 *argTrackTop = GCT_NONE;
7052 noway_assert(!gcCnt.IsOverflow());
7054 /* We're about to kill the corresponding (pointer) arg records */
7056 if (!emitFullArgInfo)
7058 u2.emitGcArgTrackCnt -= gcCnt.Value();
7061 if (!emitFullGCinfo)
7066 /* Right after the call, the arguments are still sitting on the
7067 stack, but they are effectively dead. For fully-interruptible
7068 methods, we need to report that */
7070 if (emitFullGCinfo && gcCnt.Value())
7072 /* Allocate a new ptr arg entry and fill it in */
7074 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
7075 regPtrNext->rpdGCtype = GCT_GCREF; // Kills need a non-0 value (??)
7077 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
7079 regPtrNext->rpdArg = TRUE;
7080 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_KILL;
7081 regPtrNext->rpdPtrArg = gcCnt.Value();
7084 if (EMIT_GC_VERBOSE)
7086 printf("[%08X] ptr arg kill %u\n", dspPtr(regPtrNext), count);
7091 /* Now that ptr args have been marked as non-ptrs, we need to record
7092 the call itself as one that has no arguments. */
7094 emitStackPopLargeStk(addr, true, callInstrSize, 0);
7098 /*****************************************************************************
7099 * A helper for recording a relocation with the EE.
7101 void emitter::emitRecordRelocation(void* location, /* IN */
7102 void* target, /* IN */
7103 WORD fRelocType, /* IN */
7104 WORD slotNum /* = 0 */, /* IN */
7105 INT32 addlDelta /* = 0 */) /* IN */
7107 // If we're an unmatched altjit, don't tell the VM anything. We still record the relocation for
7108 // late disassembly; maybe we'll need it?
7109 if (emitComp->info.compMatchedVM)
7111 emitCmpHandle->recordRelocation(location, target, fRelocType, slotNum, addlDelta);
7113 #if defined(LATE_DISASM)
7114 codeGen->getDisAssembler().disRecordRelocation((size_t)location, (size_t)target);
7115 #endif // defined(LATE_DISASM)
7119 /*****************************************************************************
7120 * A helper for handling a Thumb-Mov32 of position-independent (PC-relative) value
7122 * This routine either records relocation for the location with the EE,
7123 * or creates a virtual relocation entry to perform offset fixup during
7124 * compilation without recording it with EE - depending on which of
7125 * absolute/relocative relocations mode are used for code section.
7127 void emitter::emitHandlePCRelativeMov32(void* location, /* IN */
7128 void* target) /* IN */
7130 if (emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_RELATIVE_CODE_RELOCS))
7132 emitRecordRelocation(location, target, IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL);
7136 emitRecordRelocation(location, target, IMAGE_REL_BASED_THUMB_MOV32);
7139 #endif // _TARGET_ARM_
7141 /*****************************************************************************
7142 * A helper for recording a call site with the EE.
7144 void emitter::emitRecordCallSite(ULONG instrOffset, /* IN */
7145 CORINFO_SIG_INFO* callSig, /* IN */
7146 CORINFO_METHOD_HANDLE methodHandle) /* IN */
7149 // Since CORINFO_SIG_INFO is a heavyweight structure, in most cases we can
7150 // lazily obtain it here using the given method handle (we only save the sig
7151 // info when we explicitly need it, i.e. for CALLI calls, vararg calls, and
7153 if (callSig == nullptr)
7155 assert(methodHandle != nullptr);
7157 if (Compiler::eeGetHelperNum(methodHandle) == CORINFO_HELP_UNDEF)
7159 if (emitScratchSigInfo == nullptr)
7161 emitScratchSigInfo = new (emitComp, CMK_CorSig) CORINFO_SIG_INFO;
7164 emitComp->eeGetMethodSig(methodHandle, emitScratchSigInfo);
7165 callSig = emitScratchSigInfo;
7169 emitCmpHandle->recordCallSite(instrOffset, callSig, methodHandle);
7170 #endif // defined(DEBUG)
7173 /*****************************************************************************/
7174 #endif // EMIT_TRACK_STACK_DEPTH
7175 /*****************************************************************************/
7176 /*****************************************************************************/
7180 /*****************************************************************************
7181 * Given a code offset, return a string representing a label for that offset.
7182 * If the code offset is just after the end of the code of the function, the
7183 * label will be "END". If the code offset doesn't correspond to any known
7184 * offset, the label will be "UNKNOWN". The strings are returned from static
7185 * buffers. This function rotates amongst four such static buffers (there are
7186 * cases where this function is called four times to provide data for a single
7190 const char* emitter::emitOffsetToLabel(unsigned offs)
7192 const size_t TEMP_BUFFER_LEN = 40;
7193 static unsigned curBuf = 0;
7194 static char buf[4][TEMP_BUFFER_LEN];
7199 UNATIVE_OFFSET nextof = 0;
7201 for (ig = emitIGlist; ig != nullptr; ig = ig->igNext)
7203 assert(nextof == ig->igOffs);
7205 if (ig->igOffs == offs)
7208 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "G_M%03u_IG%02u", Compiler::s_compMethodsCount, ig->igNum);
7209 retbuf = buf[curBuf];
7210 curBuf = (curBuf + 1) % 4;
7213 else if (ig->igOffs > offs)
7215 // We went past the requested offset but didn't find it.
7216 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "UNKNOWN");
7217 retbuf = buf[curBuf];
7218 curBuf = (curBuf + 1) % 4;
7222 nextof = ig->igOffs + ig->igSize;
7227 // It's a pseudo-label to the end.
7228 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "END");
7229 retbuf = buf[curBuf];
7230 curBuf = (curBuf + 1) % 4;
7235 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "UNKNOWN");
7236 retbuf = buf[curBuf];
7237 curBuf = (curBuf + 1) % 4;