a925f1f8a5bd53980fdd66827cb12d24fc3bbf23
[platform/upstream/coreclr.git] / src / jit / emit.h
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
6 #ifndef _EMIT_H_
7 #define _EMIT_H_
8
9 #include "instr.h"
10
11 #ifndef _GCINFO_H_
12 #include "gcinfo.h"
13 #endif
14
15 #include "jitgcinfo.h"
16
17 /*****************************************************************************/
18 #ifdef TRANSLATE_PDB
19 #ifndef _ADDRMAP_INCLUDED_
20 #include "addrmap.h"
21 #endif
22 #ifndef _LOCALMAP_INCLUDED_
23 #include "localmap.h"
24 #endif
25 #ifndef _PDBREWRITE_H_
26 #include "pdbrewrite.h"
27 #endif
28 #endif // TRANSLATE_PDB
29
30 /*****************************************************************************/
31 #ifdef _MSC_VER
32 #pragma warning(disable : 4200) // allow arrays of 0 size inside structs
33 #endif
34 #define TRACK_GC_TEMP_LIFETIMES 0
35
36 /*****************************************************************************/
37
38 #if 0
39 #define EMITVERBOSE 1
40 #else
41 #define EMITVERBOSE (emitComp->verbose)
42 #endif
43
44 #if 0
45 #define EMIT_GC_VERBOSE 0
46 #else
47 #define EMIT_GC_VERBOSE (emitComp->verbose)
48 #endif
49
50 #if 1
51 #define EMIT_INSTLIST_VERBOSE 0
52 #else
53 #define EMIT_INSTLIST_VERBOSE (emitComp->verbose)
54 #endif
55
56 /*****************************************************************************/
57
58 #ifdef DEBUG
59 #define DEBUG_EMIT 1
60 #else
61 #define DEBUG_EMIT 0
62 #endif
63
64 #if EMITTER_STATS
65 void emitterStats(FILE* fout);
66 void emitterStaticStats(FILE* fout); // Static stats about the emitter (data structure offsets, sizes, etc.)
67 #endif
68
69 void printRegMaskInt(regMaskTP mask);
70
71 /*****************************************************************************/
72 /* Forward declarations */
73
74 class emitLocation;
75 class emitter;
76 struct insGroup;
77
78 typedef void (*emitSplitCallbackType)(void* context, emitLocation* emitLoc);
79
80 /*****************************************************************************/
81
82 //-----------------------------------------------------------------------------
83
84 inline bool needsGC(GCtype gcType)
85 {
86     if (gcType == GCT_NONE)
87     {
88         return false;
89     }
90     else
91     {
92         assert(gcType == GCT_GCREF || gcType == GCT_BYREF);
93         return true;
94     }
95 }
96
97 //-----------------------------------------------------------------------------
98
99 #ifdef DEBUG
100
101 inline bool IsValidGCtype(GCtype gcType)
102 {
103     return (gcType == GCT_NONE || gcType == GCT_GCREF || gcType == GCT_BYREF);
104 }
105
106 // Get a string name to represent the GC type
107
108 inline const char* GCtypeStr(GCtype gcType)
109 {
110     switch (gcType)
111     {
112         case GCT_NONE:
113             return "npt";
114         case GCT_GCREF:
115             return "gcr";
116         case GCT_BYREF:
117             return "byr";
118         default:
119             assert(!"Invalid GCtype");
120             return "err";
121     }
122 }
123
124 #endif // DEBUG
125
126 /*****************************************************************************/
127
128 #if DEBUG_EMIT
129 #define INTERESTING_JUMP_NUM -1 // set to 0 to see all jump info
130 //#define INTERESTING_JUMP_NUM    0
131 #endif
132
133 /*****************************************************************************
134  *
135  *  Represent an emitter location.
136  */
137
138 class emitLocation
139 {
140 public:
141     emitLocation() : ig(nullptr), codePos(0)
142     {
143     }
144
145     emitLocation(insGroup* _ig) : ig(_ig), codePos(0)
146     {
147     }
148
149     emitLocation(void* emitCookie) : ig((insGroup*)emitCookie), codePos(0)
150     {
151     }
152
153     // A constructor for code that needs to call it explicitly.
154     void Init()
155     {
156         this->emitLocation::emitLocation();
157     }
158
159     void CaptureLocation(emitter* emit);
160
161     bool IsCurrentLocation(emitter* emit) const;
162
163     // This function is highly suspect, since it presumes knowledge of the codePos "cookie",
164     // and doesn't look at the 'ig' pointer.
165     bool IsOffsetZero() const
166     {
167         return (codePos == 0);
168     }
169
170     UNATIVE_OFFSET CodeOffset(emitter* emit) const;
171
172     insGroup* GetIG() const
173     {
174         return ig;
175     }
176
177     int GetInsNum() const;
178
179     bool operator!=(const emitLocation& other) const
180     {
181         return (ig != other.ig) || (codePos != other.codePos);
182     }
183
184     bool operator==(const emitLocation& other) const
185     {
186         return !(*this != other);
187     }
188
189     bool Valid() const
190     {
191         // Things we could validate:
192         //   1. the instruction group pointer is non-nullptr.
193         //   2. 'ig' is a legal pointer to an instruction group.
194         //   3. 'codePos' is a legal offset into 'ig'.
195         // Currently, we just do #1.
196         // #2 and #3 should only be done in DEBUG, if they are implemented.
197
198         if (ig == nullptr)
199         {
200             return false;
201         }
202
203         return true;
204     }
205
206 #ifdef _TARGET_AMD64_
207     UNATIVE_OFFSET GetFuncletPrologOffset(emitter* emit) const;
208 #endif // _TARGET_AMD64_
209
210 #ifdef DEBUG
211     void Print() const;
212 #endif // DEBUG
213
214 private:
215     insGroup* ig;      // the instruction group
216     unsigned  codePos; // the code position within the IG (see emitCurOffset())
217 };
218
219 /************************************************************************/
220 /*          The following describes an instruction group                */
221 /************************************************************************/
222
223 DECLARE_TYPED_ENUM(insGroupPlaceholderType, unsigned char)
224 {
225     IGPT_PROLOG, // currently unused
226         IGPT_EPILOG,
227 #if FEATURE_EH_FUNCLETS
228         IGPT_FUNCLET_PROLOG, IGPT_FUNCLET_EPILOG,
229 #endif // FEATURE_EH_FUNCLETS
230 }
231 END_DECLARE_TYPED_ENUM(insGroupPlaceholderType, unsigned char)
232
233 #if defined(_MSC_VER) && defined(_TARGET_ARM_)
234 // ARM aligns structures that contain 64-bit ints or doubles on 64-bit boundaries. This causes unwanted
235 // padding to be added to the end, so sizeof() is unnecessarily big.
236 #pragma pack(push)
237 #pragma pack(4)
238 #endif // defined(_MSC_VER) && defined(_TARGET_ARM_)
239
240 struct insPlaceholderGroupData
241 {
242     insGroup*               igPhNext;
243     BasicBlock*             igPhBB;
244     VARSET_TP               igPhInitGCrefVars;
245     regMaskTP               igPhInitGCrefRegs;
246     regMaskTP               igPhInitByrefRegs;
247     VARSET_TP               igPhPrevGCrefVars;
248     regMaskTP               igPhPrevGCrefRegs;
249     regMaskTP               igPhPrevByrefRegs;
250     insGroupPlaceholderType igPhType;
251 }; // end of struct insPlaceholderGroupData
252
253 struct insGroup
254 {
255     insGroup* igNext;
256
257 #ifdef DEBUG
258     insGroup* igSelf; // for consistency checking
259 #endif
260
261     UNATIVE_OFFSET igNum;     // for ordering (and display) purposes
262     UNATIVE_OFFSET igOffs;    // offset of this group within method
263     unsigned int   igFuncIdx; // Which function/funclet does this belong to? (Index into Compiler::compFuncInfos array.)
264     unsigned short igFlags;   // see IGF_xxx below
265     unsigned short igSize;    // # of bytes of code in this group
266
267 #define IGF_GC_VARS 0x0001    // new set of live GC ref variables
268 #define IGF_BYREF_REGS 0x0002 // new set of live by-ref registers
269 #if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
270 #define IGF_FINALLY_TARGET 0x0004 // this group is the start of a basic block that is returned to after a finally.
271 #endif                            // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_)
272 #define IGF_FUNCLET_PROLOG 0x0008 // this group belongs to a funclet prolog
273 #define IGF_FUNCLET_EPILOG 0x0010 // this group belongs to a funclet epilog.
274 #define IGF_EPILOG 0x0020         // this group belongs to a main function epilog
275 #define IGF_NOGCINTERRUPT 0x0040  // this IG is is a no-interrupt region (prolog, epilog, etc.)
276 #define IGF_UPD_ISZ 0x0080        // some instruction sizes updated
277 #define IGF_PLACEHOLDER 0x0100    // this is a placeholder group, to be filled in later
278 #define IGF_EMIT_ADD 0x0200       // this is a block added by the emitter
279                                   // because the codegen block was too big. Also used for
280                                   // placeholder IGs that aren't also labels.
281
282 // Mask of IGF_* flags that should be propagated to new blocks when they are created.
283 // This allows prologs and epilogs to be any number of IGs, but still be
284 // automatically marked properly.
285 #if FEATURE_EH_FUNCLETS
286 #ifdef DEBUG
287 #define IGF_PROPAGATE_MASK (IGF_EPILOG | IGF_FUNCLET_PROLOG | IGF_FUNCLET_EPILOG)
288 #else // DEBUG
289 #define IGF_PROPAGATE_MASK (IGF_EPILOG | IGF_FUNCLET_PROLOG)
290 #endif // DEBUG
291 #else  // FEATURE_EH_FUNCLETS
292 #define IGF_PROPAGATE_MASK (IGF_EPILOG)
293 #endif // FEATURE_EH_FUNCLETS
294
295     // Try to do better packing based on how large regMaskSmall is (8, 16, or 64 bits).
296     CLANG_FORMAT_COMMENT_ANCHOR;
297 #if REGMASK_BITS <= 32
298
299     union {
300         BYTE*                    igData;   // addr of instruction descriptors
301         insPlaceholderGroupData* igPhData; // when igFlags & IGF_PLACEHOLDER
302     };
303
304 #if EMIT_TRACK_STACK_DEPTH
305     unsigned igStkLvl; // stack level on entry
306 #endif
307     regMaskSmall  igGCregs; // set of registers with live GC refs
308     unsigned char igInsCnt; // # of instructions  in this group
309
310 #else // REGMASK_BITS
311
312     regMaskSmall igGCregs; // set of registers with live GC refs
313
314     union {
315         BYTE*                    igData;   // addr of instruction descriptors
316         insPlaceholderGroupData* igPhData; // when igFlags & IGF_PLACEHOLDER
317     };
318
319 #if EMIT_TRACK_STACK_DEPTH
320     unsigned igStkLvl; // stack level on entry
321 #endif
322
323     unsigned char igInsCnt; // # of instructions  in this group
324
325 #endif // REGMASK_BITS
326
327     VARSET_VALRET_TP igGCvars() const
328     {
329         assert(igFlags & IGF_GC_VARS);
330
331         BYTE* ptr = (BYTE*)igData;
332         ptr -= sizeof(VARSET_TP);
333
334         return *(VARSET_TP*)ptr;
335     }
336
337     unsigned igByrefRegs() const
338     {
339         assert(igFlags & IGF_BYREF_REGS);
340
341         BYTE* ptr = (BYTE*)igData;
342
343         if (igFlags & IGF_GC_VARS)
344         {
345             ptr -= sizeof(VARSET_TP);
346         }
347
348         ptr -= sizeof(unsigned);
349
350         return *(unsigned*)ptr;
351     }
352
353 }; // end of struct insGroup
354
355 //  For AMD64 the maximum prolog/epilog size supported on the OS is 256 bytes
356 //  Since it is incorrect for us to be jumping across funclet prolog/epilogs
357 //  we will use the following estimate as the maximum placeholder size.
358 //
359 #define MAX_PLACEHOLDER_IG_SIZE 256
360
361 #if defined(_MSC_VER) && defined(_TARGET_ARM_)
362 #pragma pack(pop)
363 #endif // defined(_MSC_VER) && defined(_TARGET_ARM_)
364
365 /*****************************************************************************/
366
367 #define DEFINE_ID_OPS
368 #include "emitfmts.h"
369 #undef DEFINE_ID_OPS
370
371 enum LclVarAddrTag
372 {
373     LVA_STANDARD_ENCODING = 0,
374     LVA_LARGE_OFFSET      = 1,
375     LVA_COMPILER_TEMP     = 2,
376     LVA_LARGE_VARNUM      = 3
377 };
378
379 struct emitLclVarAddr
380 {
381     // Constructor
382     void initLclVarAddr(int varNum, unsigned offset);
383
384     int lvaVarNum(); // Returns the variable to access. Note that it returns a negative number for compiler spill temps.
385     unsigned lvaOffset(); // returns the offset into the variable to access
386
387     // This struct should be 32 bits in size for the release build.
388     // We have this constraint because this type is used in a union
389     // with several other pointer sized types in the instrDesc struct.
390     //
391 protected:
392     unsigned _lvaVarNum : 15; // Usually the lvaVarNum
393     unsigned _lvaExtra : 15;  // Usually the lvaOffset
394     unsigned _lvaTag : 2;     // tag field to support larger varnums
395 };
396
397 enum idAddrUnionTag
398 {
399     iaut_ALIGNED_POINTER = 0x0,
400     iaut_DATA_OFFSET     = 0x1,
401     iaut_INST_COUNT      = 0x2,
402     iaut_UNUSED_TAG      = 0x3,
403
404     iaut_MASK  = 0x3,
405     iaut_SHIFT = 2
406 };
407
408 class emitter
409 {
410     friend class emitLocation;
411     friend class Compiler;
412     friend class CodeGen;
413     friend class CodeGenInterface;
414
415 public:
416     /*************************************************************************
417      *
418      *  Define the public entry points.
419      */
420
421     // Constructor.
422     emitter()
423     {
424 #ifdef DEBUG
425         // There seem to be some cases where this is used without being initialized via CodeGen::inst_set_SV_var().
426         emitVarRefOffs = 0;
427 #endif // DEBUG
428
429 #ifdef _TARGET_XARCH_
430         SetUseSSE3_4(false);
431 #endif // _TARGET_XARCH_
432
433 #ifdef FEATURE_AVX_SUPPORT
434         SetUseAVX(false);
435 #endif // FEATURE_AVX_SUPPORT
436     }
437
438 #include "emitpub.h"
439
440 protected:
441     /************************************************************************/
442     /*                        Miscellaneous stuff                           */
443     /************************************************************************/
444
445     Compiler* emitComp;
446     GCInfo*   gcInfo;
447     CodeGen*  codeGen;
448
449     typedef GCInfo::varPtrDsc varPtrDsc;
450     typedef GCInfo::regPtrDsc regPtrDsc;
451     typedef GCInfo::CallDsc   callDsc;
452
453     void* emitGetMem(size_t sz);
454
455     DECLARE_TYPED_ENUM(opSize, unsigned)
456     {
457         OPSZ1 = 0, OPSZ2 = 1, OPSZ4 = 2, OPSZ8 = 3, OPSZ16 = 4, OPSZ32 = 5, OPSZ_COUNT = 6,
458 #ifdef _TARGET_AMD64_
459         OPSZP = OPSZ8,
460 #else
461         OPSZP = OPSZ4,
462 #endif
463     }
464     END_DECLARE_TYPED_ENUM(opSize, unsigned)
465
466 #define OPSIZE_INVALID ((opSize)0xffff)
467
468     static const emitter::opSize emitSizeEncode[];
469     static const emitAttr        emitSizeDecode[];
470
471     static emitter::opSize emitEncodeSize(emitAttr size);
472     static emitAttr emitDecodeSize(emitter::opSize ensz);
473
474     // Currently, we only allow one IG for the prolog
475     bool emitIGisInProlog(const insGroup* ig)
476     {
477         return ig == emitPrologIG;
478     }
479
480     bool emitIGisInEpilog(const insGroup* ig)
481     {
482         return (ig != nullptr) && ((ig->igFlags & IGF_EPILOG) != 0);
483     }
484
485 #if FEATURE_EH_FUNCLETS
486
487     bool emitIGisInFuncletProlog(const insGroup* ig)
488     {
489         return (ig != nullptr) && ((ig->igFlags & IGF_FUNCLET_PROLOG) != 0);
490     }
491
492     bool emitIGisInFuncletEpilog(const insGroup* ig)
493     {
494         return (ig != nullptr) && ((ig->igFlags & IGF_FUNCLET_EPILOG) != 0);
495     }
496
497 #endif // FEATURE_EH_FUNCLETS
498
499     // If "ig" corresponds to the start of a basic block that is the
500     // target of a funclet return, generate GC information for it's start
501     // address "cp", as if it were the return address of a call.
502     void emitGenGCInfoIfFuncletRetTarget(insGroup* ig, BYTE* cp);
503
504     void emitRecomputeIGoffsets();
505
506     /************************************************************************/
507     /*          The following describes a single instruction                */
508     /************************************************************************/
509
510     DECLARE_TYPED_ENUM(insFormat, unsigned)
511     {
512 #define IF_DEF(en, op1, op2) IF_##en,
513 #include "emitfmts.h"
514
515         IF_COUNT
516     }
517     END_DECLARE_TYPED_ENUM(insFormat, unsigned)
518
519 #define AM_DISP_BITS ((sizeof(unsigned) * 8) - 2 * (REGNUM_BITS + 1) - 2)
520 #define AM_DISP_BIG_VAL (-(1 << (AM_DISP_BITS - 1)))
521 #define AM_DISP_MIN (-((1 << (AM_DISP_BITS - 1)) - 1))
522 #define AM_DISP_MAX (+((1 << (AM_DISP_BITS - 1)) - 1))
523
524     struct emitAddrMode
525     {
526         regNumber       amBaseReg : REGNUM_BITS + 1;
527         regNumber       amIndxReg : REGNUM_BITS + 1;
528         emitter::opSize amScale : 2;
529         int             amDisp : AM_DISP_BITS;
530     };
531
532 #if defined(DEBUG) || defined(LATE_DISASM) // LATE_DISASM needs the idMemCookie on calls to display the call target name
533
534     struct instrDesc;
535
536     struct instrDescDebugInfo
537     {
538         unsigned idNum;
539         size_t   idSize;       // size of the instruction descriptor
540         unsigned idVarRefOffs; // IL offset for LclVar reference
541         size_t   idMemCookie;  // for display of member names in addr modes
542         void*    idClsCookie;  // for display of member names in addr modes
543 #ifdef TRANSLATE_PDB
544         unsigned int idilStart; // instruction descriptor source information for PDB translation
545 #endif
546         bool              idFinallyCall; // Branch instruction is a call to finally
547         bool              idCatchRet;    // Instruction is for a catch 'return'
548         CORINFO_SIG_INFO* idCallSig;     // Used to report native call site signatures to the EE
549     };
550
551 #endif // defined(DEBUG) || defined(LATE_DISASM)
552
553 #ifdef _TARGET_ARM_
554     unsigned insEncodeSetFlags(insFlags sf);
555
556     DECLARE_TYPED_ENUM(insSize, unsigned)
557     {
558         ISZ_16BIT, ISZ_32BIT, ISZ_48BIT // pseudo-instruction for conditional branch with imm24 range,
559                                         // encoded as IT of condition followed by an unconditional branch
560     }
561     END_DECLARE_TYPED_ENUM(insSize, unsigned)
562
563     unsigned insEncodeShiftOpts(insOpts opt);
564     unsigned insEncodePUW_G0(insOpts opt, int imm);
565     unsigned insEncodePUW_H0(insOpts opt, int imm);
566
567 #endif // _TARGET_ARM_
568
569 #if defined(_TARGET_X86_) && defined(LEGACY_BACKEND)
570 #define HAS_TINY_DESC 1
571 #else
572 #define HAS_TINY_DESC 0
573 #endif
574
575     struct instrDescCns;
576
577     struct instrDesc
578     {
579     private:
580 #if defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
581         // The assembly instruction
582         instruction _idIns : 9;
583 #else  // !defined(_TARGET_XARCH_) || defined(LEGACY_BACKEND)
584         // The assembly instruction
585         instruction _idIns : 8;
586 #endif // !defined(_TARGET_XARCH_) || defined(LEGACY_BACKEND)
587         // The format for the instruction
588         insFormat _idInsFmt : 8;
589
590     public:
591         instruction idIns() const
592         {
593             return _idIns;
594         }
595         void idIns(instruction ins)
596         {
597             _idIns = ins;
598             assert(_idIns == ins);
599         }
600
601         insFormat idInsFmt() const
602         {
603             return _idInsFmt;
604         }
605         void idInsFmt(insFormat insFmt)
606         {
607 #if defined(_TARGET_ARM64_)
608             noway_assert(insFmt != IF_NONE); // Only the x86 emitter uses IF_NONE, it is invalid for ARM64 (and ARM32)
609 #endif
610             _idInsFmt = insFmt;
611             assert(_idInsFmt == insFmt);
612         }
613
614         /*
615             The idReg1 and idReg2 fields hold the first and second register
616             operand(s), whenever these are present. Note that the size of
617             these fields ranges from 3 to 6 bits, and care needs to be taken
618             to make sure all of these fields stay reasonably packed.
619          */
620
621         void idSetRelocFlags(emitAttr attr)
622         {
623             _idCnsReloc = (EA_IS_CNS_RELOC(attr) ? 1 : 0);
624             _idDspReloc = (EA_IS_DSP_RELOC(attr) ? 1 : 0);
625         }
626
627         ////////////////////////////////////////////////////////////////////////
628         // Space taken up to here:
629         // x86:   16 bits
630         // amd64: 17 bits
631         // arm:   16 bits
632         // arm64: 16 bits
633
634     private:
635 #ifdef _TARGET_XARCH_
636         unsigned _idCodeSize : 4; // size of instruction in bytes
637 #endif
638
639 #if defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
640         opSize _idOpSize : 3; // operand size: 0=1 , 1=2 , 2=4 , 3=8, 4=16, 5=32
641                               // At this point we have fully consumed first DWORD so that next field
642                               // doesn't cross a byte boundary.
643 #elif defined(_TARGET_ARM64_)
644 // Moved the definition of '_idOpSize' later so that we don't cross a 32-bit boundary when laying out bitfields
645 #else  // ARM or x86-LEGACY_BACKEND
646         opSize _idOpSize : 2; // operand size: 0=1 , 1=2 , 2=4 , 3=8
647 #endif // ARM or x86-LEGACY_BACKEND
648
649         // On Amd64, this is where the second DWORD begins
650         // On System V a call could return a struct in 2 registers. The instrDescCGCA struct below has  member that
651         // stores the GC-ness of the second register.
652         // It is added to the instrDescCGCA and not here (the base struct) since it is not needed by all the
653         // instructions. This struct (instrDesc) is very carefully kept to be no more than 128 bytes. There is no more
654         // space to add members for keeping GC-ness of the second return registers. It will also bloat the base struct
655         // unnecessarily since the GC-ness of the second register is only needed for call instructions.
656         // The instrDescCGCA struct's member keeping the GC-ness of the first return register is _idcSecondRetRegGCType.
657         GCtype _idGCref : 2; // GCref operand? (value is a "GCtype")
658
659         // Note that we use the _idReg1 and _idReg2 fields to hold
660         // the live gcrefReg mask for the call instructions on x86/x64
661         //
662         regNumber _idReg1 : REGNUM_BITS; // register num
663
664         regNumber _idReg2 : REGNUM_BITS;
665
666         ////////////////////////////////////////////////////////////////////////
667         // Space taken up to here:
668         // x86:   30 bits
669         // amd64: 38 bits
670         // arm:   32 bits
671         // arm64: 30 bits
672         CLANG_FORMAT_COMMENT_ANCHOR;
673
674 #if HAS_TINY_DESC
675         //
676         // For x86 use last two bits to differentiate if we are tiny or small
677         //
678         unsigned _idTinyDsc : 1;  // is this a "tiny"  descriptor?
679         unsigned _idSmallDsc : 1; // is this a "small" descriptor?
680
681 #else // !HAS_TINY_DESC
682
683         //
684         // On x86/arm platforms we have used 32 bits so far (4 bytes)
685         // On amd64 we have used 38 bits so far (4 bytes + 6 bits)
686         //
687
688         //
689         // For amd64 we just can't fit anything useful into a single DWORD
690         // So we eliminate the notion of 'tiny', and have small (2 DWORDS)
691         // or not small (which is bigger, just like x86)
692         //
693
694         unsigned _idSmallDsc : 1;  // is this a "small" descriptor?
695         unsigned _idLargeCns : 1;  // does a large constant     follow?
696         unsigned _idLargeDsp : 1;  // does a large displacement follow?
697         unsigned _idLargeCall : 1; // large call descriptor used
698
699         unsigned _idBound : 1;      // jump target / frame offset bound
700         unsigned _idCallRegPtr : 1; // IL indirect calls: addr in reg
701         unsigned _idCallAddr : 1;   // IL indirect calls: can make a direct call to iiaAddr
702         unsigned _idNoGC : 1;       // Some helpers don't get recorded in GC tables
703
704 #ifdef _TARGET_ARM64_
705         opSize   _idOpSize : 3;     // operand size: 0=1 , 1=2 , 2=4 , 3=8, 4=16
706         insOpts  _idInsOpt : 6;     // options for instructions
707         unsigned _idLclVar : 1;     // access a local on stack
708 #endif
709
710 #ifdef _TARGET_ARM_
711         insSize  _idInsSize : 2;    // size of instruction: 16, 32 or 48 bits
712         insFlags _idInsFlags : 1;   // will this instruction set the flags
713         unsigned _idLclVar : 1;     // access a local on stack
714         unsigned _idLclFPBase : 1;  // access a local on stack - SP based offset
715         insOpts  _idInsOpt : 3;     // options for Load/Store instructions
716
717 // For arm we have used 16 bits
718 #define ID_EXTRA_BITFIELD_BITS (16)
719
720 #elif defined(_TARGET_ARM64_)
721 // For Arm64, we have used 16 bits from the second DWORD.
722 #define ID_EXTRA_BITFIELD_BITS (16)
723 #elif defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
724 // For xarch !LEGACY_BACKEND, we have used 14 bits from the second DWORD.
725 #define ID_EXTRA_BITFIELD_BITS (14)
726 #elif defined(_TARGET_X86_)
727 // For x86, we have used 6 bits from the second DWORD.
728 #define ID_EXTRA_BITFIELD_BITS (6)
729 #else
730 #error Unsupported or unset target architecture
731 #endif
732
733         ////////////////////////////////////////////////////////////////////////
734         // Space taken up to here:
735         // x86:   38 bits  // if HAS_TINY_DESC is not defined (which it is)
736         // amd64: 46 bits
737         // arm:   48 bits
738         // arm64: 48 bits
739         CLANG_FORMAT_COMMENT_ANCHOR;
740
741         unsigned _idCnsReloc : 1; // LargeCns is an RVA and needs reloc tag
742         unsigned _idDspReloc : 1; // LargeDsp is an RVA and needs reloc tag
743
744 #define ID_EXTRA_RELOC_BITS (2)
745
746         ////////////////////////////////////////////////////////////////////////
747         // Space taken up to here:
748         // x86:   40 bits
749         // amd64: 48 bits
750         // arm:   50 bits
751         // arm64: 50 bits
752         CLANG_FORMAT_COMMENT_ANCHOR;
753
754 #define ID_EXTRA_BITS (ID_EXTRA_RELOC_BITS + ID_EXTRA_BITFIELD_BITS)
755
756 /* Use whatever bits are left over for small constants */
757
758 #define ID_BIT_SMALL_CNS (32 - ID_EXTRA_BITS)
759 #define ID_MIN_SMALL_CNS 0
760 #define ID_MAX_SMALL_CNS (int)((1 << ID_BIT_SMALL_CNS) - 1U)
761
762         ////////////////////////////////////////////////////////////////////////
763         // Small constant size:
764         // x86:   24 bits
765         // amd64: 16 bits
766         // arm:   14 bits
767         // arm64: 14 bits
768
769         unsigned _idSmallCns : ID_BIT_SMALL_CNS;
770
771         ////////////////////////////////////////////////////////////////////////
772         // Space taken up to here: 64 bits, all architectures, by design.
773         ////////////////////////////////////////////////////////////////////////
774         CLANG_FORMAT_COMMENT_ANCHOR;
775
776 #endif // !HAS_TINY_DESC
777
778 #if defined(DEBUG) || defined(LATE_DISASM)
779
780         instrDescDebugInfo* _idDebugOnlyInfo;
781
782     public:
783         instrDescDebugInfo* idDebugOnlyInfo() const
784         {
785             return _idDebugOnlyInfo;
786         }
787         void idDebugOnlyInfo(instrDescDebugInfo* info)
788         {
789             _idDebugOnlyInfo = info;
790         }
791
792     private:
793 #endif // defined(DEBUG) || defined(LATE_DISASM)
794
795         //
796         // This is the end of the smallest instrDesc we can allocate for all
797         //   platforms.
798         // Non-DEBUG sizes:
799         //   x86: 32 bits, and it is called the 'tiny' descriptor.
800         //   amd64/arm/arm64: 64 bits, and it is called the 'small' descriptor.
801         // DEBUG sizes (includes one pointer):
802         //   x86:   2 DWORDs, 64 bits
803         //   amd64: 4 DWORDs, 128 bits
804         //   arm:   3 DWORDs, 96 bits
805         //   arm64: 4 DWORDs, 128 bits
806         // There should no padding or alignment issues on any platform or
807         //   configuration (including DEBUG which has 1 extra pointer).
808         //
809         CLANG_FORMAT_COMMENT_ANCHOR;
810
811 #if HAS_TINY_DESC
812
813         unsigned _idLargeCns : 1;  // does a large constant     follow?
814         unsigned _idLargeDsp : 1;  // does a large displacement follow?
815         unsigned _idLargeCall : 1; // large call descriptor used
816         unsigned _idBound : 1;     // jump target / frame offset bound
817
818         unsigned _idCallRegPtr : 1; // IL indirect calls: addr in reg
819         unsigned _idCallAddr : 1;   // IL indirect calls: can make a direct call to iiaAddr
820         unsigned _idNoGC : 1;       // Some helpers don't get recorded in GC tables
821
822 #define ID_EXTRA_BITFIELD_BITS (7)
823
824         //
825         // For x86, we are using  7 bits from the second DWORD for bitfields.
826         //
827
828         unsigned _idCnsReloc : 1; // LargeCns is an RVA and needs reloc tag
829         unsigned _idDspReloc : 1; // LargeDsp is an RVA and needs reloc tag
830
831 #define ID_EXTRA_REG_BITS (0)
832
833 #define ID_EXTRA_BITS (ID_EXTRA_BITFIELD_BITS + ID_EXTRA_RELOC_BITS + ID_EXTRA_REG_BITS)
834
835 /* Use whatever bits are left over for small constants */
836
837 #define ID_BIT_SMALL_CNS (32 - ID_EXTRA_BITS)
838 #define ID_MIN_SMALL_CNS 0
839 #define ID_MAX_SMALL_CNS (int)((1 << ID_BIT_SMALL_CNS) - 1U)
840
841         // For x86 we have 23 bits remaining for the
842         //   small constant in this extra DWORD.
843
844         unsigned _idSmallCns : ID_BIT_SMALL_CNS;
845
846 #endif // HAS_TINY_DESC
847
848 //
849 // This is the end of the 'small' instrDesc which is the same on all
850 //   platforms (except 64-bit DEBUG which is a little bigger).
851 // Non-DEBUG sizes:
852 //   x86/amd64/arm/arm64: 64 bits
853 // DEBUG sizes (includes one pointer):
854 //   x86:   2 DWORDs, 64 bits
855 //   amd64: 4 DWORDs, 128 bits
856 //   arm:   3 DWORDs, 96 bits
857 //   arm64: 4 DWORDs, 128 bits
858 // There should no padding or alignment issues on any platform or
859 //   configuration (including DEBUG which has 1 extra pointer).
860 //
861
862 /*
863     If you add lots more fields that need to be cleared (such
864     as various flags), you might need to update the body of
865     emitter::emitAllocInstr() to clear them.
866  */
867
868 #if defined(DEBUG) || defined(LATE_DISASM)
869 #define TINY_IDSC_DEBUG_EXTRA (sizeof(void*))
870 #else
871 #define TINY_IDSC_DEBUG_EXTRA (0)
872 #endif
873
874 #if HAS_TINY_DESC
875 #define TINY_IDSC_SIZE (4 + TINY_IDSC_DEBUG_EXTRA)
876 #define SMALL_IDSC_SIZE (8 + TINY_IDSC_DEBUG_EXTRA)
877 #else
878 #define TINY_IDSC_SIZE (8 + TINY_IDSC_DEBUG_EXTRA)
879 #define SMALL_IDSC_SIZE TINY_IDSC_SIZE
880 #endif
881
882         void checkSizes();
883
884         union idAddrUnion {
885 // TODO-Cleanup: We should really add a DEBUG-only tag to this union so we can add asserts
886 // about reading what we think is here, to avoid unexpected corruption issues.
887
888 #ifndef _TARGET_ARM64_
889             emitLclVarAddr iiaLclVar;
890 #endif
891             BasicBlock*  iiaBBlabel;
892             insGroup*    iiaIGlabel;
893             BYTE*        iiaAddr;
894             emitAddrMode iiaAddrMode;
895
896             CORINFO_FIELD_HANDLE iiaFieldHnd; // iiaFieldHandle is also used to encode
897                                               // an offset into the JIT data constant area
898             bool iiaIsJitDataOffset() const;
899             int  iiaGetJitDataOffset() const;
900
901 #ifdef _TARGET_ARMARCH_
902
903             // iiaEncodedInstrCount and its accessor functions are used to specify an instruction
904             // count for jumps, instead of using a label and multiple blocks. This is used in the
905             // prolog as well as for IF_LARGEJMP pseudo-branch instructions.
906             int iiaEncodedInstrCount;
907
908             bool iiaHasInstrCount() const
909             {
910                 return (iiaEncodedInstrCount & iaut_MASK) == iaut_INST_COUNT;
911             }
912             int iiaGetInstrCount() const
913             {
914                 assert(iiaHasInstrCount());
915                 return (iiaEncodedInstrCount >> iaut_SHIFT);
916             }
917             void iiaSetInstrCount(int count)
918             {
919                 assert(abs(count) < 10);
920                 iiaEncodedInstrCount = (count << iaut_SHIFT) | iaut_INST_COUNT;
921             }
922
923             struct
924             {
925 #ifdef _TARGET_ARM64_
926                 // For 64-bit architecture this 32-bit structure can pack with these unsigned bit fields
927                 emitLclVarAddr iiaLclVar;
928                 unsigned       _idReg3Scaled : 1; // Reg3 is scaled by idOpSize bits
929                 GCtype         _idGCref2 : 2;
930 #endif
931                 regNumber _idReg3 : REGNUM_BITS;
932                 regNumber _idReg4 : REGNUM_BITS;
933             };
934 #elif defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
935             struct
936             {
937                 regNumber _idReg3 : REGNUM_BITS;
938             };
939 #endif // defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
940
941         } _idAddrUnion;
942
943         /* Trivial wrappers to return properly typed enums */
944     public:
945 #if HAS_TINY_DESC
946
947         bool idIsTiny() const
948         {
949             return (_idTinyDsc != 0);
950         }
951         void idSetIsTiny()
952         {
953             _idTinyDsc = 1;
954         }
955
956 #else
957
958         bool idIsTiny() const
959         {
960             return false;
961         }
962         void idSetIsTiny()
963         {
964             _idSmallDsc = 1;
965         }
966
967 #endif // HAS_TINY_DESC
968
969         bool idIsSmallDsc() const
970         {
971             return (_idSmallDsc != 0);
972         }
973         void idSetIsSmallDsc()
974         {
975             _idSmallDsc = 1;
976         }
977
978 #if defined(_TARGET_XARCH_)
979
980         unsigned idCodeSize() const
981         {
982             return _idCodeSize;
983         }
984         void idCodeSize(unsigned sz)
985         {
986             _idCodeSize = sz;
987             assert(sz == _idCodeSize);
988         }
989
990 #elif defined(_TARGET_ARM64_)
991         unsigned idCodeSize() const
992         {
993             int size = 4;
994             switch (idInsFmt())
995             {
996                 case IF_LARGEADR:
997                 // adrp + add
998                 case IF_LARGEJMP:
999                     // b<cond> + b<uncond>
1000                     size = 8;
1001                     break;
1002                 case IF_LARGELDC:
1003                     if (isVectorRegister(idReg1()))
1004                     {
1005                         // adrp + ldr + fmov
1006                         size = 12;
1007                     }
1008                     else
1009                     {
1010                         // adrp + ldr
1011                         size = 8;
1012                     }
1013                     break;
1014                 default:
1015                     break;
1016             }
1017
1018             return size;
1019         }
1020
1021 #elif defined(_TARGET_ARM_)
1022
1023         bool idInstrIsT1() const
1024         {
1025             return (_idInsSize == ISZ_16BIT);
1026         }
1027         unsigned idCodeSize() const
1028         {
1029             unsigned result = (_idInsSize == ISZ_16BIT) ? 2 : (_idInsSize == ISZ_32BIT) ? 4 : 6;
1030             return result;
1031         }
1032         insSize idInsSize() const
1033         {
1034             return _idInsSize;
1035         }
1036         void idInsSize(insSize isz)
1037         {
1038             _idInsSize = isz;
1039             assert(isz == _idInsSize);
1040         }
1041         insFlags idInsFlags() const
1042         {
1043             return _idInsFlags;
1044         }
1045         void idInsFlags(insFlags sf)
1046         {
1047             _idInsFlags = sf;
1048             assert(sf == _idInsFlags);
1049         }
1050 #endif // _TARGET_ARM_
1051
1052         emitAttr idOpSize()
1053         {
1054             return emitDecodeSize(_idOpSize);
1055         }
1056         void idOpSize(emitAttr opsz)
1057         {
1058             _idOpSize = emitEncodeSize(opsz);
1059         }
1060
1061         GCtype idGCref() const
1062         {
1063             return (GCtype)_idGCref;
1064         }
1065         void idGCref(GCtype gctype)
1066         {
1067             _idGCref = gctype;
1068         }
1069
1070         regNumber idReg1() const
1071         {
1072             return _idReg1;
1073         }
1074         void idReg1(regNumber reg)
1075         {
1076             _idReg1 = reg;
1077             assert(reg == _idReg1);
1078         }
1079
1080 #ifdef _TARGET_ARM64_
1081         GCtype idGCrefReg2() const
1082         {
1083             assert(!idIsTiny());
1084             assert(!idIsSmallDsc());
1085             return (GCtype)idAddr()->_idGCref2;
1086         }
1087         void idGCrefReg2(GCtype gctype)
1088         {
1089             assert(!idIsTiny());
1090             assert(!idIsSmallDsc());
1091             idAddr()->_idGCref2 = gctype;
1092         }
1093 #endif // _TARGET_ARM64_
1094
1095         regNumber idReg2() const
1096         {
1097             return _idReg2;
1098         }
1099         void idReg2(regNumber reg)
1100         {
1101             _idReg2 = reg;
1102             assert(reg == _idReg2);
1103         }
1104
1105 #if defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
1106         regNumber idReg3() const
1107         {
1108             assert(!idIsTiny());
1109             assert(!idIsSmallDsc());
1110             return idAddr()->_idReg3;
1111         }
1112         void idReg3(regNumber reg)
1113         {
1114             assert(!idIsTiny());
1115             assert(!idIsSmallDsc());
1116             idAddr()->_idReg3 = reg;
1117             assert(reg == idAddr()->_idReg3);
1118         }
1119 #endif // defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
1120 #ifdef _TARGET_ARMARCH_
1121         insOpts idInsOpt() const
1122         {
1123             return (insOpts)_idInsOpt;
1124         }
1125         void idInsOpt(insOpts opt)
1126         {
1127             _idInsOpt = opt;
1128             assert(opt == _idInsOpt);
1129         }
1130
1131         regNumber idReg3() const
1132         {
1133             assert(!idIsTiny());
1134             assert(!idIsSmallDsc());
1135             return idAddr()->_idReg3;
1136         }
1137         void idReg3(regNumber reg)
1138         {
1139             assert(!idIsTiny());
1140             assert(!idIsSmallDsc());
1141             idAddr()->_idReg3 = reg;
1142             assert(reg == idAddr()->_idReg3);
1143         }
1144         regNumber idReg4() const
1145         {
1146             assert(!idIsTiny());
1147             assert(!idIsSmallDsc());
1148             return idAddr()->_idReg4;
1149         }
1150         void idReg4(regNumber reg)
1151         {
1152             assert(!idIsTiny());
1153             assert(!idIsSmallDsc());
1154             idAddr()->_idReg4 = reg;
1155             assert(reg == idAddr()->_idReg4);
1156         }
1157 #ifdef _TARGET_ARM64_
1158         bool idReg3Scaled() const
1159         {
1160             assert(!idIsTiny());
1161             assert(!idIsSmallDsc());
1162             return (idAddr()->_idReg3Scaled == 1);
1163         }
1164         void idReg3Scaled(bool val)
1165         {
1166             assert(!idIsTiny());
1167             assert(!idIsSmallDsc());
1168             idAddr()->_idReg3Scaled = val ? 1 : 0;
1169         }
1170 #endif // _TARGET_ARM64_
1171
1172 #endif // _TARGET_ARMARCH_
1173
1174         inline static bool fitsInSmallCns(ssize_t val)
1175         {
1176             return ((val >= ID_MIN_SMALL_CNS) && (val <= ID_MAX_SMALL_CNS));
1177         }
1178
1179         bool idIsLargeCns() const
1180         {
1181             assert(!idIsTiny());
1182             return _idLargeCns != 0;
1183         }
1184         void idSetIsLargeCns()
1185         {
1186             assert(!idIsTiny());
1187             _idLargeCns = 1;
1188         }
1189
1190         bool idIsLargeDsp() const
1191         {
1192             assert(!idIsTiny());
1193             return _idLargeDsp != 0;
1194         }
1195         void idSetIsLargeDsp()
1196         {
1197             assert(!idIsTiny());
1198             _idLargeDsp = 1;
1199         }
1200         void idSetIsSmallDsp()
1201         {
1202             assert(!idIsTiny());
1203             _idLargeDsp = 0;
1204         }
1205
1206         bool idIsLargeCall() const
1207         {
1208             assert(!idIsTiny());
1209             return _idLargeCall != 0;
1210         }
1211         void idSetIsLargeCall()
1212         {
1213             assert(!idIsTiny());
1214             _idLargeCall = 1;
1215         }
1216
1217         bool idIsBound() const
1218         {
1219             assert(!idIsTiny());
1220             return _idBound != 0;
1221         }
1222         void idSetIsBound()
1223         {
1224             assert(!idIsTiny());
1225             _idBound = 1;
1226         }
1227
1228         bool idIsCallRegPtr() const
1229         {
1230             assert(!idIsTiny());
1231             return _idCallRegPtr != 0;
1232         }
1233         void idSetIsCallRegPtr()
1234         {
1235             assert(!idIsTiny());
1236             _idCallRegPtr = 1;
1237         }
1238
1239         bool idIsCallAddr() const
1240         {
1241             assert(!idIsTiny());
1242             return _idCallAddr != 0;
1243         }
1244         void idSetIsCallAddr()
1245         {
1246             assert(!idIsTiny());
1247             _idCallAddr = 1;
1248         }
1249
1250         // Only call instructions that call helper functions may be marked as "IsNoGC", indicating
1251         // that a thread executing such a call cannot be stopped for GC.  Thus, in partially-interruptible
1252         // code, it is not necessary to generate GC info for a call so labeled.
1253         bool idIsNoGC() const
1254         {
1255             assert(!idIsTiny());
1256             return _idNoGC != 0;
1257         }
1258         void idSetIsNoGC(bool val)
1259         {
1260             assert(!idIsTiny());
1261             _idNoGC = val;
1262         }
1263
1264 #ifdef _TARGET_ARMARCH_
1265         bool idIsLclVar() const
1266         {
1267             return !idIsTiny() && _idLclVar != 0;
1268         }
1269         void idSetIsLclVar()
1270         {
1271             assert(!idIsTiny());
1272             _idLclVar = 1;
1273         }
1274 #endif // _TARGET_ARMARCH_
1275
1276 #if defined(_TARGET_ARM_)
1277         bool idIsLclFPBase() const
1278         {
1279             return !idIsTiny() && _idLclFPBase != 0;
1280         }
1281         void idSetIsLclFPBase()
1282         {
1283             assert(!idIsTiny());
1284             _idLclFPBase = 1;
1285         }
1286 #endif // defined(_TARGET_ARM_)
1287
1288         bool idIsCnsReloc() const
1289         {
1290             assert(!idIsTiny());
1291             return _idCnsReloc != 0;
1292         }
1293         void idSetIsCnsReloc()
1294         {
1295             assert(!idIsTiny());
1296             _idCnsReloc = 1;
1297         }
1298
1299         bool idIsDspReloc() const
1300         {
1301             assert(!idIsTiny());
1302             return _idDspReloc != 0;
1303         }
1304         void idSetIsDspReloc(bool val = true)
1305         {
1306             assert(!idIsTiny());
1307             _idDspReloc = val;
1308         }
1309         bool idIsReloc()
1310         {
1311             return idIsDspReloc() || idIsCnsReloc();
1312         }
1313
1314         unsigned idSmallCns() const
1315         {
1316             assert(!idIsTiny());
1317             return _idSmallCns;
1318         }
1319         void idSmallCns(size_t value)
1320         {
1321             assert(!idIsTiny());
1322             assert(fitsInSmallCns(value));
1323             _idSmallCns = value;
1324         }
1325
1326         inline const idAddrUnion* idAddr() const
1327         {
1328             assert(!idIsSmallDsc() && !idIsTiny());
1329             return &this->_idAddrUnion;
1330         }
1331
1332         inline idAddrUnion* idAddr()
1333         {
1334             assert(!idIsSmallDsc() && !idIsTiny());
1335             return &this->_idAddrUnion;
1336         }
1337     }; // End of  struct instrDesc
1338
1339     void dispIns(instrDesc* id);
1340
1341     void appendToCurIG(instrDesc* id);
1342
1343     /********************************************************************************************/
1344
1345     struct instrDescJmp : instrDesc
1346     {
1347         instrDescJmp* idjNext; // next jump in the group/method
1348         insGroup*     idjIG;   // containing group
1349
1350         union {
1351             BYTE* idjAddr; // address of jump ins (for patching)
1352         } idjTemp;
1353
1354         unsigned idjOffs : 30;    // Before jump emission, this is the byte offset within IG of the jump instruction.
1355                                   // After emission, for forward jumps, this is the target offset -- in bytes from the
1356                                   // beginning of the function -- of the target instruction of the jump, used to
1357                                   // determine if this jump needs to be patched.
1358         unsigned idjShort : 1;    // is the jump known to be a short  one?
1359         unsigned idjKeepLong : 1; // should the jump be kept long? (used for
1360                                   // hot to cold and cold to hot jumps)
1361     };
1362
1363 #if !defined(_TARGET_ARM64_) // This shouldn't be needed for ARM32, either, but I don't want to touch the ARM32 JIT.
1364     struct instrDescLbl : instrDescJmp
1365     {
1366         emitLclVarAddr dstLclVar;
1367     };
1368 #endif // !_TARGET_ARM64_
1369
1370     struct instrDescCns : instrDesc // large const
1371     {
1372         ssize_t idcCnsVal;
1373     };
1374
1375     struct instrDescDsp : instrDesc // large displacement
1376     {
1377         ssize_t iddDspVal;
1378     };
1379
1380     struct instrDescCnsDsp : instrDesc // large cons + disp
1381     {
1382         ssize_t iddcCnsVal;
1383         int     iddcDspVal;
1384     };
1385
1386     struct instrDescAmd : instrDesc // large addrmode disp
1387     {
1388         ssize_t idaAmdVal;
1389     };
1390
1391     struct instrDescCnsAmd : instrDesc // large cons + addrmode disp
1392     {
1393         ssize_t idacCnsVal;
1394         ssize_t idacAmdVal;
1395     };
1396
1397     struct instrDescCGCA : instrDesc // call with ...
1398     {
1399         VARSET_TP idcGCvars;    // ... updated GC vars or
1400         ssize_t   idcDisp;      // ... big addrmode disp
1401         regMaskTP idcGcrefRegs; // ... gcref registers
1402         regMaskTP idcByrefRegs; // ... byref registers
1403         unsigned  idcArgCnt;    // ... lots of args or (<0 ==> caller pops args)
1404
1405 #if MULTIREG_HAS_SECOND_GC_RET
1406         // This method handle the GC-ness of the second register in a 2 register returned struct on System V.
1407         GCtype idSecondGCref() const
1408         {
1409             return (GCtype)_idcSecondRetRegGCType;
1410         }
1411         void idSecondGCref(GCtype gctype)
1412         {
1413             _idcSecondRetRegGCType = gctype;
1414         }
1415
1416     private:
1417         // This member stores the GC-ness of the second register in a 2 register returned struct on System V.
1418         // It is added to the call struct since it is not needed by the base instrDesc struct, which keeps GC-ness
1419         // of the first register for the instCall nodes.
1420         // The base instrDesc is very carefully kept to be no more than 128 bytes. There is no more space to add members
1421         // for keeping GC-ness of the second return registers. It will also bloat the base struct unnecessarily
1422         // since the GC-ness of the second register is only needed for call instructions.
1423         // The base struct's member keeping the GC-ness of the first return register is _idGCref.
1424         GCtype _idcSecondRetRegGCType : 2; // ... GC type for the second return register.
1425 #endif                                     // MULTIREG_HAS_SECOND_GC_RET
1426     };
1427
1428     struct instrDescArmFP : instrDesc
1429     {
1430         regNumber r1;
1431         regNumber r2;
1432         regNumber r3;
1433     };
1434
1435     insUpdateModes emitInsUpdateMode(instruction ins);
1436     insFormat emitInsModeFormat(instruction ins, insFormat base);
1437
1438     static const BYTE emitInsModeFmtTab[];
1439 #ifdef DEBUG
1440     static const unsigned emitInsModeFmtCnt;
1441 #endif
1442
1443     size_t emitGetInstrDescSize(const instrDesc* id);
1444     size_t emitGetInstrDescSizeSC(const instrDesc* id);
1445
1446     ssize_t emitGetInsCns(instrDesc* id);
1447     ssize_t emitGetInsDsp(instrDesc* id);
1448     ssize_t emitGetInsAmd(instrDesc* id);
1449     ssize_t emitGetInsCnsDsp(instrDesc* id, ssize_t* dspPtr);
1450     ssize_t emitGetInsSC(instrDesc* id);
1451     ssize_t emitGetInsCIdisp(instrDesc* id);
1452     unsigned emitGetInsCIargs(instrDesc* id);
1453
1454     // Return the argument count for a direct call "id".
1455     int emitGetInsCDinfo(instrDesc* id);
1456
1457     unsigned emitInsCount;
1458
1459 /************************************************************************/
1460 /*           A few routines used for debug display purposes             */
1461 /************************************************************************/
1462
1463 #if defined(DEBUG) || EMITTER_STATS
1464
1465     static const char* emitIfName(unsigned f);
1466
1467 #endif // defined(DEBUG) || EMITTER_STATS
1468
1469 #ifdef DEBUG
1470
1471     unsigned emitVarRefOffs;
1472
1473     const char* emitRegName(regNumber reg, emitAttr size = EA_PTRSIZE, bool varName = true);
1474     const char* emitFloatRegName(regNumber reg, emitAttr size = EA_PTRSIZE, bool varName = true);
1475
1476     const char* emitFldName(CORINFO_FIELD_HANDLE fieldVal);
1477     const char* emitFncName(CORINFO_METHOD_HANDLE callVal);
1478
1479     void emitDispIGflags(unsigned flags);
1480     void emitDispIG(insGroup* ig, insGroup* igPrev = nullptr, bool verbose = false);
1481     void emitDispIGlist(bool verbose = false);
1482     void emitDispGCinfo();
1483     void emitDispClsVar(CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, bool reloc = false);
1484     void emitDispFrameRef(int varx, int disp, int offs, bool asmfm);
1485     void emitDispInsOffs(unsigned offs, bool doffs);
1486     void emitDispInsHex(BYTE* code, size_t sz);
1487
1488 #else // !DEBUG
1489 #define emitVarRefOffs 0
1490 #endif // !DEBUG
1491
1492     /************************************************************************/
1493     /*                      Method prolog and epilog                        */
1494     /************************************************************************/
1495
1496     unsigned emitPrologEndPos;
1497
1498     unsigned       emitEpilogCnt;
1499     UNATIVE_OFFSET emitEpilogSize;
1500
1501 #ifdef _TARGET_XARCH_
1502
1503     void           emitStartExitSeq(); // Mark the start of the "return" sequence
1504     emitLocation   emitExitSeqBegLoc;
1505     UNATIVE_OFFSET emitExitSeqSize; // minimum size of any return sequence - the 'ret' after the epilog
1506
1507 #endif // _TARGET_XARCH_
1508
1509     insGroup* emitPlaceholderList; // per method placeholder list - head
1510     insGroup* emitPlaceholderLast; // per method placeholder list - tail
1511
1512 #ifdef JIT32_GCENCODER
1513
1514     // The x86 GC encoder needs to iterate over a list of epilogs to generate a table of
1515     // epilog offsets. Epilogs always start at the beginning of an IG, so save the first
1516     // IG of the epilog, and use it to find the epilog offset at the end of code generation.
1517     struct EpilogList
1518     {
1519         EpilogList*  elNext;
1520         emitLocation elLoc;
1521
1522         EpilogList() : elNext(nullptr), elLoc()
1523         {
1524         }
1525     };
1526
1527     EpilogList* emitEpilogList; // per method epilog list - head
1528     EpilogList* emitEpilogLast; // per method epilog list - tail
1529
1530 public:
1531     void emitStartEpilog();
1532
1533     bool emitHasEpilogEnd();
1534
1535     size_t emitGenEpilogLst(size_t (*fp)(void*, unsigned), void* cp);
1536
1537 #endif // JIT32_GCENCODER
1538
1539     void emitBegPrologEpilog(insGroup* igPh);
1540     void emitEndPrologEpilog();
1541
1542     void emitBegFnEpilog(insGroup* igPh);
1543     void emitEndFnEpilog();
1544
1545 #if FEATURE_EH_FUNCLETS
1546
1547     void emitBegFuncletProlog(insGroup* igPh);
1548     void emitEndFuncletProlog();
1549
1550     void emitBegFuncletEpilog(insGroup* igPh);
1551     void emitEndFuncletEpilog();
1552
1553 #endif // FEATURE_EH_FUNCLETS
1554
1555 /************************************************************************/
1556 /*           Members and methods used in PDB translation                */
1557 /************************************************************************/
1558
1559 #ifdef TRANSLATE_PDB
1560
1561     inline void SetIDSource(instrDesc* pID);
1562     void MapCode(int ilOffset, BYTE* imgDest);
1563     void MapFunc(int                imgOff,
1564                  int                procLen,
1565                  int                dbgStart,
1566                  int                dbgEnd,
1567                  short              frameReg,
1568                  int                stkAdjust,
1569                  int                lvaCount,
1570                  OptJit::LclVarDsc* lvaTable,
1571                  bool               framePtr);
1572
1573 private:
1574     int              emitInstrDescILBase; // code offset of IL that produced this instruction desctriptor
1575     int              emitInstrDescILBase; // code offset of IL that produced this instruction desctriptor
1576     static AddrMap*  emitPDBOffsetTable;  // translation table for mapping IL addresses to native addresses
1577     static LocalMap* emitPDBLocalTable;   // local symbol translation table
1578     static bool      emitIsPDBEnabled;    // flag to disable PDB translation code when a PDB is not found
1579     static BYTE*     emitILBaseOfCode;    // start of IL .text section
1580     static BYTE*     emitILMethodBase;    // beginning of IL method (start of header)
1581     static BYTE*     emitILMethodStart;   // beginning of IL method code (right after the header)
1582     static BYTE*     emitImgBaseOfCode;   // start of the image .text section
1583
1584 #endif
1585
1586     /************************************************************************/
1587     /*    Methods to record a code position and later convert to offset     */
1588     /************************************************************************/
1589
1590     unsigned emitFindInsNum(insGroup* ig, instrDesc* id);
1591     UNATIVE_OFFSET emitFindOffset(insGroup* ig, unsigned insNum);
1592
1593 /************************************************************************/
1594 /*        Members and methods used to issue (encode) instructions.      */
1595 /************************************************************************/
1596
1597 #ifdef DEBUG
1598     // If we have started issuing instructions from the list of instrDesc, this is set
1599     bool emitIssuing;
1600 #endif
1601
1602     BYTE* emitCodeBlock;     // Hot code block
1603     BYTE* emitColdCodeBlock; // Cold code block
1604     BYTE* emitConsBlock;     // Read-only (constant) data block
1605
1606     UNATIVE_OFFSET emitTotalHotCodeSize;
1607     UNATIVE_OFFSET emitTotalColdCodeSize;
1608
1609     UNATIVE_OFFSET emitCurCodeOffs(BYTE* dst)
1610     {
1611         size_t distance;
1612         if ((dst >= emitCodeBlock) && (dst <= (emitCodeBlock + emitTotalHotCodeSize)))
1613         {
1614             distance = (dst - emitCodeBlock);
1615         }
1616         else
1617         {
1618             assert(emitFirstColdIG);
1619             assert(emitColdCodeBlock);
1620             assert((dst >= emitColdCodeBlock) && (dst <= (emitColdCodeBlock + emitTotalColdCodeSize)));
1621
1622             distance = (dst - emitColdCodeBlock + emitTotalHotCodeSize);
1623         }
1624         noway_assert((UNATIVE_OFFSET)distance == distance);
1625         return (UNATIVE_OFFSET)distance;
1626     }
1627
1628     BYTE* emitOffsetToPtr(UNATIVE_OFFSET offset)
1629     {
1630         if (offset < emitTotalHotCodeSize)
1631         {
1632             return emitCodeBlock + offset;
1633         }
1634         else
1635         {
1636             assert(offset < (emitTotalHotCodeSize + emitTotalColdCodeSize));
1637
1638             return emitColdCodeBlock + (offset - emitTotalHotCodeSize);
1639         }
1640     }
1641
1642     BYTE* emitDataOffsetToPtr(UNATIVE_OFFSET offset)
1643     {
1644         assert(offset < emitDataSize());
1645         return emitConsBlock + offset;
1646     }
1647
1648     bool emitJumpCrossHotColdBoundary(size_t srcOffset, size_t dstOffset)
1649     {
1650         if (emitTotalColdCodeSize == 0)
1651         {
1652             return false;
1653         }
1654
1655         assert(srcOffset < (emitTotalHotCodeSize + emitTotalColdCodeSize));
1656         assert(dstOffset < (emitTotalHotCodeSize + emitTotalColdCodeSize));
1657
1658         return ((srcOffset < emitTotalHotCodeSize) != (dstOffset < emitTotalHotCodeSize));
1659     }
1660
1661     unsigned char emitOutputByte(BYTE* dst, ssize_t val);
1662     unsigned char emitOutputWord(BYTE* dst, ssize_t val);
1663     unsigned char emitOutputLong(BYTE* dst, ssize_t val);
1664     unsigned char emitOutputSizeT(BYTE* dst, ssize_t val);
1665
1666 #if !defined(LEGACY_BACKEND) && defined(_TARGET_X86_)
1667     unsigned char emitOutputByte(BYTE* dst, size_t val);
1668     unsigned char emitOutputWord(BYTE* dst, size_t val);
1669     unsigned char emitOutputLong(BYTE* dst, size_t val);
1670     unsigned char emitOutputSizeT(BYTE* dst, size_t val);
1671
1672     unsigned char emitOutputByte(BYTE* dst, unsigned __int64 val);
1673     unsigned char emitOutputWord(BYTE* dst, unsigned __int64 val);
1674     unsigned char emitOutputLong(BYTE* dst, unsigned __int64 val);
1675     unsigned char emitOutputSizeT(BYTE* dst, unsigned __int64 val);
1676 #endif // !defined(LEGACY_BACKEND) && defined(_TARGET_X86_)
1677
1678     size_t emitIssue1Instr(insGroup* ig, instrDesc* id, BYTE** dp);
1679     size_t emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp);
1680
1681     bool emitHasFramePtr;
1682
1683 #ifdef PSEUDORANDOM_NOP_INSERTION
1684     bool emitInInstrumentation;
1685 #endif // PSEUDORANDOM_NOP_INSERTION
1686
1687     unsigned emitMaxTmpSize;
1688
1689 #ifdef LEGACY_BACKEND
1690     unsigned emitLclSize;
1691     unsigned emitGrowableMaxByteOffs;
1692     void emitTmpSizeChanged(unsigned tmpSize);
1693 #ifdef DEBUG
1694     unsigned emitMaxByteOffsIdNum;
1695 #endif // DEBUG
1696 #endif // LEGACY_BACKEND
1697
1698 #ifdef DEBUG
1699     bool emitChkAlign; // perform some alignment checks
1700 #endif
1701
1702     insGroup* emitCurIG;
1703
1704     void emitSetShortJump(instrDescJmp* id);
1705     void emitSetMediumJump(instrDescJmp* id);
1706     UNATIVE_OFFSET emitSizeOfJump(instrDescJmp* jmp);
1707     UNATIVE_OFFSET emitInstCodeSz(instrDesc* id);
1708
1709 #ifndef LEGACY_BACKEND
1710     CORINFO_FIELD_HANDLE emitLiteralConst(ssize_t cnsValIn, emitAttr attr = EA_8BYTE);
1711     CORINFO_FIELD_HANDLE emitFltOrDblConst(GenTreeDblCon* tree, emitAttr attr = EA_UNKNOWN);
1712     regNumber emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src);
1713     regNumber emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2);
1714     void emitInsMov(instruction ins, emitAttr attr, GenTree* node);
1715     insFormat emitMapFmtForIns(insFormat fmt, instruction ins);
1716     insFormat emitMapFmtAtoM(insFormat fmt);
1717     void emitHandleMemOp(GenTreeIndir* indir, instrDesc* id, insFormat fmt, instruction ins);
1718     void spillIntArgRegsToShadowSlots();
1719 #endif // !LEGACY_BACKEND
1720
1721 /************************************************************************/
1722 /*      The logic that creates and keeps track of instruction groups    */
1723 /************************************************************************/
1724
1725 #ifdef _TARGET_ARM_
1726 // The only place where this limited instruction group size is a problem is
1727 // in the prolog, where we only support a single instruction group. We should really fix that.
1728 // ARM can require a bigger prolog instruction group. One scenario is where a
1729 // function uses all the incoming integer and single-precision floating-point arguments,
1730 // and must store them all to the frame on entry. If the frame is very large, we generate
1731 // ugly code like "movw r10, 0x488; add r10, sp; vstr s0, [r10]" for each store, which
1732 // eats up our insGroup buffer.
1733 #define SC_IG_BUFFER_SIZE (100 * sizeof(instrDesc) + 14 * TINY_IDSC_SIZE)
1734 #else // !_TARGET_ARM_
1735 #define SC_IG_BUFFER_SIZE (50 * sizeof(instrDesc) + 14 * TINY_IDSC_SIZE)
1736 #endif // !_TARGET_ARM_
1737
1738     size_t emitIGbuffSize;
1739
1740     insGroup* emitIGlist; // first  instruction group
1741     insGroup* emitIGlast; // last   instruction group
1742     insGroup* emitIGthis; // issued instruction group
1743
1744     insGroup* emitPrologIG; // prolog instruction group
1745
1746     instrDescJmp* emitJumpList;       // list of local jumps in method
1747     instrDescJmp* emitJumpLast;       // last of local jumps in method
1748     void          emitJumpDistBind(); // Bind all the local jumps in method
1749
1750     void emitCheckFuncletBranch(instrDesc* jmp, insGroup* jmpIG); // Check for illegal branches between funclets
1751
1752     bool emitFwdJumps;   // forward jumps present?
1753     bool emitNoGCIG;     // Are we generating IGF_NOGCINTERRUPT insGroups (for prologs, epilogs, etc.)
1754     bool emitForceNewIG; // If we generate an instruction, and not another instruction group, force create a new emitAdd
1755                          // instruction group.
1756
1757     BYTE* emitCurIGfreeNext; // next available byte in buffer
1758     BYTE* emitCurIGfreeEndp; // one byte past the last available byte in buffer
1759     BYTE* emitCurIGfreeBase; // first byte address
1760
1761     unsigned       emitCurIGinsCnt;   // # of collected instr's in buffer
1762     unsigned       emitCurIGsize;     // estimated code size of current group in bytes
1763     UNATIVE_OFFSET emitCurCodeOffset; // current code offset within group
1764     UNATIVE_OFFSET emitTotalCodeSize; // bytes of code in entire method
1765
1766     insGroup* emitFirstColdIG; // first cold instruction group
1767
1768     void emitSetFirstColdIGCookie(void* bbEmitCookie)
1769     {
1770         emitFirstColdIG = (insGroup*)bbEmitCookie;
1771     }
1772
1773     int emitOffsAdj; // current code offset adjustment
1774
1775     instrDescJmp* emitCurIGjmpList; // list of jumps   in current IG
1776
1777     // emitPrev* and emitInit* are only used during code generation, not during
1778     // emission (issuing), to determine what GC values to store into an IG.
1779     // Note that only the Vars ones are actually used, apparently due to bugs
1780     // in that tracking. See emitSavIG(): the important use of ByrefRegs is commented
1781     // out, and GCrefRegs is always saved.
1782
1783     VARSET_TP emitPrevGCrefVars;
1784     regMaskTP emitPrevGCrefRegs;
1785     regMaskTP emitPrevByrefRegs;
1786
1787     VARSET_TP emitInitGCrefVars;
1788     regMaskTP emitInitGCrefRegs;
1789     regMaskTP emitInitByrefRegs;
1790
1791     // If this is set, we ignore comparing emitPrev* and emitInit* to determine
1792     // whether to save GC state (to save space in the IG), and always save it.
1793
1794     bool emitForceStoreGCState;
1795
1796     // emitThis* variables are used during emission, to track GC updates
1797     // on a per-instruction basis. During code generation, per-instruction
1798     // tracking is done with variables gcVarPtrSetCur, gcRegGCrefSetCur,
1799     // and gcRegByrefSetCur. However, these are also used for a slightly
1800     // different purpose during code generation: to try to minimize the
1801     // amount of GC data stored to an IG, by only storing deltas from what
1802     // we expect to see at an IG boundary. Also, only emitThisGCrefVars is
1803     // really the only one used; the others seem to be calculated, but not
1804     // used due to bugs.
1805
1806     VARSET_TP emitThisGCrefVars;
1807     regMaskTP emitThisGCrefRegs; // Current set of registers holding GC references
1808     regMaskTP emitThisByrefRegs; // Current set of registers holding BYREF references
1809
1810     bool emitThisGCrefVset; // Is "emitThisGCrefVars" up to date?
1811
1812     regNumber emitSyncThisObjReg; // where is "this" enregistered for synchronized methods?
1813
1814 #if MULTIREG_HAS_SECOND_GC_RET
1815     void emitSetSecondRetRegGCType(instrDescCGCA* id, emitAttr secondRetSize);
1816 #endif // MULTIREG_HAS_SECOND_GC_RET
1817
1818     static void emitEncodeCallGCregs(regMaskTP regs, instrDesc* id);
1819     static unsigned emitDecodeCallGCregs(instrDesc* id);
1820
1821     unsigned emitNxtIGnum;
1822
1823     // random nop insertion to break up nop sleds
1824     unsigned emitNextNop;
1825     bool     emitRandomNops;
1826     void     emitEnableRandomNops()
1827     {
1828         emitRandomNops = true;
1829     }
1830     void emitDisableRandomNops()
1831     {
1832         emitRandomNops = false;
1833     }
1834
1835     insGroup* emitAllocAndLinkIG();
1836     insGroup* emitAllocIG();
1837     void emitInitIG(insGroup* ig);
1838     void emitInsertIGAfter(insGroup* insertAfterIG, insGroup* ig);
1839
1840     void emitNewIG();
1841
1842 #if !defined(JIT32_GCENCODER)
1843     void emitDisableGC();
1844     void emitEnableGC();
1845 #endif // !defined(JIT32_GCENCODER)
1846
1847     void emitGenIG(insGroup* ig);
1848     insGroup* emitSavIG(bool emitAdd = false);
1849     void emitNxtIG(bool emitAdd = false);
1850
1851     bool emitCurIGnonEmpty()
1852     {
1853         return (emitCurIG && emitCurIGfreeNext > emitCurIGfreeBase);
1854     }
1855
1856     instrDesc* emitLastIns;
1857
1858 #ifdef DEBUG
1859     void emitCheckIGoffsets();
1860 #endif
1861
1862     // Terminates any in-progress instruction group, making the current IG a new empty one.
1863     // Mark this instruction group as having a label; return the the new instruction group.
1864     // Sets the emitter's record of the currently live GC variables
1865     // and registers.  The "isFinallyTarget" parameter indicates that the current location is
1866     // the start of a basic block that is returned to after a finally clause in non-exceptional execution.
1867     void* emitAddLabel(VARSET_VALARG_TP GCvars, regMaskTP gcrefRegs, regMaskTP byrefRegs, BOOL isFinallyTarget = FALSE);
1868
1869 #ifdef _TARGET_ARMARCH_
1870
1871     void emitGetInstrDescs(insGroup* ig, instrDesc** id, int* insCnt);
1872
1873     bool emitGetLocationInfo(emitLocation* emitLoc, insGroup** pig, instrDesc** pid, int* pinsRemaining = NULL);
1874
1875     bool emitNextID(insGroup*& ig, instrDesc*& id, int& insRemaining);
1876
1877     typedef void (*emitProcessInstrFunc_t)(instrDesc* id, void* context);
1878
1879     void emitWalkIDs(emitLocation* locFrom, emitProcessInstrFunc_t processFunc, void* context);
1880
1881     static void emitGenerateUnwindNop(instrDesc* id, void* context);
1882
1883 #endif // _TARGET_ARMARCH_
1884
1885 #if defined(_TARGET_ARM_)
1886     emitter::insFormat emitInsFormat(instruction ins);
1887     size_t emitInsCode(instruction ins, insFormat fmt);
1888 #endif
1889
1890 #ifdef _TARGET_X86_
1891     void emitMarkStackLvl(unsigned stackLevel);
1892 #endif
1893
1894     int emitNextRandomNop();
1895
1896     void* emitAllocInstr(size_t sz, emitAttr attr);
1897
1898     instrDesc* emitAllocInstr(emitAttr attr)
1899     {
1900         return (instrDesc*)emitAllocInstr(sizeof(instrDesc), attr);
1901     }
1902
1903     instrDescJmp* emitAllocInstrJmp()
1904     {
1905         return (instrDescJmp*)emitAllocInstr(sizeof(instrDescJmp), EA_1BYTE);
1906     }
1907
1908 #if !defined(_TARGET_ARM64_)
1909     instrDescLbl* emitAllocInstrLbl()
1910     {
1911         return (instrDescLbl*)emitAllocInstr(sizeof(instrDescLbl), EA_4BYTE);
1912     }
1913 #endif // !_TARGET_ARM64_
1914
1915     instrDescCns* emitAllocInstrCns(emitAttr attr)
1916     {
1917         return (instrDescCns*)emitAllocInstr(sizeof(instrDescCns), attr);
1918     }
1919     instrDescCns* emitAllocInstrCns(emitAttr attr, int cns)
1920     {
1921         instrDescCns* result = (instrDescCns*)emitAllocInstr(sizeof(instrDescCns), attr);
1922         result->idSetIsLargeCns();
1923         result->idcCnsVal = cns;
1924         return result;
1925     }
1926
1927     instrDescDsp* emitAllocInstrDsp(emitAttr attr)
1928     {
1929         return (instrDescDsp*)emitAllocInstr(sizeof(instrDescDsp), attr);
1930     }
1931
1932     instrDescCnsDsp* emitAllocInstrCnsDsp(emitAttr attr)
1933     {
1934         return (instrDescCnsDsp*)emitAllocInstr(sizeof(instrDescCnsDsp), attr);
1935     }
1936
1937     instrDescAmd* emitAllocInstrAmd(emitAttr attr)
1938     {
1939         return (instrDescAmd*)emitAllocInstr(sizeof(instrDescAmd), attr);
1940     }
1941
1942     instrDescCnsAmd* emitAllocInstrCnsAmd(emitAttr attr)
1943     {
1944         return (instrDescCnsAmd*)emitAllocInstr(sizeof(instrDescCnsAmd), attr);
1945     }
1946
1947     instrDescCGCA* emitAllocInstrCGCA(emitAttr attr)
1948     {
1949         return (instrDescCGCA*)emitAllocInstr(sizeof(instrDescCGCA), attr);
1950     }
1951
1952     instrDesc* emitNewInstrTiny(emitAttr attr);
1953     instrDesc* emitNewInstrSmall(emitAttr attr);
1954     instrDesc* emitNewInstr(emitAttr attr = EA_4BYTE);
1955     instrDesc* emitNewInstrSC(emitAttr attr, ssize_t cns);
1956     instrDesc* emitNewInstrCns(emitAttr attr, ssize_t cns);
1957     instrDesc* emitNewInstrDsp(emitAttr attr, ssize_t dsp);
1958     instrDesc* emitNewInstrCnsDsp(emitAttr attr, ssize_t cns, int dsp);
1959     instrDescJmp* emitNewInstrJmp();
1960
1961 #if !defined(_TARGET_ARM64_)
1962     instrDescLbl* emitNewInstrLbl();
1963 #endif // !_TARGET_ARM64_
1964
1965     static const BYTE emitFmtToOps[];
1966
1967 #ifdef DEBUG
1968     static const unsigned emitFmtCount;
1969 #endif
1970
1971     bool emitIsTinyInsDsc(instrDesc* id);
1972     bool emitIsScnsInsDsc(instrDesc* id);
1973
1974     size_t emitSizeOfInsDsc(instrDesc* id);
1975
1976     /************************************************************************/
1977     /*        The following keeps track of stack-based GC values            */
1978     /************************************************************************/
1979
1980     unsigned emitTrkVarCnt;
1981     int*     emitGCrFrameOffsTab; // Offsets of tracked stack ptr vars (varTrkIndex -> stkOffs)
1982
1983     unsigned    emitGCrFrameOffsCnt; // Number of       tracked stack ptr vars
1984     int         emitGCrFrameOffsMin; // Min offset of a tracked stack ptr var
1985     int         emitGCrFrameOffsMax; // Max offset of a tracked stack ptr var
1986     bool        emitContTrkPtrLcls;  // All lcl between emitGCrFrameOffsMin/Max are only tracked stack ptr vars
1987     varPtrDsc** emitGCrFrameLiveTab; // Cache of currently live varPtrs (stkOffs -> varPtrDsc)
1988
1989     int emitArgFrameOffsMin;
1990     int emitArgFrameOffsMax;
1991
1992     int emitLclFrameOffsMin;
1993     int emitLclFrameOffsMax;
1994
1995     int emitSyncThisObjOffs; // what is the offset of "this" for synchronized methods?
1996
1997 public:
1998     void emitSetFrameRangeGCRs(int offsLo, int offsHi);
1999     void emitSetFrameRangeLcls(int offsLo, int offsHi);
2000     void emitSetFrameRangeArgs(int offsLo, int offsHi);
2001
2002     static instruction emitJumpKindToIns(emitJumpKind jumpKind);
2003     static emitJumpKind emitInsToJumpKind(instruction ins);
2004     static emitJumpKind emitReverseJumpKind(emitJumpKind jumpKind);
2005
2006 #ifdef _TARGET_ARM_
2007     static unsigned emitJumpKindCondCode(emitJumpKind jumpKind);
2008 #endif
2009
2010 #ifdef DEBUG
2011     void emitInsSanityCheck(instrDesc* id);
2012 #endif
2013
2014 #ifdef _TARGET_ARMARCH_
2015     // Returns true if instruction "id->idIns()" writes to a register that might be used to contain a GC
2016     // pointer. This exempts the SP and PC registers, and floating point registers. Memory access
2017     // instructions that pre- or post-increment their memory address registers are *not* considered to write
2018     // to GC registers, even if that memory address is a by-ref: such an instruction cannot change the GC
2019     // status of that register, since it must be a byref before and remains one after.
2020     //
2021     // This may return false positives.
2022     bool emitInsMayWriteToGCReg(instrDesc* id);
2023
2024     // Returns "true" if instruction "id->idIns()" writes to a LclVar stack location.
2025     bool emitInsWritesToLclVarStackLoc(instrDesc* id);
2026
2027     // Returns true if the instruction may write to more than one register.
2028     bool emitInsMayWriteMultipleRegs(instrDesc* id);
2029
2030     // Returns "true" if instruction "id->idIns()" writes to a LclVar stack slot pair.
2031     bool emitInsWritesToLclVarStackLocPair(instrDesc* id);
2032 #endif // _TARGET_ARMARCH_
2033
2034     /************************************************************************/
2035     /*    The following is used to distinguish helper vs non-helper calls   */
2036     /************************************************************************/
2037
2038     static bool emitNoGChelper(unsigned IHX);
2039
2040     /************************************************************************/
2041     /*         The following logic keeps track of live GC ref values        */
2042     /************************************************************************/
2043
2044     bool emitFullArgInfo; // full arg info (including non-ptr arg)?
2045     bool emitFullGCinfo;  // full GC pointer maps?
2046     bool emitFullyInt;    // fully interruptible code?
2047
2048 #if EMIT_TRACK_STACK_DEPTH
2049     unsigned emitCntStackDepth; // 0 in prolog/epilog, One DWORD elsewhere
2050     unsigned emitMaxStackDepth; // actual computed max. stack depth
2051 #endif
2052
2053     /* Stack modelling wrt GC */
2054
2055     bool emitSimpleStkUsed; // using the "simple" stack table?
2056
2057     union {
2058         struct // if emitSimpleStkUsed==true
2059         {
2060 #define BITS_IN_BYTE (8)
2061 #define MAX_SIMPLE_STK_DEPTH (BITS_IN_BYTE * sizeof(unsigned))
2062
2063             unsigned emitSimpleStkMask;      // bit per pushed dword (if it fits. Lowest bit <==> last pushed arg)
2064             unsigned emitSimpleByrefStkMask; // byref qualifier for emitSimpleStkMask
2065         } u1;
2066
2067         struct // if emitSimpleStkUsed==false
2068         {
2069             BYTE   emitArgTrackLcl[16]; // small local table to avoid malloc
2070             BYTE*  emitArgTrackTab;     // base of the argument tracking stack
2071             BYTE*  emitArgTrackTop;     // top  of the argument tracking stack
2072             USHORT emitGcArgTrackCnt;   // count of pending arg records (stk-depth for frameless methods, gc ptrs on stk
2073                                         // for framed methods)
2074         } u2;
2075     };
2076
2077     unsigned emitCurStackLvl; // amount of bytes pushed on stack
2078
2079 #if EMIT_TRACK_STACK_DEPTH
2080     /* Functions for stack tracking */
2081
2082     void emitStackPush(BYTE* addr, GCtype gcType);
2083
2084     void emitStackPushN(BYTE* addr, unsigned count);
2085
2086     void emitStackPop(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count = 1);
2087
2088     void emitStackKillArgs(BYTE* addr, unsigned count, unsigned char callInstrSize);
2089
2090     void emitRecordGCcall(BYTE* codePos, unsigned char callInstrSize);
2091
2092     // Helpers for the above
2093
2094     void emitStackPushLargeStk(BYTE* addr, GCtype gcType, unsigned count = 1);
2095     void emitStackPopLargeStk(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count = 1);
2096 #endif // EMIT_TRACK_STACK_DEPTH
2097
2098     /* Liveness of stack variables, and registers */
2099
2100     void emitUpdateLiveGCvars(int offs, BYTE* addr, bool birth);
2101     void emitUpdateLiveGCvars(VARSET_VALARG_TP vars, BYTE* addr);
2102     void emitUpdateLiveGCregs(GCtype gcType, regMaskTP regs, BYTE* addr);
2103
2104 #ifdef DEBUG
2105     const char* emitGetFrameReg();
2106     void emitDispRegSet(regMaskTP regs);
2107     void emitDispVarSet();
2108 #endif
2109
2110     void emitGCregLiveUpd(GCtype gcType, regNumber reg, BYTE* addr);
2111     void emitGCregLiveSet(GCtype gcType, regMaskTP mask, BYTE* addr, bool isThis);
2112     void emitGCregDeadUpdMask(regMaskTP, BYTE* addr);
2113     void emitGCregDeadUpd(regNumber reg, BYTE* addr);
2114     void emitGCregDeadSet(GCtype gcType, regMaskTP mask, BYTE* addr);
2115
2116     void emitGCvarLiveUpd(int offs, int varNum, GCtype gcType, BYTE* addr);
2117     void emitGCvarLiveSet(int offs, GCtype gcType, BYTE* addr, ssize_t disp = -1);
2118     void emitGCvarDeadUpd(int offs, BYTE* addr);
2119     void emitGCvarDeadSet(int offs, BYTE* addr, ssize_t disp = -1);
2120
2121     GCtype emitRegGCtype(regNumber reg);
2122
2123     // We have a mixture of code emission methods, some of which return the size of the emitted instruction,
2124     // requiring the caller to add this to the current code pointer (dst += <call to emit code>), others of which
2125     // return the updated code pointer (dst = <call to emit code>).  Sometimes we'd like to get the size of
2126     // the generated instruction for the latter style.  This method accomplishes that --
2127     // "emitCodeWithInstructionSize(dst, <call to emitCode>, &instrSize)" will do the call, and set
2128     // "*instrSize" to the after-before code pointer difference.  Returns the result of the call.  (And
2129     // asserts that the instruction size fits in an unsigned char.)
2130     static BYTE* emitCodeWithInstructionSize(BYTE* codePtrBefore, BYTE* newCodePointer, unsigned char* instrSize);
2131
2132     /************************************************************************/
2133     /*      The following logic keeps track of initialized data sections    */
2134     /************************************************************************/
2135
2136     /* One of these is allocated for every blob of initialized data */
2137
2138     struct dataSection
2139     {
2140         enum sectionType
2141         {
2142             data,
2143             blockAbsoluteAddr,
2144             blockRelative32
2145         };
2146
2147         dataSection*   dsNext;
2148         UNATIVE_OFFSET dsSize;
2149         sectionType    dsType;
2150         // variable-sized array used to store the constant data
2151         // or BasicBlock* array in the block cases.
2152         BYTE dsCont[0];
2153     };
2154
2155     /* These describe the entire initialized/uninitialized data sections */
2156
2157     struct dataSecDsc
2158     {
2159         dataSection*   dsdList;
2160         dataSection*   dsdLast;
2161         UNATIVE_OFFSET dsdOffs;
2162     };
2163
2164     dataSecDsc emitConsDsc;
2165
2166     dataSection* emitDataSecCur;
2167
2168     void emitOutputDataSec(dataSecDsc* sec, BYTE* dst);
2169
2170     /************************************************************************/
2171     /*              Handles to the current class and method.                */
2172     /************************************************************************/
2173
2174     COMP_HANDLE emitCmpHandle;
2175
2176     /************************************************************************/
2177     /*               Helpers for interface to EE                            */
2178     /************************************************************************/
2179
2180     void emitRecordRelocation(void* location,       /* IN */
2181                               void* target,         /* IN */
2182                               WORD  fRelocType,     /* IN */
2183                               WORD  slotNum   = 0,  /* IN */
2184                               INT32 addlDelta = 0); /* IN */
2185
2186 #ifdef _TARGET_ARM_
2187     void emitHandlePCRelativeMov32(void* location, /* IN */
2188                                    void* target);  /* IN */
2189 #endif
2190
2191     void emitRecordCallSite(ULONG                 instrOffset,   /* IN */
2192                             CORINFO_SIG_INFO*     callSig,       /* IN */
2193                             CORINFO_METHOD_HANDLE methodHandle); /* IN */
2194
2195 #ifdef DEBUG
2196     // This is a scratch buffer used to minimize the number of sig info structs
2197     // we have to allocate for recordCallSite.
2198     CORINFO_SIG_INFO* emitScratchSigInfo;
2199 #endif // DEBUG
2200
2201 /************************************************************************/
2202 /*               Logic to collect and display statistics                */
2203 /************************************************************************/
2204
2205 #if EMITTER_STATS
2206
2207     friend void emitterStats(FILE* fout);
2208     friend void emitterStaticStats(FILE* fout);
2209
2210     static size_t emitSizeMethod;
2211
2212     static unsigned emitTotalInsCnt;
2213
2214     static unsigned emitTotalIGcnt;   // total number of insGroup allocated
2215     static unsigned emitTotalPhIGcnt; // total number of insPlaceholderGroupData allocated
2216     static unsigned emitTotalIGicnt;
2217     static size_t   emitTotalIGsize;
2218     static unsigned emitTotalIGmcnt; // total method count
2219     static unsigned emitTotalIGjmps;
2220     static unsigned emitTotalIGptrs;
2221
2222     static size_t emitTotMemAlloc;
2223
2224     static unsigned emitSmallDspCnt;
2225     static unsigned emitLargeDspCnt;
2226
2227     static unsigned emitSmallCnsCnt;
2228 #define SMALL_CNS_TSZ 256
2229     static unsigned emitSmallCns[SMALL_CNS_TSZ];
2230     static unsigned emitLargeCnsCnt;
2231
2232     static unsigned emitIFcounts[IF_COUNT];
2233
2234 #endif // EMITTER_STATS
2235
2236 /*************************************************************************
2237  *
2238  *  Define any target-dependent emitter members.
2239  */
2240
2241 #include "emitdef.h"
2242
2243     // It would be better if this were a constructor, but that would entail revamping the allocation
2244     // infrastructure of the entire JIT...
2245     void Init()
2246     {
2247         VarSetOps::AssignNoCopy(emitComp, emitPrevGCrefVars, VarSetOps::MakeEmpty(emitComp));
2248         VarSetOps::AssignNoCopy(emitComp, emitInitGCrefVars, VarSetOps::MakeEmpty(emitComp));
2249         VarSetOps::AssignNoCopy(emitComp, emitThisGCrefVars, VarSetOps::MakeEmpty(emitComp));
2250     }
2251 };
2252
2253 /*****************************************************************************
2254  *
2255  *  Define any target-dependent inlines.
2256  */
2257
2258 #include "emitinl.h"
2259
2260 inline void emitter::instrDesc::checkSizes()
2261 {
2262 #ifdef DEBUG
2263 #if HAS_TINY_DESC
2264     C_ASSERT(TINY_IDSC_SIZE == (offsetof(instrDesc, _idDebugOnlyInfo) + sizeof(instrDescDebugInfo*)));
2265 #else // !tiny
2266     C_ASSERT(SMALL_IDSC_SIZE == (offsetof(instrDesc, _idDebugOnlyInfo) + sizeof(instrDescDebugInfo*)));
2267 #endif
2268 #endif
2269     C_ASSERT(SMALL_IDSC_SIZE == offsetof(instrDesc, _idAddrUnion));
2270 }
2271
2272 /*****************************************************************************
2273  *
2274  *  Returns true if the given instruction descriptor is a "tiny" or a "small
2275  *  constant" one (i.e. one of the descriptors that don't have all instrDesc
2276  *  fields allocated).
2277  */
2278
2279 inline bool emitter::emitIsTinyInsDsc(instrDesc* id)
2280 {
2281     return id->idIsTiny();
2282 }
2283
2284 inline bool emitter::emitIsScnsInsDsc(instrDesc* id)
2285 {
2286     return id->idIsSmallDsc();
2287 }
2288
2289 /*****************************************************************************
2290  *
2291  *  Given an instruction, return its "update mode" (RD/WR/RW).
2292  */
2293
2294 inline insUpdateModes emitter::emitInsUpdateMode(instruction ins)
2295 {
2296 #ifdef DEBUG
2297     assert((unsigned)ins < emitInsModeFmtCnt);
2298 #endif
2299     return (insUpdateModes)emitInsModeFmtTab[ins];
2300 }
2301
2302 /*****************************************************************************
2303  *
2304  *  Return the number of epilog blocks generated so far.
2305  */
2306
2307 inline unsigned emitter::emitGetEpilogCnt()
2308 {
2309     return emitEpilogCnt;
2310 }
2311
2312 /*****************************************************************************
2313  *
2314  *  Return the current size of the specified data section.
2315  */
2316
2317 inline UNATIVE_OFFSET emitter::emitDataSize()
2318 {
2319     return emitConsDsc.dsdOffs;
2320 }
2321
2322 /*****************************************************************************
2323  *
2324  *  Return a handle to the current position in the output stream. This can
2325  *  be later converted to an actual code offset in bytes.
2326  */
2327
2328 inline void* emitter::emitCurBlock()
2329 {
2330     return emitCurIG;
2331 }
2332
2333 /*****************************************************************************
2334  *
2335  *  The emitCurOffset() method returns a cookie that identifies the current
2336  *  position in the instruction stream. Due to things like scheduling (and
2337  *  the fact that the final size of some instructions cannot be known until
2338  *  the end of code generation), we return a value with the instruction number
2339  *  and its estimated offset to the caller.
2340  */
2341
2342 inline unsigned emitGetInsNumFromCodePos(unsigned codePos)
2343 {
2344     return (codePos & 0xFFFF);
2345 }
2346
2347 inline unsigned emitGetInsOfsFromCodePos(unsigned codePos)
2348 {
2349     return (codePos >> 16);
2350 }
2351
2352 inline unsigned emitter::emitCurOffset()
2353 {
2354     unsigned codePos = emitCurIGinsCnt + (emitCurIGsize << 16);
2355
2356     assert(emitGetInsOfsFromCodePos(codePos) == emitCurIGsize);
2357     assert(emitGetInsNumFromCodePos(codePos) == emitCurIGinsCnt);
2358
2359     // printf("[IG=%02u;ID=%03u;OF=%04X] => %08X\n", emitCurIG->igNum, emitCurIGinsCnt, emitCurIGsize, codePos);
2360
2361     return codePos;
2362 }
2363
2364 extern const unsigned short emitTypeSizes[TYP_COUNT];
2365
2366 template <class T>
2367 inline emitAttr emitTypeSize(T type)
2368 {
2369     assert(TypeGet(type) < TYP_COUNT);
2370     assert(emitTypeSizes[TypeGet(type)] > 0);
2371     return (emitAttr)emitTypeSizes[TypeGet(type)];
2372 }
2373
2374 extern const unsigned short emitTypeActSz[TYP_COUNT];
2375
2376 inline emitAttr emitActualTypeSize(var_types type)
2377 {
2378     assert(type < TYP_COUNT);
2379     assert(emitTypeActSz[type] > 0);
2380     return (emitAttr)emitTypeActSz[type];
2381 }
2382
2383 /*****************************************************************************
2384  *
2385  *  Convert between an operand size in bytes and a smaller encoding used for
2386  *  storage in instruction descriptors.
2387  */
2388
2389 /* static */ inline emitter::opSize emitter::emitEncodeSize(emitAttr size)
2390 {
2391     assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE ||
2392            size == EA_32BYTE);
2393
2394     return emitSizeEncode[((int)size) - 1];
2395 }
2396
2397 /* static */ inline emitAttr emitter::emitDecodeSize(emitter::opSize ensz)
2398 {
2399     assert(((unsigned)ensz) < OPSZ_COUNT);
2400
2401     return emitSizeDecode[ensz];
2402 }
2403
2404 /*****************************************************************************
2405  *
2406  *  Little helpers to allocate various flavors of instructions.
2407  */
2408
2409 inline emitter::instrDesc* emitter::emitNewInstrTiny(emitAttr attr)
2410 {
2411     instrDesc* id;
2412
2413     id = (instrDesc*)emitAllocInstr(TINY_IDSC_SIZE, attr);
2414     id->idSetIsTiny();
2415
2416     return id;
2417 }
2418
2419 inline emitter::instrDesc* emitter::emitNewInstrSmall(emitAttr attr)
2420 {
2421     instrDesc* id;
2422
2423     // This is larger than the Tiny Descr
2424     id = (instrDesc*)emitAllocInstr(SMALL_IDSC_SIZE, attr);
2425     id->idSetIsSmallDsc();
2426
2427     return id;
2428 }
2429
2430 inline emitter::instrDesc* emitter::emitNewInstr(emitAttr attr)
2431 {
2432     // This is larger than the Small Descr
2433     return emitAllocInstr(attr);
2434 }
2435
2436 inline emitter::instrDescJmp* emitter::emitNewInstrJmp()
2437 {
2438     return emitAllocInstrJmp();
2439 }
2440
2441 #if !defined(_TARGET_ARM64_)
2442 inline emitter::instrDescLbl* emitter::emitNewInstrLbl()
2443 {
2444     return emitAllocInstrLbl();
2445 }
2446 #endif // !_TARGET_ARM64_
2447
2448 inline emitter::instrDesc* emitter::emitNewInstrDsp(emitAttr attr, ssize_t dsp)
2449 {
2450     if (dsp == 0)
2451     {
2452         instrDesc* id = emitAllocInstr(attr);
2453
2454 #if EMITTER_STATS
2455         emitSmallDspCnt++;
2456 #endif
2457
2458         return id;
2459     }
2460     else
2461     {
2462         instrDescDsp* id = emitAllocInstrDsp(attr);
2463
2464         id->idSetIsLargeDsp();
2465         id->iddDspVal = dsp;
2466
2467 #if EMITTER_STATS
2468         emitLargeDspCnt++;
2469 #endif
2470
2471         return id;
2472     }
2473 }
2474
2475 /*****************************************************************************
2476  *
2477  *  Allocate an instruction descriptor for an instruction with a constant operand.
2478  *  The instruction descriptor uses the idAddrUnion to save additional info
2479  *  so the smallest size that this can be is sizeof(instrDesc).
2480  *  Note that this very similar to emitter::emitNewInstrSC(), except it never
2481  *  allocates a small descriptor.
2482  */
2483 inline emitter::instrDesc* emitter::emitNewInstrCns(emitAttr attr, ssize_t cns)
2484 {
2485     if (instrDesc::fitsInSmallCns(cns))
2486     {
2487         instrDesc* id = emitAllocInstr(attr);
2488
2489         id->idSmallCns(cns);
2490
2491 #if EMITTER_STATS
2492         emitSmallCnsCnt++;
2493         if (cns - ID_MIN_SMALL_CNS >= SMALL_CNS_TSZ)
2494             emitSmallCns[SMALL_CNS_TSZ - 1]++;
2495         else
2496             emitSmallCns[cns - ID_MIN_SMALL_CNS]++;
2497 #endif
2498
2499         return id;
2500     }
2501     else
2502     {
2503         instrDescCns* id = emitAllocInstrCns(attr);
2504
2505         id->idSetIsLargeCns();
2506         id->idcCnsVal = cns;
2507
2508 #if EMITTER_STATS
2509         emitLargeCnsCnt++;
2510 #endif
2511
2512         return id;
2513     }
2514 }
2515
2516 /*****************************************************************************
2517  *
2518  *  Get the instrDesc size, general purpose version
2519  *
2520  */
2521
2522 inline size_t emitter::emitGetInstrDescSize(const instrDesc* id)
2523 {
2524     if (id->idIsTiny())
2525     {
2526         return TINY_IDSC_SIZE;
2527     }
2528
2529     if (id->idIsSmallDsc())
2530     {
2531         return SMALL_IDSC_SIZE;
2532     }
2533
2534     if (id->idIsLargeCns())
2535     {
2536         return sizeof(instrDescCns);
2537     }
2538
2539     return sizeof(instrDesc);
2540 }
2541
2542 /*****************************************************************************
2543  *
2544  *  Allocate an instruction descriptor for an instruction with a small integer
2545  *  constant operand. This is the same as emitNewInstrCns() except that here
2546  *  any constant that is small enough for instrDesc::fitsInSmallCns() only gets
2547  *  allocated SMALL_IDSC_SIZE bytes (and is thus a small descriptor, whereas
2548  *  emitNewInstrCns() always allocates at least sizeof(instrDesc).
2549  */
2550
2551 inline emitter::instrDesc* emitter::emitNewInstrSC(emitAttr attr, ssize_t cns)
2552 {
2553     instrDesc* id;
2554
2555     if (instrDesc::fitsInSmallCns(cns))
2556     {
2557         id = (instrDesc*)emitAllocInstr(SMALL_IDSC_SIZE, attr);
2558
2559         id->idSmallCns(cns);
2560         id->idSetIsSmallDsc();
2561     }
2562     else
2563     {
2564         id = (instrDesc*)emitAllocInstr(sizeof(instrDescCns), attr);
2565
2566         id->idSetIsLargeCns();
2567         ((instrDescCns*)id)->idcCnsVal = cns;
2568     }
2569
2570     return id;
2571 }
2572
2573 /*****************************************************************************
2574  *
2575  *  Get the instrDesc size for something that contains a constant
2576  */
2577
2578 inline size_t emitter::emitGetInstrDescSizeSC(const instrDesc* id)
2579 {
2580     if (id->idIsSmallDsc())
2581     {
2582         return SMALL_IDSC_SIZE;
2583     }
2584     else if (id->idIsLargeCns())
2585     {
2586         return sizeof(instrDescCns);
2587     }
2588     else
2589     {
2590         return sizeof(instrDesc);
2591     }
2592 }
2593
2594 /*****************************************************************************
2595  *
2596  *  The following helpers should be used to access the various values that
2597  *  get stored in different places within the instruction descriptor.
2598  */
2599
2600 inline ssize_t emitter::emitGetInsCns(instrDesc* id)
2601 {
2602     return id->idIsLargeCns() ? ((instrDescCns*)id)->idcCnsVal : id->idSmallCns();
2603 }
2604
2605 inline ssize_t emitter::emitGetInsDsp(instrDesc* id)
2606 {
2607     if (id->idIsLargeDsp())
2608     {
2609         if (id->idIsLargeCns())
2610         {
2611             return ((instrDescCnsDsp*)id)->iddcDspVal;
2612         }
2613         return ((instrDescDsp*)id)->iddDspVal;
2614     }
2615     return 0;
2616 }
2617
2618 inline ssize_t emitter::emitGetInsCnsDsp(instrDesc* id, ssize_t* dspPtr)
2619 {
2620     if (id->idIsLargeCns())
2621     {
2622         if (id->idIsLargeDsp())
2623         {
2624             *dspPtr = ((instrDescCnsDsp*)id)->iddcDspVal;
2625             return ((instrDescCnsDsp*)id)->iddcCnsVal;
2626         }
2627         else
2628         {
2629             *dspPtr = 0;
2630             return ((instrDescCns*)id)->idcCnsVal;
2631         }
2632     }
2633     else
2634     {
2635         if (id->idIsLargeDsp())
2636         {
2637             *dspPtr = ((instrDescDsp*)id)->iddDspVal;
2638             return id->idSmallCns();
2639         }
2640         else
2641         {
2642             *dspPtr = 0;
2643             return id->idSmallCns();
2644         }
2645     }
2646 }
2647
2648 /*****************************************************************************
2649  *
2650  *  Get hold of the argument count for an indirect call.
2651  */
2652
2653 inline unsigned emitter::emitGetInsCIargs(instrDesc* id)
2654 {
2655     if (id->idIsLargeCall())
2656     {
2657         return ((instrDescCGCA*)id)->idcArgCnt;
2658     }
2659     else
2660     {
2661         assert(id->idIsLargeDsp() == false);
2662         assert(id->idIsLargeCns() == false);
2663
2664         ssize_t cns = emitGetInsCns(id);
2665         assert((unsigned)cns == (size_t)cns);
2666         return (unsigned)cns;
2667     }
2668 }
2669
2670 /*****************************************************************************
2671  *
2672  *  Returns true if the given register contains a live GC ref.
2673  */
2674
2675 inline GCtype emitter::emitRegGCtype(regNumber reg)
2676 {
2677     assert(emitIssuing);
2678
2679     if ((emitThisGCrefRegs & genRegMask(reg)) != 0)
2680     {
2681         return GCT_GCREF;
2682     }
2683     else if ((emitThisByrefRegs & genRegMask(reg)) != 0)
2684     {
2685         return GCT_BYREF;
2686     }
2687     else
2688     {
2689         return GCT_NONE;
2690     }
2691 }
2692
2693 #ifdef DEBUG
2694
2695 #if EMIT_TRACK_STACK_DEPTH
2696 #define CHECK_STACK_DEPTH() assert((int)emitCurStackLvl >= 0)
2697 #else
2698 #define CHECK_STACK_DEPTH()
2699 #endif
2700
2701 #endif // DEBUG
2702
2703 /*****************************************************************************
2704  *
2705  *  Return true when a given code offset is properly aligned for the target
2706  */
2707
2708 inline bool IsCodeAligned(UNATIVE_OFFSET offset)
2709 {
2710     return ((offset & (CODE_ALIGN - 1)) == 0);
2711 }
2712
2713 // Static:
2714 inline BYTE* emitter::emitCodeWithInstructionSize(BYTE* codePtrBefore, BYTE* newCodePointer, unsigned char* instrSize)
2715 {
2716     // DLD: Perhaps this method should return the instruction size, and we should do dst += <that size>
2717     // as is done in other cases?
2718     assert(newCodePointer >= codePtrBefore);
2719     ClrSafeInt<unsigned char> callInstrSizeSafe = ClrSafeInt<unsigned char>(newCodePointer - codePtrBefore);
2720     assert(!callInstrSizeSafe.IsOverflow());
2721     *instrSize = callInstrSizeSafe.Value();
2722     return newCodePointer;
2723 }
2724
2725 /*****************************************************************************
2726  *
2727  *  Add a new IG to the current list, and get it ready to receive code.
2728  */
2729
2730 inline void emitter::emitNewIG()
2731 {
2732     insGroup* ig = emitAllocAndLinkIG();
2733
2734     /* It's linked in. Now, set it up to accept code */
2735
2736     emitGenIG(ig);
2737 }
2738
2739 #if !defined(JIT32_GCENCODER)
2740 // Start a new instruction group that is not interruptable
2741 inline void emitter::emitDisableGC()
2742 {
2743     emitNoGCIG = true;
2744
2745     if (emitCurIGnonEmpty())
2746     {
2747         emitNxtIG(true);
2748     }
2749     else
2750     {
2751         emitCurIG->igFlags |= IGF_NOGCINTERRUPT;
2752     }
2753 }
2754
2755 // Start a new instruction group that is interruptable
2756 inline void emitter::emitEnableGC()
2757 {
2758     emitNoGCIG = false;
2759
2760     // The next time an instruction needs to be generated, force a new instruction group.
2761     // It will be an emitAdd group in that case. Note that the next thing we see might be
2762     // a label, which will force a non-emitAdd group.
2763     //
2764     // Note that we can't just create a new instruction group here, because we don't know
2765     // if there are going to be any instructions added to it, and we don't support empty
2766     // instruction groups.
2767     emitForceNewIG = true;
2768 }
2769 #endif // !defined(JIT32_GCENCODER)
2770
2771 /*****************************************************************************/
2772 #endif // _EMIT_H_
2773 /*****************************************************************************/