diff options
Diffstat (limited to 'src/jit/gentree.h')
-rw-r--r-- | src/jit/gentree.h | 193 |
1 files changed, 169 insertions, 24 deletions
diff --git a/src/jit/gentree.h b/src/jit/gentree.h index f6c850ea5a..1402445da0 100644 --- a/src/jit/gentree.h +++ b/src/jit/gentree.h @@ -1027,6 +1027,11 @@ public: return OperIsCopyBlkOp(OperGet()); } + bool OperIsPutArgStk() const + { + return gtOper == GT_PUTARG_STK; + } + bool OperIsAddrMode() const { return OperIsAddrMode(OperGet()); @@ -1125,7 +1130,7 @@ public: static int OperIsSimple(genTreeOps gtOper) { - return (OperKind(gtOper) & GTK_SMPOP ) != 0; + return (OperKind(gtOper) & GTK_SMPOP ) != 0; } static @@ -1294,7 +1299,7 @@ public: static inline bool RequiresNonNullOp2(genTreeOps oper); - + bool IsListOfLclFlds(); #endif // DEBUG inline bool IsZero(); @@ -2277,7 +2282,7 @@ struct GenTreeColon: public GenTreeOp /* gtCall -- method call (GT_CALL) */ typedef class fgArgInfo * fgArgInfoPtr; -struct GenTreeCall: public GenTree +struct GenTreeCall final : public GenTree { GenTreePtr gtCallObjp; // The instance argument ('this' pointer) GenTreeArgList* gtCallArgs; // The list of arguments in original evaluation order @@ -2296,6 +2301,14 @@ struct GenTreeCall: public GenTree CORINFO_SIG_INFO* callSig; // Used by tail calls and to register callsites with the EE regMaskTP gtCallRegUsedMask; // mask of registers used to pass parameters +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc; + + void SetRegisterReturningStructState(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR& structDescIn) + { + structDesc.CopyFrom(structDescIn); + } +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING #define GTF_CALL_M_EXPLICIT_TAILCALL 0x0001 // GT_CALL -- the call is "tail" prefixed and importer has performed tail call checks #define GTF_CALL_M_TAILCALL 0x0002 // GT_CALL -- the call is a tailcall @@ -2438,9 +2451,12 @@ struct GenTreeCall: public GenTree GenTreeCall(var_types type) : GenTree(GT_CALL, type) - {} + { + } #if DEBUGGABLE_GENTREE - GenTreeCall() : GenTree() {} + GenTreeCall() : GenTree() + { + } #endif }; @@ -3024,7 +3040,7 @@ struct GenTreeRetExpr: public GenTree { GenTreePtr gtInlineCandidate; -#ifdef _TARGET_ARM_ +#if defined(_TARGET_ARM_) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) CORINFO_CLASS_HANDLE gtRetClsHnd; #endif @@ -3243,10 +3259,26 @@ struct GenTreePutArgStk: public GenTreeUnOp // Fast tail calls set this to true. // In future if we need to add more such bool fields consider bit fields. - GenTreePutArgStk(genTreeOps oper, var_types type, unsigned slotNum, bool _putInIncomingArgArea = false - DEBUG_ARG(GenTreePtr callNode = NULL) DEBUG_ARG(bool largeNode = false)) : - GenTreeUnOp(oper, type DEBUG_ARG(largeNode)), - gtSlotNum(slotNum), putInIncomingArgArea(_putInIncomingArgArea) + GenTreePutArgStk( + genTreeOps oper, + var_types type, + unsigned slotNum + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots) + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct), + bool _putInIncomingArgArea = false + DEBUG_ARG(GenTreePtr callNode = NULL) + DEBUG_ARG(bool largeNode = false)) + : + GenTreeUnOp(oper, type DEBUG_ARG(largeNode)), + gtSlotNum(slotNum), + putInIncomingArgArea(_putInIncomingArgArea) +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + , gtPutArgStkKind(PutArgStkKindInvalid), + gtNumSlots(numSlots), + gtIsStruct(isStruct), + gtNumberReferenceSlots(0), + gtGcPtrs(nullptr) +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING { #ifdef DEBUG gtCall = callNode; @@ -3254,22 +3286,53 @@ struct GenTreePutArgStk: public GenTreeUnOp } - GenTreePutArgStk(genTreeOps oper, var_types type, GenTreePtr op1, unsigned slotNum, bool _putInIncomingArgArea = false - DEBUG_ARG(GenTreePtr callNode = NULL) DEBUG_ARG(bool largeNode = false)) : - GenTreeUnOp(oper, type, op1 DEBUG_ARG(largeNode)), - gtSlotNum(slotNum), putInIncomingArgArea(_putInIncomingArgArea) + GenTreePutArgStk( + genTreeOps oper, + var_types type, + GenTreePtr op1, + unsigned slotNum + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots) + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct), + bool _putInIncomingArgArea = false + DEBUG_ARG(GenTreePtr callNode = NULL) + DEBUG_ARG(bool largeNode = false)) + : + GenTreeUnOp(oper, type, op1 DEBUG_ARG(largeNode)), + gtSlotNum(slotNum), + putInIncomingArgArea(_putInIncomingArgArea) +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + , gtPutArgStkKind(PutArgStkKindInvalid), + gtNumSlots(numSlots), + gtIsStruct(isStruct), + gtNumberReferenceSlots(0), + gtGcPtrs(nullptr) +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING { #ifdef DEBUG gtCall = callNode; #endif } -#else // !FEATURE_FASTTAIL_CALL - - GenTreePutArgStk(genTreeOps oper, var_types type, unsigned slotNum - DEBUG_ARG(GenTreePtr callNode = NULL) DEBUG_ARG(bool largeNode = false)) : - GenTreeUnOp(oper, type DEBUG_ARG(largeNode)), - gtSlotNum(slotNum) +#else // !FEATURE_FASTTAILCALL + + GenTreePutArgStk( + genTreeOps oper, + var_types type, + unsigned slotNum + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots) + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct) + DEBUG_ARG(GenTreePtr callNode = NULL) + DEBUG_ARG(bool largeNode = false)) + : + GenTreeUnOp(oper, type DEBUG_ARG(largeNode)), + gtSlotNum(slotNum) +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + , gtPutArgStkKind(PutArgStkKindInvalid), + gtNumSlots(numSlots), + gtIsStruct(isStruct), + gtNumberReferenceSlots(0), + gtGcPtrs(nullptr) +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING { #ifdef DEBUG gtCall = callNode; @@ -3277,10 +3340,25 @@ struct GenTreePutArgStk: public GenTreeUnOp } - GenTreePutArgStk(genTreeOps oper, var_types type, GenTreePtr op1, unsigned slotNum - DEBUG_ARG(GenTreePtr callNode = NULL) DEBUG_ARG(bool largeNode = false)) : - GenTreeUnOp(oper, type, op1 DEBUG_ARG(largeNode)), - gtSlotNum(slotNum) + GenTreePutArgStk( + genTreeOps oper, + var_types type, + GenTreePtr op1, + unsigned slotNum + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(unsigned numSlots) + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(bool isStruct) + DEBUG_ARG(GenTreePtr callNode = NULL) + DEBUG_ARG(bool largeNode = false)) + : + GenTreeUnOp(oper, type, op1 DEBUG_ARG(largeNode)), + gtSlotNum(slotNum) +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + , gtPutArgStkKind(PutArgStkKindInvalid), + gtNumSlots(numSlots), + gtIsStruct(isStruct), + gtNumberReferenceSlots(0), + gtGcPtrs(nullptr) +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING { #ifdef DEBUG gtCall = callNode; @@ -3288,10 +3366,53 @@ struct GenTreePutArgStk: public GenTreeUnOp } #endif // FEATURE_FASTTAILCALL +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + //------------------------------------------------------------------------ + // setGcPointers: Sets the number of references and the layout of the struct object returned by the VM. + // + // Arguments: + // numPointers - Number of pointer references. + // pointers - layout of the struct (with pointers marked.) + // + // Return Value: + // None + // + // Notes: + // This data is used in the codegen for GT_PUTARG_STK to decide how to copy the struct to the stack by value. + // If no pointer references are used, block copying instructions are used. + // Otherwise the pointer reference slots are copied atomically in a way that gcinfo is emitted. + // Any non pointer references between the pointer reference slots are copied in block fashion. + // + void setGcPointers(unsigned numPointers, BYTE* pointers) + { + gtNumberReferenceSlots = numPointers; + gtGcPtrs = pointers; + } +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING + #ifdef DEBUG GenTreePtr gtCall; // the call node to which this argument belongs #endif +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + // Instruction selection: during codegen time, what code sequence we will be using + // to encode this operation. + + enum PutArgStkKind : __int8 + { + PutArgStkKindInvalid, + PutArgStkKindRepInstr, + PutArgStkKindUnroll, + }; + + PutArgStkKind gtPutArgStkKind; + + unsigned gtNumSlots; // Number of slots for the argument to be passed on stack + bool gtIsStruct; // This stack arg is a struct. + unsigned gtNumberReferenceSlots; // Number of reference slots. + BYTE* gtGcPtrs; // gcPointers +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING + #if DEBUGGABLE_GENTREE GenTreePutArgStk() : GenTreeUnOp() {} #endif @@ -3325,6 +3446,30 @@ inline GenTreePtr GenTree::MoveNext() return gtOp.gtOp2; } +#ifdef DEBUG +inline bool GenTree::IsListOfLclFlds() + +{ + if (!IsList()) + { + return false; + } + + GenTree* gtListPtr = this; + while (gtListPtr->Current() != nullptr) + { + if (gtListPtr->Current()->OperGet() != GT_LCL_FLD) + { + return false; + } + + gtListPtr = gtListPtr->MoveNext(); + } + + return true; +} +#endif // DEBUG + inline GenTreePtr GenTree::Current() { assert(IsList()); |