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 /*****************************************************************************/
15 #include "jitgcinfo.h"
17 /*****************************************************************************/
19 #ifndef _ADDRMAP_INCLUDED_
22 #ifndef _LOCALMAP_INCLUDED_
25 #ifndef _PDBREWRITE_H_
26 #include "pdbrewrite.h"
28 #endif // TRANSLATE_PDB
30 /*****************************************************************************/
32 #pragma warning(disable : 4200) // allow arrays of 0 size inside structs
34 #define TRACK_GC_TEMP_LIFETIMES 0
36 /*****************************************************************************/
41 #define EMITVERBOSE (emitComp->verbose)
45 #define EMIT_GC_VERBOSE 0
47 #define EMIT_GC_VERBOSE (emitComp->verbose)
51 #define EMIT_INSTLIST_VERBOSE 0
53 #define EMIT_INSTLIST_VERBOSE (emitComp->verbose)
56 /*****************************************************************************/
65 void emitterStats(FILE* fout);
66 void emitterStaticStats(FILE* fout); // Static stats about the emitter (data structure offsets, sizes, etc.)
69 void printRegMaskInt(regMaskTP mask);
71 /*****************************************************************************/
72 /* Forward declarations */
78 typedef void (*emitSplitCallbackType)(void* context, emitLocation* emitLoc);
80 /*****************************************************************************/
82 //-----------------------------------------------------------------------------
84 inline bool needsGC(GCtype gcType)
86 if (gcType == GCT_NONE)
92 assert(gcType == GCT_GCREF || gcType == GCT_BYREF);
97 //-----------------------------------------------------------------------------
101 inline bool IsValidGCtype(GCtype gcType)
103 return (gcType == GCT_NONE || gcType == GCT_GCREF || gcType == GCT_BYREF);
106 // Get a string name to represent the GC type
108 inline const char* GCtypeStr(GCtype gcType)
119 assert(!"Invalid GCtype");
126 /*****************************************************************************/
129 #define INTERESTING_JUMP_NUM -1 // set to 0 to see all jump info
130 //#define INTERESTING_JUMP_NUM 0
133 /*****************************************************************************
135 * Represent an emitter location.
141 emitLocation() : ig(nullptr), codePos(0)
145 emitLocation(insGroup* _ig) : ig(_ig), codePos(0)
149 emitLocation(void* emitCookie) : ig((insGroup*)emitCookie), codePos(0)
153 // A constructor for code that needs to call it explicitly.
156 this->emitLocation::emitLocation();
159 void CaptureLocation(emitter* emit);
161 bool IsCurrentLocation(emitter* emit) const;
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
167 return (codePos == 0);
170 UNATIVE_OFFSET CodeOffset(emitter* emit) const;
172 insGroup* GetIG() const
177 int GetInsNum() const;
179 bool operator!=(const emitLocation& other) const
181 return (ig != other.ig) || (codePos != other.codePos);
184 bool operator==(const emitLocation& other) const
186 return !(*this != other);
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.
206 #ifdef _TARGET_AMD64_
207 UNATIVE_OFFSET GetFuncletPrologOffset(emitter* emit) const;
208 #endif // _TARGET_AMD64_
215 insGroup* ig; // the instruction group
216 unsigned codePos; // the code position within the IG (see emitCurOffset())
219 /************************************************************************/
220 /* The following describes an instruction group */
221 /************************************************************************/
223 DECLARE_TYPED_ENUM(insGroupPlaceholderType, unsigned char)
225 IGPT_PROLOG, // currently unused
227 #if FEATURE_EH_FUNCLETS
228 IGPT_FUNCLET_PROLOG, IGPT_FUNCLET_EPILOG,
229 #endif // FEATURE_EH_FUNCLETS
231 END_DECLARE_TYPED_ENUM(insGroupPlaceholderType, unsigned char)
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.
238 #endif // defined(_MSC_VER) && defined(_TARGET_ARM_)
240 struct insPlaceholderGroupData
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
258 insGroup* igSelf; // for consistency checking
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
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.
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
287 #define IGF_PROPAGATE_MASK (IGF_EPILOG | IGF_FUNCLET_PROLOG | IGF_FUNCLET_EPILOG)
289 #define IGF_PROPAGATE_MASK (IGF_EPILOG | IGF_FUNCLET_PROLOG)
291 #else // FEATURE_EH_FUNCLETS
292 #define IGF_PROPAGATE_MASK (IGF_EPILOG)
293 #endif // FEATURE_EH_FUNCLETS
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
300 BYTE* igData; // addr of instruction descriptors
301 insPlaceholderGroupData* igPhData; // when igFlags & IGF_PLACEHOLDER
304 #if EMIT_TRACK_STACK_DEPTH
305 unsigned igStkLvl; // stack level on entry
307 regMaskSmall igGCregs; // set of registers with live GC refs
308 unsigned char igInsCnt; // # of instructions in this group
310 #else // REGMASK_BITS
312 regMaskSmall igGCregs; // set of registers with live GC refs
315 BYTE* igData; // addr of instruction descriptors
316 insPlaceholderGroupData* igPhData; // when igFlags & IGF_PLACEHOLDER
319 #if EMIT_TRACK_STACK_DEPTH
320 unsigned igStkLvl; // stack level on entry
323 unsigned char igInsCnt; // # of instructions in this group
325 #endif // REGMASK_BITS
327 VARSET_VALRET_TP igGCvars() const
329 assert(igFlags & IGF_GC_VARS);
331 BYTE* ptr = (BYTE*)igData;
332 ptr -= sizeof(VARSET_TP);
334 return *(VARSET_TP*)ptr;
337 unsigned igByrefRegs() const
339 assert(igFlags & IGF_BYREF_REGS);
341 BYTE* ptr = (BYTE*)igData;
343 if (igFlags & IGF_GC_VARS)
345 ptr -= sizeof(VARSET_TP);
348 ptr -= sizeof(unsigned);
350 return *(unsigned*)ptr;
353 }; // end of struct insGroup
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.
359 #define MAX_PLACEHOLDER_IG_SIZE 256
361 #if defined(_MSC_VER) && defined(_TARGET_ARM_)
363 #endif // defined(_MSC_VER) && defined(_TARGET_ARM_)
365 /*****************************************************************************/
367 #define DEFINE_ID_OPS
368 #include "emitfmts.h"
373 LVA_STANDARD_ENCODING = 0,
374 LVA_LARGE_OFFSET = 1,
375 LVA_COMPILER_TEMP = 2,
379 struct emitLclVarAddr
382 void initLclVarAddr(int varNum, unsigned offset);
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
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.
392 unsigned _lvaVarNum : 15; // Usually the lvaVarNum
393 unsigned _lvaExtra : 15; // Usually the lvaOffset
394 unsigned _lvaTag : 2; // tag field to support larger varnums
399 iaut_ALIGNED_POINTER = 0x0,
400 iaut_DATA_OFFSET = 0x1,
401 iaut_INST_COUNT = 0x2,
402 iaut_UNUSED_TAG = 0x3,
410 friend class emitLocation;
411 friend class Compiler;
412 friend class CodeGen;
413 friend class CodeGenInterface;
416 /*************************************************************************
418 * Define the public entry points.
425 // There seem to be some cases where this is used without being initialized via CodeGen::inst_set_SV_var().
429 #ifdef _TARGET_XARCH_
431 #endif // _TARGET_XARCH_
433 #ifdef FEATURE_AVX_SUPPORT
435 #endif // FEATURE_AVX_SUPPORT
441 /************************************************************************/
442 /* Miscellaneous stuff */
443 /************************************************************************/
449 typedef GCInfo::varPtrDsc varPtrDsc;
450 typedef GCInfo::regPtrDsc regPtrDsc;
451 typedef GCInfo::CallDsc callDsc;
453 void* emitGetMem(size_t sz);
455 DECLARE_TYPED_ENUM(opSize, unsigned)
457 OPSZ1 = 0, OPSZ2 = 1, OPSZ4 = 2, OPSZ8 = 3, OPSZ16 = 4, OPSZ32 = 5, OPSZ_COUNT = 6,
458 #ifdef _TARGET_AMD64_
464 END_DECLARE_TYPED_ENUM(opSize, unsigned)
466 #define OPSIZE_INVALID ((opSize)0xffff)
468 static const emitter::opSize emitSizeEncode[];
469 static const emitAttr emitSizeDecode[];
471 static emitter::opSize emitEncodeSize(emitAttr size);
472 static emitAttr emitDecodeSize(emitter::opSize ensz);
474 // Currently, we only allow one IG for the prolog
475 bool emitIGisInProlog(const insGroup* ig)
477 return ig == emitPrologIG;
480 bool emitIGisInEpilog(const insGroup* ig)
482 return (ig != nullptr) && ((ig->igFlags & IGF_EPILOG) != 0);
485 #if FEATURE_EH_FUNCLETS
487 bool emitIGisInFuncletProlog(const insGroup* ig)
489 return (ig != nullptr) && ((ig->igFlags & IGF_FUNCLET_PROLOG) != 0);
492 bool emitIGisInFuncletEpilog(const insGroup* ig)
494 return (ig != nullptr) && ((ig->igFlags & IGF_FUNCLET_EPILOG) != 0);
497 #endif // FEATURE_EH_FUNCLETS
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);
504 void emitRecomputeIGoffsets();
506 /************************************************************************/
507 /* The following describes a single instruction */
508 /************************************************************************/
510 DECLARE_TYPED_ENUM(insFormat, unsigned)
512 #define IF_DEF(en, op1, op2) IF_##en,
513 #include "emitfmts.h"
517 END_DECLARE_TYPED_ENUM(insFormat, unsigned)
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))
526 regNumber amBaseReg : REGNUM_BITS + 1;
527 regNumber amIndxReg : REGNUM_BITS + 1;
528 emitter::opSize amScale : 2;
529 int amDisp : AM_DISP_BITS;
532 #if defined(DEBUG) || defined(LATE_DISASM) // LATE_DISASM needs the idMemCookie on calls to display the call target name
536 struct instrDescDebugInfo
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
544 unsigned int idilStart; // instruction descriptor source information for PDB translation
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
551 #endif // defined(DEBUG) || defined(LATE_DISASM)
554 unsigned insEncodeSetFlags(insFlags sf);
556 DECLARE_TYPED_ENUM(insSize, unsigned)
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
561 END_DECLARE_TYPED_ENUM(insSize, unsigned)
563 unsigned insEncodeShiftOpts(insOpts opt);
564 unsigned insEncodePUW_G0(insOpts opt, int imm);
565 unsigned insEncodePUW_H0(insOpts opt, int imm);
567 #endif // _TARGET_ARM_
569 #if defined(_TARGET_X86_) && defined(LEGACY_BACKEND)
570 #define HAS_TINY_DESC 1
572 #define HAS_TINY_DESC 0
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;
591 instruction idIns() const
595 void idIns(instruction ins)
598 assert(_idIns == ins);
601 insFormat idInsFmt() const
605 void idInsFmt(insFormat insFmt)
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)
611 assert(_idInsFmt == insFmt);
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.
621 void idSetRelocFlags(emitAttr attr)
623 _idCnsReloc = (EA_IS_CNS_RELOC(attr) ? 1 : 0);
624 _idDspReloc = (EA_IS_DSP_RELOC(attr) ? 1 : 0);
627 ////////////////////////////////////////////////////////////////////////
628 // Space taken up to here:
635 #ifdef _TARGET_XARCH_
636 unsigned _idCodeSize : 4; // size of instruction in bytes
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
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")
659 // Note that we use the _idReg1 and _idReg2 fields to hold
660 // the live gcrefReg mask for the call instructions on x86/x64
662 regNumber _idReg1 : REGNUM_BITS; // register num
664 regNumber _idReg2 : REGNUM_BITS;
666 ////////////////////////////////////////////////////////////////////////
667 // Space taken up to here:
672 CLANG_FORMAT_COMMENT_ANCHOR;
676 // For x86 use last two bits to differentiate if we are tiny or small
678 unsigned _idTinyDsc : 1; // is this a "tiny" descriptor?
679 unsigned _idSmallDsc : 1; // is this a "small" descriptor?
681 #else // !HAS_TINY_DESC
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)
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)
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
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
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
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
717 // For arm we have used 16 bits
718 #define ID_EXTRA_BITFIELD_BITS (16)
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)
730 #error Unsupported or unset target architecture
733 ////////////////////////////////////////////////////////////////////////
734 // Space taken up to here:
735 // x86: 38 bits // if HAS_TINY_DESC is not defined (which it is)
739 CLANG_FORMAT_COMMENT_ANCHOR;
741 unsigned _idCnsReloc : 1; // LargeCns is an RVA and needs reloc tag
742 unsigned _idDspReloc : 1; // LargeDsp is an RVA and needs reloc tag
744 #define ID_EXTRA_RELOC_BITS (2)
746 ////////////////////////////////////////////////////////////////////////
747 // Space taken up to here:
752 CLANG_FORMAT_COMMENT_ANCHOR;
754 #define ID_EXTRA_BITS (ID_EXTRA_RELOC_BITS + ID_EXTRA_BITFIELD_BITS)
756 /* Use whatever bits are left over for small constants */
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)
762 ////////////////////////////////////////////////////////////////////////
763 // Small constant size:
769 unsigned _idSmallCns : ID_BIT_SMALL_CNS;
771 ////////////////////////////////////////////////////////////////////////
772 // Space taken up to here: 64 bits, all architectures, by design.
773 ////////////////////////////////////////////////////////////////////////
774 CLANG_FORMAT_COMMENT_ANCHOR;
776 #endif // !HAS_TINY_DESC
778 #if defined(DEBUG) || defined(LATE_DISASM)
780 instrDescDebugInfo* _idDebugOnlyInfo;
783 instrDescDebugInfo* idDebugOnlyInfo() const
785 return _idDebugOnlyInfo;
787 void idDebugOnlyInfo(instrDescDebugInfo* info)
789 _idDebugOnlyInfo = info;
793 #endif // defined(DEBUG) || defined(LATE_DISASM)
796 // This is the end of the smallest instrDesc we can allocate for all
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).
809 CLANG_FORMAT_COMMENT_ANCHOR;
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
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
822 #define ID_EXTRA_BITFIELD_BITS (7)
825 // For x86, we are using 7 bits from the second DWORD for bitfields.
828 unsigned _idCnsReloc : 1; // LargeCns is an RVA and needs reloc tag
829 unsigned _idDspReloc : 1; // LargeDsp is an RVA and needs reloc tag
831 #define ID_EXTRA_REG_BITS (0)
833 #define ID_EXTRA_BITS (ID_EXTRA_BITFIELD_BITS + ID_EXTRA_RELOC_BITS + ID_EXTRA_REG_BITS)
835 /* Use whatever bits are left over for small constants */
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)
841 // For x86 we have 23 bits remaining for the
842 // small constant in this extra DWORD.
844 unsigned _idSmallCns : ID_BIT_SMALL_CNS;
846 #endif // HAS_TINY_DESC
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).
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).
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.
868 #if defined(DEBUG) || defined(LATE_DISASM)
869 #define TINY_IDSC_DEBUG_EXTRA (sizeof(void*))
871 #define TINY_IDSC_DEBUG_EXTRA (0)
875 #define TINY_IDSC_SIZE (4 + TINY_IDSC_DEBUG_EXTRA)
876 #define SMALL_IDSC_SIZE (8 + TINY_IDSC_DEBUG_EXTRA)
878 #define TINY_IDSC_SIZE (8 + TINY_IDSC_DEBUG_EXTRA)
879 #define SMALL_IDSC_SIZE TINY_IDSC_SIZE
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.
888 #ifndef _TARGET_ARM64_
889 emitLclVarAddr iiaLclVar;
891 BasicBlock* iiaBBlabel;
892 insGroup* iiaIGlabel;
894 emitAddrMode iiaAddrMode;
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;
901 #ifdef _TARGET_ARMARCH_
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;
908 bool iiaHasInstrCount() const
910 return (iiaEncodedInstrCount & iaut_MASK) == iaut_INST_COUNT;
912 int iiaGetInstrCount() const
914 assert(iiaHasInstrCount());
915 return (iiaEncodedInstrCount >> iaut_SHIFT);
917 void iiaSetInstrCount(int count)
919 assert(abs(count) < 10);
920 iiaEncodedInstrCount = (count << iaut_SHIFT) | iaut_INST_COUNT;
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;
931 regNumber _idReg3 : REGNUM_BITS;
932 regNumber _idReg4 : REGNUM_BITS;
934 #elif defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
937 regNumber _idReg3 : REGNUM_BITS;
939 #endif // defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
943 /* Trivial wrappers to return properly typed enums */
947 bool idIsTiny() const
949 return (_idTinyDsc != 0);
958 bool idIsTiny() const
967 #endif // HAS_TINY_DESC
969 bool idIsSmallDsc() const
971 return (_idSmallDsc != 0);
973 void idSetIsSmallDsc()
978 #if defined(_TARGET_XARCH_)
980 unsigned idCodeSize() const
984 void idCodeSize(unsigned sz)
987 assert(sz == _idCodeSize);
990 #elif defined(_TARGET_ARM64_)
991 unsigned idCodeSize() const
999 // b<cond> + b<uncond>
1003 if (isVectorRegister(idReg1()))
1005 // adrp + ldr + fmov
1021 #elif defined(_TARGET_ARM_)
1023 bool idInstrIsT1() const
1025 return (_idInsSize == ISZ_16BIT);
1027 unsigned idCodeSize() const
1029 unsigned result = (_idInsSize == ISZ_16BIT) ? 2 : (_idInsSize == ISZ_32BIT) ? 4 : 6;
1032 insSize idInsSize() const
1036 void idInsSize(insSize isz)
1039 assert(isz == _idInsSize);
1041 insFlags idInsFlags() const
1045 void idInsFlags(insFlags sf)
1048 assert(sf == _idInsFlags);
1050 #endif // _TARGET_ARM_
1054 return emitDecodeSize(_idOpSize);
1056 void idOpSize(emitAttr opsz)
1058 _idOpSize = emitEncodeSize(opsz);
1061 GCtype idGCref() const
1063 return (GCtype)_idGCref;
1065 void idGCref(GCtype gctype)
1070 regNumber idReg1() const
1074 void idReg1(regNumber reg)
1077 assert(reg == _idReg1);
1080 #ifdef _TARGET_ARM64_
1081 GCtype idGCrefReg2() const
1083 assert(!idIsTiny());
1084 assert(!idIsSmallDsc());
1085 return (GCtype)idAddr()->_idGCref2;
1087 void idGCrefReg2(GCtype gctype)
1089 assert(!idIsTiny());
1090 assert(!idIsSmallDsc());
1091 idAddr()->_idGCref2 = gctype;
1093 #endif // _TARGET_ARM64_
1095 regNumber idReg2() const
1099 void idReg2(regNumber reg)
1102 assert(reg == _idReg2);
1105 #if defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
1106 regNumber idReg3() const
1108 assert(!idIsTiny());
1109 assert(!idIsSmallDsc());
1110 return idAddr()->_idReg3;
1112 void idReg3(regNumber reg)
1114 assert(!idIsTiny());
1115 assert(!idIsSmallDsc());
1116 idAddr()->_idReg3 = reg;
1117 assert(reg == idAddr()->_idReg3);
1119 #endif // defined(_TARGET_XARCH_) && !defined(LEGACY_BACKEND)
1120 #ifdef _TARGET_ARMARCH_
1121 insOpts idInsOpt() const
1123 return (insOpts)_idInsOpt;
1125 void idInsOpt(insOpts opt)
1128 assert(opt == _idInsOpt);
1131 regNumber idReg3() const
1133 assert(!idIsTiny());
1134 assert(!idIsSmallDsc());
1135 return idAddr()->_idReg3;
1137 void idReg3(regNumber reg)
1139 assert(!idIsTiny());
1140 assert(!idIsSmallDsc());
1141 idAddr()->_idReg3 = reg;
1142 assert(reg == idAddr()->_idReg3);
1144 regNumber idReg4() const
1146 assert(!idIsTiny());
1147 assert(!idIsSmallDsc());
1148 return idAddr()->_idReg4;
1150 void idReg4(regNumber reg)
1152 assert(!idIsTiny());
1153 assert(!idIsSmallDsc());
1154 idAddr()->_idReg4 = reg;
1155 assert(reg == idAddr()->_idReg4);
1157 #ifdef _TARGET_ARM64_
1158 bool idReg3Scaled() const
1160 assert(!idIsTiny());
1161 assert(!idIsSmallDsc());
1162 return (idAddr()->_idReg3Scaled == 1);
1164 void idReg3Scaled(bool val)
1166 assert(!idIsTiny());
1167 assert(!idIsSmallDsc());
1168 idAddr()->_idReg3Scaled = val ? 1 : 0;
1170 #endif // _TARGET_ARM64_
1172 #endif // _TARGET_ARMARCH_
1174 inline static bool fitsInSmallCns(ssize_t val)
1176 return ((val >= ID_MIN_SMALL_CNS) && (val <= ID_MAX_SMALL_CNS));
1179 bool idIsLargeCns() const
1181 assert(!idIsTiny());
1182 return _idLargeCns != 0;
1184 void idSetIsLargeCns()
1186 assert(!idIsTiny());
1190 bool idIsLargeDsp() const
1192 assert(!idIsTiny());
1193 return _idLargeDsp != 0;
1195 void idSetIsLargeDsp()
1197 assert(!idIsTiny());
1200 void idSetIsSmallDsp()
1202 assert(!idIsTiny());
1206 bool idIsLargeCall() const
1208 assert(!idIsTiny());
1209 return _idLargeCall != 0;
1211 void idSetIsLargeCall()
1213 assert(!idIsTiny());
1217 bool idIsBound() const
1219 assert(!idIsTiny());
1220 return _idBound != 0;
1224 assert(!idIsTiny());
1228 bool idIsCallRegPtr() const
1230 assert(!idIsTiny());
1231 return _idCallRegPtr != 0;
1233 void idSetIsCallRegPtr()
1235 assert(!idIsTiny());
1239 bool idIsCallAddr() const
1241 assert(!idIsTiny());
1242 return _idCallAddr != 0;
1244 void idSetIsCallAddr()
1246 assert(!idIsTiny());
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
1255 assert(!idIsTiny());
1256 return _idNoGC != 0;
1258 void idSetIsNoGC(bool val)
1260 assert(!idIsTiny());
1264 #ifdef _TARGET_ARMARCH_
1265 bool idIsLclVar() const
1267 return !idIsTiny() && _idLclVar != 0;
1269 void idSetIsLclVar()
1271 assert(!idIsTiny());
1274 #endif // _TARGET_ARMARCH_
1276 #if defined(_TARGET_ARM_)
1277 bool idIsLclFPBase() const
1279 return !idIsTiny() && _idLclFPBase != 0;
1281 void idSetIsLclFPBase()
1283 assert(!idIsTiny());
1286 #endif // defined(_TARGET_ARM_)
1288 bool idIsCnsReloc() const
1290 assert(!idIsTiny());
1291 return _idCnsReloc != 0;
1293 void idSetIsCnsReloc()
1295 assert(!idIsTiny());
1299 bool idIsDspReloc() const
1301 assert(!idIsTiny());
1302 return _idDspReloc != 0;
1304 void idSetIsDspReloc(bool val = true)
1306 assert(!idIsTiny());
1311 return idIsDspReloc() || idIsCnsReloc();
1314 unsigned idSmallCns() const
1316 assert(!idIsTiny());
1319 void idSmallCns(size_t value)
1321 assert(!idIsTiny());
1322 assert(fitsInSmallCns(value));
1323 _idSmallCns = value;
1326 inline const idAddrUnion* idAddr() const
1328 assert(!idIsSmallDsc() && !idIsTiny());
1329 return &this->_idAddrUnion;
1332 inline idAddrUnion* idAddr()
1334 assert(!idIsSmallDsc() && !idIsTiny());
1335 return &this->_idAddrUnion;
1337 }; // End of struct instrDesc
1339 void dispIns(instrDesc* id);
1341 void appendToCurIG(instrDesc* id);
1343 /********************************************************************************************/
1345 struct instrDescJmp : instrDesc
1347 instrDescJmp* idjNext; // next jump in the group/method
1348 insGroup* idjIG; // containing group
1351 BYTE* idjAddr; // address of jump ins (for patching)
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)
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
1366 emitLclVarAddr dstLclVar;
1368 #endif // !_TARGET_ARM64_
1370 struct instrDescCns : instrDesc // large const
1375 struct instrDescDsp : instrDesc // large displacement
1380 struct instrDescCnsDsp : instrDesc // large cons + disp
1386 struct instrDescAmd : instrDesc // large addrmode disp
1391 struct instrDescCnsAmd : instrDesc // large cons + addrmode disp
1397 struct instrDescCGCA : instrDesc // call with ...
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)
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
1409 return (GCtype)_idcSecondRetRegGCType;
1411 void idSecondGCref(GCtype gctype)
1413 _idcSecondRetRegGCType = gctype;
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
1428 struct instrDescArmFP : instrDesc
1435 insUpdateModes emitInsUpdateMode(instruction ins);
1436 insFormat emitInsModeFormat(instruction ins, insFormat base);
1438 static const BYTE emitInsModeFmtTab[];
1440 static const unsigned emitInsModeFmtCnt;
1443 size_t emitGetInstrDescSize(const instrDesc* id);
1444 size_t emitGetInstrDescSizeSC(const instrDesc* id);
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);
1454 // Return the argument count for a direct call "id".
1455 int emitGetInsCDinfo(instrDesc* id);
1457 unsigned emitInsCount;
1459 /************************************************************************/
1460 /* A few routines used for debug display purposes */
1461 /************************************************************************/
1463 #if defined(DEBUG) || EMITTER_STATS
1465 static const char* emitIfName(unsigned f);
1467 #endif // defined(DEBUG) || EMITTER_STATS
1471 unsigned emitVarRefOffs;
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);
1476 const char* emitFldName(CORINFO_FIELD_HANDLE fieldVal);
1477 const char* emitFncName(CORINFO_METHOD_HANDLE callVal);
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);
1489 #define emitVarRefOffs 0
1492 /************************************************************************/
1493 /* Method prolog and epilog */
1494 /************************************************************************/
1496 unsigned emitPrologEndPos;
1498 unsigned emitEpilogCnt;
1499 UNATIVE_OFFSET emitEpilogSize;
1501 #ifdef _TARGET_XARCH_
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
1507 #endif // _TARGET_XARCH_
1509 insGroup* emitPlaceholderList; // per method placeholder list - head
1510 insGroup* emitPlaceholderLast; // per method placeholder list - tail
1512 #ifdef JIT32_GCENCODER
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.
1522 EpilogList() : elNext(nullptr), elLoc()
1527 EpilogList* emitEpilogList; // per method epilog list - head
1528 EpilogList* emitEpilogLast; // per method epilog list - tail
1531 void emitStartEpilog();
1533 bool emitHasEpilogEnd();
1535 size_t emitGenEpilogLst(size_t (*fp)(void*, unsigned), void* cp);
1537 #endif // JIT32_GCENCODER
1539 void emitBegPrologEpilog(insGroup* igPh);
1540 void emitEndPrologEpilog();
1542 void emitBegFnEpilog(insGroup* igPh);
1543 void emitEndFnEpilog();
1545 #if FEATURE_EH_FUNCLETS
1547 void emitBegFuncletProlog(insGroup* igPh);
1548 void emitEndFuncletProlog();
1550 void emitBegFuncletEpilog(insGroup* igPh);
1551 void emitEndFuncletEpilog();
1553 #endif // FEATURE_EH_FUNCLETS
1555 /************************************************************************/
1556 /* Members and methods used in PDB translation */
1557 /************************************************************************/
1559 #ifdef TRANSLATE_PDB
1561 inline void SetIDSource(instrDesc* pID);
1562 void MapCode(int ilOffset, BYTE* imgDest);
1563 void MapFunc(int imgOff,
1570 OptJit::LclVarDsc* lvaTable,
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
1586 /************************************************************************/
1587 /* Methods to record a code position and later convert to offset */
1588 /************************************************************************/
1590 unsigned emitFindInsNum(insGroup* ig, instrDesc* id);
1591 UNATIVE_OFFSET emitFindOffset(insGroup* ig, unsigned insNum);
1593 /************************************************************************/
1594 /* Members and methods used to issue (encode) instructions. */
1595 /************************************************************************/
1598 // If we have started issuing instructions from the list of instrDesc, this is set
1602 BYTE* emitCodeBlock; // Hot code block
1603 BYTE* emitColdCodeBlock; // Cold code block
1604 BYTE* emitConsBlock; // Read-only (constant) data block
1606 UNATIVE_OFFSET emitTotalHotCodeSize;
1607 UNATIVE_OFFSET emitTotalColdCodeSize;
1609 UNATIVE_OFFSET emitCurCodeOffs(BYTE* dst)
1612 if ((dst >= emitCodeBlock) && (dst <= (emitCodeBlock + emitTotalHotCodeSize)))
1614 distance = (dst - emitCodeBlock);
1618 assert(emitFirstColdIG);
1619 assert(emitColdCodeBlock);
1620 assert((dst >= emitColdCodeBlock) && (dst <= (emitColdCodeBlock + emitTotalColdCodeSize)));
1622 distance = (dst - emitColdCodeBlock + emitTotalHotCodeSize);
1624 noway_assert((UNATIVE_OFFSET)distance == distance);
1625 return (UNATIVE_OFFSET)distance;
1628 BYTE* emitOffsetToPtr(UNATIVE_OFFSET offset)
1630 if (offset < emitTotalHotCodeSize)
1632 return emitCodeBlock + offset;
1636 assert(offset < (emitTotalHotCodeSize + emitTotalColdCodeSize));
1638 return emitColdCodeBlock + (offset - emitTotalHotCodeSize);
1642 BYTE* emitDataOffsetToPtr(UNATIVE_OFFSET offset)
1644 assert(offset < emitDataSize());
1645 return emitConsBlock + offset;
1648 bool emitJumpCrossHotColdBoundary(size_t srcOffset, size_t dstOffset)
1650 if (emitTotalColdCodeSize == 0)
1655 assert(srcOffset < (emitTotalHotCodeSize + emitTotalColdCodeSize));
1656 assert(dstOffset < (emitTotalHotCodeSize + emitTotalColdCodeSize));
1658 return ((srcOffset < emitTotalHotCodeSize) != (dstOffset < emitTotalHotCodeSize));
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);
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);
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_)
1678 size_t emitIssue1Instr(insGroup* ig, instrDesc* id, BYTE** dp);
1679 size_t emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp);
1681 bool emitHasFramePtr;
1683 #ifdef PSEUDORANDOM_NOP_INSERTION
1684 bool emitInInstrumentation;
1685 #endif // PSEUDORANDOM_NOP_INSERTION
1687 unsigned emitMaxTmpSize;
1689 #ifdef LEGACY_BACKEND
1690 unsigned emitLclSize;
1691 unsigned emitGrowableMaxByteOffs;
1692 void emitTmpSizeChanged(unsigned tmpSize);
1694 unsigned emitMaxByteOffsIdNum;
1696 #endif // LEGACY_BACKEND
1699 bool emitChkAlign; // perform some alignment checks
1702 insGroup* emitCurIG;
1704 void emitSetShortJump(instrDescJmp* id);
1705 void emitSetMediumJump(instrDescJmp* id);
1706 UNATIVE_OFFSET emitSizeOfJump(instrDescJmp* jmp);
1707 UNATIVE_OFFSET emitInstCodeSz(instrDesc* id);
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
1721 /************************************************************************/
1722 /* The logic that creates and keeps track of instruction groups */
1723 /************************************************************************/
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_
1738 size_t emitIGbuffSize;
1740 insGroup* emitIGlist; // first instruction group
1741 insGroup* emitIGlast; // last instruction group
1742 insGroup* emitIGthis; // issued instruction group
1744 insGroup* emitPrologIG; // prolog instruction group
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
1750 void emitCheckFuncletBranch(instrDesc* jmp, insGroup* jmpIG); // Check for illegal branches between funclets
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.
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
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
1766 insGroup* emitFirstColdIG; // first cold instruction group
1768 void emitSetFirstColdIGCookie(void* bbEmitCookie)
1770 emitFirstColdIG = (insGroup*)bbEmitCookie;
1773 int emitOffsAdj; // current code offset adjustment
1775 instrDescJmp* emitCurIGjmpList; // list of jumps in current IG
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.
1783 VARSET_TP emitPrevGCrefVars;
1784 regMaskTP emitPrevGCrefRegs;
1785 regMaskTP emitPrevByrefRegs;
1787 VARSET_TP emitInitGCrefVars;
1788 regMaskTP emitInitGCrefRegs;
1789 regMaskTP emitInitByrefRegs;
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.
1794 bool emitForceStoreGCState;
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.
1806 VARSET_TP emitThisGCrefVars;
1807 regMaskTP emitThisGCrefRegs; // Current set of registers holding GC references
1808 regMaskTP emitThisByrefRegs; // Current set of registers holding BYREF references
1810 bool emitThisGCrefVset; // Is "emitThisGCrefVars" up to date?
1812 regNumber emitSyncThisObjReg; // where is "this" enregistered for synchronized methods?
1814 #if MULTIREG_HAS_SECOND_GC_RET
1815 void emitSetSecondRetRegGCType(instrDescCGCA* id, emitAttr secondRetSize);
1816 #endif // MULTIREG_HAS_SECOND_GC_RET
1818 static void emitEncodeCallGCregs(regMaskTP regs, instrDesc* id);
1819 static unsigned emitDecodeCallGCregs(instrDesc* id);
1821 unsigned emitNxtIGnum;
1823 // random nop insertion to break up nop sleds
1824 unsigned emitNextNop;
1825 bool emitRandomNops;
1826 void emitEnableRandomNops()
1828 emitRandomNops = true;
1830 void emitDisableRandomNops()
1832 emitRandomNops = false;
1835 insGroup* emitAllocAndLinkIG();
1836 insGroup* emitAllocIG();
1837 void emitInitIG(insGroup* ig);
1838 void emitInsertIGAfter(insGroup* insertAfterIG, insGroup* ig);
1842 #if !defined(JIT32_GCENCODER)
1843 void emitDisableGC();
1844 void emitEnableGC();
1845 #endif // !defined(JIT32_GCENCODER)
1847 void emitGenIG(insGroup* ig);
1848 insGroup* emitSavIG(bool emitAdd = false);
1849 void emitNxtIG(bool emitAdd = false);
1851 bool emitCurIGnonEmpty()
1853 return (emitCurIG && emitCurIGfreeNext > emitCurIGfreeBase);
1856 instrDesc* emitLastIns;
1859 void emitCheckIGoffsets();
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);
1869 #ifdef _TARGET_ARMARCH_
1871 void emitGetInstrDescs(insGroup* ig, instrDesc** id, int* insCnt);
1873 bool emitGetLocationInfo(emitLocation* emitLoc, insGroup** pig, instrDesc** pid, int* pinsRemaining = NULL);
1875 bool emitNextID(insGroup*& ig, instrDesc*& id, int& insRemaining);
1877 typedef void (*emitProcessInstrFunc_t)(instrDesc* id, void* context);
1879 void emitWalkIDs(emitLocation* locFrom, emitProcessInstrFunc_t processFunc, void* context);
1881 static void emitGenerateUnwindNop(instrDesc* id, void* context);
1883 #endif // _TARGET_ARMARCH_
1885 #if defined(_TARGET_ARM_)
1886 emitter::insFormat emitInsFormat(instruction ins);
1887 size_t emitInsCode(instruction ins, insFormat fmt);
1891 void emitMarkStackLvl(unsigned stackLevel);
1894 int emitNextRandomNop();
1896 void* emitAllocInstr(size_t sz, emitAttr attr);
1898 instrDesc* emitAllocInstr(emitAttr attr)
1900 return (instrDesc*)emitAllocInstr(sizeof(instrDesc), attr);
1903 instrDescJmp* emitAllocInstrJmp()
1905 return (instrDescJmp*)emitAllocInstr(sizeof(instrDescJmp), EA_1BYTE);
1908 #if !defined(_TARGET_ARM64_)
1909 instrDescLbl* emitAllocInstrLbl()
1911 return (instrDescLbl*)emitAllocInstr(sizeof(instrDescLbl), EA_4BYTE);
1913 #endif // !_TARGET_ARM64_
1915 instrDescCns* emitAllocInstrCns(emitAttr attr)
1917 return (instrDescCns*)emitAllocInstr(sizeof(instrDescCns), attr);
1919 instrDescCns* emitAllocInstrCns(emitAttr attr, int cns)
1921 instrDescCns* result = (instrDescCns*)emitAllocInstr(sizeof(instrDescCns), attr);
1922 result->idSetIsLargeCns();
1923 result->idcCnsVal = cns;
1927 instrDescDsp* emitAllocInstrDsp(emitAttr attr)
1929 return (instrDescDsp*)emitAllocInstr(sizeof(instrDescDsp), attr);
1932 instrDescCnsDsp* emitAllocInstrCnsDsp(emitAttr attr)
1934 return (instrDescCnsDsp*)emitAllocInstr(sizeof(instrDescCnsDsp), attr);
1937 instrDescAmd* emitAllocInstrAmd(emitAttr attr)
1939 return (instrDescAmd*)emitAllocInstr(sizeof(instrDescAmd), attr);
1942 instrDescCnsAmd* emitAllocInstrCnsAmd(emitAttr attr)
1944 return (instrDescCnsAmd*)emitAllocInstr(sizeof(instrDescCnsAmd), attr);
1947 instrDescCGCA* emitAllocInstrCGCA(emitAttr attr)
1949 return (instrDescCGCA*)emitAllocInstr(sizeof(instrDescCGCA), attr);
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();
1961 #if !defined(_TARGET_ARM64_)
1962 instrDescLbl* emitNewInstrLbl();
1963 #endif // !_TARGET_ARM64_
1965 static const BYTE emitFmtToOps[];
1968 static const unsigned emitFmtCount;
1971 bool emitIsTinyInsDsc(instrDesc* id);
1972 bool emitIsScnsInsDsc(instrDesc* id);
1974 size_t emitSizeOfInsDsc(instrDesc* id);
1976 /************************************************************************/
1977 /* The following keeps track of stack-based GC values */
1978 /************************************************************************/
1980 unsigned emitTrkVarCnt;
1981 int* emitGCrFrameOffsTab; // Offsets of tracked stack ptr vars (varTrkIndex -> stkOffs)
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)
1989 int emitArgFrameOffsMin;
1990 int emitArgFrameOffsMax;
1992 int emitLclFrameOffsMin;
1993 int emitLclFrameOffsMax;
1995 int emitSyncThisObjOffs; // what is the offset of "this" for synchronized methods?
1998 void emitSetFrameRangeGCRs(int offsLo, int offsHi);
1999 void emitSetFrameRangeLcls(int offsLo, int offsHi);
2000 void emitSetFrameRangeArgs(int offsLo, int offsHi);
2002 static instruction emitJumpKindToIns(emitJumpKind jumpKind);
2003 static emitJumpKind emitInsToJumpKind(instruction ins);
2004 static emitJumpKind emitReverseJumpKind(emitJumpKind jumpKind);
2007 static unsigned emitJumpKindCondCode(emitJumpKind jumpKind);
2011 void emitInsSanityCheck(instrDesc* id);
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.
2021 // This may return false positives.
2022 bool emitInsMayWriteToGCReg(instrDesc* id);
2024 // Returns "true" if instruction "id->idIns()" writes to a LclVar stack location.
2025 bool emitInsWritesToLclVarStackLoc(instrDesc* id);
2027 // Returns true if the instruction may write to more than one register.
2028 bool emitInsMayWriteMultipleRegs(instrDesc* id);
2030 // Returns "true" if instruction "id->idIns()" writes to a LclVar stack slot pair.
2031 bool emitInsWritesToLclVarStackLocPair(instrDesc* id);
2032 #endif // _TARGET_ARMARCH_
2034 /************************************************************************/
2035 /* The following is used to distinguish helper vs non-helper calls */
2036 /************************************************************************/
2038 static bool emitNoGChelper(unsigned IHX);
2040 /************************************************************************/
2041 /* The following logic keeps track of live GC ref values */
2042 /************************************************************************/
2044 bool emitFullArgInfo; // full arg info (including non-ptr arg)?
2045 bool emitFullGCinfo; // full GC pointer maps?
2046 bool emitFullyInt; // fully interruptible code?
2048 #if EMIT_TRACK_STACK_DEPTH
2049 unsigned emitCntStackDepth; // 0 in prolog/epilog, One DWORD elsewhere
2050 unsigned emitMaxStackDepth; // actual computed max. stack depth
2053 /* Stack modelling wrt GC */
2055 bool emitSimpleStkUsed; // using the "simple" stack table?
2058 struct // if emitSimpleStkUsed==true
2060 #define BITS_IN_BYTE (8)
2061 #define MAX_SIMPLE_STK_DEPTH (BITS_IN_BYTE * sizeof(unsigned))
2063 unsigned emitSimpleStkMask; // bit per pushed dword (if it fits. Lowest bit <==> last pushed arg)
2064 unsigned emitSimpleByrefStkMask; // byref qualifier for emitSimpleStkMask
2067 struct // if emitSimpleStkUsed==false
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)
2077 unsigned emitCurStackLvl; // amount of bytes pushed on stack
2079 #if EMIT_TRACK_STACK_DEPTH
2080 /* Functions for stack tracking */
2082 void emitStackPush(BYTE* addr, GCtype gcType);
2084 void emitStackPushN(BYTE* addr, unsigned count);
2086 void emitStackPop(BYTE* addr, bool isCall, unsigned char callInstrSize, unsigned count = 1);
2088 void emitStackKillArgs(BYTE* addr, unsigned count, unsigned char callInstrSize);
2090 void emitRecordGCcall(BYTE* codePos, unsigned char callInstrSize);
2092 // Helpers for the above
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
2098 /* Liveness of stack variables, and registers */
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);
2105 const char* emitGetFrameReg();
2106 void emitDispRegSet(regMaskTP regs);
2107 void emitDispVarSet();
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);
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);
2121 GCtype emitRegGCtype(regNumber reg);
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);
2132 /************************************************************************/
2133 /* The following logic keeps track of initialized data sections */
2134 /************************************************************************/
2136 /* One of these is allocated for every blob of initialized data */
2147 dataSection* dsNext;
2148 UNATIVE_OFFSET dsSize;
2150 // variable-sized array used to store the constant data
2151 // or BasicBlock* array in the block cases.
2155 /* These describe the entire initialized/uninitialized data sections */
2159 dataSection* dsdList;
2160 dataSection* dsdLast;
2161 UNATIVE_OFFSET dsdOffs;
2164 dataSecDsc emitConsDsc;
2166 dataSection* emitDataSecCur;
2168 void emitOutputDataSec(dataSecDsc* sec, BYTE* dst);
2170 /************************************************************************/
2171 /* Handles to the current class and method. */
2172 /************************************************************************/
2174 COMP_HANDLE emitCmpHandle;
2176 /************************************************************************/
2177 /* Helpers for interface to EE */
2178 /************************************************************************/
2180 void emitRecordRelocation(void* location, /* IN */
2181 void* target, /* IN */
2182 WORD fRelocType, /* IN */
2183 WORD slotNum = 0, /* IN */
2184 INT32 addlDelta = 0); /* IN */
2187 void emitHandlePCRelativeMov32(void* location, /* IN */
2188 void* target); /* IN */
2191 void emitRecordCallSite(ULONG instrOffset, /* IN */
2192 CORINFO_SIG_INFO* callSig, /* IN */
2193 CORINFO_METHOD_HANDLE methodHandle); /* IN */
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;
2201 /************************************************************************/
2202 /* Logic to collect and display statistics */
2203 /************************************************************************/
2207 friend void emitterStats(FILE* fout);
2208 friend void emitterStaticStats(FILE* fout);
2210 static size_t emitSizeMethod;
2212 static unsigned emitTotalInsCnt;
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;
2222 static size_t emitTotMemAlloc;
2224 static unsigned emitSmallDspCnt;
2225 static unsigned emitLargeDspCnt;
2227 static unsigned emitSmallCnsCnt;
2228 #define SMALL_CNS_TSZ 256
2229 static unsigned emitSmallCns[SMALL_CNS_TSZ];
2230 static unsigned emitLargeCnsCnt;
2232 static unsigned emitIFcounts[IF_COUNT];
2234 #endif // EMITTER_STATS
2236 /*************************************************************************
2238 * Define any target-dependent emitter members.
2241 #include "emitdef.h"
2243 // It would be better if this were a constructor, but that would entail revamping the allocation
2244 // infrastructure of the entire JIT...
2247 VarSetOps::AssignNoCopy(emitComp, emitPrevGCrefVars, VarSetOps::MakeEmpty(emitComp));
2248 VarSetOps::AssignNoCopy(emitComp, emitInitGCrefVars, VarSetOps::MakeEmpty(emitComp));
2249 VarSetOps::AssignNoCopy(emitComp, emitThisGCrefVars, VarSetOps::MakeEmpty(emitComp));
2253 /*****************************************************************************
2255 * Define any target-dependent inlines.
2258 #include "emitinl.h"
2260 inline void emitter::instrDesc::checkSizes()
2264 C_ASSERT(TINY_IDSC_SIZE == (offsetof(instrDesc, _idDebugOnlyInfo) + sizeof(instrDescDebugInfo*)));
2266 C_ASSERT(SMALL_IDSC_SIZE == (offsetof(instrDesc, _idDebugOnlyInfo) + sizeof(instrDescDebugInfo*)));
2269 C_ASSERT(SMALL_IDSC_SIZE == offsetof(instrDesc, _idAddrUnion));
2272 /*****************************************************************************
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).
2279 inline bool emitter::emitIsTinyInsDsc(instrDesc* id)
2281 return id->idIsTiny();
2284 inline bool emitter::emitIsScnsInsDsc(instrDesc* id)
2286 return id->idIsSmallDsc();
2289 /*****************************************************************************
2291 * Given an instruction, return its "update mode" (RD/WR/RW).
2294 inline insUpdateModes emitter::emitInsUpdateMode(instruction ins)
2297 assert((unsigned)ins < emitInsModeFmtCnt);
2299 return (insUpdateModes)emitInsModeFmtTab[ins];
2302 /*****************************************************************************
2304 * Return the number of epilog blocks generated so far.
2307 inline unsigned emitter::emitGetEpilogCnt()
2309 return emitEpilogCnt;
2312 /*****************************************************************************
2314 * Return the current size of the specified data section.
2317 inline UNATIVE_OFFSET emitter::emitDataSize()
2319 return emitConsDsc.dsdOffs;
2322 /*****************************************************************************
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.
2328 inline void* emitter::emitCurBlock()
2333 /*****************************************************************************
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.
2342 inline unsigned emitGetInsNumFromCodePos(unsigned codePos)
2344 return (codePos & 0xFFFF);
2347 inline unsigned emitGetInsOfsFromCodePos(unsigned codePos)
2349 return (codePos >> 16);
2352 inline unsigned emitter::emitCurOffset()
2354 unsigned codePos = emitCurIGinsCnt + (emitCurIGsize << 16);
2356 assert(emitGetInsOfsFromCodePos(codePos) == emitCurIGsize);
2357 assert(emitGetInsNumFromCodePos(codePos) == emitCurIGinsCnt);
2359 // printf("[IG=%02u;ID=%03u;OF=%04X] => %08X\n", emitCurIG->igNum, emitCurIGinsCnt, emitCurIGsize, codePos);
2364 extern const unsigned short emitTypeSizes[TYP_COUNT];
2367 inline emitAttr emitTypeSize(T type)
2369 assert(TypeGet(type) < TYP_COUNT);
2370 assert(emitTypeSizes[TypeGet(type)] > 0);
2371 return (emitAttr)emitTypeSizes[TypeGet(type)];
2374 extern const unsigned short emitTypeActSz[TYP_COUNT];
2376 inline emitAttr emitActualTypeSize(var_types type)
2378 assert(type < TYP_COUNT);
2379 assert(emitTypeActSz[type] > 0);
2380 return (emitAttr)emitTypeActSz[type];
2383 /*****************************************************************************
2385 * Convert between an operand size in bytes and a smaller encoding used for
2386 * storage in instruction descriptors.
2389 /* static */ inline emitter::opSize emitter::emitEncodeSize(emitAttr size)
2391 assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE ||
2394 return emitSizeEncode[((int)size) - 1];
2397 /* static */ inline emitAttr emitter::emitDecodeSize(emitter::opSize ensz)
2399 assert(((unsigned)ensz) < OPSZ_COUNT);
2401 return emitSizeDecode[ensz];
2404 /*****************************************************************************
2406 * Little helpers to allocate various flavors of instructions.
2409 inline emitter::instrDesc* emitter::emitNewInstrTiny(emitAttr attr)
2413 id = (instrDesc*)emitAllocInstr(TINY_IDSC_SIZE, attr);
2419 inline emitter::instrDesc* emitter::emitNewInstrSmall(emitAttr attr)
2423 // This is larger than the Tiny Descr
2424 id = (instrDesc*)emitAllocInstr(SMALL_IDSC_SIZE, attr);
2425 id->idSetIsSmallDsc();
2430 inline emitter::instrDesc* emitter::emitNewInstr(emitAttr attr)
2432 // This is larger than the Small Descr
2433 return emitAllocInstr(attr);
2436 inline emitter::instrDescJmp* emitter::emitNewInstrJmp()
2438 return emitAllocInstrJmp();
2441 #if !defined(_TARGET_ARM64_)
2442 inline emitter::instrDescLbl* emitter::emitNewInstrLbl()
2444 return emitAllocInstrLbl();
2446 #endif // !_TARGET_ARM64_
2448 inline emitter::instrDesc* emitter::emitNewInstrDsp(emitAttr attr, ssize_t dsp)
2452 instrDesc* id = emitAllocInstr(attr);
2462 instrDescDsp* id = emitAllocInstrDsp(attr);
2464 id->idSetIsLargeDsp();
2465 id->iddDspVal = dsp;
2475 /*****************************************************************************
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.
2483 inline emitter::instrDesc* emitter::emitNewInstrCns(emitAttr attr, ssize_t cns)
2485 if (instrDesc::fitsInSmallCns(cns))
2487 instrDesc* id = emitAllocInstr(attr);
2489 id->idSmallCns(cns);
2493 if (cns - ID_MIN_SMALL_CNS >= SMALL_CNS_TSZ)
2494 emitSmallCns[SMALL_CNS_TSZ - 1]++;
2496 emitSmallCns[cns - ID_MIN_SMALL_CNS]++;
2503 instrDescCns* id = emitAllocInstrCns(attr);
2505 id->idSetIsLargeCns();
2506 id->idcCnsVal = cns;
2516 /*****************************************************************************
2518 * Get the instrDesc size, general purpose version
2522 inline size_t emitter::emitGetInstrDescSize(const instrDesc* id)
2526 return TINY_IDSC_SIZE;
2529 if (id->idIsSmallDsc())
2531 return SMALL_IDSC_SIZE;
2534 if (id->idIsLargeCns())
2536 return sizeof(instrDescCns);
2539 return sizeof(instrDesc);
2542 /*****************************************************************************
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).
2551 inline emitter::instrDesc* emitter::emitNewInstrSC(emitAttr attr, ssize_t cns)
2555 if (instrDesc::fitsInSmallCns(cns))
2557 id = (instrDesc*)emitAllocInstr(SMALL_IDSC_SIZE, attr);
2559 id->idSmallCns(cns);
2560 id->idSetIsSmallDsc();
2564 id = (instrDesc*)emitAllocInstr(sizeof(instrDescCns), attr);
2566 id->idSetIsLargeCns();
2567 ((instrDescCns*)id)->idcCnsVal = cns;
2573 /*****************************************************************************
2575 * Get the instrDesc size for something that contains a constant
2578 inline size_t emitter::emitGetInstrDescSizeSC(const instrDesc* id)
2580 if (id->idIsSmallDsc())
2582 return SMALL_IDSC_SIZE;
2584 else if (id->idIsLargeCns())
2586 return sizeof(instrDescCns);
2590 return sizeof(instrDesc);
2594 /*****************************************************************************
2596 * The following helpers should be used to access the various values that
2597 * get stored in different places within the instruction descriptor.
2600 inline ssize_t emitter::emitGetInsCns(instrDesc* id)
2602 return id->idIsLargeCns() ? ((instrDescCns*)id)->idcCnsVal : id->idSmallCns();
2605 inline ssize_t emitter::emitGetInsDsp(instrDesc* id)
2607 if (id->idIsLargeDsp())
2609 if (id->idIsLargeCns())
2611 return ((instrDescCnsDsp*)id)->iddcDspVal;
2613 return ((instrDescDsp*)id)->iddDspVal;
2618 inline ssize_t emitter::emitGetInsCnsDsp(instrDesc* id, ssize_t* dspPtr)
2620 if (id->idIsLargeCns())
2622 if (id->idIsLargeDsp())
2624 *dspPtr = ((instrDescCnsDsp*)id)->iddcDspVal;
2625 return ((instrDescCnsDsp*)id)->iddcCnsVal;
2630 return ((instrDescCns*)id)->idcCnsVal;
2635 if (id->idIsLargeDsp())
2637 *dspPtr = ((instrDescDsp*)id)->iddDspVal;
2638 return id->idSmallCns();
2643 return id->idSmallCns();
2648 /*****************************************************************************
2650 * Get hold of the argument count for an indirect call.
2653 inline unsigned emitter::emitGetInsCIargs(instrDesc* id)
2655 if (id->idIsLargeCall())
2657 return ((instrDescCGCA*)id)->idcArgCnt;
2661 assert(id->idIsLargeDsp() == false);
2662 assert(id->idIsLargeCns() == false);
2664 ssize_t cns = emitGetInsCns(id);
2665 assert((unsigned)cns == (size_t)cns);
2666 return (unsigned)cns;
2670 /*****************************************************************************
2672 * Returns true if the given register contains a live GC ref.
2675 inline GCtype emitter::emitRegGCtype(regNumber reg)
2677 assert(emitIssuing);
2679 if ((emitThisGCrefRegs & genRegMask(reg)) != 0)
2683 else if ((emitThisByrefRegs & genRegMask(reg)) != 0)
2695 #if EMIT_TRACK_STACK_DEPTH
2696 #define CHECK_STACK_DEPTH() assert((int)emitCurStackLvl >= 0)
2698 #define CHECK_STACK_DEPTH()
2703 /*****************************************************************************
2705 * Return true when a given code offset is properly aligned for the target
2708 inline bool IsCodeAligned(UNATIVE_OFFSET offset)
2710 return ((offset & (CODE_ALIGN - 1)) == 0);
2714 inline BYTE* emitter::emitCodeWithInstructionSize(BYTE* codePtrBefore, BYTE* newCodePointer, unsigned char* instrSize)
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;
2725 /*****************************************************************************
2727 * Add a new IG to the current list, and get it ready to receive code.
2730 inline void emitter::emitNewIG()
2732 insGroup* ig = emitAllocAndLinkIG();
2734 /* It's linked in. Now, set it up to accept code */
2739 #if !defined(JIT32_GCENCODER)
2740 // Start a new instruction group that is not interruptable
2741 inline void emitter::emitDisableGC()
2745 if (emitCurIGnonEmpty())
2751 emitCurIG->igFlags |= IGF_NOGCINTERRUPT;
2755 // Start a new instruction group that is interruptable
2756 inline void emitter::emitEnableGC()
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.
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;
2769 #endif // !defined(JIT32_GCENCODER)
2771 /*****************************************************************************/
2773 /*****************************************************************************/