1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
|
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
/*****************************************************************************/
#ifndef GTNODE
#error Define GTNODE before including this file.
#endif
/*****************************************************************************/
//
// Node enum
// , "Node name"
// ,commutative
// ,operKind
GTNODE(NONE , "<none>" ,0,GTK_SPECIAL)
//-----------------------------------------------------------------------------
// Leaf nodes (i.e. these nodes have no sub-operands):
//-----------------------------------------------------------------------------
GTNODE(LCL_VAR , "lclVar" ,0,GTK_LEAF|GTK_LOCAL) // local variable
GTNODE(LCL_FLD , "lclFld" ,0,GTK_LEAF|GTK_LOCAL) // field in a non-primitive variable
GTNODE(LCL_VAR_ADDR , "&lclVar" ,0,GTK_LEAF) // address of local variable
GTNODE(LCL_FLD_ADDR , "&lclFld" ,0,GTK_LEAF) // address of field in a non-primitive variable
GTNODE(STORE_LCL_VAR , "st.lclVar" ,0,GTK_UNOP|GTK_LOCAL) // store to local variable
GTNODE(STORE_LCL_FLD , "st.lclFld" ,0,GTK_UNOP|GTK_LOCAL) // store to field in a non-primitive variable
GTNODE(CATCH_ARG , "catchArg" ,0,GTK_LEAF) // Exception object in a catch block
GTNODE(LABEL , "codeLabel" ,0,GTK_LEAF) // Jump-target
GTNODE(FTN_ADDR , "ftnAddr" ,0,GTK_LEAF) // Address of a function
GTNODE(RET_EXPR , "retExpr" ,0,GTK_LEAF) // Place holder for the return expression from an inline candidate
//-----------------------------------------------------------------------------
// Constant nodes:
//-----------------------------------------------------------------------------
GTNODE(CNS_INT , "const" ,0,GTK_LEAF|GTK_CONST)
GTNODE(CNS_LNG , "lconst" ,0,GTK_LEAF|GTK_CONST)
GTNODE(CNS_DBL , "dconst" ,0,GTK_LEAF|GTK_CONST)
GTNODE(CNS_STR , "sconst" ,0,GTK_LEAF|GTK_CONST)
//-----------------------------------------------------------------------------
// Unary operators (1 operand):
//-----------------------------------------------------------------------------
GTNODE(NOT , "~" ,0,GTK_UNOP)
GTNODE(NOP , "nop" ,0,GTK_UNOP)
GTNODE(NEG , "unary -" ,0,GTK_UNOP)
GTNODE(COPY , "copy" ,0,GTK_UNOP) // Copies a variable from its current location to a register that satisfies
// code generation constraints. The child is the actual lclVar node.
GTNODE(RELOAD , "reload" ,0,GTK_UNOP)
GTNODE(CHS , "flipsign" ,0,GTK_BINOP|GTK_ASGOP) // GT_CHS is actually unary -- op2 is ignored.
// Changing to unary presently causes problems, though -- take a little work to fix.
GTNODE(ARR_LENGTH , "arrLen" ,0,GTK_UNOP|GTK_EXOP) // array-length
GTNODE(INTRINSIC , "intrinsic" ,0,GTK_BINOP|GTK_EXOP) // intrinsics
GTNODE(LOCKADD , "lockAdd" ,0,GTK_BINOP)
GTNODE(XADD , "XAdd" ,0,GTK_BINOP)
GTNODE(XCHG , "Xchg" ,0,GTK_BINOP)
GTNODE(CMPXCHG , "cmpxchg" ,0,GTK_SPECIAL)
GTNODE(MEMORYBARRIER , "memoryBarrier" ,0,GTK_LEAF)
GTNODE(CAST , "cast" ,0,GTK_UNOP|GTK_EXOP) // conversion to another type
GTNODE(CKFINITE , "ckfinite" ,0,GTK_UNOP) // Check for NaN
GTNODE(LCLHEAP , "lclHeap" ,0,GTK_UNOP) // alloca()
GTNODE(JMP , "jump" ,0,GTK_LEAF) // Jump to another function
GTNODE(ADDR , "addr" ,0,GTK_UNOP) // address of
GTNODE(IND , "indir" ,0,GTK_UNOP) // load indirection
GTNODE(STOREIND , "storeIndir" ,0,GTK_BINOP) // store indirection
// TODO-Cleanup: GT_ARR_BOUNDS_CHECK should be made a GTK_BINOP now that it has only two child nodes
GTNODE(ARR_BOUNDS_CHECK , "arrBndsChk" ,0,GTK_SPECIAL) // array bounds check
GTNODE(LDOBJ , "ldobj" ,0,GTK_UNOP|GTK_EXOP)
GTNODE(BOX , "box" ,0,GTK_UNOP|GTK_EXOP)
#ifdef FEATURE_SIMD
GTNODE(SIMD_CHK , "simdChk" ,0,GTK_SPECIAL) // Compare whether an index is less than the given SIMD vector length, and call CORINFO_HELP_RNGCHKFAIL if not.
// TODO-CQ: In future may want to add a field that specifies different exceptions but we'll
// need VM assistance for that.
// TODO-CQ: It would actually be very nice to make this an unconditional throw, and expose the control flow that
// does the compare, so that it can be more easily optimized. But that involves generating qmarks at import time...
#endif // FEATURE_SIMD
//-----------------------------------------------------------------------------
// Binary operators (2 operands):
//-----------------------------------------------------------------------------
GTNODE(ADD , "+" ,1,GTK_BINOP)
GTNODE(SUB , "-" ,0,GTK_BINOP)
GTNODE(MUL , "*" ,1,GTK_BINOP)
GTNODE(DIV , "/" ,0,GTK_BINOP)
GTNODE(MOD , "%" ,0,GTK_BINOP)
GTNODE(UDIV , "/" ,0,GTK_BINOP)
GTNODE(UMOD , "%" ,0,GTK_BINOP)
GTNODE(OR , "|" ,1,GTK_BINOP|GTK_LOGOP)
GTNODE(XOR , "^" ,1,GTK_BINOP|GTK_LOGOP)
GTNODE(AND , "&" ,1,GTK_BINOP|GTK_LOGOP)
GTNODE(LSH , "<<" ,0,GTK_BINOP)
GTNODE(RSH , ">>" ,0,GTK_BINOP)
GTNODE(RSZ , ">>>" ,0,GTK_BINOP)
GTNODE(ROL , "rol" ,0,GTK_BINOP)
GTNODE(ROR , "ror" ,0,GTK_BINOP)
GTNODE(MULHI , "mulhi" ,1,GTK_BINOP) // returns high bits (top N bits of the 2N bit result of an NxN multiply)
GTNODE(ASG , "=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_ADD , "+=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_SUB , "-=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_MUL , "*=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_DIV , "/=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_MOD , "%=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_UDIV , "/=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_UMOD , "%=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_OR , "|=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_XOR , "^=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_AND , "&=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_LSH , "<<=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_RSH , ">>=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(ASG_RSZ , ">>>=" ,0,GTK_BINOP|GTK_ASGOP)
GTNODE(EQ , "==" ,0,GTK_BINOP|GTK_RELOP)
GTNODE(NE , "!=" ,0,GTK_BINOP|GTK_RELOP)
GTNODE(LT , "<" ,0,GTK_BINOP|GTK_RELOP)
GTNODE(LE , "<=" ,0,GTK_BINOP|GTK_RELOP)
GTNODE(GE , ">=" ,0,GTK_BINOP|GTK_RELOP)
GTNODE(GT , ">" ,0,GTK_BINOP|GTK_RELOP)
GTNODE(COMMA , "comma" ,0,GTK_BINOP)
GTNODE(QMARK , "qmark" ,0,GTK_BINOP|GTK_EXOP)
GTNODE(COLON , "colon" ,0,GTK_BINOP)
GTNODE(INDEX , "[]" ,0,GTK_BINOP|GTK_EXOP) // SZ-array-element
GTNODE(MKREFANY , "mkrefany" ,0,GTK_BINOP)
GTNODE(LEA , "lea" ,0,GTK_BINOP|GTK_EXOP)
#if !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_)
// A GT_LONG node simply represents the long value produced by the concatenation
// of its two (lower and upper half) operands. Some GT_LONG nodes are transient,
// during the decomposing of longs; others are handled by codegen as operands of
// nodes such as calls, returns and stores of long lclVars.
GTNODE(LONG , "long" ,0,GTK_BINOP)
// The following are nodes representing the upper half of a 64-bit operation
// that requires a carry/borrow. However, they are all named GT_XXX_HI for
// consistency.
GTNODE(ADD_HI , "+Hi" ,1,GTK_BINOP|GTK_EXOP)
GTNODE(SUB_HI , "-Hi" ,0,GTK_BINOP|GTK_EXOP)
GTNODE(MUL_HI , "*Hi" ,1,GTK_BINOP|GTK_EXOP)
GTNODE(DIV_HI , "/Hi" ,0,GTK_BINOP|GTK_EXOP)
GTNODE(MOD_HI , "%Hi" ,0,GTK_BINOP|GTK_EXOP)
#endif // !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_)
#ifdef FEATURE_SIMD
GTNODE(SIMD , "simd" ,0,GTK_BINOP|GTK_EXOP) // SIMD functions/operators/intrinsics
#endif // FEATURE_SIMD
//-----------------------------------------------------------------------------
// Other nodes that look like unary/binary operators:
//-----------------------------------------------------------------------------
GTNODE(JTRUE , "jmpTrue" ,0,GTK_UNOP)
GTNODE(LIST , "<list>" ,0,GTK_BINOP)
//-----------------------------------------------------------------------------
// Other nodes that have special structure:
//-----------------------------------------------------------------------------
GTNODE(FIELD , "field" ,0,GTK_SPECIAL) // Member-field
GTNODE(ARR_ELEM , "arrMD&" ,0,GTK_SPECIAL) // Multi-dimensional array-element address
GTNODE(ARR_INDEX , "arrMDIdx" ,0,GTK_BINOP|GTK_EXOP) // Effective, bounds-checked index for one dimension of a multi-dimensional array element
GTNODE(ARR_OFFSET , "arrMDOffs" ,0,GTK_SPECIAL) // Flattened offset of multi-dimensional array element
GTNODE(CALL , "call()" ,0,GTK_SPECIAL)
//-----------------------------------------------------------------------------
// Statement operator nodes:
//-----------------------------------------------------------------------------
GTNODE(BEG_STMTS , "begStmts" ,0,GTK_SPECIAL) // used only temporarily in importer by impBegin/EndTreeList()
GTNODE(STMT , "stmtExpr" ,0,GTK_SPECIAL) // top-level list nodes in bbTreeList
GTNODE(RETURN , "return" ,0,GTK_UNOP) // return from current function
GTNODE(SWITCH , "switch" ,0,GTK_UNOP) // switch
GTNODE(NO_OP , "no_op" ,0,GTK_LEAF) // nop!
GTNODE(START_NONGC, "start_nongc",0,GTK_LEAF) // starts a new instruction group that will be non-gc interruptible
GTNODE(PROF_HOOK , "prof_hook" ,0,GTK_LEAF) // profiler Enter/Leave/TailCall hook
GTNODE(RETFILT , "retfilt", 0,GTK_UNOP) // end filter with TYP_I_IMPL return value
#if !FEATURE_EH_FUNCLETS
GTNODE(END_LFIN , "endLFin" ,0,GTK_LEAF) // end locally-invoked finally
#endif // !FEATURE_EH_FUNCLETS
GTNODE(INITBLK , "initBlk" ,0,GTK_BINOP)
GTNODE(COPYBLK , "copyBlk" ,0,GTK_BINOP)
GTNODE(COPYOBJ , "copyObj" ,0,GTK_BINOP)
//-----------------------------------------------------------------------------
// Nodes used for optimizations.
//-----------------------------------------------------------------------------
GTNODE(PHI , "phi" ,0,GTK_UNOP) // phi node for ssa.
GTNODE(PHI_ARG , "phiArg" ,0,GTK_LEAF|GTK_LOCAL) // phi(phiarg, phiarg, phiarg)
//-----------------------------------------------------------------------------
// Nodes used by Lower to generate a closer CPU representation of other nodes
//-----------------------------------------------------------------------------
GTNODE(JMPTABLE , "jumpTable" , 0, GTK_LEAF) // Generates the jump table for switches
GTNODE(SWITCH_TABLE, "tableSwitch", 0, GTK_BINOP) // Jump Table based switch construct
//-----------------------------------------------------------------------------
// Nodes used only within the code generator:
//-----------------------------------------------------------------------------
GTNODE(REG_VAR , "regVar" ,0,GTK_LEAF|GTK_LOCAL) // register variable
GTNODE(CLS_VAR , "clsVar" ,0,GTK_LEAF) // static data member
GTNODE(CLS_VAR_ADDR , "&clsVar" ,0,GTK_LEAF) // static data member address
GTNODE(STORE_CLS_VAR, "st.clsVar" ,0,GTK_LEAF) // store to static data member
GTNODE(ARGPLACE , "argPlace" ,0,GTK_LEAF) // placeholder for a register arg
GTNODE(NULLCHECK , "nullcheck" ,0,GTK_UNOP) // null checks the source
GTNODE(PHYSREG , "physregSrc" ,0,GTK_LEAF) // read from a physical register
GTNODE(PHYSREGDST , "physregDst" ,0,GTK_UNOP) // write to a physical register
GTNODE(EMITNOP , "emitnop" ,0,GTK_LEAF) // emitter-placed nop
GTNODE(PINVOKE_PROLOG,"pinvoke_prolog",0,GTK_LEAF) // pinvoke prolog seq
GTNODE(PINVOKE_EPILOG,"pinvoke_epilog",0,GTK_LEAF) // pinvoke epilog seq
GTNODE(PUTARG_REG , "putarg_reg" ,0,GTK_UNOP) // operator that places outgoing arg in register
GTNODE(PUTARG_STK , "putarg_stk" ,0,GTK_UNOP) // operator that places outgoing arg in stack
GTNODE(RETURNTRAP , "returnTrap" ,0,GTK_UNOP) // a conditional call to wait on gc
GTNODE(SWAP , "swap" ,0,GTK_BINOP) // op1 and op2 swap (registers)
/*****************************************************************************/
#undef GTNODE
/*****************************************************************************/
|