Fix reading Time zone rules using Julian days (#17672)
[platform/upstream/coreclr.git] / src / jit / codegenclassic.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 "classic" JIT backend.  It is included by CodeGen.h in the
8 // definition of the CodeGen class.
9 //
10
11 #ifndef _CODEGENCLASSIC_H_
12 #define _CODEGENCLASSIC_H_
13
14 #ifdef LEGACY_BACKEND // Not necessary (it's this way in the #include location), but helpful to IntelliSense
15
16 public:
17 regNumber genIsEnregisteredIntVariable(GenTree* tree);
18
19 void sched_AM(instruction ins,
20               emitAttr    size,
21               regNumber   ireg,
22               bool        rdst,
23               GenTree*    tree,
24               unsigned    offs,
25               bool        cons  = false,
26               int         cval  = 0,
27               insFlags    flags = INS_FLAGS_DONT_CARE);
28
29 protected:
30 #if FEATURE_STACK_FP_X87
31 VARSET_TP genFPregVars;    // mask corresponding to genFPregCnt
32 unsigned  genFPdeadRegCnt; // The dead unpopped part of genFPregCnt
33 #endif                     // FEATURE_STACK_FP_X87
34
35 //-------------------------------------------------------------------------
36
37 void genSetRegToIcon(regNumber reg, ssize_t val, var_types type = TYP_INT, insFlags flags = INS_FLAGS_DONT_CARE);
38
39 regNumber genGetRegSetToIcon(ssize_t val, regMaskTP regBest = 0, var_types type = TYP_INT);
40 void genDecRegBy(regNumber reg, ssize_t ival, GenTree* tree);
41 void genIncRegBy(regNumber reg, ssize_t ival, GenTree* tree, var_types dstType = TYP_INT, bool ovfl = false);
42
43 void genMulRegBy(regNumber reg, ssize_t ival, GenTree* tree, var_types dstType = TYP_INT, bool ovfl = false);
44
45 //-------------------------------------------------------------------------
46
47 bool genRegTrashable(regNumber reg, GenTree* tree);
48
49 //
50 // Prolog functions and data (there are a few exceptions for more generally used things)
51 //
52
53 regMaskTP genPInvokeMethodProlog(regMaskTP initRegs);
54
55 void genPInvokeMethodEpilog();
56
57 regNumber genPInvokeCallProlog(LclVarDsc*            varDsc,
58                                int                   argSize,
59                                CORINFO_METHOD_HANDLE methodToken,
60                                BasicBlock*           returnLabel);
61
62 void genPInvokeCallEpilog(LclVarDsc* varDsc, regMaskTP retVal);
63
64 regNumber genLclHeap(GenTree* size);
65
66 void genDyingVars(VARSET_VALARG_TP beforeSet, VARSET_VALARG_TP afterSet);
67
68 bool genContainsVarDeath(GenTree* from, GenTree* to, unsigned varNum);
69
70 void genComputeReg(
71     GenTree* tree, regMaskTP needReg, RegSet::ExactReg mustReg, RegSet::KeepReg keepReg, bool freeOnly = false);
72
73 void genCompIntoFreeReg(GenTree* tree, regMaskTP needReg, RegSet::KeepReg keepReg);
74
75 void genReleaseReg(GenTree* tree);
76
77 void genRecoverReg(GenTree* tree, regMaskTP needReg, RegSet::KeepReg keepReg);
78
79 void genMoveRegPairHalf(GenTree* tree, regNumber dst, regNumber src, int off = 0);
80
81 void genMoveRegPair(GenTree* tree, regMaskTP needReg, regPairNo newPair);
82
83 void genComputeRegPair(
84     GenTree* tree, regPairNo needRegPair, regMaskTP avoidReg, RegSet::KeepReg keepReg, bool freeOnly = false);
85
86 void genCompIntoFreeRegPair(GenTree* tree, regMaskTP avoidReg, RegSet::KeepReg keepReg);
87
88 void genComputeAddressable(GenTree*        tree,
89                            regMaskTP       addrReg,
90                            RegSet::KeepReg keptReg,
91                            regMaskTP       needReg,
92                            RegSet::KeepReg keepReg,
93                            bool            freeOnly = false);
94
95 void genReleaseRegPair(GenTree* tree);
96
97 void genRecoverRegPair(GenTree* tree, regPairNo regPair, RegSet::KeepReg keepReg);
98
99 void genEvalIntoFreeRegPair(GenTree* tree, regPairNo regPair, regMaskTP avoidReg);
100
101 void genMakeRegPairAvailable(regPairNo regPair);
102
103 bool genMakeIndAddrMode(GenTree*        addr,
104                         GenTree*        oper,
105                         bool            forLea,
106                         regMaskTP       regMask,
107                         RegSet::KeepReg keepReg,
108                         regMaskTP*      useMaskPtr,
109                         bool            deferOp = false);
110
111 regMaskTP genMakeRvalueAddressable(
112     GenTree* tree, regMaskTP needReg, RegSet::KeepReg keepReg, bool forLoadStore, bool smallOK = false);
113
114 regMaskTP genMakeAddressable(
115     GenTree* tree, regMaskTP needReg, RegSet::KeepReg keepReg, bool smallOK = false, bool deferOK = false);
116
117 regMaskTP genMakeAddrArrElem(GenTree* arrElem, GenTree* tree, regMaskTP needReg, RegSet::KeepReg keepReg);
118
119 regMaskTP genMakeAddressable2(GenTree*        tree,
120                               regMaskTP       needReg,
121                               RegSet::KeepReg keepReg,
122                               bool            forLoadStore,
123                               bool            smallOK      = false,
124                               bool            deferOK      = false,
125                               bool            evalSideEffs = false);
126
127 bool genStillAddressable(GenTree* tree);
128
129 regMaskTP genRestoreAddrMode(GenTree* addr, GenTree* tree, bool lockPhase);
130
131 regMaskTP genRestAddressable(GenTree* tree, regMaskTP addrReg, regMaskTP lockMask);
132
133 regMaskTP genKeepAddressable(GenTree* tree, regMaskTP addrReg, regMaskTP avoidMask = RBM_NONE);
134
135 void genDoneAddressable(GenTree* tree, regMaskTP addrReg, RegSet::KeepReg keptReg);
136
137 GenTree* genMakeAddrOrFPstk(GenTree* tree, regMaskTP* regMaskPtr, bool roundResult);
138
139 void genEmitGSCookieCheck(bool pushReg);
140
141 void genEvalSideEffects(GenTree* tree);
142
143 void genCondJump(GenTree* cond, BasicBlock* destTrue = NULL, BasicBlock* destFalse = NULL, bool bStackFPFixup = true);
144
145 emitJumpKind genCondSetFlags(GenTree* cond);
146
147 void genJCC(genTreeOps cmp, BasicBlock* block, var_types type);
148
149 void genJccLongHi(genTreeOps cmp, BasicBlock* jumpTrue, BasicBlock* jumpFalse, bool unsOper = false);
150
151 void genJccLongLo(genTreeOps cmp, BasicBlock* jumpTrue, BasicBlock* jumpFalse);
152
153 void genCondJumpLng(GenTree* cond, BasicBlock* jumpTrue, BasicBlock* jumpFalse, bool bFPTransition = false);
154
155 bool genUse_fcomip();
156
157 void genTableSwitch(regNumber reg, unsigned jumpCnt, BasicBlock** jumpTab);
158
159 regMaskTP WriteBarrier(GenTree* tgt, GenTree* assignVal, regMaskTP addrReg);
160
161 void genCodeForTreeConst(GenTree* tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE);
162
163 void genCodeForTreeLeaf(GenTree* tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE);
164
165 // If "tree" is a comma node, generates code for the left comma arguments,
166 // in order, returning the first right argument in the list that is not
167 // a comma node.
168 GenTree* genCodeForCommaTree(GenTree* tree);
169
170 void genCodeForTreeLeaf_GT_JMP(GenTree* tree);
171
172 static Compiler::fgWalkPreFn fgIsVarAssignedTo;
173
174 void genCodeForQmark(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
175
176 bool genCodeForQmarkWithCMOV(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
177
178 #ifdef _TARGET_XARCH_
179 void genCodeForMultEAX(GenTree* tree);
180 #endif
181 #ifdef _TARGET_ARM_
182 void genCodeForMult64(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
183 #endif
184
185 void genCodeForTreeSmpBinArithLogOp(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
186
187 void genCodeForTreeSmpBinArithLogAsgOp(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
188
189 void genCodeForUnsignedMod(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
190
191 void genCodeForSignedMod(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
192
193 void genCodeForUnsignedDiv(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
194
195 void genCodeForSignedDiv(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
196
197 void genCodeForGeneralDivide(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
198
199 void genCodeForAsgShift(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
200
201 void genCodeForShift(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
202
203 void genCodeForRelop(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
204
205 void genCodeForCopyObj(GenTree* tree, regMaskTP destReg);
206
207 void genCodeForBlkOp(GenTree* tree, regMaskTP destReg);
208
209 void genCodeForTreeSmpOp(GenTree* tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE);
210
211 regNumber genIntegerCast(GenTree* tree, regMaskTP needReg, regMaskTP bestReg);
212
213 void genCodeForNumericCast(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
214
215 void genCodeForTreeSmpOp_GT_ADDR(GenTree* tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE);
216
217 void genCodeForTreeSmpOpAsg(GenTree* tree);
218
219 void genCodeForTreeSmpOpAsg_DONE_ASSG(GenTree* tree, regMaskTP addrReg, regNumber reg, bool ovfl);
220
221 void genCodeForTreeSpecialOp(GenTree* tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE);
222
223 void genCodeForTree(GenTree* tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE);
224
225 void genCodeForTree_DONE_LIFE(GenTree* tree, regNumber reg)
226 {
227     /* We've computed the value of 'tree' into 'reg' */
228
229     assert(reg != 0xFEEFFAAFu);
230     assert(!IsUninitialized(reg));
231
232     genMarkTreeInReg(tree, reg);
233 }
234
235 void genCodeForTree_DONE_LIFE(GenTree* tree, regPairNo regPair)
236 {
237     /* We've computed the value of 'tree' into 'regPair' */
238
239     genMarkTreeInRegPair(tree, regPair);
240 }
241
242 void genCodeForTree_DONE(GenTree* tree, regNumber reg)
243 {
244     /* Check whether this subtree has freed up any variables */
245
246     genUpdateLife(tree);
247
248     genCodeForTree_DONE_LIFE(tree, reg);
249 }
250
251 void genCodeForTree_REG_VAR1(GenTree* tree)
252 {
253     /* Value is already in a register */
254
255     regNumber reg = tree->gtRegNum;
256
257     gcInfo.gcMarkRegPtrVal(reg, tree->TypeGet());
258
259     genCodeForTree_DONE(tree, reg);
260 }
261
262 void genCodeForTreeLng(GenTree* tree, regMaskTP needReg, regMaskTP avoidReg);
263
264 regPairNo genCodeForLongModInt(GenTree* tree, regMaskTP needReg);
265
266 unsigned genRegCountForLiveIntEnregVars(GenTree* tree);
267
268 #ifdef _TARGET_ARM_
269 void genStoreFromFltRetRegs(GenTree* tree);
270 void genLoadIntoFltRetRegs(GenTree* tree);
271 void genLdStFltRetRegsPromotedVar(LclVarDsc* varDsc, bool isLoadIntoFltReg);
272 #endif
273
274 #if CPU_HAS_FP_SUPPORT
275 void genRoundFpExpression(GenTree* op, var_types type = TYP_UNDEF);
276 void genCodeForTreeFlt(GenTree* tree, regMaskTP needReg = RBM_ALLFLOAT, regMaskTP bestReg = RBM_NONE);
277 #endif
278
279 // FP stuff
280 #include "fp.h"
281
282 void genCodeForJumpTable(GenTree* tree);
283 void genCodeForSwitchTable(GenTree* tree);
284 void genCodeForSwitch(GenTree* tree);
285
286 size_t genPushArgList(GenTreeCall* call);
287
288 #ifdef _TARGET_ARM_
289 // We are generating code for a promoted struct local variable.  Fill the next slot (register or
290 // 4-byte stack slot) with one or more field variables of the promoted struct local -- or 2 such slots
291 // if the next field is a 64-bit value.
292 // The arguments are:
293 //    "arg" is the current argument node.
294 //
295 //    "curArgTabEntry" arg table entry pointer for "arg".
296 //
297 //    "promotedStructLocalVarDesc" describes the struct local being copied, assumed non-NULL.
298 //
299 //    "fieldSize" is somewhat misnamed; it must be the element in the struct's GC layout describing the next slot
300 //       of the struct -- it will be EA_4BYTE, EA_GCREF, or EA_BYREF.
301 //
302 //    "*pNextPromotedStructFieldVar" must be the the local variable number of the next field variable to copy;
303 //       this location will be updated by the call to reflect the bytes that are copied.
304 //
305 //    "*pBytesOfNextSlotOfCurPromotedStruct" must be the number of bytes within the struct local at which the next
306 //       slot to be copied starts.  This location will be updated by the call to reflect the bytes that are copied.
307 //
308 //    "*pCurRegNum" must be the current argument register number, and will be updated if argument registers are filled.
309 //
310 //    "argOffset" must be the offset of the next slot to be filled in the outgoing argument area, if the argument is to
311 //    be
312 //       put in the outgoing arg area of the stack (or else should be INT_MAX if the next slot to be filled is a
313 //       register).
314 //       (Strictly speaking, after the addition of "argOffsetOfFirstStackSlot", this arg is redundant, and is only used
315 //       in assertions, and could be removed.)
316 //
317 //    "fieldOffsetOfFirstStackSlot" must be the offset within the promoted struct local of the first slot that should be
318 //       copied to the outgoing argument area -- non-zero only in the case of a struct that spans registers and stack
319 //       slots.
320 //
321 //    "argOffsetOfFirstStackSlot" must be the 4-byte-aligned offset of the first offset in the outgoing argument area
322 //    which could
323 //       contain part of the struct.  (Explicit alignment may mean it doesn't actually contain part of the struct.)
324 //
325 //    "*deadFieldVarRegs" is an out parameter, the set of registers containing promoted field variables that become dead
326 //    after
327 //       this (implicit) use.
328 //
329 //    "*pRegTmp" -- if a temporary register is needed, and this is not REG_STK, uses that register.  Otherwise, if it is
330 //    REG_STK,
331 //       allocates a register, uses it, and sets "*pRegTmp" to the allocated register.
332 //
333 // Returns "true" iff it filled two slots with an 8-byte value.
334 bool genFillSlotFromPromotedStruct(GenTree*       arg,
335                                    fgArgTabEntry* curArgTabEntry,
336                                    LclVarDsc*     promotedStructLocalVarDesc,
337                                    emitAttr       fieldSize,
338                                    unsigned*      pNextPromotedStructFieldVar,         // IN/OUT
339                                    unsigned*      pBytesOfNextSlotOfCurPromotedStruct, // IN/OUT
340                                    regNumber*     pCurRegNum,                          // IN/OUT
341                                    int            argOffset,
342                                    int            fieldOffsetOfFirstStackSlot,
343                                    int            argOffsetOfFirstStackSlot,
344                                    regMaskTP*     deadFieldVarRegs, // OUT
345                                    regNumber*     pRegTmp);         // IN/OUT
346
347 #endif // _TARGET_ARM_
348 // Requires that "curr" is a cpblk.  If the RHS is a promoted struct local,
349 // then returns a regMaskTP representing the set of registers holding
350 // fieldVars of the RHS that go dead with this use (as determined by the live set
351 // of cpBlk).
352 regMaskTP genFindDeadFieldRegs(GenTree* cpBlk);
353
354 void SetupLateArgs(GenTreeCall* call);
355
356 #ifdef _TARGET_ARM_
357 void PushMkRefAnyArg(GenTree* mkRefAnyTree, fgArgTabEntry* curArgTabEntry, regMaskTP regNeedMask);
358 #endif // _TARGET_ARM_
359
360 regMaskTP genLoadIndirectCallTarget(GenTreeCall* call);
361
362 regMaskTP genCodeForCall(GenTreeCall* call, bool valUsed);
363
364 GenTree* genGetAddrModeBase(GenTree* tree);
365
366 GenTree* genIsAddrMode(GenTree* tree, GenTree** indxPtr);
367
368 private:
369 bool genIsLocalLastUse(GenTree* tree);
370
371 bool genIsRegCandidateLocal(GenTree* tree);
372
373 //=========================================================================
374 //  Debugging support
375 //=========================================================================
376
377 #if FEATURE_STACK_FP_X87
378 /*
379 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
380 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
381 XX                                                                           XX
382 XX                   Flat FP model                                           XX
383 XX                                                                           XX
384 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
385 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
386 */
387
388 bool StackFPIsSameAsFloat(double d);
389 bool FlatFPSameRegisters(FlatFPStateX87* pState, regMaskTP mask);
390
391 // FlatFPStateX87_ functions are the actual verbs to do stuff
392 // like doing a transition, loading   register, etc. It's also
393 // responsible for emitting the x87 code to do so. We keep
394 // them in Compiler because we don't want to store a pointer to the
395 // emitter.
396 void FlatFPX87_Kill(FlatFPStateX87* pState, unsigned iVirtual);
397 void FlatFPX87_PushVirtual(FlatFPStateX87* pState, unsigned iRegister, bool bEmitCode = true);
398 unsigned FlatFPX87_Pop(FlatFPStateX87* pState, bool bEmitCode = true);
399 unsigned FlatFPX87_Top(FlatFPStateX87* pState, bool bEmitCode = true);
400 void FlatFPX87_Unload(FlatFPStateX87* pState, unsigned iVirtual, bool bEmitCode = true);
401 #endif
402
403 // Codegen functions. This is the API that codegen will use
404 regMaskTP genPushArgumentStackFP(GenTree* arg);
405 void genRoundFpExpressionStackFP(GenTree* op, var_types type = TYP_UNDEF);
406 void genCodeForTreeStackFP_Const(GenTree* tree);
407 void genCodeForTreeStackFP_Leaf(GenTree* tree);
408 void genCodeForTreeStackFP_SmpOp(GenTree* tree);
409 void genCodeForTreeStackFP_Special(GenTree* tree);
410 void genCodeForTreeStackFP_Cast(GenTree* tree);
411 void genCodeForTreeStackFP(GenTree* tree);
412 void genCondJumpFltStackFP(GenTree* cond, BasicBlock* jumpTrue, BasicBlock* jumpFalse, bool bDoTransition = true);
413 void genCondJumpFloat(GenTree* cond, BasicBlock* jumpTrue, BasicBlock* jumpFalse);
414 void genCondJumpLngStackFP(GenTree* cond, BasicBlock* jumpTrue, BasicBlock* jumpFalse);
415
416 void genFloatConst(GenTree* tree, RegSet::RegisterPreference* pref);
417 void genFloatLeaf(GenTree* tree, RegSet::RegisterPreference* pref);
418 void genFloatSimple(GenTree* tree, RegSet::RegisterPreference* pref);
419 void genFloatMath(GenTree* tree, RegSet::RegisterPreference* pref);
420 void genFloatCheckFinite(GenTree* tree, RegSet::RegisterPreference* pref);
421 void genLoadFloat(GenTree* tree, regNumber reg);
422 void genFloatAssign(GenTree* tree);
423 void genFloatArith(GenTree* tree, RegSet::RegisterPreference* pref);
424 void genFloatAsgArith(GenTree* tree);
425
426 regNumber genAssignArithFloat(genTreeOps oper, GenTree* dst, regNumber dstreg, GenTree* src, regNumber srcreg);
427
428 GenTree* genMakeAddressableFloat(GenTree*   tree,
429                                  regMaskTP* regMaskIntPtr,
430                                  regMaskTP* regMaskFltPtr,
431                                  bool       bCollapseConstantDoubles = true);
432
433 void genCodeForTreeFloat(GenTree* tree, RegSet::RegisterPreference* pref = NULL);
434
435 void genCodeForTreeFloat(GenTree* tree, regMaskTP needReg, regMaskTP bestReg);
436
437 regNumber genArithmFloat(
438     genTreeOps oper, GenTree* dst, regNumber dstreg, GenTree* src, regNumber srcreg, bool bReverse);
439 void genCodeForTreeCastFloat(GenTree* tree, RegSet::RegisterPreference* pref);
440 void genCodeForTreeCastToFloat(GenTree* tree, RegSet::RegisterPreference* pref);
441 void genCodeForTreeCastFromFloat(GenTree* tree, RegSet::RegisterPreference* pref);
442 void genKeepAddressableFloat(GenTree* tree, regMaskTP* regMaskIntPtr, regMaskTP* regMaskFltPtr);
443 void genDoneAddressableFloat(GenTree* tree, regMaskTP addrRegInt, regMaskTP addrRegFlt, RegSet::KeepReg keptReg);
444 void genComputeAddressableFloat(GenTree*        tree,
445                                 regMaskTP       addrRegInt,
446                                 regMaskTP       addrRegFlt,
447                                 RegSet::KeepReg keptReg,
448                                 regMaskTP       needReg,
449                                 RegSet::KeepReg keepReg,
450                                 bool            freeOnly = false);
451 void genRoundFloatExpression(GenTree* op, var_types type);
452
453 #if FEATURE_STACK_FP_X87
454 // Assumes then block will be generated before else block.
455 struct QmarkStateStackFP
456 {
457     FlatFPStateX87 stackState;
458 };
459
460 void genQMarkRegVarTransition(GenTree* nextNode, VARSET_VALARG_TP liveset);
461 void genQMarkBeforeElseStackFP(QmarkStateStackFP* pState, VARSET_VALARG_TP varsetCond, GenTree* nextNode);
462 void genQMarkAfterElseBlockStackFP(QmarkStateStackFP* pState, VARSET_VALARG_TP varsetCond, GenTree* nextNode);
463 void genQMarkAfterThenBlockStackFP(QmarkStateStackFP* pState);
464
465 #endif
466
467 GenTree* genMakeAddressableStackFP(GenTree*   tree,
468                                    regMaskTP* regMaskIntPtr,
469                                    regMaskTP* regMaskFltPtr,
470                                    bool       bCollapseConstantDoubles = true);
471 void genKeepAddressableStackFP(GenTree* tree, regMaskTP* regMaskIntPtr, regMaskTP* regMaskFltPtr);
472 void genDoneAddressableStackFP(GenTree* tree, regMaskTP addrRegInt, regMaskTP addrRegFlt, RegSet::KeepReg keptReg);
473
474 void genCodeForTreeStackFP_Asg(GenTree* tree);
475 void genCodeForTreeStackFP_AsgArithm(GenTree* tree);
476 void genCodeForTreeStackFP_Arithm(GenTree* tree);
477 void genCodeForTreeStackFP_DONE(GenTree* tree, regNumber reg);
478 void genCodeForTreeFloat_DONE(GenTree* tree, regNumber reg);
479
480 void genSetupStateStackFP(BasicBlock* block);
481 regMaskTP genRegMaskFromLivenessStackFP(VARSET_VALARG_TP varset);
482
483 // bReverse means make op1 addressable and codegen for op2.
484 // If op1 or op2 are comma expressions, will do code-gen for their non-last comma parts,
485 // and set op1 and op2 to the remaining non-comma expressions.
486 void genSetupForOpStackFP(
487     GenTree*& op1, GenTree*& op2, bool bReverse, bool bMakeOp1Addressable, bool bOp1ReadOnly, bool bOp2ReadOnly);
488
489 #if FEATURE_STACK_FP_X87
490
491 #ifdef DEBUG
492 bool ConsistentAfterStatementStackFP();
493 #endif
494
495 private:
496 void SpillTempsStackFP(regMaskTP canSpillMask);
497 void SpillForCallStackFP();
498 void UnspillRegVarsStackFp();
499
500 // Transition API. Takes care of the stack matching of basicblock boundaries
501 void genCodeForPrologStackFP();
502 void genCodeForEndBlockTransitionStackFP(BasicBlock* block);
503
504 void genCodeForBBTransitionStackFP(BasicBlock* pDst);
505 void genCodeForTransitionStackFP(FlatFPStateX87* pSrc, FlatFPStateX87* pDst);
506 void genCodeForTransitionFromMask(FlatFPStateX87* pSrc, regMaskTP mask, bool bEmitCode = true);
507 BasicBlock* genTransitionBlockStackFP(FlatFPStateX87* pState, BasicBlock* pFrom, BasicBlock* pTarget);
508
509 // This is the API codegen will use to emit virtual fp code. In theory, nobody above this API
510 // should know about x87 instructions.
511
512 int  genNumberTemps();
513 void genDiscardStackFP(GenTree* tree);
514 void genRegRenameWithMasks(regNumber dstReg, regNumber srcReg);
515 void genRegVarBirthStackFP(GenTree* tree);
516 void genRegVarBirthStackFP(LclVarDsc* varDsc);
517 void genRegVarDeathStackFP(GenTree* tree);
518 void genRegVarDeathStackFP(LclVarDsc* varDsc);
519 void genLoadStackFP(GenTree* tree, regNumber reg);
520 void genMovStackFP(GenTree* dst, regNumber dstreg, GenTree* src, regNumber srcreg);
521 bool genCompInsStackFP(GenTree* tos, GenTree* other);
522 regNumber genArithmStackFP(
523     genTreeOps oper, GenTree* dst, regNumber dstreg, GenTree* src, regNumber srcreg, bool bReverse);
524 regNumber genAsgArithmStackFP(genTreeOps oper, GenTree* dst, regNumber dstreg, GenTree* src, regNumber srcreg);
525 void genCondJmpInsStackFP(emitJumpKind jumpKind,
526                           BasicBlock*  jumpTrue,
527                           BasicBlock*  jumpFalse,
528                           bool         bDoTransition = true);
529 void genTableSwitchStackFP(regNumber reg, unsigned jumpCnt, BasicBlock** jumpTab);
530
531 void JitDumpFPState();
532 #else  // !FEATURE_STACK_FP_X87
533 void SpillForCallRegisterFP(regMaskTP noSpillMask);
534 #endif // !FEATURE_STACK_FP_X87
535
536 // When bOnlyNoMemAccess = true, the load will be generated only for constant loading that doesn't
537 // involve memory accesses, (ie: fldz for positive zero, or fld1 for 1). Will return true the function
538 // did the load
539 bool genConstantLoadStackFP(GenTree* tree, bool bOnlyNoMemAccess = false);
540 void genEndOfStatement();
541
542 #if FEATURE_STACK_FP_X87
543 struct genRegVarDiesInSubTreeData
544 {
545     regNumber reg;
546     bool      result;
547 };
548 static Compiler::fgWalkPreFn genRegVarDiesInSubTreeWorker;
549 bool genRegVarDiesInSubTree(GenTree* tree, regNumber reg);
550 #endif // FEATURE_STACK_FP_X87
551
552 // Float spill
553 void UnspillFloat(RegSet::SpillDsc* spillDsc);
554 void UnspillFloat(GenTree* tree);
555 void UnspillFloat(LclVarDsc* varDsc);
556 void UnspillFloatMachineDep(RegSet::SpillDsc* spillDsc);
557 void UnspillFloatMachineDep(RegSet::SpillDsc* spillDsc, bool useSameReg);
558 void RemoveSpillDsc(RegSet::SpillDsc* spillDsc);
559
560 protected:
561 struct genLivenessSet
562 {
563     VARSET_TP    liveSet;
564     VARSET_TP    varPtrSet;
565     regMaskSmall maskVars;
566     regMaskSmall gcRefRegs;
567     regMaskSmall byRefRegs;
568
569     genLivenessSet() : liveSet(VarSetOps::UninitVal()), varPtrSet(VarSetOps::UninitVal())
570     {
571     }
572 };
573
574 void saveLiveness(genLivenessSet* ls);
575 void restoreLiveness(genLivenessSet* ls);
576 void checkLiveness(genLivenessSet* ls);
577 void unspillLiveness(genLivenessSet* ls);
578
579 //-------------------------------------------------------------------------
580 //
581 //  If we know that the flags register is set to a value that corresponds
582 //  to the current value of a register or variable, the following values
583 //  record that information.
584 //
585
586 emitLocation genFlagsEqLoc;
587 regNumber    genFlagsEqReg;
588 unsigned     genFlagsEqVar;
589
590 void genFlagsEqualToNone();
591 void genFlagsEqualToReg(GenTree* tree, regNumber reg);
592 void genFlagsEqualToVar(GenTree* tree, unsigned var);
593 bool genFlagsAreReg(regNumber reg);
594 bool genFlagsAreVar(unsigned var);
595
596 #endif // LEGACY_BACKEND
597
598 #endif // _CODEGENCLASSIC_H_