Merge pull request #5998 from briansull/Update-ReturnTypeDesc
[platform/upstream/coreclr.git] / src / jit / gentree.h
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 XX                                                                           XX
8 XX                          GenTree                                          XX
9 XX                                                                           XX
10 XX  This is the node in the semantic tree graph. It represents the operation XX
11 XX  corresponding to the node, and other information during code-gen.        XX
12 XX                                                                           XX
13 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
14 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
15 */
16
17 /*****************************************************************************/
18 #ifndef _GENTREE_H_
19 #define _GENTREE_H_
20 /*****************************************************************************/
21
22 #include "vartype.h"    // For "var_types"
23 #include "target.h"     // For "regNumber"
24 #include "ssaconfig.h"  // For "SsaConfig::RESERVED_SSA_NUM"
25 #include "reglist.h"
26 #include "valuenumtype.h"
27 #include "simplerhash.h"
28 #include "nodeinfo.h"
29 #include "simd.h"
30
31 // Debugging GenTree is much easier if we add a magic virtual function to make the debugger able to figure out what type it's got.
32 // This is enabled by default in DEBUG. To enable it in RET builds (temporarily!), you need to change the build to define DEBUGGABLE_GENTREE=1,
33 // as well as pass /OPT:NOICF to the linker (or else all the vtables get merged, making the debugging value supplied by them useless).
34 // See protojit.nativeproj for a commented example of setting the build flags correctly.
35 #ifndef DEBUGGABLE_GENTREE
36 #ifdef DEBUG
37 #define DEBUGGABLE_GENTREE  1
38 #else // !DEBUG
39 #define DEBUGGABLE_GENTREE  0
40 #endif // !DEBUG
41 #endif // !DEBUGGABLE_GENTREE
42
43 // The SpecialCodeKind enum is used to indicate the type of special (unique)
44 // target block that will be targeted by an instruction.
45 // These are used by:
46 //   GenTreeBoundsChk nodes (SCK_RNGCHK_FAIL, SCK_ARG_EXCPN, SCK_ARG_RNG_EXCPN)
47 //     - these nodes have a field (gtThrowKind) to indicate which kind
48 //   GenTreeOps nodes, for which codegen will generate the branch
49 //     - it will use the appropriate kind based on the opcode, though it's not
50 //       clear why SCK_OVERFLOW == SCK_ARITH_EXCPN
51 // SCK_PAUSE_EXEC is not currently used.
52 //   
53 enum        SpecialCodeKind
54 {
55     SCK_NONE,
56     SCK_RNGCHK_FAIL,                // target when range check fails
57     SCK_PAUSE_EXEC,                 // target to stop (e.g. to allow GC)
58     SCK_DIV_BY_ZERO,                // target for divide by zero (Not used on X86/X64)
59     SCK_ARITH_EXCPN,                // target on arithmetic exception
60     SCK_OVERFLOW = SCK_ARITH_EXCPN, // target on overflow
61     SCK_ARG_EXCPN,                  // target on ArgumentException (currently used only for SIMD intrinsics)
62     SCK_ARG_RNG_EXCPN,              // target on ArgumentOutOfRangeException (currently used only for SIMD intrinsics)
63     SCK_COUNT
64 };
65
66 /*****************************************************************************/
67
68 DECLARE_TYPED_ENUM(genTreeOps,BYTE)
69 {
70     #define GTNODE(en,sn,cm,ok) GT_ ## en,
71     #include "gtlist.h"
72
73     GT_COUNT,
74
75     // GT_CNS_NATIVELONG is the gtOper symbol for GT_CNS_LNG or GT_CNS_INT, depending on the target.
76     // For the 64-bit targets we will only use GT_CNS_INT as it used to represent all the possible sizes
77     // For the 32-bit targets we use a GT_CNS_LNG to hold a 64-bit integer constant and GT_CNS_INT for all others.
78     // In the future when we retarget the JIT for x86 we should consider eliminating GT_CNS_LNG
79     //
80 #ifdef _TARGET_64BIT_
81     GT_CNS_NATIVELONG = GT_CNS_INT,
82 #else
83     GT_CNS_NATIVELONG = GT_CNS_LNG,
84 #endif
85 }
86 END_DECLARE_TYPED_ENUM(genTreeOps,BYTE)
87
88 /*****************************************************************************
89  *
90  *  The following enum defines a set of bit flags that can be used
91  *  to classify expression tree nodes. Note that some operators will
92  *  have more than one bit set, as follows:
93  *
94  *          GTK_CONST    implies    GTK_LEAF
95  *          GTK_RELOP    implies    GTK_BINOP
96  *          GTK_LOGOP    implies    GTK_BINOP
97  */
98
99 enum genTreeKinds
100 {
101     GTK_SPECIAL = 0x0000,       // unclassified operator (special handling reqd)
102
103     GTK_CONST   = 0x0001,       // constant     operator
104     GTK_LEAF    = 0x0002,       // leaf         operator
105     GTK_UNOP    = 0x0004,       // unary        operator
106     GTK_BINOP   = 0x0008,       // binary       operator
107     GTK_RELOP   = 0x0010,       // comparison   operator
108     GTK_LOGOP   = 0x0020,       // logical      operator
109     GTK_ASGOP   = 0x0040,       // assignment   operator
110
111     GTK_KINDMASK= 0x007F,       // operator kind mask
112
113     GTK_COMMUTE = 0x0080,       // commutative  operator
114
115     GTK_EXOP    = 0x0100,       // Indicates that an oper for a node type that extends GenTreeOp (or GenTreeUnOp)
116                                 // by adding non-node fields to unary or binary operator.
117
118     GTK_LOCAL   = 0x0200,       // is a local access (load, store, phi)
119
120     /* Define composite value(s) */
121
122     GTK_SMPOP   = (GTK_UNOP|GTK_BINOP|GTK_RELOP|GTK_LOGOP)
123 };
124
125 /*****************************************************************************/
126
127 #define SMALL_TREE_NODES    1
128
129 /*****************************************************************************/
130
131 DECLARE_TYPED_ENUM(gtCallTypes,BYTE)
132 {
133     CT_USER_FUNC,       // User function
134     CT_HELPER,          // Jit-helper
135     CT_INDIRECT,        // Indirect call
136
137     CT_COUNT            // fake entry (must be last)
138 }
139 END_DECLARE_TYPED_ENUM(gtCallTypes,BYTE)
140
141
142 /*****************************************************************************/
143
144 struct                  BasicBlock;
145  
146 struct                  InlineCandidateInfo;
147
148 /*****************************************************************************/
149
150 // GT_FIELD nodes will be lowered into more "code-gen-able" representations, like
151 // GT_IND's of addresses, or GT_LCL_FLD nodes.  We'd like to preserve the more abstract
152 // information, and will therefore annotate such lowered nodes with FieldSeq's.  A FieldSeq
153 // represents a (possibly) empty sequence of fields.  The fields are in the order
154 // in which they are dereferenced.  The first field may be an object field or a struct field;
155 // all subsequent fields must be struct fields.
156 struct FieldSeqNode
157 {
158     CORINFO_FIELD_HANDLE m_fieldHnd;
159     FieldSeqNode*        m_next;
160
161     FieldSeqNode(CORINFO_FIELD_HANDLE fieldHnd, FieldSeqNode* next) : m_fieldHnd(fieldHnd), m_next(next) {}
162
163     // returns true when this is the pseudo #FirstElem field sequence
164     bool IsFirstElemFieldSeq();
165
166     // returns true when this is the pseudo #ConstantIndex field sequence
167     bool IsConstantIndexFieldSeq();
168
169     // returns true when this is the the pseudo #FirstElem field sequence or the pseudo #ConstantIndex field sequence
170     bool IsPseudoField();
171
172     // Make sure this provides methods that allow it to be used as a KeyFuncs type in SimplerHash.
173     static int GetHashCode(FieldSeqNode fsn)
174     {
175         return static_cast<int>(reinterpret_cast<intptr_t>(fsn.m_fieldHnd)) ^ static_cast<int>(reinterpret_cast<intptr_t>(fsn.m_next));
176     }
177
178     static bool Equals(FieldSeqNode fsn1, FieldSeqNode fsn2)
179     {
180         return fsn1.m_fieldHnd == fsn2.m_fieldHnd && fsn1.m_next == fsn2.m_next;
181     }
182 };
183
184 // This class canonicalizes field sequences.
185 class FieldSeqStore
186 {
187     typedef SimplerHashTable<FieldSeqNode, /*KeyFuncs*/FieldSeqNode, FieldSeqNode*, JitSimplerHashBehavior> FieldSeqNodeCanonMap;
188
189     IAllocator*           m_alloc;
190     FieldSeqNodeCanonMap* m_canonMap;
191
192     static FieldSeqNode   s_notAField;  // No value, just exists to provide an address.
193
194     // Dummy variables to provide the addresses for the "pseudo field handle" statics below.
195     static int FirstElemPseudoFieldStruct;
196     static int ConstantIndexPseudoFieldStruct;
197
198 public:
199     FieldSeqStore(IAllocator* alloc);
200
201     // Returns the (canonical in the store) singleton field sequence for the given handle.
202     FieldSeqNode* CreateSingleton(CORINFO_FIELD_HANDLE fieldHnd);
203
204     // This is a special distinguished FieldSeqNode indicating that a constant does *not*
205     // represent a valid field sequence.  This is "infectious", in the sense that appending it
206     // (on either side) to any field sequence yields the "NotAField()" sequence.
207     static FieldSeqNode* NotAField() { return &s_notAField; }
208
209     // Returns the (canonical in the store) field sequence representing the concatenation of
210     // the sequences represented by "a" and "b".  Assumes that "a" and "b" are canonical; that is,
211     // they are the results of CreateSingleton, NotAField, or Append calls.  If either of the arguments
212     // are the "NotAField" value, so is the result.
213     FieldSeqNode* Append(FieldSeqNode* a, FieldSeqNode* b);
214
215     // We have a few "pseudo" field handles:
216
217     // This treats the constant offset of the first element of something as if it were a field.
218     // Works for method table offsets of boxed structs, or first elem offset of arrays/strings.
219     static CORINFO_FIELD_HANDLE FirstElemPseudoField;
220
221     // If there is a constant index, we make a psuedo field to correspond to the constant added to
222     // offset of the indexed field.  This keeps the field sequence structure "normalized", especially in the
223     // case where the element type is a struct, so we might add a further struct field offset.
224     static CORINFO_FIELD_HANDLE ConstantIndexPseudoField;
225
226     static bool IsPseudoField(CORINFO_FIELD_HANDLE hnd)
227     {
228         return hnd == FirstElemPseudoField || hnd == ConstantIndexPseudoField;
229     }
230 };
231
232
233
234 /*****************************************************************************/
235
236 typedef struct GenTree *  GenTreePtr;
237 struct GenTreeArgList;
238
239 // Forward declarations of the subtypes
240 #define GTSTRUCT_0(fn, en)                struct GenTree##fn;
241 #define GTSTRUCT_1(fn, en)                struct GenTree##fn;
242 #define GTSTRUCT_2(fn, en, en2)           struct GenTree##fn;
243 #define GTSTRUCT_3(fn, en, en2, en3)      struct GenTree##fn;
244 #define GTSTRUCT_4(fn, en, en2, en3, en4) struct GenTree##fn;
245 #define GTSTRUCT_N(fn, ...) struct GenTree##fn;
246 #include "gtstructs.h"
247
248 /*****************************************************************************/
249
250 #ifndef _HOST_64BIT_
251 #include <pshpack4.h>
252 #endif
253
254 struct GenTree
255 {
256     // We use GT_STRUCT_0 only for the category of simple ops.
257 #define GTSTRUCT_0(fn, en)           GenTree##fn* As##fn() \
258                                      { \
259                                          assert(this->OperIsSimple()); \
260                                          return reinterpret_cast<GenTree##fn*>(this); \
261                                      } \
262                                      GenTree##fn& As##fn##Ref() { return *As##fn(); } \
263                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
264 #define GTSTRUCT_1(fn, en)           GenTree##fn* As##fn() \
265                                      { \
266                                          assert(this->gtOper == en); \
267                                          return reinterpret_cast<GenTree##fn*>(this); \
268                                      } \
269                                      GenTree##fn& As##fn##Ref() { return *As##fn(); } \
270                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
271 #define GTSTRUCT_2(fn, en, en2)      GenTree##fn* As##fn() \
272                                      { \
273                                          assert(this->gtOper == en || this->gtOper == en2); \
274                                          return reinterpret_cast<GenTree##fn*>(this); \
275                                      } \
276                                      GenTree##fn& As##fn##Ref() { return *As##fn(); } \
277                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
278 #define GTSTRUCT_3(fn, en, en2, en3) GenTree##fn* As##fn() \
279                                      { \
280                                          assert(this->gtOper == en || this->gtOper == en2 || this->gtOper == en3); \
281                                          return reinterpret_cast<GenTree##fn*>(this); \
282                                      } \
283                                      GenTree##fn& As##fn##Ref() { return *As##fn(); } \
284                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
285
286 #define GTSTRUCT_4(fn, en, en2, en3, en4) GenTree##fn* As##fn() \
287                                      { \
288                                          assert(this->gtOper == en || this->gtOper == en2 || this->gtOper == en3 || this->gtOper == en4); \
289                                          return reinterpret_cast<GenTree##fn*>(this); \
290                                      } \
291                                      GenTree##fn& As##fn##Ref() { return *As##fn(); } \
292                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
293
294 #ifdef DEBUG
295 // VC does not optimize out this loop in retail even though the value it computes is unused
296 // so we need a separate version for non-debug
297 #define GTSTRUCT_N(fn, ...)          GenTree##fn* As##fn() \
298                                      { \
299                                          genTreeOps validOps[] = {__VA_ARGS__}; \
300                                          bool found = false;            \
301                                          for (unsigned i=0; i<ArrLen(validOps); i++) { \
302                                              if (this->gtOper == validOps[i]) \
303                                              {                          \
304                                                  found = true;          \
305                                                  break;                 \
306                                              }                          \
307                                          }                              \
308                                          assert(found);                 \
309                                          return reinterpret_cast<GenTree##fn*>(this); \
310                                      }                                  \
311                                      GenTree##fn& As##fn##Ref() { return *As##fn(); }                    \
312                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
313 #else
314 #define GTSTRUCT_N(fn, ...)          GenTree##fn* As##fn()    \
315                                      { \
316                                          return reinterpret_cast<GenTree##fn*>(this); \
317                                      }                                  \
318                                      GenTree##fn& As##fn##Ref() { return *As##fn(); }                    \
319                                      __declspec(property(get=As##fn##Ref)) GenTree##fn& gt##fn;
320 #endif
321
322 #include "gtstructs.h"
323
324     genTreeOps          gtOper;       // enum subtype BYTE
325     var_types           gtType;       // enum subtype BYTE 
326
327     genTreeOps          OperGet() const { return gtOper; }
328     var_types           TypeGet() const { return gtType; }
329
330 #ifdef DEBUG
331     genTreeOps          gtOperSave;   // Only used to save gtOper when we destroy a node, to aid debugging.
332 #endif
333
334 #if FEATURE_ANYCSE
335
336 #define NO_CSE           (0)
337
338 #define IS_CSE_INDEX(x)  (x != 0)
339 #define IS_CSE_USE(x)    (x > 0)
340 #define IS_CSE_DEF(x)    (x < 0)
341 #define GET_CSE_INDEX(x) ((x > 0) ? x : -x)
342 #define TO_CSE_DEF(x)    (-x)
343
344     signed char       gtCSEnum;        // 0 or the CSE index (negated if def)
345                                        // valid only for CSE expressions
346
347 #endif // FEATURE_ANYCSE
348
349 #if ASSERTION_PROP
350     unsigned short     gtAssertionNum;  // 0 or Assertion table index
351                                         // valid only for non-GT_STMT nodes
352
353     bool         HasAssertion() const             { return gtAssertionNum != 0; }
354     void         ClearAssertion()                 { gtAssertionNum = 0;         }
355
356     unsigned short GetAssertion() const             { return gtAssertionNum;  }
357     void           SetAssertion(unsigned short value) { assert((unsigned short)value == value); gtAssertionNum = (unsigned short)value; }
358
359 #endif
360
361 #if FEATURE_STACK_FP_X87
362     unsigned char       gtFPlvl;        // x87 stack depth at this node
363     void                gtCopyFPlvl(GenTree * other) { gtFPlvl = other->gtFPlvl; }
364     void                gtSetFPlvl(unsigned level) { noway_assert(FitsIn<unsigned char>(level)); gtFPlvl = (unsigned char)level; }
365 #else // FEATURE_STACK_FP_X87
366     void                gtCopyFPlvl(GenTree * other) { }
367     void                gtSetFPlvl(unsigned level) { }
368 #endif // FEATURE_STACK_FP_X87
369
370     //
371     // Cost metrics on the node. Don't allow direct access to the variable for setting.
372     //
373
374 public:
375
376 #ifdef DEBUG
377     // You are not allowed to read the cost values before they have been set in gtSetEvalOrder().
378     // Keep track of whether the costs have been initialized, and assert if they are read before being initialized.
379     // Obviously, this information does need to be initialized when a node is created.
380     // This is public so the dumpers can see it.
381
382     bool gtCostsInitialized;
383 #endif // DEBUG
384
385 #define MAX_COST        UCHAR_MAX
386 #define IND_COST_EX     3             // execution cost for an indirection
387
388     __declspec(property(get=GetCostEx))
389     unsigned char    gtCostEx;     // estimate of expression execution cost
390
391     __declspec(property(get=GetCostSz))
392     unsigned char    gtCostSz;     // estimate of expression code size cost
393
394     unsigned char GetCostEx() const { assert(gtCostsInitialized); return _gtCostEx; }
395     unsigned char GetCostSz() const { assert(gtCostsInitialized); return _gtCostSz; }
396
397     // Set the costs. They are always both set at the same time.
398     // Don't use the "put" property: force calling this function, to make it more obvious in the few places
399     // that set the values.
400     // Note that costs are only set in gtSetEvalOrder() and its callees.
401     void            SetCosts(unsigned costEx, unsigned costSz)
402     {
403         assert(costEx != (unsigned)-1); // looks bogus
404         assert(costSz != (unsigned)-1); // looks bogus
405         INDEBUG(gtCostsInitialized = true;)
406
407         _gtCostEx = (costEx > MAX_COST) ? MAX_COST : (unsigned char)costEx;
408         _gtCostSz = (costSz > MAX_COST) ? MAX_COST : (unsigned char)costSz;
409     }
410
411     // Opimized copy function, to avoid the SetCosts() function comparisons, and make it more clear that a node copy is happening.
412     void            CopyCosts(const GenTree* const tree)
413     {
414         INDEBUG(gtCostsInitialized = tree->gtCostsInitialized;) // If the 'tree' costs aren't initialized, we'll hit an assert below.
415         _gtCostEx = tree->gtCostEx;
416         _gtCostSz = tree->gtCostSz;
417     }
418
419     // Same as CopyCosts, but avoids asserts if the costs we are copying have not been initialized.
420     // This is because the importer, for example, clones nodes, before these costs have been initialized.
421     // Note that we directly access the 'tree' costs, not going through the accessor functions (either
422     // directly or through the properties).
423     void            CopyRawCosts(const GenTree* const tree)
424     {
425         INDEBUG(gtCostsInitialized = tree->gtCostsInitialized;)
426         _gtCostEx = tree->_gtCostEx;
427         _gtCostSz = tree->_gtCostSz;
428     }
429
430 private:
431
432     unsigned char    _gtCostEx;     // estimate of expression execution cost
433     unsigned char    _gtCostSz;     // estimate of expression code size cost
434
435     //
436     // Register or register pair number of the node.
437     //
438
439 #ifdef DEBUG
440 public:
441     enum genRegTag
442     {
443         GT_REGTAG_NONE,     // Nothing has been assigned to _gtRegNum/_gtRegPair
444         GT_REGTAG_REG,      // _gtRegNum  has been assigned
445 #if CPU_LONG_USES_REGPAIR
446         GT_REGTAG_REGPAIR   // _gtRegPair has been assigned
447 #endif
448     };
449     genRegTag GetRegTag() const
450     {
451 #if CPU_LONG_USES_REGPAIR
452         assert(gtRegTag == GT_REGTAG_NONE || gtRegTag == GT_REGTAG_REG || gtRegTag == GT_REGTAG_REGPAIR);
453 #else
454         assert(gtRegTag == GT_REGTAG_NONE || gtRegTag == GT_REGTAG_REG);
455 #endif
456         return gtRegTag;
457     }
458 private:
459     genRegTag           gtRegTag; // What is in _gtRegNum/_gtRegPair?
460 #endif // DEBUG
461
462 private:
463
464     union
465     { 
466         // NOTE: After LSRA, one of these values may be valid even if GTF_REG_VAL is not set in gtFlags.
467         // They store the register assigned to the node. If a register is not assigned, _gtRegNum is set to REG_NA
468         // or _gtRegPair is set to REG_PAIR_NONE, depending on the node type.
469         regNumberSmall   _gtRegNum;     // which register      the value is in
470         regPairNoSmall   _gtRegPair;    // which register pair the value is in
471     };
472
473 public:
474
475     // The register number is stored in a small format (8 bits), but the getters return and the setters take
476     // a full-size (unsigned) format, to localize the casts here.
477
478     __declspec(property(get=GetRegNum,put=SetRegNum))
479     regNumber           gtRegNum;
480
481     // for codegen purposes, is this node a subnode of its parent
482     bool isContained() const;
483
484     bool isContainedIndir() const;
485
486     bool isIndirAddrMode();
487
488     bool isIndir() const;
489
490     bool isContainedIntOrIImmed() const     { return isContained() && IsCnsIntOrI(); }
491
492     bool isContainedFltOrDblImmed() const   { return isContained() && (OperGet() == GT_CNS_DBL); }
493
494     bool isLclField() const                 { return OperGet() == GT_LCL_FLD || OperGet() == GT_STORE_LCL_FLD; }
495
496     bool isContainedLclField() const        { return isContained() && isLclField(); }
497
498     // Indicates whether it is a memory op.
499     // Right now it includes Indir and LclField ops.
500     bool isMemoryOp() const                 { return isIndir() || isLclField(); }
501
502     bool isContainedMemoryOp() const        { return isContained() && isMemoryOp(); }
503
504     regNumber GetRegNum() const
505     {
506         assert((gtRegTag == GT_REGTAG_REG) ||
507                (gtRegTag == GT_REGTAG_NONE)); // TODO-Cleanup: get rid of the NONE case, and fix everyplace that reads undefined values
508         regNumber reg = (regNumber) _gtRegNum;
509         assert((gtRegTag == GT_REGTAG_NONE) || // TODO-Cleanup: get rid of the NONE case, and fix everyplace that reads undefined values
510                (reg >= REG_FIRST &&
511                 reg <= REG_COUNT));
512         return reg;
513     }
514
515     void SetRegNum(regNumber reg)
516     {
517         assert(reg >= REG_FIRST &&
518                reg <= REG_COUNT);
519         // Make sure the upper bits of _gtRegPair are clear
520         _gtRegPair = (regPairNoSmall) 0;
521         _gtRegNum = (regNumberSmall) reg;
522         INDEBUG(gtRegTag = GT_REGTAG_REG;)
523         assert(_gtRegNum == reg);
524     }
525
526 #if CPU_LONG_USES_REGPAIR
527     __declspec(property(get=GetRegPair,put=SetRegPair))
528     regPairNo           gtRegPair;
529
530     regPairNo GetRegPair() const
531     {
532         assert((gtRegTag == GT_REGTAG_REGPAIR) ||
533                (gtRegTag == GT_REGTAG_NONE)); // TODO-Cleanup: get rid of the NONE case, and fix everyplace that reads undefined values
534         regPairNo regPair = (regPairNo) _gtRegPair;
535         assert((gtRegTag == GT_REGTAG_NONE) || // TODO-Cleanup: get rid of the NONE case, and fix everyplace that reads undefined values
536                (regPair >= REG_PAIR_FIRST &&
537                 regPair <= REG_PAIR_LAST) ||
538                (regPair == REG_PAIR_NONE));     // allow initializing to an undefined value
539         return regPair;
540     }
541
542     void SetRegPair(regPairNo regPair)
543     {
544         assert((regPair >= REG_PAIR_FIRST &&
545                 regPair <= REG_PAIR_LAST) ||
546                (regPair == REG_PAIR_NONE));     // allow initializing to an undefined value
547         _gtRegPair = (regPairNoSmall) regPair;
548         INDEBUG(gtRegTag = GT_REGTAG_REGPAIR;)
549         assert(_gtRegPair == regPair);
550     }
551 #endif
552
553     // Copy the _gtRegNum/_gtRegPair/gtRegTag fields
554     void CopyReg(GenTreePtr from);
555
556     void gtClearReg(Compiler* compiler);
557
558     bool gtHasReg() const;
559
560     regMaskTP gtGetRegMask() const;
561
562     unsigned            gtFlags;        // see GTF_xxxx below
563     
564     ValueNumPair        gtVNPair;
565
566     regMaskSmall        gtRsvdRegs;     // set of fixed trashed  registers
567 #ifdef LEGACY_BACKEND
568     regMaskSmall        gtUsedRegs;     // set of used (trashed) registers
569 #endif // LEGACY_BACKEND
570
571 #ifndef LEGACY_BACKEND
572     TreeNodeInfo        gtLsraInfo;
573 #endif // !LEGACY_BACKEND
574
575     void                SetVNsFromNode(GenTreePtr tree)
576     {
577         gtVNPair = tree->gtVNPair;
578     }
579
580     ValueNum            GetVN(ValueNumKind vnk) const
581     {
582         if (vnk == VNK_Liberal)
583         {
584             return gtVNPair.GetLiberal();
585         }
586         else
587         {
588             assert(vnk == VNK_Conservative);
589             return gtVNPair.GetConservative();
590         }
591     }
592     void                SetVN(ValueNumKind vnk, ValueNum vn)
593     {
594         if (vnk == VNK_Liberal)
595         {
596             return gtVNPair.SetLiberal(vn);
597         }
598         else
599         {
600             assert(vnk == VNK_Conservative);
601             return gtVNPair.SetConservative(vn);
602         }
603     }
604     void                SetVNs(ValueNumPair vnp)
605     {
606         gtVNPair = vnp;
607     }
608     void                ClearVN()
609     {
610         gtVNPair = ValueNumPair();          // Initializes both elements to "NoVN".
611     }
612
613     //---------------------------------------------------------------------
614     //  The first set of flags can be used with a large set of nodes, and
615     //  thus they must all have distinct values. That is, one can test any
616     //  expression node for one of these flags.
617     //---------------------------------------------------------------------
618
619     #define GTF_ASG             0x00000001  // sub-expression contains an assignment
620     #define GTF_CALL            0x00000002  // sub-expression contains a  func. call
621     #define GTF_EXCEPT          0x00000004  // sub-expression might throw an exception
622     #define GTF_GLOB_REF        0x00000008  // sub-expression uses global variable(s)
623     #define GTF_ORDER_SIDEEFF   0x00000010  // sub-expression has a re-ordering side effect
624
625     // If you set these flags, make sure that code:gtExtractSideEffList knows how to find the tree,
626     // otherwise the C# (run csc /o-)
627     // var v = side_eff_operation
628     // with no use of v will drop your tree on the floor.
629     #define GTF_PERSISTENT_SIDE_EFFECTS (GTF_ASG|GTF_CALL)
630     #define GTF_SIDE_EFFECT     (GTF_PERSISTENT_SIDE_EFFECTS|GTF_EXCEPT)
631     #define GTF_GLOB_EFFECT     (GTF_SIDE_EFFECT|GTF_GLOB_REF)
632     #define GTF_ALL_EFFECT      (GTF_GLOB_EFFECT|GTF_ORDER_SIDEEFF)
633
634     // The extra flag GTF_DEAD is used to tell the consumer of these flags
635     // that we are calling in the context of performing a CSE, thus we 
636     // should allow the run-once side effects of running a class constructor.
637     //
638     #define GTF_PERSISTENT_SIDE_EFFECTS_IN_CSE (GTF_ASG|GTF_CALL|GTF_DEAD)
639
640     // Can any side-effects be observed externally, say by a caller method?
641     // For assignments, only assignments to global memory can be observed
642     // externally, whereas simple assignments to local variables can not.
643     //
644     // Be careful when using this inside a "try" protected region as the
645     // order of assignments to local variables would need to be preserved
646     // wrt side effects if the variables are alive on entry to the
647     // "catch/finally" region. In such cases, even assignments to locals 
648     // will have to be restricted.
649     #define GTF_GLOBALLY_VISIBLE_SIDE_EFFECTS(flags)                    \
650         (((flags) & (GTF_CALL|GTF_EXCEPT))                   ||         \
651          (((flags) & (GTF_ASG|GTF_GLOB_REF)) == (GTF_ASG|GTF_GLOB_REF)))
652     
653     #define GTF_REVERSE_OPS     0x00000020  // operand op2 should be evaluated before op1 (normally, op1 is evaluated first and op2 is evaluated second)
654     #define GTF_REG_VAL         0x00000040  // operand is sitting in a register (or part of a TYP_LONG operand is sitting in a register)
655
656     #define GTF_SPILLED         0x00000080  // the value   has been spilled
657     #define GTF_SPILLED_OPER    0x00000100  //   op1 has been spilled
658
659 #ifdef LEGACY_BACKEND
660     #define GTF_SPILLED_OP2     0x00000200  //   op2 has been spilled
661 #endif // LEGACY_BACKEND
662
663 #ifdef DEBUG
664 #ifndef LEGACY_BACKEND
665     #define GTF_MORPHED         0x00000200  // the node has been morphed (in the global morphing phase)
666 #else // LEGACY_BACKEND
667     // For LEGACY_BACKEND, 0x00000200 is in use, but we can use the same value as GTF_SPILLED since we
668     // don't call gtSetEvalOrder(), which clears GTF_MORPHED, after GTF_SPILLED has been set.
669     #define GTF_MORPHED         0x00000080  // the node has been morphed (in the global morphing phase)
670 #endif // LEGACY_BACKEND
671 #endif // DEBUG
672
673     #define GTF_REDINDEX_CHECK  0x00000100  // Used for redundant range checks. Disjoint from GTF_SPILLED_OPER
674
675     #define GTF_ZSF_SET         0x00000400  // the zero(ZF) and sign(SF) flags set to the operand
676 #if FEATURE_SET_FLAGS
677     #define GTF_SET_FLAGS       0x00000800  // Requires that codegen for this node set the flags
678                                             // Use gtSetFlags() to check this flags
679 #endif
680     #define GTF_IND_NONFAULTING 0x00000800  // An indir that cannot fault.  GTF_SET_FLAGS is not used on indirs
681
682 #if FEATURE_ANYCSE
683     #define GTF_DEAD            0x00001000  // this node won't be used any more
684 #endif // FEATURE_ANYCSE
685
686     #define GTF_MAKE_CSE        0x00002000  // Hoisted Expression: try hard to make this into CSE  (see optPerformHoistExpr)
687     #define GTF_DONT_CSE        0x00004000  // don't bother CSE'ing this expr
688     #define GTF_COLON_COND      0x00008000  // this node is conditionally executed (part of ? :)
689
690 #if defined(DEBUG) && SMALL_TREE_NODES
691     #define GTF_NODE_LARGE      0x00010000
692     #define GTF_NODE_SMALL      0x00020000
693
694     // Property of the node itself, not the gtOper
695     #define GTF_NODE_MASK       (GTF_COLON_COND | GTF_MORPHED   | GTF_NODE_SMALL | GTF_NODE_LARGE )
696 #else
697     #define GTF_NODE_MASK       (GTF_COLON_COND)
698 #endif
699
700     #define GTF_BOOLEAN         0x00040000  // value is known to be 0/1
701
702     #define GTF_SMALL_OK        0x00080000  // actual small int sufficient
703
704     #define GTF_UNSIGNED        0x00100000  // with GT_CAST:   the source operand is an unsigned type
705                                             // with operators: the specified node is an unsigned operator
706
707     #define GTF_LATE_ARG        0x00200000  // the specified node is evaluated to a temp in the arg list, and this temp is added to gtCallLateArgs.
708
709     #define GTF_SPILL           0x00400000  // needs to be spilled here
710     #define GTF_SPILL_HIGH      0x00040000  // shared with GTF_BOOLEAN
711
712     #define GTF_COMMON_MASK     0x007FFFFF  // mask of all the flags above
713
714     #define GTF_REUSE_REG_VAL   0x00800000  // This is set by the register allocator on nodes whose value already exists in the
715                                             // register assigned to this node, so the code generator does not have to generate
716                                             // code to produce the value.
717                                             // It is currently used only on constant nodes.
718                                             // It CANNOT be set on var (GT_LCL*) nodes, or on indir (GT_IND or GT_STOREIND) nodes, since
719                                             // 1) it is not needed for lclVars and is highly unlikely to be useful for indir nodes, and
720                                             // 2) it conflicts with GTFD_VAR_CSE_REF for lclVars (though this is debug only, and
721                                             //    GTF_IND_ARR_INDEX for indirs.
722
723     //---------------------------------------------------------------------
724     //  The following flags can be used only with a small set of nodes, and
725     //  thus their values need not be distinct (other than within the set
726     //  that goes with a particular node/nodes, of course). That is, one can
727     //  only test for one of these flags if the 'gtOper' value is tested as
728     //  well to make sure it's the right operator for the particular flag.
729     //---------------------------------------------------------------------
730
731     // NB: GTF_VAR_* and GTF_REG_* share the same namespace of flags, because
732     // GT_LCL_VAR nodes may be changed to GT_REG_VAR nodes without resetting
733     // the flags. These are also used by GT_LCL_FLD.
734     #define GTF_VAR_DEF         0x80000000  // GT_LCL_VAR -- this is a definition
735     #define GTF_VAR_USEASG      0x40000000  // GT_LCL_VAR -- this is a use/def for a x<op>=y
736     #define GTF_VAR_USEDEF      0x20000000  // GT_LCL_VAR -- this is a use/def as in x=x+y (only the lhs x is tagged)
737     #define GTF_VAR_CAST        0x10000000  // GT_LCL_VAR -- has been explictly cast (variable node may not be type of local)
738     #define GTF_VAR_ITERATOR    0x08000000  // GT_LCL_VAR -- this is a iterator reference in the loop condition
739     #define GTF_VAR_CLONED      0x01000000  // GT_LCL_VAR -- this node has been cloned or is a clone
740                                             // Relevant for inlining optimizations (see fgInlinePrependStatements)
741
742     // TODO-Cleanup: Currently, GTF_REG_BIRTH is used only by stackfp
743     //         We should consider using it more generally for VAR_BIRTH, instead of
744     //         GTF_VAR_DEF && !GTF_VAR_USEASG
745     #define GTF_REG_BIRTH       0x04000000  // GT_REG_VAR -- enregistered variable born here
746     #define GTF_VAR_DEATH       0x02000000  // GT_LCL_VAR, GT_REG_VAR -- variable dies here (last use)
747
748     #define GTF_VAR_ARR_INDEX   0x00000020  // The variable is part of (the index portion of) an array index expression.
749                                             // Shares a value with GTF_REVERSE_OPS, which is meaningless for local var.
750
751     #define GTF_LIVENESS_MASK   (GTF_VAR_DEF|GTF_VAR_USEASG|GTF_VAR_USEDEF|GTF_REG_BIRTH|GTF_VAR_DEATH)
752
753     #define GTF_CALL_UNMANAGED  0x80000000  // GT_CALL    -- direct call to unmanaged code
754     #define GTF_CALL_INLINE_CANDIDATE 0x40000000 // GT_CALL -- this call has been marked as an inline candidate
755 //  
756     #define GTF_CALL_VIRT_KIND_MASK  0x30000000 
757     #define GTF_CALL_NONVIRT         0x00000000  // GT_CALL    -- a non virtual call
758     #define GTF_CALL_VIRT_STUB       0x10000000  // GT_CALL    -- a stub-dispatch virtual call
759     #define GTF_CALL_VIRT_VTABLE     0x20000000  // GT_CALL    -- a  vtable-based virtual call
760
761     #define GTF_CALL_NULLCHECK  0x08000000  // GT_CALL    -- must check instance pointer for null
762     #define GTF_CALL_POP_ARGS   0x04000000  // GT_CALL    -- caller pop arguments?
763     #define GTF_CALL_HOISTABLE  0x02000000  // GT_CALL    -- call is hoistable
764     #define GTF_CALL_REG_SAVE   0x01000000  // GT_CALL    -- This call preserves all integer regs
765                                             // For additional flags for GT_CALL node see GTF_CALL_M_
766
767 #ifdef DEBUG
768     #define GTFD_VAR_CSE_REF    0x00800000  // GT_LCL_VAR -- This is a CSE LCL_VAR node
769 #endif
770
771     #define GTF_NOP_DEATH         0x40000000  // GT_NOP     -- operand dies here
772
773     #define GTF_FLD_NULLCHECK     0x80000000  // GT_FIELD -- need to nullcheck the "this" pointer
774     #define GTF_FLD_VOLATILE      0x40000000  // GT_FIELD/GT_CLS_VAR -- same as GTF_IND_VOLATILE
775
776     #define GTF_INX_RNGCHK        0x80000000  // GT_INDEX -- the array reference should be range-checked.
777     #define GTF_INX_REFARR_LAYOUT 0x20000000  // GT_INDEX -- same as GTF_IND_REFARR_LAYOUT
778     #define GTF_INX_STRING_LAYOUT 0x40000000  // GT_INDEX -- this uses the special string array layout
779
780     #define GTF_IND_VOLATILE      0x40000000  // GT_IND   -- the load or store must use volatile sematics (this is a nop on X86)
781     #define GTF_IND_REFARR_LAYOUT 0x20000000  // GT_IND   -- the array holds object refs (only effects layout of Arrays)
782     #define GTF_IND_TGTANYWHERE   0x10000000  // GT_IND   -- the target could be anywhere
783     #define GTF_IND_TLS_REF       0x08000000  // GT_IND   -- the target is accessed via TLS
784     #define GTF_IND_ASG_LHS       0x04000000  // GT_IND   -- this GT_IND node is (the effective val) of the LHS of an assignment; don't evaluate it independently.
785     #define GTF_IND_UNALIGNED     0x02000000  // GT_IND   -- the load or store is unaligned (we assume worst case alignment of 1 byte) 
786     #define GTF_IND_INVARIANT     0x01000000  // GT_IND   -- the target is invariant (a prejit indirection)
787     #define GTF_IND_ARR_LEN       0x80000000  // GT_IND   -- the indirection represents an array length (of the REF contribution to its argument).
788     #define GTF_IND_ARR_INDEX     0x00800000  // GT_IND   -- the indirection represents an (SZ) array index (this shares the same value as GTFD_VAR_CSE_REF,
789                                               //             but is disjoint because a GT_LCL_VAR is never an ind (GT_IND or GT_STOREIND)
790
791     #define GTF_IND_FLAGS         (GTF_IND_VOLATILE|GTF_IND_REFARR_LAYOUT|GTF_IND_TGTANYWHERE|GTF_IND_NONFAULTING|\
792                                    GTF_IND_TLS_REF|GTF_IND_UNALIGNED|GTF_IND_INVARIANT|GTF_IND_ARR_INDEX)
793
794     #define GTF_CLS_VAR_ASG_LHS   0x04000000  // GT_CLS_VAR   -- this GT_CLS_VAR node is (the effective val) of the LHS of an assignment; don't evaluate it independently.
795
796     #define GTF_ADDR_ONSTACK      0x80000000  // GT_ADDR    -- this expression is guaranteed to be on the stack
797
798
799     #define GTF_ADDRMODE_NO_CSE 0x80000000  // GT_ADD/GT_MUL/GT_LSH -- Do not CSE this node only, forms complex addressing mode
800
801     #define GTF_MUL_64RSLT      0x40000000  // GT_MUL     -- produce 64-bit result
802
803     #define GTF_MOD_INT_RESULT  0x80000000  // GT_MOD,    -- the real tree represented by this
804                                             // GT_UMOD       node evaluates to an int even though
805                                             //               its type is long.  The result is
806                                             //               placed in the low member of the
807                                             //               reg pair
808
809     #define GTF_RELOP_NAN_UN    0x80000000  // GT_<relop> -- Is branch taken if ops are NaN?
810     #define GTF_RELOP_JMP_USED  0x40000000  // GT_<relop> -- result of compare used for jump or ?:
811     #define GTF_RELOP_QMARK     0x20000000  // GT_<relop> -- the node is the condition for ?:
812     #define GTF_RELOP_SMALL     0x10000000  // GT_<relop> -- We should use a byte or short sized compare (op1->gtType is the small type)
813     #define GTF_RELOP_ZTT       0x08000000  // GT_<relop> -- Loop test cloned for converting while-loops into do-while with explicit "loop test" in the header block.
814
815     #define GTF_QMARK_CAST_INSTOF 0x80000000  // GT_QMARK   -- Is this a top (not nested) level qmark created for castclass or instanceof?
816
817     #define GTF_BOX_VALUE 0x80000000  // GT_BOX   -- "box" is on a value type
818
819     #define GTF_ICON_HDL_MASK   0xF0000000  // Bits used by handle types below
820
821     #define GTF_ICON_SCOPE_HDL  0x10000000  // GT_CNS_INT -- constant is a scope handle
822     #define GTF_ICON_CLASS_HDL  0x20000000  // GT_CNS_INT -- constant is a class handle
823     #define GTF_ICON_METHOD_HDL 0x30000000  // GT_CNS_INT -- constant is a method handle
824     #define GTF_ICON_FIELD_HDL  0x40000000  // GT_CNS_INT -- constant is a field handle
825     #define GTF_ICON_STATIC_HDL 0x50000000  // GT_CNS_INT -- constant is a handle to static data
826     #define GTF_ICON_STR_HDL    0x60000000  // GT_CNS_INT -- constant is a string handle
827     #define GTF_ICON_PSTR_HDL   0x70000000  // GT_CNS_INT -- constant is a ptr to a string handle
828     #define GTF_ICON_PTR_HDL    0x80000000  // GT_CNS_INT -- constant is a ldptr handle
829     #define GTF_ICON_VARG_HDL   0x90000000  // GT_CNS_INT -- constant is a var arg cookie handle
830     #define GTF_ICON_PINVKI_HDL 0xA0000000  // GT_CNS_INT -- constant is a pinvoke calli handle
831     #define GTF_ICON_TOKEN_HDL  0xB0000000  // GT_CNS_INT -- constant is a token handle
832     #define GTF_ICON_TLS_HDL    0xC0000000  // GT_CNS_INT -- constant is a TLS ref with offset
833     #define GTF_ICON_FTN_ADDR   0xD0000000  // GT_CNS_INT -- constant is a function address
834     #define GTF_ICON_CIDMID_HDL 0xE0000000  // GT_CNS_INT -- constant is a class or module ID handle
835     #define GTF_ICON_BBC_PTR    0xF0000000  // GT_CNS_INT -- constant is a basic block count pointer
836
837     #define GTF_ICON_FIELD_OFF  0x08000000  // GT_CNS_INT -- constant is a field offset
838
839     #define GTF_BLK_HASGCPTR    0x80000000  // GT_COPYBLK -- This struct copy will copy GC Pointers
840     #define GTF_BLK_VOLATILE    0x40000000  // GT_INITBLK/GT_COPYBLK -- is a volatile block operation
841     #define GTF_BLK_UNALIGNED   0x02000000  // GT_INITBLK/GT_COPYBLK -- is an unaligned block operation
842
843     #define GTF_OVERFLOW        0x10000000  // GT_ADD, GT_SUB, GT_MUL, - Need overflow check
844                                             // GT_ASG_ADD, GT_ASG_SUB,
845                                             // GT_CAST
846                                             // Use gtOverflow(Ex)() to check this flag
847
848     #define GTF_NO_OP_NO        0x80000000  // GT_NO_OP   --Have the codegenerator generate a special nop
849
850     //----------------------------------------------------------------
851
852     #define GTF_STMT_CMPADD     0x80000000  // GT_STMT    -- added by compiler
853     #define GTF_STMT_HAS_CSE    0x40000000  // GT_STMT    -- CSE def or use was subsituted
854     #define GTF_STMT_TOP_LEVEL  0x20000000  // GT_STMT    -- Top-level statement - true iff gtStmtList->gtPrev == nullptr
855                                             //               True for all stmts when in FGOrderTree
856     #define GTF_STMT_SKIP_LOWER 0x10000000  // GT_STMT    -- Skip lowering if we already lowered an embedded stmt.
857
858     //----------------------------------------------------------------
859
860     GenTreePtr          gtNext;
861     GenTreePtr          gtPrev;
862
863 #ifdef DEBUG
864     unsigned            gtTreeID;
865     unsigned            gtSeqNum;       // liveness traversal order within the current statement
866 #endif
867
868     static
869     const unsigned short   gtOperKindTable[];
870
871     static
872     unsigned        OperKind(unsigned gtOper)
873     {
874         assert(gtOper < GT_COUNT);
875
876         return  gtOperKindTable[gtOper];
877     }
878
879     unsigned        OperKind() const
880     {
881         assert(gtOper < GT_COUNT);
882
883         return  gtOperKindTable[gtOper];
884     }
885
886     static bool     IsExOp(unsigned opKind)
887     {
888         return (opKind & GTK_EXOP) != 0;
889     }
890     // Returns the operKind with the GTK_EX_OP bit removed (the
891     // kind of operator, unary or binary, that is extended).
892     static unsigned StripExOp(unsigned opKind)
893     {
894         return opKind & ~GTK_EXOP;
895     }
896
897     static
898     bool            OperIsConst(genTreeOps gtOper)
899     {
900         return  (OperKind(gtOper) & GTK_CONST  ) != 0;
901     }
902
903     bool            OperIsConst() const
904     {
905         return  (OperKind(gtOper) & GTK_CONST  ) != 0;
906     }
907
908     static
909     bool            OperIsLeaf(genTreeOps gtOper)
910     {
911         return  (OperKind(gtOper) & GTK_LEAF   ) != 0;
912     }
913
914     bool            OperIsLeaf() const
915     {
916         return  (OperKind(gtOper) & GTK_LEAF   ) != 0;
917     }
918
919     static
920     bool            OperIsCompare(genTreeOps gtOper)
921     {
922         return  (OperKind(gtOper) & GTK_RELOP  ) != 0;
923     }
924
925     static
926     bool            OperIsLocal(genTreeOps gtOper)
927     {
928         bool result = (OperKind(gtOper) & GTK_LOCAL) != 0;
929         assert(result ==
930                (gtOper == GT_LCL_VAR ||
931                 gtOper == GT_PHI_ARG ||
932                 gtOper == GT_REG_VAR ||
933                 gtOper == GT_LCL_FLD ||
934                 gtOper == GT_STORE_LCL_VAR ||
935                 gtOper == GT_STORE_LCL_FLD));
936         return result;
937     }
938
939     static
940     bool            OperIsBlkOp(genTreeOps gtOper)
941     {
942         return (gtOper == GT_INITBLK ||
943                 gtOper == GT_COPYBLK ||
944                 gtOper == GT_COPYOBJ);
945     }
946
947     static
948     bool            OperIsCopyBlkOp(genTreeOps gtOper)
949     {
950         return (gtOper == GT_COPYOBJ || gtOper == GT_COPYBLK);
951     }
952
953
954     static
955     bool            OperIsLocalAddr(genTreeOps gtOper)
956     {
957         return (gtOper == GT_LCL_VAR_ADDR ||
958                 gtOper == GT_LCL_FLD_ADDR);
959     }
960
961     static
962     bool           OperIsScalarLocal(genTreeOps gtOper)
963     {
964         return (gtOper == GT_LCL_VAR ||
965                 gtOper == GT_REG_VAR ||
966                 gtOper == GT_STORE_LCL_VAR);
967     }
968
969     static
970     bool            OperIsNonPhiLocal(genTreeOps gtOper)
971     {
972         return OperIsLocal(gtOper) && (gtOper != GT_PHI_ARG);
973     }
974
975     static
976     bool            OperIsLocalRead(genTreeOps gtOper)
977     {
978         return (OperIsLocal(gtOper) && !OperIsLocalStore(gtOper));
979     }
980
981     static
982     bool            OperIsLocalStore(genTreeOps gtOper)
983     {
984         return (gtOper == GT_STORE_LCL_VAR ||
985                 gtOper == GT_STORE_LCL_FLD);
986
987     }
988
989     static
990     bool            OperIsAddrMode(genTreeOps gtOper)
991     {
992         return (gtOper == GT_LEA);
993     }
994
995     bool            OperIsBlkOp() const
996     {
997         return OperIsBlkOp(OperGet());
998     }
999
1000     bool            OperIsCopyBlkOp() const
1001     {
1002         return OperIsCopyBlkOp(OperGet());
1003     }
1004
1005     bool            OperIsPutArgStk() const
1006     {
1007         return gtOper == GT_PUTARG_STK;
1008     }
1009
1010     bool            OperIsAddrMode() const
1011     {
1012         return OperIsAddrMode(OperGet());
1013     }
1014
1015     bool            OperIsLocal() const
1016     {
1017         return OperIsLocal(OperGet());
1018     }
1019
1020     bool            OperIsLocalAddr() const
1021     {
1022         return OperIsLocalAddr(OperGet());
1023     }
1024
1025     bool            OperIsScalarLocal() const
1026     {
1027         return OperIsScalarLocal(OperGet());
1028     }
1029
1030     bool            OperIsNonPhiLocal() const
1031     {
1032         return OperIsNonPhiLocal(OperGet());
1033     }
1034
1035     bool            OperIsLocalStore() const
1036     {
1037         return OperIsLocalStore(OperGet());
1038     }
1039
1040     bool            OperIsLocalRead() const
1041     {
1042         return OperIsLocalRead(OperGet());
1043     }
1044
1045     bool            OperIsCompare()
1046     {
1047         return  (OperKind(gtOper) & GTK_RELOP  ) != 0;
1048     }
1049
1050     static
1051     bool            OperIsLogical(genTreeOps gtOper)
1052     {
1053         return  (OperKind(gtOper) & GTK_LOGOP  ) != 0;
1054     }
1055
1056     bool            OperIsLogical() const
1057     {
1058         return  (OperKind(gtOper) & GTK_LOGOP  ) != 0;
1059     }
1060
1061     static
1062     bool            OperIsShift(genTreeOps gtOper)
1063     {
1064         return (gtOper == GT_LSH) ||
1065                (gtOper == GT_RSH) ||
1066                (gtOper == GT_RSZ);
1067     }
1068
1069     bool            OperIsShift() const
1070     {
1071         return OperIsShift(OperGet());
1072     }
1073
1074     static
1075     bool            OperIsRotate(genTreeOps gtOper)
1076     {
1077         return (gtOper == GT_ROL) ||
1078                (gtOper == GT_ROR);
1079     }
1080
1081     bool            OperIsRotate() const
1082     {
1083         return OperIsRotate(OperGet());
1084     }
1085
1086     static
1087     bool            OperIsShiftOrRotate(genTreeOps gtOper)
1088     {
1089         return OperIsShift(gtOper) ||
1090                OperIsRotate(gtOper);
1091     }
1092
1093     bool            OperIsShiftOrRotate() const
1094     {
1095         return OperIsShiftOrRotate(OperGet());
1096     }
1097
1098     bool            OperIsArithmetic() const
1099     {
1100         genTreeOps op = OperGet();
1101         return     op==GT_ADD
1102                 || op==GT_SUB
1103                 || op==GT_MUL
1104                 || op==GT_DIV
1105                 || op==GT_MOD
1106
1107                 || op==GT_UDIV
1108                 || op==GT_UMOD
1109
1110                 || op==GT_OR
1111                 || op==GT_XOR
1112                 || op==GT_AND
1113
1114                 || OperIsShiftOrRotate(op);
1115     }
1116
1117 #if !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_)
1118     static
1119     bool            OperIsHigh(genTreeOps gtOper)
1120     {
1121         switch (gtOper)
1122         {
1123         case GT_ADD_HI:
1124         case GT_SUB_HI:
1125         case GT_MUL_HI:
1126         case GT_DIV_HI:
1127         case GT_MOD_HI:
1128             return true;
1129         default:
1130             return false;
1131         }
1132     }
1133
1134     bool            OperIsHigh() const
1135     {
1136         return OperIsHigh(OperGet());
1137     }
1138 #endif // !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_)
1139
1140     static
1141     bool            OperIsUnary(genTreeOps gtOper)
1142     {
1143         return  (OperKind(gtOper) & GTK_UNOP   ) != 0;
1144     }
1145
1146     bool            OperIsUnary() const
1147     {
1148         return   OperIsUnary(gtOper);
1149     }
1150
1151     static
1152     bool            OperIsBinary(genTreeOps gtOper)
1153     {
1154         return  (OperKind(gtOper) & GTK_BINOP  ) != 0;
1155     }
1156
1157     bool            OperIsBinary() const
1158     {
1159         return   OperIsBinary(gtOper);
1160     }
1161
1162     static
1163     bool            OperIsSimple(genTreeOps gtOper)
1164     {
1165         return (OperKind(gtOper) & GTK_SMPOP  ) != 0;
1166     }
1167
1168     static
1169     bool            OperIsSpecial(genTreeOps gtOper)
1170     {        
1171         return  ((OperKind(gtOper) & GTK_KINDMASK) == GTK_SPECIAL);
1172     }
1173
1174     bool            OperIsSimple() const
1175     {
1176         return  OperIsSimple(gtOper);
1177     }
1178
1179 #ifdef FEATURE_SIMD
1180     bool             isCommutativeSIMDIntrinsic();
1181 #else // !
1182     bool             isCommutativeSIMDIntrinsic()
1183     {
1184         return false;
1185     }
1186 #endif // FEATURE_SIMD
1187
1188     static
1189     bool            OperIsCommutative(genTreeOps gtOper)
1190     {
1191         return  (OperKind(gtOper) & GTK_COMMUTE) != 0;
1192     }
1193
1194     bool            OperIsCommutative()
1195     {
1196         return OperIsCommutative(gtOper) || (OperIsSIMD(gtOper) && isCommutativeSIMDIntrinsic());
1197     }
1198
1199     static
1200     bool            OperIsAssignment(genTreeOps gtOper)
1201     {
1202         return  (OperKind(gtOper) & GTK_ASGOP) != 0;
1203     }
1204
1205     bool            OperIsAssignment() const
1206     {
1207         return  OperIsAssignment(gtOper);
1208     }
1209
1210     static
1211     bool            OperIsIndir(genTreeOps gtOper)
1212     {
1213         return  gtOper == GT_IND || gtOper == GT_STOREIND || gtOper == GT_NULLCHECK;
1214     }
1215
1216     bool            OperIsIndir() const
1217     {
1218         return  OperIsIndir(gtOper);
1219     }
1220
1221     static 
1222     bool            OperIsImplicitIndir(genTreeOps gtOper)
1223     {
1224         switch (gtOper)
1225         {
1226         case GT_LOCKADD:
1227         case GT_XADD:
1228         case GT_CMPXCHG:
1229         case GT_COPYBLK:
1230         case GT_COPYOBJ:
1231         case GT_INITBLK:
1232         case GT_OBJ:
1233         case GT_BOX:
1234         case GT_ARR_INDEX:
1235         case GT_ARR_ELEM:
1236         case GT_ARR_OFFSET:
1237             return true;
1238         default:
1239             return false;
1240         }
1241     }
1242
1243     bool            OperIsImplicitIndir() const
1244     {
1245         return  OperIsImplicitIndir(gtOper);
1246     }
1247
1248     bool            OperIsStore() const
1249     {
1250         return OperIsStore(gtOper);
1251     }
1252
1253     static
1254     bool            OperIsStore(genTreeOps gtOper)
1255     {
1256         return (gtOper == GT_STOREIND
1257                 || gtOper == GT_STORE_LCL_VAR
1258                 || gtOper == GT_STORE_LCL_FLD
1259                 || gtOper == GT_STORE_CLS_VAR);
1260     }
1261
1262     static
1263     bool            OperIsAtomicOp(genTreeOps gtOper)
1264     {
1265         return  (gtOper == GT_XADD 
1266                  || gtOper == GT_XCHG  
1267                  || gtOper == GT_LOCKADD 
1268                  || gtOper == GT_CMPXCHG);
1269     }
1270
1271     bool            OperIsAtomicOp()
1272     {
1273         return  OperIsAtomicOp(gtOper);
1274     }
1275
1276     // This is basically here for cleaner FEATURE_SIMD #ifdefs.
1277     static
1278     bool            OperIsSIMD(genTreeOps gtOper)
1279     {
1280 #ifdef FEATURE_SIMD
1281         return gtOper == GT_SIMD;
1282 #else // !FEATURE_SIMD
1283         return false;
1284 #endif // !FEATURE_SIMD
1285     }
1286
1287     bool            OperIsSIMD()
1288     {
1289         return OperIsSIMD(gtOper);
1290     }
1291
1292     // Requires that "op" is an op= operator.  Returns
1293     // the corresponding "op".
1294     static
1295     genTreeOps      OpAsgToOper(genTreeOps op);
1296
1297 #ifdef DEBUG
1298     bool            NullOp1Legal() const
1299     {
1300         assert(OperIsSimple(gtOper));
1301         switch (gtOper)
1302         {
1303         case GT_PHI: case GT_LEA: case GT_RETFILT: case GT_NOP:
1304             return true;
1305         case GT_RETURN:
1306             return gtType == TYP_VOID;
1307         default:
1308             return false;
1309         }
1310     }
1311
1312     bool            NullOp2Legal() const
1313     {
1314         assert(OperIsSimple(gtOper));
1315         if (!OperIsBinary(gtOper))
1316         {
1317             return true;
1318         }
1319         switch (gtOper)
1320         {
1321         case GT_LIST:
1322         case GT_INTRINSIC:
1323         case GT_LEA:
1324         case GT_STOREIND:
1325         case GT_INITBLK:
1326         case GT_COPYBLK:
1327         case GT_COPYOBJ:
1328 #ifdef FEATURE_SIMD
1329         case GT_SIMD:
1330 #endif // !FEATURE_SIMD
1331             return true;
1332         default:
1333             return false;
1334         }
1335     }
1336
1337     static
1338     inline bool RequiresNonNullOp2(genTreeOps oper);
1339     bool IsListForMultiRegArg();
1340 #endif // DEBUG
1341
1342     inline bool IsFPZero();
1343     inline bool IsIntegralConst(ssize_t constVal);
1344
1345     inline bool IsBoxedValue();
1346
1347     bool IsList() const
1348     {
1349         return gtOper == GT_LIST;
1350     }
1351
1352     inline GenTreePtr MoveNext();
1353
1354     inline GenTreePtr Current();
1355
1356     inline GenTreePtr *pCurrent();
1357
1358     inline GenTreePtr gtGetOp1();
1359
1360     inline GenTreePtr gtGetOp2();
1361
1362     // Given a tree node, if this is a child of that node, return the pointer to the child node so that it
1363     // can be modified; otherwise, return null.
1364     GenTreePtr*       gtGetChildPointer(GenTreePtr parent);
1365
1366     // Get the parent of this node, and optionally capture the pointer to the child so that it can be modified.
1367     GenTreePtr        gtGetParent(GenTreePtr** parentChildPtrPtr);
1368
1369     inline GenTreePtr gtEffectiveVal(bool commaOnly = false);
1370
1371     // Return the child of this node if it is a GT_RELOAD or GT_COPY; otherwise simply return the node itself
1372     inline GenTree*   gtSkipReloadOrCopy();
1373
1374     // Returns true if it is a call node returning its value in more than one register
1375     inline bool     IsMultiRegCall() const;
1376
1377     // Returns true if it is a GT_COPY or GT_RELOAD node
1378     inline bool     IsCopyOrReload() const;
1379
1380     // Returns true if it is a GT_COPY or GT_RELOAD of a multi-reg call node
1381     inline bool     IsCopyOrReloadOfMultiRegCall() const;
1382
1383     bool            OperMayThrow();
1384
1385     unsigned        GetScaleIndexMul();
1386     unsigned        GetScaleIndexShf();
1387     unsigned        GetScaledIndex();
1388
1389     // Returns true if "addr" is a GT_ADD node, at least one of whose arguments is an integer
1390     // (<= 32 bit) constant.  If it returns true, it sets "*offset" to (one of the) constant value(s), and
1391     // "*addr" to the other argument.
1392     bool            IsAddWithI32Const(GenTreePtr* addr, int* offset);
1393
1394     // Insert 'node' after this node in execution order.
1395     void            InsertAfterSelf(GenTree* node, GenTreeStmt* stmt = nullptr);
1396
1397 public:
1398
1399 #if SMALL_TREE_NODES
1400     static
1401     unsigned char   s_gtNodeSizes[];
1402 #endif
1403
1404     static
1405     void            InitNodeSize();
1406
1407     size_t          GetNodeSize() const;
1408
1409     bool            IsNodeProperlySized() const;
1410
1411     void            CopyFrom(const GenTree* src, Compiler* comp);
1412
1413     static
1414     genTreeOps      ReverseRelop(genTreeOps relop);
1415
1416     static
1417     genTreeOps      SwapRelop(genTreeOps relop);
1418
1419     //---------------------------------------------------------------------
1420
1421     static
1422     bool            Compare(GenTreePtr op1, GenTreePtr op2, bool swapOK = false);
1423
1424     //---------------------------------------------------------------------
1425     #ifdef DEBUG
1426     //---------------------------------------------------------------------
1427
1428     static
1429     const   char *  NodeName(genTreeOps op);
1430
1431     static
1432     const   char *  OpName(genTreeOps op);
1433
1434     //---------------------------------------------------------------------
1435     #endif
1436     //---------------------------------------------------------------------
1437
1438     bool                        IsNothingNode       () const;
1439     void                        gtBashToNOP         ();
1440
1441     // Value number update action enumeration
1442     enum ValueNumberUpdate
1443     {
1444         CLEAR_VN,       // Clear value number
1445         PRESERVE_VN     // Preserve value number
1446     };
1447
1448     void                        SetOper(genTreeOps oper, ValueNumberUpdate vnUpdate = CLEAR_VN);  // set gtOper
1449     void                        SetOperResetFlags   (genTreeOps oper);  // set gtOper and reset flags
1450
1451     void                        ChangeOperConst     (genTreeOps oper);  // ChangeOper(constOper)
1452     // set gtOper and only keep GTF_COMMON_MASK flags
1453     void                        ChangeOper(genTreeOps oper, ValueNumberUpdate vnUpdate = CLEAR_VN);
1454     void                        ChangeOperUnchecked (genTreeOps oper);
1455
1456     bool IsLocal() const
1457     {
1458         return OperIsLocal(OperGet());
1459     }
1460
1461     // Returns "true" iff 'this' is a GT_LCL_FLD or GT_STORE_LCL_FLD on which the type
1462     // is not the same size as the type of the GT_LCL_VAR.
1463     bool IsPartialLclFld(Compiler* comp);
1464
1465     // Returns "true" iff "this" defines a local variable.  Requires "comp" to be the 
1466     // current compilation.  If returns "true", sets "*pLclVarTree" to the
1467     // tree for the local that is defined, and, if "pIsEntire" is non-null, sets "*pIsEntire" to
1468     // true or false, depending on whether the assignment writes to the entirety of the local
1469     // variable, or just a portion of it.
1470     bool DefinesLocal(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, bool* pIsEntire = nullptr);
1471
1472     // Returns true if "this" represents the address of a local, or a field of a local.  If returns true, sets
1473     // "*pLclVarTree" to the node indicating the local variable.  If the address is that of a field of this node,
1474     // sets "*pFldSeq" to the field sequence representing that field, else null.
1475     bool IsLocalAddrExpr(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, FieldSeqNode** pFldSeq);
1476
1477     // Simpler variant of the above which just returns the local node if this is an expression that 
1478     // yields an address into a local
1479     GenTreeLclVarCommon* IsLocalAddrExpr();
1480
1481     // Determine whether this is an assignment tree of the form X = X (op) Y,
1482     // where Y is an arbitrary tree, and X is a lclVar.
1483     unsigned             IsLclVarUpdateTree(GenTree** otherTree, genTreeOps *updateOper);
1484
1485     // If returns "true", "this" may represent the address of a static or instance field
1486     // (or a field of such a field, in the case of an object field of type struct).  
1487     // If returns "true", then either "*pObj" is set to the object reference, 
1488     // or "*pStatic" is set to the baseAddr or offset to be added to the "*pFldSeq" 
1489     // Only one of "*pObj" or "*pStatic" will be set, the other one will be null.
1490     // The boolean return value only indicates that "this" *may* be a field address 
1491     // -- the field sequence must also be checked.  
1492     // If it is a field address, the field sequence will be a sequence of length >= 1, 
1493     // starting with an instance or static field, and optionally continuing with struct fields.
1494     bool IsFieldAddr(Compiler* comp, GenTreePtr* pObj, GenTreePtr* pStatic, FieldSeqNode** pFldSeq);
1495
1496     // Requires "this" to be the address of an array (the child of a GT_IND labeled with GTF_IND_ARR_INDEX).
1497     // Sets "pArr" to the node representing the array (either an array object pointer, or perhaps a byref to the some element).
1498     // Sets "*pArrayType" to the class handle for the array type.
1499     // Sets "*inxVN" to the value number inferred for the array index.
1500     // Sets "*pFldSeq" to the sequence, if any, of struct fields used to index into the array element.
1501     void ParseArrayAddress(Compiler* comp, 
1502                            struct ArrayInfo* arrayInfo, 
1503                            GenTreePtr* pArr, 
1504                            ValueNum* pInxVN,
1505                            FieldSeqNode** pFldSeq);
1506
1507     // Helper method for the above.
1508     void ParseArrayAddressWork(Compiler* comp, ssize_t inputMul, GenTreePtr* pArr, ValueNum* pInxVN, ssize_t* pOffset, FieldSeqNode** pFldSeq);
1509
1510     // Requires "this" to be a GT_IND.  Requires the outermost caller to set "*pFldSeq" to nullptr.
1511     // Returns true if it is an array index expression, or access to a (sequence of) struct field(s)
1512     // within a struct array element.  If it returns true, sets *arrayInfo to the array information, and sets *pFldSeq to the sequence
1513     // of struct field accesses.
1514     bool ParseArrayElemForm(Compiler* comp, ArrayInfo* arrayInfo, FieldSeqNode** pFldSeq);
1515
1516     // Requires "this" to be the address of a (possible) array element (or struct field within that).
1517     // If it is, sets "*arrayInfo" to the array access info, "*pFldSeq" to the sequence of struct fields
1518     // accessed within the array element, and returns true.  If not, returns "false".
1519     bool ParseArrayElemAddrForm(Compiler* comp, ArrayInfo* arrayInfo, FieldSeqNode** pFldSeq);
1520
1521     // Requires "this" to be an int expression.  If it is a sequence of one or more integer constants added together,
1522     // returns true and sets "*pFldSeq" to the sequence of fields with which those constants are annotated.
1523     bool ParseOffsetForm(Compiler* comp, FieldSeqNode** pFldSeq);
1524
1525     // Labels "*this" as an array index expression: label all constants and variables that could contribute, as part of an affine expression, to the value of the
1526     // of the index.
1527     void LabelIndex(Compiler* comp, bool isConst = true);
1528
1529     // Assumes that "this" occurs in a context where it is being dereferenced as the LHS of an assignment-like
1530     // statement (assignment, initblk, or copyblk).  The "width" should be the number of bytes copied by the
1531     // operation.  Returns "true" if "this" is an address of (or within)
1532     // a local variable; sets "*pLclVarTree" to that local variable instance; and, if "pIsEntire" is non-null,
1533     // sets "*pIsEntire" to true if this assignment writes the full width of the local.
1534     bool DefinesLocalAddr(Compiler* comp, unsigned width, GenTreeLclVarCommon** pLclVarTree, bool* pIsEntire);
1535
1536     bool                        IsRegVar            () const
1537     {
1538         return OperGet() == GT_REG_VAR?true:false;
1539     }
1540     bool                        InReg() const
1541     {
1542         return (gtFlags & GTF_REG_VAL)?true:false;       
1543     }
1544     void                        SetInReg()
1545     {
1546         gtFlags |= GTF_REG_VAL;
1547     }
1548
1549     regNumber                   GetReg() const
1550     {
1551         return InReg() ? gtRegNum : REG_NA;
1552     }
1553     bool                        IsRegVarDeath       () const
1554     {
1555         assert(OperGet() == GT_REG_VAR);
1556         return (gtFlags & GTF_VAR_DEATH)?true:false;       
1557     }
1558     bool                        IsRegVarBirth       () const
1559     {
1560         assert(OperGet() == GT_REG_VAR);
1561         return (gtFlags & GTF_REG_BIRTH)?true:false;       
1562     }
1563     bool                        IsReverseOp() const
1564     {
1565         return (gtFlags & GTF_REVERSE_OPS)?true:false;
1566     }
1567
1568     inline bool                 IsCnsIntOrI         () const;
1569
1570     inline bool                 IsIntegralConst     () const;
1571
1572     inline bool                 IsIntCnsFitsInI32   ();
1573
1574     inline bool                 IsCnsFltOrDbl() const;
1575
1576     inline bool                 IsCnsNonZeroFltOrDbl();    
1577
1578     bool                        IsIconHandle        () const
1579     {
1580         assert(gtOper == GT_CNS_INT);
1581         return (gtFlags & GTF_ICON_HDL_MASK) ? true : false;
1582     }
1583
1584     bool                        IsIconHandle        (unsigned handleType) const
1585     {
1586         assert(gtOper == GT_CNS_INT);
1587         assert((handleType & GTF_ICON_HDL_MASK) != 0);      // check that handleType is one of the valid GTF_ICON_* values
1588         assert((handleType & ~GTF_ICON_HDL_MASK) == 0);
1589         return (gtFlags & GTF_ICON_HDL_MASK) == handleType;
1590     }
1591
1592     // Return just the part of the flags corresponding to the GTF_ICON_*_HDL flag. For example,
1593     // GTF_ICON_SCOPE_HDL. The tree node must be a const int, but it might not be a handle, in which
1594     // case we'll return zero.
1595     unsigned                    GetIconHandleFlag   () const
1596     {
1597         assert(gtOper == GT_CNS_INT);
1598         return (gtFlags & GTF_ICON_HDL_MASK);
1599     }
1600
1601     // Mark this node as no longer being a handle; clear its GTF_ICON_*_HDL bits.
1602     void                        ClearIconHandleMask()
1603     {
1604         assert(gtOper == GT_CNS_INT);
1605         gtFlags &= ~GTF_ICON_HDL_MASK;
1606     }
1607
1608     // Return true if the two GT_CNS_INT trees have the same handle flag (GTF_ICON_*_HDL).
1609     static bool                 SameIconHandleFlag(GenTree* t1, GenTree* t2)
1610     {
1611         return t1->GetIconHandleFlag() == t2->GetIconHandleFlag();
1612     }
1613
1614     bool                        IsArgPlaceHolderNode() const { return OperGet() == GT_ARGPLACE; }
1615     bool                        IsCall              () const { return OperGet() == GT_CALL; }
1616     bool                        IsStatement         () const { return OperGet() == GT_STMT; }
1617     inline bool                 IsHelperCall        ();
1618
1619     bool                        IsVarAddr           () const;
1620     bool                        gtOverflow          () const;
1621     bool                        gtOverflowEx        () const;
1622     bool                        gtSetFlags          () const;
1623     bool                        gtRequestSetFlags   ();
1624 #ifdef DEBUG
1625     bool                        gtIsValid64RsltMul  ();
1626     static int                  gtDispFlags         (unsigned flags);
1627 #endif
1628
1629     // cast operations 
1630     inline var_types            CastFromType();
1631     inline var_types&           CastToType();
1632
1633     // Returns "true" iff "*this" is an assignment (GT_ASG) tree that defines an SSA name (lcl = phi(...));
1634     bool IsPhiDefn();
1635
1636     // Returns "true" iff "*this" is a statement containing an assignment that defines an SSA name (lcl = phi(...));
1637     bool IsPhiDefnStmt();
1638
1639     // Can't use an assignment operator, because we need the extra "comp" argument
1640     // (to provide the allocator necessary for the VarSet assignment).
1641     // TODO-Cleanup: Not really needed now, w/o liveset on tree nodes
1642     void CopyTo(class Compiler* comp, const GenTree& gt);
1643
1644     // Like the above, excepts assumes copying from small node to small node.
1645     // (Following the code it replaces, it does *not* copy the GenTree fields,
1646     // which CopyTo does.)
1647     void CopyToSmall(const GenTree& gt);
1648
1649     // Because of the fact that we hid the assignment operator of "BitSet" (in DEBUG),
1650     // we can't synthesize an assignment operator.
1651     // TODO-Cleanup: Could change this w/o liveset on tree nodes
1652     // (This is also necessary for the VTable trick.)
1653     GenTree() {}
1654
1655     // Returns the number of children of the current node.
1656     unsigned NumChildren();
1657
1658     // Requires "childNum < NumChildren()".  Returns the "n"th child of "this."
1659     GenTreePtr GetChild(unsigned childNum);
1660
1661     // The maximum possible # of children of any node.
1662     static const int MAX_CHILDREN = 6;
1663
1664     bool IsReuseRegVal() const
1665     {
1666         // This can be extended to non-constant nodes, but not to local or indir nodes.
1667         if(OperIsConst() && ((gtFlags & GTF_REUSE_REG_VAL) != 0))
1668         {
1669             return true;
1670         }
1671         return false;
1672     }
1673     void SetReuseRegVal()
1674     {
1675         assert(OperIsConst());
1676         gtFlags |= GTF_REUSE_REG_VAL;
1677     }
1678     void ResetReuseRegVal()
1679     {
1680         assert(OperIsConst());
1681         gtFlags &= ~GTF_REUSE_REG_VAL;
1682     }
1683
1684 #ifdef DEBUG
1685   private:
1686     GenTree& operator=(const GenTree& gt) {
1687         assert(!"Don't copy");
1688         return *this;
1689     }
1690 #endif // DEBUG
1691
1692 #if DEBUGGABLE_GENTREE
1693     // In DEBUG builds, add a dummy virtual method, to give the debugger run-time type information.
1694     virtual void DummyVirt() {}
1695
1696     typedef void* VtablePtr;
1697
1698     VtablePtr GetVtableForOper(genTreeOps oper);
1699     void SetVtableForOper(genTreeOps oper);
1700
1701     static VtablePtr s_vtablesForOpers[GT_COUNT];
1702     static VtablePtr s_vtableForOp;
1703 #endif // DEBUGGABLE_GENTREE
1704
1705   public:
1706     inline void* operator new(size_t sz, class Compiler*, genTreeOps oper);
1707
1708     inline GenTree(genTreeOps oper, var_types type
1709                    DEBUGARG(bool largeNode = false));
1710 };
1711
1712
1713 /*****************************************************************************/
1714 // In the current design, we never instantiate GenTreeUnOp: it exists only to be
1715 // used as a base class.  For unary operators, we instantiate GenTreeOp, with a NULL second
1716 // argument.  We check that this is true dynamically.  We could tighten this and get static
1717 // checking, but that would entail accessing the first child of a unary operator via something
1718 // like gtUnOp.gtOp1 instead of gtOp.gtOp1.
1719 struct GenTreeUnOp: public GenTree
1720 {
1721     GenTreePtr      gtOp1;
1722
1723 protected:
1724     GenTreeUnOp(genTreeOps oper, var_types type 
1725                 DEBUGARG(bool largeNode = false)) : 
1726         GenTree(oper, type 
1727                 DEBUGARG(largeNode)),
1728         gtOp1(nullptr)
1729         {}
1730
1731     GenTreeUnOp(genTreeOps oper, var_types type, GenTreePtr op1 
1732                 DEBUGARG(bool largeNode = false)) : 
1733         GenTree(oper, type 
1734                 DEBUGARG(largeNode)), 
1735         gtOp1(op1)
1736         {
1737             assert(op1 != nullptr || NullOp1Legal());
1738             if (op1 != nullptr)  // Propagate effects flags from child.
1739                 gtFlags |= op1->gtFlags & GTF_ALL_EFFECT;
1740         }
1741
1742 #if DEBUGGABLE_GENTREE
1743     GenTreeUnOp() : GenTree(), gtOp1(nullptr) {}
1744 #endif
1745 };
1746
1747 struct GenTreeOp: public GenTreeUnOp
1748 {
1749     GenTreePtr      gtOp2;
1750
1751     GenTreeOp(genTreeOps oper, var_types type, GenTreePtr op1, GenTreePtr op2 
1752               DEBUGARG(bool largeNode = false)) : 
1753         GenTreeUnOp(oper, type, op1 
1754                     DEBUGARG(largeNode)), 
1755         gtOp2(op2) 
1756         {
1757             // comparisons are always integral types
1758             assert(!GenTree::OperIsCompare(oper) || varTypeIsIntegral(type));
1759             // Binary operators, with a few exceptions, require a non-nullptr
1760             // second argument.
1761             assert(op2 != nullptr || NullOp2Legal());
1762             // Unary operators, on the other hand, require a null second argument.
1763             assert(!OperIsUnary(oper) || op2 == nullptr);
1764             // Propagate effects flags from child.  (UnOp handled this for first child.)
1765             if (op2 != nullptr)
1766             {
1767                 gtFlags |= op2->gtFlags & GTF_ALL_EFFECT;
1768             }
1769         }
1770
1771     // A small set of types are unary operators with optional arguments.  We use
1772     // this constructor to build those.
1773     GenTreeOp(genTreeOps oper, var_types type 
1774               DEBUGARG(bool largeNode = false)) : 
1775         GenTreeUnOp(oper, type 
1776                     DEBUGARG(largeNode)),
1777         gtOp2(nullptr)
1778         {
1779             // Unary operators with optional arguments:
1780             assert(oper == GT_NOP     ||
1781                    oper == GT_RETURN  ||
1782                    oper == GT_RETFILT ||
1783                    OperIsBlkOp(oper));
1784         }
1785
1786 #if DEBUGGABLE_GENTREE
1787     GenTreeOp() : GenTreeUnOp(), gtOp2(nullptr) {}
1788 #endif
1789 };
1790
1791
1792 struct GenTreeVal: public GenTree
1793 {
1794     size_t          gtVal1;
1795
1796     GenTreeVal(genTreeOps oper, var_types type, ssize_t val) : 
1797         GenTree(oper, type),
1798         gtVal1(val)
1799         {}
1800 #if DEBUGGABLE_GENTREE
1801     GenTreeVal() : GenTree() {}
1802 #endif
1803 };
1804
1805 struct GenTreeIntConCommon: public GenTree
1806 {
1807     inline INT64   LngValue();
1808     inline void    SetLngValue(INT64 val);
1809     inline ssize_t IconValue();
1810     inline void SetIconValue(ssize_t val);
1811     
1812     GenTreeIntConCommon(genTreeOps oper, var_types type
1813                         DEBUGARG(bool largeNode = false)) : 
1814         GenTree(oper, type 
1815                 DEBUGARG(largeNode))
1816         {}
1817
1818         bool FitsInI32() 
1819         {  
1820             return FitsInI32(IconValue());
1821         }
1822
1823         static bool FitsInI32(ssize_t val)
1824         {
1825 #ifdef _TARGET_64BIT_
1826             return (int)val == val;
1827 #else
1828             return true;
1829 #endif
1830         }
1831
1832         bool ImmedValNeedsReloc(Compiler* comp);
1833         bool GenTreeIntConCommon::ImmedValCanBeFolded(Compiler* comp, genTreeOps op);
1834
1835 #ifdef _TARGET_XARCH_
1836         bool FitsInAddrBase(Compiler* comp);
1837         bool AddrNeedsReloc(Compiler* comp);
1838 #endif
1839
1840 #if DEBUGGABLE_GENTREE
1841     GenTreeIntConCommon() : GenTree() {}
1842 #endif
1843 };
1844
1845 // node representing a read from a physical register
1846 struct GenTreePhysReg: public GenTree
1847 {
1848     // physregs need a field beyond gtRegNum because 
1849     // gtRegNum indicates the destination (and can be changed)
1850     // whereas reg indicates the source
1851     regNumber gtSrcReg;
1852     GenTreePhysReg(regNumber r, var_types type=TYP_I_IMPL) : 
1853         GenTree(GT_PHYSREG, type), gtSrcReg(r)
1854     {
1855     }
1856 #if DEBUGGABLE_GENTREE
1857     GenTreePhysReg() : GenTree() {}
1858 #endif
1859 };
1860
1861 #ifndef LEGACY_BACKEND
1862 // gtJumpTable - Switch Jump Table
1863 //
1864 // This node stores a DWORD constant that represents the
1865 // absolute address of a jump table for switches.  The code 
1866 // generator uses this table to code the destination for every case
1867 // in an array of addresses which starting position is stored in
1868 // this constant.
1869 struct GenTreeJumpTable : public GenTreeIntConCommon
1870 {
1871     ssize_t        gtJumpTableAddr;
1872
1873     GenTreeJumpTable(var_types type
1874                   DEBUGARG(bool largeNode = false)) : 
1875         GenTreeIntConCommon(GT_JMPTABLE, type 
1876                             DEBUGARG(largeNode)) 
1877         {}
1878 #if DEBUGGABLE_GENTREE
1879     GenTreeJumpTable() : GenTreeIntConCommon() {}
1880 #endif // DEBUG
1881 };
1882 #endif // !LEGACY_BACKEND
1883
1884 /* gtIntCon -- integer constant (GT_CNS_INT) */
1885 struct GenTreeIntCon: public GenTreeIntConCommon
1886 {
1887     /* 
1888      * This is the GT_CNS_INT struct definition.
1889      * It's used to hold for both int constants and pointer handle constants.
1890      * For the 64-bit targets we will only use GT_CNS_INT as it used to represent all the possible sizes
1891      * For the 32-bit targets we use a GT_CNS_LNG to hold a 64-bit integer constant and GT_CNS_INT for all others.
1892      * In the future when we retarget the JIT for x86 we should consider eliminating GT_CNS_LNG
1893      */
1894     ssize_t         gtIconVal;   // Must overlap and have the same offset with the gtIconVal field in GenTreeLngCon below.
1895     
1896     /* The InitializeArray intrinsic needs to go back to the newarray statement
1897        to find the class handle of the array so that we can get its size.  However,
1898        in ngen mode, the handle in that statement does not correspond to the compile
1899        time handle (rather it lets you get a handle at run-time).  In that case, we also
1900        need to store a compile time handle, which goes in this gtCompileTimeHandle field.
1901     */
1902     ssize_t         gtCompileTimeHandle;
1903
1904     // TODO-Cleanup: It's not clear what characterizes the cases where the field
1905     // above is used.  It may be that its uses and those of the "gtFieldSeq" field below
1906     // are mutually exclusive, and they could be put in a union.  Or else we should separate
1907     // this type into three subtypes.
1908
1909     // If this constant represents the offset of one or more fields, "gtFieldSeq" represents that
1910     // sequence of fields.
1911     FieldSeqNode*   gtFieldSeq;
1912
1913 #if defined (LATE_DISASM)
1914
1915     /*  If the constant was morphed from some other node,
1916         these fields enable us to get back to what the node
1917         originally represented. See use of gtNewIconHandleNode()
1918      */
1919
1920     union
1921     {
1922         /* Template struct - The significant field of the other
1923          * structs should overlap exactly with this struct
1924          */
1925
1926         struct
1927         {
1928             unsigned        gtIconHdl1;
1929             void *          gtIconHdl2;
1930         }
1931                             gtIconHdl;
1932
1933         /* GT_FIELD, etc */
1934
1935         struct
1936         {
1937             unsigned                gtIconCPX;
1938             CORINFO_CLASS_HANDLE    gtIconCls;
1939         }
1940                                     gtIconFld;
1941     };
1942 #endif
1943
1944     GenTreeIntCon(var_types type, ssize_t value
1945                   DEBUGARG(bool largeNode = false)) : 
1946         GenTreeIntConCommon(GT_CNS_INT, type 
1947                             DEBUGARG(largeNode)),
1948         gtIconVal(value),
1949         gtCompileTimeHandle(0),
1950         gtFieldSeq(FieldSeqStore::NotAField())
1951         {}
1952
1953     GenTreeIntCon(var_types type, ssize_t value, FieldSeqNode* fields
1954                   DEBUGARG(bool largeNode = false)) : 
1955         GenTreeIntConCommon(GT_CNS_INT, type 
1956                             DEBUGARG(largeNode)),
1957         gtIconVal(value),
1958         gtCompileTimeHandle(0),
1959         gtFieldSeq(fields)
1960         {
1961             assert(fields != NULL);
1962         }
1963
1964 #ifdef _TARGET_64BIT_
1965     void TruncateOrSignExtend32()
1966     {        
1967         if (gtFlags & GTF_UNSIGNED)
1968         {
1969             gtIconVal = UINT32(gtIconVal);
1970         }
1971         else
1972         {
1973             gtIconVal = INT32(gtIconVal);
1974         }
1975     }
1976 #endif // _TARGET_64BIT_
1977
1978 #if DEBUGGABLE_GENTREE
1979     GenTreeIntCon() : GenTreeIntConCommon() {}
1980 #endif
1981 };
1982
1983
1984 /* gtLngCon -- long    constant (GT_CNS_LNG) */
1985
1986 struct GenTreeLngCon: public GenTreeIntConCommon
1987 {
1988     INT64 gtLconVal;   // Must overlap and have the same offset with the gtIconVal field in GenTreeIntCon above.
1989     INT32 LoVal()
1990     {
1991         return (INT32)(gtLconVal & 0xffffffff);
1992     }
1993
1994     INT32 HiVal()
1995     {
1996         return (INT32)(gtLconVal >> 32);;
1997     }
1998
1999     GenTreeLngCon(INT64 val) : 
2000         GenTreeIntConCommon(GT_CNS_NATIVELONG, TYP_LONG)
2001         { SetLngValue(val); }
2002 #if DEBUGGABLE_GENTREE
2003     GenTreeLngCon() : GenTreeIntConCommon() {}
2004 #endif
2005 };
2006
2007
2008 inline INT64 GenTreeIntConCommon::LngValue()
2009 {
2010 #ifndef _TARGET_64BIT_
2011     assert(gtOper == GT_CNS_LNG);
2012     return AsLngCon()->gtLconVal;
2013 #else
2014     return IconValue();
2015 #endif
2016 }
2017
2018 inline void GenTreeIntConCommon::SetLngValue(INT64 val)
2019 {
2020 #ifndef _TARGET_64BIT_
2021     assert(gtOper == GT_CNS_LNG);
2022     AsLngCon()->gtLconVal = val;
2023 #else
2024     // Compile time asserts that these two fields overlap and have the same offsets:  gtIconVal and gtLconVal
2025     C_ASSERT(offsetof(GenTreeLngCon, gtLconVal) == offsetof(GenTreeIntCon, gtIconVal));
2026     C_ASSERT(sizeof(AsLngCon()->gtLconVal) == sizeof(AsIntCon()->gtIconVal));
2027
2028     SetIconValue(ssize_t(val));
2029 #endif
2030 }
2031
2032 inline ssize_t GenTreeIntConCommon::IconValue()
2033 {
2034     assert(gtOper == GT_CNS_INT);   //  We should never see a GT_CNS_LNG for a 64-bit target!
2035     return AsIntCon()->gtIconVal;
2036 }
2037
2038 inline void GenTreeIntConCommon::SetIconValue(ssize_t val)
2039 {
2040     assert(gtOper == GT_CNS_INT);   //  We should never see a GT_CNS_LNG for a 64-bit target!
2041     AsIntCon()->gtIconVal = val;
2042 }
2043
2044 /* gtDblCon -- double  constant (GT_CNS_DBL) */
2045
2046 struct GenTreeDblCon: public GenTree
2047 {
2048     double          gtDconVal;
2049
2050     bool            isBitwiseEqual(GenTreeDblCon* other)
2051     {
2052         unsigned __int64 bits = *(unsigned __int64 *)(&gtDconVal);
2053         unsigned __int64 otherBits = *(unsigned __int64 *)(&(other->gtDconVal));
2054         return (bits == otherBits);
2055     }
2056
2057     GenTreeDblCon(double val) : 
2058         GenTree(GT_CNS_DBL, TYP_DOUBLE),
2059         gtDconVal(val)
2060         {}
2061 #if DEBUGGABLE_GENTREE
2062     GenTreeDblCon() : GenTree() {}
2063 #endif
2064 };
2065
2066
2067 /* gtStrCon -- string  constant (GT_CNS_STR) */
2068
2069 struct GenTreeStrCon: public GenTree
2070 {
2071     unsigned              gtSconCPX;
2072     CORINFO_MODULE_HANDLE gtScpHnd;
2073
2074     // Because this node can come from an inlined method we need to
2075     // have the scope handle, since it will become a helper call.
2076     GenTreeStrCon(unsigned sconCPX, CORINFO_MODULE_HANDLE mod
2077                   DEBUGARG(bool largeNode = false)) : 
2078         GenTree(GT_CNS_STR, TYP_REF 
2079                 DEBUGARG(largeNode)),
2080         gtSconCPX(sconCPX), gtScpHnd(mod)
2081         {}
2082 #if DEBUGGABLE_GENTREE
2083     GenTreeStrCon() : GenTree() {}
2084 #endif
2085 };
2086
2087 // Common supertype of LCL_VAR, LCL_FLD, REG_VAR, PHI_ARG
2088 // This inherits from UnOp because lclvar stores are Unops
2089 struct GenTreeLclVarCommon: public GenTreeUnOp
2090 {
2091 private:
2092     unsigned        _gtLclNum;      // The local number. An index into the Compiler::lvaTable array.
2093     unsigned        _gtSsaNum;      // The SSA number.
2094
2095 public:
2096     GenTreeLclVarCommon(genTreeOps oper, var_types type, unsigned lclNum
2097                         DEBUGARG(bool largeNode = false)) : 
2098         GenTreeUnOp(oper, type 
2099                 DEBUGARG(largeNode))
2100     {
2101         SetLclNum(lclNum);
2102     }
2103
2104     unsigned GetLclNum() const
2105     {
2106         return _gtLclNum;
2107     }
2108     __declspec(property(get=GetLclNum))  unsigned  gtLclNum;
2109
2110     void SetLclNum(unsigned lclNum)
2111     {
2112         _gtLclNum = lclNum;
2113         _gtSsaNum = SsaConfig::RESERVED_SSA_NUM;
2114     }
2115
2116     unsigned GetSsaNum() const
2117     {
2118         return _gtSsaNum;
2119     }
2120     __declspec(property(get=GetSsaNum))  unsigned  gtSsaNum;
2121
2122     void SetSsaNum(unsigned ssaNum)
2123     {
2124         _gtSsaNum = ssaNum;
2125     }
2126
2127     bool HasSsaName()
2128     {
2129         return (gtSsaNum != SsaConfig::RESERVED_SSA_NUM);
2130     }
2131
2132 #if DEBUGGABLE_GENTREE
2133     GenTreeLclVarCommon() : GenTreeUnOp() {}
2134 #endif
2135 };
2136
2137 // gtLclVar -- load/store/addr of local variable 
2138
2139 struct GenTreeLclVar: public GenTreeLclVarCommon
2140 {
2141     IL_OFFSET       gtLclILoffs;    // instr offset of ref (only for debug info)
2142
2143     GenTreeLclVar(var_types type, unsigned lclNum, IL_OFFSET ilOffs
2144                   DEBUGARG(bool largeNode = false)) : 
2145         GenTreeLclVarCommon(GT_LCL_VAR, type, lclNum
2146                             DEBUGARG(largeNode)),
2147             gtLclILoffs(ilOffs)
2148             {}
2149     
2150     GenTreeLclVar(genTreeOps oper, var_types type, unsigned lclNum, IL_OFFSET ilOffs
2151               DEBUGARG(bool largeNode = false)) : 
2152         GenTreeLclVarCommon(oper, type, lclNum
2153                             DEBUGARG(largeNode)),
2154             gtLclILoffs(ilOffs)
2155             {
2156                 assert(OperIsLocal(oper) || OperIsLocalAddr(oper));
2157             }
2158     
2159 #if DEBUGGABLE_GENTREE
2160     GenTreeLclVar() : GenTreeLclVarCommon() {}
2161 #endif
2162 };
2163
2164 // gtLclFld -- load/store/addr of local variable field 
2165
2166 struct GenTreeLclFld: public GenTreeLclVarCommon
2167 {
2168     unsigned        gtLclOffs;      // offset into the variable to access
2169
2170     FieldSeqNode*   gtFieldSeq;     // This LclFld node represents some sequences of accesses.
2171
2172     // old/FE style constructor where load/store/addr share same opcode
2173     GenTreeLclFld(var_types type, unsigned lclNum, unsigned lclOffs) : 
2174         GenTreeLclVarCommon(GT_LCL_FLD, type, lclNum),
2175         gtLclOffs(lclOffs), gtFieldSeq(NULL)
2176         {
2177             assert(sizeof(*this) <= s_gtNodeSizes[GT_LCL_FLD]);
2178         }
2179
2180
2181     GenTreeLclFld(genTreeOps oper, var_types type, unsigned lclNum, unsigned lclOffs) : 
2182         GenTreeLclVarCommon(oper, type, lclNum),
2183         gtLclOffs(lclOffs), gtFieldSeq(NULL)
2184         {
2185             assert(sizeof(*this) <= s_gtNodeSizes[GT_LCL_FLD]);
2186         }
2187 #if DEBUGGABLE_GENTREE
2188     GenTreeLclFld() : GenTreeLclVarCommon() {}
2189 #endif
2190 };
2191
2192 struct GenTreeRegVar: public GenTreeLclVarCommon
2193 {
2194     // TODO-Cleanup: Note that the base class GenTree already has a gtRegNum field.
2195     // It's not clear exactly why a GT_REG_VAR has a separate field. When
2196     // GT_REG_VAR is created, the two are identical. It appears that they may
2197     // or may not remain so. In particular, there is a comment in stackfp.cpp
2198     // that states:
2199     //
2200     //      There used to be an assertion: assert(src->gtRegNum == src->gtRegVar.gtRegNum, ...)
2201     //      here, but there's actually no reason to assume that.  AFAICT, for FP vars under stack FP,
2202     //      src->gtRegVar.gtRegNum is the allocated stack pseudo-register, but src->gtRegNum is the
2203     //      FP stack position into which that is loaded to represent a particular use of the variable.
2204     //
2205     // It might be the case that only for stackfp do they ever differ.
2206     //
2207     // The following might be possible: the GT_REG_VAR node has a last use prior to a complex
2208     // subtree being evaluated. It could then be spilled from the register. Later,
2209     // it could be unspilled into a different register, which would be recorded at
2210     // the unspill time in the GenTree::gtRegNum, whereas GenTreeRegVar::gtRegNum
2211     // is left alone. It's not clear why that is useful.
2212     //
2213     // Assuming there is a particular use, like stack fp, that requires it, maybe we
2214     // can get rid of GT_REG_VAR and just leave it as GT_LCL_VAR, using the base class gtRegNum field.
2215     // If we need it for stackfp, we could add a GenTreeStackFPRegVar type, which carries both the
2216     // pieces of information, in a clearer and more specific way (in particular, with
2217     // a different member name).
2218     //
2219
2220 private:
2221
2222     regNumberSmall  _gtRegNum;
2223
2224 public:
2225
2226     GenTreeRegVar(var_types type, unsigned lclNum, regNumber regNum) : 
2227         GenTreeLclVarCommon(GT_REG_VAR, type, lclNum
2228                             )
2229         {
2230             gtRegNum = regNum;
2231         }
2232
2233     // The register number is stored in a small format (8 bits), but the getters return and the setters take
2234     // a full-size (unsigned) format, to localize the casts here.
2235
2236     __declspec(property(get=GetRegNum,put=SetRegNum))
2237     regNumber           gtRegNum;
2238
2239     regNumber GetRegNum() const
2240     {
2241         return (regNumber) _gtRegNum;
2242     }
2243
2244     void SetRegNum(regNumber reg)
2245     {
2246         _gtRegNum = (regNumberSmall) reg;
2247         assert(_gtRegNum == reg);
2248     }
2249
2250 #if DEBUGGABLE_GENTREE
2251     GenTreeRegVar() : GenTreeLclVarCommon() {}
2252 #endif
2253 };
2254                               
2255 /* gtCast -- conversion to a different type  (GT_CAST) */
2256
2257 struct GenTreeCast: public GenTreeOp
2258 {
2259     GenTreePtr&     CastOp() { return gtOp1; }
2260     var_types       gtCastType;
2261
2262     GenTreeCast(var_types type, GenTreePtr op, var_types castType 
2263                 DEBUGARG(bool largeNode = false)) : 
2264         GenTreeOp(GT_CAST, type, op, nullptr
2265                     DEBUGARG(largeNode)), 
2266         gtCastType(castType) 
2267         {}
2268 #if DEBUGGABLE_GENTREE
2269     GenTreeCast() : GenTreeOp() {}
2270 #endif
2271 };
2272
2273
2274 // GT_BOX nodes are place markers for boxed values.  The "real" tree
2275 // for most purposes is in gtBoxOp.
2276 struct GenTreeBox: public GenTreeUnOp
2277 {
2278     // An expanded helper call to implement the "box" if we don't get
2279     // rid of it any other way.  Must be in same position as op1.
2280
2281     GenTreePtr&      BoxOp() { return gtOp1; }
2282     // This is the statement that contains the assignment tree when the node is an inlined GT_BOX on a value
2283     // type            
2284     GenTreePtr       gtAsgStmtWhenInlinedBoxValue;
2285
2286     GenTreeBox(var_types type, GenTreePtr boxOp, GenTreePtr asgStmtWhenInlinedBoxValue) : 
2287         GenTreeUnOp(GT_BOX, type, boxOp),
2288         gtAsgStmtWhenInlinedBoxValue(asgStmtWhenInlinedBoxValue)
2289         {}
2290 #if DEBUGGABLE_GENTREE
2291     GenTreeBox() : GenTreeUnOp() {}
2292 #endif
2293 };
2294
2295
2296
2297 /* gtField  -- data member ref  (GT_FIELD) */
2298
2299 struct GenTreeField: public GenTree
2300 {
2301     GenTreePtr      gtFldObj;
2302     CORINFO_FIELD_HANDLE    gtFldHnd;
2303     DWORD           gtFldOffset;
2304     bool            gtFldMayOverlap;
2305 #ifdef FEATURE_READYTORUN_COMPILER
2306     CORINFO_CONST_LOOKUP gtFieldLookup;
2307 #endif
2308
2309     GenTreeField(var_types type) : 
2310         GenTree(GT_FIELD, type 
2311                 ) 
2312     {
2313         gtFldMayOverlap = false;
2314     }
2315 #if DEBUGGABLE_GENTREE
2316     GenTreeField() : GenTree() {}
2317 #endif
2318 };
2319
2320 // Represents the Argument list of a call node, as a Lisp-style linked list.
2321 // (Originally I had hoped that this could have *only* the m_arg/m_rest fields, but it turns out
2322 // that enough of the GenTree mechanism is used that it makes sense just to make it a subtype.  But
2323 // note that in many ways, this is *not* a "real" node of the tree, but rather a mechanism for
2324 // giving call nodes a flexible number of children.  GenTreeArgListNodes never evaluate to registers,
2325 // for example.)
2326
2327 // Note that while this extends GenTreeOp, it is *not* an EXOP.  We don't add any new fields, and one
2328 // is free to allocate a GenTreeOp of type GT_LIST.  If you use this type, you get the convenient Current/Rest
2329 // method names for the arguments.
2330 struct GenTreeArgList: public GenTreeOp  
2331 {
2332     GenTreePtr&      Current() { return gtOp1; }
2333     GenTreeArgList*& Rest()    { assert(gtOp2 == NULL || gtOp2->OperGet() == GT_LIST); return *reinterpret_cast<GenTreeArgList**>(&gtOp2); }
2334
2335 #if DEBUGGABLE_GENTREE
2336     GenTreeArgList() : GenTreeOp() {}
2337 #endif
2338
2339     GenTreeArgList(GenTreePtr arg) :
2340         GenTreeArgList(arg, nullptr) {}
2341       
2342     GenTreeArgList(GenTreePtr arg, GenTreeArgList* rest) : 
2343         GenTreeOp(GT_LIST, TYP_VOID, arg, rest) 
2344     {
2345         // With structs passed in multiple args we could have an arg
2346         // GT_LIST containing a list of LCL_FLDs, see IsListForMultiRegArg()
2347         //
2348         assert((arg != nullptr) && ((!arg->IsList()) || (arg->IsListForMultiRegArg())));
2349         gtFlags |=  arg->gtFlags & GTF_ALL_EFFECT;
2350         if (rest != NULL)
2351         {
2352             gtFlags |= rest->gtFlags & GTF_ALL_EFFECT;
2353         }
2354     }
2355 };
2356
2357 // There was quite a bit of confusion in the code base about which of gtOp1 and gtOp2 was the
2358 // 'then' and 'else' clause of a colon node.  Adding these accessors, while not enforcing anything,
2359 // at least *allows* the programmer to be obviously correct.
2360 // However, these conventions seem backward.
2361 // TODO-Cleanup: If we could get these accessors used everywhere, then we could switch them.
2362 struct GenTreeColon: public GenTreeOp
2363 {
2364     GenTreePtr&      ThenNode() { return gtOp2; }
2365     GenTreePtr&      ElseNode() { return gtOp1; }
2366
2367 #if DEBUGGABLE_GENTREE
2368     GenTreeColon() : GenTreeOp() {}
2369 #endif
2370
2371     GenTreeColon(var_types typ, GenTreePtr thenNode, GenTreePtr elseNode) : 
2372         GenTreeOp(GT_COLON, typ, elseNode, thenNode)
2373         {}
2374 };
2375
2376 // gtCall   -- method call      (GT_CALL)
2377 typedef class fgArgInfo *  fgArgInfoPtr;
2378 enum class InlineObservation;
2379
2380 // Return type descriptor of a GT_CALL node.
2381 // x64 Unix, Arm64, Arm32 and x86 allow a value to be returned in multiple
2382 // registers. For such calls this struct provides the following info 
2383 // on their return type
2384 //    - type of value returned in each return register
2385 //    - ABI return register numbers in which the value is returned
2386 //    - count of return registers in which the value is returned
2387 //
2388 // TODO-ARM: Update this to meet the needs of Arm64 and Arm32
2389 //
2390 // TODO-AllArch: Right now it is used for describing multi-reg returned types.
2391 // Eventually we would want to use it for describing even single-reg
2392 // returned types (e.g. structs returned in single register x64/arm).
2393 // This would allow us not to lie or normalize single struct return
2394 // values in importer/morph.
2395 struct ReturnTypeDesc
2396 {
2397 private:
2398     var_types m_regType[MAX_RET_REG_COUNT];
2399
2400 #ifdef DEBUG
2401     bool m_inited;
2402 #endif
2403
2404 public:
2405     ReturnTypeDesc()
2406     {
2407         Reset();
2408     }
2409
2410     // Initialize the return type descriptor given its type handle
2411     void InitializeReturnType(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd);
2412
2413     // Reset type descriptor to defaults
2414     void Reset()
2415     {
2416         for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
2417         {
2418             m_regType[i] = TYP_UNKNOWN;
2419         }
2420 #ifdef DEBUG
2421         m_inited = false;
2422 #endif
2423     }
2424
2425     //--------------------------------------------------------------------------------------------
2426     // GetReturnRegCount:  Get the count of return registers in which the return value is returned.
2427     //
2428     // Arguments:
2429     //    None
2430     //
2431     // Return Value:
2432     //   Count of return registers.
2433     //   Returns 0 if the return type is not returned in registers.
2434     unsigned GetReturnRegCount() const
2435     {
2436         assert(m_inited);
2437
2438         int regCount = 0;
2439         for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
2440         {
2441             if (m_regType[i] == TYP_UNKNOWN)
2442             {
2443                 break;
2444             }
2445             // otherwise
2446             regCount++;
2447         }
2448
2449 #ifdef DEBUG
2450         // Any remaining elements in m_regTypes[] should also be TYP_UNKNOWN
2451         for (unsigned i = regCount+1; i < MAX_RET_REG_COUNT; ++i)
2452         {
2453             assert(m_regType[i] == TYP_UNKNOWN);
2454         }
2455 #endif        
2456
2457         return regCount;
2458     }
2459
2460     //-----------------------------------------------------------------------
2461     // IsMultiRegRetType: check whether the type is returned in multiple 
2462     // return registers.
2463     //
2464     // Arguments: 
2465     //    None
2466     //
2467     // Return Value:
2468     //    Returns true if the type is returned in multiple return registers.
2469     //    False otherwise.
2470     // Note that we only have to examine the first two values to determine this
2471     //
2472     bool IsMultiRegRetType() const
2473     {
2474         if (MAX_RET_REG_COUNT < 2)
2475         {
2476             return false;
2477         }
2478         else
2479         {
2480             return ((m_regType[0] != TYP_UNKNOWN) &&
2481                     (m_regType[1] != TYP_UNKNOWN));
2482         }
2483     }
2484
2485     //--------------------------------------------------------------------------
2486     // GetReturnRegType:  Get var_type of the return register specified by index.
2487     // 
2488     // Arguments:
2489     //    index - Index of the return register.
2490     //            First return register will have an index 0 and so on.
2491     //
2492     // Return Value:
2493     //    var_type of the return register specified by its index.
2494     //    asserts if the index does not have a valid register return type.
2495     
2496     var_types GetReturnRegType(unsigned index)
2497     {
2498         var_types result = m_regType[index];
2499         assert(result != TYP_UNKNOWN);
2500
2501         return result;
2502     }
2503
2504     // Get ith ABI return register 
2505     regNumber GetABIReturnReg(unsigned idx);
2506
2507     // Get reg mask of ABI return registers 
2508     regMaskTP GetABIReturnRegs();
2509 };
2510
2511 struct GenTreeCall final : public GenTree
2512 {
2513     GenTreePtr        gtCallObjp;             // The instance argument ('this' pointer)
2514     GenTreeArgList*   gtCallArgs;             // The list of arguments in original evaluation order
2515     GenTreeArgList*   gtCallLateArgs;         // On x86:     The register arguments in an optimal order
2516                                               // On ARM/x64: - also includes any outgoing arg space arguments
2517                                               //             - that were evaluated into a temp LclVar
2518     fgArgInfoPtr      fgArgInfo;
2519
2520 #if !FEATURE_FIXED_OUT_ARGS
2521     int               regArgListCount;
2522     regList           regArgList;  
2523 #endif
2524     
2525     // TODO-Throughput: Revisit this (this used to be only defined if
2526     // FEATURE_FIXED_OUT_ARGS was enabled, so this makes GenTreeCall 4 bytes bigger on x86). 
2527     CORINFO_SIG_INFO* callSig;                // Used by tail calls and to register callsites with the EE
2528
2529 #ifdef LEGACY_BACKEND
2530     regMaskTP         gtCallRegUsedMask;      // mask of registers used to pass parameters
2531 #endif // LEGACY_BACKEND
2532
2533     // State required to support multi-reg returning call nodes.
2534     // For now it is enabled only for x64 unix.
2535     //
2536     // TODO-AllArch: enable for all call nodes to unify single-reg and multi-reg returns.
2537 #if FEATURE_MULTIREG_RET
2538     ReturnTypeDesc    gtReturnTypeDesc;
2539
2540     // gtRegNum would always be the first return reg.
2541     // The following array holds the other reg numbers of multi-reg return.
2542     regNumber         gtOtherRegs[MAX_RET_REG_COUNT - 1];
2543
2544     // GTF_SPILL or GTF_SPILLED flag on a multi-reg call node indicates that one or
2545     // more of its result regs are in that state.  The spill flag of each of the
2546     // return register is stored in the below array.
2547     unsigned          gtSpillFlags[MAX_RET_REG_COUNT];
2548 #endif 
2549
2550     //-----------------------------------------------------------------------
2551     // GetReturnTypeDesc: get the type descriptor of return value of the call
2552     //
2553     // Arguments:
2554     //    None
2555     //
2556     // Returns
2557     //    Type descriptor of the value returned by call
2558     //
2559     // Note:
2560     //    Right now implemented only for x64 unix and yet to be 
2561     //    implemented for other multi-reg target arch (Arm64/Arm32/x86).
2562     //
2563     // TODO-AllArch: enable for all call nodes to unify single-reg and multi-reg returns.
2564     ReturnTypeDesc*   GetReturnTypeDesc()
2565     {
2566 #if FEATURE_MULTIREG_RET
2567         return &gtReturnTypeDesc;
2568 #else
2569         return nullptr;
2570 #endif
2571     }
2572
2573     //---------------------------------------------------------------------------
2574     // GetRegNumByIdx: get ith return register allocated to this call node.
2575     //
2576     // Arguments:
2577     //     idx   -   index of the return register
2578     //
2579     // Return Value:
2580     //     Return regNumber of ith return register of call node.
2581     //     Returns REG_NA if there is no valid return register for the given index.
2582     //
2583     regNumber  GetRegNumByIdx(unsigned idx) const
2584     {
2585         assert(idx < MAX_RET_REG_COUNT);
2586
2587         if (idx == 0)
2588         {
2589             return gtRegNum;
2590         }
2591
2592 #if FEATURE_MULTIREG_RET
2593         return gtOtherRegs[idx-1];
2594 #else
2595         return REG_NA;
2596 #endif
2597     }
2598
2599     //----------------------------------------------------------------------
2600     // SetRegNumByIdx: set ith return register of this call node
2601     //
2602     // Arguments:
2603     //    reg    -   reg number
2604     //    idx    -   index of the return register
2605     //
2606     // Return Value:
2607     //    None
2608     //
2609     void  SetRegNumByIdx(regNumber reg, unsigned idx)
2610     {
2611         assert(idx < MAX_RET_REG_COUNT);
2612
2613         if (idx == 0)
2614         {
2615             gtRegNum = reg;
2616         }
2617 #if FEATURE_MULTIREG_RET
2618         else
2619         {
2620             gtOtherRegs[idx - 1] = reg;
2621             assert(gtOtherRegs[idx - 1] == reg);
2622         }
2623 #else
2624         unreached();
2625 #endif
2626     }
2627
2628     //----------------------------------------------------------------------------
2629     // ClearOtherRegs: clear multi-reg state to indicate no regs are allocated
2630     //
2631     // Arguments:
2632     //    None
2633     //
2634     // Return Value:
2635     //    None
2636     //
2637     void  ClearOtherRegs()
2638     {
2639 #if FEATURE_MULTIREG_RET
2640         for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
2641         {
2642             gtOtherRegs[i] = REG_NA;
2643         }
2644 #endif
2645     }
2646
2647     //----------------------------------------------------------------------------
2648     // CopyOtherRegs: copy multi-reg state from the given call node to this node
2649     //
2650     // Arguments:
2651     //    fromCall  -  GenTreeCall node from which to copy multi-reg state
2652     //
2653     // Return Value:
2654     //    None
2655     //
2656     void CopyOtherRegs(GenTreeCall* fromCall)
2657     {
2658 #if FEATURE_MULTIREG_RET
2659         for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
2660         {
2661             this->gtOtherRegs[i] = fromCall->gtOtherRegs[i];
2662         }
2663 #endif
2664     }
2665
2666     // Get reg mask of all the valid registers of gtOtherRegs array
2667     regMaskTP  GetOtherRegMask() const;
2668
2669     //----------------------------------------------------------------------
2670     // GetRegSpillFlagByIdx: get spill flag associated with the return register 
2671     // specified by its index.
2672     //
2673     // Arguments:
2674     //    idx  -  Position or index of the return register
2675     //
2676     // Return Value:
2677     //    Returns GTF_* flags associated with.
2678     unsigned GetRegSpillFlagByIdx(unsigned idx) const
2679     {
2680         assert(idx < MAX_RET_REG_COUNT);
2681
2682 #if FEATURE_MULTIREG_RET
2683         return gtSpillFlags[idx];
2684 #else
2685         assert(!"unreached");
2686         return 0;
2687 #endif
2688     }
2689
2690     //----------------------------------------------------------------------
2691     // SetRegSpillFlagByIdx: set spill flags for the return register 
2692     // specified by its index.
2693     //
2694     // Arguments:
2695     //    flags  -  GTF_* flags
2696     //    idx    -  Position or index of the return register
2697     //
2698     // Return Value:
2699     //    None
2700     void SetRegSpillFlagByIdx(unsigned flags, unsigned idx)
2701     {
2702         assert(idx < MAX_RET_REG_COUNT);
2703
2704 #if FEATURE_MULTIREG_RET
2705         gtSpillFlags[idx] = flags;
2706 #else
2707         unreached();
2708 #endif
2709     }
2710
2711     //-------------------------------------------------------------------
2712     // clearOtherRegFlags: clear GTF_* flags associated with gtOtherRegs
2713     //
2714     // Arguments:
2715     //     None
2716     //
2717     // Return Value:
2718     //     None
2719     void ClearOtherRegFlags()
2720     {
2721 #if FEATURE_MULTIREG_RET
2722         for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
2723         {
2724             gtSpillFlags[i] = 0;
2725         }
2726 #endif
2727     }
2728
2729     //-------------------------------------------------------------------------
2730     // CopyOtherRegFlags: copy GTF_* flags associated with gtOtherRegs from
2731     // the given call node.
2732     //
2733     // Arguments:
2734     //    fromCall  -  GenTreeCall node from which to copy
2735     //
2736     // Return Value:
2737     //    None
2738     //
2739     void CopyOtherRegFlags(GenTreeCall* fromCall)
2740     {
2741 #if FEATURE_MULTIREG_RET
2742         for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
2743         {
2744             this->gtSpillFlags[i] = fromCall->gtSpillFlags[i];
2745         }
2746 #endif
2747     }
2748
2749 #define     GTF_CALL_M_EXPLICIT_TAILCALL       0x0001  // GT_CALL -- the call is "tail" prefixed and importer has performed tail call checks
2750 #define     GTF_CALL_M_TAILCALL                0x0002  // GT_CALL -- the call is a tailcall
2751 #define     GTF_CALL_M_VARARGS                 0x0004  // GT_CALL -- the call uses varargs ABI
2752 #define     GTF_CALL_M_RETBUFFARG              0x0008  // GT_CALL -- first parameter is the return buffer argument
2753 #define     GTF_CALL_M_DELEGATE_INV            0x0010  // GT_CALL -- call to Delegate.Invoke
2754 #define     GTF_CALL_M_NOGCCHECK               0x0020  // GT_CALL -- not a call for computing full interruptability
2755 #define     GTF_CALL_M_SPECIAL_INTRINSIC       0x0040  // GT_CALL -- function that could be optimized as an intrinsic 
2756                                                        // in special cases. Used to optimize fast way out in morphing
2757 #define     GTF_CALL_M_UNMGD_THISCALL          0x0080  // "this" pointer (first argument) should be enregistered (only for GTF_CALL_UNMANAGED)
2758 #define     GTF_CALL_M_VIRTSTUB_REL_INDIRECT   0x0080  // the virtstub is indirected through a relative address (only for GTF_CALL_VIRT_STUB)
2759 #define     GTF_CALL_M_NONVIRT_SAME_THIS       0x0080  // callee "this" pointer is equal to caller this pointer (only for GTF_CALL_NONVIRT)
2760 #define     GTF_CALL_M_FRAME_VAR_DEATH         0x0100  // GT_CALL -- the compLvFrameListRoot variable dies here (last use)
2761
2762 #ifndef LEGACY_BACKEND
2763 #define     GTF_CALL_M_TAILCALL_VIA_HELPER     0x0200  // GT_CALL -- call is a tail call dispatched via tail call JIT helper.
2764 #endif // !LEGACY_BACKEND
2765
2766 #if FEATURE_TAILCALL_OPT
2767 #define     GTF_CALL_M_IMPLICIT_TAILCALL       0x0400  // GT_CALL -- call is an opportunistic tail call and importer has performed tail call checks
2768 #define     GTF_CALL_M_TAILCALL_TO_LOOP        0x0800  // GT_CALL -- call is a fast recursive tail call that can be converted into a loop
2769 #endif
2770
2771 #define     GTF_CALL_M_PINVOKE                 0x1000  // GT_CALL -- call is a pinvoke.  This mirrors VM flag CORINFO_FLG_PINVOKE.
2772                                                        // A call marked as Pinvoke is not necessarily a GT_CALL_UNMANAGED. For e.g.
2773                                                        // an IL Stub dynamically generated for a PInvoke declaration is flagged as
2774                                                        // a Pinvoke but not as an unmanaged call. See impCheckForPInvokeCall() to
2775                                                        // know when these flags are set.
2776
2777 #define     GTF_CALL_M_R2R_REL_INDIRECT        0x2000  // GT_CALL -- ready to run call is indirected through a relative address
2778
2779     bool IsUnmanaged()       { return (gtFlags & GTF_CALL_UNMANAGED) != 0; }
2780     bool NeedsNullCheck()    { return (gtFlags & GTF_CALL_NULLCHECK) != 0; }
2781     bool CallerPop()         { return (gtFlags & GTF_CALL_POP_ARGS) != 0;  }
2782     bool IsVirtual()         { return (gtFlags & GTF_CALL_VIRT_KIND_MASK) != GTF_CALL_NONVIRT; }
2783     bool IsVirtualStub()     { return (gtFlags & GTF_CALL_VIRT_KIND_MASK) == GTF_CALL_VIRT_STUB; }
2784     bool IsVirtualVtable()   { return (gtFlags & GTF_CALL_VIRT_KIND_MASK) == GTF_CALL_VIRT_VTABLE; }
2785     bool IsInlineCandidate() { return (gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0; }
2786
2787 #ifndef LEGACY_BACKEND
2788     // Whether the method has non-standard args (i.e. passed in R10 or R11)
2789     // See fgMorphArgs() to know the call types for which non-standard args are inserted.
2790     bool HasNonStandardArgs()  { return IsUnmanaged() || (gtCallType == CT_INDIRECT && (IsVirtualStub() || gtCallCookie)); }
2791
2792     // Get the count of non-standard arg count 
2793     int  GetNonStandardArgCount() 
2794     {
2795         if (IsUnmanaged())
2796         {
2797             // R11 = PInvoke cookie param
2798             return 1;
2799         }
2800         else if (gtCallType == CT_INDIRECT)
2801         {
2802             if (IsVirtualStub())
2803             {
2804                 // R11 = Virtual stub param
2805                 return 1;
2806             }
2807             else if (gtCallCookie != nullptr)
2808             {
2809                 // R10 = PInvoke target param
2810                 // R11 = PInvoke cookie param
2811                 return 2;
2812             }
2813         }
2814
2815         return 0;
2816     }
2817 #endif // !LEGACY_BACKEND
2818
2819     // Returns true if this call uses a retBuf argument and its calling convention
2820     bool HasRetBufArg() const
2821     {
2822          return (gtCallMoreFlags & GTF_CALL_M_RETBUFFARG) != 0;
2823     }
2824
2825     //-------------------------------------------------------------------------
2826     // TreatAsHasRetBufArg:
2827     //
2828     // Arguments:
2829     //     compiler, the compiler instance so that we can call eeGetHelperNum
2830     //
2831     // Return Value:
2832     //     Returns true if we treat the call as if it has a retBuf argument
2833     //     This method may actually have a retBuf argument 
2834     //     or it could be a JIT helper that we are still transforming during 
2835     //     the importer phase.
2836     //
2837     // Notes:
2838     //     On ARM64 marking the method with the GTF_CALL_M_RETBUFFARG flag
2839     //     will make HasRetBufArg() return true, but will also force the 
2840     //     use of register x8 to pass the RetBuf argument.
2841     //
2842     bool TreatAsHasRetBufArg(Compiler* compiler);
2843
2844     //-----------------------------------------------------------------------------------------
2845     // HasMultiRegRetVal: whether the call node returns its value in multiple return registers.
2846     //
2847     // Arguments:
2848     //     None
2849     //
2850     // Return Value:
2851     //     True if the call is returning a multi-reg return value. False otherwise.
2852     //
2853     // Note:
2854     //     This is implemented only for x64 Unix and yet to be implemented for
2855     //     other multi-reg return target arch (arm64/arm32/x86).
2856     //
2857     // TODO-ARM: Implement this routine for Arm64 and Arm32
2858     bool HasMultiRegRetVal() const 
2859     { 
2860 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
2861         return varTypeIsStruct(gtType) && !HasRetBufArg(); 
2862 #elif defined(_TARGET_X86_) && !defined(LEGACY_BACKEND)
2863         // LEGACY_BACKEND does not use multi reg returns for calls with long return types
2864         return varTypeIsLong(gtType);
2865 #else
2866         return false;
2867 #endif
2868     }
2869
2870     // Returns true if VM has flagged this method as CORINFO_FLG_PINVOKE.
2871     bool IsPInvoke()                { return (gtCallMoreFlags & GTF_CALL_M_PINVOKE) != 0; }
2872
2873     // Note that the distinction of whether tail prefixed or an implicit tail call
2874     // is maintained on a call node till fgMorphCall() after which it will be
2875     // either a tail call (i.e. IsTailCall() is true) or a non-tail call.
2876     bool IsTailPrefixedCall()       { return (gtCallMoreFlags & GTF_CALL_M_EXPLICIT_TAILCALL) != 0; }     
2877
2878     // This method returning "true" implies that tail call flowgraph morhphing has 
2879     // performed final checks and committed to making a tail call.
2880     bool IsTailCall()               { return (gtCallMoreFlags & GTF_CALL_M_TAILCALL) != 0; }
2881
2882     // This method returning "true" implies that importer has performed tail call checks
2883     // and providing a hint that this can be converted to a tail call.
2884     bool CanTailCall()              { return IsTailPrefixedCall() || IsImplicitTailCall(); }
2885
2886 #ifndef LEGACY_BACKEND
2887     bool IsTailCallViaHelper()      { return IsTailCall() && (gtCallMoreFlags & GTF_CALL_M_TAILCALL_VIA_HELPER); } 
2888 #else // LEGACY_BACKEND
2889     bool IsTailCallViaHelper()      { return true; }
2890 #endif // LEGACY_BACKEND
2891
2892 #if FEATURE_FASTTAILCALL    
2893     bool IsFastTailCall()           { return IsTailCall() && !(gtCallMoreFlags & GTF_CALL_M_TAILCALL_VIA_HELPER); }
2894 #else // !FEATURE_FASTTAILCALL
2895     bool IsFastTailCall()           { return false; }    
2896 #endif // !FEATURE_FASTTAILCALL
2897
2898 #if FEATURE_TAILCALL_OPT
2899     // Returns true if this is marked for opportunistic tail calling.
2900     // That is, can be tail called though not explicitly prefixed with "tail" prefix.
2901     bool IsImplicitTailCall()       { return (gtCallMoreFlags & GTF_CALL_M_IMPLICIT_TAILCALL) != 0; }
2902     bool IsTailCallConvertibleToLoop() { return (gtCallMoreFlags & GTF_CALL_M_TAILCALL_TO_LOOP) != 0; }
2903 #else // !FEATURE_TAILCALL_OPT
2904     bool IsImplicitTailCall()       { return false; }
2905     bool IsTailCallConvertibleToLoop() { return false; }
2906 #endif // !FEATURE_TAILCALL_OPT
2907
2908     bool IsSameThis()      { return (gtCallMoreFlags & GTF_CALL_M_NONVIRT_SAME_THIS) != 0; } 
2909     bool IsDelegateInvoke(){ return (gtCallMoreFlags & GTF_CALL_M_DELEGATE_INV) != 0; } 
2910     bool IsVirtualStubRelativeIndir() { return (gtCallMoreFlags & GTF_CALL_M_VIRTSTUB_REL_INDIRECT) != 0; } 
2911 #ifdef FEATURE_READYTORUN_COMPILER
2912     bool IsR2RRelativeIndir() { return (gtCallMoreFlags & GTF_CALL_M_R2R_REL_INDIRECT) != 0; }
2913     void setEntryPoint(CORINFO_CONST_LOOKUP entryPoint) {
2914         gtEntryPoint = entryPoint;
2915         if (gtEntryPoint.accessType == IAT_PVALUE)
2916         {
2917             gtCallMoreFlags |= GTF_CALL_M_R2R_REL_INDIRECT;
2918         }
2919     }
2920 #endif // FEATURE_READYTORUN_COMPILER
2921     bool IsVarargs()       { return (gtCallMoreFlags & GTF_CALL_M_VARARGS) != 0; }
2922
2923     unsigned short  gtCallMoreFlags;        // in addition to gtFlags
2924     
2925     unsigned char   gtCallType   :3;        // value from the gtCallTypes enumeration
2926     unsigned char   gtReturnType :5;        // exact return type
2927
2928     CORINFO_CLASS_HANDLE    gtRetClsHnd;    // The return type handle of the call if it is a struct; always available
2929
2930     union
2931     {
2932         // only used for CALLI unmanaged calls (CT_INDIRECT)
2933         GenTreePtr      gtCallCookie;           
2934         // gtInlineCandidateInfo is only used when inlining methods 
2935         InlineCandidateInfo* gtInlineCandidateInfo;
2936         void* gtStubCallStubAddr;             // GTF_CALL_VIRT_STUB - these are never inlined                
2937         CORINFO_GENERIC_HANDLE compileTimeHelperArgumentHandle; // Used to track type handle argument of dynamic helpers
2938         void* gtDirectCallAddress; // Used to pass direct call address between lower and codegen
2939     };
2940
2941     // expression evaluated after args are placed which determines the control target
2942     GenTree * gtControlExpr; 
2943
2944     union
2945     {
2946         CORINFO_METHOD_HANDLE gtCallMethHnd;  // CT_USER_FUNC
2947         GenTreePtr  gtCallAddr;               // CT_INDIRECT
2948     };
2949
2950 #ifdef FEATURE_READYTORUN_COMPILER
2951     // Call target lookup info for method call from a Ready To Run module
2952     CORINFO_CONST_LOOKUP gtEntryPoint;
2953 #endif
2954
2955 #if defined(DEBUG) || defined(INLINE_DATA)
2956     // For non-inline candidates, track the first observation
2957     // that blocks candidacy.
2958     InlineObservation gtInlineObservation;
2959
2960     // IL offset of the call wrt its parent method.
2961     IL_OFFSET gtRawILOffset;
2962 #endif // defined(DEBUG) || defined(INLINE_DATA)
2963
2964     GenTreeCall(var_types type) : 
2965         GenTree(GT_CALL, type) 
2966     {
2967     }
2968 #if DEBUGGABLE_GENTREE
2969     GenTreeCall() : GenTree()
2970     {
2971     }
2972 #endif
2973 };
2974
2975 struct GenTreeCmpXchg: public GenTree
2976 {
2977     GenTreePtr      gtOpLocation;
2978     GenTreePtr      gtOpValue;
2979     GenTreePtr      gtOpComparand;
2980
2981     GenTreeCmpXchg(var_types type, GenTreePtr loc, GenTreePtr val, GenTreePtr comparand) : 
2982         GenTree(GT_CMPXCHG, type), 
2983         gtOpLocation(loc), gtOpValue(val),  gtOpComparand(comparand)
2984         {
2985             // There's no reason to do a compare-exchange on a local location, so we'll assume that all of these
2986             // have global effects.
2987             gtFlags |= GTF_GLOB_EFFECT;
2988         }
2989 #if DEBUGGABLE_GENTREE
2990     GenTreeCmpXchg() : GenTree() {}
2991 #endif
2992 };
2993
2994
2995
2996 struct GenTreeFptrVal: public GenTree
2997 {
2998     CORINFO_METHOD_HANDLE gtFptrMethod;
2999
3000 #ifdef FEATURE_READYTORUN_COMPILER
3001     CORINFO_CONST_LOOKUP gtEntryPoint;
3002     CORINFO_RESOLVED_TOKEN* gtLdftnResolvedToken;
3003 #endif
3004
3005     GenTreeFptrVal(var_types type, CORINFO_METHOD_HANDLE meth) : 
3006         GenTree(GT_FTN_ADDR, type), 
3007         gtFptrMethod(meth) 
3008         {}
3009 #if DEBUGGABLE_GENTREE
3010     GenTreeFptrVal() : GenTree() {}
3011 #endif
3012 };
3013
3014 /* gtQmark */
3015 struct GenTreeQmark : public GenTreeOp
3016 {
3017     // Livesets on entry to then and else subtrees
3018     VARSET_TP       gtThenLiveSet;
3019     VARSET_TP       gtElseLiveSet;
3020     
3021     // The "Compiler*" argument is not a DEBUGARG here because we use it to keep track of the set of
3022     // (possible) QMark nodes.
3023     GenTreeQmark(var_types type, GenTreePtr cond, GenTreePtr colonOp, class Compiler* comp);
3024
3025 #if DEBUGGABLE_GENTREE
3026     GenTreeQmark() : GenTreeOp(GT_QMARK, TYP_INT, NULL, NULL) {}
3027 #endif
3028 };
3029
3030 /* gtIntrinsic   -- intrinsic   (possibly-binary op [NULL op2 is allowed] with an additional field) */
3031
3032 struct GenTreeIntrinsic: public GenTreeOp
3033 {
3034     CorInfoIntrinsics     gtIntrinsicId;
3035     CORINFO_METHOD_HANDLE gtMethodHandle;    // Method handle of the method which is treated as an intrinsic.
3036
3037 #ifdef FEATURE_READYTORUN_COMPILER
3038     // Call target lookup info for method call from a Ready To Run module
3039     CORINFO_CONST_LOOKUP gtEntryPoint;
3040 #endif
3041
3042     GenTreeIntrinsic(var_types type, GenTreePtr op1, CorInfoIntrinsics intrinsicId, CORINFO_METHOD_HANDLE methodHandle) :
3043         GenTreeOp(GT_INTRINSIC, type, op1, NULL),
3044         gtIntrinsicId(intrinsicId),
3045         gtMethodHandle(methodHandle)
3046         {}
3047
3048     GenTreeIntrinsic(var_types type, GenTreePtr op1, GenTreePtr op2, CorInfoIntrinsics intrinsicId, CORINFO_METHOD_HANDLE methodHandle) :
3049         GenTreeOp(GT_INTRINSIC, type, op1, op2),
3050         gtIntrinsicId(intrinsicId),
3051         gtMethodHandle(methodHandle)
3052         {}
3053
3054 #if DEBUGGABLE_GENTREE
3055     GenTreeIntrinsic() : GenTreeOp() {}
3056 #endif
3057 };
3058
3059 #ifdef FEATURE_SIMD
3060
3061 /* gtSIMD   -- SIMD intrinsic   (possibly-binary op [NULL op2 is allowed] with additional fields) */
3062 struct GenTreeSIMD: public GenTreeOp
3063 {
3064     SIMDIntrinsicID         gtSIMDIntrinsicID;  // operation Id
3065     var_types               gtSIMDBaseType;     // SIMD vector base type
3066     unsigned                gtSIMDSize;         // SIMD vector size in bytes
3067
3068     GenTreeSIMD(var_types type, GenTreePtr op1, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size) : 
3069         GenTreeOp(GT_SIMD, type, op1, nullptr),
3070         gtSIMDIntrinsicID(simdIntrinsicID),
3071         gtSIMDBaseType(baseType),
3072         gtSIMDSize(size)
3073         {}
3074
3075     GenTreeSIMD(var_types type, GenTreePtr op1, GenTreePtr op2, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size) : 
3076         GenTreeOp(GT_SIMD, type, op1, op2),
3077         gtSIMDIntrinsicID(simdIntrinsicID),
3078         gtSIMDBaseType(baseType),
3079         gtSIMDSize(size)
3080         {}
3081
3082 #if DEBUGGABLE_GENTREE
3083     GenTreeSIMD() : GenTreeOp() {}
3084 #endif
3085 };
3086 #endif // FEATURE_SIMD
3087
3088 /* gtIndex -- array access */
3089
3090 struct GenTreeIndex: public GenTreeOp
3091 {
3092     GenTreePtr&     Arr()   { return gtOp1; }
3093     GenTreePtr&     Index() { return gtOp2; }
3094
3095     unsigned        gtIndElemSize;  // size of elements in the array
3096     CORINFO_CLASS_HANDLE gtStructElemClass;   // If the element type is a struct, this is the struct type.
3097
3098     GenTreeIndex(var_types type, GenTreePtr arr, GenTreePtr ind, unsigned indElemSize) :
3099         GenTreeOp(GT_INDEX, type, arr, ind),
3100         gtIndElemSize(indElemSize),
3101         gtStructElemClass(nullptr)  // We always initialize this after construction.
3102         {
3103 #ifdef DEBUG
3104             if (JitConfig.JitSkipArrayBoundCheck() == 1)
3105             {
3106                 // Skip bounds check
3107             }
3108             else
3109 #endif
3110             {
3111                 // Do bounds check
3112                 gtFlags |= GTF_INX_RNGCHK;
3113             }
3114
3115             if (type == TYP_REF)
3116             {
3117                 gtFlags |= GTF_INX_REFARR_LAYOUT;
3118             }
3119
3120             gtFlags |= GTF_EXCEPT|GTF_GLOB_REF;
3121         }
3122 #if DEBUGGABLE_GENTREE
3123     GenTreeIndex() : GenTreeOp() {}
3124 #endif
3125 };
3126
3127 /* gtArrLen -- array length (GT_ARR_LENGTH)
3128    GT_ARR_LENGTH is used for "arr.length" */
3129
3130 struct GenTreeArrLen: public GenTreeUnOp
3131 {
3132     GenTreePtr&     ArrRef() { return gtOp1; }   // the array address node
3133 private:
3134     int             gtArrLenOffset; // constant to add to "gtArrRef" to get the address of the array length.
3135
3136 public:
3137     inline int      ArrLenOffset() {
3138         return gtArrLenOffset;
3139     }
3140
3141     GenTreeArrLen(var_types type, GenTreePtr arrRef, int lenOffset) : 
3142         GenTreeUnOp(GT_ARR_LENGTH, type, arrRef), 
3143         gtArrLenOffset(lenOffset)
3144         {}
3145
3146 #if DEBUGGABLE_GENTREE
3147     GenTreeArrLen() : GenTreeUnOp() {}
3148 #endif
3149 };
3150
3151 // This takes:
3152 // - a comparison value (generally an array length),
3153 // - an index value, and
3154 // - the label to jump to if the index is out of range.
3155 // - the "kind" of the throw block to branch to on failure
3156 // It generates no result.
3157
3158 struct GenTreeBoundsChk: public GenTree
3159 {
3160     GenTreePtr              gtArrLen;       // An expression for the length of the array being indexed.
3161     GenTreePtr              gtIndex;        // The index expression.
3162
3163     GenTreePtr              gtIndRngFailBB; // Label to jump to for array-index-out-of-range
3164     SpecialCodeKind         gtThrowKind;    // Kind of throw block to branch to on failure
3165
3166     /* Only out-of-ranges at same stack depth can jump to the same label (finding return address is easier)
3167        For delayed calling of fgSetRngChkTarget() so that the
3168        optimizer has a chance of eliminating some of the rng checks */
3169     unsigned        gtStkDepth;
3170
3171     GenTreeBoundsChk(genTreeOps oper, var_types type, GenTreePtr arrLen, GenTreePtr index, SpecialCodeKind kind) : 
3172         GenTree(oper, type), 
3173         gtArrLen(arrLen), gtIndex(index), 
3174         gtIndRngFailBB(NULL), 
3175         gtThrowKind(kind),
3176         gtStkDepth(0)
3177         {
3178             // Effects flags propagate upwards.
3179             gtFlags |= (arrLen->gtFlags & GTF_ALL_EFFECT);
3180             gtFlags |= GTF_EXCEPT;
3181         }
3182 #if DEBUGGABLE_GENTREE
3183     GenTreeBoundsChk() : GenTree() {}
3184 #endif
3185
3186     // If the gtArrLen is really an array length, returns array reference, else "NULL".
3187     GenTreePtr GetArray()
3188     {
3189         if (gtArrLen->OperGet() == GT_ARR_LENGTH)
3190         {
3191             return gtArrLen->gtArrLen.ArrRef();
3192         }
3193         else
3194         {
3195             return NULL;
3196         }
3197     }
3198 };
3199
3200 // gtArrElem -- general array element (GT_ARR_ELEM), for non "SZ_ARRAYS"
3201 //              -- multidimensional arrays, or 1-d arrays with non-zero lower bounds.
3202
3203 struct GenTreeArrElem: public GenTree
3204 {
3205     GenTreePtr      gtArrObj;
3206
3207     #define         GT_ARR_MAX_RANK 3
3208     GenTreePtr      gtArrInds[GT_ARR_MAX_RANK]; // Indices
3209     unsigned char   gtArrRank;                  // Rank of the array
3210
3211     unsigned char   gtArrElemSize;              // !!! Caution, this is an "unsigned char", it is used only
3212                                                 // on the optimization path of array intrisics.
3213                                                 // It stores the size of array elements WHEN it can fit
3214                                                 // into an "unsigned char".
3215                                                 // This has caused VSW 571394.
3216     var_types       gtArrElemType;              // The array element type
3217
3218     // Requires that "inds" is a pointer to an array of "rank" GenTreePtrs for the indices.
3219     GenTreeArrElem(var_types type, GenTreePtr arr, unsigned char rank, unsigned char elemSize, var_types elemType, GenTreePtr* inds) : 
3220         GenTree(GT_ARR_ELEM, type), 
3221         gtArrObj(arr), gtArrRank(rank), gtArrElemSize(elemSize), gtArrElemType(elemType)
3222         {
3223             for (unsigned char i = 0; i < rank; i++) gtArrInds[i] = inds[i];
3224             gtFlags |= GTF_EXCEPT;
3225         }
3226 #if DEBUGGABLE_GENTREE
3227     GenTreeArrElem() : GenTree() {}
3228 #endif
3229 };
3230
3231 //--------------------------------------------
3232 // 
3233 // GenTreeArrIndex (gtArrIndex): Expression to bounds-check the index for one dimension of a
3234 //    multi-dimensional or non-zero-based array., and compute the effective index
3235 //    (i.e. subtracting the lower bound).
3236 //
3237 // Notes:
3238 //    This node is similar in some ways to GenTreeBoundsChk, which ONLY performs the check.
3239 //    The reason that this node incorporates the check into the effective index computation is
3240 //    to avoid duplicating the codegen, as the effective index is required to compute the
3241 //    offset anyway.
3242 //    TODO-CQ: Enable optimization of the lower bound and length by replacing this:
3243 //                /--*  <arrObj>
3244 //                +--*  <index0>
3245 //             +--* ArrIndex[i, ]
3246 //    with something like:
3247 //                   /--*  <arrObj>
3248 //                /--*  ArrLowerBound[i, ]
3249 //                |  /--*  <arrObj>
3250 //                +--*  ArrLen[i, ]    (either generalize GT_ARR_LENGTH or add a new node)
3251 //                +--*  <index0>
3252 //             +--* ArrIndex[i, ]
3253 //    Which could, for example, be optimized to the following when known to be within bounds:
3254 //                /--*  TempForLowerBoundDim0
3255 //                +--*  <index0>
3256 //             +--* - (GT_SUB)
3257 //
3258 struct GenTreeArrIndex: public GenTreeOp
3259 {
3260     // The array object - may be any expression producing an Array reference, but is likely to be a lclVar.
3261     GenTreePtr&     ArrObj()    { return gtOp1; }
3262     // The index expression - may be any integral expression.
3263     GenTreePtr&     IndexExpr() { return gtOp2; }
3264     unsigned char   gtCurrDim;      // The current dimension
3265     unsigned char   gtArrRank;      // Rank of the array
3266     var_types       gtArrElemType;  // The array element type
3267
3268     GenTreeArrIndex(var_types type, GenTreePtr arrObj, GenTreePtr indexExpr,
3269                   unsigned char currDim, unsigned char arrRank, var_types elemType) :
3270         GenTreeOp(GT_ARR_INDEX, type, arrObj, indexExpr),
3271                   gtCurrDim(currDim), gtArrRank(arrRank), gtArrElemType(elemType)
3272     {
3273         gtFlags |= GTF_EXCEPT;
3274     }
3275 #if DEBUGGABLE_GENTREE
3276 protected:
3277     friend GenTree;
3278     // Used only for GenTree::GetVtableForOper()
3279     GenTreeArrIndex() : GenTreeOp() {}
3280 #endif
3281 };
3282
3283 // Represents either an InitBlk, InitObj, CpBlk or CpObj 
3284 // MSIL OpCode.
3285 struct GenTreeBlkOp : public GenTreeOp
3286 {
3287 public:
3288     // The destination for the CpBlk/CpObj/InitBlk/InitObj to copy bits to
3289     GenTreePtr Dest()         { 
3290                                 assert(gtOp1->gtOper == GT_LIST);
3291                                 return gtOp1->gtOp.gtOp1;
3292                               }
3293
3294     // True if this BlkOpNode is a volatile memory operation.
3295     bool IsVolatile() const { return (gtFlags & GTF_BLK_VOLATILE) != 0; }
3296
3297     // Instruction selection: during codegen time, what code sequence we will be using
3298     // to encode this operation.
3299     enum
3300     {
3301         BlkOpKindInvalid,
3302         BlkOpKindHelper,
3303         BlkOpKindRepInstr,
3304         BlkOpKindUnroll,
3305     } gtBlkOpKind;
3306
3307     bool gtBlkOpGcUnsafe; 
3308
3309     GenTreeBlkOp(genTreeOps oper) :
3310         GenTreeOp(oper, TYP_VOID DEBUGARG(true)),
3311             gtBlkOpKind(BlkOpKindInvalid),
3312             gtBlkOpGcUnsafe(false)
3313     {
3314         assert(OperIsBlkOp(oper));
3315     }
3316
3317 #if DEBUGGABLE_GENTREE
3318 protected:
3319     friend GenTree;
3320     GenTreeBlkOp() : GenTreeOp(){}
3321 #endif // DEBUGGABLE_GENTREE
3322 };
3323
3324 // gtObj  -- 'object' (GT_OBJ). */
3325
3326 struct GenTreeObj: public GenTreeUnOp
3327 {
3328     // The address of the block.
3329     GenTreePtr&     Addr()          { return gtOp1; }
3330
3331     CORINFO_CLASS_HANDLE gtClass;   // the class of the object
3332
3333     GenTreeObj(var_types type, GenTreePtr addr, CORINFO_CLASS_HANDLE cls) : 
3334         GenTreeUnOp(GT_OBJ, type, addr),
3335         gtClass(cls)
3336         {
3337             gtFlags |= GTF_GLOB_REF; // An Obj is always a global reference.
3338         }
3339
3340 #if DEBUGGABLE_GENTREE
3341     GenTreeObj() : GenTreeUnOp() {}
3342 #endif
3343 };
3344
3345 // Represents a CpObj MSIL Node.
3346 struct GenTreeCpObj : public GenTreeBlkOp
3347 {
3348 public:
3349     // The source for the CpBlk/CpObj to copy bits from
3350     GenTreePtr Source()       {
3351         assert(gtOper == GT_COPYOBJ && gtOp1->gtOper == GT_LIST);
3352         return gtOp1->gtOp.gtOp2;
3353     }
3354
3355     // In the case of CopyObj, this is the class token that represents the type that is being copied.
3356     GenTreePtr ClsTok() { return gtOp2; }
3357
3358     // If non-null, this array represents the gc-layout of the class that is being copied
3359     // with CpObj.
3360     BYTE*       gtGcPtrs;
3361
3362     // If non-zero, this is the number of slots in the class layout that 
3363     // contain gc-pointers.
3364     unsigned    gtGcPtrCount;
3365
3366     // If non-zero, the number of pointer-sized slots that constitutes the class token in CpObj.
3367     unsigned    gtSlots;
3368
3369     GenTreeCpObj(unsigned gcPtrCount, unsigned gtSlots, BYTE* gtGcPtrs) :
3370         GenTreeBlkOp(GT_COPYOBJ),
3371         gtGcPtrs(gtGcPtrs),
3372         gtGcPtrCount(gcPtrCount),
3373         gtSlots(gtSlots){ }
3374
3375 #if DEBUGGABLE_GENTREE
3376 protected:
3377     friend GenTree;
3378     GenTreeCpObj() : GenTreeBlkOp(),
3379         gtGcPtrs(nullptr),
3380         gtGcPtrCount(0),
3381         gtSlots(0) {}
3382 #endif // DEBUGGABLE_GENTREE
3383 };
3384
3385 // Represents either an InitBlk or InitObj MSIL OpCode.
3386 struct GenTreeInitBlk : public GenTreeBlkOp
3387 {
3388 public:
3389
3390     // The value used to fill the destination buffer.
3391     GenTreePtr InitVal() { assert(gtOp1->gtOper == GT_LIST);
3392                            return gtOp1->gtOp.gtOp2; }
3393
3394     // The size of the buffer to be copied.
3395     GenTreePtr Size()    { return gtOp2; }
3396
3397     GenTreeInitBlk() : GenTreeBlkOp(GT_INITBLK){}
3398
3399 #if DEBUGGABLE_GENTREE
3400 protected:
3401     friend GenTree;
3402 #endif // DEBUGGABLE_GENTREE
3403 };
3404
3405 // Represents a CpBlk or CpObj with no GC-pointers MSIL OpCode.
3406 struct GenTreeCpBlk : public GenTreeBlkOp
3407 {
3408 public:
3409
3410     // The value used to fill the destination buffer.
3411     // The source for the CpBlk/CpObj to copy bits from
3412     GenTreePtr Source() { assert(gtOp1->gtOper == GT_LIST);
3413                           return gtOp1->gtOp.gtOp2; }
3414
3415     // The size of the buffer to be copied.
3416     GenTreePtr Size()   { return gtOp2; }
3417
3418     GenTreeCpBlk() : GenTreeBlkOp(GT_COPYBLK){}
3419
3420 #if DEBUGGABLE_GENTREE
3421 protected:
3422     friend GenTree;
3423 #endif // DEBUGGABLE_GENTREE
3424 };
3425
3426 //--------------------------------------------
3427 // 
3428 // GenTreeArrOffset (gtArrOffset): Expression to compute the accumulated offset for the address
3429 //    of an element of a multi-dimensional or non-zero-based array.
3430 //
3431 // Notes:
3432 //    The result of this expression is (gtOffset * dimSize) + gtIndex
3433 //    where dimSize is the length/stride/size of the dimension, and is obtained from gtArrObj.
3434 //    This node is generated in conjunction with the GenTreeArrIndex node, which computes the
3435 //    effective index for a single dimension.  The sub-trees can be separately optimized, e.g.
3436 //    within a loop body where the expression for the 0th dimension may be invariant.
3437 //
3438 //    Here is an example of how the tree might look for a two-dimension array reference:
3439 //                /--*  const 0
3440 //                |  /--* <arrObj>
3441 //                |  +--* <index0>
3442 //                +--* ArrIndex[i, ]
3443 //                +--*  <arrObj>
3444 //             /--| arrOffs[i, ]
3445 //             |  +--*  <arrObj>
3446 //             |  +--*  <index1>
3447 //             +--* ArrIndex[*,j]
3448 //             +--*  <arrObj>
3449 //          /--| arrOffs[*,j]
3450 //    TODO-CQ: see comment on GenTreeArrIndex for how its representation may change.  When that
3451 //    is done, we will also want to replace the <arrObj> argument to arrOffs with the
3452 //    ArrLen as for GenTreeArrIndex.
3453 //
3454 struct GenTreeArrOffs: public GenTree
3455 {
3456     GenTreePtr      gtOffset;       // The accumulated offset for lower dimensions - must be TYP_I_IMPL, and
3457                                     // will either be a CSE temp, the constant 0, or another GenTreeArrOffs node.
3458     GenTreePtr      gtIndex;        // The effective index for the current dimension - must be non-negative
3459                                     // and can be any expression (though it is likely to be either a GenTreeArrIndex,
3460                                     // node, a lclVar, or a constant).
3461     GenTreePtr      gtArrObj;       // The array object - may be any expression producing an Array reference,
3462                                     // but is likely to be a lclVar.
3463     unsigned char   gtCurrDim;      // The current dimension
3464     unsigned char   gtArrRank;      // Rank of the array
3465     var_types       gtArrElemType;  // The array element type
3466
3467     GenTreeArrOffs(var_types type, GenTreePtr offset, GenTreePtr index, GenTreePtr arrObj,
3468                    unsigned char currDim, unsigned char rank, var_types elemType) : 
3469         GenTree(GT_ARR_OFFSET, type), gtOffset(offset), gtIndex(index), gtArrObj(arrObj),
3470                 gtCurrDim(currDim), gtArrRank(rank), gtArrElemType(elemType)
3471     {
3472         assert(index->gtFlags & GTF_EXCEPT);
3473         gtFlags |= GTF_EXCEPT;
3474     }
3475 #if DEBUGGABLE_GENTREE
3476     GenTreeArrOffs() : GenTree() {}
3477 #endif
3478 };
3479
3480 /* gtAddrMode -- Target-specific canonicalized addressing expression (GT_LEA) */
3481
3482 struct GenTreeAddrMode: public GenTreeOp
3483 {
3484     // Address is Base + Index*Scale + Offset.
3485     // These are the legal patterns:
3486     //
3487     //      Base                                // Base != nullptr && Index == nullptr && Scale == 0 && Offset == 0
3488     //      Base + Index*Scale                  // Base != nullptr && Index != nullptr && Scale != 0 && Offset == 0
3489     //      Base + Offset                       // Base != nullptr && Index == nullptr && Scale == 0 && Offset != 0
3490     //      Base + Index*Scale + Offset         // Base != nullptr && Index != nullptr && Scale != 0 && Offset != 0
3491     //             Index*Scale                  // Base == nullptr && Index != nullptr && Scale >  1 && Offset == 0
3492     //             Index*Scale + Offset         // Base == nullptr && Index != nullptr && Scale >  1 && Offset != 0
3493     //                           Offset         // Base == nullptr && Index == nullptr && Scale == 0 && Offset != 0
3494     //
3495     // So, for example:
3496     //      1. Base + Index is legal with Scale==1
3497     //      2. If Index is null, Scale should be zero (or unintialized / unused)
3498     //      3. If Scale==1, then we should have "Base" instead of "Index*Scale", and "Base + Offset" instead of "Index*Scale + Offset".
3499
3500     // First operand is base address/pointer
3501     bool            HasBase() const     { return gtOp1 != nullptr; }
3502     GenTreePtr&     Base()              { return gtOp1; }
3503
3504     // Second operand is scaled index value
3505     bool            HasIndex() const    { return gtOp2 != nullptr; }
3506     GenTreePtr&     Index()             { return gtOp2; }
3507
3508     unsigned        gtScale;        // The scale factor
3509     unsigned        gtOffset;       // The offset to add
3510
3511     GenTreeAddrMode(var_types type, GenTreePtr base, GenTreePtr index,
3512                     unsigned scale, unsigned offset) : 
3513         GenTreeOp(GT_LEA, type, base, index )
3514     {
3515         gtScale = scale;
3516         gtOffset = offset;
3517     }
3518 #if DEBUGGABLE_GENTREE
3519 protected:
3520     friend GenTree;
3521     // Used only for GenTree::GetVtableForOper()
3522     GenTreeAddrMode() : GenTreeOp() {}
3523 #endif
3524 };
3525
3526 // Indir is just an op, no additional data, but some additional abstractions
3527 struct GenTreeIndir: public GenTreeOp
3528 {
3529     // like an assign, op1 is the destination
3530     GenTreePtr&     Addr()      { return gtOp1; }
3531
3532     // these methods provide an interface to the indirection node which 
3533     bool            HasBase();
3534     bool            HasIndex();
3535     GenTree*        Base(); 
3536     GenTree*        Index(); 
3537     unsigned        Scale();
3538     size_t          Offset();
3539
3540     GenTreeIndir(genTreeOps oper, var_types type, GenTree *addr, GenTree *data) : 
3541     GenTreeOp(oper, type, addr, data)
3542     {
3543     }
3544
3545 #if DEBUGGABLE_GENTREE
3546 protected:
3547     friend GenTree;
3548     // Used only for GenTree::GetVtableForOper()
3549     GenTreeIndir() : GenTreeOp() {}
3550 #endif
3551 };
3552
3553 // Read-modify-write status of a RMW memory op rooted at a storeInd 
3554 enum  RMWStatus {    
3555     STOREIND_RMW_STATUS_UNKNOWN,  // RMW status of storeInd unknown
3556                                   // Default status unless modified by IsRMWMemOpRootedAtStoreInd()
3557
3558     // One of these denote storeind is a RMW memory operation.
3559     STOREIND_RMW_DST_IS_OP1,       // StoreInd is known to be a RMW memory op and dst candidate is op1
3560     STOREIND_RMW_DST_IS_OP2,       // StoreInd is known to be a RMW memory op and dst candidate is op2
3561
3562     // One of these denote the reason for storeind is marked as non-RMW operation
3563     STOREIND_RMW_UNSUPPORTED_ADDR, // Addr mode is not yet supported for RMW memory
3564     STOREIND_RMW_UNSUPPORTED_OPER, // Operation is not supported for RMW memory
3565     STOREIND_RMW_UNSUPPORTED_TYPE, // Type is not supported for RMW memory
3566     STOREIND_RMW_INDIR_UNEQUAL     // Indir to read value is not equivalent to indir that writes the value
3567 };
3568
3569 // StoreInd is just a BinOp, with additional RMW status
3570 struct GenTreeStoreInd: public GenTreeIndir
3571 {
3572 #if !CPU_LOAD_STORE_ARCH
3573     // The below flag is set and used during lowering
3574     RMWStatus  gtRMWStatus;
3575
3576     bool  IsRMWStatusUnknown() { return gtRMWStatus == STOREIND_RMW_STATUS_UNKNOWN; }
3577     bool  IsNonRMWMemoryOp() {
3578         return gtRMWStatus == STOREIND_RMW_UNSUPPORTED_ADDR ||
3579                gtRMWStatus == STOREIND_RMW_UNSUPPORTED_OPER ||
3580                gtRMWStatus == STOREIND_RMW_UNSUPPORTED_TYPE ||
3581                gtRMWStatus == STOREIND_RMW_INDIR_UNEQUAL;
3582     }
3583     bool  IsRMWMemoryOp() { return gtRMWStatus == STOREIND_RMW_DST_IS_OP1 || gtRMWStatus == STOREIND_RMW_DST_IS_OP2; }
3584     bool  IsRMWDstOp1() { return gtRMWStatus == STOREIND_RMW_DST_IS_OP1; }
3585     bool  IsRMWDstOp2() { return gtRMWStatus == STOREIND_RMW_DST_IS_OP2; }
3586 #endif //!CPU_LOAD_STORE_ARCH
3587
3588     RMWStatus GetRMWStatus() { 
3589 #if !CPU_LOAD_STORE_ARCH
3590         return gtRMWStatus; 
3591 #else
3592         return STOREIND_RMW_STATUS_UNKNOWN;
3593 #endif
3594     }
3595
3596     void SetRMWStatusDefault() 
3597     {
3598 #if !CPU_LOAD_STORE_ARCH
3599         gtRMWStatus = STOREIND_RMW_STATUS_UNKNOWN;
3600 #endif
3601     }
3602
3603     void SetRMWStatus(RMWStatus status)
3604     {
3605 #if !CPU_LOAD_STORE_ARCH
3606         gtRMWStatus = status;
3607 #endif
3608     }
3609
3610     GenTreePtr&     Data()      { return gtOp2; }
3611
3612     GenTreeStoreInd(var_types type, GenTree *destPtr, GenTree *data) : 
3613     GenTreeIndir(GT_STOREIND, type, destPtr, data)
3614     {
3615         SetRMWStatusDefault();
3616     }
3617
3618 #if DEBUGGABLE_GENTREE
3619 protected:
3620     friend GenTree;
3621     // Used only for GenTree::GetVtableForOper()
3622     GenTreeStoreInd() : GenTreeIndir() { SetRMWStatusDefault(); }
3623 #endif
3624 };
3625
3626
3627 /* gtRetExp -- Place holder for the return expression from an inline candidate (GT_RET_EXPR) */
3628
3629 struct GenTreeRetExpr: public GenTree
3630 {
3631     GenTreePtr      gtInlineCandidate;
3632
3633     CORINFO_CLASS_HANDLE gtRetClsHnd;
3634
3635     GenTreeRetExpr(var_types type) : 
3636         GenTree(GT_RET_EXPR, type) 
3637         {}
3638 #if DEBUGGABLE_GENTREE
3639     GenTreeRetExpr() : GenTree() {}
3640 #endif
3641 };
3642
3643
3644 /* gtStmt   -- 'statement expr' (GT_STMT) */
3645
3646 class InlineContext;
3647
3648 struct GenTreeStmt: public GenTree
3649 {
3650     GenTreePtr      gtStmtExpr;      // root of the expression tree
3651     GenTreePtr      gtStmtList;      // first node (for forward walks)
3652     InlineContext*  gtInlineContext; // The inline context for this statement.
3653   
3654 #if defined(DEBUGGING_SUPPORT) || defined(DEBUG)
3655     IL_OFFSETX      gtStmtILoffsx;   // instr offset (if available)
3656 #endif
3657
3658 #ifdef DEBUG
3659     IL_OFFSET       gtStmtLastILoffs;// instr offset at end of stmt
3660 #endif
3661
3662     bool            gtStmtIsTopLevel()
3663     {
3664         return (gtFlags & GTF_STMT_TOP_LEVEL) != 0;
3665     }
3666
3667     bool            gtStmtIsEmbedded()
3668     {
3669         return !gtStmtIsTopLevel();
3670     }
3671
3672     // Return the next statement, if it is embedded, otherwise nullptr
3673     GenTreeStmt*    gtStmtNextIfEmbedded()
3674     {
3675         GenTree* nextStmt = gtNext;
3676         if (nextStmt != nullptr && nextStmt->gtStmt.gtStmtIsEmbedded())
3677         {
3678             return nextStmt->AsStmt();
3679         }
3680         else
3681         {
3682             return nullptr;
3683         }
3684     }
3685
3686     GenTree*    gtStmtNextTopLevelStmt()
3687     {
3688         GenTree* nextStmt = gtNext;
3689         while (nextStmt != nullptr && nextStmt->gtStmt.gtStmtIsEmbedded())
3690         {
3691             nextStmt = nextStmt->gtNext;
3692         }
3693         return nextStmt;
3694     }
3695
3696     __declspec(property(get=getNextStmt))
3697     GenTreeStmt* gtNextStmt;
3698
3699     __declspec(property(get=getPrevStmt))
3700     GenTreeStmt* gtPrevStmt;
3701
3702     GenTreeStmt* getNextStmt() 
3703     {
3704         if (gtNext == nullptr)
3705             return nullptr;
3706         else
3707             return gtNext->AsStmt();
3708     }
3709
3710     GenTreeStmt* getPrevStmt() 
3711     {
3712         if (gtPrev == nullptr)
3713             return nullptr;
3714         else
3715             return gtPrev->AsStmt();
3716     }
3717
3718     GenTreeStmt(GenTreePtr expr, IL_OFFSETX offset)
3719         : GenTree(GT_STMT, TYP_VOID)
3720         , gtStmtExpr(expr)
3721         , gtStmtList(nullptr)
3722         , gtInlineContext(nullptr)
3723 #if defined(DEBUGGING_SUPPORT) || defined(DEBUG)
3724         , gtStmtILoffsx(offset)
3725 #endif
3726 #ifdef DEBUG
3727         , gtStmtLastILoffs(BAD_IL_OFFSET)
3728 #endif
3729     {
3730         // Statements can't have statements as part of their expression tree.
3731         assert(expr->gtOper != GT_STMT);
3732
3733         gtFlags |= GTF_STMT_TOP_LEVEL;
3734
3735         // Set the statement to have the same costs as the top node of the tree.
3736         // This is used long before costs have been assigned, so we need to copy
3737         // the raw costs.
3738         CopyRawCosts(expr);
3739     }
3740
3741 #if DEBUGGABLE_GENTREE
3742     GenTreeStmt() : GenTree(GT_STMT, TYP_VOID) {}
3743 #endif
3744 };
3745
3746
3747
3748
3749 /*  NOTE: Any tree nodes that are larger than 8 bytes (two ints or
3750     pointers) must be flagged as 'large' in GenTree::InitNodeSize().
3751  */
3752
3753                 
3754 /* gtClsVar -- 'static data member' (GT_CLS_VAR) */
3755
3756 struct GenTreeClsVar: public GenTree
3757 {
3758     CORINFO_FIELD_HANDLE    gtClsVarHnd;
3759     FieldSeqNode*           gtFieldSeq;
3760
3761     GenTreeClsVar(var_types type, CORINFO_FIELD_HANDLE clsVarHnd, FieldSeqNode* fldSeq) : 
3762         GenTree(GT_CLS_VAR, type), 
3763         gtClsVarHnd(clsVarHnd),
3764         gtFieldSeq(fldSeq)
3765         {
3766             gtFlags |= GTF_GLOB_REF;
3767         }
3768 #if DEBUGGABLE_GENTREE
3769     GenTreeClsVar() : GenTree() {}
3770 #endif
3771 };
3772
3773 /* gtArgPlace -- 'register argument placeholder' (GT_ARGPLACE) */
3774
3775 struct GenTreeArgPlace: public GenTree
3776 {
3777     CORINFO_CLASS_HANDLE    gtArgPlaceClsHnd;    // Needed when we have a TYP_STRUCT argument
3778
3779     GenTreeArgPlace(var_types type, CORINFO_CLASS_HANDLE clsHnd) : 
3780         GenTree(GT_ARGPLACE, type), 
3781         gtArgPlaceClsHnd(clsHnd) 
3782         {}
3783 #if DEBUGGABLE_GENTREE
3784     GenTreeArgPlace() : GenTree() {}
3785 #endif
3786 };
3787
3788 /* gtLabel  -- code label target    (GT_LABEL) */
3789
3790 struct GenTreeLabel: public GenTree
3791 {
3792     BasicBlock* gtLabBB;
3793
3794     GenTreeLabel(BasicBlock* bb) : 
3795         GenTree(GT_LABEL, TYP_VOID), 
3796         gtLabBB(bb) 
3797         {}
3798 #if DEBUGGABLE_GENTREE
3799     GenTreeLabel() : GenTree() {}
3800 #endif
3801 };
3802
3803 /* gtPhiArg -- phi node rhs argument, var = phi(phiarg, phiarg, phiarg...); GT_PHI_ARG */
3804 struct GenTreePhiArg: public GenTreeLclVarCommon
3805 {
3806     BasicBlock  *   gtPredBB;
3807
3808     GenTreePhiArg(var_types type, unsigned lclNum, unsigned snum, BasicBlock* block)
3809         : GenTreeLclVarCommon(GT_PHI_ARG, type, lclNum)
3810         , gtPredBB(block)
3811     { 
3812         SetSsaNum(snum);
3813     }
3814
3815 #if DEBUGGABLE_GENTREE
3816     GenTreePhiArg() : GenTreeLclVarCommon() {}
3817 #endif
3818 };
3819
3820 /* gtPutArgStk -- Argument passed on stack */
3821
3822 struct GenTreePutArgStk: public GenTreeUnOp
3823 {
3824     unsigned gtSlotNum;        // Slot number of the argument to be passed on stack
3825
3826 #if FEATURE_FASTTAILCALL
3827     bool putInIncomingArgArea;    // Whether this arg needs to be placed in incoming arg area.
3828                                   // By default this is false and will be placed in out-going arg area.
3829                                   // Fast tail calls set this to true.
3830                                   // In future if we need to add more such bool fields consider bit fields.
3831
3832     GenTreePutArgStk(
3833             genTreeOps oper,
3834             var_types type,
3835             unsigned slotNum
3836             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots)
3837             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct),
3838             bool _putInIncomingArgArea = false
3839             DEBUGARG(GenTreePtr callNode = NULL)
3840             DEBUGARG(bool largeNode = false))
3841         : 
3842         GenTreeUnOp(oper, type DEBUGARG(largeNode)),
3843         gtSlotNum(slotNum),
3844         putInIncomingArgArea(_putInIncomingArgArea)
3845 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3846         , gtPutArgStkKind(PutArgStkKindInvalid),
3847         gtNumSlots(numSlots),
3848         gtIsStruct(isStruct),
3849         gtNumberReferenceSlots(0),
3850         gtGcPtrs(nullptr)
3851 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3852     {
3853 #ifdef DEBUG
3854         gtCall = callNode;
3855 #endif
3856     }
3857
3858
3859     GenTreePutArgStk(
3860             genTreeOps oper,
3861             var_types type,
3862             GenTreePtr op1,
3863             unsigned slotNum
3864             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots)
3865             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct),
3866             bool _putInIncomingArgArea = false
3867             DEBUGARG(GenTreePtr callNode = NULL)
3868             DEBUGARG(bool largeNode = false))
3869         :
3870         GenTreeUnOp(oper, type, op1 DEBUGARG(largeNode)), 
3871         gtSlotNum(slotNum),
3872         putInIncomingArgArea(_putInIncomingArgArea)
3873 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3874         , gtPutArgStkKind(PutArgStkKindInvalid),
3875         gtNumSlots(numSlots),
3876         gtIsStruct(isStruct),
3877         gtNumberReferenceSlots(0),
3878         gtGcPtrs(nullptr)
3879 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3880     {
3881 #ifdef DEBUG
3882         gtCall = callNode;
3883 #endif
3884     }
3885
3886 #else  // !FEATURE_FASTTAILCALL
3887
3888     GenTreePutArgStk(
3889             genTreeOps oper,
3890             var_types type,
3891             unsigned slotNum
3892             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots)
3893             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct)
3894             DEBUGARG(GenTreePtr callNode = NULL)
3895             DEBUGARG(bool largeNode = false))
3896         :
3897         GenTreeUnOp(oper, type DEBUGARG(largeNode)),
3898         gtSlotNum(slotNum)
3899 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3900         , gtPutArgStkKind(PutArgStkKindInvalid),
3901         gtNumSlots(numSlots),
3902         gtIsStruct(isStruct),
3903         gtNumberReferenceSlots(0),
3904         gtGcPtrs(nullptr)
3905 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3906     {
3907 #ifdef DEBUG
3908         gtCall = callNode;
3909 #endif
3910     }
3911
3912
3913     GenTreePutArgStk(
3914             genTreeOps oper,
3915             var_types type,
3916             GenTreePtr op1,
3917             unsigned slotNum
3918             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots)
3919             FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct)
3920             DEBUGARG(GenTreePtr callNode = NULL)
3921             DEBUGARG(bool largeNode = false))
3922         :
3923         GenTreeUnOp(oper, type, op1 DEBUGARG(largeNode)), 
3924         gtSlotNum(slotNum)
3925 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3926         , gtPutArgStkKind(PutArgStkKindInvalid),
3927         gtNumSlots(numSlots),
3928         gtIsStruct(isStruct),
3929         gtNumberReferenceSlots(0),
3930         gtGcPtrs(nullptr)
3931 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3932     {
3933 #ifdef DEBUG
3934         gtCall = callNode;
3935 #endif
3936     }
3937 #endif // FEATURE_FASTTAILCALL
3938
3939     unsigned getArgOffset() { return gtSlotNum * TARGET_POINTER_SIZE; }
3940
3941 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3942     unsigned getArgSize() { return gtNumSlots * TARGET_POINTER_SIZE; }
3943 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3944
3945 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3946     //------------------------------------------------------------------------
3947     // setGcPointers: Sets the number of references and the layout of the struct object returned by the VM.
3948     //
3949     // Arguments:
3950     //    numPointers - Number of pointer references.
3951     //    pointers    - layout of the struct (with pointers marked.)
3952     //
3953     // Return Value:
3954     //    None
3955     //
3956     // Notes:
3957     //    This data is used in the codegen for GT_PUTARG_STK to decide how to copy the struct to the stack by value.
3958     //    If no pointer references are used, block copying instructions are used.
3959     //    Otherwise the pointer reference slots are copied atomically in a way that gcinfo is emitted.
3960     //    Any non pointer references between the pointer reference slots are copied in block fashion.
3961     //
3962     void setGcPointers(unsigned numPointers, BYTE* pointers)
3963     {
3964         gtNumberReferenceSlots = numPointers;
3965         gtGcPtrs = pointers;
3966     }
3967 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3968
3969 #ifdef DEBUG
3970     GenTreePtr      gtCall;                // the call node to which this argument belongs
3971 #endif
3972
3973 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
3974     // Instruction selection: during codegen time, what code sequence we will be using
3975     // to encode this operation.
3976
3977     enum PutArgStkKind : __int8
3978     {
3979         PutArgStkKindInvalid,
3980         PutArgStkKindRepInstr,
3981         PutArgStkKindUnroll,
3982     };
3983
3984     PutArgStkKind gtPutArgStkKind;
3985
3986     unsigned gtNumSlots;              // Number of slots for the argument to be passed on stack
3987     bool     gtIsStruct;              // This stack arg is a struct.
3988     unsigned gtNumberReferenceSlots;  // Number of reference slots.
3989     BYTE*    gtGcPtrs;                // gcPointers
3990 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
3991
3992 #if DEBUGGABLE_GENTREE
3993     GenTreePutArgStk() : GenTreeUnOp() {}
3994 #endif
3995 };
3996
3997 // Represents GT_COPY or GT_RELOAD node
3998 struct GenTreeCopyOrReload : public GenTreeUnOp
3999 {
4000     // State required to support copy/reload of a multi-reg call node.
4001     // First register is is always given by gtRegNum.
4002     //
4003 #if FEATURE_MULTIREG_RET
4004     regNumber gtOtherRegs[MAX_RET_REG_COUNT - 1];
4005 #endif
4006
4007     //----------------------------------------------------------
4008     // ClearOtherRegs: set gtOtherRegs to REG_NA.
4009     //
4010     // Arguments:
4011     //    None
4012     //
4013     // Return Value:
4014     //    None
4015     //
4016     void ClearOtherRegs()
4017     {
4018 #if FEATURE_MULTIREG_RET
4019         for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
4020         {
4021             gtOtherRegs[i] = REG_NA;
4022         }
4023 #endif
4024     }
4025
4026     //-----------------------------------------------------------
4027     // GetRegNumByIdx: Get regNumber of ith position.
4028     //
4029     // Arguments:
4030     //    idx   -   register position.
4031     //
4032     // Return Value:
4033     //    Returns regNumber assigned to ith position.
4034     //
4035     regNumber GetRegNumByIdx(unsigned idx) const
4036     {
4037         assert(idx < MAX_RET_REG_COUNT);
4038
4039         if (idx == 0)
4040         {
4041             return gtRegNum;
4042         }
4043
4044 #if FEATURE_MULTIREG_RET
4045         return gtOtherRegs[idx - 1];
4046 #else
4047         return REG_NA;
4048 #endif
4049     }
4050
4051     //-----------------------------------------------------------
4052     // SetRegNumByIdx: Set the regNumber for ith position.
4053     //
4054     // Arguments:
4055     //    reg   -   reg number 
4056     //    idx   -   register position.
4057     //
4058     // Return Value:
4059     //    None.
4060     //
4061     void SetRegNumByIdx(regNumber reg, unsigned idx)
4062     {
4063         assert(idx < MAX_RET_REG_COUNT);
4064
4065         if (idx == 0)
4066         {
4067             gtRegNum = reg;
4068         }
4069 #if FEATURE_MULTIREG_RET
4070         else
4071         {
4072             gtOtherRegs[idx - 1] = reg;
4073             assert(gtOtherRegs[idx - 1] == reg);
4074         }
4075 #else
4076         else
4077         {
4078             unreached();
4079         }
4080 #endif
4081     }
4082
4083     //----------------------------------------------------------------------------
4084     // CopyOtherRegs: copy multi-reg state from the given copy/reload node to this
4085     // node.
4086     //
4087     // Arguments:
4088     //    from  -  GenTree node from which to copy multi-reg state
4089     //
4090     // Return Value:
4091     //    None
4092     //
4093     // TODO-ARM: Implement this routine for Arm64 and Arm32
4094     // TODO-X86: Implement this routine for x86
4095     void CopyOtherRegs(GenTreeCopyOrReload* from)
4096     {
4097         assert(OperGet() == from->OperGet());
4098
4099 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
4100         for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
4101         {
4102             gtOtherRegs[i] = from->gtOtherRegs[i];
4103         }
4104 #endif
4105     }
4106
4107     GenTreeCopyOrReload(genTreeOps oper,
4108         var_types type,
4109         GenTree* op1) : GenTreeUnOp(oper, type, op1)
4110     {
4111         gtRegNum = REG_NA;
4112         ClearOtherRegs();
4113     }
4114
4115 #if DEBUGGABLE_GENTREE
4116     GenTreeCopyOrReload() : GenTreeUnOp() {}
4117 #endif
4118 };
4119
4120 //------------------------------------------------------------------------
4121 // Deferred inline functions of GenTree -- these need the subtypes above to
4122 // be defined already.
4123 //------------------------------------------------------------------------
4124
4125 //------------------------------------------------------------------------
4126 // IsFPZero: Checks whether this is a floating point constant with value 0.0
4127 //
4128 // Return Value:
4129 //    Returns true iff the tree is an GT_CNS_DBL, with value of 0.0.
4130
4131 inline bool GenTree::IsFPZero()
4132 {
4133     if ((gtOper == GT_CNS_DBL) && (gtDblCon.gtDconVal == 0.0))
4134         return true;
4135     return false;
4136 }
4137
4138 //------------------------------------------------------------------------
4139 // IsIntegralConst: Checks whether this is a constant node with the given value
4140 //
4141 // Arguments:
4142 //    constVal - the value of interest
4143 //
4144 // Return Value:
4145 //    Returns true iff the tree is an integral constant opcode, with
4146 //    the given value.
4147 //
4148 // Notes:
4149 //    Like gtIconVal, the argument is of ssize_t, so cannot check for
4150 //    long constants in a target-independent way.
4151
4152 inline bool GenTree::IsIntegralConst(ssize_t constVal)
4153
4154 {
4155     if ((gtOper == GT_CNS_INT) && (gtIntConCommon.IconValue() == constVal))
4156         return true;
4157
4158     if ((gtOper == GT_CNS_LNG) && (gtIntConCommon.LngValue() == constVal))
4159         return true;
4160
4161     return false;
4162 }
4163
4164 inline bool GenTree::IsBoxedValue()
4165 {
4166     assert(gtOper != GT_BOX || gtBox.BoxOp() != NULL);
4167     return (gtOper == GT_BOX) && (gtFlags & GTF_BOX_VALUE);
4168 }
4169
4170 inline GenTreePtr GenTree::MoveNext()
4171 {
4172     assert(IsList());
4173     return gtOp.gtOp2;
4174 }
4175
4176 #ifdef DEBUG
4177 //------------------------------------------------------------------------
4178 // IsListForMultiRegArg: Given an GenTree node that represents an argument
4179 //                       enforce (or don't enforce) the following invariant.
4180 //
4181 // For LEGACY_BACKEND or architectures that don't support MultiReg args
4182 // we don't allow a GT_LIST at all.
4183 //
4184 // Currently for AMD64 UNIX we allow a limited case where a GT_LIST is 
4185 // allowed but every element must be a GT_LCL_FLD.
4186 //
4187 // For the future targets that allow for Multireg args (and this includes
4188 //  the current ARM64 target) we allow a GT_LIST of arbitrary nodes, these
4189 //  would typically start out as GT_LCL_VARs or GT_LCL_FLDS or GT_INDs, 
4190 //  but could be changed into constants or GT_COMMA trees by the later 
4191 //  optimization phases.
4192 // 
4193 // Arguments:
4194 //    instance method for a GenTree node
4195 //
4196 // Return values:
4197 //    true:      the GenTree node is accepted as a valid argument
4198 //    false:     the GenTree node is not accepted as a valid argumeny
4199 //
4200 inline bool GenTree::IsListForMultiRegArg()
4201 {
4202     if (!IsList())
4203     {
4204         // We don't have a GT_LIST, so just return true.
4205         return true;
4206     }
4207     else  // We do have a GT_LIST
4208     {
4209 #if defined(LEGACY_BACKEND) || !FEATURE_MULTIREG_ARGS
4210
4211         // Not allowed to have a GT_LIST for an argument 
4212         // unless we have a RyuJIT backend and FEATURE_MULTIREG_ARGS
4213
4214         return false;
4215
4216 #else  // we have RyuJIT backend and FEATURE_MULTIREG_ARGS
4217
4218 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
4219         // For UNIX ABI we currently only allow a GT_LIST of GT_LCL_FLDs nodes 
4220         GenTree* gtListPtr = this;
4221         while (gtListPtr != nullptr) 
4222         {
4223             // ToDo: fix UNIX_AMD64 so that we do not generate this kind of a List
4224             //  Note the list as currently created is malformed, as the last entry is a nullptr
4225             if (gtListPtr->Current() == nullptr)
4226                 break;
4227
4228             // Only a list of GT_LCL_FLDs is allowed
4229             if (gtListPtr->Current()->OperGet() != GT_LCL_FLD)
4230             {
4231                 return false;
4232             }
4233             gtListPtr = gtListPtr->MoveNext();
4234         }
4235 #endif  // FEATURE_UNIX_AMD64_STRUCT_PASSING
4236
4237         // Note that for non-UNIX ABI the GT_LIST may contain any node
4238         //
4239         // We allow this GT_LIST as an argument 
4240         return true;
4241
4242 #endif  // RyuJIT backend and FEATURE_MULTIREG_ARGS
4243     }
4244 }
4245 #endif // DEBUG
4246
4247 inline GenTreePtr GenTree::Current()
4248 {
4249     assert(IsList());
4250     return gtOp.gtOp1;
4251 }
4252
4253 inline GenTreePtr *GenTree::pCurrent()
4254 {
4255     assert(IsList());
4256     return &(gtOp.gtOp1);
4257 }
4258
4259 inline GenTreePtr      GenTree::gtGetOp1() 
4260 {
4261     return gtOp.gtOp1;
4262 }
4263
4264 #ifdef DEBUG
4265 /* static */
4266 inline bool GenTree::RequiresNonNullOp2(genTreeOps oper)
4267 {
4268     switch (oper)
4269     {
4270     case GT_ADD:
4271     case GT_SUB:
4272     case GT_MUL:
4273     case GT_DIV:
4274     case GT_MOD:
4275     case GT_UDIV:
4276     case GT_UMOD:
4277     case GT_OR:
4278     case GT_XOR:
4279     case GT_AND:
4280     case GT_LSH:
4281     case GT_RSH:
4282     case GT_RSZ:
4283     case GT_ROL:
4284     case GT_ROR:
4285     case GT_INDEX:
4286     case GT_ASG:
4287     case GT_ASG_ADD:
4288     case GT_ASG_SUB:
4289     case GT_ASG_MUL:
4290     case GT_ASG_DIV:
4291     case GT_ASG_MOD:
4292     case GT_ASG_UDIV:
4293     case GT_ASG_UMOD:
4294     case GT_ASG_OR:
4295     case GT_ASG_XOR:
4296     case GT_ASG_AND:
4297     case GT_ASG_LSH:
4298     case GT_ASG_RSH:
4299     case GT_ASG_RSZ:
4300     case GT_EQ:
4301     case GT_NE:
4302     case GT_LT:
4303     case GT_LE:
4304     case GT_GE:
4305     case GT_GT:
4306     case GT_COMMA:
4307     case GT_QMARK:
4308     case GT_COLON:
4309     case GT_MKREFANY:
4310     case GT_INITBLK:
4311     case GT_COPYBLK:
4312         return true;
4313     default:
4314         return false;
4315     }
4316 }
4317 #endif // DEBUG
4318
4319 inline GenTreePtr      GenTree::gtGetOp2() 
4320 {
4321     /* gtOp.gtOp2 is only valid for GTK_BINOP nodes. */
4322
4323     GenTreePtr op2 = OperIsBinary() ? gtOp.gtOp2 : nullptr;
4324
4325     // This documents the genTreeOps for which gtOp.gtOp2 cannot be nullptr.
4326     // This helps prefix in its analyis of code which calls gtGetOp2()
4327
4328     assert((op2 != nullptr) || !RequiresNonNullOp2(gtOper));
4329
4330     return op2;
4331 }
4332
4333 inline GenTreePtr      GenTree::gtEffectiveVal(bool commaOnly)
4334 {
4335     switch (gtOper)
4336     {
4337     case GT_COMMA:
4338         return gtOp.gtOp2->gtEffectiveVal(commaOnly);
4339
4340     case GT_NOP:
4341         if (!commaOnly && gtOp.gtOp1 != NULL) 
4342             return gtOp.gtOp1->gtEffectiveVal();
4343         break;
4344
4345     default:
4346         break;
4347     }       
4348
4349     return this;
4350 }
4351
4352 inline GenTree*         GenTree::gtSkipReloadOrCopy()
4353 {
4354     // There can be only one reload or copy (we can't have a reload/copy of a reload/copy)
4355     if (gtOper == GT_RELOAD || gtOper == GT_COPY)
4356     {
4357         assert(gtGetOp1()->OperGet() != GT_RELOAD && gtGetOp1()->OperGet() != GT_COPY);
4358         return gtGetOp1();
4359     }
4360     return this;
4361 }
4362
4363 //-----------------------------------------------------------------------------------
4364 // IsMultiRegCall: whether a call node returning its value in more than one register
4365 //
4366 // Arguments:
4367 //     None
4368 //
4369 // Return Value:
4370 //     Returns true if this GenTree is a multi register returning call 
4371 inline bool  GenTree::IsMultiRegCall() const
4372 {
4373     if (this->IsCall())
4374     {
4375         // We cannot use AsCall() as it is not declared const
4376         const GenTreeCall* call = reinterpret_cast<const GenTreeCall *>(this);
4377         return call->HasMultiRegRetVal();
4378     }
4379
4380     return false;
4381 }
4382
4383 //-------------------------------------------------------------------------
4384 // IsCopyOrReload: whether this is a GT_COPY or GT_RELOAD node.
4385 //
4386 // Arguments:
4387 //     None
4388 //
4389 // Return Value:
4390 //     Returns true if this GenTree is a copy or reload node.
4391 inline bool GenTree::IsCopyOrReload() const
4392 {
4393     return (gtOper == GT_COPY || gtOper == GT_RELOAD);
4394 }
4395
4396 //-----------------------------------------------------------------------------------
4397 // IsCopyOrReloadOfMultiRegCall: whether this is a GT_COPY or GT_RELOAD of a multi-reg
4398 // call node.
4399 //
4400 // Arguments:
4401 //     None
4402 //
4403 // Return Value:
4404 //     Returns true if this GenTree is a copy or reload of multi-reg call node.
4405 inline bool GenTree::IsCopyOrReloadOfMultiRegCall() const
4406 {
4407     if (IsCopyOrReload())
4408     {
4409         GenTree* t = const_cast<GenTree*>(this);
4410         return t->gtGetOp1()->IsMultiRegCall();
4411     }
4412
4413     return false;
4414 }
4415
4416 inline bool GenTree::IsCnsIntOrI() const
4417 {
4418     return (gtOper == GT_CNS_INT);
4419 }
4420
4421 inline bool GenTree::IsIntegralConst() const
4422 {
4423 #ifdef _TARGET_64BIT_
4424     return IsCnsIntOrI();
4425 #else // !_TARGET_64BIT_
4426     return ((gtOper == GT_CNS_INT) || (gtOper == GT_CNS_LNG));
4427 #endif // !_TARGET_64BIT_
4428 }
4429
4430 inline bool GenTree::IsIntCnsFitsInI32()
4431 {
4432 #ifdef _TARGET_64BIT_
4433     return IsCnsIntOrI() && ((int)gtIntConCommon.IconValue() == gtIntConCommon.IconValue());
4434 #else // !_TARGET_64BIT_
4435     return IsCnsIntOrI();
4436 #endif // !_TARGET_64BIT_
4437 }
4438
4439 inline bool GenTree::IsCnsFltOrDbl() const
4440 {
4441     return OperGet() == GT_CNS_DBL;
4442 }
4443
4444 inline bool GenTree::IsCnsNonZeroFltOrDbl()
4445 {
4446     if (OperGet() == GT_CNS_DBL)
4447     {
4448         double constValue = gtDblCon.gtDconVal;
4449         return *(__int64*)&constValue != 0;
4450     }
4451
4452     return false;
4453 }
4454
4455 inline bool GenTree::IsHelperCall() { return OperGet() == GT_CALL && gtCall.gtCallType == CT_HELPER; }
4456
4457 inline var_types GenTree::CastFromType() { return this->gtCast.CastOp()->TypeGet(); }
4458 inline var_types& GenTree::CastToType()  { return this->gtCast.gtCastType; }
4459
4460
4461 /*****************************************************************************/
4462
4463 #ifndef _HOST_64BIT_
4464 #include <poppack.h>
4465 #endif
4466
4467 /*****************************************************************************/
4468
4469 #if     SMALL_TREE_NODES
4470
4471 // In debug, on some platforms (e.g., when LATE_DISASM is defined), GenTreeIntCon is bigger than GenTreeLclFld.
4472 const
4473 size_t              TREE_NODE_SZ_SMALL = max(sizeof(GenTreeIntCon), sizeof(GenTreeLclFld));
4474
4475 #endif // SMALL_TREE_NODES
4476
4477 const
4478 size_t              TREE_NODE_SZ_LARGE = sizeof(GenTreeCall);
4479
4480 /*****************************************************************************
4481  * Types returned by GenTree::lvaLclVarRefs()
4482  */
4483
4484 enum varRefKinds
4485 {
4486     VR_INVARIANT  = 0x00,      // an invariant value
4487     VR_NONE       = 0x00,
4488     VR_IND_REF    = 0x01,      // an object reference
4489     VR_IND_SCL    = 0x02,      // a non-object reference
4490     VR_GLB_VAR    = 0x04,      // a global (clsVar)
4491 };
4492 // Add a temp define to avoid merge conflict.
4493 #define VR_IND_PTR VR_IND_REF
4494
4495 /*****************************************************************************/
4496 #endif  // !GENTREE_H
4497 /*****************************************************************************/
4498