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.
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.
11 #ifndef LEGACY_BACKEND // Not necessary (it's this way in the #include location), but helpful to IntelliSense
13 void genSetRegToConst(regNumber targetReg, var_types targetType, GenTreePtr tree);
14 void genCodeForTreeNode(GenTreePtr treeNode);
15 void genCodeForBinary(GenTreePtr treeNode);
17 #if defined(_TARGET_X86_)
18 void genCodeForLongUMod(GenTreeOp* node);
19 #endif // _TARGET_X86_
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);
27 #if defined(_TARGET_ARMARCH_)
28 void genScaledAdd(emitAttr attr, regNumber targetReg, regNumber baseReg, regNumber indexReg, int scale);
29 #endif // _TARGET_ARMARCH_
31 #if defined(_TARGET_ARM_)
32 void genCodeForMulLong(GenTreeMultiRegOp* treeNode);
33 #endif // _TARGET_ARM_
35 #if !defined(_TARGET_64BIT_)
36 void genLongToIntCast(GenTreePtr treeNode);
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);
49 void genPutArgSplit(GenTreePutArgSplit* treeNode);
52 #if defined(_TARGET_XARCH_)
53 unsigned getBaseVarForPutArgStk(GenTreePtr treeNode);
54 #endif // _TARGET_XARCH_
56 unsigned getFirstArgWithStackSlot();
58 void genCompareFloat(GenTreePtr treeNode);
59 void genCompareInt(GenTreePtr treeNode);
62 enum SIMDScalarMoveType
64 SMT_ZeroInitUpper, // zero initlaize target upper bits
65 SMT_ZeroInitUpper_SrcHasUpperZeros, // zero initialize target upper bits; source upper bits are known to be zero
66 SMT_PreserveUpper // preserve target upper bits
69 instruction getOpForSIMDIntrinsic(SIMDIntrinsicID intrinsicId, var_types baseType, unsigned* ival = nullptr);
70 void genSIMDScalarMove(
71 var_types targetType, var_types type, regNumber target, regNumber src, SIMDScalarMoveType moveType);
72 void genSIMDZero(var_types targetType, var_types baseType, regNumber targetReg);
73 void genSIMDIntrinsicInit(GenTreeSIMD* simdNode);
74 void genSIMDIntrinsicInitN(GenTreeSIMD* simdNode);
75 void genSIMDIntrinsicInitArray(GenTreeSIMD* simdNode);
76 void genSIMDIntrinsicUnOp(GenTreeSIMD* simdNode);
77 void genSIMDIntrinsicBinOp(GenTreeSIMD* simdNode);
78 void genSIMDIntrinsicRelOp(GenTreeSIMD* simdNode);
79 void genSIMDIntrinsicDotProduct(GenTreeSIMD* simdNode);
80 void genSIMDIntrinsicSetItem(GenTreeSIMD* simdNode);
81 void genSIMDIntrinsicGetItem(GenTreeSIMD* simdNode);
82 void genSIMDIntrinsicShuffleSSE2(GenTreeSIMD* simdNode);
83 void genSIMDIntrinsicUpperSave(GenTreeSIMD* simdNode);
84 void genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode);
85 void genSIMDLo64BitConvert(SIMDIntrinsicID intrinsicID,
91 void genSIMDIntrinsic32BitConvert(GenTreeSIMD* simdNode);
92 void genSIMDIntrinsic64BitConvert(GenTreeSIMD* simdNode);
93 void genSIMDIntrinsicNarrow(GenTreeSIMD* simdNode);
94 void genSIMDExtractUpperHalf(GenTreeSIMD* simdNode, regNumber srcReg, regNumber tgtReg);
95 void genSIMDIntrinsicWiden(GenTreeSIMD* simdNode);
96 void genSIMDIntrinsic(GenTreeSIMD* simdNode);
97 void genSIMDCheck(GenTree* treeNode);
99 // TYP_SIMD12 (i.e Vector3 of size 12 bytes) is not a hardware supported size and requires
100 // two reads/writes on 64-bit targets. These routines abstract reading/writing of Vector3
101 // values through an indirection. Note that Vector3 locals allocated on stack would have
102 // their size rounded to TARGET_POINTER_SIZE (which is 8 bytes on 64-bit targets) and hence
103 // Vector3 locals could be treated as TYP_SIMD16 while reading/writing.
104 void genStoreIndTypeSIMD12(GenTree* treeNode);
105 void genLoadIndTypeSIMD12(GenTree* treeNode);
106 void genStoreLclTypeSIMD12(GenTree* treeNode);
107 void genLoadLclTypeSIMD12(GenTree* treeNode);
109 void genStoreSIMD12ToStack(regNumber operandReg, regNumber tmpReg);
110 void genPutArgStkSIMD12(GenTree* treeNode);
111 #endif // _TARGET_X86_
112 #endif // FEATURE_SIMD
114 #if FEATURE_HW_INTRINSICS
115 void genHWIntrinsic(GenTreeHWIntrinsic* node);
116 void genSSEIntrinsic(GenTreeHWIntrinsic* node);
117 void genSSE2Intrinsic(GenTreeHWIntrinsic* node);
118 void genSSE3Intrinsic(GenTreeHWIntrinsic* node);
119 void genSSSE3Intrinsic(GenTreeHWIntrinsic* node);
120 void genSSE41Intrinsic(GenTreeHWIntrinsic* node);
121 void genSSE42Intrinsic(GenTreeHWIntrinsic* node);
122 void genAVXIntrinsic(GenTreeHWIntrinsic* node);
123 void genAVX2Intrinsic(GenTreeHWIntrinsic* node);
124 void genAESIntrinsic(GenTreeHWIntrinsic* node);
125 void genBMI1Intrinsic(GenTreeHWIntrinsic* node);
126 void genBMI2Intrinsic(GenTreeHWIntrinsic* node);
127 void genFMAIntrinsic(GenTreeHWIntrinsic* node);
128 void genLZCNTIntrinsic(GenTreeHWIntrinsic* node);
129 void genPCLMULQDQIntrinsic(GenTreeHWIntrinsic* node);
130 void genPOPCNTIntrinsic(GenTreeHWIntrinsic* node);
131 #endif // FEATURE_HW_INTRINSICS
133 #if !defined(_TARGET_64BIT_)
135 // CodeGen for Long Ints
137 void genStoreLongLclVar(GenTree* treeNode);
139 #endif // !defined(_TARGET_64BIT_)
141 void genProduceReg(GenTree* tree);
142 void genUnspillRegIfNeeded(GenTree* tree);
143 regNumber genConsumeReg(GenTree* tree);
144 void genCopyRegIfNeeded(GenTree* tree, regNumber needReg);
145 void genConsumeRegAndCopy(GenTree* tree, regNumber needReg);
147 void genConsumeIfReg(GenTreePtr tree)
149 if (!tree->isContained())
151 (void)genConsumeReg(tree);
155 void genRegCopy(GenTreePtr tree);
156 void genTransferRegGCState(regNumber dst, regNumber src);
157 void genConsumeAddress(GenTree* addr);
158 void genConsumeAddrMode(GenTreeAddrMode* mode);
159 void genSetBlockSize(GenTreeBlk* blkNode, regNumber sizeReg);
160 void genConsumeBlockSrc(GenTreeBlk* blkNode);
161 void genSetBlockSrc(GenTreeBlk* blkNode, regNumber srcReg);
162 void genConsumeBlockOp(GenTreeBlk* blkNode, regNumber dstReg, regNumber srcReg, regNumber sizeReg);
164 #ifdef FEATURE_PUT_STRUCT_ARG_STK
165 void genConsumePutStructArgStk(GenTreePutArgStk* putArgStkNode, regNumber dstReg, regNumber srcReg, regNumber sizeReg);
166 #endif // FEATURE_PUT_STRUCT_ARG_STK
168 void genConsumeArgSplitStruct(GenTreePutArgSplit* putArgNode);
171 void genConsumeRegs(GenTree* tree);
172 void genConsumeOperands(GenTreeOp* tree);
173 void genEmitGSCookieCheck(bool pushReg);
174 void genSetRegToIcon(regNumber reg, ssize_t val, var_types type = TYP_INT, insFlags flags = INS_FLAGS_DONT_CARE);
175 void genCodeForShift(GenTreePtr tree);
177 #if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
178 void genCodeForShiftLong(GenTreePtr tree);
181 #ifdef _TARGET_XARCH_
182 void genCodeForShiftRMW(GenTreeStoreInd* storeInd);
183 void genCodeForBT(GenTreeOp* bt);
184 #endif // _TARGET_XARCH_
186 void genCodeForCast(GenTreeOp* tree);
187 void genCodeForLclAddr(GenTree* tree);
188 void genCodeForIndexAddr(GenTreeIndexAddr* tree);
189 void genCodeForIndir(GenTreeIndir* tree);
190 void genCodeForNegNot(GenTree* tree);
191 void genCodeForLclVar(GenTreeLclVar* tree);
192 void genCodeForLclFld(GenTreeLclFld* tree);
193 void genCodeForStoreLclFld(GenTreeLclFld* tree);
194 void genCodeForStoreLclVar(GenTreeLclVar* tree);
195 void genCodeForReturnTrap(GenTreeOp* tree);
196 void genCodeForJcc(GenTreeCC* tree);
197 void genCodeForSetcc(GenTreeCC* setcc);
198 void genCodeForStoreInd(GenTreeStoreInd* tree);
199 void genCodeForSwap(GenTreeOp* tree);
200 void genCodeForCpObj(GenTreeObj* cpObjNode);
201 void genCodeForCpBlk(GenTreeBlk* cpBlkNode);
202 void genCodeForCpBlkRepMovs(GenTreeBlk* cpBlkNode);
203 void genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode);
204 void genCodeForPhysReg(GenTreePhysReg* tree);
205 void genCodeForNullCheck(GenTreeOp* tree);
206 void genCodeForCmpXchg(GenTreeCmpXchg* tree);
208 void genAlignStackBeforeCall(GenTreePutArgStk* putArgStk);
209 void genAlignStackBeforeCall(GenTreeCall* call);
210 void genRemoveAlignmentAfterCall(GenTreeCall* call, unsigned bias = 0);
212 #if defined(UNIX_X86_ABI)
214 unsigned curNestedAlignment; // Keep track of alignment adjustment required during codegen.
215 unsigned maxNestedAlignment; // The maximum amount of alignment adjustment required.
217 void SubtractNestedAlignment(unsigned adjustment)
219 assert(curNestedAlignment >= adjustment);
220 unsigned newNestedAlignment = curNestedAlignment - adjustment;
221 if (curNestedAlignment != newNestedAlignment)
223 JITDUMP("Adjusting stack nested alignment from %d to %d\n", curNestedAlignment, newNestedAlignment);
225 curNestedAlignment = newNestedAlignment;
228 void AddNestedAlignment(unsigned adjustment)
230 unsigned newNestedAlignment = curNestedAlignment + adjustment;
231 if (curNestedAlignment != newNestedAlignment)
233 JITDUMP("Adjusting stack nested alignment from %d to %d\n", curNestedAlignment, newNestedAlignment);
235 curNestedAlignment = newNestedAlignment;
237 if (curNestedAlignment > maxNestedAlignment)
239 JITDUMP("Max stack nested alignment changed from %d to %d\n", maxNestedAlignment, curNestedAlignment);
240 maxNestedAlignment = curNestedAlignment;
246 #ifdef FEATURE_PUT_STRUCT_ARG_STK
248 bool genAdjustStackForPutArgStk(GenTreePutArgStk* putArgStk);
249 void genPushReg(var_types type, regNumber srcReg);
250 void genPutArgStkFieldList(GenTreePutArgStk* putArgStk);
251 #endif // _TARGET_X86_
253 void genPutStructArgStk(GenTreePutArgStk* treeNode);
255 unsigned genMove8IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
256 unsigned genMove4IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
257 unsigned genMove2IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
258 unsigned genMove1IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
259 void genStructPutArgRepMovs(GenTreePutArgStk* putArgStkNode);
260 void genStructPutArgUnroll(GenTreePutArgStk* putArgStkNode);
261 void genStoreRegToStackArg(var_types type, regNumber reg, int offset);
262 #endif // FEATURE_PUT_STRUCT_ARG_STK
264 void genCodeForLoadOffset(instruction ins, emitAttr size, regNumber dst, GenTree* base, unsigned offset);
265 void genCodeForStoreOffset(instruction ins, emitAttr size, regNumber src, GenTree* base, unsigned offset);
267 #ifdef _TARGET_ARM64_
268 void genCodeForLoadPairOffset(regNumber dst, regNumber dst2, GenTree* base, unsigned offset);
269 void genCodeForStorePairOffset(regNumber src, regNumber src2, GenTree* base, unsigned offset);
270 #endif // _TARGET_ARM64_
272 void genCodeForStoreBlk(GenTreeBlk* storeBlkNode);
273 void genCodeForInitBlk(GenTreeBlk* initBlkNode);
274 void genCodeForInitBlkRepStos(GenTreeBlk* initBlkNode);
275 void genCodeForInitBlkUnroll(GenTreeBlk* initBlkNode);
276 void genJumpTable(GenTree* tree);
277 void genTableBasedSwitch(GenTree* tree);
278 void genCodeForArrIndex(GenTreeArrIndex* treeNode);
279 void genCodeForArrOffset(GenTreeArrOffs* treeNode);
280 instruction genGetInsForOper(genTreeOps oper, var_types type);
281 bool genEmitOptimizedGCWriteBarrier(GCInfo::WriteBarrierForm writeBarrierForm, GenTree* addr, GenTree* data);
282 void genCallInstruction(GenTreeCall* call);
283 void genJmpMethod(GenTreePtr jmp);
284 BasicBlock* genCallFinally(BasicBlock* block);
285 void genCodeForJumpTrue(GenTreePtr tree);
286 #ifdef _TARGET_ARM64_
287 void genCodeForJumpCompare(GenTreeOp* tree);
288 #endif // _TARGET_ARM64_
290 #if FEATURE_EH_FUNCLETS
291 void genEHCatchRet(BasicBlock* block);
292 #else // !FEATURE_EH_FUNCLETS
293 void genEHFinallyOrFilterRet(BasicBlock* block);
294 #endif // !FEATURE_EH_FUNCLETS
296 void genMultiRegCallStoreToLocal(GenTreePtr treeNode);
298 // Deals with codegen for muti-register struct returns.
299 bool isStructReturn(GenTreePtr treeNode);
300 void genStructReturn(GenTreePtr treeNode);
302 void genReturn(GenTreePtr treeNode);
304 void genLclHeap(GenTreePtr tree);
306 bool genIsRegCandidateLocal(GenTreePtr tree)
308 if (!tree->IsLocal())
312 const LclVarDsc* varDsc = &compiler->lvaTable[tree->gtLclVarCommon.gtLclNum];
313 return (varDsc->lvIsRegCandidate());
316 #ifdef FEATURE_PUT_STRUCT_ARG_STK
319 #else // !_TARGET_X86_
320 unsigned m_stkArgVarNum;
321 unsigned m_stkArgOffset;
322 #endif // !_TARGET_X86_
323 #endif // !FEATURE_PUT_STRUCT_ARG_STK
326 GenTree* lastConsumedNode;
327 void genNumberOperandUse(GenTree* const operand, int& useNum) const;
328 void genCheckConsumeNode(GenTree* const node);
330 inline void genCheckConsumeNode(GenTree* treeNode)
335 #endif // !LEGACY_BACKEND