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.
4
5/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7XX XX
8XX emit.cpp XX
9XX XX
10XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12*/
13
14#include "jitpch.h"
15#ifdef _MSC_VER
16#pragma hdrstop
17#endif
18
19#include "hostallocator.h"
20#include "instr.h"
21#include "emit.h"
22#include "codegen.h"
23
24/*****************************************************************************
25 *
26 * Represent an emitter location.
27 */
28
29void emitLocation::CaptureLocation(emitter* emit)
30{
31 ig = emit->emitCurIG;
32 codePos = emit->emitCurOffset();
33
34 assert(Valid());
35}
36
37bool emitLocation::IsCurrentLocation(emitter* emit) const
38{
39 assert(Valid());
40 return (ig == emit->emitCurIG) && (codePos == emit->emitCurOffset());
41}
42
43UNATIVE_OFFSET emitLocation::CodeOffset(emitter* emit) const
44{
45 assert(Valid());
46 return emit->emitCodeOffset(ig, codePos);
47}
48
49int emitLocation::GetInsNum() const
50{
51 return emitGetInsNumFromCodePos(codePos);
52}
53
54// Get the instruction offset in the current instruction group, which must be a funclet prolog group.
55// This is used to find an instruction offset used in unwind data.
56// TODO-AMD64-Bug?: We only support a single main function prolog group, but allow for multiple funclet prolog
57// groups (not that we actually use that flexibility, since the funclet prolog will be small). How to
58// handle that?
59UNATIVE_OFFSET emitLocation::GetFuncletPrologOffset(emitter* emit) const
60{
61 assert(ig->igFuncIdx != 0);
62 assert((ig->igFlags & IGF_FUNCLET_PROLOG) != 0);
63 assert(ig == emit->emitCurIG);
64
65 return emit->emitCurIGsize;
66}
67
68#ifdef DEBUG
69void emitLocation::Print() const
70{
71 unsigned insNum = emitGetInsNumFromCodePos(codePos);
72 unsigned insOfs = emitGetInsOfsFromCodePos(codePos);
73 printf("(G_M%03u_IG%02u,ins#%d,ofs#%d)", Compiler::s_compMethodsCount, ig->igNum, insNum, insOfs);
74}
75#endif // DEBUG
76
77/*****************************************************************************
78 *
79 * Return the name of an instruction format.
80 */
81
82#if defined(DEBUG) || EMITTER_STATS
83
84const char* emitter::emitIfName(unsigned f)
85{
86 static const char* const ifNames[] = {
87#define IF_DEF(en, op1, op2) "IF_" #en,
88#include "emitfmts.h"
89 };
90
91 static char errBuff[32];
92
93 if (f < _countof(ifNames))
94 {
95 return ifNames[f];
96 }
97
98 sprintf_s(errBuff, sizeof(errBuff), "??%u??", f);
99 return errBuff;
100}
101
102#endif
103
104#ifdef TRANSLATE_PDB
105
106/* these are protected */
107
108AddrMap* emitter::emitPDBOffsetTable = 0;
109LocalMap* emitter::emitPDBLocalTable = 0;
110bool emitter::emitIsPDBEnabled = true;
111BYTE* emitter::emitILBaseOfCode = 0;
112BYTE* emitter::emitILMethodBase = 0;
113BYTE* emitter::emitILMethodStart = 0;
114BYTE* emitter::emitImgBaseOfCode = 0;
115
116void emitter::MapCode(int ilOffset, BYTE* imgDest)
117{
118 if (emitIsPDBEnabled)
119 {
120 emitPDBOffsetTable->MapSrcToDest(ilOffset, (int)(imgDest - emitImgBaseOfCode));
121 }
122}
123
124void emitter::MapFunc(int imgOff,
125 int procLen,
126 int dbgStart,
127 int dbgEnd,
128 short frameReg,
129 int stkAdjust,
130 int lvaCount,
131 OptJit::LclVarDsc* lvaTable,
132 bool framePtr)
133{
134 if (emitIsPDBEnabled)
135 {
136 // this code stores information about local symbols for the PDB translation
137
138 assert(lvaCount >= 0); // don't allow a negative count
139
140 LvaDesc* rgLvaDesc = 0;
141
142 if (lvaCount > 0)
143 {
144 rgLvaDesc = new LvaDesc[lvaCount];
145
146 if (!rgLvaDesc)
147 {
148 NOMEM();
149 }
150
151 LvaDesc* pDst = rgLvaDesc;
152 OptJit::LclVarDsc* pSrc = lvaTable;
153 for (int i = 0; i < lvaCount; ++i, ++pDst, ++pSrc)
154 {
155 pDst->slotNum = pSrc->lvSlotNum;
156 pDst->isReg = pSrc->lvRegister;
157 pDst->reg = (pSrc->lvRegister ? pSrc->lvRegNum : frameReg);
158 pDst->off = pSrc->lvStkOffs + stkAdjust;
159 }
160 }
161
162 emitPDBLocalTable->AddFunc((int)(emitILMethodBase - emitILBaseOfCode), imgOff - (int)emitImgBaseOfCode, procLen,
163 dbgStart - imgOff, dbgEnd - imgOff, lvaCount, rgLvaDesc, framePtr);
164 // do not delete rgLvaDesc here -- responsibility is now on emitPDBLocalTable destructor
165 }
166}
167
168/* these are public */
169
170void emitter::SetILBaseOfCode(BYTE* pTextBase)
171{
172 emitILBaseOfCode = pTextBase;
173}
174
175void emitter::SetILMethodBase(BYTE* pMethodEntry)
176{
177 emitILMethodBase = pMethodEntry;
178}
179
180void emitter::SetILMethodStart(BYTE* pMethodCode)
181{
182 emitILMethodStart = pMethodCode;
183}
184
185void emitter::SetImgBaseOfCode(BYTE* pTextBase)
186{
187 emitImgBaseOfCode = pTextBase;
188}
189
190void emitter::SetIDBaseToProlog()
191{
192 emitInstrDescILBase = (int)(emitILMethodBase - emitILBaseOfCode);
193}
194
195void emitter::SetIDBaseToOffset(int methodOffset)
196{
197 emitInstrDescILBase = methodOffset + (int)(emitILMethodStart - emitILBaseOfCode);
198}
199
200void emitter::DisablePDBTranslation()
201{
202 // this function should disable PDB translation code
203 emitIsPDBEnabled = false;
204}
205
206bool emitter::IsPDBEnabled()
207{
208 return emitIsPDBEnabled;
209}
210
211void emitter::InitTranslationMaps(int ilCodeSize)
212{
213 if (emitIsPDBEnabled)
214 {
215 emitPDBOffsetTable = AddrMap::Create(ilCodeSize);
216 emitPDBLocalTable = LocalMap::Create();
217 }
218}
219
220void emitter::DeleteTranslationMaps()
221{
222 if (emitPDBOffsetTable)
223 {
224 delete emitPDBOffsetTable;
225 emitPDBOffsetTable = 0;
226 }
227 if (emitPDBLocalTable)
228 {
229 delete emitPDBLocalTable;
230 emitPDBLocalTable = 0;
231 }
232}
233
234void emitter::InitTranslator(PDBRewriter* pPDB, int* rgSecMap, IMAGE_SECTION_HEADER** rgpHeader, int numSections)
235{
236 if (emitIsPDBEnabled)
237 {
238 pPDB->InitMaps(rgSecMap, // new PE section header order
239 rgpHeader, // array of section headers
240 numSections, // number of sections
241 emitPDBOffsetTable, // code offset translation table
242 emitPDBLocalTable); // slot variable translation table
243 }
244}
245
246#endif // TRANSLATE_PDB
247
248/*****************************************************************************/
249
250#if EMITTER_STATS
251
252static unsigned totAllocdSize;
253static unsigned totActualSize;
254
255unsigned emitter::emitIFcounts[emitter::IF_COUNT];
256
257static unsigned emitSizeBuckets[] = {100, 1024 * 1, 1024 * 2, 1024 * 3, 1024 * 4, 1024 * 5, 1024 * 10, 0};
258static Histogram emitSizeTable(emitSizeBuckets);
259
260static unsigned GCrefsBuckets[] = {0, 1, 2, 5, 10, 20, 50, 128, 256, 512, 1024, 0};
261static Histogram GCrefsTable(GCrefsBuckets);
262
263static unsigned stkDepthBuckets[] = {0, 1, 2, 5, 10, 16, 32, 128, 1024, 0};
264static Histogram stkDepthTable(stkDepthBuckets);
265
266size_t emitter::emitSizeMethod;
267
268size_t emitter::emitTotMemAlloc;
269unsigned emitter::emitTotalInsCnt;
270unsigned emitter::emitTotalIGcnt;
271unsigned emitter::emitTotalPhIGcnt;
272unsigned emitter::emitTotalIGjmps;
273unsigned emitter::emitTotalIGptrs;
274unsigned emitter::emitTotalIGicnt;
275size_t emitter::emitTotalIGsize;
276unsigned emitter::emitTotalIGmcnt;
277
278unsigned emitter::emitSmallDspCnt;
279unsigned emitter::emitLargeDspCnt;
280
281unsigned emitter::emitSmallCnsCnt;
282unsigned emitter::emitLargeCnsCnt;
283unsigned emitter::emitSmallCns[SMALL_CNS_TSZ];
284
285void emitterStaticStats(FILE* fout)
286{
287 // insGroup members
288
289 fprintf(fout, "\n");
290 fprintf(fout, "insGroup:\n");
291 fprintf(fout, "Offset of igNext = %2u\n", offsetof(insGroup, igNext));
292#ifdef DEBUG
293 fprintf(fout, "Offset of igSelf = %2u\n", offsetof(insGroup, igSelf));
294#endif
295 fprintf(fout, "Offset of igNum = %2u\n", offsetof(insGroup, igNum));
296 fprintf(fout, "Offset of igOffs = %2u\n", offsetof(insGroup, igOffs));
297 fprintf(fout, "Offset of igFuncIdx = %2u\n", offsetof(insGroup, igFuncIdx));
298 fprintf(fout, "Offset of igFlags = %2u\n", offsetof(insGroup, igFlags));
299 fprintf(fout, "Offset of igSize = %2u\n", offsetof(insGroup, igSize));
300 fprintf(fout, "Offset of igData = %2u\n", offsetof(insGroup, igData));
301#if EMIT_TRACK_STACK_DEPTH
302 fprintf(fout, "Offset of igStkLvl = %2u\n", offsetof(insGroup, igStkLvl));
303#endif
304 fprintf(fout, "Offset of igGCregs = %2u\n", offsetof(insGroup, igGCregs));
305 fprintf(fout, "Offset of igInsCnt = %2u\n", offsetof(insGroup, igInsCnt));
306 fprintf(fout, "Size of insGroup = %u\n", sizeof(insGroup));
307
308 // insPlaceholderGroupData members
309
310 fprintf(fout, "\n");
311 fprintf(fout, "insPlaceholderGroupData:\n");
312 fprintf(fout, "Offset of igPhNext = %2u\n", offsetof(insPlaceholderGroupData, igPhNext));
313 fprintf(fout, "Offset of igPhBB = %2u\n", offsetof(insPlaceholderGroupData, igPhBB));
314 fprintf(fout, "Offset of igPhInitGCrefVars = %2u\n", offsetof(insPlaceholderGroupData, igPhInitGCrefVars));
315 fprintf(fout, "Offset of igPhInitGCrefRegs = %2u\n", offsetof(insPlaceholderGroupData, igPhInitGCrefRegs));
316 fprintf(fout, "Offset of igPhInitByrefRegs = %2u\n", offsetof(insPlaceholderGroupData, igPhInitByrefRegs));
317 fprintf(fout, "Offset of igPhPrevGCrefVars = %2u\n", offsetof(insPlaceholderGroupData, igPhPrevGCrefVars));
318 fprintf(fout, "Offset of igPhPrevGCrefRegs = %2u\n", offsetof(insPlaceholderGroupData, igPhPrevGCrefRegs));
319 fprintf(fout, "Offset of igPhPrevByrefRegs = %2u\n", offsetof(insPlaceholderGroupData, igPhPrevByrefRegs));
320 fprintf(fout, "Offset of igPhType = %2u\n", offsetof(insPlaceholderGroupData, igPhType));
321 fprintf(fout, "Size of insPlaceholderGroupData = %u\n", sizeof(insPlaceholderGroupData));
322
323 fprintf(fout, "\n");
324 fprintf(fout, "Size of instrDesc = %2u\n", sizeof(emitter::instrDesc));
325 // fprintf(fout, "Offset of _idIns = %2u\n", offsetof(emitter::instrDesc, _idIns ));
326 // fprintf(fout, "Offset of _idInsFmt = %2u\n", offsetof(emitter::instrDesc, _idInsFmt ));
327 // fprintf(fout, "Offset of _idOpSize = %2u\n", offsetof(emitter::instrDesc, _idOpSize ));
328 // fprintf(fout, "Offset of idSmallCns = %2u\n", offsetof(emitter::instrDesc, idSmallCns ));
329 // fprintf(fout, "Offset of _idAddrUnion= %2u\n", offsetof(emitter::instrDesc, _idAddrUnion));
330 // fprintf(fout, "\n");
331 // fprintf(fout, "Size of _idAddrUnion= %2u\n", sizeof(((emitter::instrDesc*)0)->_idAddrUnion));
332
333 fprintf(fout, "\n");
334 fprintf(fout, "GCInfo::regPtrDsc:\n");
335 fprintf(fout, "Offset of rpdNext = %2u\n", offsetof(GCInfo::regPtrDsc, rpdNext));
336 fprintf(fout, "Offset of rpdOffs = %2u\n", offsetof(GCInfo::regPtrDsc, rpdOffs));
337 fprintf(fout, "Offset of <union> = %2u\n", offsetof(GCInfo::regPtrDsc, rpdPtrArg));
338 fprintf(fout, "Size of GCInfo::regPtrDsc = %2u\n", sizeof(GCInfo::regPtrDsc));
339
340 fprintf(fout, "\n");
341}
342
343void emitterStats(FILE* fout)
344{
345 if (totAllocdSize > 0)
346 {
347 assert(totActualSize <= totAllocdSize);
348
349 fprintf(fout, "\nTotal allocated code size = %u\n", totAllocdSize);
350
351 if (totActualSize < totAllocdSize)
352 {
353 fprintf(fout, "Total generated code size = %u ", totActualSize);
354
355 fprintf(fout, "(%4.3f%% waste)", 100 * ((totAllocdSize - totActualSize) / (double)totActualSize));
356 fprintf(fout, "\n");
357 }
358
359 assert(emitter::emitTotalInsCnt);
360
361 fprintf(fout, "Average of %4.2f bytes of code generated per instruction\n",
362 (double)totActualSize / emitter::emitTotalInsCnt);
363 }
364
365 fprintf(fout, "\nInstruction format frequency table:\n\n");
366
367 unsigned f, ic = 0, dc = 0;
368
369 for (f = 0; f < emitter::IF_COUNT; f++)
370 {
371 ic += emitter::emitIFcounts[f];
372 }
373
374 for (f = 0; f < emitter::IF_COUNT; f++)
375 {
376 unsigned c = emitter::emitIFcounts[f];
377
378 if ((c > 0) && (1000 * c >= ic))
379 {
380 dc += c;
381 fprintf(fout, " %-13s %8u (%5.2f%%)\n", emitter::emitIfName(f), c, 100.0 * c / ic);
382 }
383 }
384
385 fprintf(fout, " --------------------------------\n");
386 fprintf(fout, " %-13s %8u (%5.2f%%)\n", "Total shown", dc, 100.0 * dc / ic);
387
388 if (emitter::emitTotalIGmcnt)
389 {
390 fprintf(fout, "Total of %8u methods\n", emitter::emitTotalIGmcnt);
391 fprintf(fout, "Total of %8u insGroup\n", emitter::emitTotalIGcnt);
392 fprintf(fout, "Total of %8u insPlaceholderGroupData\n", emitter::emitTotalPhIGcnt);
393 fprintf(fout, "Total of %8u instructions\n", emitter::emitTotalIGicnt);
394 fprintf(fout, "Total of %8u jumps\n", emitter::emitTotalIGjmps);
395 fprintf(fout, "Total of %8u GC livesets\n", emitter::emitTotalIGptrs);
396 fprintf(fout, "\n");
397 fprintf(fout, "Average of %8.1lf insGroup per method\n",
398 (double)emitter::emitTotalIGcnt / emitter::emitTotalIGmcnt);
399 fprintf(fout, "Average of %8.1lf insPhGroup per method\n",
400 (double)emitter::emitTotalPhIGcnt / emitter::emitTotalIGmcnt);
401 fprintf(fout, "Average of %8.1lf instructions per method\n",
402 (double)emitter::emitTotalIGicnt / emitter::emitTotalIGmcnt);
403 fprintf(fout, "Average of %8.1lf desc. bytes per method\n",
404 (double)emitter::emitTotalIGsize / emitter::emitTotalIGmcnt);
405 fprintf(fout, "Average of %8.1lf jumps per method\n",
406 (double)emitter::emitTotalIGjmps / emitter::emitTotalIGmcnt);
407 fprintf(fout, "Average of %8.1lf GC livesets per method\n",
408 (double)emitter::emitTotalIGptrs / emitter::emitTotalIGmcnt);
409 fprintf(fout, "\n");
410 fprintf(fout, "Average of %8.1lf instructions per group \n",
411 (double)emitter::emitTotalIGicnt / emitter::emitTotalIGcnt);
412 fprintf(fout, "Average of %8.1lf desc. bytes per group \n",
413 (double)emitter::emitTotalIGsize / emitter::emitTotalIGcnt);
414 fprintf(fout, "Average of %8.1lf jumps per group \n",
415 (double)emitter::emitTotalIGjmps / emitter::emitTotalIGcnt);
416 fprintf(fout, "\n");
417 fprintf(fout, "Average of %8.1lf bytes per instrDesc\n",
418 (double)emitter::emitTotalIGsize / emitter::emitTotalIGicnt);
419 fprintf(fout, "\n");
420 fprintf(fout, "A total of %8u desc. bytes\n", emitter::emitTotalIGsize);
421 fprintf(fout, "\n");
422 }
423
424 fprintf(fout, "Descriptor size distribution:\n");
425 emitSizeTable.dump(fout);
426 fprintf(fout, "\n");
427
428 fprintf(fout, "GC ref frame variable counts:\n");
429 GCrefsTable.dump(fout);
430 fprintf(fout, "\n");
431
432 fprintf(fout, "Max. stack depth distribution:\n");
433 stkDepthTable.dump(fout);
434 fprintf(fout, "\n");
435
436 int i;
437 unsigned c;
438 unsigned m;
439
440 if (emitter::emitSmallCnsCnt || emitter::emitLargeCnsCnt)
441 {
442 fprintf(fout, "SmallCnsCnt = %6u\n", emitter::emitSmallCnsCnt);
443 fprintf(fout, "LargeCnsCnt = %6u (%3u %% of total)\n", emitter::emitLargeCnsCnt,
444 100 * emitter::emitLargeCnsCnt / (emitter::emitLargeCnsCnt + emitter::emitSmallCnsCnt));
445 }
446
447#if 0
448 // TODO-Cleanup: WHy is this in #if 0 - Is EMITTER_STATS ever used? Fix or delete this.
449 if (emitter::emitSmallCnsCnt)
450 {
451 fprintf(fout, "\n");
452
453 m = emitter::emitSmallCnsCnt/1000 + 1;
454
455 for (i = ID_MIN_SMALL_CNS; i < ID_MAX_SMALL_CNS; i++)
456 {
457 c = emitter::emitSmallCns[i-ID_MIN_SMALL_CNS];
458 if (c >= m)
459 fprintf(fout, "cns[%4d] = %u\n", i, c);
460 }
461 }
462#endif // 0
463
464 fprintf(fout, "%8u bytes allocated in the emitter\n", emitter::emitTotMemAlloc);
465}
466
467#endif // EMITTER_STATS
468
469/*****************************************************************************/
470
471const unsigned short emitTypeSizes[] = {
472#define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) sze,
473#include "typelist.h"
474#undef DEF_TP
475};
476
477const unsigned short emitTypeActSz[] = {
478#define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) asze,
479#include "typelist.h"
480#undef DEF_TP
481};
482
483/*****************************************************************************/
484/*****************************************************************************
485 *
486 * Initialize the emitter - called once, at DLL load time.
487 */
488
489void emitter::emitInit()
490{
491}
492
493/*****************************************************************************
494 *
495 * Shut down the emitter - called once, at DLL exit time.
496 */
497
498void emitter::emitDone()
499{
500}
501
502/*****************************************************************************
503 *
504 * Allocate memory.
505 */
506
507void* emitter::emitGetMem(size_t sz)
508{
509 assert(sz % sizeof(int) == 0);
510
511#if EMITTER_STATS
512 emitTotMemAlloc += sz;
513#endif
514
515 return emitComp->getAllocator(CMK_InstDesc).allocate<char>(sz);
516}
517
518/*****************************************************************************
519 *
520 * emitLclVarAddr support methods
521 */
522void emitLclVarAddr::initLclVarAddr(int varNum, unsigned offset)
523{
524 if (varNum < 32768)
525 {
526 if (varNum >= 0)
527 {
528 if (offset < 32768)
529 {
530 _lvaTag = LVA_STANDARD_ENCODING;
531 _lvaExtra = offset; // offset known to be in [0..32767]
532 _lvaVarNum = (unsigned)varNum; // varNum known to be in [0..32767]
533 }
534 else // offset >= 32768
535 {
536 // We could support larger local offsets here at the cost of less varNums
537 if (offset >= 65536)
538 {
539 IMPL_LIMITATION("JIT doesn't support offsets larger than 65535 into valuetypes\n");
540 }
541
542 _lvaTag = LVA_LARGE_OFFSET;
543 _lvaExtra = (offset - 32768); // (offset-32768) is known to be in [0..32767]
544 _lvaVarNum = (unsigned)varNum; // varNum known to be in [0..32767]
545 }
546 }
547 else // varNum < 0, These are used for Compiler spill temps
548 {
549 if (varNum < -32767)
550 {
551 IMPL_LIMITATION("JIT doesn't support more than 32767 Compiler Spill temps\n");
552 }
553 if (offset > 32767)
554 {
555 IMPL_LIMITATION(
556 "JIT doesn't support offsets larger than 32767 into valuetypes for Compiler Spill temps\n");
557 }
558
559 _lvaTag = LVA_COMPILER_TEMP;
560 _lvaExtra = offset; // offset known to be in [0..32767]
561 _lvaVarNum = (unsigned)(-varNum); // -varNum known to be in [1..32767]
562 }
563 }
564 else // varNum >= 32768
565 {
566 if (offset >= 256)
567 {
568 IMPL_LIMITATION("JIT doesn't support offsets larger than 255 into valuetypes for local vars > 32767\n");
569 }
570 if (varNum >= 0x00400000)
571 { // 0x00400000 == 2^22
572 IMPL_LIMITATION("JIT doesn't support more than 2^22 variables\n");
573 }
574
575 _lvaTag = LVA_LARGE_VARNUM;
576 _lvaVarNum = varNum & 0x00007FFF; // varNum bits 14 to 0
577 _lvaExtra = (varNum & 0x003F8000) >> 15; // varNum bits 21 to 15 in _lvaExtra bits 6 to 0, 7 bits total
578 _lvaExtra |= (offset << 7); // offset bits 7 to 0 in _lvaExtra bits 14 to 7, 8 bits total
579 }
580}
581
582// Returns the variable to access. Note that it returns a negative number for compiler spill temps.
583int emitLclVarAddr::lvaVarNum()
584{
585 switch (_lvaTag)
586 {
587 case LVA_COMPILER_TEMP:
588 return -((int)_lvaVarNum);
589 case LVA_LARGE_VARNUM:
590 return (int)(((_lvaExtra & 0x007F) << 15) + _lvaVarNum);
591 default: // LVA_STANDARD_ENCODING or LVA_LARGE_OFFSET
592 assert((_lvaTag == LVA_STANDARD_ENCODING) || (_lvaTag == LVA_LARGE_OFFSET));
593 return (int)_lvaVarNum;
594 }
595}
596
597unsigned emitLclVarAddr::lvaOffset() // returns the offset into the variable to access
598{
599 switch (_lvaTag)
600 {
601 case LVA_LARGE_OFFSET:
602 return (32768 + _lvaExtra);
603 case LVA_LARGE_VARNUM:
604 return (_lvaExtra & 0x7F80) >> 7;
605 default: // LVA_STANDARD_ENCODING or LVA_COMPILER_TEMP
606 assert((_lvaTag == LVA_STANDARD_ENCODING) || (_lvaTag == LVA_COMPILER_TEMP));
607 return _lvaExtra;
608 }
609}
610
611/*****************************************************************************
612 *
613 * Record some info about the method about to be emitted.
614 */
615
616void emitter::emitBegCG(Compiler* comp, COMP_HANDLE cmpHandle)
617{
618 emitComp = comp;
619 emitCmpHandle = cmpHandle;
620}
621
622void emitter::emitEndCG()
623{
624}
625
626/*****************************************************************************
627 *
628 * Prepare the given IG for emission of code.
629 */
630
631void emitter::emitGenIG(insGroup* ig)
632{
633 /* Set the "current IG" value */
634
635 emitCurIG = ig;
636
637#if EMIT_TRACK_STACK_DEPTH
638
639 /* Record the stack level on entry to this group */
640
641 ig->igStkLvl = emitCurStackLvl;
642
643 // If we don't have enough bits in igStkLvl, refuse to compile
644
645 if (ig->igStkLvl != emitCurStackLvl)
646 {
647 IMPL_LIMITATION("Too many arguments pushed on stack");
648 }
649
650// printf("Start IG #%02u [stk=%02u]\n", ig->igNum, emitCurStackLvl);
651
652#endif
653
654 if (emitNoGCIG)
655 {
656 ig->igFlags |= IGF_NOGCINTERRUPT;
657 }
658
659 /* Prepare to issue instructions */
660
661 emitCurIGinsCnt = 0;
662 emitCurIGsize = 0;
663
664 assert(emitCurIGjmpList == nullptr);
665
666 /* Allocate the temp instruction buffer if we haven't done so */
667
668 if (emitCurIGfreeBase == nullptr)
669 {
670 emitIGbuffSize = SC_IG_BUFFER_SIZE;
671 emitCurIGfreeBase = (BYTE*)emitGetMem(emitIGbuffSize);
672 }
673
674 emitCurIGfreeNext = emitCurIGfreeBase;
675 emitCurIGfreeEndp = emitCurIGfreeBase + emitIGbuffSize;
676}
677
678/*****************************************************************************
679 *
680 * Finish and save the current IG.
681 */
682
683insGroup* emitter::emitSavIG(bool emitAdd)
684{
685 insGroup* ig;
686 BYTE* id;
687
688 size_t sz;
689 size_t gs;
690
691 assert(emitCurIGfreeNext <= emitCurIGfreeEndp);
692
693 /* Get hold of the IG descriptor */
694
695 ig = emitCurIG;
696 assert(ig);
697
698 /* Compute how much code we've generated */
699
700 sz = emitCurIGfreeNext - emitCurIGfreeBase;
701
702 /* Compute the total size we need to allocate */
703
704 gs = roundUp(sz);
705
706 /* Do we need space for GC? */
707
708 if (!(ig->igFlags & IGF_EMIT_ADD))
709 {
710 /* Is the initial set of live GC vars different from the previous one? */
711
712 if (emitForceStoreGCState || !VarSetOps::Equal(emitComp, emitPrevGCrefVars, emitInitGCrefVars))
713 {
714 /* Remember that we will have a new set of live GC variables */
715
716 ig->igFlags |= IGF_GC_VARS;
717
718#if EMITTER_STATS
719 emitTotalIGptrs++;
720#endif
721
722 /* We'll allocate extra space to record the liveset */
723
724 gs += sizeof(VARSET_TP);
725 }
726
727 /* Is the initial set of live Byref regs different from the previous one? */
728
729 /* Remember that we will have a new set of live GC variables */
730
731 ig->igFlags |= IGF_BYREF_REGS;
732
733 /* We'll allocate extra space (DWORD aligned) to record the GC regs */
734
735 gs += sizeof(int);
736 }
737
738 /* Allocate space for the instructions and optional liveset */
739
740 id = (BYTE*)emitGetMem(gs);
741
742 /* Do we need to store the byref regs */
743
744 if (ig->igFlags & IGF_BYREF_REGS)
745 {
746 /* Record the byref regs in front the of the instructions */
747
748 *castto(id, unsigned*)++ = (unsigned)emitInitByrefRegs;
749 }
750
751 /* Do we need to store the liveset? */
752
753 if (ig->igFlags & IGF_GC_VARS)
754 {
755 /* Record the liveset in front the of the instructions */
756 VarSetOps::AssignNoCopy(emitComp, (*castto(id, VARSET_TP*)), VarSetOps::MakeEmpty(emitComp));
757 VarSetOps::Assign(emitComp, (*castto(id, VARSET_TP*)++), emitInitGCrefVars);
758 }
759
760 /* Record the collected instructions */
761
762 assert((ig->igFlags & IGF_PLACEHOLDER) == 0);
763 ig->igData = id;
764
765 memcpy(id, emitCurIGfreeBase, sz);
766
767#ifdef DEBUG
768 if (false && emitComp->verbose) // this is not useful in normal dumps (hence it is normally under if (false)
769 {
770 // If there's an error during emission, we may want to connect the post-copy address
771 // of an instrDesc with the pre-copy address (the one that was originally created). This
772 // printing enables that.
773 printf("copying instruction group from [0x%x..0x%x) to [0x%x..0x%x).\n", dspPtr(emitCurIGfreeBase),
774 dspPtr(emitCurIGfreeBase + sz), dspPtr(id), dspPtr(id + sz));
775 }
776#endif
777
778 /* Record how many instructions and bytes of code this group contains */
779
780 noway_assert((BYTE)emitCurIGinsCnt == emitCurIGinsCnt);
781 noway_assert((unsigned short)emitCurIGsize == emitCurIGsize);
782
783 ig->igInsCnt = (BYTE)emitCurIGinsCnt;
784 ig->igSize = (unsigned short)emitCurIGsize;
785 emitCurCodeOffset += emitCurIGsize;
786 assert(IsCodeAligned(emitCurCodeOffset));
787
788#if EMITTER_STATS
789 emitTotalIGicnt += emitCurIGinsCnt;
790 emitTotalIGsize += sz;
791 emitSizeMethod += sz;
792#endif
793
794 // printf("Group [%08X]%3u has %2u instructions (%4u bytes at %08X)\n", ig, ig->igNum, emitCurIGinsCnt, sz, id);
795
796 /* Record the live GC register set - if and only if it is not an emitter added block */
797
798 if (!(ig->igFlags & IGF_EMIT_ADD))
799 {
800 ig->igGCregs = (regMaskSmall)emitInitGCrefRegs;
801 }
802
803 if (!emitAdd)
804 {
805 /* Update the previous recorded live GC ref sets, but not if
806 if we are starting an "overflow" buffer. Note that this is
807 only used to determine whether we need to store or not store
808 the GC ref sets for the next IG, which is dependent on exactly
809 what the state of the emitter GC ref sets will be when the
810 next IG is processed in the emitter.
811 */
812
813 VarSetOps::Assign(emitComp, emitPrevGCrefVars, emitThisGCrefVars);
814 emitPrevGCrefRegs = emitThisGCrefRegs;
815 emitPrevByrefRegs = emitThisByrefRegs;
816
817 emitForceStoreGCState = false;
818 }
819
820#ifdef DEBUG
821 if (emitComp->opts.dspCode)
822 {
823 printf("\n G_M%03u_IG%02u:", Compiler::s_compMethodsCount, ig->igNum);
824 if (emitComp->verbose)
825 {
826 printf(" ; offs=%06XH, funclet=%02u", ig->igOffs, ig->igFuncIdx);
827 }
828 else
829 {
830 printf(" ; funclet=%02u", ig->igFuncIdx);
831 }
832 printf("\n");
833 }
834#endif
835
836 /* Did we have any jumps in this group? */
837
838 if (emitCurIGjmpList)
839 {
840 instrDescJmp* list = nullptr;
841 instrDescJmp* last = nullptr;
842
843 /* Move jumps to the global list, update their 'next' links */
844
845 do
846 {
847 /* Grab the jump and remove it from the list */
848
849 instrDescJmp* oj = emitCurIGjmpList;
850 emitCurIGjmpList = oj->idjNext;
851
852 /* Figure out the address of where the jump got copied */
853
854 size_t of = (BYTE*)oj - emitCurIGfreeBase;
855 instrDescJmp* nj = (instrDescJmp*)(ig->igData + of);
856
857 // printf("Jump moved from %08X to %08X\n", oj, nj);
858 // printf("jmp [%08X] at %08X + %03u\n", nj, ig, nj->idjOffs);
859
860 assert(nj->idjIG == ig);
861 assert(nj->idIns() == oj->idIns());
862 assert(nj->idjNext == oj->idjNext);
863
864 /* Make sure the jumps are correctly ordered */
865
866 assert(last == nullptr || last->idjOffs > nj->idjOffs);
867
868 if (ig->igFlags & IGF_FUNCLET_PROLOG)
869 {
870 // Our funclet prologs have short jumps, if the prolog would ever have
871 // long jumps, then we'd have to insert the list in sorted order than
872 // just append to the emitJumpList.
873 noway_assert(nj->idjShort);
874 if (nj->idjShort)
875 {
876 continue;
877 }
878 }
879
880 /* Append the new jump to the list */
881
882 nj->idjNext = list;
883 list = nj;
884
885 if (last == nullptr)
886 {
887 last = nj;
888 }
889 } while (emitCurIGjmpList);
890
891 if (last != nullptr)
892 {
893 /* Append the jump(s) from this IG to the global list */
894 bool prologJump = (ig == emitPrologIG);
895 if ((emitJumpList == nullptr) || prologJump)
896 {
897 last->idjNext = emitJumpList;
898 emitJumpList = list;
899 }
900 else
901 {
902 last->idjNext = nullptr;
903 emitJumpLast->idjNext = list;
904 }
905
906 if (!prologJump || (emitJumpLast == nullptr))
907 {
908 emitJumpLast = last;
909 }
910 }
911 }
912
913 /* Fix the last instruction field */
914
915 if (sz != 0)
916 {
917 assert(emitLastIns != nullptr);
918 assert(emitCurIGfreeBase <= (BYTE*)emitLastIns);
919 assert((BYTE*)emitLastIns < emitCurIGfreeBase + sz);
920 emitLastIns = (instrDesc*)((BYTE*)id + ((BYTE*)emitLastIns - (BYTE*)emitCurIGfreeBase));
921 }
922
923 /* Reset the buffer free pointers */
924
925 emitCurIGfreeNext = emitCurIGfreeBase;
926
927 return ig;
928}
929
930/*****************************************************************************
931 *
932 * Start generating code to be scheduled; called once per method.
933 */
934
935void emitter::emitBegFN(bool hasFramePtr
936#if defined(DEBUG)
937 ,
938 bool chkAlign
939#endif
940 ,
941 unsigned maxTmpSize)
942{
943 insGroup* ig;
944
945 /* Assume we won't need the temp instruction buffer */
946
947 emitCurIGfreeBase = nullptr;
948 emitIGbuffSize = 0;
949
950 /* Record stack frame info (the temp size is just an estimate) */
951
952 emitHasFramePtr = hasFramePtr;
953
954 emitMaxTmpSize = maxTmpSize;
955
956#ifdef DEBUG
957 emitChkAlign = chkAlign;
958#endif
959
960 /* We have no epilogs yet */
961
962 emitEpilogSize = 0;
963 emitEpilogCnt = 0;
964
965#ifdef _TARGET_XARCH_
966 emitExitSeqBegLoc.Init();
967 emitExitSeqSize = INT_MAX;
968#endif // _TARGET_XARCH_
969
970 emitPlaceholderList = emitPlaceholderLast = nullptr;
971
972#ifdef JIT32_GCENCODER
973 emitEpilogList = emitEpilogLast = nullptr;
974#endif // JIT32_GCENCODER
975
976 /* We don't have any jumps */
977
978 emitJumpList = emitJumpLast = nullptr;
979 emitCurIGjmpList = nullptr;
980
981 emitFwdJumps = false;
982 emitNoGCIG = false;
983 emitForceNewIG = false;
984
985 /* We have not recorded any live sets */
986
987 assert(VarSetOps::IsEmpty(emitComp, emitThisGCrefVars));
988 assert(VarSetOps::IsEmpty(emitComp, emitInitGCrefVars));
989 assert(VarSetOps::IsEmpty(emitComp, emitPrevGCrefVars));
990 emitThisGCrefRegs = RBM_NONE;
991 emitInitGCrefRegs = RBM_NONE;
992 emitPrevGCrefRegs = RBM_NONE;
993 emitThisByrefRegs = RBM_NONE;
994 emitInitByrefRegs = RBM_NONE;
995 emitPrevByrefRegs = RBM_NONE;
996
997 emitForceStoreGCState = false;
998
999#ifdef DEBUG
1000
1001 emitIssuing = false;
1002
1003#endif
1004
1005 /* Assume there will be no GC ref variables */
1006
1007 emitGCrFrameOffsMin = emitGCrFrameOffsMax = emitGCrFrameOffsCnt = 0;
1008#ifdef DEBUG
1009 emitGCrFrameLiveTab = nullptr;
1010#endif
1011
1012 /* We have no groups / code at this point */
1013
1014 emitIGlist = emitIGlast = nullptr;
1015
1016 emitCurCodeOffset = 0;
1017 emitFirstColdIG = nullptr;
1018 emitTotalCodeSize = 0;
1019
1020#if EMITTER_STATS
1021 emitTotalIGmcnt++;
1022 emitSizeMethod = 0;
1023#endif
1024
1025 emitInsCount = 0;
1026
1027 /* The stack is empty now */
1028
1029 emitCurStackLvl = 0;
1030
1031#if EMIT_TRACK_STACK_DEPTH
1032 emitMaxStackDepth = 0;
1033 emitCntStackDepth = sizeof(int);
1034#endif
1035
1036 /* No data sections have been created */
1037
1038 emitDataSecCur = nullptr;
1039
1040 memset(&emitConsDsc, 0, sizeof(emitConsDsc));
1041
1042#ifdef PSEUDORANDOM_NOP_INSERTION
1043 // for random NOP insertion
1044
1045 emitEnableRandomNops();
1046 emitComp->info.compRNG.Init(emitComp->info.compChecksum);
1047 emitNextNop = emitNextRandomNop();
1048 emitInInstrumentation = false;
1049#endif // PSEUDORANDOM_NOP_INSERTION
1050
1051 /* Create the first IG, it will be used for the prolog */
1052
1053 emitNxtIGnum = 1;
1054
1055 emitPrologIG = emitIGlist = emitIGlast = emitCurIG = ig = emitAllocIG();
1056
1057 emitLastIns = nullptr;
1058
1059 ig->igNext = nullptr;
1060
1061#ifdef DEBUG
1062 emitScratchSigInfo = nullptr;
1063#endif // DEBUG
1064
1065 /* Append another group, to start generating the method body */
1066
1067 emitNewIG();
1068}
1069
1070#ifdef PSEUDORANDOM_NOP_INSERTION
1071int emitter::emitNextRandomNop()
1072{
1073 return emitComp->info.compRNG.Next(1, 9);
1074}
1075#endif
1076
1077/*****************************************************************************
1078 *
1079 * Done generating code to be scheduled; called once per method.
1080 */
1081
1082void emitter::emitEndFN()
1083{
1084}
1085
1086// member function iiaIsJitDataOffset for idAddrUnion, defers to Compiler::eeIsJitDataOffs
1087bool emitter::instrDesc::idAddrUnion::iiaIsJitDataOffset() const
1088{
1089 return Compiler::eeIsJitDataOffs(iiaFieldHnd);
1090}
1091
1092// member function iiaGetJitDataOffset for idAddrUnion, defers to Compiler::eeGetJitDataOffs
1093int emitter::instrDesc::idAddrUnion::iiaGetJitDataOffset() const
1094{
1095 assert(iiaIsJitDataOffset());
1096 return Compiler::eeGetJitDataOffs(iiaFieldHnd);
1097}
1098
1099void emitter::dispIns(instrDesc* id)
1100{
1101#ifdef DEBUG
1102 emitInsSanityCheck(id);
1103
1104 if (emitComp->opts.dspCode)
1105 {
1106 emitDispIns(id, true, false, false);
1107 }
1108
1109#if EMIT_TRACK_STACK_DEPTH
1110 assert((int)emitCurStackLvl >= 0);
1111#endif
1112 size_t sz = emitSizeOfInsDsc(id);
1113 assert(id->idDebugOnlyInfo()->idSize == sz);
1114#endif // DEBUG
1115
1116#if EMITTER_STATS
1117 emitIFcounts[id->idInsFmt()]++;
1118#endif
1119}
1120
1121void emitter::appendToCurIG(instrDesc* id)
1122{
1123 emitCurIGsize += id->idCodeSize();
1124}
1125
1126/*****************************************************************************
1127 *
1128 * Display (optionally) an instruction offset.
1129 */
1130
1131#ifdef DEBUG
1132
1133void emitter::emitDispInsOffs(unsigned offs, bool doffs)
1134{
1135 if (doffs)
1136 {
1137 printf("%06X", offs);
1138 }
1139 else
1140 {
1141 printf(" ");
1142 }
1143}
1144
1145#endif // DEBUG
1146
1147#ifdef JIT32_GCENCODER
1148
1149/*****************************************************************************
1150 *
1151 * Call the specified function pointer for each epilog block in the current
1152 * method with the epilog's relative code offset. Returns the sum of the
1153 * values returned by the callback.
1154 */
1155
1156size_t emitter::emitGenEpilogLst(size_t (*fp)(void*, unsigned), void* cp)
1157{
1158 EpilogList* el;
1159 size_t sz;
1160
1161 for (el = emitEpilogList, sz = 0; el != nullptr; el = el->elNext)
1162 {
1163 assert(el->elLoc.GetIG()->igFlags & IGF_EPILOG);
1164
1165 // The epilog starts at the location recorded in the epilog list.
1166 sz += fp(cp, el->elLoc.CodeOffset(this));
1167 }
1168
1169 return sz;
1170}
1171
1172#endif // JIT32_GCENCODER
1173
1174/*****************************************************************************
1175 *
1176 * The following series of methods allocates instruction descriptors.
1177 */
1178
1179void* emitter::emitAllocInstr(size_t sz, emitAttr opsz)
1180{
1181 instrDesc* id;
1182
1183#ifdef DEBUG
1184 // Under STRESS_EMITTER, put every instruction in its own instruction group.
1185 // We can't do this for a prolog, epilog, funclet prolog, or funclet epilog,
1186 // because those are generated out of order. We currently have a limitation
1187 // where the jump shortening pass uses the instruction group number to determine
1188 // if something is earlier or later in the code stream. This implies that
1189 // these groups cannot be more than a single instruction group. Note that
1190 // the prolog/epilog placeholder groups ARE generated in order, and are
1191 // re-used. But generating additional groups would not work.
1192 if (emitComp->compStressCompile(Compiler::STRESS_EMITTER, 1) && emitCurIGinsCnt && !emitIGisInProlog(emitCurIG) &&
1193 !emitIGisInEpilog(emitCurIG)
1194#if FEATURE_EH_FUNCLETS
1195 && !emitIGisInFuncletProlog(emitCurIG) && !emitIGisInFuncletEpilog(emitCurIG)
1196#endif // FEATURE_EH_FUNCLETS
1197 )
1198 {
1199 emitNxtIG(true);
1200 }
1201#endif
1202
1203#ifdef PSEUDORANDOM_NOP_INSERTION
1204 // TODO-ARM-Bug?: PSEUDORANDOM_NOP_INSERTION is not defined for _TARGET_ARM_
1205 // ARM - This is currently broken on _TARGET_ARM_
1206 // When nopSize is odd we misalign emitCurIGsize
1207 //
1208 if (!emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && !emitInInstrumentation &&
1209 !emitIGisInProlog(emitCurIG) && // don't do this in prolog or epilog
1210 !emitIGisInEpilog(emitCurIG) &&
1211 emitRandomNops // sometimes we turn off where exact codegen is needed (pinvoke inline)
1212 )
1213 {
1214 if (emitNextNop == 0)
1215 {
1216 int nopSize = 4;
1217 emitInInstrumentation = true;
1218 instrDesc* idnop = emitNewInstr();
1219 emitInInstrumentation = false;
1220 idnop->idInsFmt(IF_NONE);
1221 idnop->idIns(INS_nop);
1222#if defined(_TARGET_XARCH_)
1223 idnop->idCodeSize(nopSize);
1224#else
1225#error "Undefined target for pseudorandom NOP insertion"
1226#endif
1227
1228 emitCurIGsize += nopSize;
1229 emitNextNop = emitNextRandomNop();
1230 }
1231 else
1232 emitNextNop--;
1233 }
1234#endif // PSEUDORANDOM_NOP_INSERTION
1235
1236 assert(IsCodeAligned(emitCurIGsize));
1237
1238 /* Make sure we have enough space for the new instruction */
1239
1240 if ((emitCurIGfreeNext + sz >= emitCurIGfreeEndp) || emitForceNewIG)
1241 {
1242 emitNxtIG(true);
1243 }
1244
1245 /* Grab the space for the instruction */
1246
1247 emitLastIns = id = (instrDesc*)emitCurIGfreeNext;
1248 emitCurIGfreeNext += sz;
1249
1250 assert(sz >= sizeof(void*));
1251 memset(id, 0, sz);
1252
1253 // These fields should have been zero-ed by the above
1254 assert(id->idReg1() == regNumber(0));
1255 assert(id->idReg2() == regNumber(0));
1256#ifdef _TARGET_XARCH_
1257 assert(id->idCodeSize() == 0);
1258#endif
1259
1260 // Make sure that idAddrUnion is just a union of various pointer sized things
1261 C_ASSERT(sizeof(CORINFO_FIELD_HANDLE) <= sizeof(void*));
1262 C_ASSERT(sizeof(CORINFO_METHOD_HANDLE) <= sizeof(void*));
1263 C_ASSERT(sizeof(emitter::emitAddrMode) <= sizeof(void*));
1264 C_ASSERT(sizeof(emitLclVarAddr) <= sizeof(void*));
1265 C_ASSERT(sizeof(emitter::instrDesc) == (SMALL_IDSC_SIZE + sizeof(void*)));
1266
1267 emitInsCount++;
1268
1269#if defined(DEBUG)
1270 /* In debug mode we clear/set some additional fields */
1271
1272 instrDescDebugInfo* info = (instrDescDebugInfo*)emitGetMem(sizeof(*info));
1273
1274 info->idNum = emitInsCount;
1275 info->idSize = sz;
1276 info->idVarRefOffs = 0;
1277 info->idMemCookie = 0;
1278#ifdef TRANSLATE_PDB
1279 info->idilStart = emitInstrDescILBase;
1280#endif
1281 info->idFinallyCall = false;
1282 info->idCatchRet = false;
1283 info->idCallSig = nullptr;
1284
1285 id->idDebugOnlyInfo(info);
1286
1287#endif // defined(DEBUG)
1288
1289 /* Store the size and handle the two special values
1290 that indicate GCref and ByRef */
1291
1292 if (EA_IS_GCREF(opsz))
1293 {
1294 /* A special value indicates a GCref pointer value */
1295
1296 id->idGCref(GCT_GCREF);
1297 id->idOpSize(EA_PTRSIZE);
1298 }
1299 else if (EA_IS_BYREF(opsz))
1300 {
1301 /* A special value indicates a Byref pointer value */
1302
1303 id->idGCref(GCT_BYREF);
1304 id->idOpSize(EA_PTRSIZE);
1305 }
1306 else
1307 {
1308 id->idGCref(GCT_NONE);
1309 id->idOpSize(EA_SIZE(opsz));
1310 }
1311
1312 // Amd64: ip-relative addressing is supported even when not generating relocatable ngen code
1313 if (EA_IS_DSP_RELOC(opsz)
1314#ifndef _TARGET_AMD64_
1315 && emitComp->opts.compReloc
1316#endif //_TARGET_AMD64_
1317 )
1318 {
1319 /* Mark idInfo()->idDspReloc to remember that the */
1320 /* address mode has a displacement that is relocatable */
1321 id->idSetIsDspReloc();
1322 }
1323
1324 if (EA_IS_CNS_RELOC(opsz) && emitComp->opts.compReloc)
1325 {
1326 /* Mark idInfo()->idCnsReloc to remember that the */
1327 /* instruction has an immediate constant that is relocatable */
1328 id->idSetIsCnsReloc();
1329 }
1330
1331#if EMITTER_STATS
1332 emitTotalInsCnt++;
1333#endif
1334
1335 /* Update the instruction count */
1336
1337 emitCurIGinsCnt++;
1338
1339 return id;
1340}
1341
1342#ifdef DEBUG
1343
1344//------------------------------------------------------------------------
1345// emitCheckIGoffsets: Make sure the code offsets of all instruction groups look reasonable.
1346//
1347// Note: It checks that each instruction group starts right after the previous ig.
1348// For the first cold ig offset is also should be the last hot ig + its size.
1349// emitCurCodeOffs maintains distance for the split case to look like they are consistent.
1350// Also it checks total code size.
1351//
1352void emitter::emitCheckIGoffsets()
1353{
1354 size_t currentOffset = 0;
1355
1356 for (insGroup* tempIG = emitIGlist; tempIG != nullptr; tempIG = tempIG->igNext)
1357 {
1358 if (tempIG->igOffs != currentOffset)
1359 {
1360 printf("Block #%u has offset %08X, expected %08X\n", tempIG->igNum, tempIG->igOffs, currentOffset);
1361 assert(!"bad block offset");
1362 }
1363
1364 currentOffset += tempIG->igSize;
1365 }
1366
1367 if (emitTotalCodeSize != 0 && emitTotalCodeSize != currentOffset)
1368 {
1369 printf("Total code size is %08X, expected %08X\n", emitTotalCodeSize, currentOffset);
1370
1371 assert(!"bad total code size");
1372 }
1373}
1374
1375#endif // DEBUG
1376
1377/*****************************************************************************
1378 *
1379 * Begin generating a method prolog.
1380 */
1381
1382void emitter::emitBegProlog()
1383{
1384 assert(emitComp->compGeneratingProlog);
1385
1386#if EMIT_TRACK_STACK_DEPTH
1387
1388 /* Don't measure stack depth inside the prolog, it's misleading */
1389
1390 emitCntStackDepth = 0;
1391
1392 assert(emitCurStackLvl == 0);
1393
1394#endif
1395
1396 emitNoGCIG = true;
1397 emitForceNewIG = false;
1398
1399 /* Switch to the pre-allocated prolog IG */
1400
1401 emitGenIG(emitPrologIG);
1402
1403 /* Nothing is live on entry to the prolog */
1404
1405 // These were initialized to Empty at the start of compilation.
1406 VarSetOps::ClearD(emitComp, emitInitGCrefVars);
1407 VarSetOps::ClearD(emitComp, emitPrevGCrefVars);
1408 emitInitGCrefRegs = RBM_NONE;
1409 emitPrevGCrefRegs = RBM_NONE;
1410 emitInitByrefRegs = RBM_NONE;
1411 emitPrevByrefRegs = RBM_NONE;
1412}
1413
1414/*****************************************************************************
1415 *
1416 * Return the code offset of the current location in the prolog.
1417 */
1418
1419unsigned emitter::emitGetPrologOffsetEstimate()
1420{
1421 /* For now only allow a single prolog ins group */
1422
1423 assert(emitPrologIG);
1424 assert(emitPrologIG == emitCurIG);
1425
1426 return emitCurIGsize;
1427}
1428
1429/*****************************************************************************
1430 *
1431 * Mark the code offset of the current location as the end of the prolog,
1432 * so it can be used later to compute the actual size of the prolog.
1433 */
1434
1435void emitter::emitMarkPrologEnd()
1436{
1437 assert(emitComp->compGeneratingProlog);
1438
1439 /* For now only allow a single prolog ins group */
1440
1441 assert(emitPrologIG);
1442 assert(emitPrologIG == emitCurIG);
1443
1444 emitPrologEndPos = emitCurOffset();
1445}
1446
1447/*****************************************************************************
1448 *
1449 * Finish generating a method prolog.
1450 */
1451
1452void emitter::emitEndProlog()
1453{
1454 assert(emitComp->compGeneratingProlog);
1455
1456 emitNoGCIG = false;
1457
1458 /* Save the prolog IG if non-empty or if only one block */
1459
1460 if (emitCurIGnonEmpty() || emitCurIG == emitPrologIG)
1461 {
1462 emitSavIG();
1463 }
1464
1465#if EMIT_TRACK_STACK_DEPTH
1466 /* Reset the stack depth values */
1467
1468 emitCurStackLvl = 0;
1469 emitCntStackDepth = sizeof(int);
1470#endif
1471}
1472
1473/*****************************************************************************
1474 *
1475 * Create a placeholder instruction group to be used by a prolog or epilog,
1476 * either for the main function, or a funclet.
1477 */
1478
1479void emitter::emitCreatePlaceholderIG(insGroupPlaceholderType igType,
1480 BasicBlock* igBB,
1481 VARSET_VALARG_TP GCvars,
1482 regMaskTP gcrefRegs,
1483 regMaskTP byrefRegs,
1484 bool last)
1485{
1486 assert(igBB != nullptr);
1487
1488 bool emitAdd = false;
1489
1490 if (igType == IGPT_EPILOG
1491#if FEATURE_EH_FUNCLETS
1492 || igType == IGPT_FUNCLET_EPILOG
1493#endif // FEATURE_EH_FUNCLETS
1494 )
1495 {
1496#ifdef _TARGET_AMD64_
1497 emitOutputPreEpilogNOP();
1498#endif // _TARGET_AMD64_
1499
1500 emitAdd = true;
1501 }
1502
1503 if (emitCurIGnonEmpty())
1504 {
1505 emitNxtIG(emitAdd);
1506 }
1507
1508 /* Update GC tracking for the beginning of the placeholder IG */
1509
1510 if (!emitAdd)
1511 {
1512 VarSetOps::Assign(emitComp, emitThisGCrefVars, GCvars);
1513 VarSetOps::Assign(emitComp, emitInitGCrefVars, GCvars);
1514 emitThisGCrefRegs = emitInitGCrefRegs = gcrefRegs;
1515 emitThisByrefRegs = emitInitByrefRegs = byrefRegs;
1516 }
1517
1518 /* Convert the group to a placeholder group */
1519
1520 insGroup* igPh = emitCurIG;
1521
1522 igPh->igFlags |= IGF_PLACEHOLDER;
1523
1524 /* Note that we might be re-using a previously created but empty IG. In this
1525 * case, we need to make sure any re-used fields, such as igFuncIdx, are correct.
1526 */
1527
1528 igPh->igFuncIdx = emitComp->compCurrFuncIdx;
1529
1530 /* Create a separate block of memory to store placeholder information.
1531 * We could use unions to put some of this into the insGroup itself, but we don't
1532 * want to grow the insGroup, and it's difficult to make sure the
1533 * insGroup fields are getting set and used elsewhere.
1534 */
1535
1536 igPh->igPhData = new (emitComp, CMK_InstDesc) insPlaceholderGroupData;
1537
1538 igPh->igPhData->igPhNext = nullptr;
1539 igPh->igPhData->igPhType = igType;
1540 igPh->igPhData->igPhBB = igBB;
1541
1542 VarSetOps::AssignNoCopy(emitComp, igPh->igPhData->igPhPrevGCrefVars, VarSetOps::UninitVal());
1543 VarSetOps::Assign(emitComp, igPh->igPhData->igPhPrevGCrefVars, emitPrevGCrefVars);
1544 igPh->igPhData->igPhPrevGCrefRegs = emitPrevGCrefRegs;
1545 igPh->igPhData->igPhPrevByrefRegs = emitPrevByrefRegs;
1546
1547 VarSetOps::AssignNoCopy(emitComp, igPh->igPhData->igPhInitGCrefVars, VarSetOps::UninitVal());
1548 VarSetOps::Assign(emitComp, igPh->igPhData->igPhInitGCrefVars, emitInitGCrefVars);
1549 igPh->igPhData->igPhInitGCrefRegs = emitInitGCrefRegs;
1550 igPh->igPhData->igPhInitByrefRegs = emitInitByrefRegs;
1551
1552#if EMITTER_STATS
1553 emitTotalPhIGcnt += 1;
1554#endif
1555
1556 // Mark function prologs and epilogs properly in the igFlags bits. These bits
1557 // will get used and propagated when the placeholder is converted to a non-placeholder
1558 // during prolog/epilog generation.
1559
1560 if (igType == IGPT_EPILOG)
1561 {
1562 igPh->igFlags |= IGF_EPILOG;
1563 }
1564#if FEATURE_EH_FUNCLETS
1565 else if (igType == IGPT_FUNCLET_PROLOG)
1566 {
1567 igPh->igFlags |= IGF_FUNCLET_PROLOG;
1568 }
1569 else if (igType == IGPT_FUNCLET_EPILOG)
1570 {
1571 igPh->igFlags |= IGF_FUNCLET_EPILOG;
1572 }
1573#endif // FEATURE_EH_FUNCLETS
1574
1575 /* Link it into the placeholder list */
1576
1577 if (emitPlaceholderList)
1578 {
1579 emitPlaceholderLast->igPhData->igPhNext = igPh;
1580 }
1581 else
1582 {
1583 emitPlaceholderList = igPh;
1584 }
1585
1586 emitPlaceholderLast = igPh;
1587
1588 // Give an estimated size of this placeholder IG and
1589 // increment emitCurCodeOffset since we are not calling emitNewIG()
1590 //
1591 emitCurIGsize += MAX_PLACEHOLDER_IG_SIZE;
1592 emitCurCodeOffset += emitCurIGsize;
1593
1594#if FEATURE_EH_FUNCLETS
1595 // Add the appropriate IP mapping debugging record for this placeholder
1596 // group. genExitCode() adds the mapping for main function epilogs.
1597 if (emitComp->opts.compDbgInfo)
1598 {
1599 if (igType == IGPT_FUNCLET_PROLOG)
1600 {
1601 codeGen->genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::PROLOG, true);
1602 }
1603 else if (igType == IGPT_FUNCLET_EPILOG)
1604 {
1605 codeGen->genIPmappingAdd((IL_OFFSETX)ICorDebugInfo::EPILOG, true);
1606 }
1607 }
1608#endif // FEATURE_EH_FUNCLETS
1609
1610 /* Start a new IG if more code follows */
1611
1612 if (last)
1613 {
1614 emitCurIG = nullptr;
1615 }
1616 else
1617 {
1618 if (igType == IGPT_EPILOG
1619#if FEATURE_EH_FUNCLETS
1620 || igType == IGPT_FUNCLET_EPILOG
1621#endif // FEATURE_EH_FUNCLETS
1622 )
1623 {
1624 // If this was an epilog, then assume this is the end of any currently in progress
1625 // no-GC region. If a block after the epilog needs to be no-GC, it needs to call
1626 // emitter::emitDisableGC() directly. This behavior is depended upon by the fast
1627 // tailcall implementation, which disables GC at the beginning of argument setup,
1628 // but assumes that after the epilog it will be re-enabled.
1629 emitNoGCIG = false;
1630 }
1631
1632 emitNewIG();
1633
1634 // We don't know what the GC ref state will be at the end of the placeholder
1635 // group. So, force the next IG to store all the GC ref state variables;
1636 // don't omit them because emitPrev* is the same as emitInit*, because emitPrev*
1637 // will be inaccurate. (Note that, currently, GCrefRegs and ByrefRegs are always
1638 // saved anyway.)
1639 //
1640 // There is no need to re-initialize the emitPrev* variables, as they won't be used
1641 // with emitForceStoreGCState==true, and will be re-initialized just before
1642 // emitForceStoreGCState is set to false;
1643
1644 emitForceStoreGCState = true;
1645
1646 /* The group after the placeholder group doesn't get the "propagate" flags */
1647
1648 emitCurIG->igFlags &= ~IGF_PROPAGATE_MASK;
1649 }
1650
1651#ifdef DEBUG
1652 if (emitComp->verbose)
1653 {
1654 printf("*************** After placeholder IG creation\n");
1655 emitDispIGlist(false);
1656 }
1657#endif
1658}
1659
1660/*****************************************************************************
1661 *
1662 * Generate all prologs and epilogs
1663 */
1664
1665void emitter::emitGeneratePrologEpilog()
1666{
1667#ifdef DEBUG
1668 unsigned prologCnt = 0;
1669 unsigned epilogCnt = 0;
1670#if FEATURE_EH_FUNCLETS
1671 unsigned funcletPrologCnt = 0;
1672 unsigned funcletEpilogCnt = 0;
1673#endif // FEATURE_EH_FUNCLETS
1674#endif // DEBUG
1675
1676 insGroup* igPh;
1677 insGroup* igPhNext;
1678
1679 // Generating the prolog/epilog is going to destroy the placeholder group,
1680 // so save the "next" pointer before that happens.
1681
1682 for (igPh = emitPlaceholderList; igPh != nullptr; igPh = igPhNext)
1683 {
1684 assert(igPh->igFlags & IGF_PLACEHOLDER);
1685
1686 igPhNext = igPh->igPhData->igPhNext;
1687
1688 BasicBlock* igPhBB = igPh->igPhData->igPhBB;
1689
1690 switch (igPh->igPhData->igPhType)
1691 {
1692 case IGPT_PROLOG: // currently unused
1693 INDEBUG(++prologCnt);
1694 break;
1695
1696 case IGPT_EPILOG:
1697 INDEBUG(++epilogCnt);
1698 emitBegFnEpilog(igPh);
1699 codeGen->genFnEpilog(igPhBB);
1700 emitEndFnEpilog();
1701 break;
1702
1703#if FEATURE_EH_FUNCLETS
1704
1705 case IGPT_FUNCLET_PROLOG:
1706 INDEBUG(++funcletPrologCnt);
1707 emitBegFuncletProlog(igPh);
1708 codeGen->genFuncletProlog(igPhBB);
1709 emitEndFuncletProlog();
1710 break;
1711
1712 case IGPT_FUNCLET_EPILOG:
1713 INDEBUG(++funcletEpilogCnt);
1714 emitBegFuncletEpilog(igPh);
1715 codeGen->genFuncletEpilog();
1716 emitEndFuncletEpilog();
1717 break;
1718
1719#endif // FEATURE_EH_FUNCLETS
1720
1721 default:
1722 unreached();
1723 }
1724 }
1725
1726#ifdef DEBUG
1727 if (emitComp->verbose)
1728 {
1729 printf("%d prologs, %d epilogs", prologCnt, epilogCnt);
1730#if FEATURE_EH_FUNCLETS
1731 printf(", %d funclet prologs, %d funclet epilogs", funcletPrologCnt, funcletEpilogCnt);
1732#endif // FEATURE_EH_FUNCLETS
1733 printf("\n");
1734
1735// prolog/epilog code doesn't use this yet
1736// noway_assert(prologCnt == 1);
1737// noway_assert(epilogCnt == emitEpilogCnt); // Is this correct?
1738#if FEATURE_EH_FUNCLETS
1739 assert(funcletPrologCnt == emitComp->ehFuncletCount());
1740#endif // FEATURE_EH_FUNCLETS
1741 }
1742#endif // DEBUG
1743}
1744
1745/*****************************************************************************
1746 *
1747 * Begin all prolog and epilog generation
1748 */
1749
1750void emitter::emitStartPrologEpilogGeneration()
1751{
1752 /* Save the current IG if it's non-empty */
1753
1754 if (emitCurIGnonEmpty())
1755 {
1756 emitSavIG();
1757 }
1758 else
1759 {
1760 assert(emitCurIG == nullptr);
1761 }
1762}
1763
1764/*****************************************************************************
1765 *
1766 * Finish all prolog and epilog generation
1767 */
1768
1769void emitter::emitFinishPrologEpilogGeneration()
1770{
1771 /* Update the offsets of all the blocks */
1772
1773 emitRecomputeIGoffsets();
1774
1775 /* We should not generate any more code after this */
1776
1777 emitCurIG = nullptr;
1778}
1779
1780/*****************************************************************************
1781 *
1782 * Common code for prolog / epilog beginning. Convert the placeholder group to actual code IG,
1783 * and set it as the current group.
1784 */
1785
1786void emitter::emitBegPrologEpilog(insGroup* igPh)
1787{
1788 assert(igPh->igFlags & IGF_PLACEHOLDER);
1789
1790 /* Save the current IG if it's non-empty */
1791
1792 if (emitCurIGnonEmpty())
1793 {
1794 emitSavIG();
1795 }
1796
1797 /* Convert the placeholder group to a normal group.
1798 * We need to be very careful to re-initialize the IG properly.
1799 * It turns out, this means we only need to clear the placeholder bit
1800 * and clear the igPhData field, and emitGenIG() will do the rest,
1801 * since in the placeholder IG we didn't touch anything that is set by emitAllocIG().
1802 */
1803
1804 igPh->igFlags &= ~IGF_PLACEHOLDER;
1805 emitNoGCIG = true;
1806 emitForceNewIG = false;
1807
1808 /* Set up the GC info that we stored in the placeholder */
1809
1810 VarSetOps::Assign(emitComp, emitPrevGCrefVars, igPh->igPhData->igPhPrevGCrefVars);
1811 emitPrevGCrefRegs = igPh->igPhData->igPhPrevGCrefRegs;
1812 emitPrevByrefRegs = igPh->igPhData->igPhPrevByrefRegs;
1813
1814 VarSetOps::Assign(emitComp, emitThisGCrefVars, igPh->igPhData->igPhInitGCrefVars);
1815 VarSetOps::Assign(emitComp, emitInitGCrefVars, igPh->igPhData->igPhInitGCrefVars);
1816 emitThisGCrefRegs = emitInitGCrefRegs = igPh->igPhData->igPhInitGCrefRegs;
1817 emitThisByrefRegs = emitInitByrefRegs = igPh->igPhData->igPhInitByrefRegs;
1818
1819 igPh->igPhData = nullptr;
1820
1821 /* Create a non-placeholder group pointer that we'll now use */
1822
1823 insGroup* ig = igPh;
1824
1825 /* Set the current function using the function index we stored */
1826
1827 emitComp->funSetCurrentFunc(ig->igFuncIdx);
1828
1829 /* Set the new IG as the place to generate code */
1830
1831 emitGenIG(ig);
1832
1833#if EMIT_TRACK_STACK_DEPTH
1834
1835 /* Don't measure stack depth inside the prolog / epilog, it's misleading */
1836
1837 emitCntStackDepth = 0;
1838
1839 assert(emitCurStackLvl == 0);
1840
1841#endif
1842}
1843
1844/*****************************************************************************
1845 *
1846 * Common code for end of prolog / epilog
1847 */
1848
1849void emitter::emitEndPrologEpilog()
1850{
1851 emitNoGCIG = false;
1852
1853 /* Save the IG if non-empty */
1854
1855 if (emitCurIGnonEmpty())
1856 {
1857 emitSavIG();
1858 }
1859
1860 assert(emitCurIGsize <= MAX_PLACEHOLDER_IG_SIZE);
1861
1862#if EMIT_TRACK_STACK_DEPTH
1863 /* Reset the stack depth values */
1864
1865 emitCurStackLvl = 0;
1866 emitCntStackDepth = sizeof(int);
1867#endif
1868}
1869
1870/*****************************************************************************
1871 *
1872 * Begin generating a main function epilog.
1873 */
1874
1875void emitter::emitBegFnEpilog(insGroup* igPh)
1876{
1877 emitEpilogCnt++;
1878
1879 emitBegPrologEpilog(igPh);
1880
1881#ifdef JIT32_GCENCODER
1882
1883 EpilogList* el = new (emitComp, CMK_GC) EpilogList();
1884
1885 if (emitEpilogLast != nullptr)
1886 {
1887 emitEpilogLast->elNext = el;
1888 }
1889 else
1890 {
1891 emitEpilogList = el;
1892 }
1893
1894 emitEpilogLast = el;
1895
1896#endif // JIT32_GCENCODER
1897}
1898
1899/*****************************************************************************
1900 *
1901 * Finish generating a funclet epilog.
1902 */
1903
1904void emitter::emitEndFnEpilog()
1905{
1906 emitEndPrologEpilog();
1907
1908#ifdef JIT32_GCENCODER
1909 assert(emitEpilogLast != nullptr);
1910
1911 UNATIVE_OFFSET epilogBegCodeOffset = emitEpilogLast->elLoc.CodeOffset(this);
1912 UNATIVE_OFFSET epilogExitSeqStartCodeOffset = emitExitSeqBegLoc.CodeOffset(this);
1913 UNATIVE_OFFSET newSize = epilogExitSeqStartCodeOffset - epilogBegCodeOffset;
1914
1915 /* Compute total epilog size */
1916 assert(emitEpilogSize == 0 || emitEpilogSize == newSize); // All epilogs must be identical
1917 emitEpilogSize = newSize;
1918
1919 UNATIVE_OFFSET epilogEndCodeOffset = emitCodeOffset(emitCurIG, emitCurOffset());
1920 assert(epilogExitSeqStartCodeOffset != epilogEndCodeOffset);
1921
1922 newSize = epilogEndCodeOffset - epilogExitSeqStartCodeOffset;
1923 if (newSize < emitExitSeqSize)
1924 {
1925 // We expect either the epilog to be the same every time, or that
1926 // one will be a ret or a ret <n> and others will be a jmp addr or jmp [addr];
1927 // we make the epilogs the minimum of these. Note that this ONLY works
1928 // because the only instruction is the last one and thus a slight
1929 // underestimation of the epilog size is harmless (since the EIP
1930 // can not be between instructions).
1931 assert(emitEpilogCnt == 1 ||
1932 (emitExitSeqSize - newSize) <= 5 // delta between size of various forms of jmp (size is either 6 or 5)
1933 // and various forms of ret (size is either 1 or 3). The combination can
1934 // be anything been 1 and 5.
1935 );
1936 emitExitSeqSize = newSize;
1937 }
1938#endif // JIT32_GCENCODER
1939}
1940
1941#if FEATURE_EH_FUNCLETS
1942
1943/*****************************************************************************
1944 *
1945 * Begin generating a funclet prolog.
1946 */
1947
1948void emitter::emitBegFuncletProlog(insGroup* igPh)
1949{
1950 emitBegPrologEpilog(igPh);
1951}
1952
1953/*****************************************************************************
1954 *
1955 * Finish generating a funclet prolog.
1956 */
1957
1958void emitter::emitEndFuncletProlog()
1959{
1960 emitEndPrologEpilog();
1961}
1962
1963/*****************************************************************************
1964 *
1965 * Begin generating a funclet epilog.
1966 */
1967
1968void emitter::emitBegFuncletEpilog(insGroup* igPh)
1969{
1970 emitBegPrologEpilog(igPh);
1971}
1972
1973/*****************************************************************************
1974 *
1975 * Finish generating a funclet epilog.
1976 */
1977
1978void emitter::emitEndFuncletEpilog()
1979{
1980 emitEndPrologEpilog();
1981}
1982
1983#endif // FEATURE_EH_FUNCLETS
1984
1985#ifdef JIT32_GCENCODER
1986
1987//
1988// emitter::emitStartEpilog:
1989// Mark the current position so that we can later compute the total epilog size.
1990//
1991void emitter::emitStartEpilog()
1992{
1993 assert(emitEpilogLast != nullptr);
1994 emitEpilogLast->elLoc.CaptureLocation(this);
1995}
1996
1997/*****************************************************************************
1998 *
1999 * Return non-zero if the current method only has one epilog, which is
2000 * at the very end of the method body.
2001 */
2002
2003bool emitter::emitHasEpilogEnd()
2004{
2005 if (emitEpilogCnt == 1 && (emitIGlast->igFlags & IGF_EPILOG)) // This wouldn't work for funclets
2006 return true;
2007 else
2008 return false;
2009}
2010
2011#endif // JIT32_GCENCODER
2012
2013#ifdef _TARGET_XARCH_
2014
2015/*****************************************************************************
2016 *
2017 * Mark the beginning of the epilog exit sequence by remembering our position.
2018 */
2019
2020void emitter::emitStartExitSeq()
2021{
2022 assert(emitComp->compGeneratingEpilog);
2023
2024 emitExitSeqBegLoc.CaptureLocation(this);
2025}
2026
2027#endif // _TARGET_XARCH_
2028
2029/*****************************************************************************
2030 *
2031 * The code generator tells us the range of GC ref locals through this
2032 * method. Needless to say, locals and temps should be allocated so that
2033 * the size of the range is as small as possible.
2034 *
2035 * offsLo - The FP offset from which the GC pointer range starts.
2036 * offsHi - The FP offset at which the GC pointer region ends (exclusive).
2037 */
2038
2039void emitter::emitSetFrameRangeGCRs(int offsLo, int offsHi)
2040{
2041 assert(emitComp->compGeneratingProlog);
2042 assert(offsHi > offsLo);
2043
2044#ifdef DEBUG
2045
2046 // A total of 47254 methods compiled.
2047 //
2048 // GC ref frame variable counts:
2049 //
2050 // <= 0 ===> 43175 count ( 91% of total)
2051 // 1 .. 1 ===> 2367 count ( 96% of total)
2052 // 2 .. 2 ===> 887 count ( 98% of total)
2053 // 3 .. 5 ===> 579 count ( 99% of total)
2054 // 6 .. 10 ===> 141 count ( 99% of total)
2055 // 11 .. 20 ===> 40 count ( 99% of total)
2056 // 21 .. 50 ===> 42 count ( 99% of total)
2057 // 51 .. 128 ===> 15 count ( 99% of total)
2058 // 129 .. 256 ===> 4 count ( 99% of total)
2059 // 257 .. 512 ===> 4 count (100% of total)
2060 // 513 .. 1024 ===> 0 count (100% of total)
2061
2062 if (emitComp->verbose)
2063 {
2064 unsigned count = (offsHi - offsLo) / TARGET_POINTER_SIZE;
2065 printf("%u tracked GC refs are at stack offsets ", count);
2066
2067 if (offsLo >= 0)
2068 {
2069 printf(" %04X ... %04X\n", offsLo, offsHi);
2070 assert(offsHi >= 0);
2071 }
2072 else
2073#if defined(_TARGET_ARM_) && defined(PROFILING_SUPPORTED)
2074 if (!emitComp->compIsProfilerHookNeeded())
2075#endif
2076 {
2077#ifdef _TARGET_AMD64_
2078 // doesn't have to be all negative on amd
2079 printf("-%04X ... %04X\n", -offsLo, offsHi);
2080#else
2081 printf("-%04X ... -%04X\n", -offsLo, -offsHi);
2082 assert(offsHi <= 0);
2083#endif
2084 }
2085#if defined(_TARGET_ARM_) && defined(PROFILING_SUPPORTED)
2086 else
2087 {
2088 // Under profiler due to prespilling of arguments, offHi need not be < 0
2089 if (offsHi < 0)
2090 printf("-%04X ... -%04X\n", -offsLo, -offsHi);
2091 else
2092 printf("-%04X ... %04X\n", -offsLo, offsHi);
2093 }
2094#endif
2095 }
2096
2097#endif // DEBUG
2098
2099 assert(((offsHi - offsLo) % TARGET_POINTER_SIZE) == 0);
2100 assert((offsLo % TARGET_POINTER_SIZE) == 0);
2101 assert((offsHi % TARGET_POINTER_SIZE) == 0);
2102
2103 emitGCrFrameOffsMin = offsLo;
2104 emitGCrFrameOffsMax = offsHi;
2105 emitGCrFrameOffsCnt = (offsHi - offsLo) / TARGET_POINTER_SIZE;
2106}
2107
2108/*****************************************************************************
2109 *
2110 * The code generator tells us the range of local variables through this
2111 * method.
2112 */
2113
2114void emitter::emitSetFrameRangeLcls(int offsLo, int offsHi)
2115{
2116}
2117
2118/*****************************************************************************
2119 *
2120 * The code generator tells us the range of used arguments through this
2121 * method.
2122 */
2123
2124void emitter::emitSetFrameRangeArgs(int offsLo, int offsHi)
2125{
2126}
2127
2128/*****************************************************************************
2129 *
2130 * A conversion table used to map an operand size value (in bytes) into its
2131 * small encoding (0 through 3), and vice versa.
2132 */
2133
2134const emitter::opSize emitter::emitSizeEncode[] = {
2135 emitter::OPSZ1, emitter::OPSZ2, OPSIZE_INVALID, emitter::OPSZ4, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2136 emitter::OPSZ8, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2137 OPSIZE_INVALID, emitter::OPSZ16, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2138 OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID,
2139 OPSIZE_INVALID, OPSIZE_INVALID, OPSIZE_INVALID, emitter::OPSZ32,
2140};
2141
2142const emitAttr emitter::emitSizeDecode[emitter::OPSZ_COUNT] = {EA_1BYTE, EA_2BYTE, EA_4BYTE,
2143 EA_8BYTE, EA_16BYTE, EA_32BYTE};
2144
2145/*****************************************************************************
2146 *
2147 * Allocate an instruction descriptor for an instruction that uses both
2148 * a displacement and a constant.
2149 */
2150
2151emitter::instrDesc* emitter::emitNewInstrCnsDsp(emitAttr size, target_ssize_t cns, int dsp)
2152{
2153 if (dsp == 0)
2154 {
2155 if (instrDesc::fitsInSmallCns(cns))
2156 {
2157 instrDesc* id = emitAllocInstr(size);
2158
2159 id->idSmallCns(cns);
2160
2161#if EMITTER_STATS
2162 emitSmallCnsCnt++;
2163 emitSmallCns[cns - ID_MIN_SMALL_CNS]++;
2164 emitSmallDspCnt++;
2165#endif
2166
2167 return id;
2168 }
2169 else
2170 {
2171 instrDescCns* id = emitAllocInstrCns(size);
2172
2173 id->idSetIsLargeCns();
2174 id->idcCnsVal = cns;
2175
2176#if EMITTER_STATS
2177 emitLargeCnsCnt++;
2178 emitSmallDspCnt++;
2179#endif
2180
2181 return id;
2182 }
2183 }
2184 else
2185 {
2186 if (instrDesc::fitsInSmallCns(cns))
2187 {
2188 instrDescDsp* id = emitAllocInstrDsp(size);
2189
2190 id->idSetIsLargeDsp();
2191 id->iddDspVal = dsp;
2192
2193 id->idSmallCns(cns);
2194
2195#if EMITTER_STATS
2196 emitLargeDspCnt++;
2197 emitSmallCnsCnt++;
2198 emitSmallCns[cns - ID_MIN_SMALL_CNS]++;
2199#endif
2200
2201 return id;
2202 }
2203 else
2204 {
2205 instrDescCnsDsp* id = emitAllocInstrCnsDsp(size);
2206
2207 id->idSetIsLargeCns();
2208 id->iddcCnsVal = cns;
2209
2210 id->idSetIsLargeDsp();
2211 id->iddcDspVal = dsp;
2212
2213#if EMITTER_STATS
2214 emitLargeDspCnt++;
2215 emitLargeCnsCnt++;
2216#endif
2217
2218 return id;
2219 }
2220 }
2221}
2222
2223//------------------------------------------------------------------------
2224// emitNoGChelper: Returns true if garbage collection won't happen within the helper call.
2225//
2226// Notes:
2227// There is no need to record live pointers for such call sites.
2228//
2229// Arguments:
2230// helpFunc - a helper signature for the call, can be CORINFO_HELP_UNDEF, that means that the call is not a helper.
2231//
2232// Return value:
2233// true if GC can't happen within this call, false otherwise.
2234bool emitter::emitNoGChelper(CorInfoHelpFunc helpFunc)
2235{
2236 // TODO-Throughput: Make this faster (maybe via a simple table of bools?)
2237
2238 switch (helpFunc)
2239 {
2240 case CORINFO_HELP_UNDEF:
2241 return false;
2242
2243 case CORINFO_HELP_PROF_FCN_LEAVE:
2244 case CORINFO_HELP_PROF_FCN_ENTER:
2245#if defined(_TARGET_XARCH_)
2246 case CORINFO_HELP_PROF_FCN_TAILCALL:
2247#endif
2248 case CORINFO_HELP_LLSH:
2249 case CORINFO_HELP_LRSH:
2250 case CORINFO_HELP_LRSZ:
2251
2252// case CORINFO_HELP_LMUL:
2253// case CORINFO_HELP_LDIV:
2254// case CORINFO_HELP_LMOD:
2255// case CORINFO_HELP_ULDIV:
2256// case CORINFO_HELP_ULMOD:
2257
2258#ifdef _TARGET_X86_
2259 case CORINFO_HELP_ASSIGN_REF_EAX:
2260 case CORINFO_HELP_ASSIGN_REF_ECX:
2261 case CORINFO_HELP_ASSIGN_REF_EBX:
2262 case CORINFO_HELP_ASSIGN_REF_EBP:
2263 case CORINFO_HELP_ASSIGN_REF_ESI:
2264 case CORINFO_HELP_ASSIGN_REF_EDI:
2265
2266 case CORINFO_HELP_CHECKED_ASSIGN_REF_EAX:
2267 case CORINFO_HELP_CHECKED_ASSIGN_REF_ECX:
2268 case CORINFO_HELP_CHECKED_ASSIGN_REF_EBX:
2269 case CORINFO_HELP_CHECKED_ASSIGN_REF_EBP:
2270 case CORINFO_HELP_CHECKED_ASSIGN_REF_ESI:
2271 case CORINFO_HELP_CHECKED_ASSIGN_REF_EDI:
2272#endif
2273
2274 case CORINFO_HELP_ASSIGN_REF:
2275 case CORINFO_HELP_CHECKED_ASSIGN_REF:
2276 case CORINFO_HELP_ASSIGN_BYREF:
2277
2278 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
2279 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
2280
2281 case CORINFO_HELP_INIT_PINVOKE_FRAME:
2282 return true;
2283
2284 default:
2285 return false;
2286 }
2287}
2288
2289//------------------------------------------------------------------------
2290// emitNoGChelper: Returns true if garbage collection won't happen within the helper call.
2291//
2292// Notes:
2293// There is no need to record live pointers for such call sites.
2294//
2295// Arguments:
2296// methHnd - a method handle for the call.
2297//
2298// Return value:
2299// true if GC can't happen within this call, false otherwise.
2300bool emitter::emitNoGChelper(CORINFO_METHOD_HANDLE methHnd)
2301{
2302 CorInfoHelpFunc helpFunc = Compiler::eeGetHelperNum(methHnd);
2303 if (helpFunc == CORINFO_HELP_UNDEF)
2304 {
2305 return false;
2306 }
2307 return emitNoGChelper(helpFunc);
2308}
2309
2310/*****************************************************************************
2311 *
2312 * Mark the current spot as having a label.
2313 */
2314
2315void* emitter::emitAddLabel(VARSET_VALARG_TP GCvars, regMaskTP gcrefRegs, regMaskTP byrefRegs, BOOL isFinallyTarget)
2316{
2317 /* Create a new IG if the current one is non-empty */
2318
2319 if (emitCurIGnonEmpty())
2320 {
2321 emitNxtIG();
2322 }
2323
2324 VarSetOps::Assign(emitComp, emitThisGCrefVars, GCvars);
2325 VarSetOps::Assign(emitComp, emitInitGCrefVars, GCvars);
2326 emitThisGCrefRegs = emitInitGCrefRegs = gcrefRegs;
2327 emitThisByrefRegs = emitInitByrefRegs = byrefRegs;
2328
2329#if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2330 if (isFinallyTarget)
2331 {
2332 emitCurIG->igFlags |= IGF_FINALLY_TARGET;
2333 }
2334#endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
2335
2336#ifdef DEBUG
2337 if (EMIT_GC_VERBOSE)
2338 {
2339 printf("Label: IG%02u, GCvars=%s ", emitCurIG->igNum, VarSetOps::ToString(emitComp, GCvars));
2340 dumpConvertedVarSet(emitComp, GCvars);
2341 printf(", gcrefRegs=");
2342 printRegMaskInt(gcrefRegs);
2343 emitDispRegSet(gcrefRegs);
2344 printf(", byrefRegs=");
2345 printRegMaskInt(byrefRegs);
2346 emitDispRegSet(byrefRegs);
2347 printf("\n");
2348 }
2349#endif
2350 return emitCurIG;
2351}
2352
2353#ifdef _TARGET_ARMARCH_
2354
2355// Does the argument location point to an IG at the end of a function or funclet?
2356// We can ignore the codePos part of the location, since it doesn't affect the
2357// determination. If 'emitLocNextFragment' is non-NULL, it indicates the first
2358// IG of the next fragment, so it represents a function end.
2359bool emitter::emitIsFuncEnd(emitLocation* emitLoc, emitLocation* emitLocNextFragment /* = NULL */)
2360{
2361 assert(emitLoc);
2362
2363 insGroup* ig = emitLoc->GetIG();
2364 assert(ig);
2365
2366 // Are we at the end of the IG list?
2367 if ((emitLocNextFragment != NULL) && (ig->igNext == emitLocNextFragment->GetIG()))
2368 return true;
2369
2370 // Safety check
2371 if (ig->igNext == NULL)
2372 return true;
2373
2374 // Is the next IG the start of a funclet prolog?
2375 if (ig->igNext->igFlags & IGF_FUNCLET_PROLOG)
2376 return true;
2377
2378#if FEATURE_EH_FUNCLETS
2379
2380 // Is the next IG a placeholder group for a funclet prolog?
2381 if ((ig->igNext->igFlags & IGF_PLACEHOLDER) && (ig->igNext->igPhData->igPhType == IGPT_FUNCLET_PROLOG))
2382 {
2383 return true;
2384 }
2385
2386#endif // FEATURE_EH_FUNCLETS
2387
2388 return false;
2389}
2390
2391/*****************************************************************************
2392 *
2393 * Split the region from 'startLoc' to 'endLoc' into fragments by calling
2394 * a callback function to indicate the beginning of a fragment. The initial code,
2395 * starting at 'startLoc', doesn't get a callback, but the first code fragment,
2396 * about 'maxSplitSize' bytes out does, as does the beginning of each fragment
2397 * after that. There is no callback for the end (only the beginning of the last
2398 * fragment gets a callback). A fragment must contain at least one instruction
2399 * group. It should be smaller than 'maxSplitSize', although it may be larger to
2400 * satisfy the "at least one instruction group" rule. Do not split prologs or
2401 * epilogs. (Currently, prologs exist in a single instruction group at the main
2402 * function beginning, so they aren't split. Funclets, however, might span IGs,
2403 * so we can't split in between them.)
2404 *
2405 * Note that the locations must be the start of instruction groups; the part of
2406 * the location indicating offset within a group must be zero.
2407 *
2408 * If 'startLoc' is NULL, it means the start of the code.
2409 * If 'endLoc' is NULL, it means the end of the code.
2410 */
2411
2412void emitter::emitSplit(emitLocation* startLoc,
2413 emitLocation* endLoc,
2414 UNATIVE_OFFSET maxSplitSize,
2415 void* context,
2416 emitSplitCallbackType callbackFunc)
2417{
2418 insGroup* igStart = (startLoc == NULL) ? emitIGlist : startLoc->GetIG();
2419 insGroup* igEnd = (endLoc == NULL) ? NULL : endLoc->GetIG();
2420 insGroup* igPrev;
2421 insGroup* ig;
2422 insGroup* igLastReported;
2423 insGroup* igLastCandidate;
2424 UNATIVE_OFFSET curSize;
2425 UNATIVE_OFFSET candidateSize;
2426
2427 for (igPrev = NULL, ig = igLastReported = igStart, igLastCandidate = NULL, candidateSize = 0, curSize = 0;
2428 ig != igEnd && ig != NULL; igPrev = ig, ig = ig->igNext)
2429 {
2430 // Keep looking until we've gone past the maximum split size
2431 if (curSize >= maxSplitSize)
2432 {
2433 bool reportCandidate = true;
2434
2435 // Is there a candidate?
2436 if (igLastCandidate == NULL)
2437 {
2438#ifdef DEBUG
2439 if (EMITVERBOSE)
2440 printf("emitSplit: can't split at IG%02u; we don't have a candidate to report\n", ig->igNum);
2441#endif
2442 reportCandidate = false;
2443 }
2444
2445 // Don't report the same thing twice (this also happens for the first block, since igLastReported is
2446 // initialized to igStart).
2447 if (igLastCandidate == igLastReported)
2448 {
2449#ifdef DEBUG
2450 if (EMITVERBOSE)
2451 printf("emitSplit: can't split at IG%02u; we already reported it\n", igLastCandidate->igNum);
2452#endif
2453 reportCandidate = false;
2454 }
2455
2456 // Report it!
2457 if (reportCandidate)
2458 {
2459#ifdef DEBUG
2460 if (EMITVERBOSE && (candidateSize >= maxSplitSize))
2461 printf("emitSplit: split at IG%02u is size %d, larger than requested maximum size of %d\n",
2462 igLastCandidate->igNum, candidateSize, maxSplitSize);
2463#endif
2464
2465 // hand memory ownership to the callback function
2466 emitLocation* pEmitLoc = new (emitComp, CMK_Unknown) emitLocation(igLastCandidate);
2467 callbackFunc(context, pEmitLoc);
2468 igLastReported = igLastCandidate;
2469 igLastCandidate = NULL;
2470 curSize -= candidateSize;
2471 }
2472 }
2473
2474 // Update the current candidate to be this block, if it isn't in the middle of a
2475 // prolog or epilog, which we can't split. All we know is that certain
2476 // IGs are marked as prolog or epilog. We don't actually know if two adjacent
2477 // IGs are part of the *same* prolog or epilog, so we have to assume they are.
2478
2479 if (igPrev && (((igPrev->igFlags & IGF_FUNCLET_PROLOG) && (ig->igFlags & IGF_FUNCLET_PROLOG)) ||
2480 ((igPrev->igFlags & IGF_EPILOG) && (ig->igFlags & IGF_EPILOG))))
2481 {
2482 // We can't update the candidate
2483 }
2484 else
2485 {
2486 igLastCandidate = ig;
2487 candidateSize = curSize;
2488 }
2489
2490 curSize += ig->igSize;
2491
2492 } // end for loop
2493}
2494
2495/*****************************************************************************
2496 *
2497 * Given an instruction group, find the array of instructions (instrDesc) and
2498 * number of instructions in the array. If the IG is the current IG, we assume
2499 * that igData does NOT hold the instructions; they are unsaved and pointed
2500 * to by emitCurIGfreeBase.
2501 *
2502 * This function can't be called for placeholder groups, which have no instrDescs.
2503 */
2504
2505void emitter::emitGetInstrDescs(insGroup* ig, instrDesc** id, int* insCnt)
2506{
2507 assert(!(ig->igFlags & IGF_PLACEHOLDER));
2508 if (ig == emitCurIG)
2509 {
2510 *id = (instrDesc*)emitCurIGfreeBase;
2511 *insCnt = emitCurIGinsCnt;
2512 }
2513 else
2514 {
2515 *id = (instrDesc*)ig->igData;
2516 *insCnt = ig->igInsCnt;
2517 }
2518
2519 assert(*id);
2520}
2521
2522/*****************************************************************************
2523 *
2524 * Given a location (an 'emitLocation'), find the instruction group (IG) and
2525 * instruction descriptor (instrDesc) corresponding to that location. Returns
2526 * 'true' if there is an instruction, 'false' if there is no instruction
2527 * (i.e., we're at the end of the instruction list). Also, optionally return
2528 * the number of instructions that follow that instruction in the IG (in *pinsRemaining,
2529 * if pinsRemaining is non-NULL), which can be used for iterating over the
2530 * remaining instrDescs in the IG.
2531 *
2532 * We assume that emitCurIG points to the end of the instructions we care about.
2533 * For the prologs or epilogs, it points to the last IG of the prolog or epilog
2534 * that is being generated. For body code gen, it points to the place we are currently
2535 * adding code, namely, the end of currently generated code.
2536 */
2537
2538bool emitter::emitGetLocationInfo(emitLocation* emitLoc,
2539 insGroup** pig,
2540 instrDesc** pid,
2541 int* pinsRemaining /* = NULL */)
2542{
2543 assert(emitLoc != nullptr);
2544 assert(emitLoc->Valid());
2545 assert(emitLoc->GetIG() != nullptr);
2546 assert(pig != nullptr);
2547 assert(pid != nullptr);
2548
2549 insGroup* ig = emitLoc->GetIG();
2550 instrDesc* id;
2551 int insNum = emitLoc->GetInsNum();
2552 int insCnt;
2553
2554 emitGetInstrDescs(ig, &id, &insCnt);
2555 assert(insNum <= insCnt);
2556
2557 // There is a special-case: if the insNum points to the end, then we "wrap" and
2558 // consider that the instruction it is pointing at is actually the first instruction
2559 // of the next non-empty IG (which has its own valid emitLocation). This handles the
2560 // case where you capture a location, then the next instruction creates a new IG.
2561
2562 if (insNum == insCnt)
2563 {
2564 if (ig == emitCurIG)
2565 {
2566 // No instructions beyond the current location.
2567 return false;
2568 }
2569
2570 for (ig = ig->igNext; ig; ig = ig->igNext)
2571 {
2572 emitGetInstrDescs(ig, &id, &insCnt);
2573
2574 if (insCnt > 0)
2575 {
2576 insNum = 0; // Pretend the index is 0 -- the first instruction
2577 break;
2578 }
2579
2580 if (ig == emitCurIG)
2581 {
2582 // There aren't any instructions in the current IG, and this is
2583 // the current location, so we're at the end.
2584 return false;
2585 }
2586 }
2587
2588 if (ig == NULL)
2589 {
2590 // 'ig' can't be NULL, or we went past the current IG represented by 'emitCurIG'.
2591 // Perhaps 'loc' was corrupt coming in?
2592 noway_assert(!"corrupt emitter location");
2593 return false;
2594 }
2595 }
2596
2597 // Now find the instrDesc within this group that corresponds to the location
2598
2599 assert(insNum < insCnt);
2600
2601 int i;
2602 for (i = 0; i != insNum; ++i)
2603 {
2604 castto(id, BYTE*) += emitSizeOfInsDsc(id);
2605 }
2606
2607 // Return the info we found
2608
2609 *pig = ig;
2610 *pid = id;
2611
2612 if (pinsRemaining)
2613 {
2614 *pinsRemaining = insCnt - insNum - 1;
2615 }
2616
2617 return true;
2618}
2619
2620/*****************************************************************************
2621 *
2622 * Compute the next instrDesc, either in this IG, or in a subsequent IG. 'id'
2623 * will point to this instrDesc. 'ig' and 'insRemaining' will also be updated.
2624 * Returns true if there is an instruction, or false if we've iterated over all
2625 * the instructions up to the current instruction (based on 'emitCurIG').
2626 */
2627
2628bool emitter::emitNextID(insGroup*& ig, instrDesc*& id, int& insRemaining)
2629{
2630 if (insRemaining > 0)
2631 {
2632 castto(id, BYTE*) += emitSizeOfInsDsc(id);
2633 --insRemaining;
2634 return true;
2635 }
2636
2637 // We're out of instrDesc in 'ig'. Is this the current IG? If so, we're done.
2638
2639 if (ig == emitCurIG)
2640 {
2641 return false;
2642 }
2643
2644 for (ig = ig->igNext; ig; ig = ig->igNext)
2645 {
2646 int insCnt;
2647 emitGetInstrDescs(ig, &id, &insCnt);
2648
2649 if (insCnt > 0)
2650 {
2651 insRemaining = insCnt - 1;
2652 return true;
2653 }
2654
2655 if (ig == emitCurIG)
2656 {
2657 return false;
2658 }
2659 }
2660
2661 return false;
2662}
2663
2664/*****************************************************************************
2665 *
2666 * Walk instrDesc's from the location given by 'locFrom', up to the current location.
2667 * For each instruction, call the callback function 'processFunc'. 'context' is simply
2668 * passed through to the callback function.
2669 */
2670
2671void emitter::emitWalkIDs(emitLocation* locFrom, emitProcessInstrFunc_t processFunc, void* context)
2672{
2673 insGroup* ig;
2674 instrDesc* id;
2675 int insRemaining;
2676
2677 if (!emitGetLocationInfo(locFrom, &ig, &id, &insRemaining))
2678 return; // no instructions at the 'from' location
2679
2680 do
2681 {
2682 // process <<id>>
2683 (*processFunc)(id, context);
2684
2685 } while (emitNextID(ig, id, insRemaining));
2686}
2687
2688/*****************************************************************************
2689 *
2690 * A callback function for emitWalkIDs() that calls Compiler::unwindNop().
2691 */
2692
2693void emitter::emitGenerateUnwindNop(instrDesc* id, void* context)
2694{
2695 Compiler* comp = (Compiler*)context;
2696#if defined(_TARGET_ARM_)
2697 comp->unwindNop(id->idCodeSize());
2698#elif defined(_TARGET_ARM64_)
2699 comp->unwindNop();
2700#endif // defined(_TARGET_ARM64_)
2701}
2702
2703/*****************************************************************************
2704 *
2705 * emitUnwindNopPadding: call unwindNop() for every instruction from a given
2706 * location 'emitLoc' up to the current location.
2707 */
2708
2709void emitter::emitUnwindNopPadding(emitLocation* locFrom, Compiler* comp)
2710{
2711 emitWalkIDs(locFrom, emitGenerateUnwindNop, comp);
2712}
2713
2714#endif // _TARGET_ARMARCH_
2715
2716#if defined(_TARGET_ARM_)
2717
2718/*****************************************************************************
2719 *
2720 * Return the instruction size in bytes for the instruction at the specified location.
2721 * This is used to assert that the unwind code being generated on ARM has the
2722 * same size as the instruction for which it is being generated (since on ARM
2723 * the unwind codes have a one-to-one relationship with instructions, and the
2724 * unwind codes have an implicit instruction size that must match the instruction size.)
2725 * An instruction must exist at the specified location.
2726 */
2727
2728unsigned emitter::emitGetInstructionSize(emitLocation* emitLoc)
2729{
2730 insGroup* ig;
2731 instrDesc* id;
2732
2733 bool anyInstrs = emitGetLocationInfo(emitLoc, &ig, &id);
2734 assert(anyInstrs); // There better be an instruction at this location (otherwise, we're at the end of the
2735 // instruction list)
2736 return id->idCodeSize();
2737}
2738
2739#endif // defined(_TARGET_ARM_)
2740
2741/*****************************************************************************/
2742#ifdef DEBUG
2743/*****************************************************************************
2744 *
2745 * Returns the name for the register to use to access frame based variables
2746 */
2747
2748const char* emitter::emitGetFrameReg()
2749{
2750 if (emitHasFramePtr)
2751 {
2752 return STR_FPBASE;
2753 }
2754 else
2755 {
2756 return STR_SPBASE;
2757 }
2758}
2759
2760/*****************************************************************************
2761 *
2762 * Display a register set in a readable form.
2763 */
2764
2765void emitter::emitDispRegSet(regMaskTP regs)
2766{
2767 regNumber reg;
2768 bool sp = false;
2769
2770 printf(" {");
2771
2772 for (reg = REG_FIRST; reg < ACTUAL_REG_COUNT; reg = REG_NEXT(reg))
2773 {
2774 if ((regs & genRegMask(reg)) == 0)
2775 {
2776 continue;
2777 }
2778
2779 if (sp)
2780 {
2781 printf(" ");
2782 }
2783 else
2784 {
2785 sp = true;
2786 }
2787
2788 printf("%s", emitRegName(reg));
2789 }
2790
2791 printf("}");
2792}
2793
2794/*****************************************************************************
2795 *
2796 * Display the current GC ref variable set in a readable form.
2797 */
2798
2799void emitter::emitDispVarSet()
2800{
2801 unsigned vn;
2802 int of;
2803 bool sp = false;
2804
2805 for (vn = 0, of = emitGCrFrameOffsMin; vn < emitGCrFrameOffsCnt; vn += 1, of += TARGET_POINTER_SIZE)
2806 {
2807 if (emitGCrFrameLiveTab[vn])
2808 {
2809 if (sp)
2810 {
2811 printf(" ");
2812 }
2813 else
2814 {
2815 sp = true;
2816 }
2817
2818 printf("[%s", emitGetFrameReg());
2819
2820 if (of < 0)
2821 {
2822 printf("-%02XH", -of);
2823 }
2824 else if (of > 0)
2825 {
2826 printf("+%02XH", +of);
2827 }
2828
2829 printf("]");
2830 }
2831 }
2832
2833 if (!sp)
2834 {
2835 printf("none");
2836 }
2837}
2838
2839/*****************************************************************************/
2840#endif // DEBUG
2841
2842#if MULTIREG_HAS_SECOND_GC_RET
2843//------------------------------------------------------------------------
2844// emitSetSecondRetRegGCType: Sets the GC type of the second return register for instrDescCGCA struct.
2845//
2846// Arguments:
2847// id - The large call instr descriptor to set the second GC return register type on.
2848// secondRetSize - The EA_SIZE for second return register type.
2849//
2850// Return Value:
2851// None
2852//
2853
2854void emitter::emitSetSecondRetRegGCType(instrDescCGCA* id, emitAttr secondRetSize)
2855{
2856 if (EA_IS_GCREF(secondRetSize))
2857 {
2858 id->idSecondGCref(GCT_GCREF);
2859 }
2860 else if (EA_IS_BYREF(secondRetSize))
2861 {
2862 id->idSecondGCref(GCT_BYREF);
2863 }
2864 else
2865 {
2866 id->idSecondGCref(GCT_NONE);
2867 }
2868}
2869#endif // MULTIREG_HAS_SECOND_GC_RET
2870
2871/*****************************************************************************
2872 *
2873 * Allocate an instruction descriptor for an indirect call.
2874 *
2875 * We use two different descriptors to save space - the common case records
2876 * no GC variables and has both a very small argument count and an address
2877 * mode displacement; the other case records the current GC var set,
2878 * the call scope, and an arbitrarily large argument count and the
2879 * address mode displacement.
2880 */
2881
2882emitter::instrDesc* emitter::emitNewInstrCallInd(int argCnt,
2883 ssize_t disp,
2884 VARSET_VALARG_TP GCvars,
2885 regMaskTP gcrefRegs,
2886 regMaskTP byrefRegs,
2887 emitAttr retSizeIn
2888 MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize))
2889{
2890 emitAttr retSize = (retSizeIn != EA_UNKNOWN) ? retSizeIn : EA_PTRSIZE;
2891
2892 bool gcRefRegsInScratch = ((gcrefRegs & RBM_CALLEE_TRASH) != 0);
2893
2894 // Allocate a larger descriptor if any GC values need to be saved
2895 // or if we have an absurd number of arguments or a large address
2896 // mode displacement, or we have some byref registers
2897 //
2898 // On Amd64 System V OSs a larger descriptor is also needed if the
2899 // call returns a two-register-returned struct and the second
2900 // register (RDX) is a GCRef or ByRef pointer.
2901
2902 if (!VarSetOps::IsEmpty(emitComp, GCvars) || // any frame GCvars live
2903 (gcRefRegsInScratch) || // any register gc refs live in scratch regs
2904 (byrefRegs != 0) || // any register byrefs live
2905 (disp < AM_DISP_MIN) || // displacement too negative
2906 (disp > AM_DISP_MAX) || // displacement too positive
2907 (argCnt > ID_MAX_SMALL_CNS) || // too many args
2908 (argCnt < 0) // caller pops arguments
2909 // There is a second ref/byref return register.
2910 MULTIREG_HAS_SECOND_GC_RET_ONLY(|| EA_IS_GCREF_OR_BYREF(secondRetSize)))
2911 {
2912 instrDescCGCA* id;
2913
2914 id = emitAllocInstrCGCA(retSize);
2915
2916 id->idSetIsLargeCall();
2917
2918 VarSetOps::Assign(emitComp, id->idcGCvars, GCvars);
2919 id->idcGcrefRegs = gcrefRegs;
2920 id->idcByrefRegs = byrefRegs;
2921 id->idcArgCnt = argCnt;
2922 id->idcDisp = disp;
2923
2924#if MULTIREG_HAS_SECOND_GC_RET
2925 emitSetSecondRetRegGCType(id, secondRetSize);
2926#endif // MULTIREG_HAS_SECOND_GC_RET
2927
2928 return id;
2929 }
2930 else
2931 {
2932 instrDesc* id;
2933
2934 id = emitNewInstrCns(retSize, argCnt);
2935
2936 /* Make sure we didn't waste space unexpectedly */
2937 assert(!id->idIsLargeCns());
2938
2939 /* Store the displacement and make sure the value fit */
2940 id->idAddr()->iiaAddrMode.amDisp = disp;
2941 assert(id->idAddr()->iiaAddrMode.amDisp == disp);
2942
2943 /* Save the the live GC registers in the unused register fields */
2944 emitEncodeCallGCregs(gcrefRegs, id);
2945
2946 return id;
2947 }
2948}
2949
2950/*****************************************************************************
2951 *
2952 * Allocate an instruction descriptor for a direct call.
2953 *
2954 * We use two different descriptors to save space - the common case records
2955 * with no GC variables or byrefs and has a very small argument count, and no
2956 * explicit scope;
2957 * the other case records the current GC var set, the call scope,
2958 * and an arbitrarily large argument count.
2959 */
2960
2961emitter::instrDesc* emitter::emitNewInstrCallDir(int argCnt,
2962 VARSET_VALARG_TP GCvars,
2963 regMaskTP gcrefRegs,
2964 regMaskTP byrefRegs,
2965 emitAttr retSizeIn
2966 MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize))
2967{
2968 emitAttr retSize = (retSizeIn != EA_UNKNOWN) ? retSizeIn : EA_PTRSIZE;
2969
2970 // Allocate a larger descriptor if new GC values need to be saved
2971 // or if we have an absurd number of arguments or if we need to
2972 // save the scope.
2973 //
2974 // On Amd64 System V OSs a larger descriptor is also needed if the
2975 // call returns a two-register-returned struct and the second
2976 // register (RDX) is a GCRef or ByRef pointer.
2977
2978 bool gcRefRegsInScratch = ((gcrefRegs & RBM_CALLEE_TRASH) != 0);
2979
2980 if (!VarSetOps::IsEmpty(emitComp, GCvars) || // any frame GCvars live
2981 gcRefRegsInScratch || // any register gc refs live in scratch regs
2982 (byrefRegs != 0) || // any register byrefs live
2983 (argCnt > ID_MAX_SMALL_CNS) || // too many args
2984 (argCnt < 0) // caller pops arguments
2985 // There is a second ref/byref return register.
2986 MULTIREG_HAS_SECOND_GC_RET_ONLY(|| EA_IS_GCREF_OR_BYREF(secondRetSize)))
2987 {
2988 instrDescCGCA* id = emitAllocInstrCGCA(retSize);
2989
2990 // printf("Direct call with GC vars / big arg cnt / explicit scope\n");
2991
2992 id->idSetIsLargeCall();
2993
2994 VarSetOps::Assign(emitComp, id->idcGCvars, GCvars);
2995 id->idcGcrefRegs = gcrefRegs;
2996 id->idcByrefRegs = byrefRegs;
2997 id->idcDisp = 0;
2998 id->idcArgCnt = argCnt;
2999
3000#if MULTIREG_HAS_SECOND_GC_RET
3001 emitSetSecondRetRegGCType(id, secondRetSize);
3002#endif // MULTIREG_HAS_SECOND_GC_RET
3003
3004 return id;
3005 }
3006 else
3007 {
3008 instrDesc* id = emitNewInstrCns(retSize, argCnt);
3009
3010 // printf("Direct call w/o GC vars / big arg cnt / explicit scope\n");
3011
3012 /* Make sure we didn't waste space unexpectedly */
3013 assert(!id->idIsLargeCns());
3014
3015 /* Save the the live GC registers in the unused register fields */
3016 emitEncodeCallGCregs(gcrefRegs, id);
3017
3018 return id;
3019 }
3020}
3021
3022/*****************************************************************************/
3023#ifdef DEBUG
3024/*****************************************************************************
3025 *
3026 * Return a string with the name of the given class field (blank string (not
3027 * NULL) is returned when the name isn't available).
3028 */
3029
3030const char* emitter::emitFldName(CORINFO_FIELD_HANDLE fieldVal)
3031{
3032 if (emitComp->opts.varNames)
3033 {
3034 const char* memberName;
3035 const char* className;
3036
3037 const int TEMP_BUFFER_LEN = 1024;
3038 static char buff[TEMP_BUFFER_LEN];
3039
3040 memberName = emitComp->eeGetFieldName(fieldVal, &className);
3041
3042 sprintf_s(buff, TEMP_BUFFER_LEN, "'<%s>.%s'", className, memberName);
3043 return buff;
3044 }
3045 else
3046 {
3047 return "";
3048 }
3049}
3050
3051/*****************************************************************************
3052 *
3053 * Return a string with the name of the given function (blank string (not
3054 * NULL) is returned when the name isn't available).
3055 */
3056
3057const char* emitter::emitFncName(CORINFO_METHOD_HANDLE methHnd)
3058{
3059 return emitComp->eeGetMethodFullName(methHnd);
3060}
3061
3062#endif // DEBUG
3063
3064/*****************************************************************************
3065 *
3066 * Be very careful, some instruction descriptors are allocated as "tiny" and
3067 * don't have some of the tail fields of instrDesc (in particular, "idInfo").
3068 */
3069
3070const BYTE emitter::emitFmtToOps[] = {
3071#define IF_DEF(en, op1, op2) ID_OP_##op2,
3072#include "emitfmts.h"
3073};
3074
3075#ifdef DEBUG
3076const unsigned emitter::emitFmtCount = _countof(emitFmtToOps);
3077#endif
3078
3079/*****************************************************************************
3080 *
3081 * Display the current instruction group list.
3082 */
3083
3084#ifdef DEBUG
3085
3086void emitter::emitDispIGflags(unsigned flags)
3087{
3088 if (flags & IGF_GC_VARS)
3089 {
3090 printf(", gcvars");
3091 }
3092 if (flags & IGF_BYREF_REGS)
3093 {
3094 printf(", byref");
3095 }
3096#if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
3097 if (flags & IGF_FINALLY_TARGET)
3098 {
3099 printf(", ftarget");
3100 }
3101#endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
3102 if (flags & IGF_FUNCLET_PROLOG)
3103 {
3104 printf(", funclet prolog");
3105 }
3106 if (flags & IGF_FUNCLET_EPILOG)
3107 {
3108 printf(", funclet epilog");
3109 }
3110 if (flags & IGF_EPILOG)
3111 {
3112 printf(", epilog");
3113 }
3114 if (flags & IGF_NOGCINTERRUPT)
3115 {
3116 printf(", nogc");
3117 }
3118 if (flags & IGF_UPD_ISZ)
3119 {
3120 printf(", isz");
3121 }
3122 if (flags & IGF_EMIT_ADD)
3123 {
3124 printf(", emitadd");
3125 }
3126}
3127
3128void emitter::emitDispIG(insGroup* ig, insGroup* igPrev, bool verbose)
3129{
3130 const int TEMP_BUFFER_LEN = 40;
3131 char buff[TEMP_BUFFER_LEN];
3132
3133 sprintf_s(buff, TEMP_BUFFER_LEN, "G_M%03u_IG%02u: ", Compiler::s_compMethodsCount, ig->igNum);
3134 printf("%s; ", buff);
3135 if ((igPrev == nullptr) || (igPrev->igFuncIdx != ig->igFuncIdx))
3136 {
3137 printf("func=%02u, ", ig->igFuncIdx);
3138 }
3139
3140 if (ig->igFlags & IGF_PLACEHOLDER)
3141 {
3142 insGroup* igPh = ig;
3143
3144 const char* pszType;
3145 switch (igPh->igPhData->igPhType)
3146 {
3147 case IGPT_PROLOG:
3148 pszType = "prolog";
3149 break;
3150 case IGPT_EPILOG:
3151 pszType = "epilog";
3152 break;
3153#if FEATURE_EH_FUNCLETS
3154 case IGPT_FUNCLET_PROLOG:
3155 pszType = "funclet prolog";
3156 break;
3157 case IGPT_FUNCLET_EPILOG:
3158 pszType = "funclet epilog";
3159 break;
3160#endif // FEATURE_EH_FUNCLETS
3161 default:
3162 pszType = "UNKNOWN";
3163 break;
3164 }
3165 printf("%s placeholder, next placeholder=", pszType);
3166 if (igPh->igPhData->igPhNext)
3167 {
3168 printf("IG%02u ", igPh->igPhData->igPhNext->igNum);
3169 }
3170 else
3171 {
3172 printf("<END>");
3173 }
3174
3175 if (igPh->igPhData->igPhBB != nullptr)
3176 {
3177 printf(", %s", igPh->igPhData->igPhBB->dspToString());
3178 }
3179
3180 emitDispIGflags(igPh->igFlags);
3181
3182 if (ig == emitCurIG)
3183 {
3184 printf(" <-- Current IG");
3185 }
3186 if (igPh == emitPlaceholderList)
3187 {
3188 printf(" <-- First placeholder");
3189 }
3190 if (igPh == emitPlaceholderLast)
3191 {
3192 printf(" <-- Last placeholder");
3193 }
3194 printf("\n");
3195
3196 printf("%*s; PrevGCVars=%s ", strlen(buff), "",
3197 VarSetOps::ToString(emitComp, igPh->igPhData->igPhPrevGCrefVars));
3198 dumpConvertedVarSet(emitComp, igPh->igPhData->igPhPrevGCrefVars);
3199 printf(", PrevGCrefRegs=");
3200 printRegMaskInt(igPh->igPhData->igPhPrevGCrefRegs);
3201 emitDispRegSet(igPh->igPhData->igPhPrevGCrefRegs);
3202 printf(", PrevByrefRegs=");
3203 printRegMaskInt(igPh->igPhData->igPhPrevByrefRegs);
3204 emitDispRegSet(igPh->igPhData->igPhPrevByrefRegs);
3205 printf("\n");
3206
3207 printf("%*s; InitGCVars=%s ", strlen(buff), "",
3208 VarSetOps::ToString(emitComp, igPh->igPhData->igPhInitGCrefVars));
3209 dumpConvertedVarSet(emitComp, igPh->igPhData->igPhInitGCrefVars);
3210 printf(", InitGCrefRegs=");
3211 printRegMaskInt(igPh->igPhData->igPhInitGCrefRegs);
3212 emitDispRegSet(igPh->igPhData->igPhInitGCrefRegs);
3213 printf(", InitByrefRegs=");
3214 printRegMaskInt(igPh->igPhData->igPhInitByrefRegs);
3215 emitDispRegSet(igPh->igPhData->igPhInitByrefRegs);
3216 printf("\n");
3217
3218 assert(!(ig->igFlags & IGF_GC_VARS));
3219 assert(!(ig->igFlags & IGF_BYREF_REGS));
3220 }
3221 else
3222 {
3223 printf("offs=%06XH, size=%04XH", ig->igOffs, ig->igSize);
3224
3225 if (ig->igFlags & IGF_GC_VARS)
3226 {
3227 printf(", gcVars=%s ", VarSetOps::ToString(emitComp, ig->igGCvars()));
3228 dumpConvertedVarSet(emitComp, ig->igGCvars());
3229 }
3230
3231 if (!(ig->igFlags & IGF_EMIT_ADD))
3232 {
3233 printf(", gcrefRegs=");
3234 printRegMaskInt(ig->igGCregs);
3235 emitDispRegSet(ig->igGCregs);
3236 }
3237
3238 if (ig->igFlags & IGF_BYREF_REGS)
3239 {
3240 printf(", byrefRegs=");
3241 printRegMaskInt(ig->igByrefRegs());
3242 emitDispRegSet(ig->igByrefRegs());
3243 }
3244
3245 emitDispIGflags(ig->igFlags);
3246
3247 if (ig == emitCurIG)
3248 {
3249 printf(" <-- Current IG");
3250 }
3251 if (ig == emitPrologIG)
3252 {
3253 printf(" <-- Prolog IG");
3254 }
3255 printf("\n");
3256
3257 if (verbose)
3258 {
3259 BYTE* ins = ig->igData;
3260 UNATIVE_OFFSET ofs = ig->igOffs;
3261 unsigned cnt = ig->igInsCnt;
3262
3263 if (cnt)
3264 {
3265 printf("\n");
3266
3267 do
3268 {
3269 instrDesc* id = (instrDesc*)ins;
3270
3271 emitDispIns(id, false, true, false, ofs, nullptr, 0, ig);
3272
3273 ins += emitSizeOfInsDsc(id);
3274 ofs += emitInstCodeSz(id);
3275 } while (--cnt);
3276
3277 printf("\n");
3278 }
3279 }
3280 }
3281}
3282
3283void emitter::emitDispIGlist(bool verbose)
3284{
3285 insGroup* ig;
3286 insGroup* igPrev;
3287
3288 for (igPrev = nullptr, ig = emitIGlist; ig; igPrev = ig, ig = ig->igNext)
3289 {
3290 emitDispIG(ig, igPrev, verbose);
3291 }
3292}
3293
3294void emitter::emitDispGCinfo()
3295{
3296 printf("Emitter GC tracking info:");
3297 printf("\n emitPrevGCrefVars ");
3298 dumpConvertedVarSet(emitComp, emitPrevGCrefVars);
3299 printf("\n emitPrevGCrefRegs(0x%p)=", dspPtr(&emitPrevGCrefRegs));
3300 printRegMaskInt(emitPrevGCrefRegs);
3301 emitDispRegSet(emitPrevGCrefRegs);
3302 printf("\n emitPrevByrefRegs(0x%p)=", dspPtr(&emitPrevByrefRegs));
3303 printRegMaskInt(emitPrevByrefRegs);
3304 emitDispRegSet(emitPrevByrefRegs);
3305 printf("\n emitInitGCrefVars ");
3306 dumpConvertedVarSet(emitComp, emitInitGCrefVars);
3307 printf("\n emitInitGCrefRegs(0x%p)=", dspPtr(&emitInitGCrefRegs));
3308 printRegMaskInt(emitInitGCrefRegs);
3309 emitDispRegSet(emitInitGCrefRegs);
3310 printf("\n emitInitByrefRegs(0x%p)=", dspPtr(&emitInitByrefRegs));
3311 printRegMaskInt(emitInitByrefRegs);
3312 emitDispRegSet(emitInitByrefRegs);
3313 printf("\n emitThisGCrefVars ");
3314 dumpConvertedVarSet(emitComp, emitThisGCrefVars);
3315 printf("\n emitThisGCrefRegs(0x%p)=", dspPtr(&emitThisGCrefRegs));
3316 printRegMaskInt(emitThisGCrefRegs);
3317 emitDispRegSet(emitThisGCrefRegs);
3318 printf("\n emitThisByrefRegs(0x%p)=", dspPtr(&emitThisByrefRegs));
3319 printRegMaskInt(emitThisByrefRegs);
3320 emitDispRegSet(emitThisByrefRegs);
3321 printf("\n\n");
3322}
3323
3324#endif // DEBUG
3325
3326/*****************************************************************************
3327 *
3328 * Issue the given instruction. Basically, this is just a thin wrapper around
3329 * emitOutputInstr() that does a few debug checks.
3330 */
3331
3332size_t emitter::emitIssue1Instr(insGroup* ig, instrDesc* id, BYTE** dp)
3333{
3334 size_t is;
3335
3336 /* Record the beginning offset of the instruction */
3337
3338 BYTE* curInsAdr = *dp;
3339
3340 /* Issue the next instruction */
3341
3342 // printf("[S=%02u] " , emitCurStackLvl);
3343
3344 is = emitOutputInstr(ig, id, dp);
3345
3346// printf("[S=%02u]\n", emitCurStackLvl);
3347
3348#if EMIT_TRACK_STACK_DEPTH
3349
3350 /*
3351 If we're generating a full pointer map and the stack
3352 is empty, there better not be any "pending" argument
3353 push entries.
3354 */
3355
3356 assert(emitFullGCinfo == false || emitCurStackLvl != 0 || u2.emitGcArgTrackCnt == 0);
3357
3358#endif
3359
3360 /* Did the size of the instruction match our expectations? */
3361
3362 UNATIVE_OFFSET csz = (UNATIVE_OFFSET)(*dp - curInsAdr);
3363
3364 if (csz != id->idCodeSize())
3365 {
3366 /* It is fatal to under-estimate the instruction size */
3367 noway_assert(emitInstCodeSz(id) >= csz);
3368
3369#if DEBUG_EMIT
3370 if (EMITVERBOSE)
3371 {
3372 printf("Instruction predicted size = %u, actual = %u\n", emitInstCodeSz(id), csz);
3373 }
3374#endif // DEBUG_EMIT
3375
3376 /* The instruction size estimate wasn't accurate; remember this */
3377
3378 ig->igFlags |= IGF_UPD_ISZ;
3379#if defined(_TARGET_XARCH_)
3380 id->idCodeSize(csz);
3381#elif defined(_TARGET_ARM_)
3382// This is done as part of emitSetShortJump();
3383// insSize isz = emitInsSize(id->idInsFmt());
3384// id->idInsSize(isz);
3385#else
3386 /* It is fatal to over-estimate the instruction size */
3387 IMPL_LIMITATION("Over-estimated instruction size");
3388#endif
3389 }
3390
3391#ifdef DEBUG
3392 /* Make sure the instruction descriptor size also matches our expectations */
3393 if (is != emitSizeOfInsDsc(id))
3394 {
3395 printf("%s at %u: Expected size = %u , actual size = %u\n", emitIfName(id->idInsFmt()),
3396 id->idDebugOnlyInfo()->idNum, is, emitSizeOfInsDsc(id));
3397 assert(is == emitSizeOfInsDsc(id));
3398 }
3399#endif
3400
3401 return is;
3402}
3403
3404/*****************************************************************************
3405 *
3406 * Update the offsets of all the instruction groups (note: please don't be
3407 * lazy and call this routine frequently, it walks the list of instruction
3408 * groups and thus it isn't cheap).
3409 */
3410
3411void emitter::emitRecomputeIGoffsets()
3412{
3413 UNATIVE_OFFSET offs;
3414 insGroup* ig;
3415
3416 for (ig = emitIGlist, offs = 0; ig; ig = ig->igNext)
3417 {
3418 ig->igOffs = offs;
3419 assert(IsCodeAligned(ig->igOffs));
3420 offs += ig->igSize;
3421 }
3422
3423 /* Set the total code size */
3424
3425 emitTotalCodeSize = offs;
3426
3427#ifdef DEBUG
3428 emitCheckIGoffsets();
3429#endif
3430}
3431
3432/*****************************************************************************
3433 * Bind targets of relative jumps to choose the smallest possible encoding.
3434 * X86 and AMD64 have a small and large encoding.
3435 * ARM has a small, medium, and large encoding. The large encoding is a pseudo-op
3436 * to handle greater range than the conditional branch instructions can handle.
3437 * ARM64 has a small and large encoding for both conditional branch and loading label addresses.
3438 * The large encodings are pseudo-ops that represent a multiple instruction sequence, similar to ARM. (Currently
3439 * NYI).
3440 */
3441
3442void emitter::emitJumpDistBind()
3443{
3444#ifdef DEBUG
3445 if (emitComp->verbose)
3446 {
3447 printf("*************** In emitJumpDistBind()\n");
3448 }
3449 if (EMIT_INSTLIST_VERBOSE)
3450 {
3451 printf("\nInstruction list before jump distance binding:\n\n");
3452 emitDispIGlist(true);
3453 }
3454#endif
3455
3456 instrDescJmp* jmp;
3457
3458 UNATIVE_OFFSET minShortExtra; // The smallest offset greater than that required for a jump to be converted
3459 // to a small jump. If it is small enough, we will iterate in hopes of
3460 // converting those jumps we missed converting the first (or second...) time.
3461
3462#if defined(_TARGET_ARM_)
3463 UNATIVE_OFFSET minMediumExtra; // Same as 'minShortExtra', but for medium-sized jumps.
3464#endif // _TARGET_ARM_
3465
3466 UNATIVE_OFFSET adjIG;
3467 UNATIVE_OFFSET adjLJ;
3468 insGroup* lstIG;
3469#ifdef DEBUG
3470 insGroup* prologIG = emitPrologIG;
3471#endif // DEBUG
3472
3473 int jmp_iteration = 1;
3474
3475/*****************************************************************************/
3476/* If we iterate to look for more jumps to shorten, we start again here. */
3477/*****************************************************************************/
3478
3479AGAIN:
3480
3481#ifdef DEBUG
3482 emitCheckIGoffsets();
3483#endif
3484
3485/*
3486 In the following loop we convert all jump targets from "BasicBlock *"
3487 to "insGroup *" values. We also estimate which jumps will be short.
3488 */
3489
3490#ifdef DEBUG
3491 insGroup* lastIG = nullptr;
3492 instrDescJmp* lastLJ = nullptr;
3493#endif
3494
3495 lstIG = nullptr;
3496 adjLJ = 0;
3497 adjIG = 0;
3498 minShortExtra = (UNATIVE_OFFSET)-1;
3499
3500#if defined(_TARGET_ARM_)
3501 minMediumExtra = (UNATIVE_OFFSET)-1;
3502#endif // _TARGET_ARM_
3503
3504 for (jmp = emitJumpList; jmp; jmp = jmp->idjNext)
3505 {
3506 insGroup* jmpIG;
3507 insGroup* tgtIG;
3508
3509 UNATIVE_OFFSET jsz; // size of the jump instruction in bytes
3510
3511 UNATIVE_OFFSET ssz = 0; // small jump size
3512 NATIVE_OFFSET nsd = 0; // small jump max. neg distance
3513 NATIVE_OFFSET psd = 0; // small jump max. pos distance
3514
3515#if defined(_TARGET_ARM_)
3516 UNATIVE_OFFSET msz = 0; // medium jump size
3517 NATIVE_OFFSET nmd = 0; // medium jump max. neg distance
3518 NATIVE_OFFSET pmd = 0; // medium jump max. pos distance
3519 NATIVE_OFFSET mextra; // How far beyond the medium jump range is this jump offset?
3520#endif // _TARGET_ARM_
3521
3522 NATIVE_OFFSET extra; // How far beyond the short jump range is this jump offset?
3523 UNATIVE_OFFSET srcInstrOffs; // offset of the source instruction of the jump
3524 UNATIVE_OFFSET srcEncodingOffs; // offset of the source used by the instruction set to calculate the relative
3525 // offset of the jump
3526 UNATIVE_OFFSET dstOffs;
3527 NATIVE_OFFSET jmpDist; // the relative jump distance, as it will be encoded
3528 UNATIVE_OFFSET oldSize;
3529 UNATIVE_OFFSET sizeDif;
3530
3531#ifdef _TARGET_XARCH_
3532 assert(jmp->idInsFmt() == IF_LABEL || jmp->idInsFmt() == IF_RWR_LABEL || jmp->idInsFmt() == IF_SWR_LABEL);
3533
3534 /* Figure out the smallest size we can end up with */
3535
3536 if (jmp->idInsFmt() == IF_LABEL)
3537 {
3538 if (emitIsCondJump(jmp))
3539 {
3540 ssz = JCC_SIZE_SMALL;
3541 nsd = JCC_DIST_SMALL_MAX_NEG;
3542 psd = JCC_DIST_SMALL_MAX_POS;
3543 }
3544 else
3545 {
3546 ssz = JMP_SIZE_SMALL;
3547 nsd = JMP_DIST_SMALL_MAX_NEG;
3548 psd = JMP_DIST_SMALL_MAX_POS;
3549 }
3550 }
3551#endif // _TARGET_XARCH_
3552
3553#ifdef _TARGET_ARM_
3554 assert((jmp->idInsFmt() == IF_T2_J1) || (jmp->idInsFmt() == IF_T2_J2) || (jmp->idInsFmt() == IF_T1_I) ||
3555 (jmp->idInsFmt() == IF_T1_K) || (jmp->idInsFmt() == IF_T1_M) || (jmp->idInsFmt() == IF_T2_M1) ||
3556 (jmp->idInsFmt() == IF_T2_N1) || (jmp->idInsFmt() == IF_T1_J3) || (jmp->idInsFmt() == IF_LARGEJMP));
3557
3558 /* Figure out the smallest size we can end up with */
3559
3560 if (emitIsCondJump(jmp))
3561 {
3562 ssz = JCC_SIZE_SMALL;
3563 nsd = JCC_DIST_SMALL_MAX_NEG;
3564 psd = JCC_DIST_SMALL_MAX_POS;
3565
3566 msz = JCC_SIZE_MEDIUM;
3567 nmd = JCC_DIST_MEDIUM_MAX_NEG;
3568 pmd = JCC_DIST_MEDIUM_MAX_POS;
3569 }
3570 else if (emitIsCmpJump(jmp))
3571 {
3572 ssz = JMP_SIZE_SMALL;
3573 nsd = 0;
3574 psd = 126;
3575 }
3576 else if (emitIsUncondJump(jmp))
3577 {
3578 ssz = JMP_SIZE_SMALL;
3579 nsd = JMP_DIST_SMALL_MAX_NEG;
3580 psd = JMP_DIST_SMALL_MAX_POS;
3581 }
3582 else if (emitIsLoadLabel(jmp))
3583 {
3584 ssz = LBL_SIZE_SMALL;
3585 nsd = LBL_DIST_SMALL_MAX_NEG;
3586 psd = LBL_DIST_SMALL_MAX_POS;
3587 }
3588 else
3589 {
3590 assert(!"Unknown jump instruction");
3591 }
3592#endif // _TARGET_ARM_
3593
3594#ifdef _TARGET_ARM64_
3595 /* Figure out the smallest size we can end up with */
3596
3597 if (emitIsCondJump(jmp))
3598 {
3599 ssz = JCC_SIZE_SMALL;
3600 bool isTest = (jmp->idIns() == INS_tbz) || (jmp->idIns() == INS_tbnz);
3601
3602 nsd = (isTest) ? TB_DIST_SMALL_MAX_NEG : JCC_DIST_SMALL_MAX_NEG;
3603 psd = (isTest) ? TB_DIST_SMALL_MAX_POS : JCC_DIST_SMALL_MAX_POS;
3604 }
3605 else if (emitIsUncondJump(jmp))
3606 {
3607 // Nothing to do; we don't shrink these.
3608 assert(jmp->idjShort);
3609 ssz = JMP_SIZE_SMALL;
3610 }
3611 else if (emitIsLoadLabel(jmp))
3612 {
3613 ssz = LBL_SIZE_SMALL;
3614 nsd = LBL_DIST_SMALL_MAX_NEG;
3615 psd = LBL_DIST_SMALL_MAX_POS;
3616 }
3617 else if (emitIsLoadConstant(jmp))
3618 {
3619 ssz = LDC_SIZE_SMALL;
3620 nsd = LDC_DIST_SMALL_MAX_NEG;
3621 psd = LDC_DIST_SMALL_MAX_POS;
3622 }
3623 else
3624 {
3625 assert(!"Unknown jump instruction");
3626 }
3627#endif // _TARGET_ARM64_
3628
3629/* Make sure the jumps are properly ordered */
3630
3631#ifdef DEBUG
3632 assert(lastLJ == nullptr || lastIG != jmp->idjIG || lastLJ->idjOffs < jmp->idjOffs);
3633 lastLJ = (lastIG == jmp->idjIG) ? jmp : nullptr;
3634
3635 assert(lastIG == nullptr || lastIG->igNum <= jmp->idjIG->igNum || jmp->idjIG == prologIG ||
3636 emitNxtIGnum > unsigned(0xFFFF)); // igNum might overflow
3637 lastIG = jmp->idjIG;
3638#endif // DEBUG
3639
3640 /* Get hold of the current jump size */
3641
3642 jsz = emitSizeOfJump(jmp);
3643
3644 /* Get the group the jump is in */
3645
3646 jmpIG = jmp->idjIG;
3647
3648 /* Are we in a group different from the previous jump? */
3649
3650 if (lstIG != jmpIG)
3651 {
3652 /* Were there any jumps before this one? */
3653
3654 if (lstIG)
3655 {
3656 /* Adjust the offsets of the intervening blocks */
3657
3658 do
3659 {
3660 lstIG = lstIG->igNext;
3661 assert(lstIG);
3662#ifdef DEBUG
3663 if (EMITVERBOSE)
3664 {
3665 printf("Adjusted offset of " FMT_BB " from %04X to %04X\n", lstIG->igNum, lstIG->igOffs,
3666 lstIG->igOffs - adjIG);
3667 }
3668#endif // DEBUG
3669 lstIG->igOffs -= adjIG;
3670 assert(IsCodeAligned(lstIG->igOffs));
3671 } while (lstIG != jmpIG);
3672 }
3673
3674 /* We've got the first jump in a new group */
3675
3676 adjLJ = 0;
3677 lstIG = jmpIG;
3678 }
3679
3680 /* Apply any local size adjustment to the jump's relative offset */
3681
3682 jmp->idjOffs -= adjLJ;
3683
3684 // If this is a jump via register, the instruction size does not change, so we are done.
3685 CLANG_FORMAT_COMMENT_ANCHOR;
3686
3687#if defined(_TARGET_ARM64_)
3688 // JIT code and data will be allocated together for arm64 so the relative offset to JIT data is known.
3689 // In case such offset can be encodeable for `ldr` (+-1MB), shorten it.
3690 if (jmp->idAddr()->iiaIsJitDataOffset())
3691 {
3692 // Reference to JIT data
3693 assert(jmp->idIsBound());
3694 UNATIVE_OFFSET srcOffs = jmpIG->igOffs + jmp->idjOffs;
3695
3696 int doff = jmp->idAddr()->iiaGetJitDataOffset();
3697 assert(doff >= 0);
3698 ssize_t imm = emitGetInsSC(jmp);
3699 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
3700
3701 unsigned dataOffs = (unsigned)(doff + imm);
3702 assert(dataOffs < emitDataSize());
3703
3704 // Conservately assume JIT data starts after the entire code size.
3705 // TODO-ARM64: we might consider only hot code size which will be computed later in emitComputeCodeSizes().
3706 assert(emitTotalCodeSize > 0);
3707 UNATIVE_OFFSET maxDstOffs = emitTotalCodeSize + dataOffs;
3708
3709 // Check if the distance is within the encoding length.
3710 jmpDist = maxDstOffs - srcOffs;
3711 extra = jmpDist - psd;
3712 if (extra <= 0)
3713 {
3714 goto SHORT_JMP;
3715 }
3716
3717 // Keep the large form.
3718 continue;
3719 }
3720#endif
3721
3722 /* Have we bound this jump's target already? */
3723
3724 if (jmp->idIsBound())
3725 {
3726 /* Does the jump already have the smallest size? */
3727
3728 if (jmp->idjShort)
3729 {
3730 assert(emitSizeOfJump(jmp) == ssz);
3731
3732 // We should not be jumping/branching across funclets/functions
3733 emitCheckFuncletBranch(jmp, jmpIG);
3734
3735 continue;
3736 }
3737
3738 tgtIG = jmp->idAddr()->iiaIGlabel;
3739 }
3740 else
3741 {
3742 /* First time we've seen this label, convert its target */
3743 CLANG_FORMAT_COMMENT_ANCHOR;
3744
3745#ifdef DEBUG
3746 if (EMITVERBOSE)
3747 {
3748 printf("Binding: ");
3749 emitDispIns(jmp, false, false, false);
3750 printf("Binding L_M%03u_" FMT_BB, Compiler::s_compMethodsCount, jmp->idAddr()->iiaBBlabel->bbNum);
3751 }
3752#endif // DEBUG
3753
3754 tgtIG = (insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel);
3755
3756#ifdef DEBUG
3757 if (EMITVERBOSE)
3758 {
3759 if (tgtIG)
3760 {
3761 printf("to G_M%03u_IG%02u\n", Compiler::s_compMethodsCount, tgtIG->igNum);
3762 }
3763 else
3764 {
3765 printf("-- ERROR, no emitter cookie for " FMT_BB "; it is probably missing BBF_JMP_TARGET or "
3766 "BBF_HAS_LABEL.\n",
3767 jmp->idAddr()->iiaBBlabel->bbNum);
3768 }
3769 }
3770 assert(tgtIG);
3771#endif // DEBUG
3772
3773 /* Record the bound target */
3774
3775 jmp->idAddr()->iiaIGlabel = tgtIG;
3776 jmp->idSetIsBound();
3777 }
3778
3779 // We should not be jumping/branching across funclets/functions
3780 emitCheckFuncletBranch(jmp, jmpIG);
3781
3782#ifdef _TARGET_XARCH_
3783 /* Done if this is not a variable-sized jump */
3784
3785 if ((jmp->idIns() == INS_push) || (jmp->idIns() == INS_mov) || (jmp->idIns() == INS_call) ||
3786 (jmp->idIns() == INS_push_hide))
3787 {
3788 continue;
3789 }
3790#endif
3791#ifdef _TARGET_ARM_
3792 if ((jmp->idIns() == INS_push) || (jmp->idIns() == INS_mov) || (jmp->idIns() == INS_movt) ||
3793 (jmp->idIns() == INS_movw))
3794 {
3795 continue;
3796 }
3797#endif
3798#ifdef _TARGET_ARM64_
3799 // There is only one size of unconditional branch; we don't support functions larger than 2^28 bytes (our branch
3800 // range).
3801 if (emitIsUncondJump(jmp))
3802 {
3803 continue;
3804 }
3805#endif
3806
3807 /*
3808 In the following distance calculations, if we're not actually
3809 scheduling the code (i.e. reordering instructions), we can
3810 use the actual offset of the jump (rather than the beg/end of
3811 the instruction group) since the jump will not be moved around
3812 and thus its offset is accurate.
3813
3814 First we need to figure out whether this jump is a forward or
3815 backward one; to do this we simply look at the ordinals of the
3816 group that contains the jump and the target.
3817 */
3818
3819 srcInstrOffs = jmpIG->igOffs + jmp->idjOffs;
3820
3821 /* Note that the destination is always the beginning of an IG, so no need for an offset inside it */
3822 dstOffs = tgtIG->igOffs;
3823
3824#if defined(_TARGET_ARM_)
3825 srcEncodingOffs =
3826 srcInstrOffs + 4; // For relative branches, ARM PC is always considered to be the instruction address + 4
3827#elif defined(_TARGET_ARM64_)
3828 srcEncodingOffs =
3829 srcInstrOffs; // For relative branches, ARM64 PC is always considered to be the instruction address
3830#else
3831 srcEncodingOffs = srcInstrOffs + ssz; // Encoding offset of relative offset for small branch
3832#endif
3833
3834 if (jmpIG->igNum < tgtIG->igNum)
3835 {
3836 /* Forward jump */
3837
3838 /* Adjust the target offset by the current delta. This is a worst-case estimate, as jumps between
3839 here and the target could be shortened, causing the actual distance to shrink.
3840 */
3841
3842 dstOffs -= adjIG;
3843
3844 /* Compute the distance estimate */
3845
3846 jmpDist = dstOffs - srcEncodingOffs;
3847
3848 /* How much beyond the max. short distance does the jump go? */
3849
3850 extra = jmpDist - psd;
3851
3852#if DEBUG_EMIT
3853 assert(jmp->idDebugOnlyInfo() != nullptr);
3854 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3855 {
3856 if (INTERESTING_JUMP_NUM == 0)
3857 {
3858 printf("[1] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3859 }
3860 printf("[1] Jump block is at %08X\n", jmpIG->igOffs);
3861 printf("[1] Jump reloffset is %04X\n", jmp->idjOffs);
3862 printf("[1] Jump source is at %08X\n", srcEncodingOffs);
3863 printf("[1] Label block is at %08X\n", dstOffs);
3864 printf("[1] Jump dist. is %04X\n", jmpDist);
3865 if (extra > 0)
3866 {
3867 printf("[1] Dist excess [S] = %d \n", extra);
3868 }
3869 }
3870 if (EMITVERBOSE)
3871 {
3872 printf("Estimate of fwd jump [%08X/%03u]: %04X -> %04X = %04X\n", dspPtr(jmp),
3873 jmp->idDebugOnlyInfo()->idNum, srcInstrOffs, dstOffs, jmpDist);
3874 }
3875#endif // DEBUG_EMIT
3876
3877 if (extra <= 0)
3878 {
3879 /* This jump will be a short one */
3880 goto SHORT_JMP;
3881 }
3882 }
3883 else
3884 {
3885 /* Backward jump */
3886
3887 /* Compute the distance estimate */
3888
3889 jmpDist = srcEncodingOffs - dstOffs;
3890
3891 /* How much beyond the max. short distance does the jump go? */
3892
3893 extra = jmpDist + nsd;
3894
3895#if DEBUG_EMIT
3896 assert(jmp->idDebugOnlyInfo() != nullptr);
3897 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3898 {
3899 if (INTERESTING_JUMP_NUM == 0)
3900 {
3901 printf("[2] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3902 }
3903 printf("[2] Jump block is at %08X\n", jmpIG->igOffs);
3904 printf("[2] Jump reloffset is %04X\n", jmp->idjOffs);
3905 printf("[2] Jump source is at %08X\n", srcEncodingOffs);
3906 printf("[2] Label block is at %08X\n", dstOffs);
3907 printf("[2] Jump dist. is %04X\n", jmpDist);
3908 if (extra > 0)
3909 {
3910 printf("[2] Dist excess [S] = %d \n", extra);
3911 }
3912 }
3913 if (EMITVERBOSE)
3914 {
3915 printf("Estimate of bwd jump [%08X/%03u]: %04X -> %04X = %04X\n", dspPtr(jmp),
3916 jmp->idDebugOnlyInfo()->idNum, srcInstrOffs, dstOffs, jmpDist);
3917 }
3918#endif // DEBUG_EMIT
3919
3920 if (extra <= 0)
3921 {
3922 /* This jump will be a short one */
3923 goto SHORT_JMP;
3924 }
3925 }
3926
3927 /* We arrive here if the jump couldn't be made short, at least for now */
3928
3929 /* We had better not have eagerly marked the jump as short
3930 * in emitIns_J(). If we did, then it has to be able to stay short
3931 * as emitIns_J() uses the worst case scenario, and blocks can
3932 * only move closer together after that.
3933 */
3934 assert(jmp->idjShort == 0);
3935
3936 /* Keep track of the closest distance we got */
3937
3938 if (minShortExtra > (unsigned)extra)
3939 {
3940 minShortExtra = (unsigned)extra;
3941 }
3942
3943#if defined(_TARGET_ARM_)
3944
3945 // If we're here, we couldn't convert to a small jump.
3946 // Handle conversion to medium-sized conditional jumps.
3947 // 'srcInstrOffs', 'srcEncodingOffs', 'dstOffs', 'jmpDist' have already been computed
3948 // and don't need to be recomputed.
3949
3950 if (emitIsCondJump(jmp))
3951 {
3952 if (jmpIG->igNum < tgtIG->igNum)
3953 {
3954 /* Forward jump */
3955
3956 /* How much beyond the max. medium distance does the jump go? */
3957
3958 mextra = jmpDist - pmd;
3959
3960#if DEBUG_EMIT
3961 assert(jmp->idDebugOnlyInfo() != NULL);
3962 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3963 {
3964 if (mextra > 0)
3965 {
3966 if (INTERESTING_JUMP_NUM == 0)
3967 printf("[6] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3968 printf("[6] Dist excess [S] = %d \n", mextra);
3969 }
3970 }
3971#endif // DEBUG_EMIT
3972
3973 if (mextra <= 0)
3974 {
3975 /* This jump will be a medium one */
3976 goto MEDIUM_JMP;
3977 }
3978 }
3979 else
3980 {
3981 /* Backward jump */
3982
3983 /* How much beyond the max. medium distance does the jump go? */
3984
3985 mextra = jmpDist + nmd;
3986
3987#if DEBUG_EMIT
3988 assert(jmp->idDebugOnlyInfo() != NULL);
3989 if (jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3990 {
3991 if (mextra > 0)
3992 {
3993 if (INTERESTING_JUMP_NUM == 0)
3994 printf("[7] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
3995 printf("[7] Dist excess [S] = %d \n", mextra);
3996 }
3997 }
3998#endif // DEBUG_EMIT
3999
4000 if (mextra <= 0)
4001 {
4002 /* This jump will be a medium one */
4003 goto MEDIUM_JMP;
4004 }
4005 }
4006
4007 /* We arrive here if the jump couldn't be made medium, at least for now */
4008
4009 /* Keep track of the closest distance we got */
4010
4011 if (minMediumExtra > (unsigned)mextra)
4012 minMediumExtra = (unsigned)mextra;
4013 }
4014
4015#endif // _TARGET_ARM_
4016
4017 /*****************************************************************************
4018 * We arrive here if the jump must stay long, at least for now.
4019 * Go try the next one.
4020 */
4021
4022 continue;
4023
4024 /*****************************************************************************/
4025 /* Handle conversion to short jump */
4026 /*****************************************************************************/
4027
4028 SHORT_JMP:
4029
4030 /* Try to make this jump a short one */
4031
4032 emitSetShortJump(jmp);
4033
4034 if (!jmp->idjShort)
4035 {
4036 continue; // This jump must be kept long
4037 }
4038
4039 /* This jump is becoming either short or medium */
4040
4041 oldSize = jsz;
4042 jsz = ssz;
4043 assert(oldSize >= jsz);
4044 sizeDif = oldSize - jsz;
4045
4046#if defined(_TARGET_XARCH_)
4047 jmp->idCodeSize(jsz);
4048#elif defined(_TARGET_ARM_)
4049#if 0
4050 // This is done as part of emitSetShortJump():
4051 insSize isz = emitInsSize(jmp->idInsFmt());
4052 jmp->idInsSize(isz);
4053#endif
4054#elif defined(_TARGET_ARM64_)
4055 // The size of IF_LARGEJMP/IF_LARGEADR/IF_LARGELDC are 8 or 12.
4056 // All other code size is 4.
4057 assert((sizeDif == 4) || (sizeDif == 8));
4058#else
4059#error Unsupported or unset target architecture
4060#endif
4061
4062 goto NEXT_JMP;
4063
4064#if defined(_TARGET_ARM_)
4065
4066 /*****************************************************************************/
4067 /* Handle conversion to medium jump */
4068 /*****************************************************************************/
4069
4070 MEDIUM_JMP:
4071
4072 /* Try to make this jump a medium one */
4073
4074 emitSetMediumJump(jmp);
4075
4076 if (jmp->idCodeSize() > msz)
4077 {
4078 continue; // This jump wasn't shortened
4079 }
4080 assert(jmp->idCodeSize() == msz);
4081
4082 /* This jump is becoming medium */
4083
4084 oldSize = jsz;
4085 jsz = msz;
4086 assert(oldSize >= jsz);
4087 sizeDif = oldSize - jsz;
4088
4089 goto NEXT_JMP;
4090
4091#endif // _TARGET_ARM_
4092
4093 /*****************************************************************************/
4094
4095 NEXT_JMP:
4096
4097 /* Make sure the size of the jump is marked correctly */
4098
4099 assert((0 == (jsz | jmpDist)) || (jsz == emitSizeOfJump(jmp)));
4100
4101#ifdef DEBUG
4102 if (EMITVERBOSE)
4103 {
4104 printf("Shrinking jump [%08X/%03u]\n", dspPtr(jmp), jmp->idDebugOnlyInfo()->idNum);
4105 }
4106#endif
4107 noway_assert((unsigned short)sizeDif == sizeDif);
4108
4109 adjIG += sizeDif;
4110 adjLJ += sizeDif;
4111 jmpIG->igSize -= (unsigned short)sizeDif;
4112 emitTotalCodeSize -= sizeDif;
4113
4114 /* The jump size estimate wasn't accurate; flag its group */
4115
4116 jmpIG->igFlags |= IGF_UPD_ISZ;
4117
4118 } // end for each jump
4119
4120 /* Did we shorten any jumps? */
4121
4122 if (adjIG)
4123 {
4124 /* Adjust offsets of any remaining blocks */
4125
4126 assert(lstIG);
4127
4128 for (;;)
4129 {
4130 lstIG = lstIG->igNext;
4131 if (!lstIG)
4132 {
4133 break;
4134 }
4135#ifdef DEBUG
4136 if (EMITVERBOSE)
4137 {
4138 printf("Adjusted offset of " FMT_BB " from %04X to %04X\n", lstIG->igNum, lstIG->igOffs,
4139 lstIG->igOffs - adjIG);
4140 }
4141#endif // DEBUG
4142 lstIG->igOffs -= adjIG;
4143 assert(IsCodeAligned(lstIG->igOffs));
4144 }
4145
4146#ifdef DEBUG
4147 emitCheckIGoffsets();
4148#endif
4149
4150 /* Is there a chance of other jumps becoming short? */
4151 CLANG_FORMAT_COMMENT_ANCHOR;
4152#ifdef DEBUG
4153#if defined(_TARGET_ARM_)
4154 if (EMITVERBOSE)
4155 printf("Total shrinkage = %3u, min extra short jump size = %3u, min extra medium jump size = %u\n", adjIG,
4156 minShortExtra, minMediumExtra);
4157#else
4158 if (EMITVERBOSE)
4159 {
4160 printf("Total shrinkage = %3u, min extra jump size = %3u\n", adjIG, minShortExtra);
4161 }
4162#endif
4163#endif
4164
4165 if ((minShortExtra <= adjIG)
4166#if defined(_TARGET_ARM_)
4167 || (minMediumExtra <= adjIG)
4168#endif // _TARGET_ARM_
4169 )
4170 {
4171 jmp_iteration++;
4172
4173#ifdef DEBUG
4174 if (EMITVERBOSE)
4175 {
4176 printf("Iterating branch shortening. Iteration = %d\n", jmp_iteration);
4177 }
4178#endif
4179
4180 goto AGAIN;
4181 }
4182 }
4183#ifdef DEBUG
4184 if (EMIT_INSTLIST_VERBOSE)
4185 {
4186 printf("\nLabels list after the jump dist binding:\n\n");
4187 emitDispIGlist(false);
4188 }
4189
4190 emitCheckIGoffsets();
4191#endif // DEBUG
4192}
4193
4194void emitter::emitCheckFuncletBranch(instrDesc* jmp, insGroup* jmpIG)
4195{
4196#ifdef DEBUG
4197 // We should not be jumping/branching across funclets/functions
4198 // Except possibly a 'call' to a finally funclet for a local unwind
4199 // or a 'return' from a catch handler (that can go just about anywhere)
4200 // This routine attempts to validate that any branches across funclets
4201 // meets one of those criteria...
4202 assert(jmp->idIsBound());
4203
4204#ifdef _TARGET_XARCH_
4205 // An lea of a code address (for constant data stored with the code)
4206 // is treated like a jump for emission purposes but is not really a jump so
4207 // we don't have to check anything here.
4208 if (jmp->idIns() == INS_lea)
4209 {
4210 return;
4211 }
4212#endif
4213
4214#ifdef _TARGET_ARMARCH_
4215 if (jmp->idAddr()->iiaHasInstrCount())
4216 {
4217 // Too hard to figure out funclets from just an instruction count
4218 // You're on your own!
4219 return;
4220 }
4221#endif // _TARGET_ARMARCH_
4222
4223#ifdef _TARGET_ARM64_
4224 // No interest if it's not jmp.
4225 if (emitIsLoadLabel(jmp) || emitIsLoadConstant(jmp))
4226 {
4227 return;
4228 }
4229#endif // _TARGET_ARM64_
4230
4231 insGroup* tgtIG = jmp->idAddr()->iiaIGlabel;
4232 assert(tgtIG);
4233 if (tgtIG->igFuncIdx != jmpIG->igFuncIdx)
4234 {
4235 if (jmp->idDebugOnlyInfo()->idFinallyCall)
4236 {
4237 // We don't record enough information to determine this accurately, so instead
4238 // we assume that any branch to the very start of a finally is OK.
4239
4240 // No branches back to the root method
4241 assert(tgtIG->igFuncIdx > 0);
4242 FuncInfoDsc* tgtFunc = emitComp->funGetFunc(tgtIG->igFuncIdx);
4243 assert(tgtFunc->funKind == FUNC_HANDLER);
4244 EHblkDsc* tgtEH = emitComp->ehGetDsc(tgtFunc->funEHIndex);
4245
4246 // Only branches to finallys (not faults, catches, filters, etc.)
4247 assert(tgtEH->HasFinallyHandler());
4248
4249 // Only to the first block of the finally (which is properly marked)
4250 BasicBlock* tgtBlk = tgtEH->ebdHndBeg;
4251 assert(tgtBlk->bbFlags & BBF_FUNCLET_BEG);
4252
4253 // And now we made it back to where we started
4254 assert(tgtIG == emitCodeGetCookie(tgtBlk));
4255 assert(tgtIG->igFuncIdx == emitComp->funGetFuncIdx(tgtBlk));
4256 }
4257 else if (jmp->idDebugOnlyInfo()->idCatchRet)
4258 {
4259 // Again there isn't enough information to prove this correct
4260 // so just allow a 'branch' to any other 'parent' funclet
4261
4262 FuncInfoDsc* jmpFunc = emitComp->funGetFunc(jmpIG->igFuncIdx);
4263 assert(jmpFunc->funKind == FUNC_HANDLER);
4264 EHblkDsc* jmpEH = emitComp->ehGetDsc(jmpFunc->funEHIndex);
4265
4266 // Only branches out of catches
4267 assert(jmpEH->HasCatchHandler());
4268
4269 FuncInfoDsc* tgtFunc = emitComp->funGetFunc(tgtIG->igFuncIdx);
4270 assert(tgtFunc);
4271 if (tgtFunc->funKind == FUNC_HANDLER)
4272 {
4273 // An outward chain to the containing funclet/EH handler
4274 // Note that it might be anywhere within nested try bodies
4275 assert(jmpEH->ebdEnclosingHndIndex == tgtFunc->funEHIndex);
4276 }
4277 else
4278 {
4279 // This funclet is 'top level' and so it is branching back to the
4280 // root function, and should have no containing EH handlers
4281 // but it could be nested within try bodies...
4282 assert(tgtFunc->funKind == FUNC_ROOT);
4283 assert(jmpEH->ebdEnclosingHndIndex == EHblkDsc::NO_ENCLOSING_INDEX);
4284 }
4285 }
4286 else
4287 {
4288 printf("Hit an illegal branch between funclets!");
4289 assert(tgtIG->igFuncIdx == jmpIG->igFuncIdx);
4290 }
4291 }
4292#endif // DEBUG
4293}
4294
4295/*****************************************************************************
4296 *
4297 * Compute the code sizes that we're going to use to allocate the code buffers.
4298 *
4299 * This sets:
4300 *
4301 * emitTotalHotCodeSize
4302 * emitTotalColdCodeSize
4303 * Compiler::info.compTotalHotCodeSize
4304 * Compiler::info.compTotalColdCodeSize
4305 */
4306
4307void emitter::emitComputeCodeSizes()
4308{
4309 assert((emitComp->fgFirstColdBlock == nullptr) == (emitFirstColdIG == nullptr));
4310
4311 if (emitFirstColdIG)
4312 {
4313 emitTotalHotCodeSize = emitFirstColdIG->igOffs;
4314 emitTotalColdCodeSize = emitTotalCodeSize - emitTotalHotCodeSize;
4315 }
4316 else
4317 {
4318 emitTotalHotCodeSize = emitTotalCodeSize;
4319 emitTotalColdCodeSize = 0;
4320 }
4321
4322 emitComp->info.compTotalHotCodeSize = emitTotalHotCodeSize;
4323 emitComp->info.compTotalColdCodeSize = emitTotalColdCodeSize;
4324
4325#ifdef DEBUG
4326 if (emitComp->verbose)
4327 {
4328 printf("\nHot code size = 0x%X bytes\n", emitTotalHotCodeSize);
4329 printf("Cold code size = 0x%X bytes\n", emitTotalColdCodeSize);
4330 }
4331#endif
4332}
4333
4334/*****************************************************************************
4335 *
4336 * Called at the end of code generation, this method creates the code, data
4337 * and GC info blocks for the method. Returns the size of the method (which must fit in an unsigned).
4338 */
4339
4340unsigned emitter::emitEndCodeGen(Compiler* comp,
4341 bool contTrkPtrLcls,
4342 bool fullyInt,
4343 bool fullPtrMap,
4344 bool returnsGCr,
4345 unsigned xcptnsCount,
4346 unsigned* prologSize,
4347 unsigned* epilogSize,
4348 void** codeAddr,
4349 void** coldCodeAddr,
4350 void** consAddr)
4351{
4352#ifdef DEBUG
4353 if (emitComp->verbose)
4354 {
4355 printf("*************** In emitEndCodeGen()\n");
4356 }
4357#endif
4358
4359 BYTE* consBlock;
4360 BYTE* codeBlock;
4361 BYTE* coldCodeBlock;
4362 BYTE* cp;
4363
4364 assert(emitCurIG == nullptr);
4365
4366 emitCodeBlock = nullptr;
4367 emitConsBlock = nullptr;
4368
4369 /* Tell everyone whether we have fully interruptible code or not */
4370
4371 emitFullyInt = fullyInt;
4372 emitFullGCinfo = fullPtrMap;
4373
4374#ifndef UNIX_X86_ABI
4375 emitFullArgInfo = !emitHasFramePtr;
4376#else
4377 emitFullArgInfo = fullPtrMap;
4378#endif
4379
4380#if EMITTER_STATS
4381 GCrefsTable.record(emitGCrFrameOffsCnt);
4382 emitSizeTable.record(static_cast<unsigned>(emitSizeMethod));
4383 stkDepthTable.record(emitMaxStackDepth);
4384#endif // EMITTER_STATS
4385
4386 // Default values, correct even if EMIT_TRACK_STACK_DEPTH is 0.
4387 emitSimpleStkUsed = true;
4388 u1.emitSimpleStkMask = 0;
4389 u1.emitSimpleByrefStkMask = 0;
4390
4391#if EMIT_TRACK_STACK_DEPTH
4392 /* Convert max. stack depth from # of bytes to # of entries */
4393
4394 unsigned maxStackDepthIn4ByteElements = emitMaxStackDepth / sizeof(int);
4395 JITDUMP("Converting emitMaxStackDepth from bytes (%d) to elements (%d)\n", emitMaxStackDepth,
4396 maxStackDepthIn4ByteElements);
4397 emitMaxStackDepth = maxStackDepthIn4ByteElements;
4398
4399 /* Should we use the simple stack */
4400
4401 if (emitMaxStackDepth > MAX_SIMPLE_STK_DEPTH || emitFullGCinfo)
4402 {
4403 /* We won't use the "simple" argument table */
4404
4405 emitSimpleStkUsed = false;
4406
4407 /* Allocate the argument tracking table */
4408
4409 if (emitMaxStackDepth <= sizeof(u2.emitArgTrackLcl))
4410 {
4411 u2.emitArgTrackTab = (BYTE*)u2.emitArgTrackLcl;
4412 }
4413 else
4414 {
4415 u2.emitArgTrackTab = (BYTE*)emitGetMem(roundUp(emitMaxStackDepth));
4416 }
4417
4418 u2.emitArgTrackTop = u2.emitArgTrackTab;
4419 u2.emitGcArgTrackCnt = 0;
4420 }
4421#endif
4422
4423 if (emitEpilogCnt == 0)
4424 {
4425 /* No epilogs, make sure the epilog size is set to 0 */
4426
4427 emitEpilogSize = 0;
4428
4429#ifdef _TARGET_XARCH_
4430 emitExitSeqSize = 0;
4431#endif // _TARGET_XARCH_
4432 }
4433
4434 /* Return the size of the epilog to the caller */
4435
4436 *epilogSize = emitEpilogSize;
4437
4438#ifdef _TARGET_XARCH_
4439 *epilogSize += emitExitSeqSize;
4440#endif // _TARGET_XARCH_
4441
4442#ifdef DEBUG
4443 if (EMIT_INSTLIST_VERBOSE)
4444 {
4445 printf("\nInstruction list before instruction issue:\n\n");
4446 emitDispIGlist(true);
4447 }
4448
4449 emitCheckIGoffsets();
4450#endif
4451
4452 /* Allocate the code block (and optionally the data blocks) */
4453
4454 // If we're doing procedure splitting and we found cold blocks, then
4455 // allocate hot and cold buffers. Otherwise only allocate a hot
4456 // buffer.
4457
4458 coldCodeBlock = nullptr;
4459
4460 CorJitAllocMemFlag allocMemFlag = CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN;
4461
4462#ifdef _TARGET_X86_
4463 //
4464 // These are the heuristics we use to decide whether or not to force the
4465 // code to be 16-byte aligned.
4466 //
4467 // 1. For ngen code with IBC data, use 16-byte alignment if the method
4468 // has been called more than BB_VERY_HOT_WEIGHT times.
4469 // 2. For JITed code and ngen code without IBC data, use 16-byte alignment
4470 // when the code is 16 bytes or smaller. We align small getters/setters
4471 // because of they are penalized heavily on certain hardware when not 16-byte
4472 // aligned (VSWhidbey #373938). To minimize size impact of this optimization,
4473 // we do not align large methods because of the penalty is amortized for them.
4474 //
4475 if (emitComp->fgHaveProfileData())
4476 {
4477 if (emitComp->fgCalledCount > (BB_VERY_HOT_WEIGHT * emitComp->fgProfileRunsCount()))
4478 {
4479 allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN;
4480 }
4481 }
4482 else
4483 {
4484 if (emitTotalHotCodeSize <= 16)
4485 {
4486 allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN;
4487 }
4488 }
4489#endif
4490
4491#ifdef _TARGET_ARM64_
4492 // For arm64, we want to allocate JIT data always adjacent to code similar to what native compiler does.
4493 // This way allows us to use a single `ldr` to access such data like float constant/jmp table.
4494 if (emitTotalColdCodeSize > 0)
4495 {
4496 // JIT data might be far away from the cold code.
4497 NYI_ARM64("Need to handle fix-up to data from cold code.");
4498 }
4499
4500 UNATIVE_OFFSET roDataAlignmentDelta = 0;
4501 if (emitConsDsc.dsdOffs)
4502 {
4503 UNATIVE_OFFSET roDataAlignment = TARGET_POINTER_SIZE; // 8 Byte align by default.
4504 roDataAlignmentDelta = (UNATIVE_OFFSET)ALIGN_UP(emitTotalHotCodeSize, roDataAlignment) - emitTotalHotCodeSize;
4505 assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4));
4506 }
4507 emitCmpHandle->allocMem(emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs, emitTotalColdCodeSize, 0,
4508 xcptnsCount, allocMemFlag, (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock);
4509
4510 consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta;
4511
4512#else
4513 emitCmpHandle->allocMem(emitTotalHotCodeSize, emitTotalColdCodeSize, emitConsDsc.dsdOffs, xcptnsCount, allocMemFlag,
4514 (void**)&codeBlock, (void**)&coldCodeBlock, (void**)&consBlock);
4515#endif
4516
4517 // if (emitConsDsc.dsdOffs)
4518 // printf("Cons=%08X\n", consBlock);
4519
4520 /* Give the block addresses to the caller and other functions here */
4521
4522 *codeAddr = emitCodeBlock = codeBlock;
4523 *coldCodeAddr = emitColdCodeBlock = coldCodeBlock;
4524 *consAddr = emitConsBlock = consBlock;
4525
4526 /* Nothing has been pushed on the stack */
4527 CLANG_FORMAT_COMMENT_ANCHOR;
4528
4529#if EMIT_TRACK_STACK_DEPTH
4530 emitCurStackLvl = 0;
4531#endif
4532
4533 /* Assume no live GC ref variables on entry */
4534
4535 VarSetOps::ClearD(emitComp, emitThisGCrefVars); // This is initialized to Empty at the start of codegen.
4536 emitThisGCrefRegs = emitThisByrefRegs = RBM_NONE;
4537 emitThisGCrefVset = true;
4538
4539#ifdef DEBUG
4540
4541 emitIssuing = true;
4542
4543 // We don't use these after this point
4544
4545 VarSetOps::AssignNoCopy(emitComp, emitPrevGCrefVars, VarSetOps::UninitVal());
4546 emitPrevGCrefRegs = emitPrevByrefRegs = 0xBAADFEED;
4547
4548 VarSetOps::AssignNoCopy(emitComp, emitInitGCrefVars, VarSetOps::UninitVal());
4549 emitInitGCrefRegs = emitInitByrefRegs = 0xBAADFEED;
4550
4551#endif
4552
4553 /* Initialize the GC ref variable lifetime tracking logic */
4554
4555 codeGen->gcInfo.gcVarPtrSetInit();
4556
4557 emitSyncThisObjOffs = -1; /* -1 means no offset set */
4558 emitSyncThisObjReg = REG_NA; /* REG_NA means not set */
4559
4560#ifdef JIT32_GCENCODER
4561 if (emitComp->lvaKeepAliveAndReportThis())
4562 {
4563 assert(emitComp->lvaIsOriginalThisArg(0));
4564 LclVarDsc* thisDsc = &emitComp->lvaTable[0];
4565
4566 /* If "this" (which is passed in as a register argument in REG_ARG_0)
4567 is enregistered, we normally spot the "mov REG_ARG_0 -> thisReg"
4568 in the prolog and note the location of "this" at that point.
4569 However, if 'this' is enregistered into REG_ARG_0 itself, no code
4570 will be generated in the prolog, so we explicitly need to note
4571 the location of "this" here.
4572 NOTE that we can do this even if "this" is not enregistered in
4573 REG_ARG_0, and it will result in more accurate "this" info over the
4574 prolog. However, as methods are not interruptible over the prolog,
4575 we try to save space by avoiding that.
4576 */
4577
4578 if (thisDsc->lvRegister)
4579 {
4580 emitSyncThisObjReg = thisDsc->lvRegNum;
4581
4582 if (emitSyncThisObjReg == (int)REG_ARG_0 &&
4583 (codeGen->intRegState.rsCalleeRegArgMaskLiveIn & genRegMask(REG_ARG_0)))
4584 {
4585 if (emitFullGCinfo)
4586 {
4587 emitGCregLiveSet(GCT_GCREF, genRegMask(REG_ARG_0),
4588 emitCodeBlock, // from offset 0
4589 true);
4590 }
4591 else
4592 {
4593 /* If emitFullGCinfo==false, the we don't use any
4594 regPtrDsc's and so explictly note the location
4595 of "this" in GCEncode.cpp
4596 */
4597 }
4598 }
4599 }
4600 }
4601#endif // JIT32_GCENCODER
4602
4603 emitContTrkPtrLcls = contTrkPtrLcls;
4604
4605 /* Are there any GC ref variables on the stack? */
4606
4607 if (emitGCrFrameOffsCnt)
4608 {
4609 size_t siz;
4610 unsigned cnt;
4611 unsigned num;
4612 LclVarDsc* dsc;
4613 int* tab;
4614
4615 /* Allocate and clear emitGCrFrameLiveTab[]. This is the table
4616 mapping "stkOffs -> varPtrDsc". It holds a pointer to
4617 the liveness descriptor that was created when the
4618 variable became alive. When the variable becomes dead, the
4619 descriptor will be appended to the liveness descriptor list, and
4620 the entry in emitGCrFrameLiveTab[] will be made NULL.
4621
4622 Note that if all GC refs are assigned consecutively,
4623 emitGCrFrameLiveTab[] can be only as big as the number of GC refs
4624 present, instead of lvaTrackedCount.
4625 */
4626
4627 siz = emitGCrFrameOffsCnt * sizeof(*emitGCrFrameLiveTab);
4628 emitGCrFrameLiveTab = (varPtrDsc**)emitGetMem(roundUp(siz));
4629 memset(emitGCrFrameLiveTab, 0, siz);
4630
4631 /* Allocate and fill in emitGCrFrameOffsTab[]. This is the table
4632 mapping "varIndex -> stkOffs".
4633 Non-ptrs or reg vars have entries of -1.
4634 Entries of Tracked stack byrefs have the lower bit set to 1.
4635 */
4636
4637 emitTrkVarCnt = cnt = emitComp->lvaTrackedCount;
4638 assert(cnt);
4639 emitGCrFrameOffsTab = tab = (int*)emitGetMem(cnt * sizeof(int));
4640
4641 memset(emitGCrFrameOffsTab, -1, cnt * sizeof(int));
4642
4643 /* Now fill in all the actual used entries */
4644
4645 for (num = 0, dsc = emitComp->lvaTable, cnt = emitComp->lvaCount; num < cnt; num++, dsc++)
4646 {
4647 if (!dsc->lvOnFrame || (dsc->lvIsParam && !dsc->lvIsRegArg))
4648 {
4649 continue;
4650 }
4651
4652#if FEATURE_FIXED_OUT_ARGS
4653 if (num == emitComp->lvaOutgoingArgSpaceVar)
4654 {
4655 continue;
4656 }
4657#endif // FEATURE_FIXED_OUT_ARGS
4658
4659 int offs = dsc->lvStkOffs;
4660
4661 /* Is it within the interesting range of offsets */
4662
4663 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
4664 {
4665 /* Are tracked stack ptr locals laid out contiguously?
4666 If not, skip non-ptrs. The emitter is optimized to work
4667 with contiguous ptrs, but for EditNContinue, the variables
4668 are laid out in the order they occur in the local-sig.
4669 */
4670
4671 if (!emitContTrkPtrLcls)
4672 {
4673 if (!emitComp->lvaIsGCTracked(dsc))
4674 {
4675 continue;
4676 }
4677 }
4678
4679 unsigned indx = dsc->lvVarIndex;
4680
4681 assert(!dsc->lvRegister);
4682 assert(dsc->lvTracked);
4683 assert(dsc->lvRefCnt() != 0);
4684
4685 assert(dsc->TypeGet() == TYP_REF || dsc->TypeGet() == TYP_BYREF);
4686
4687 assert(indx < emitComp->lvaTrackedCount);
4688
4689// printf("Variable #%2u/%2u is at stack offset %d\n", num, indx, offs);
4690
4691#ifdef JIT32_GCENCODER
4692#ifndef WIN64EXCEPTIONS
4693 /* Remember the frame offset of the "this" argument for synchronized methods */
4694 if (emitComp->lvaIsOriginalThisArg(num) && emitComp->lvaKeepAliveAndReportThis())
4695 {
4696 emitSyncThisObjOffs = offs;
4697 offs |= this_OFFSET_FLAG;
4698 }
4699#endif
4700#endif // JIT32_GCENCODER
4701
4702 if (dsc->TypeGet() == TYP_BYREF)
4703 {
4704 offs |= byref_OFFSET_FLAG;
4705 }
4706 tab[indx] = offs;
4707 }
4708 }
4709 }
4710 else
4711 {
4712#ifdef DEBUG
4713 emitTrkVarCnt = 0;
4714 emitGCrFrameOffsTab = nullptr;
4715#endif
4716 }
4717
4718#ifdef DEBUG
4719 if (emitComp->verbose)
4720 {
4721 printf("\n***************************************************************************\n");
4722 printf("Instructions as they come out of the scheduler\n\n");
4723 }
4724#endif
4725
4726 /* Issue all instruction groups in order */
4727 cp = codeBlock;
4728
4729#define DEFAULT_CODE_BUFFER_INIT 0xcc
4730
4731 for (insGroup* ig = emitIGlist; ig != nullptr; ig = ig->igNext)
4732 {
4733 assert(!(ig->igFlags & IGF_PLACEHOLDER)); // There better not be any placeholder groups left
4734
4735 /* Is this the first cold block? */
4736 if (ig == emitFirstColdIG)
4737 {
4738 assert(emitCurCodeOffs(cp) == emitTotalHotCodeSize);
4739
4740 assert(coldCodeBlock);
4741 cp = coldCodeBlock;
4742#ifdef DEBUG
4743 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
4744 {
4745 printf("\n************** Beginning of cold code **************\n");
4746 }
4747#endif
4748 }
4749
4750 /* Are we overflowing? */
4751 if (ig->igNext && (ig->igNum + 1 != ig->igNext->igNum))
4752 {
4753 NO_WAY("Too many instruction groups");
4754 }
4755
4756 // If this instruction group is returned to from a funclet implementing a finally,
4757 // on architectures where it is necessary generate GC info for the current instruction as
4758 // if it were the instruction following a call.
4759 emitGenGCInfoIfFuncletRetTarget(ig, cp);
4760
4761 instrDesc* id = (instrDesc*)ig->igData;
4762
4763#ifdef DEBUG
4764
4765 /* Print the IG label, but only if it is a branch label */
4766
4767 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
4768 {
4769 if (emitComp->verbose)
4770 {
4771 printf("\n");
4772 emitDispIG(ig); // Display the flags, IG data, etc.
4773 }
4774 else
4775 {
4776 printf("\nG_M%03u_IG%02u:\n", Compiler::s_compMethodsCount, ig->igNum);
4777 }
4778 }
4779
4780#endif // DEBUG
4781
4782 BYTE* bp = cp;
4783
4784 /* Record the actual offset of the block, noting the difference */
4785
4786 emitOffsAdj = ig->igOffs - emitCurCodeOffs(cp);
4787 assert(emitOffsAdj >= 0);
4788
4789#if DEBUG_EMIT
4790 if ((emitOffsAdj != 0) && emitComp->verbose)
4791 {
4792 printf("Block predicted offs = %08X, actual = %08X -> size adj = %d\n", ig->igOffs, emitCurCodeOffs(cp),
4793 emitOffsAdj);
4794 }
4795#endif // DEBUG_EMIT
4796
4797 ig->igOffs = emitCurCodeOffs(cp);
4798 assert(IsCodeAligned(ig->igOffs));
4799
4800#if EMIT_TRACK_STACK_DEPTH
4801
4802 /* Set the proper stack level if appropriate */
4803
4804 if (ig->igStkLvl != emitCurStackLvl)
4805 {
4806 /* We are pushing stuff implicitly at this label */
4807
4808 assert((unsigned)ig->igStkLvl > (unsigned)emitCurStackLvl);
4809 emitStackPushN(cp, (ig->igStkLvl - (unsigned)emitCurStackLvl) / sizeof(int));
4810 }
4811
4812#endif
4813
4814 /* Update current GC information for non-overflow IG (not added implicitly by the emitter) */
4815
4816 if (!(ig->igFlags & IGF_EMIT_ADD))
4817 {
4818 /* Is there a new set of live GC ref variables? */
4819
4820 if (ig->igFlags & IGF_GC_VARS)
4821 {
4822 emitUpdateLiveGCvars(ig->igGCvars(), cp);
4823 }
4824 else if (!emitThisGCrefVset)
4825 {
4826 emitUpdateLiveGCvars(emitThisGCrefVars, cp);
4827 }
4828
4829 /* Update the set of live GC ref registers */
4830
4831 {
4832 regMaskTP GCregs = ig->igGCregs;
4833
4834 if (GCregs != emitThisGCrefRegs)
4835 {
4836 emitUpdateLiveGCregs(GCT_GCREF, GCregs, cp);
4837 }
4838 }
4839
4840 /* Is there a new set of live byref registers? */
4841
4842 if (ig->igFlags & IGF_BYREF_REGS)
4843 {
4844 unsigned byrefRegs = ig->igByrefRegs();
4845
4846 if (byrefRegs != emitThisByrefRegs)
4847 {
4848 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, cp);
4849 }
4850 }
4851 }
4852 else
4853 {
4854 // These are not set for "overflow" groups
4855 assert(!(ig->igFlags & IGF_GC_VARS));
4856 assert(!(ig->igFlags & IGF_BYREF_REGS));
4857 }
4858
4859 /* Issue each instruction in order */
4860
4861 emitCurIG = ig;
4862
4863 for (unsigned cnt = ig->igInsCnt; cnt; cnt--)
4864 {
4865 castto(id, BYTE*) += emitIssue1Instr(ig, id, &cp);
4866 }
4867
4868 emitCurIG = nullptr;
4869
4870 assert(ig->igSize >= cp - bp);
4871
4872 // Is it the last ig in the hot part?
4873 bool lastHotIG = (emitFirstColdIG != nullptr && ig->igNext == emitFirstColdIG);
4874 if (lastHotIG)
4875 {
4876 unsigned actualHotCodeSize = emitCurCodeOffs(cp);
4877 unsigned allocatedHotCodeSize = emitTotalHotCodeSize;
4878 assert(actualHotCodeSize <= allocatedHotCodeSize);
4879 if (actualHotCodeSize < allocatedHotCodeSize)
4880 {
4881 // The allocated chunk is bigger than used, fill in unused space in it.
4882 unsigned unusedSize = allocatedHotCodeSize - emitCurCodeOffs(cp);
4883 for (unsigned i = 0; i < unusedSize; ++i)
4884 {
4885 *cp++ = DEFAULT_CODE_BUFFER_INIT;
4886 }
4887 assert(allocatedHotCodeSize == emitCurCodeOffs(cp));
4888 }
4889 }
4890
4891 assert((ig->igSize >= cp - bp) || lastHotIG);
4892 ig->igSize = (unsigned short)(cp - bp);
4893 }
4894
4895#if EMIT_TRACK_STACK_DEPTH
4896 assert(emitCurStackLvl == 0);
4897#endif
4898
4899 /* Output any initialized data we may have */
4900
4901 if (emitConsDsc.dsdOffs != 0)
4902 {
4903 emitOutputDataSec(&emitConsDsc, consBlock);
4904 }
4905
4906 /* Make sure all GC ref variables are marked as dead */
4907
4908 if (emitGCrFrameOffsCnt != 0)
4909 {
4910 unsigned vn;
4911 int of;
4912 varPtrDsc** dp;
4913
4914 for (vn = 0, of = emitGCrFrameOffsMin, dp = emitGCrFrameLiveTab; vn < emitGCrFrameOffsCnt;
4915 vn++, of += TARGET_POINTER_SIZE, dp++)
4916 {
4917 if (*dp)
4918 {
4919 emitGCvarDeadSet(of, cp, vn);
4920 }
4921 }
4922 }
4923
4924 /* No GC registers are live any more */
4925
4926 if (emitThisByrefRegs)
4927 {
4928 emitUpdateLiveGCregs(GCT_BYREF, RBM_NONE, cp);
4929 }
4930 if (emitThisGCrefRegs)
4931 {
4932 emitUpdateLiveGCregs(GCT_GCREF, RBM_NONE, cp);
4933 }
4934
4935 /* Patch any forward jumps */
4936
4937 if (emitFwdJumps)
4938 {
4939 for (instrDescJmp* jmp = emitJumpList; jmp != nullptr; jmp = jmp->idjNext)
4940 {
4941#ifdef _TARGET_XARCH_
4942 assert(jmp->idInsFmt() == IF_LABEL || jmp->idInsFmt() == IF_RWR_LABEL || jmp->idInsFmt() == IF_SWR_LABEL);
4943#endif
4944 insGroup* tgt = jmp->idAddr()->iiaIGlabel;
4945
4946 if (jmp->idjTemp.idjAddr == nullptr)
4947 {
4948 continue;
4949 }
4950
4951 if (jmp->idjOffs != tgt->igOffs)
4952 {
4953 BYTE* adr = jmp->idjTemp.idjAddr;
4954 int adj = jmp->idjOffs - tgt->igOffs;
4955#ifdef _TARGET_ARM_
4956 // On Arm, the offset is encoded in unit of 2 bytes.
4957 adj >>= 1;
4958#endif
4959
4960#if DEBUG_EMIT
4961 if ((jmp->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM) || (INTERESTING_JUMP_NUM == 0))
4962 {
4963#ifdef _TARGET_ARM_
4964 printf("[5] This output is broken for ARM, since it doesn't properly decode the jump offsets of "
4965 "the instruction at adr\n");
4966#endif
4967
4968 if (INTERESTING_JUMP_NUM == 0)
4969 {
4970 printf("[5] Jump %u:\n", jmp->idDebugOnlyInfo()->idNum);
4971 }
4972
4973 if (jmp->idjShort)
4974 {
4975 printf("[5] Jump is at %08X\n", (adr + 1 - emitCodeBlock));
4976 printf("[5] Jump distance is %02X - %02X = %02X\n", *(BYTE*)adr, adj, *(BYTE*)adr - adj);
4977 }
4978 else
4979 {
4980 printf("[5] Jump is at %08X\n", (adr + 4 - emitCodeBlock));
4981 printf("[5] Jump distance is %08X - %02X = %08X\n", *(int*)adr, adj, *(int*)adr - adj);
4982 }
4983 }
4984#endif // DEBUG_EMIT
4985
4986 if (jmp->idjShort)
4987 {
4988 // Patch Forward Short Jump
4989 CLANG_FORMAT_COMMENT_ANCHOR;
4990#if defined(_TARGET_XARCH_)
4991 *(BYTE*)adr -= (BYTE)adj;
4992#elif defined(_TARGET_ARM_)
4993 // The following works because the jump offset is in the low order bits of the instruction.
4994 // Presumably we could also just call "emitOutputLJ(NULL, adr, jmp)", like for long jumps?
4995 *(short int*)adr -= (short)adj;
4996#elif defined(_TARGET_ARM64_)
4997 assert(!jmp->idAddr()->iiaHasInstrCount());
4998 emitOutputLJ(NULL, adr, jmp);
4999#else
5000#error Unsupported or unset target architecture
5001#endif
5002 }
5003 else
5004 {
5005 // Patch Forward non-Short Jump
5006 CLANG_FORMAT_COMMENT_ANCHOR;
5007#if defined(_TARGET_XARCH_)
5008 *(int*)adr -= adj;
5009#elif defined(_TARGET_ARMARCH_)
5010 assert(!jmp->idAddr()->iiaHasInstrCount());
5011 emitOutputLJ(NULL, adr, jmp);
5012#else
5013#error Unsupported or unset target architecture
5014#endif
5015 }
5016 }
5017 }
5018 }
5019
5020#ifdef DEBUG
5021 if (emitComp->opts.disAsm)
5022 {
5023 printf("\n");
5024 }
5025
5026 if (emitComp->verbose)
5027 {
5028 printf("Allocated method code size = %4u , actual size = %4u\n", emitTotalCodeSize, cp - codeBlock);
5029 }
5030#endif
5031
5032 unsigned actualCodeSize = emitCurCodeOffs(cp);
5033
5034#if EMITTER_STATS
5035 totAllocdSize += emitTotalCodeSize;
5036 totActualSize += actualCodeSize;
5037#endif
5038
5039 // Fill in eventual unused space, but do not report this space as used.
5040 // If you add this padding during the emitIGlist loop, then it will
5041 // emit offsets after the loop with wrong value (for example for GC ref variables).
5042 unsigned unusedSize = emitTotalCodeSize - emitCurCodeOffs(cp);
5043 for (unsigned i = 0; i < unusedSize; ++i)
5044 {
5045 *cp++ = DEFAULT_CODE_BUFFER_INIT;
5046 }
5047 assert(emitTotalCodeSize == emitCurCodeOffs(cp));
5048
5049 // Total code size is sum of all IG->size and doesn't include padding in the last IG.
5050 emitTotalCodeSize = actualCodeSize;
5051
5052#ifdef DEBUG
5053
5054 // Make sure these didn't change during the "issuing" phase
5055
5056 assert(VarSetOps::MayBeUninit(emitPrevGCrefVars));
5057 assert(emitPrevGCrefRegs == 0xBAADFEED);
5058 assert(emitPrevByrefRegs == 0xBAADFEED);
5059
5060 assert(VarSetOps::MayBeUninit(emitInitGCrefVars));
5061 assert(emitInitGCrefRegs == 0xBAADFEED);
5062 assert(emitInitByrefRegs == 0xBAADFEED);
5063
5064 if (EMIT_INSTLIST_VERBOSE)
5065 {
5066 printf("\nLabels list after the end of codegen:\n\n");
5067 emitDispIGlist(false);
5068 }
5069
5070 emitCheckIGoffsets();
5071
5072#endif // DEBUG
5073
5074 // Assign the real prolog size
5075 *prologSize = emitCodeOffset(emitPrologIG, emitPrologEndPos);
5076
5077 /* Return the amount of code we've generated */
5078
5079 return actualCodeSize;
5080}
5081
5082// See specification comment at the declaration.
5083void emitter::emitGenGCInfoIfFuncletRetTarget(insGroup* ig, BYTE* cp)
5084{
5085#if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
5086 // We only emit this GC information on targets where finally's are implemented via funclets,
5087 // and the finally is invoked, during non-exceptional execution, via a branch with a predefined
5088 // link register, rather than a "true call" for which we would already generate GC info. Currently,
5089 // this means precisely ARM.
5090 if (ig->igFlags & IGF_FINALLY_TARGET)
5091 {
5092 // We don't actually have a call instruction in this case, so we don't have
5093 // a real size for that instruction. We'll use 1.
5094 emitStackPop(cp, /*isCall*/ true, /*callInstrSize*/ 1, /*args*/ 0);
5095
5096 /* Do we need to record a call location for GC purposes? */
5097 if (!emitFullGCinfo)
5098 {
5099 emitRecordGCcall(cp, /*callInstrSize*/ 1);
5100 }
5101 }
5102#endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
5103}
5104
5105/*****************************************************************************
5106 *
5107 * We have an instruction in an insGroup and we need to know the
5108 * instruction number for this instruction
5109 */
5110
5111unsigned emitter::emitFindInsNum(insGroup* ig, instrDesc* idMatch)
5112{
5113 instrDesc* id = (instrDesc*)ig->igData;
5114
5115 // Check if we are the first instruction in the group
5116 if (id == idMatch)
5117 {
5118 return 0;
5119 }
5120
5121 /* Walk the list of instructions until we find a match */
5122 unsigned insNum = 0;
5123 unsigned insRemaining = ig->igInsCnt;
5124
5125 while (insRemaining > 0)
5126 {
5127 castto(id, BYTE*) += emitSizeOfInsDsc(id);
5128 insNum++;
5129 insRemaining--;
5130
5131 if (id == idMatch)
5132 {
5133 return insNum;
5134 }
5135 }
5136 assert(!"emitFindInsNum failed");
5137 return -1;
5138}
5139
5140/*****************************************************************************
5141 *
5142 * We've been asked for the code offset of an instruction but alas one or
5143 * more instruction sizes in the block have been mis-predicted, so we have
5144 * to find the true offset by looking for the instruction within the group.
5145 */
5146
5147UNATIVE_OFFSET emitter::emitFindOffset(insGroup* ig, unsigned insNum)
5148{
5149 instrDesc* id = (instrDesc*)ig->igData;
5150 UNATIVE_OFFSET of = 0;
5151
5152#ifdef DEBUG
5153 /* Make sure we were passed reasonable arguments */
5154 assert(ig && ig->igSelf == ig);
5155 assert(ig->igInsCnt >= insNum);
5156#endif
5157
5158 /* Walk the instruction list until all are counted */
5159
5160 while (insNum > 0)
5161 {
5162 of += emitInstCodeSz(id);
5163
5164 castto(id, BYTE*) += emitSizeOfInsDsc(id);
5165
5166 insNum--;
5167 }
5168
5169 return of;
5170}
5171
5172/*****************************************************************************
5173 *
5174 * Start generating a constant data section for the current
5175 * function. Returns the offset of the section in the appropriate data
5176 * block.
5177 */
5178
5179UNATIVE_OFFSET emitter::emitDataGenBeg(UNATIVE_OFFSET size, bool dblAlign, bool codeLtab)
5180{
5181 unsigned secOffs;
5182 dataSection* secDesc;
5183
5184 assert(emitDataSecCur == nullptr);
5185
5186 /* The size better not be some kind of an odd thing */
5187
5188 assert(size && size % sizeof(int) == 0);
5189
5190 /* Get hold of the current offset */
5191
5192 secOffs = emitConsDsc.dsdOffs;
5193
5194 /* Are we require to align this request on an eight byte boundry? */
5195 if (dblAlign && (secOffs % sizeof(double) != 0))
5196 {
5197 /* Need to skip 4 bytes to honor dblAlign */
5198 /* Must allocate a dummy 4 byte integer */
5199 int zero = 0;
5200 emitDataGenBeg(4, false, false);
5201 emitDataGenData(0, &zero, 4);
5202 emitDataGenEnd();
5203
5204 /* Get the new secOffs */
5205 secOffs = emitConsDsc.dsdOffs;
5206 /* Now it should be a multiple of 8 */
5207 assert(secOffs % sizeof(double) == 0);
5208 }
5209
5210 /* Advance the current offset */
5211
5212 emitConsDsc.dsdOffs += size;
5213
5214 /* Allocate a data section descriptor and add it to the list */
5215
5216 secDesc = emitDataSecCur = (dataSection*)emitGetMem(roundUp(sizeof(*secDesc) + size));
5217
5218 secDesc->dsSize = size;
5219
5220 secDesc->dsType = dataSection::data;
5221
5222 secDesc->dsNext = nullptr;
5223
5224 if (emitConsDsc.dsdLast)
5225 {
5226 emitConsDsc.dsdLast->dsNext = secDesc;
5227 }
5228 else
5229 {
5230 emitConsDsc.dsdList = secDesc;
5231 }
5232 emitConsDsc.dsdLast = secDesc;
5233
5234 return secOffs;
5235}
5236
5237// Start generating a constant data section for the current function
5238// populated with BasicBlock references.
5239// You can choose the references to be either absolute pointers, or
5240// 4-byte relative addresses.
5241// Currently the relative references are relative to the start of the
5242// first block (this is somewhat arbitrary)
5243
5244UNATIVE_OFFSET emitter::emitBBTableDataGenBeg(unsigned numEntries, bool relativeAddr)
5245{
5246 unsigned secOffs;
5247 dataSection* secDesc;
5248
5249 assert(emitDataSecCur == nullptr);
5250
5251 UNATIVE_OFFSET emittedSize;
5252
5253 if (relativeAddr)
5254 {
5255 emittedSize = numEntries * 4;
5256 }
5257 else
5258 {
5259 emittedSize = numEntries * TARGET_POINTER_SIZE;
5260 }
5261
5262 /* Get hold of the current offset */
5263
5264 secOffs = emitConsDsc.dsdOffs;
5265
5266 /* Advance the current offset */
5267
5268 emitConsDsc.dsdOffs += emittedSize;
5269
5270 /* Allocate a data section descriptor and add it to the list */
5271
5272 secDesc = emitDataSecCur = (dataSection*)emitGetMem(roundUp(sizeof(*secDesc) + numEntries * sizeof(BasicBlock*)));
5273
5274 secDesc->dsSize = emittedSize;
5275
5276 secDesc->dsType = relativeAddr ? dataSection::blockRelative32 : dataSection::blockAbsoluteAddr;
5277
5278 secDesc->dsNext = nullptr;
5279
5280 if (emitConsDsc.dsdLast)
5281 {
5282 emitConsDsc.dsdLast->dsNext = secDesc;
5283 }
5284 else
5285 {
5286 emitConsDsc.dsdList = secDesc;
5287 }
5288
5289 emitConsDsc.dsdLast = secDesc;
5290
5291 return secOffs;
5292}
5293
5294/*****************************************************************************
5295 *
5296 * Emit the given block of bits into the current data section.
5297 */
5298
5299void emitter::emitDataGenData(unsigned offs, const void* data, size_t size)
5300{
5301 assert(emitDataSecCur && (emitDataSecCur->dsSize >= offs + size));
5302
5303 assert(emitDataSecCur->dsType == dataSection::data);
5304
5305 memcpy(emitDataSecCur->dsCont + offs, data, size);
5306}
5307
5308/*****************************************************************************
5309 *
5310 * Emit the address of the given basic block into the current data section.
5311 */
5312
5313void emitter::emitDataGenData(unsigned index, BasicBlock* label)
5314{
5315 assert(emitDataSecCur != nullptr);
5316 assert(emitDataSecCur->dsType == dataSection::blockAbsoluteAddr ||
5317 emitDataSecCur->dsType == dataSection::blockRelative32);
5318
5319 unsigned emittedElemSize = emitDataSecCur->dsType == dataSection::blockAbsoluteAddr ? TARGET_POINTER_SIZE : 4;
5320
5321 assert(emitDataSecCur->dsSize >= emittedElemSize * (index + 1));
5322
5323 ((BasicBlock**)(emitDataSecCur->dsCont))[index] = label;
5324}
5325
5326/*****************************************************************************
5327 *
5328 * We're done generating a data section.
5329 */
5330
5331void emitter::emitDataGenEnd()
5332{
5333
5334#ifdef DEBUG
5335 assert(emitDataSecCur);
5336 emitDataSecCur = nullptr;
5337#endif
5338}
5339
5340/********************************************************************************
5341 * Generates a data section constant
5342 *
5343 * Parameters:
5344 * cnsAddr - memory location containing constant value
5345 * cnsSize - size of constant in bytes
5346 * dblAlign - whether to double align the data section constant
5347 *
5348 * Returns constant number as offset into data section.
5349 */
5350UNATIVE_OFFSET emitter::emitDataConst(const void* cnsAddr, unsigned cnsSize, bool dblAlign)
5351{
5352 // When generating SMALL_CODE, we don't bother with dblAlign
5353 if (dblAlign && (emitComp->compCodeOpt() == Compiler::SMALL_CODE))
5354 {
5355 dblAlign = false;
5356 }
5357
5358 UNATIVE_OFFSET cnum = emitDataGenBeg(cnsSize, dblAlign, false);
5359 emitDataGenData(0, cnsAddr, cnsSize);
5360 emitDataGenEnd();
5361
5362 return cnum;
5363}
5364
5365//------------------------------------------------------------------------
5366// emitAnyConst: Create a data section constant of arbitrary size.
5367//
5368// Arguments:
5369// cnsAddr - pointer to the data to be placed in the data section
5370// cnsSize - size of the data
5371// dblAlign - whether to align the data section to an 8 byte boundary
5372//
5373// Return Value:
5374// A field handle representing the data offset to access the constant.
5375//
5376CORINFO_FIELD_HANDLE emitter::emitAnyConst(const void* cnsAddr, unsigned cnsSize, bool dblAlign)
5377{
5378 UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
5379 return emitComp->eeFindJitDataOffs(cnum);
5380}
5381
5382//------------------------------------------------------------------------
5383// emitFltOrDblConst: Create a float or double data section constant.
5384//
5385// Arguments:
5386// constValue - constant value
5387// attr - constant size
5388//
5389// Return Value:
5390// A field handle representing the data offset to access the constant.
5391//
5392// Notes:
5393// If attr is EA_4BYTE then the double value is converted to a float value.
5394// If attr is EA_8BYTE then 8 byte alignment is automatically requested.
5395//
5396CORINFO_FIELD_HANDLE emitter::emitFltOrDblConst(double constValue, emitAttr attr)
5397{
5398 assert((attr == EA_4BYTE) || (attr == EA_8BYTE));
5399
5400 void* cnsAddr;
5401 float f;
5402 bool dblAlign;
5403
5404 if (attr == EA_4BYTE)
5405 {
5406 f = forceCastToFloat(constValue);
5407 cnsAddr = &f;
5408 dblAlign = false;
5409 }
5410 else
5411 {
5412 cnsAddr = &constValue;
5413 dblAlign = true;
5414 }
5415
5416 // Access to inline data is 'abstracted' by a special type of static member
5417 // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
5418 // to constant data, not a real static field.
5419
5420 UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
5421 UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
5422 return emitComp->eeFindJitDataOffs(cnum);
5423}
5424
5425/*****************************************************************************
5426 *
5427 * Output the given data section at the specified address.
5428 */
5429
5430void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst)
5431{
5432#ifdef DEBUG
5433 if (EMITVERBOSE)
5434 {
5435 printf("\nEmitting data sections: %u total bytes\n", sec->dsdOffs);
5436 }
5437
5438 unsigned secNum = 0;
5439#endif
5440
5441 assert(dst);
5442 assert(sec->dsdOffs);
5443 assert(sec->dsdList);
5444
5445 /* Walk and emit the contents of all the data blocks */
5446
5447 dataSection* dsc;
5448
5449 for (dsc = sec->dsdList; dsc; dsc = dsc->dsNext)
5450 {
5451 size_t dscSize = dsc->dsSize;
5452
5453 // absolute label table
5454 if (dsc->dsType == dataSection::blockAbsoluteAddr)
5455 {
5456 JITDUMP(" section %u, size %u, block absolute addr\n", secNum++, dscSize);
5457
5458 assert(dscSize && dscSize % TARGET_POINTER_SIZE == 0);
5459 size_t numElems = dscSize / TARGET_POINTER_SIZE;
5460 target_size_t* bDst = (target_size_t*)dst;
5461 for (unsigned i = 0; i < numElems; i++)
5462 {
5463 BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i];
5464
5465 // Convert the BasicBlock* value to an IG address
5466 insGroup* lab = (insGroup*)emitCodeGetCookie(block);
5467
5468 // Append the appropriate address to the destination
5469 BYTE* target = emitOffsetToPtr(lab->igOffs);
5470
5471#ifdef _TARGET_ARM_
5472 target = (BYTE*)((size_t)target | 1); // Or in thumb bit
5473#endif
5474 bDst[i] = (target_size_t)target;
5475 if (emitComp->opts.compReloc)
5476 {
5477 emitRecordRelocation(&(bDst[i]), target, IMAGE_REL_BASED_HIGHLOW);
5478 }
5479
5480 JITDUMP(" " FMT_BB ": 0x%p\n", block->bbNum, bDst[i]);
5481 }
5482 }
5483 // relative label table
5484 else if (dsc->dsType == dataSection::blockRelative32)
5485 {
5486 JITDUMP(" section %u, size %u, block relative addr\n", secNum++, dscSize);
5487
5488 unsigned elemSize = 4;
5489 size_t numElems = dscSize / 4;
5490 unsigned* uDst = (unsigned*)dst;
5491 insGroup* labFirst = (insGroup*)emitCodeGetCookie(emitComp->fgFirstBB);
5492
5493 for (unsigned i = 0; i < numElems; i++)
5494 {
5495 BasicBlock* block = ((BasicBlock**)dsc->dsCont)[i];
5496
5497 // Convert the BasicBlock* value to an IG address
5498 insGroup* lab = (insGroup*)emitCodeGetCookie(block);
5499
5500 assert(FitsIn<uint32_t>(lab->igOffs - labFirst->igOffs));
5501 uDst[i] = lab->igOffs - labFirst->igOffs;
5502
5503 JITDUMP(" " FMT_BB ": 0x%x\n", block->bbNum, uDst[i]);
5504 }
5505 }
5506 else
5507 {
5508 JITDUMP(" section %u, size %u, raw data\n", secNum++, dscSize);
5509
5510 // Simple binary data: copy the bytes to the target
5511 assert(dsc->dsType == dataSection::data);
5512
5513 memcpy(dst, dsc->dsCont, dscSize);
5514
5515#ifdef DEBUG
5516 if (EMITVERBOSE)
5517 {
5518 printf(" ");
5519 for (size_t i = 0; i < dscSize; i++)
5520 {
5521 printf("%02x ", dsc->dsCont[i]);
5522 if ((((i + 1) % 16) == 0) && (i + 1 != dscSize))
5523 {
5524 printf("\n ");
5525 }
5526 }
5527 printf("\n");
5528 }
5529#endif // DEBUG
5530 }
5531 dst += dscSize;
5532 }
5533}
5534
5535/*****************************************************************************/
5536/*****************************************************************************
5537 *
5538 * Record the fact that the given variable now contains a live GC ref.
5539 */
5540
5541void emitter::emitGCvarLiveSet(int offs, GCtype gcType, BYTE* addr, ssize_t disp)
5542{
5543 assert(emitIssuing);
5544
5545 varPtrDsc* desc;
5546
5547 assert((abs(offs) % TARGET_POINTER_SIZE) == 0);
5548 assert(needsGC(gcType));
5549
5550 /* Compute the index into the GC frame table if the caller didn't do it */
5551
5552 if (disp == -1)
5553 {
5554 disp = (offs - emitGCrFrameOffsMin) / TARGET_POINTER_SIZE;
5555 }
5556
5557 assert((size_t)disp < emitGCrFrameOffsCnt);
5558
5559 /* Allocate a lifetime record */
5560
5561 desc = new (emitComp, CMK_GC) varPtrDsc;
5562
5563 desc->vpdBegOfs = emitCurCodeOffs(addr);
5564#ifdef DEBUG
5565 desc->vpdEndOfs = 0xFACEDEAD;
5566#endif
5567
5568 desc->vpdVarNum = offs;
5569
5570 desc->vpdNext = nullptr;
5571
5572#if !defined(JIT32_GCENCODER) || !defined(WIN64EXCEPTIONS)
5573 /* the lower 2 bits encode props about the stk ptr */
5574
5575 if (offs == emitSyncThisObjOffs)
5576 {
5577 desc->vpdVarNum |= this_OFFSET_FLAG;
5578 }
5579#endif
5580
5581 if (gcType == GCT_BYREF)
5582 {
5583 desc->vpdVarNum |= byref_OFFSET_FLAG;
5584 }
5585
5586 /* Append the new entry to the end of the list */
5587 if (codeGen->gcInfo.gcVarPtrLast == nullptr)
5588 {
5589 assert(codeGen->gcInfo.gcVarPtrList == nullptr);
5590 codeGen->gcInfo.gcVarPtrList = codeGen->gcInfo.gcVarPtrLast = desc;
5591 }
5592 else
5593 {
5594 assert(codeGen->gcInfo.gcVarPtrList != nullptr);
5595 codeGen->gcInfo.gcVarPtrLast->vpdNext = desc;
5596 codeGen->gcInfo.gcVarPtrLast = desc;
5597 }
5598
5599 /* Record the variable descriptor in the table */
5600
5601 assert(emitGCrFrameLiveTab[disp] == nullptr);
5602 emitGCrFrameLiveTab[disp] = desc;
5603
5604#ifdef DEBUG
5605 if (EMITVERBOSE)
5606 {
5607 printf("[%08X] %s var born at [%s", dspPtr(desc), GCtypeStr(gcType), emitGetFrameReg());
5608
5609 if (offs < 0)
5610 {
5611 printf("-%02XH", -offs);
5612 }
5613 else if (offs > 0)
5614 {
5615 printf("+%02XH", +offs);
5616 }
5617
5618 printf("]\n");
5619 }
5620#endif
5621
5622 /* The "global" live GC variable mask is no longer up-to-date */
5623
5624 emitThisGCrefVset = false;
5625}
5626
5627/*****************************************************************************
5628 *
5629 * Record the fact that the given variable no longer contains a live GC ref.
5630 */
5631
5632void emitter::emitGCvarDeadSet(int offs, BYTE* addr, ssize_t disp)
5633{
5634 assert(emitIssuing);
5635
5636 varPtrDsc* desc;
5637
5638 assert(abs(offs) % sizeof(int) == 0);
5639
5640 /* Compute the index into the GC frame table if the caller didn't do it */
5641
5642 if (disp == -1)
5643 {
5644 disp = (offs - emitGCrFrameOffsMin) / TARGET_POINTER_SIZE;
5645 }
5646
5647 assert((unsigned)disp < emitGCrFrameOffsCnt);
5648
5649 /* Get hold of the lifetime descriptor and clear the entry */
5650
5651 desc = emitGCrFrameLiveTab[disp];
5652 emitGCrFrameLiveTab[disp] = nullptr;
5653
5654 assert(desc);
5655 assert((desc->vpdVarNum & ~OFFSET_MASK) == (unsigned)offs);
5656
5657 /* Record the death code offset */
5658
5659 assert(desc->vpdEndOfs == 0xFACEDEAD);
5660 desc->vpdEndOfs = emitCurCodeOffs(addr);
5661
5662#ifdef DEBUG
5663 if (EMITVERBOSE)
5664 {
5665 GCtype gcType = (desc->vpdVarNum & byref_OFFSET_FLAG) ? GCT_BYREF : GCT_GCREF;
5666#if !defined(JIT32_GCENCODER) || !defined(WIN64EXCEPTIONS)
5667 bool isThis = (desc->vpdVarNum & this_OFFSET_FLAG) != 0;
5668
5669 printf("[%08X] %s%s var died at [%s", dspPtr(desc), GCtypeStr(gcType), isThis ? "this-ptr" : "",
5670 emitGetFrameReg());
5671#else
5672 bool isPinned = (desc->vpdVarNum & pinned_OFFSET_FLAG) != 0;
5673
5674 printf("[%08X] %s%s var died at [%s", dspPtr(desc), GCtypeStr(gcType), isPinned ? "pinned" : "",
5675 emitGetFrameReg());
5676#endif
5677
5678 if (offs < 0)
5679 {
5680 printf("-%02XH", -offs);
5681 }
5682 else if (offs > 0)
5683 {
5684 printf("+%02XH", +offs);
5685 }
5686
5687 printf("]\n");
5688 }
5689#endif
5690
5691 /* The "global" live GC variable mask is no longer up-to-date */
5692
5693 emitThisGCrefVset = false;
5694}
5695
5696/*****************************************************************************
5697 *
5698 * Record a new set of live GC ref variables.
5699 */
5700
5701void emitter::emitUpdateLiveGCvars(VARSET_VALARG_TP vars, BYTE* addr)
5702{
5703 assert(emitIssuing);
5704
5705 // Don't track GC changes in epilogs
5706 if (emitIGisInEpilog(emitCurIG))
5707 {
5708 return;
5709 }
5710
5711 /* Is the current set accurate and unchanged? */
5712
5713 if (emitThisGCrefVset && VarSetOps::Equal(emitComp, emitThisGCrefVars, vars))
5714 {
5715 return;
5716 }
5717
5718#ifdef DEBUG
5719 if (EMIT_GC_VERBOSE)
5720 {
5721 printf("New GC ref live vars=%s ", VarSetOps::ToString(emitComp, vars));
5722 dumpConvertedVarSet(emitComp, vars);
5723 printf("\n");
5724 }
5725#endif
5726
5727 VarSetOps::Assign(emitComp, emitThisGCrefVars, vars);
5728
5729 /* Are there any GC ref variables on the stack? */
5730
5731 if (emitGCrFrameOffsCnt)
5732 {
5733 int* tab;
5734 unsigned cnt = emitTrkVarCnt;
5735 unsigned num;
5736
5737 /* Test all the tracked variable bits in the mask */
5738
5739 for (num = 0, tab = emitGCrFrameOffsTab; num < cnt; num++, tab++)
5740 {
5741 int val = *tab;
5742
5743 if (val != -1)
5744 {
5745 // byref_OFFSET_FLAG and this_OFFSET_FLAG are set
5746 // in the table-offsets for byrefs and this-ptr
5747
5748 int offs = val & ~OFFSET_MASK;
5749
5750 // printf("var #%2u at %3d is now %s\n", num, offs, (vars & 1) ? "live" : "dead");
5751
5752 if (VarSetOps::IsMember(emitComp, vars, num))
5753 {
5754 GCtype gcType = (val & byref_OFFSET_FLAG) ? GCT_BYREF : GCT_GCREF;
5755 emitGCvarLiveUpd(offs, INT_MAX, gcType, addr);
5756 }
5757 else
5758 {
5759 emitGCvarDeadUpd(offs, addr);
5760 }
5761 }
5762 }
5763 }
5764
5765 emitThisGCrefVset = true;
5766}
5767
5768/*****************************************************************************
5769 *
5770 * Record a call location for GC purposes (we know that this is a method that
5771 * will not be fully interruptible).
5772 */
5773
5774void emitter::emitRecordGCcall(BYTE* codePos, unsigned char callInstrSize)
5775{
5776 assert(emitIssuing);
5777 assert(!emitFullGCinfo);
5778
5779 unsigned offs = emitCurCodeOffs(codePos);
5780 unsigned regs = (emitThisGCrefRegs | emitThisByrefRegs) & ~RBM_INTRET;
5781 callDsc* call;
5782
5783#ifdef JIT32_GCENCODER
5784 // The JIT32 GCInfo encoder allows us to (as the comment previously here said):
5785 // "Bail if this is a totally boring call", but the GCInfoEncoder/Decoder interface
5786 // requires a definition for every call site, so we skip these "early outs" when we're
5787 // using the general encoder.
5788 if (regs == 0)
5789 {
5790#if EMIT_TRACK_STACK_DEPTH
5791 if (emitCurStackLvl == 0)
5792 return;
5793#endif
5794 /* Nope, only interesting calls get recorded */
5795
5796 if (emitSimpleStkUsed)
5797 {
5798 if (!u1.emitSimpleStkMask)
5799 return;
5800 }
5801 else
5802 {
5803 if (u2.emitGcArgTrackCnt == 0)
5804 return;
5805 }
5806 }
5807#endif // JIT32_GCENCODER
5808
5809#ifdef DEBUG
5810
5811 if (EMIT_GC_VERBOSE)
5812 {
5813 printf("; Call at %04X [stk=%u], GCvars=", offs - callInstrSize, emitCurStackLvl);
5814 emitDispVarSet();
5815 printf(", gcrefRegs=");
5816 printRegMaskInt(emitThisGCrefRegs);
5817 emitDispRegSet(emitThisGCrefRegs);
5818 // printRegMaskInt(emitThisGCrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5819 // emitDispRegSet (emitThisGCrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5820 printf(", byrefRegs=");
5821 printRegMaskInt(emitThisByrefRegs);
5822 emitDispRegSet(emitThisByrefRegs);
5823 // printRegMaskInt(emitThisByrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5824 // emitDispRegSet (emitThisByrefRegs & ~RBM_INTRET & RBM_CALLEE_SAVED); // only display callee-saved
5825 printf("\n");
5826 }
5827
5828#endif
5829
5830 /* Allocate a 'call site' descriptor and start filling it in */
5831
5832 call = new (emitComp, CMK_GC) callDsc;
5833
5834 call->cdBlock = nullptr;
5835 call->cdOffs = offs;
5836#ifndef JIT32_GCENCODER
5837 call->cdCallInstrSize = callInstrSize;
5838#endif
5839 call->cdNext = nullptr;
5840
5841 call->cdGCrefRegs = (regMaskSmall)emitThisGCrefRegs;
5842 call->cdByrefRegs = (regMaskSmall)emitThisByrefRegs;
5843
5844#if EMIT_TRACK_STACK_DEPTH
5845#ifndef UNIX_AMD64_ABI
5846 noway_assert(FitsIn<USHORT>(emitCurStackLvl / ((unsigned)sizeof(unsigned))));
5847#endif // UNIX_AMD64_ABI
5848#endif
5849
5850 // Append the call descriptor to the list */
5851 if (codeGen->gcInfo.gcCallDescLast == nullptr)
5852 {
5853 assert(codeGen->gcInfo.gcCallDescList == nullptr);
5854 codeGen->gcInfo.gcCallDescList = codeGen->gcInfo.gcCallDescLast = call;
5855 }
5856 else
5857 {
5858 assert(codeGen->gcInfo.gcCallDescList != nullptr);
5859 codeGen->gcInfo.gcCallDescLast->cdNext = call;
5860 codeGen->gcInfo.gcCallDescLast = call;
5861 }
5862
5863 /* Record the current "pending" argument list */
5864
5865 if (emitSimpleStkUsed)
5866 {
5867 /* The biggest call is less than MAX_SIMPLE_STK_DEPTH. So use
5868 small format */
5869
5870 call->u1.cdArgMask = u1.emitSimpleStkMask;
5871 call->u1.cdByrefArgMask = u1.emitSimpleByrefStkMask;
5872 call->cdArgCnt = 0;
5873 }
5874 else
5875 {
5876 /* The current call has too many arguments, so we need to report the
5877 offsets of each individual GC arg. */
5878
5879 call->cdArgCnt = u2.emitGcArgTrackCnt;
5880 if (call->cdArgCnt == 0)
5881 {
5882 call->u1.cdArgMask = call->u1.cdByrefArgMask = 0;
5883 return;
5884 }
5885
5886 call->cdArgTable = new (emitComp, CMK_GC) unsigned[u2.emitGcArgTrackCnt];
5887
5888 unsigned gcArgs = 0;
5889 unsigned stkLvl = emitCurStackLvl / sizeof(int);
5890
5891 for (unsigned i = 0; i < stkLvl; i++)
5892 {
5893 GCtype gcType = (GCtype)u2.emitArgTrackTab[stkLvl - i - 1];
5894
5895 if (needsGC(gcType))
5896 {
5897 call->cdArgTable[gcArgs] = i * TARGET_POINTER_SIZE;
5898
5899 if (gcType == GCT_BYREF)
5900 {
5901 call->cdArgTable[gcArgs] |= byref_OFFSET_FLAG;
5902 }
5903
5904 gcArgs++;
5905 }
5906 }
5907
5908 assert(gcArgs == u2.emitGcArgTrackCnt);
5909 }
5910}
5911
5912/*****************************************************************************
5913 *
5914 * Record a new set of live GC ref registers.
5915 */
5916
5917void emitter::emitUpdateLiveGCregs(GCtype gcType, regMaskTP regs, BYTE* addr)
5918{
5919 assert(emitIssuing);
5920
5921 // Don't track GC changes in epilogs
5922 if (emitIGisInEpilog(emitCurIG))
5923 {
5924 return;
5925 }
5926
5927 regMaskTP life;
5928 regMaskTP dead;
5929 regMaskTP chg;
5930
5931#ifdef DEBUG
5932 if (EMIT_GC_VERBOSE)
5933 {
5934 printf("New %sReg live regs=", GCtypeStr(gcType));
5935 printRegMaskInt(regs);
5936 emitDispRegSet(regs);
5937 printf("\n");
5938 }
5939#endif
5940
5941 assert(needsGC(gcType));
5942
5943 regMaskTP& emitThisXXrefRegs = (gcType == GCT_GCREF) ? emitThisGCrefRegs : emitThisByrefRegs;
5944 regMaskTP& emitThisYYrefRegs = (gcType == GCT_GCREF) ? emitThisByrefRegs : emitThisGCrefRegs;
5945 assert(emitThisXXrefRegs != regs);
5946
5947 if (emitFullGCinfo)
5948 {
5949 /* Figure out which GC registers are becoming live/dead at this point */
5950
5951 dead = (emitThisXXrefRegs & ~regs);
5952 life = (~emitThisXXrefRegs & regs);
5953
5954 /* Can't simultaneously become live and dead at the same time */
5955
5956 assert((dead | life) != 0);
5957 assert((dead & life) == 0);
5958
5959 /* Compute the 'changing state' mask */
5960
5961 chg = (dead | life);
5962
5963 do
5964 {
5965 regMaskTP bit = genFindLowestBit(chg);
5966 regNumber reg = genRegNumFromMask(bit);
5967
5968 if (life & bit)
5969 {
5970 emitGCregLiveUpd(gcType, reg, addr);
5971 }
5972 else
5973 {
5974 emitGCregDeadUpd(reg, addr);
5975 }
5976
5977 chg -= bit;
5978 } while (chg);
5979
5980 assert(emitThisXXrefRegs == regs);
5981 }
5982 else
5983 {
5984 emitThisYYrefRegs &= ~regs; // Kill the regs from the other GC type (if live)
5985 emitThisXXrefRegs = regs; // Mark them as live in the requested GC type
5986 }
5987
5988 // The 2 GC reg masks can't be overlapping
5989
5990 assert((emitThisGCrefRegs & emitThisByrefRegs) == 0);
5991}
5992
5993/*****************************************************************************
5994 *
5995 * Record the fact that the given register now contains a live GC ref.
5996 */
5997
5998void emitter::emitGCregLiveSet(GCtype gcType, regMaskTP regMask, BYTE* addr, bool isThis)
5999{
6000 assert(emitIssuing);
6001 assert(needsGC(gcType));
6002
6003 regPtrDsc* regPtrNext;
6004
6005 assert(!isThis || emitComp->lvaKeepAliveAndReportThis());
6006 // assert(emitFullyInt || isThis);
6007 assert(emitFullGCinfo);
6008
6009 assert(((emitThisGCrefRegs | emitThisByrefRegs) & regMask) == 0);
6010
6011 /* Allocate a new regptr entry and fill it in */
6012
6013 regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6014 regPtrNext->rpdGCtype = gcType;
6015
6016 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6017 regPtrNext->rpdArg = FALSE;
6018 regPtrNext->rpdCall = FALSE;
6019 regPtrNext->rpdIsThis = isThis;
6020 regPtrNext->rpdCompiler.rpdAdd = (regMaskSmall)regMask;
6021 regPtrNext->rpdCompiler.rpdDel = 0;
6022}
6023
6024/*****************************************************************************
6025 *
6026 * Record the fact that the given register no longer contains a live GC ref.
6027 */
6028
6029void emitter::emitGCregDeadSet(GCtype gcType, regMaskTP regMask, BYTE* addr)
6030{
6031 assert(emitIssuing);
6032 assert(needsGC(gcType));
6033
6034 regPtrDsc* regPtrNext;
6035
6036 // assert(emitFullyInt);
6037 assert(emitFullGCinfo);
6038
6039 assert(((emitThisGCrefRegs | emitThisByrefRegs) & regMask) != 0);
6040
6041 /* Allocate a new regptr entry and fill it in */
6042
6043 regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6044 regPtrNext->rpdGCtype = gcType;
6045
6046 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6047 regPtrNext->rpdCall = FALSE;
6048 regPtrNext->rpdIsThis = FALSE;
6049 regPtrNext->rpdArg = FALSE;
6050 regPtrNext->rpdCompiler.rpdAdd = 0;
6051 regPtrNext->rpdCompiler.rpdDel = (regMaskSmall)regMask;
6052}
6053
6054/*****************************************************************************
6055 *
6056 * Emit an 8-bit integer as code.
6057 */
6058
6059unsigned char emitter::emitOutputByte(BYTE* dst, ssize_t val)
6060{
6061 *castto(dst, unsigned char*) = (unsigned char)val;
6062
6063#ifdef DEBUG
6064 if (emitComp->opts.dspEmit)
6065 {
6066 printf("; emit_byte 0%02XH\n", val & 0xFF);
6067 }
6068#ifdef _TARGET_AMD64_
6069 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6070 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6071#endif // _TARGET_AMD64_
6072#endif
6073
6074 return sizeof(unsigned char);
6075}
6076
6077/*****************************************************************************
6078 *
6079 * Emit a 16-bit integer as code.
6080 */
6081
6082unsigned char emitter::emitOutputWord(BYTE* dst, ssize_t val)
6083{
6084 MISALIGNED_WR_I2(dst, (short)val);
6085
6086#ifdef DEBUG
6087 if (emitComp->opts.dspEmit)
6088 {
6089 printf("; emit_word 0%02XH,0%02XH\n", (val & 0xFF), (val >> 8) & 0xFF);
6090 }
6091#ifdef _TARGET_AMD64_
6092 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6093 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6094#endif // _TARGET_AMD64_
6095#endif
6096
6097 return sizeof(short);
6098}
6099
6100/*****************************************************************************
6101 *
6102 * Emit a 32-bit integer as code.
6103 */
6104
6105unsigned char emitter::emitOutputLong(BYTE* dst, ssize_t val)
6106{
6107 MISALIGNED_WR_I4(dst, (int)val);
6108
6109#ifdef DEBUG
6110 if (emitComp->opts.dspEmit)
6111 {
6112 printf("; emit_long 0%08XH\n", (int)val);
6113 }
6114#ifdef _TARGET_AMD64_
6115 // if we're emitting code bytes, ensure that we've already emitted the rex prefix!
6116 assert(((val & 0xFF00000000LL) == 0) || ((val & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL));
6117#endif // _TARGET_AMD64_
6118#endif
6119
6120 return sizeof(int);
6121}
6122
6123/*****************************************************************************
6124 *
6125 * Emit a pointer-sized integer as code.
6126 */
6127
6128unsigned char emitter::emitOutputSizeT(BYTE* dst, ssize_t val)
6129{
6130 MISALIGNED_WR_ST(dst, val);
6131
6132#ifdef DEBUG
6133 if (emitComp->opts.dspEmit)
6134 {
6135#ifdef _TARGET_AMD64_
6136 printf("; emit_size_t 0%016llXH\n", val);
6137#else // _TARGET_AMD64_
6138 printf("; emit_size_t 0%08XH\n", val);
6139#endif // _TARGET_AMD64_
6140 }
6141#endif // DEBUG
6142
6143 return TARGET_POINTER_SIZE;
6144}
6145
6146//------------------------------------------------------------------------
6147// Wrappers to emitOutputByte, emitOutputWord, emitOutputLong, emitOutputSizeT
6148// that take unsigned __int64 or size_t type instead of ssize_t. Used on RyuJIT/x86.
6149//
6150// Arguments:
6151// dst - passed through
6152// val - passed through
6153//
6154// Return Value:
6155// Same as wrapped function.
6156//
6157
6158#if defined(_TARGET_X86_)
6159unsigned char emitter::emitOutputByte(BYTE* dst, size_t val)
6160{
6161 return emitOutputByte(dst, (ssize_t)val);
6162}
6163
6164unsigned char emitter::emitOutputWord(BYTE* dst, size_t val)
6165{
6166 return emitOutputWord(dst, (ssize_t)val);
6167}
6168
6169unsigned char emitter::emitOutputLong(BYTE* dst, size_t val)
6170{
6171 return emitOutputLong(dst, (ssize_t)val);
6172}
6173
6174unsigned char emitter::emitOutputSizeT(BYTE* dst, size_t val)
6175{
6176 return emitOutputSizeT(dst, (ssize_t)val);
6177}
6178
6179unsigned char emitter::emitOutputByte(BYTE* dst, unsigned __int64 val)
6180{
6181 return emitOutputByte(dst, (ssize_t)val);
6182}
6183
6184unsigned char emitter::emitOutputWord(BYTE* dst, unsigned __int64 val)
6185{
6186 return emitOutputWord(dst, (ssize_t)val);
6187}
6188
6189unsigned char emitter::emitOutputLong(BYTE* dst, unsigned __int64 val)
6190{
6191 return emitOutputLong(dst, (ssize_t)val);
6192}
6193
6194unsigned char emitter::emitOutputSizeT(BYTE* dst, unsigned __int64 val)
6195{
6196 return emitOutputSizeT(dst, (ssize_t)val);
6197}
6198#endif // defined(_TARGET_X86_)
6199
6200/*****************************************************************************
6201 *
6202 * Given a block cookie and a code position, return the actual code offset;
6203 * this can only be called at the end of code generation.
6204 */
6205
6206UNATIVE_OFFSET emitter::emitCodeOffset(void* blockPtr, unsigned codePos)
6207{
6208 insGroup* ig;
6209
6210 UNATIVE_OFFSET of;
6211 unsigned no = emitGetInsNumFromCodePos(codePos);
6212
6213 /* Make sure we weren't passed some kind of a garbage thing */
6214
6215 ig = (insGroup*)blockPtr;
6216#ifdef DEBUG
6217 assert(ig && ig->igSelf == ig);
6218#endif
6219
6220 /* The first and last offsets are always easy */
6221
6222 if (no == 0)
6223 {
6224 of = 0;
6225 }
6226 else if (no == ig->igInsCnt)
6227 {
6228 of = ig->igSize;
6229 }
6230 else if (ig->igFlags & IGF_UPD_ISZ)
6231 {
6232 /*
6233 Some instruction sizes have changed, so we'll have to figure
6234 out the instruction offset "the hard way".
6235 */
6236
6237 of = emitFindOffset(ig, no);
6238 }
6239 else
6240 {
6241 /* All instructions correctly predicted, the offset stays the same */
6242
6243 of = emitGetInsOfsFromCodePos(codePos);
6244
6245 // printf("[IG=%02u;ID=%03u;OF=%04X] <= %08X\n", ig->igNum, emitGetInsNumFromCodePos(codePos), of, codePos);
6246
6247 /* Make sure the offset estimate is accurate */
6248
6249 assert(of == emitFindOffset(ig, emitGetInsNumFromCodePos(codePos)));
6250 }
6251
6252 return ig->igOffs + of;
6253}
6254
6255/*****************************************************************************
6256 *
6257 * Record the fact that the given register now contains a live GC ref.
6258 */
6259
6260void emitter::emitGCregLiveUpd(GCtype gcType, regNumber reg, BYTE* addr)
6261{
6262 assert(emitIssuing);
6263
6264 // Don't track GC changes in epilogs
6265 if (emitIGisInEpilog(emitCurIG))
6266 {
6267 return;
6268 }
6269
6270 assert(needsGC(gcType));
6271
6272 regMaskTP regMask = genRegMask(reg);
6273
6274 regMaskTP& emitThisXXrefRegs = (gcType == GCT_GCREF) ? emitThisGCrefRegs : emitThisByrefRegs;
6275 regMaskTP& emitThisYYrefRegs = (gcType == GCT_GCREF) ? emitThisByrefRegs : emitThisGCrefRegs;
6276
6277 if ((emitThisXXrefRegs & regMask) == 0)
6278 {
6279 // If the register was holding the other GC type, that type should
6280 // go dead now
6281
6282 if (emitThisYYrefRegs & regMask)
6283 {
6284 emitGCregDeadUpd(reg, addr);
6285 }
6286
6287 // For synchronized methods, "this" is always alive and in the same register.
6288 // However, if we generate any code after the epilog block (where "this"
6289 // goes dead), "this" will come alive again. We need to notice that.
6290 // Note that we only expect isThis to be true at an insGroup boundary.
6291
6292 bool isThis = (reg == emitSyncThisObjReg) ? true : false;
6293
6294 if (emitFullGCinfo)
6295 {
6296 emitGCregLiveSet(gcType, regMask, addr, isThis);
6297 }
6298
6299 emitThisXXrefRegs |= regMask;
6300
6301#ifdef DEBUG
6302 if (EMIT_GC_VERBOSE)
6303 {
6304 printf("%sReg +[%s]\n", GCtypeStr(gcType), emitRegName(reg));
6305 }
6306#endif
6307 }
6308
6309 // The 2 GC reg masks can't be overlapping
6310
6311 assert((emitThisGCrefRegs & emitThisByrefRegs) == 0);
6312}
6313
6314/*****************************************************************************
6315 *
6316 * Record the fact that the given set of registers no longer contain live GC refs.
6317 */
6318
6319void emitter::emitGCregDeadUpdMask(regMaskTP regs, BYTE* addr)
6320{
6321 assert(emitIssuing);
6322
6323 // Don't track GC changes in epilogs
6324 if (emitIGisInEpilog(emitCurIG))
6325 {
6326 return;
6327 }
6328
6329 // First, handle the gcref regs going dead
6330
6331 regMaskTP gcrefRegs = emitThisGCrefRegs & regs;
6332
6333 // "this" can never go dead in synchronized methods, except in the epilog
6334 // after the call to CORINFO_HELP_MON_EXIT.
6335 assert(emitSyncThisObjReg == REG_NA || (genRegMask(emitSyncThisObjReg) & regs) == 0);
6336
6337 if (gcrefRegs)
6338 {
6339 assert((emitThisByrefRegs & gcrefRegs) == 0);
6340
6341 if (emitFullGCinfo)
6342 {
6343 emitGCregDeadSet(GCT_GCREF, gcrefRegs, addr);
6344 }
6345
6346 emitThisGCrefRegs &= ~gcrefRegs;
6347
6348#ifdef DEBUG
6349 if (EMIT_GC_VERBOSE)
6350 {
6351 printf("gcrReg ");
6352 printRegMaskInt(gcrefRegs);
6353 printf(" -");
6354 emitDispRegSet(gcrefRegs);
6355 printf("\n");
6356 }
6357#endif
6358 }
6359
6360 // Second, handle the byref regs going dead
6361
6362 regMaskTP byrefRegs = emitThisByrefRegs & regs;
6363
6364 if (byrefRegs)
6365 {
6366 assert((emitThisGCrefRegs & byrefRegs) == 0);
6367
6368 if (emitFullGCinfo)
6369 {
6370 emitGCregDeadSet(GCT_BYREF, byrefRegs, addr);
6371 }
6372
6373 emitThisByrefRegs &= ~byrefRegs;
6374
6375#ifdef DEBUG
6376 if (EMIT_GC_VERBOSE)
6377 {
6378 printf("byrReg ");
6379 printRegMaskInt(byrefRegs);
6380 printf(" -");
6381 emitDispRegSet(byrefRegs);
6382 printf("\n");
6383 }
6384#endif
6385 }
6386}
6387
6388/*****************************************************************************
6389 *
6390 * Record the fact that the given register no longer contains a live GC ref.
6391 */
6392
6393void emitter::emitGCregDeadUpd(regNumber reg, BYTE* addr)
6394{
6395 assert(emitIssuing);
6396
6397 // Don't track GC changes in epilogs
6398 if (emitIGisInEpilog(emitCurIG))
6399 {
6400 return;
6401 }
6402
6403 regMaskTP regMask = genRegMask(reg);
6404
6405 if ((emitThisGCrefRegs & regMask) != 0)
6406 {
6407 assert((emitThisByrefRegs & regMask) == 0);
6408
6409 if (emitFullGCinfo)
6410 {
6411 emitGCregDeadSet(GCT_GCREF, regMask, addr);
6412 }
6413
6414 emitThisGCrefRegs &= ~regMask;
6415
6416#ifdef DEBUG
6417 if (EMIT_GC_VERBOSE)
6418 {
6419 printf("%s -[%s]\n", "gcrReg", emitRegName(reg));
6420 }
6421#endif
6422 }
6423 else if ((emitThisByrefRegs & regMask) != 0)
6424 {
6425 if (emitFullGCinfo)
6426 {
6427 emitGCregDeadSet(GCT_BYREF, regMask, addr);
6428 }
6429
6430 emitThisByrefRegs &= ~regMask;
6431
6432#ifdef DEBUG
6433 if (EMIT_GC_VERBOSE)
6434 {
6435 printf("%s -[%s]\n", "byrReg", emitRegName(reg));
6436 }
6437#endif
6438 }
6439}
6440
6441/*****************************************************************************
6442 *
6443 * Record the fact that the given variable now contains a live GC ref.
6444 * varNum may be INT_MAX or negative (indicating a spill temp) only if
6445 * offs is guaranteed to be the offset of a tracked GC ref. Else we
6446 * need a valid value to check if the variable is tracked or not.
6447 */
6448
6449void emitter::emitGCvarLiveUpd(int offs, int varNum, GCtype gcType, BYTE* addr)
6450{
6451 assert(abs(offs) % sizeof(int) == 0);
6452 assert(needsGC(gcType));
6453
6454#if FEATURE_FIXED_OUT_ARGS
6455 if ((unsigned)varNum == emitComp->lvaOutgoingArgSpaceVar)
6456 {
6457 if (emitFullGCinfo)
6458 {
6459 /* Append an "arg push" entry to track a GC written to the
6460 outgoing argument space.
6461 Allocate a new ptr arg entry and fill it in */
6462
6463 regPtrDsc* regPtrNext = gcInfo->gcRegPtrAllocDsc();
6464 regPtrNext->rpdGCtype = gcType;
6465 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6466 regPtrNext->rpdArg = TRUE;
6467 regPtrNext->rpdCall = FALSE;
6468 noway_assert(FitsIn<unsigned short>(offs));
6469 regPtrNext->rpdPtrArg = (unsigned short)offs;
6470 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_PUSH;
6471 regPtrNext->rpdIsThis = FALSE;
6472
6473#ifdef DEBUG
6474 if (EMIT_GC_VERBOSE)
6475 {
6476 printf("[%04X] %s arg write\n", offs, GCtypeStr(gcType));
6477 }
6478#endif
6479 }
6480 }
6481 else
6482#endif // FEATURE_FIXED_OUT_ARGS
6483 {
6484 /* Is the frame offset within the "interesting" range? */
6485
6486 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
6487 {
6488 /* Normally all variables in this range must be tracked stack
6489 pointers. However, for EnC, we relax this condition. So we
6490 must check if this is not such a variable.
6491 Note that varNum might be negative, indicating a spill temp.
6492 */
6493
6494 if (varNum != INT_MAX)
6495 {
6496 bool isTracked = false;
6497 if (varNum >= 0)
6498 {
6499 // This is NOT a spill temp
6500 LclVarDsc* varDsc = &emitComp->lvaTable[varNum];
6501 isTracked = emitComp->lvaIsGCTracked(varDsc);
6502 }
6503 else
6504 {
6505 // Is it an untracked spill temp?
6506 isTracked = TRACK_GC_TEMP_LIFETIMES;
6507 }
6508 if (!isTracked)
6509 {
6510#if DOUBLE_ALIGN
6511 assert(!emitContTrkPtrLcls ||
6512 // EBP based variables in the double-aligned frames are indeed input arguments.
6513 // and we don't require them to fall into the "interesting" range.
6514 ((emitComp->rpFrameType == FT_DOUBLE_ALIGN_FRAME) && (varNum >= 0) &&
6515 (emitComp->lvaTable[varNum].lvFramePointerBased == 1)));
6516#else
6517 assert(!emitContTrkPtrLcls);
6518#endif
6519 return;
6520 }
6521 }
6522
6523 size_t disp;
6524
6525 /* Compute the index into the GC frame table */
6526
6527 disp = (offs - emitGCrFrameOffsMin) / TARGET_POINTER_SIZE;
6528 assert(disp < emitGCrFrameOffsCnt);
6529
6530 /* If the variable is currently dead, mark it as live */
6531
6532 if (emitGCrFrameLiveTab[disp] == nullptr)
6533 {
6534 emitGCvarLiveSet(offs, gcType, addr, disp);
6535 }
6536 }
6537 }
6538}
6539
6540/*****************************************************************************
6541 *
6542 * Record the fact that the given variable no longer contains a live GC ref.
6543 */
6544
6545void emitter::emitGCvarDeadUpd(int offs, BYTE* addr)
6546{
6547 assert(emitIssuing);
6548 assert(abs(offs) % sizeof(int) == 0);
6549
6550 /* Is the frame offset within the "interesting" range? */
6551
6552 if (offs >= emitGCrFrameOffsMin && offs < emitGCrFrameOffsMax)
6553 {
6554 size_t disp;
6555
6556 /* Compute the index into the GC frame table */
6557
6558 disp = (offs - emitGCrFrameOffsMin) / TARGET_POINTER_SIZE;
6559 assert(disp < emitGCrFrameOffsCnt);
6560
6561 /* If the variable is currently live, mark it as dead */
6562
6563 if (emitGCrFrameLiveTab[disp] != nullptr)
6564 {
6565 emitGCvarDeadSet(offs, addr, disp);
6566 }
6567 }
6568}
6569
6570/*****************************************************************************
6571 *
6572 * Allocate a new IG and link it in to the global list after the current IG
6573 */
6574
6575insGroup* emitter::emitAllocAndLinkIG()
6576{
6577 insGroup* ig = emitAllocIG();
6578
6579 assert(emitCurIG);
6580
6581 emitInsertIGAfter(emitCurIG, ig);
6582
6583 /* Propagate some IG flags from the current group to the new group */
6584
6585 ig->igFlags |= (emitCurIG->igFlags & IGF_PROPAGATE_MASK);
6586
6587 /* Set the new IG as the current IG */
6588
6589 emitCurIG = ig;
6590
6591 return ig;
6592}
6593
6594/*****************************************************************************
6595 *
6596 * Allocate an instruction group descriptor and assign it the next index.
6597 */
6598
6599insGroup* emitter::emitAllocIG()
6600{
6601 insGroup* ig;
6602
6603 /* Allocate a group descriptor */
6604
6605 size_t sz = sizeof(insGroup);
6606 ig = (insGroup*)emitGetMem(sz);
6607
6608#ifdef DEBUG
6609 ig->igSelf = ig;
6610#endif
6611
6612#if EMITTER_STATS
6613 emitTotalIGcnt += 1;
6614 emitTotalIGsize += sz;
6615 emitSizeMethod += sz;
6616#endif
6617
6618 /* Do basic initialization */
6619
6620 emitInitIG(ig);
6621
6622 return ig;
6623}
6624
6625/*****************************************************************************
6626 *
6627 * Initialize an instruction group
6628 */
6629
6630void emitter::emitInitIG(insGroup* ig)
6631{
6632 /* Assign the next available index to the instruction group */
6633
6634 ig->igNum = emitNxtIGnum;
6635
6636 emitNxtIGnum++;
6637
6638 /* Record the (estimated) code offset of the group */
6639
6640 ig->igOffs = emitCurCodeOffset;
6641 assert(IsCodeAligned(ig->igOffs));
6642
6643 /* Set the current function index */
6644
6645 ig->igFuncIdx = emitComp->compCurrFuncIdx;
6646
6647 ig->igFlags = 0;
6648
6649 /* Zero out some fields to avoid printing garbage in JitDumps. These
6650 really only need to be set in DEBUG, but do it in all cases to make
6651 sure we act the same in non-DEBUG builds.
6652 */
6653
6654 ig->igSize = 0;
6655 ig->igGCregs = RBM_NONE;
6656 ig->igInsCnt = 0;
6657}
6658
6659/*****************************************************************************
6660 *
6661 * Insert instruction group 'ig' after 'igInsertAfterIG'
6662 */
6663
6664void emitter::emitInsertIGAfter(insGroup* insertAfterIG, insGroup* ig)
6665{
6666 assert(emitIGlist);
6667 assert(emitIGlast);
6668
6669 ig->igNext = insertAfterIG->igNext;
6670 insertAfterIG->igNext = ig;
6671
6672 if (emitIGlast == insertAfterIG)
6673 {
6674 // If we are inserting at the end, then update the 'last' pointer
6675 emitIGlast = ig;
6676 }
6677}
6678
6679/*****************************************************************************
6680 *
6681 * Save the current IG and start a new one.
6682 */
6683
6684void emitter::emitNxtIG(bool emitAdd)
6685{
6686 /* Right now we don't allow multi-IG prologs */
6687
6688 assert(emitCurIG != emitPrologIG);
6689
6690 /* First save the current group */
6691
6692 emitSavIG(emitAdd);
6693
6694 /* Update the GC live sets for the group's start
6695 * Do it only if not an emitter added block */
6696
6697 if (!emitAdd)
6698 {
6699 VarSetOps::Assign(emitComp, emitInitGCrefVars, emitThisGCrefVars);
6700 emitInitGCrefRegs = emitThisGCrefRegs;
6701 emitInitByrefRegs = emitThisByrefRegs;
6702 }
6703
6704 /* Start generating the new group */
6705
6706 emitNewIG();
6707
6708 /* If this is an emitter added block, flag it */
6709
6710 if (emitAdd)
6711 {
6712 emitCurIG->igFlags |= IGF_EMIT_ADD;
6713 }
6714
6715 // We've created a new IG; no need to force another one.
6716 emitForceNewIG = false;
6717}
6718
6719/*****************************************************************************
6720 *
6721 * emitGetInsSC: Get the instruction's constant value.
6722 */
6723
6724target_ssize_t emitter::emitGetInsSC(instrDesc* id)
6725{
6726#ifdef _TARGET_ARM_ // should it be _TARGET_ARMARCH_? Why do we need this? Note that on ARM64 we store scaled immediates
6727 // for some formats
6728 if (id->idIsLclVar())
6729 {
6730 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
6731
6732 regNumber baseReg;
6733 int offs = id->idAddr()->iiaLclVar.lvaOffset();
6734#if defined(_TARGET_ARM_)
6735 int adr =
6736 emitComp->lvaFrameAddress(varNum, id->idIsLclFPBase(), &baseReg, offs, CodeGen::instIsFP(id->idIns()));
6737 int dsp = adr + offs;
6738 if ((id->idIns() == INS_sub) || (id->idIns() == INS_subw))
6739 dsp = -dsp;
6740#elif defined(_TARGET_ARM64_)
6741 // TODO-ARM64-Cleanup: this is currently unreachable. Do we need it?
6742 bool FPbased;
6743 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
6744 int dsp = adr + offs;
6745 if (id->idIns() == INS_sub)
6746 dsp = -dsp;
6747#endif
6748 return dsp;
6749 }
6750 else
6751#endif // _TARGET_ARM_
6752 if (id->idIsLargeCns())
6753 {
6754 return ((instrDescCns*)id)->idcCnsVal;
6755 }
6756 else
6757 {
6758 return id->idSmallCns();
6759 }
6760}
6761
6762#ifdef _TARGET_ARM_
6763
6764BYTE* emitter::emitGetInsRelocValue(instrDesc* id)
6765{
6766 return ((instrDescReloc*)id)->idrRelocVal;
6767}
6768
6769#endif // _TARGET_ARM_
6770
6771/*****************************************************************************/
6772#if EMIT_TRACK_STACK_DEPTH
6773/*****************************************************************************
6774 *
6775 * Record a push of a single dword on the stack.
6776 */
6777
6778void emitter::emitStackPush(BYTE* addr, GCtype gcType)
6779{
6780#ifdef DEBUG
6781 assert(IsValidGCtype(gcType));
6782#endif
6783
6784 if (emitSimpleStkUsed)
6785 {
6786 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6787 assert(emitCurStackLvl / sizeof(int) < MAX_SIMPLE_STK_DEPTH);
6788
6789 u1.emitSimpleStkMask <<= 1;
6790 u1.emitSimpleStkMask |= (unsigned)needsGC(gcType);
6791
6792 u1.emitSimpleByrefStkMask <<= 1;
6793 u1.emitSimpleByrefStkMask |= (gcType == GCT_BYREF);
6794
6795 assert((u1.emitSimpleStkMask & u1.emitSimpleByrefStkMask) == u1.emitSimpleByrefStkMask);
6796 }
6797 else
6798 {
6799 emitStackPushLargeStk(addr, gcType);
6800 }
6801
6802 emitCurStackLvl += sizeof(int);
6803}
6804
6805/*****************************************************************************
6806 *
6807 * Record a push of a bunch of non-GC dwords on the stack.
6808 */
6809
6810void emitter::emitStackPushN(BYTE* addr, unsigned count)
6811{
6812 assert(count);
6813
6814 if (emitSimpleStkUsed)
6815 {
6816 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6817
6818 u1.emitSimpleStkMask <<= count;
6819 u1.emitSimpleByrefStkMask <<= count;
6820 }
6821 else
6822 {
6823 emitStackPushLargeStk(addr, GCT_NONE, count);
6824 }
6825
6826 emitCurStackLvl += count * sizeof(int);
6827}
6828
6829/*****************************************************************************
6830 *
6831 * Record a pop of the given number of dwords from the stack.
6832 */
6833
6834void emitter::emitStackPop(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count)
6835{
6836 assert(emitCurStackLvl / sizeof(int) >= count);
6837 assert(!isCall || callInstrSize > 0);
6838
6839 if (count)
6840 {
6841 if (emitSimpleStkUsed)
6842 {
6843 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCinfo
6844
6845 unsigned cnt = count;
6846
6847 do
6848 {
6849 u1.emitSimpleStkMask >>= 1;
6850 u1.emitSimpleByrefStkMask >>= 1;
6851 } while (--cnt);
6852 }
6853 else
6854 {
6855 emitStackPopLargeStk(addr, isCall, callInstrSize, count);
6856 }
6857
6858 emitCurStackLvl -= count * sizeof(int);
6859 }
6860 else
6861 {
6862 assert(isCall);
6863
6864 // For the general encoder we do the call below always when it's a call, to ensure that the call is
6865 // recorded (when we're doing the ptr reg map for a non-fully-interruptible method).
6866 if (emitFullGCinfo
6867#ifndef JIT32_GCENCODER
6868 || (emitComp->genFullPtrRegMap && (!emitComp->genInterruptible) && isCall)
6869#endif // JIT32_GCENCODER
6870 )
6871 {
6872 emitStackPopLargeStk(addr, isCall, callInstrSize, 0);
6873 }
6874 }
6875}
6876
6877/*****************************************************************************
6878 *
6879 * Record a push of a single word on the stack for a full pointer map.
6880 */
6881
6882void emitter::emitStackPushLargeStk(BYTE* addr, GCtype gcType, unsigned count)
6883{
6884 S_UINT32 level(emitCurStackLvl / sizeof(int));
6885
6886 assert(IsValidGCtype(gcType));
6887 assert(count);
6888 assert(!emitSimpleStkUsed);
6889
6890 do
6891 {
6892 /* Push an entry for this argument on the tracking stack */
6893
6894 // printf("Pushed [%d] at lvl %2u [max=%u]\n", isGCref, emitArgTrackTop - emitArgTrackTab, emitMaxStackDepth);
6895
6896 assert(level.IsOverflow() || u2.emitArgTrackTop == u2.emitArgTrackTab + level.Value());
6897 *u2.emitArgTrackTop++ = (BYTE)gcType;
6898 assert(u2.emitArgTrackTop <= u2.emitArgTrackTab + emitMaxStackDepth);
6899
6900 if (emitFullArgInfo || needsGC(gcType))
6901 {
6902 if (emitFullGCinfo)
6903 {
6904 /* Append an "arg push" entry if this is a GC ref or
6905 FPO method. Allocate a new ptr arg entry and fill it in */
6906
6907 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
6908 regPtrNext->rpdGCtype = gcType;
6909
6910 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
6911 regPtrNext->rpdArg = TRUE;
6912 regPtrNext->rpdCall = FALSE;
6913 if (level.IsOverflow() || !FitsIn<unsigned short>(level.Value()))
6914 {
6915 IMPL_LIMITATION("Too many/too big arguments to encode GC information");
6916 }
6917 regPtrNext->rpdPtrArg = (unsigned short)level.Value();
6918 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_PUSH;
6919 regPtrNext->rpdIsThis = FALSE;
6920
6921#ifdef DEBUG
6922 if (EMIT_GC_VERBOSE)
6923 {
6924 printf("[%08X] %s arg push %u\n", dspPtr(regPtrNext), GCtypeStr(gcType), level.Value());
6925 }
6926#endif
6927 }
6928
6929 /* This is an "interesting" argument push */
6930
6931 u2.emitGcArgTrackCnt++;
6932 }
6933 level += 1;
6934 assert(!level.IsOverflow());
6935 } while (--count);
6936}
6937
6938/*****************************************************************************
6939 *
6940 * Record a pop of the given number of words from the stack for a full ptr
6941 * map.
6942 */
6943
6944void emitter::emitStackPopLargeStk(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count)
6945{
6946 assert(emitIssuing);
6947
6948 unsigned argStkCnt;
6949 S_UINT16 argRecCnt(0); // arg count for ESP, ptr-arg count for EBP
6950 unsigned gcrefRegs, byrefRegs;
6951
6952#ifdef JIT32_GCENCODER
6953 // For the general encoder, we always need to record calls, so we make this call
6954 // even when emitSimpleStkUsed is true.
6955 assert(!emitSimpleStkUsed);
6956#endif
6957
6958 /* Count how many pointer records correspond to this "pop" */
6959
6960 for (argStkCnt = count; argStkCnt; argStkCnt--)
6961 {
6962 assert(u2.emitArgTrackTop > u2.emitArgTrackTab);
6963
6964 GCtype gcType = (GCtype)(*--u2.emitArgTrackTop);
6965
6966 assert(IsValidGCtype(gcType));
6967
6968 // printf("Popped [%d] at lvl %u\n", GCtypeStr(gcType), emitArgTrackTop - emitArgTrackTab);
6969
6970 // This is an "interesting" argument
6971
6972 if (emitFullArgInfo || needsGC(gcType))
6973 {
6974 argRecCnt += 1;
6975 }
6976 }
6977
6978 assert(u2.emitArgTrackTop >= u2.emitArgTrackTab);
6979 assert(u2.emitArgTrackTop == u2.emitArgTrackTab + emitCurStackLvl / sizeof(int) - count);
6980 noway_assert(!argRecCnt.IsOverflow());
6981
6982 /* We're about to pop the corresponding arg records */
6983
6984 u2.emitGcArgTrackCnt -= argRecCnt.Value();
6985
6986#ifdef JIT32_GCENCODER
6987 // For the general encoder, we always have to record calls, so we don't take this early return.
6988 if (!emitFullGCinfo)
6989 return;
6990#endif
6991
6992 // Do we have any interesting (i.e., callee-saved) registers live here?
6993
6994 gcrefRegs = byrefRegs = 0;
6995
6996 // We make a bitmask whose bits correspond to callee-saved register indices (in the sequence
6997 // of callee-saved registers only).
6998 for (unsigned calleeSavedRegIdx = 0; calleeSavedRegIdx < CNT_CALLEE_SAVED; calleeSavedRegIdx++)
6999 {
7000 regMaskTP calleeSavedRbm = raRbmCalleeSaveOrder[calleeSavedRegIdx];
7001 if (emitThisGCrefRegs & calleeSavedRbm)
7002 {
7003 gcrefRegs |= (1 << calleeSavedRegIdx);
7004 }
7005 if (emitThisByrefRegs & calleeSavedRbm)
7006 {
7007 byrefRegs |= (1 << calleeSavedRegIdx);
7008 }
7009 }
7010
7011#ifdef JIT32_GCENCODER
7012 // For the general encoder, we always have to record calls, so we don't take this early return. /* Are there any
7013 // args to pop at this call site?
7014
7015 if (argRecCnt.Value() == 0)
7016 {
7017 /*
7018 Or do we have a partially interruptible EBP-less frame, and any
7019 of EDI,ESI,EBX,EBP are live, or is there an outer/pending call?
7020 */
7021 CLANG_FORMAT_COMMENT_ANCHOR;
7022
7023#if !FPO_INTERRUPTIBLE
7024 if (emitFullyInt || (gcrefRegs == 0 && byrefRegs == 0 && u2.emitGcArgTrackCnt == 0))
7025#endif
7026 return;
7027 }
7028#endif // JIT32_GCENCODER
7029
7030 /* Only calls may pop more than one value */
7031 // More detail:
7032 // _cdecl calls accomplish this popping via a post-call-instruction SP adjustment.
7033 // The "rpdCall" field below should be interpreted as "the instruction accomplishes
7034 // call-related popping, even if it's not itself a call". Therefore, we don't just
7035 // use the "isCall" input argument, which means that the instruction actually is a call --
7036 // we use the OR of "isCall" or the "pops more than one value."
7037
7038 bool isCallRelatedPop = (argRecCnt.Value() > 1);
7039
7040 /* Allocate a new ptr arg entry and fill it in */
7041
7042 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
7043 regPtrNext->rpdGCtype = GCT_GCREF; // Pops need a non-0 value (??)
7044
7045 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
7046 regPtrNext->rpdCall = (isCall || isCallRelatedPop);
7047#ifndef JIT32_GCENCODER
7048 if (regPtrNext->rpdCall)
7049 {
7050 assert(isCall || callInstrSize == 0);
7051 regPtrNext->rpdCallInstrSize = callInstrSize;
7052 }
7053#endif
7054 regPtrNext->rpdCallGCrefRegs = gcrefRegs;
7055 regPtrNext->rpdCallByrefRegs = byrefRegs;
7056 regPtrNext->rpdArg = TRUE;
7057 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_POP;
7058 regPtrNext->rpdPtrArg = argRecCnt.Value();
7059
7060#ifdef DEBUG
7061 if (EMIT_GC_VERBOSE)
7062 {
7063 printf("[%08X] ptr arg pop %u\n", dspPtr(regPtrNext), count);
7064 }
7065#endif
7066}
7067
7068/*****************************************************************************
7069 * For caller-pop arguments, we report the arguments as pending arguments.
7070 * However, any GC arguments are now dead, so we need to report them
7071 * as non-GC.
7072 */
7073
7074void emitter::emitStackKillArgs(BYTE* addr, unsigned count, unsigned char callInstrSize)
7075{
7076 assert(count > 0);
7077
7078 if (emitSimpleStkUsed)
7079 {
7080 assert(!emitFullGCinfo); // Simple stk not used for emitFullGCInfo
7081
7082 /* We don't need to report this to the GC info, but we do need
7083 to kill mark the ptrs on the stack as non-GC */
7084
7085 assert(emitCurStackLvl / sizeof(int) >= count);
7086
7087 for (unsigned lvl = 0; lvl < count; lvl++)
7088 {
7089 u1.emitSimpleStkMask &= ~(1 << lvl);
7090 u1.emitSimpleByrefStkMask &= ~(1 << lvl);
7091 }
7092 }
7093 else
7094 {
7095 BYTE* argTrackTop = u2.emitArgTrackTop;
7096 S_UINT16 gcCnt(0);
7097
7098 for (unsigned i = 0; i < count; i++)
7099 {
7100 assert(argTrackTop > u2.emitArgTrackTab);
7101
7102 --argTrackTop;
7103
7104 GCtype gcType = (GCtype)(*argTrackTop);
7105 assert(IsValidGCtype(gcType));
7106
7107 if (needsGC(gcType))
7108 {
7109 // printf("Killed %s at lvl %u\n", GCtypeStr(gcType), argTrackTop - emitArgTrackTab);
7110
7111 *argTrackTop = GCT_NONE;
7112 gcCnt += 1;
7113 }
7114 }
7115
7116 noway_assert(!gcCnt.IsOverflow());
7117
7118 /* We're about to kill the corresponding (pointer) arg records */
7119
7120 if (!emitFullArgInfo)
7121 {
7122 u2.emitGcArgTrackCnt -= gcCnt.Value();
7123 }
7124
7125 if (!emitFullGCinfo)
7126 {
7127 return;
7128 }
7129
7130 /* Right after the call, the arguments are still sitting on the
7131 stack, but they are effectively dead. For fully-interruptible
7132 methods, we need to report that */
7133
7134 if (emitFullGCinfo && gcCnt.Value())
7135 {
7136 /* Allocate a new ptr arg entry and fill it in */
7137
7138 regPtrDsc* regPtrNext = codeGen->gcInfo.gcRegPtrAllocDsc();
7139 regPtrNext->rpdGCtype = GCT_GCREF; // Kills need a non-0 value (??)
7140
7141 regPtrNext->rpdOffs = emitCurCodeOffs(addr);
7142
7143 regPtrNext->rpdArg = TRUE;
7144 regPtrNext->rpdArgType = (unsigned short)GCInfo::rpdARG_KILL;
7145 regPtrNext->rpdPtrArg = gcCnt.Value();
7146
7147#ifdef DEBUG
7148 if (EMIT_GC_VERBOSE)
7149 {
7150 printf("[%08X] ptr arg kill %u\n", dspPtr(regPtrNext), count);
7151 }
7152#endif
7153 }
7154
7155 /* Now that ptr args have been marked as non-ptrs, we need to record
7156 the call itself as one that has no arguments. */
7157
7158 emitStackPopLargeStk(addr, true, callInstrSize, 0);
7159 }
7160}
7161
7162/*****************************************************************************
7163 * A helper for recording a relocation with the EE.
7164 */
7165void emitter::emitRecordRelocation(void* location, /* IN */
7166 void* target, /* IN */
7167 WORD fRelocType, /* IN */
7168 WORD slotNum /* = 0 */, /* IN */
7169 INT32 addlDelta /* = 0 */) /* IN */
7170{
7171 assert(slotNum == 0); // It is unused on all supported platforms.
7172
7173 // If we're an unmatched altjit, don't tell the VM anything. We still record the relocation for
7174 // late disassembly; maybe we'll need it?
7175 if (emitComp->info.compMatchedVM)
7176 {
7177 emitCmpHandle->recordRelocation(location, target, fRelocType, slotNum, addlDelta);
7178 }
7179#if defined(LATE_DISASM)
7180 codeGen->getDisAssembler().disRecordRelocation((size_t)location, (size_t)target);
7181#endif // defined(LATE_DISASM)
7182}
7183
7184#ifdef _TARGET_ARM_
7185/*****************************************************************************
7186 * A helper for handling a Thumb-Mov32 of position-independent (PC-relative) value
7187 *
7188 * This routine either records relocation for the location with the EE,
7189 * or creates a virtual relocation entry to perform offset fixup during
7190 * compilation without recording it with EE - depending on which of
7191 * absolute/relocative relocations mode are used for code section.
7192 */
7193void emitter::emitHandlePCRelativeMov32(void* location, /* IN */
7194 void* target) /* IN */
7195{
7196 if (emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_RELATIVE_CODE_RELOCS))
7197 {
7198 emitRecordRelocation(location, target, IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL);
7199 }
7200 else
7201 {
7202 emitRecordRelocation(location, target, IMAGE_REL_BASED_THUMB_MOV32);
7203 }
7204}
7205#endif // _TARGET_ARM_
7206
7207/*****************************************************************************
7208 * A helper for recording a call site with the EE.
7209 */
7210void emitter::emitRecordCallSite(ULONG instrOffset, /* IN */
7211 CORINFO_SIG_INFO* callSig, /* IN */
7212 CORINFO_METHOD_HANDLE methodHandle) /* IN */
7213{
7214#if defined(DEBUG)
7215 // Since CORINFO_SIG_INFO is a heavyweight structure, in most cases we can
7216 // lazily obtain it here using the given method handle (we only save the sig
7217 // info when we explicitly need it, i.e. for CALLI calls, vararg calls, and
7218 // tail calls).
7219 if (callSig == nullptr)
7220 {
7221 assert(methodHandle != nullptr);
7222
7223 if (Compiler::eeGetHelperNum(methodHandle) == CORINFO_HELP_UNDEF)
7224 {
7225 if (emitScratchSigInfo == nullptr)
7226 {
7227 emitScratchSigInfo = new (emitComp, CMK_CorSig) CORINFO_SIG_INFO;
7228 }
7229
7230 emitComp->eeGetMethodSig(methodHandle, emitScratchSigInfo);
7231 callSig = emitScratchSigInfo;
7232 }
7233 }
7234
7235 emitCmpHandle->recordCallSite(instrOffset, callSig, methodHandle);
7236#endif // defined(DEBUG)
7237}
7238
7239/*****************************************************************************/
7240#endif // EMIT_TRACK_STACK_DEPTH
7241/*****************************************************************************/
7242/*****************************************************************************/
7243
7244#ifdef DEBUG
7245
7246/*****************************************************************************
7247 * Given a code offset, return a string representing a label for that offset.
7248 * If the code offset is just after the end of the code of the function, the
7249 * label will be "END". If the code offset doesn't correspond to any known
7250 * offset, the label will be "UNKNOWN". The strings are returned from static
7251 * buffers. This function rotates amongst four such static buffers (there are
7252 * cases where this function is called four times to provide data for a single
7253 * printf()).
7254 */
7255
7256const char* emitter::emitOffsetToLabel(unsigned offs)
7257{
7258 const size_t TEMP_BUFFER_LEN = 40;
7259 static unsigned curBuf = 0;
7260 static char buf[4][TEMP_BUFFER_LEN];
7261 char* retbuf;
7262
7263 UNATIVE_OFFSET nextof = 0;
7264
7265 for (insGroup* ig = emitIGlist; ig != nullptr; ig = ig->igNext)
7266 {
7267 // There is an eventual unused space after the last actual hot block
7268 // before the first allocated cold block.
7269 assert((nextof == ig->igOffs) || (ig == emitFirstColdIG));
7270
7271 if (ig->igOffs == offs)
7272 {
7273 // Found it!
7274 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "G_M%03u_IG%02u", Compiler::s_compMethodsCount, ig->igNum);
7275 retbuf = buf[curBuf];
7276 curBuf = (curBuf + 1) % 4;
7277 return retbuf;
7278 }
7279 else if (ig->igOffs > offs)
7280 {
7281 // We went past the requested offset but didn't find it.
7282 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "UNKNOWN");
7283 retbuf = buf[curBuf];
7284 curBuf = (curBuf + 1) % 4;
7285 return retbuf;
7286 }
7287
7288 nextof = ig->igOffs + ig->igSize;
7289 }
7290
7291 if (nextof == offs)
7292 {
7293 // It's a pseudo-label to the end.
7294 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "END");
7295 retbuf = buf[curBuf];
7296 curBuf = (curBuf + 1) % 4;
7297 return retbuf;
7298 }
7299 else
7300 {
7301 sprintf_s(buf[curBuf], TEMP_BUFFER_LEN, "UNKNOWN");
7302 retbuf = buf[curBuf];
7303 curBuf = (curBuf + 1) % 4;
7304 return retbuf;
7305 }
7306}
7307
7308#endif // DEBUG
7309
7310//------------------------------------------------------------------------
7311// emitGetGCRegsSavedOrModified: Returns the set of registers that keeps gcrefs and byrefs across the call.
7312//
7313// Notes: it returns union of two sets:
7314// 1) registers that could contain GC/byRefs before the call and call doesn't touch them;
7315// 2) registers that contain GC/byRefs before the call and call modifies them, but they still
7316// contain GC/byRefs.
7317//
7318// Arguments:
7319// methHnd - the method handler of the call.
7320//
7321// Return value:
7322// the saved set of registers.
7323//
7324regMaskTP emitter::emitGetGCRegsSavedOrModified(CORINFO_METHOD_HANDLE methHnd)
7325{
7326 // Is it a helper with a special saved set?
7327 bool isNoGCHelper = emitNoGChelper(methHnd);
7328 if (isNoGCHelper)
7329 {
7330 CorInfoHelpFunc helpFunc = Compiler::eeGetHelperNum(methHnd);
7331
7332 // Get the set of registers that this call kills and remove it from the saved set.
7333 regMaskTP savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(helpFunc);
7334
7335#ifdef DEBUG
7336 if (emitComp->verbose)
7337 {
7338 printf("NoGC Call: savedSet=");
7339 printRegMaskInt(savedSet);
7340 emitDispRegSet(savedSet);
7341 printf("\n");
7342 }
7343#endif
7344 return savedSet;
7345 }
7346 else
7347 {
7348 // This is the saved set of registers after a normal call.
7349 return RBM_CALLEE_SAVED;
7350 }
7351}
7352