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