diff options
Diffstat (limited to 'src/jit/compiler.h')
-rw-r--r-- | src/jit/compiler.h | 158 |
1 files changed, 133 insertions, 25 deletions
diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 520c94a462..bc851dcf1d 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -269,9 +269,12 @@ public: unsigned char lvOverlappingFields :1; // True when we have a struct with possibly overlapping fields unsigned char lvContainsHoles :1; // True when we have a promoted struct that contains holes unsigned char lvCustomLayout :1; // True when this struct has "CustomLayout" -#ifdef _TARGET_ARM_ +#if defined(_TARGET_ARM_) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) unsigned char lvDontPromote:1; // Should struct promoter consider this variable for promotion? - unsigned char lvIsHfaRegArg:1; // Is this argument variable holding a HFA register argument. +#endif + +#ifdef _TARGET_ARM_ + unsigned char lvIsHfaRegArg :1; // Is this argument variable holding a HFA register argument. unsigned char lvHfaTypeIsFloat:1; // Is the HFA type float or double? #endif @@ -290,7 +293,7 @@ public: unsigned char lvSIMDType :1; // This is a SIMD struct unsigned char lvUsedInSIMDIntrinsic :1; // This tells lclvar is used for simd intrinsic #endif // FEATURE_SIMD - unsigned char lvRegStruct : 1; // This is a reg-sized non-field-addressed struct. + unsigned char lvRegStruct :1; // This is a reg-sized non-field-addressed struct. union { @@ -305,6 +308,26 @@ public: unsigned char lvFldOffset; unsigned char lvFldOrdinal; +#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + regNumber lvRegNumForSlot(unsigned slotNum) + { + if (slotNum == 0) + { + return lvArgReg; + } + else if (slotNum == 1) + { + return lvOtherArgReg; + } + else + { + assert(false && "Invalid slotNum!"); + } + + unreached(); + } +#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + private: regNumberSmall _lvRegNum; // Used to store the register this variable is in (or, the low register of a register pair). @@ -314,7 +337,13 @@ private: #if !defined(_TARGET_64BIT_) regNumberSmall _lvOtherReg; // Used for "upper half" of long var. #endif // !defined(_TARGET_64BIT_) + regNumberSmall _lvArgReg; // The register in which this argument is passed. + +#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + regNumberSmall _lvOtherArgReg; // Used for the second part of the struct passed in a register. +#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + #ifndef LEGACY_BACKEND union { @@ -382,7 +411,7 @@ public: regNumber lvArgReg; regNumber GetArgReg() const -{ + { return (regNumber) _lvArgReg; } @@ -392,6 +421,22 @@ public: assert(_lvArgReg == reg); } +#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + __declspec(property(get = GetOtherArgReg, put = SetOtherArgReg)) + regNumber lvOtherArgReg; + + regNumber GetOtherArgReg() const + { + return (regNumber)_lvOtherArgReg; + } + + void SetOtherArgReg(regNumber reg) + { + _lvOtherArgReg = (regNumberSmall)reg; + assert(_lvOtherArgReg == reg); + } +#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + #ifdef FEATURE_SIMD // Is this is a SIMD struct? bool lvIsSIMDType() const @@ -1139,6 +1184,15 @@ struct FuncInfoDsc struct fgArgTabEntry { + +#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + fgArgTabEntry() + { + otherRegNum = REG_NA; + isStruct = false; // is this a struct arg + } +#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + GenTreePtr node; // Initially points at the Op1 field of 'parent', but if the argument is replaced with an GT_ASG or placeholder // it will point at the actual argument in the gtCallLateArgs list. GenTreePtr parent; // Points at the GT_LIST node in the gtCallArgs for this argument @@ -1165,6 +1219,13 @@ struct fgArgTabEntry bool isBackFilled :1; // True when the argument fills a register slot skipped due to alignment requirements of previous arguments. bool isNonStandard:1; // True if it is an arg that is passed in a reg other than a standard arg reg +#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + regNumber otherRegNum; // The (second) register to use when passing this argument. + bool isStruct; // is this a struct arg + + SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc; +#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + void SetIsHfaRegArg(bool hfaRegArg) { isHfaRegArg = hfaRegArg; @@ -1196,10 +1257,10 @@ class fgArgInfo unsigned nextSlotNum; // Updatable slot count value unsigned stkLevel; // Stack depth when we make this call (for x86) - unsigned argTableSize; // size of argTable array (equal to the argCount when done with fgMorphArgs) - bool argsComplete; // marker for state - bool argsSorted; // marker for state - fgArgTabEntryPtr * argTable; // variable sized array of per argument descrption: (i.e. argTable[argTableSize]) + unsigned argTableSize; // size of argTable array (equal to the argCount when done with fgMorphArgs) + bool argsComplete; // marker for state + bool argsSorted; // marker for state + fgArgTabEntryPtr * argTable; // variable sized array of per argument descrption: (i.e. argTable[argTableSize]) private: @@ -1217,11 +1278,24 @@ public: unsigned numRegs, unsigned alignment); +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + fgArgTabEntryPtr AddRegArg (unsigned argNum, + GenTreePtr node, + GenTreePtr parent, + regNumber regNum, + unsigned numRegs, + unsigned alignment, + const bool isStruct, + const regNumber otherRegNum = REG_NA, + const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* const structDescPtr = nullptr); +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING + fgArgTabEntryPtr AddStkArg (unsigned argNum, GenTreePtr node, GenTreePtr parent, unsigned numSlots, - unsigned alignment); + unsigned alignment + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(const bool isStruct)); void RemorphReset (); fgArgTabEntryPtr RemorphRegArg (unsigned argNum, @@ -1391,7 +1465,9 @@ public: DWORD expensiveDebugCheckLevel; #endif - +#if defined(_TARGET_ARM_) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + CORINFO_CLASS_HANDLE GetStructClassHandle(GenTreePtr tree); +#endif // defined(_TARGET_ARM_) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) #ifdef _TARGET_ARM_ @@ -1403,8 +1479,6 @@ public: // floating-point registers. // - inline CORINFO_CLASS_HANDLE GetHfaClassHandle(GenTreePtr tree); - bool IsHfa(CORINFO_CLASS_HANDLE hClass); bool IsHfa(GenTreePtr tree); @@ -1417,6 +1491,14 @@ public: #endif // _TARGET_ARM_ //------------------------------------------------------------------------- + // The following is used for struct passing on System V system. + // +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + bool IsRegisterPassable(CORINFO_CLASS_HANDLE hClass); + bool IsRegisterPassable(GenTreePtr tree); +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING + + //------------------------------------------------------------------------- // The following is used for validating format of EH table // @@ -2450,7 +2532,7 @@ public : unsigned char fldOrdinal; var_types fldType; unsigned fldSize; - CORINFO_CLASS_HANDLE fldTypeHnd; + CORINFO_CLASS_HANDLE fldTypeHnd; }; // Info about struct to be promoted. @@ -3006,9 +3088,12 @@ private: bool impReturnInstruction(BasicBlock *block, int prefixFlags, OPCODE &opcode); void impAbortInline(bool abortThisInlineOnly, bool contextDependent, const char *reason); -#ifdef _TARGET_ARM_ +#if defined(_TARGET_ARM_) void impMarkLclDstNotPromotable(unsigned tmpNum, GenTreePtr op, CORINFO_CLASS_HANDLE hClass); - GenTreePtr impAssignHfaToVar(GenTreePtr op, CORINFO_CLASS_HANDLE hClass); +#endif + +#if defined(_TARGET_ARM_) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + GenTreePtr impAssignStructToVar(GenTreePtr op, CORINFO_CLASS_HANDLE hClass); #endif // A free list of linked list nodes used to represent to-do stacks of basic blocks. @@ -3026,9 +3111,11 @@ private: bool impIsValueType (typeInfo* pTypeInfo); var_types mangleVarArgsType (var_types type); + +#if FEATURE_VARARG regNumber getCallArgIntRegister (regNumber floatReg); regNumber getCallArgFloatRegister (regNumber intReg); - +#endif // FEATURE_VARARG //--------------------------- Inlining------------------------------------- #if defined(DEBUG) || MEASURE_INLINING @@ -4080,10 +4167,9 @@ public: bool fgCastNeeded(GenTreePtr tree, var_types toType); GenTreePtr fgDoNormalizeOnStore(GenTreePtr tree); - GenTreePtr fgMakeTmpArgNode(unsigned tmpVarNum); - - /* The following check for loops that don't execute calls */ + GenTreePtr fgMakeTmpArgNode(unsigned tmpVarNum FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(const bool passedInRegisters)); + // The following check for loops that don't execute calls bool fgLoopCallMarked; void fgLoopCallTest (BasicBlock *srcBB, @@ -4450,7 +4536,14 @@ private: GenTreePtr fgMorphCast (GenTreePtr tree); GenTreePtr fgUnwrapProxy (GenTreePtr objRef); GenTreeCall* fgMorphArgs (GenTreeCall* call); - void fgMakeOutgoingStructArgCopy(GenTreeCall* call, GenTree* args, unsigned argIndex, CORINFO_CLASS_HANDLE copyBlkClass); + + void fgMakeOutgoingStructArgCopy( + GenTreeCall* call, + GenTree* args, + unsigned argIndex, + CORINFO_CLASS_HANDLE copyBlkClass + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structDescPtr)); + void fgFixupStructReturn (GenTreePtr call); GenTreePtr fgMorphLocalVar (GenTreePtr tree); bool fgAddrCouldBeNull (GenTreePtr addr); @@ -4570,11 +4663,11 @@ private: void fgInsertInlineeBlocks (InlineInfo * pInlineInfo); GenTreePtr fgInlinePrependStatements(InlineInfo * inlineInfo); -#ifdef _TARGET_ARM_ +#if defined(_TARGET_ARM_) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) GenTreePtr fgGetStructAsStructPtr(GenTreePtr tree); - GenTreePtr fgAssignHfaInlineeToVar(GenTreePtr child, CORINFO_CLASS_HANDLE retClsHnd); - void fgAttachHfaInlineeToAsg(GenTreePtr tree, GenTreePtr child, CORINFO_CLASS_HANDLE retClsHnd); -#endif + GenTreePtr fgAssignStructInlineeToVar(GenTreePtr child, CORINFO_CLASS_HANDLE retClsHnd); + void fgAttachStructInlineeToAsg(GenTreePtr tree, GenTreePtr child, CORINFO_CLASS_HANDLE retClsHnd); +#endif // defined(_TARGET_ARM_) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) static fgWalkPreFn fgUpdateInlineReturnExpressionPlaceHolder; #ifdef DEBUG @@ -6275,6 +6368,17 @@ public : void eeSetEHinfo(unsigned EHnumber, const CORINFO_EH_CLAUSE* clause); + // ICorStaticInfo wrapper functions + +#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) +#ifdef DEBUG + static void dumpSystemVClassificationType(SystemVClassificationType ct); +#endif // DEBUG + + void eeGetSystemVAmd64PassStructInRegisterDescriptor(/*IN*/ CORINFO_CLASS_HANDLE structHnd, + /*OUT*/ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr); +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING + // Utility functions #if defined(DEBUG) @@ -8433,6 +8537,11 @@ public: static HelperCallProperties s_helperCallProperties; +#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + var_types GetTypeFromClassificationAndSizes(SystemVClassificationType classType, int size); + var_types getEightByteType(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR& structDesc, unsigned slotNum); + void fgMorphSystemVStructArgs(GenTreeCall* call, bool hasStructArgument); +#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) }; // end of class Compiler // Inline methods of CompAllocator. @@ -8466,7 +8575,6 @@ LclVarDsc::LclVarDsc(Compiler* comp) { } - /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |