// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // // // This file contains the members of CodeGen that are defined and used // only by the "classic" JIT backend. It is included by CodeGen.h in the // definition of the CodeGen class. // #ifndef _CODEGENCLASSIC_H_ #define _CODEGENCLASSIC_H_ #ifdef LEGACY_BACKEND // Not necessary (it's this way in the #include location), but helpful to IntelliSense #if FEATURE_STACK_FP_X87 VARSET_TP genFPregVars; // mask corresponding to genFPregCnt unsigned genFPdeadRegCnt; // The dead unpopped part of genFPregCnt #endif // FEATURE_STACK_FP_X87 //------------------------------------------------------------------------- void genSetRegToIcon (regNumber reg, ssize_t val, var_types type = TYP_INT, insFlags flags = INS_FLAGS_DONT_CARE); regNumber genGetRegSetToIcon (ssize_t val, regMaskTP regBest = 0, var_types type = TYP_INT); void genDecRegBy (regNumber reg, ssize_t ival, GenTreePtr tree); void genMulRegBy (regNumber reg, ssize_t ival, GenTreePtr tree, var_types dstType = TYP_INT, bool ovfl = false); //------------------------------------------------------------------------- bool genRegTrashable (regNumber reg, GenTreePtr tree); // // Prolog functions and data (there are a few exceptions for more generally used things) // regNumber genLclHeap (GenTreePtr size); void genSinglePush (); void genSinglePop (); void genDyingVars (VARSET_VALARG_TP beforeSet, VARSET_VALARG_TP afterSet); bool genContainsVarDeath (GenTreePtr from, GenTreePtr to, unsigned varNum); void genComputeReg (GenTreePtr tree, regMaskTP needReg, RegSet::ExactReg mustReg, RegSet::KeepReg keepReg, bool freeOnly = false); void genCompIntoFreeReg (GenTreePtr tree, regMaskTP needReg, RegSet::KeepReg keepReg); void genReleaseReg (GenTreePtr tree); void genRecoverReg (GenTreePtr tree, regMaskTP needReg, RegSet::KeepReg keepReg); void genMoveRegPairHalf (GenTreePtr tree, regNumber dst, regNumber src, int off = 0); void genMoveRegPair (GenTreePtr tree, regMaskTP needReg, regPairNo newPair); void genComputeRegPair (GenTreePtr tree, regPairNo needRegPair, regMaskTP avoidReg, RegSet::KeepReg keepReg, bool freeOnly = false); void genCompIntoFreeRegPair(GenTreePtr tree, regMaskTP avoidReg, RegSet::KeepReg keepReg); void genComputeAddressable(GenTreePtr tree, regMaskTP addrReg, RegSet::KeepReg keptReg, regMaskTP needReg, RegSet::KeepReg keepReg, bool freeOnly = false); void genReleaseRegPair (GenTreePtr tree); void genRecoverRegPair (GenTreePtr tree, regPairNo regPair, RegSet::KeepReg keepReg); void genEvalIntoFreeRegPair(GenTreePtr tree, regPairNo regPair, regMaskTP avoidReg); void genMakeRegPairAvailable(regPairNo regPair); bool genMakeIndAddrMode (GenTreePtr addr, GenTreePtr oper, bool forLea, regMaskTP regMask, RegSet::KeepReg keepReg, regMaskTP * useMaskPtr, bool deferOp = false); regMaskTP genMakeRvalueAddressable(GenTreePtr tree, regMaskTP needReg, RegSet::KeepReg keepReg, bool forLoadStore, bool smallOK = false); regMaskTP genMakeAddressable (GenTreePtr tree, regMaskTP needReg, RegSet::KeepReg keepReg, bool smallOK = false, bool deferOK = false); regMaskTP genMakeAddrArrElem (GenTreePtr arrElem, GenTreePtr tree, regMaskTP needReg, RegSet::KeepReg keepReg); regMaskTP genMakeAddressable2 (GenTreePtr tree, regMaskTP needReg, RegSet::KeepReg keepReg, bool forLoadStore, bool smallOK = false, bool deferOK = false, bool evalSideEffs = false); bool genStillAddressable (GenTreePtr tree); regMaskTP genRestoreAddrMode (GenTreePtr addr, GenTreePtr tree, bool lockPhase); regMaskTP genRestAddressable (GenTreePtr tree, regMaskTP addrReg, regMaskTP lockMask); regMaskTP genKeepAddressable (GenTreePtr tree, regMaskTP addrReg, regMaskTP avoidMask = RBM_NONE); void genDoneAddressable (GenTreePtr tree, regMaskTP addrReg, RegSet::KeepReg keptReg); GenTreePtr genMakeAddrOrFPstk (GenTreePtr tree, regMaskTP * regMaskPtr, bool roundResult); void genEmitGSCookieCheck(bool pushReg); void genEvalSideEffects (GenTreePtr tree); void genCondJump (GenTreePtr cond, BasicBlock * destTrue = NULL, BasicBlock * destFalse = NULL, bool bStackFPFixup = true); emitJumpKind genCondSetFlags (GenTreePtr cond); void genJCC (genTreeOps cmp, BasicBlock * block, var_types type); void genJccLongHi (genTreeOps cmp, BasicBlock * jumpTrue, BasicBlock * jumpFalse, bool unsOper = false); void genJccLongLo (genTreeOps cmp, BasicBlock * jumpTrue, BasicBlock * jumpFalse); void genCondJumpLng (GenTreePtr cond, BasicBlock * jumpTrue, BasicBlock * jumpFalse, bool bFPTransition = false); bool genUse_fcomip(); void genTableSwitch (regNumber reg, unsigned jumpCnt, BasicBlock ** jumpTab); regMaskTP WriteBarrier (GenTreePtr tgt, GenTreePtr assignVal, regMaskTP addrReg); void genCodeForTreeConst (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE); void genCodeForTreeLeaf (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE); // If "tree" is a comma node, generates code for the left comma arguments, // in order, returning the first right argument in the list that is not // a comma node. GenTreePtr genCodeForCommaTree (GenTreePtr tree); void genCodeForTreeLeaf_GT_JMP (GenTreePtr tree); static Compiler::fgWalkPreFn fgIsVarAssignedTo; void genCodeForQmark (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); bool genCodeForQmarkWithCMOV (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); #ifdef _TARGET_XARCH_ void genCodeForMultEAX (GenTreePtr tree); #endif #ifdef _TARGET_ARM_ void genCodeForMult64 (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); #endif void genCodeForTreeSmpBinArithLogOp (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); void genCodeForTreeSmpBinArithLogAsgOp (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); void genCodeForUnsignedMod (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); void genCodeForSignedMod (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); void genCodeForUnsignedDiv (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); void genCodeForSignedDiv (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); void genCodeForGeneralDivide (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); void genCodeForAsgShift (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); void genCodeForShift (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); void genCodeForRelop (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); void genCodeForTreeSmpOp (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE); regNumber genIntegerCast(GenTree *tree, regMaskTP needReg, regMaskTP bestReg); void genCodeForNumericCast(GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg); void genCodeForTreeSmpOp_GT_ADDR (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE); void genCodeForTreeSmpOpAsg (GenTreePtr tree); void genCodeForTreeSmpOpAsg_DONE_ASSG(GenTreePtr tree, regMaskTP addrReg, regNumber reg, bool ovfl); void genCodeForTreeSpecialOp (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE); void genCodeForTree (GenTreePtr tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE); void genCodeForTree_DONE_LIFE (GenTreePtr tree, regNumber reg) { /* We've computed the value of 'tree' into 'reg' */ assert(reg != 0xFEEFFAAFu); assert(!IsUninitialized(reg)); genMarkTreeInReg(tree, reg); } void genCodeForTree_DONE_LIFE (GenTreePtr tree, regPairNo regPair) { /* We've computed the value of 'tree' into 'regPair' */ genMarkTreeInRegPair(tree, regPair); } void genCodeForTree_DONE (GenTreePtr tree, regNumber reg) { /* Check whether this subtree has freed up any variables */ genUpdateLife(tree); genCodeForTree_DONE_LIFE(tree, reg); } void genCodeForTree_REG_VAR1 (GenTreePtr tree) { /* Value is already in a register */ regNumber reg = tree->gtRegNum; gcInfo.gcMarkRegPtrVal(reg, tree->TypeGet()); genCodeForTree_DONE(tree, reg); } void genCodeForTreeLng (GenTreePtr tree, regMaskTP needReg, regMaskTP avoidReg); regPairNo genCodeForLongModInt(GenTreePtr tree, regMaskTP needReg); unsigned genRegCountForLiveIntEnregVars(GenTreePtr tree); #ifdef _TARGET_ARM_ void genStoreFromFltRetRegs (GenTreePtr tree); void genLoadIntoFltRetRegs (GenTreePtr tree); void genLdStFltRetRegsPromotedVar (LclVarDsc* varDsc, bool isLoadIntoFltReg); #endif #if CPU_HAS_FP_SUPPORT void genRoundFpExpression(GenTreePtr op, var_types type = TYP_UNDEF); void genCodeForTreeFlt (GenTreePtr tree, regMaskTP needReg = RBM_ALLFLOAT, regMaskTP bestReg = RBM_NONE); #endif // FP stuff #include "fp.h" void genCodeForJumpTable (GenTreePtr tree); void genCodeForSwitchTable (GenTreePtr tree); void genCodeForSwitch (GenTreePtr tree); regMaskTP genPushRegs (regMaskTP regs, regMaskTP * byrefRegs, regMaskTP * noRefRegs); void genPopRegs (regMaskTP regs, regMaskTP byrefRegs, regMaskTP noRefRegs); size_t genPushArgList (GenTreePtr call); #ifdef _TARGET_ARM_ // We are generating code for a promoted struct local variable. Fill the next slot (register or // 4-byte stack slot) with one or more field variables of the promoted struct local -- or 2 such slots // if the next field is a 64-bit value. // The arguments are: // "arg" is the current argument node. // // "curArgTabEntry" arg table entry pointer for "arg". // // "promotedStructLocalVarDesc" describes the struct local being copied, assumed non-NULL. // // "fieldSize" is somewhat misnamed; it must be the element in the struct's GC layout describing the next slot // of the struct -- it will be EA_4BYTE, EA_GCREF, or EA_BYREF. // // "*pNextPromotedStructFieldVar" must be the the local variable number of the next field variable to copy; // this location will be updated by the call to reflect the bytes that are copied. // // "*pBytesOfNextSlotOfCurPromotedStruct" must be the number of bytes within the struct local at which the next // slot to be copied starts. This location will be updated by the call to reflect the bytes that are copied. // // "*pCurRegNum" must be the current argument register number, and will be updated if argument registers are filled. // // "argOffset" must be the offset of the next slot to be filled in the outgoing argument area, if the argument is to be // put in the outgoing arg area of the stack (or else should be INT_MAX if the next slot to be filled is a register). // (Strictly speaking, after the addition of "argOffsetOfFirstStackSlot", this arg is redundant, and is only used // in assertions, and could be removed.) // // "fieldOffsetOfFirstStackSlot" must be the offset within the promoted struct local of the first slot that should be // copied to the outgoing argument area -- non-zero only in the case of a struct that spans registers and stack slots. // // "argOffsetOfFirstStackSlot" must be the 4-byte-aligned offset of the first offset in the outgoing argument area which could // contain part of the struct. (Explicit alignment may mean it doesn't actually contain part of the struct.) // // "*deadFieldVarRegs" is an out parameter, the set of registers containing promoted field variables that become dead after // this (implicit) use. // // "*pRegTmp" -- if a temporary register is needed, and this is not REG_STK, uses that register. Otherwise, if it is REG_STK, // allocates a register, uses it, and sets "*pRegTmp" to the allocated register. // // Returns "true" iff it filled two slots with an 8-byte value. bool genFillSlotFromPromotedStruct(GenTreePtr arg, fgArgTabEntryPtr curArgTabEntry, LclVarDsc* promotedStructLocalVarDesc, emitAttr fieldSize, unsigned* pNextPromotedStructFieldVar, // IN/OUT unsigned *pBytesOfNextSlotOfCurPromotedStruct, // IN/OUT regNumber* pCurRegNum, // IN/OUT int argOffset, int fieldOffsetOfFirstStackSlot, int argOffsetOfFirstStackSlot, regMaskTP* deadFieldVarRegs, // OUT regNumber* pRegTmp); // IN/OUT #endif // _TARGET_ARM_ // Requires that "curr" is a cpblk. If the RHS is a promoted struct local, // then returns a regMaskTP representing the set of registers holding // fieldVars of the RHS that go dead with this use (as determined by the live set // of cpBlk). regMaskTP genFindDeadFieldRegs(GenTreePtr cpBlk); void SetupLateArgs (GenTreePtr call); #ifdef _TARGET_ARM_ void PushMkRefAnyArg (GenTreePtr mkRefAnyTree, fgArgTabEntryPtr curArgTabEntry, regMaskTP regNeedMask); #endif // _TARGET_ARM_ regMaskTP genLoadIndirectCallTarget(GenTreePtr call); regMaskTP genCodeForCall (GenTreePtr call, bool valUsed); GenTreePtr genGetAddrModeBase (GenTreePtr tree); GenTreePtr genIsAddrMode (GenTreePtr tree, GenTreePtr * indxPtr); private: bool genIsLocalLastUse (GenTreePtr tree); bool genIsRegCandidateLocal(GenTreePtr tree); //========================================================================= // Debugging support //========================================================================= #if FEATURE_STACK_FP_X87 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XX XX Flat FP model XX XX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ bool StackFPIsSameAsFloat (double d); bool FlatFPSameRegisters (FlatFPStateX87* pState, regMaskTP mask); // FlatFPStateX87_ functions are the actual verbs to do stuff // like doing a transition, loading register, etc. It's also // responsible for emitting the x87 code to do so. We keep // them in Compiler because we don't want to store a pointer to the // emitter. void FlatFPX87_Kill (FlatFPStateX87* pState, unsigned iVirtual); void FlatFPX87_PushVirtual (FlatFPStateX87* pState, unsigned iRegister, bool bEmitCode = true); unsigned FlatFPX87_Pop (FlatFPStateX87* pState, bool bEmitCode = true); unsigned FlatFPX87_Top (FlatFPStateX87* pState, bool bEmitCode = true); void FlatFPX87_Unload (FlatFPStateX87* pState, unsigned iVirtual, bool bEmitCode = true); #endif // Codegen functions. This is the API that codegen will use regMaskTP genPushArgumentStackFP (GenTreePtr arg); void genRoundFpExpressionStackFP (GenTreePtr op, var_types type = TYP_UNDEF); void genCodeForTreeStackFP_Const (GenTreePtr tree); void genCodeForTreeStackFP_Leaf (GenTreePtr tree); void genCodeForTreeStackFP_SmpOp (GenTreePtr tree); void genCodeForTreeStackFP_Special (GenTreePtr tree); void genCodeForTreeStackFP_Cast (GenTreePtr tree); void genCodeForTreeStackFP (GenTreePtr tree); void genCondJumpFltStackFP (GenTreePtr cond, BasicBlock * jumpTrue, BasicBlock * jumpFalse, bool bDoTransition = true); void genCondJumpFloat (GenTreePtr cond, BasicBlock * jumpTrue, BasicBlock * jumpFalse); void genCondJumpLngStackFP (GenTreePtr cond, BasicBlock * jumpTrue, BasicBlock * jumpFalse); void genFloatConst(GenTree *tree, RegSet::RegisterPreference *pref); void genFloatLeaf(GenTree *tree, RegSet::RegisterPreference *pref); void genFloatSimple(GenTree *tree, RegSet::RegisterPreference *pref); void genFloatMath(GenTree *tree, RegSet::RegisterPreference *pref); void genFloatCheckFinite(GenTree *tree, RegSet::RegisterPreference *pref); void genLoadFloat(GenTreePtr tree, regNumber reg); void genFloatAssign(GenTree *tree); void genFloatArith(GenTree *tree, RegSet::RegisterPreference *pref); void genFloatAsgArith(GenTree *tree); regNumber genAssignArithFloat(genTreeOps oper, GenTreePtr dst, regNumber dstreg, GenTreePtr src, regNumber srcreg); GenTreePtr genMakeAddressableFloat(GenTreePtr tree, regMaskTP * regMaskIntPtr, regMaskTP * regMaskFltPtr, bool bCollapseConstantDoubles = true); void genCodeForTreeFloat(GenTreePtr tree, RegSet::RegisterPreference *pref = NULL); void genCodeForTreeFloat(GenTreePtr tree, regMaskTP needReg, regMaskTP bestReg); regNumber genArithmFloat(genTreeOps oper, GenTreePtr dst, regNumber dstreg, GenTreePtr src, regNumber srcreg, bool bReverse); void genCodeForTreeCastFloat(GenTreePtr tree, RegSet::RegisterPreference *pref); void genCodeForTreeCastToFloat(GenTreePtr tree, RegSet::RegisterPreference *pref); void genCodeForTreeCastFromFloat(GenTreePtr tree, RegSet::RegisterPreference *pref); void genKeepAddressableFloat(GenTreePtr tree, regMaskTP * regMaskIntPtr, regMaskTP * regMaskFltPtr); void genDoneAddressableFloat(GenTreePtr tree, regMaskTP addrRegInt, regMaskTP addrRegFlt, RegSet::KeepReg keptReg); void genComputeAddressableFloat(GenTreePtr tree, regMaskTP addrRegInt, regMaskTP addrRegFlt, RegSet::KeepReg keptReg, regMaskTP needReg, RegSet::KeepReg keepReg, bool freeOnly = false); void genRoundFloatExpression(GenTreePtr op, var_types type); #if FEATURE_STACK_FP_X87 // Assumes then block will be generated before else block. struct QmarkStateStackFP { FlatFPStateX87 stackState; }; void genQMarkRegVarTransition (GenTreePtr nextNode, VARSET_VALARG_TP liveset); void genQMarkBeforeElseStackFP (QmarkStateStackFP* pState, VARSET_VALARG_TP varsetCond, GenTreePtr nextNode); void genQMarkAfterElseBlockStackFP (QmarkStateStackFP* pState, VARSET_VALARG_TP varsetCond, GenTreePtr nextNode); void genQMarkAfterThenBlockStackFP (QmarkStateStackFP* pState); #endif GenTreePtr genMakeAddressableStackFP (GenTreePtr tree, regMaskTP * regMaskIntPtr, regMaskTP * regMaskFltPtr, bool bCollapseConstantDoubles = true); void genKeepAddressableStackFP (GenTreePtr tree, regMaskTP * regMaskIntPtr, regMaskTP * regMaskFltPtr); void genDoneAddressableStackFP (GenTreePtr tree, regMaskTP addrRegInt, regMaskTP addrRegFlt, RegSet::KeepReg keptReg); void genCodeForTreeStackFP_Asg (GenTreePtr tree); void genCodeForTreeStackFP_AsgArithm (GenTreePtr tree); void genCodeForTreeStackFP_Arithm (GenTreePtr tree); void genCodeForTreeStackFP_DONE (GenTreePtr tree, regNumber reg); void genCodeForTreeFloat_DONE (GenTreePtr tree, regNumber reg); void genSetupStateStackFP (BasicBlock* block); regMaskTP genRegMaskFromLivenessStackFP (VARSET_VALARG_TP varset); // bReverse means make op1 addressable and codegen for op2. // If op1 or op2 are comma expressions, will do code-gen for their non-last comma parts, // and set op1 and op2 to the remaining non-comma expressions. void genSetupForOpStackFP (GenTreePtr& op1, GenTreePtr& op2, bool bReverse, bool bMakeOp1Addressable, bool bOp1ReadOnly, bool bOp2ReadOnly); #if FEATURE_STACK_FP_X87 #ifdef DEBUG bool ConsistentAfterStatementStackFP (); #endif private: void SpillTempsStackFP (regMaskTP canSpillMask); void SpillForCallStackFP (); void UnspillRegVarsStackFp (); // Transition API. Takes care of the stack matching of basicblock boundaries void genCodeForPrologStackFP (); void genCodeForEndBlockTransitionStackFP (BasicBlock* block); void genCodeForBBTransitionStackFP (BasicBlock* pDst); void genCodeForTransitionStackFP (FlatFPStateX87* pSrc, FlatFPStateX87* pDst); void genCodeForTransitionFromMask (FlatFPStateX87* pSrc, regMaskTP mask, bool bEmitCode = true); BasicBlock* genTransitionBlockStackFP (FlatFPStateX87* pState, BasicBlock* pFrom, BasicBlock* pTarget); // This is the API codegen will use to emit virtual fp code. In theory, nobody above this API // should know about x87 instructions. int genNumberTemps (); void genDiscardStackFP (GenTreePtr tree); void genRegRenameWithMasks (regNumber dstReg, regNumber srcReg); void genRegVarBirthStackFP (GenTreePtr tree); void genRegVarBirthStackFP (LclVarDsc* varDsc); void genRegVarDeathStackFP (GenTreePtr tree); void genRegVarDeathStackFP (LclVarDsc* varDsc); void genLoadStackFP (GenTreePtr tree, regNumber reg); void genMovStackFP (GenTreePtr dst, regNumber dstreg, GenTreePtr src, regNumber srcreg); bool genCompInsStackFP (GenTreePtr tos, GenTreePtr other); regNumber genArithmStackFP (genTreeOps oper, GenTreePtr dst, regNumber dstreg, GenTreePtr src, regNumber srcreg, bool bReverse); regNumber genAsgArithmStackFP (genTreeOps oper, GenTreePtr dst, regNumber dstreg, GenTreePtr src, regNumber srcreg); void genCondJmpInsStackFP (emitJumpKind jumpKind, BasicBlock * jumpTrue, BasicBlock * jumpFalse, bool bDoTransition = true); void genTableSwitchStackFP (regNumber reg, unsigned jumpCnt, BasicBlock ** jumpTab); void JitDumpFPState (); #else // !FEATURE_STACK_FP_X87 void SpillForCallRegisterFP (regMaskTP noSpillMask); #endif // !FEATURE_STACK_FP_X87 // When bOnlyNoMemAccess = true, the load will be generated only for constant loading that doesn't // involve memory accesses, (ie: fldz for positive zero, or fld1 for 1). Will return true the function // did the load bool genConstantLoadStackFP (GenTreePtr tree, bool bOnlyNoMemAccess = false); void genEndOfStatement (); #if FEATURE_STACK_FP_X87 struct genRegVarDiesInSubTreeData { regNumber reg; bool result; }; static Compiler::fgWalkPreFn genRegVarDiesInSubTreeWorker; bool genRegVarDiesInSubTree (GenTreePtr tree, regNumber reg); #endif // FEATURE_STACK_FP_X87 // Float spill void UnspillFloat (RegSet::SpillDsc *spillDsc); void UnspillFloat (GenTreePtr tree); void UnspillFloat (LclVarDsc * varDsc); void UnspillFloatMachineDep (RegSet::SpillDsc *spillDsc); void UnspillFloatMachineDep (RegSet::SpillDsc* spillDsc, bool useSameReg); void RemoveSpillDsc (RegSet::SpillDsc* spillDsc); protected : struct genLivenessSet { VARSET_TP liveSet; VARSET_TP varPtrSet; regMaskSmall maskVars; regMaskSmall gcRefRegs; regMaskSmall byRefRegs; genLivenessSet() : VARSET_INIT_NOCOPY(liveSet, VarSetOps::UninitVal()), VARSET_INIT_NOCOPY(varPtrSet, VarSetOps::UninitVal()) {} }; void saveLiveness (genLivenessSet * ls); void restoreLiveness (genLivenessSet * ls); void checkLiveness (genLivenessSet * ls); void unspillLiveness (genLivenessSet * ls); #endif // LEGACY_BACKEND #endif _CODEGENCLASSIC_H_