Merge pull request #13926 from sdmaclea/PR-ARM64-BOUND-CHECK
[platform/upstream/coreclr.git] / src / jit / codegenlinear.h
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 //
6 // This file contains the members of CodeGen that are defined and used
7 // only by the RyuJIT backend.  It is included by CodeGen.h in the
8 // definition of the CodeGen class.
9 //
10
11 #ifndef LEGACY_BACKEND // Not necessary (it's this way in the #include location), but helpful to IntelliSense
12
13 void genSetRegToConst(regNumber targetReg, var_types targetType, GenTreePtr tree);
14 void genCodeForTreeNode(GenTreePtr treeNode);
15 void genCodeForBinary(GenTreePtr treeNode);
16
17 #if defined(_TARGET_X86_)
18 void genCodeForLongUMod(GenTreeOp* node);
19 #endif // _TARGET_X86_
20
21 void genCodeForDivMod(GenTreeOp* treeNode);
22 void genCodeForMul(GenTreeOp* treeNode);
23 void genCodeForMulHi(GenTreeOp* treeNode);
24 void genLeaInstruction(GenTreeAddrMode* lea);
25 void genSetRegToCond(regNumber dstReg, GenTreePtr tree);
26
27 #if defined(_TARGET_ARMARCH_)
28 void genScaledAdd(emitAttr attr, regNumber targetReg, regNumber baseReg, regNumber indexReg, int scale);
29 #endif // _TARGET_ARMARCH_
30
31 #if defined(_TARGET_ARM_)
32 void genCodeForMulLong(GenTreeMultiRegOp* treeNode);
33 #endif // _TARGET_ARM_
34
35 #if !defined(_TARGET_64BIT_)
36 void genLongToIntCast(GenTreePtr treeNode);
37 #endif
38
39 void genIntToIntCast(GenTreePtr treeNode);
40 void genFloatToFloatCast(GenTreePtr treeNode);
41 void genFloatToIntCast(GenTreePtr treeNode);
42 void genIntToFloatCast(GenTreePtr treeNode);
43 void genCkfinite(GenTreePtr treeNode);
44 void genCodeForCompare(GenTreeOp* tree);
45 void genIntrinsic(GenTreePtr treeNode);
46 void genPutArgStk(GenTreePutArgStk* treeNode);
47 void genPutArgReg(GenTreeOp* tree);
48 #ifdef _TARGET_ARM_
49 void genPutArgSplit(GenTreePutArgSplit* treeNode);
50 #endif
51
52 #if defined(_TARGET_XARCH_)
53 unsigned getBaseVarForPutArgStk(GenTreePtr treeNode);
54 #endif // _TARGET_XARCH_
55
56 #if defined(_TARGET_XARCH_) || defined(_TARGET_ARM64_)
57 unsigned getFirstArgWithStackSlot();
58 #endif // _TARGET_XARCH_ || _TARGET_ARM64_
59
60 void genCompareFloat(GenTreePtr treeNode);
61 void genCompareInt(GenTreePtr treeNode);
62
63 #ifdef FEATURE_SIMD
64 enum SIMDScalarMoveType
65 {
66     SMT_ZeroInitUpper,                  // zero initlaize target upper bits
67     SMT_ZeroInitUpper_SrcHasUpperZeros, // zero initialize target upper bits; source upper bits are known to be zero
68     SMT_PreserveUpper                   // preserve target upper bits
69 };
70
71 instruction getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_types baseType, unsigned* ival = nullptr);
72 void genSIMDScalarMove(
73     var_types targetType, var_types type, regNumber target, regNumber src, SIMDScalarMoveType moveType);
74 void genSIMDZero(var_types targetType, var_types baseType, regNumber targetReg);
75 void genSIMDIntrinsicInit(GenTreeSIMD* simdNode);
76 void genSIMDIntrinsicInitN(GenTreeSIMD* simdNode);
77 void genSIMDIntrinsicInitArray(GenTreeSIMD* simdNode);
78 void genSIMDIntrinsicUnOp(GenTreeSIMD* simdNode);
79 void genSIMDIntrinsicBinOp(GenTreeSIMD* simdNode);
80 void genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode);
81 void genSIMDIntrinsicDotProduct(GenTreeSIMD* simdNode);
82 void genSIMDIntrinsicSetItem(GenTreeSIMD* simdNode);
83 void genSIMDIntrinsicGetItem(GenTreeSIMD* simdNode);
84 void genSIMDIntrinsicShuffleSSE2(GenTreeSIMD* simdNode);
85 void genSIMDIntrinsicUpperSave(GenTreeSIMD* simdNode);
86 void genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode);
87 void genSIMDLo64BitConvert(SIMDIntrinsicID intrinsicID,
88                            var_types       simdType,
89                            var_types       baseType,
90                            regNumber       tmpReg,
91                            regNumber       tmpIntReg,
92                            regNumber       targetReg);
93 void genSIMDIntrinsic32BitConvert(GenTreeSIMD* simdNode);
94 void genSIMDIntrinsic64BitConvert(GenTreeSIMD* simdNode);
95 void genSIMDIntrinsicNarrow(GenTreeSIMD* simdNode);
96 void genSIMDExtractUpperHalf(GenTreeSIMD* simdNode, regNumber srcReg, regNumber tgtReg);
97 void genSIMDIntrinsicWiden(GenTreeSIMD* simdNode);
98 void genSIMDIntrinsic(GenTreeSIMD* simdNode);
99 void genSIMDCheck(GenTree* treeNode);
100
101 // TYP_SIMD12 (i.e Vector3 of size 12 bytes) is not a hardware supported size and requires
102 // two reads/writes on 64-bit targets. These routines abstract reading/writing of Vector3
103 // values through an indirection. Note that Vector3 locals allocated on stack would have
104 // their size rounded to TARGET_POINTER_SIZE (which is 8 bytes on 64-bit targets) and hence
105 // Vector3 locals could be treated as TYP_SIMD16 while reading/writing.
106 void genStoreIndTypeSIMD12(GenTree* treeNode);
107 void genLoadIndTypeSIMD12(GenTree* treeNode);
108 void genStoreLclTypeSIMD12(GenTree* treeNode);
109 void genLoadLclTypeSIMD12(GenTree* treeNode);
110 #ifdef _TARGET_X86_
111 void genStoreSIMD12ToStack(regNumber operandReg, regNumber tmpReg);
112 void genPutArgStkSIMD12(GenTree* treeNode);
113 #endif // _TARGET_X86_
114 #endif // FEATURE_SIMD
115
116 #if !defined(_TARGET_64BIT_)
117
118 // CodeGen for Long Ints
119
120 void genStoreLongLclVar(GenTree* treeNode);
121
122 #endif // !defined(_TARGET_64BIT_)
123
124 void genProduceReg(GenTree* tree);
125 void genUnspillRegIfNeeded(GenTree* tree);
126 regNumber genConsumeReg(GenTree* tree);
127 void genCopyRegIfNeeded(GenTree* tree, regNumber needReg);
128 void genConsumeRegAndCopy(GenTree* tree, regNumber needReg);
129
130 void genConsumeIfReg(GenTreePtr tree)
131 {
132     if (!tree->isContained())
133     {
134         (void)genConsumeReg(tree);
135     }
136 }
137
138 void genRegCopy(GenTreePtr tree);
139 void genTransferRegGCState(regNumber dst, regNumber src);
140 void genConsumeAddress(GenTree* addr);
141 void genConsumeAddrMode(GenTreeAddrMode* mode);
142 void genSetBlockSize(GenTreeBlk* blkNode, regNumber sizeReg);
143 void genConsumeBlockSrc(GenTreeBlk* blkNode);
144 void genSetBlockSrc(GenTreeBlk* blkNode, regNumber srcReg);
145 void genConsumeBlockOp(GenTreeBlk* blkNode, regNumber dstReg, regNumber srcReg, regNumber sizeReg);
146
147 #ifdef FEATURE_PUT_STRUCT_ARG_STK
148 void genConsumePutStructArgStk(GenTreePutArgStk* putArgStkNode, regNumber dstReg, regNumber srcReg, regNumber sizeReg);
149 #endif // FEATURE_PUT_STRUCT_ARG_STK
150 #ifdef _TARGET_ARM_
151 void genConsumeArgSplitStruct(GenTreePutArgSplit* putArgNode);
152 #endif
153
154 void genConsumeRegs(GenTree* tree);
155 void genConsumeOperands(GenTreeOp* tree);
156 void genEmitGSCookieCheck(bool pushReg);
157 void genSetRegToIcon(regNumber reg, ssize_t val, var_types type = TYP_INT, insFlags flags = INS_FLAGS_DONT_CARE);
158 void genCodeForShift(GenTreePtr tree);
159
160 #if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
161 void genCodeForShiftLong(GenTreePtr tree);
162 #endif
163
164 #ifdef _TARGET_XARCH_
165 void genCodeForShiftRMW(GenTreeStoreInd* storeInd);
166 void genCodeForBT(GenTreeOp* bt);
167 #endif // _TARGET_XARCH_
168
169 void genCodeForCast(GenTreeOp* tree);
170 void genCodeForLclAddr(GenTree* tree);
171 void genCodeForIndexAddr(GenTreeIndexAddr* tree);
172 void genCodeForIndir(GenTreeIndir* tree);
173 void genCodeForNegNot(GenTree* tree);
174 void genCodeForLclVar(GenTreeLclVar* tree);
175 void genCodeForLclFld(GenTreeLclFld* tree);
176 void genCodeForStoreLclFld(GenTreeLclFld* tree);
177 void genCodeForStoreLclVar(GenTreeLclVar* tree);
178 void genCodeForReturnTrap(GenTreeOp* tree);
179 void genCodeForJcc(GenTreeCC* tree);
180 void genCodeForSetcc(GenTreeCC* setcc);
181 void genCodeForStoreInd(GenTreeStoreInd* tree);
182 void genCodeForSwap(GenTreeOp* tree);
183 void genCodeForCpObj(GenTreeObj* cpObjNode);
184 void genCodeForCpBlk(GenTreeBlk* cpBlkNode);
185 void genCodeForCpBlkRepMovs(GenTreeBlk* cpBlkNode);
186 void genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode);
187 void genCodeForPhysReg(GenTreePhysReg* tree);
188 void genCodeForNullCheck(GenTreeOp* tree);
189 void genCodeForCmpXchg(GenTreeCmpXchg* tree);
190
191 void genAlignStackBeforeCall(GenTreePutArgStk* putArgStk);
192 void genAlignStackBeforeCall(GenTreeCall* call);
193 void genRemoveAlignmentAfterCall(GenTreeCall* call, unsigned bias = 0);
194
195 #if defined(UNIX_X86_ABI)
196
197 unsigned curNestedAlignment; // Keep track of alignment adjustment required during codegen.
198 unsigned maxNestedAlignment; // The maximum amount of alignment adjustment required.
199
200 void SubtractNestedAlignment(unsigned adjustment)
201 {
202     assert(curNestedAlignment >= adjustment);
203     unsigned newNestedAlignment = curNestedAlignment - adjustment;
204     if (curNestedAlignment != newNestedAlignment)
205     {
206         JITDUMP("Adjusting stack nested alignment from %d to %d\n", curNestedAlignment, newNestedAlignment);
207     }
208     curNestedAlignment = newNestedAlignment;
209 }
210
211 void AddNestedAlignment(unsigned adjustment)
212 {
213     unsigned newNestedAlignment = curNestedAlignment + adjustment;
214     if (curNestedAlignment != newNestedAlignment)
215     {
216         JITDUMP("Adjusting stack nested alignment from %d to %d\n", curNestedAlignment, newNestedAlignment);
217     }
218     curNestedAlignment = newNestedAlignment;
219
220     if (curNestedAlignment > maxNestedAlignment)
221     {
222         JITDUMP("Max stack nested alignment changed from %d to %d\n", maxNestedAlignment, curNestedAlignment);
223         maxNestedAlignment = curNestedAlignment;
224     }
225 }
226
227 #endif
228
229 #ifdef FEATURE_PUT_STRUCT_ARG_STK
230 #ifdef _TARGET_X86_
231 bool genAdjustStackForPutArgStk(GenTreePutArgStk* putArgStk);
232 void genPushReg(var_types type, regNumber srcReg);
233 void genPutArgStkFieldList(GenTreePutArgStk* putArgStk);
234 #endif // _TARGET_X86_
235
236 void genPutStructArgStk(GenTreePutArgStk* treeNode);
237
238 unsigned genMove8IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
239 unsigned genMove4IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
240 unsigned genMove2IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
241 unsigned genMove1IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
242 void genStructPutArgRepMovs(GenTreePutArgStk* putArgStkNode);
243 void genStructPutArgUnroll(GenTreePutArgStk* putArgStkNode);
244 void genStoreRegToStackArg(var_types type, regNumber reg, int offset);
245 #endif // FEATURE_PUT_STRUCT_ARG_STK
246
247 void genCodeForLoadOffset(instruction ins, emitAttr size, regNumber dst, GenTree* base, unsigned offset);
248 void genCodeForStoreOffset(instruction ins, emitAttr size, regNumber src, GenTree* base, unsigned offset);
249
250 #ifdef _TARGET_ARM64_
251 void genCodeForLoadPairOffset(regNumber dst, regNumber dst2, GenTree* base, unsigned offset);
252 void genCodeForStorePairOffset(regNumber src, regNumber src2, GenTree* base, unsigned offset);
253 #endif // _TARGET_ARM64_
254
255 void genCodeForStoreBlk(GenTreeBlk* storeBlkNode);
256 void genCodeForInitBlk(GenTreeBlk* initBlkNode);
257 void genCodeForInitBlkRepStos(GenTreeBlk* initBlkNode);
258 void genCodeForInitBlkUnroll(GenTreeBlk* initBlkNode);
259 void genJumpTable(GenTree* tree);
260 void genTableBasedSwitch(GenTree* tree);
261 void genCodeForArrIndex(GenTreeArrIndex* treeNode);
262 void genCodeForArrOffset(GenTreeArrOffs* treeNode);
263 instruction genGetInsForOper(genTreeOps oper, var_types type);
264 bool genEmitOptimizedGCWriteBarrier(GCInfo::WriteBarrierForm writeBarrierForm, GenTree* addr, GenTree* data);
265 void genCallInstruction(GenTreeCall* call);
266 void genJmpMethod(GenTreePtr jmp);
267 BasicBlock* genCallFinally(BasicBlock* block);
268 void genCodeForJumpTrue(GenTreePtr tree);
269
270 #if FEATURE_EH_FUNCLETS
271 void genEHCatchRet(BasicBlock* block);
272 #else  // !FEATURE_EH_FUNCLETS
273 void genEHFinallyOrFilterRet(BasicBlock* block);
274 #endif // !FEATURE_EH_FUNCLETS
275
276 void genMultiRegCallStoreToLocal(GenTreePtr treeNode);
277
278 // Deals with codegen for muti-register struct returns.
279 bool isStructReturn(GenTreePtr treeNode);
280 void genStructReturn(GenTreePtr treeNode);
281
282 void genReturn(GenTreePtr treeNode);
283
284 void genLclHeap(GenTreePtr tree);
285
286 bool genIsRegCandidateLocal(GenTreePtr tree)
287 {
288     if (!tree->IsLocal())
289     {
290         return false;
291     }
292     const LclVarDsc* varDsc = &compiler->lvaTable[tree->gtLclVarCommon.gtLclNum];
293     return (varDsc->lvIsRegCandidate());
294 }
295
296 #ifdef FEATURE_PUT_STRUCT_ARG_STK
297 #ifdef _TARGET_X86_
298 bool m_pushStkArg;
299 #else  // !_TARGET_X86_
300 unsigned m_stkArgVarNum;
301 unsigned m_stkArgOffset;
302 #endif // !_TARGET_X86_
303 #endif // !FEATURE_PUT_STRUCT_ARG_STK
304
305 #ifdef DEBUG
306 GenTree* lastConsumedNode;
307 void genNumberOperandUse(GenTree* const operand, int& useNum) const;
308 void genCheckConsumeNode(GenTree* const node);
309 #else  // !DEBUG
310 inline void genCheckConsumeNode(GenTree* treeNode)
311 {
312 }
313 #endif // DEBUG
314
315 #endif // !LEGACY_BACKEND