diff options
author | Brian Sullivan <briansul@microsoft.com> | 2016-04-04 15:26:38 -0700 |
---|---|---|
committer | Brian Sullivan <briansul@microsoft.com> | 2016-04-04 18:26:04 -0700 |
commit | 4de1138be664fb43448b08149b5aab4eb720b7a9 (patch) | |
tree | 831cd2fb7e3d4d9c3c473d75d09663b2951b4a86 | |
parent | d62613deb7af2c1d9126e3abfa368536d3df5a04 (diff) | |
download | coreclr-4de1138be664fb43448b08149b5aab4eb720b7a9.tar.gz coreclr-4de1138be664fb43448b08149b5aab4eb720b7a9.tar.bz2 coreclr-4de1138be664fb43448b08149b5aab4eb720b7a9.zip |
Safe refactoring changes and code cleanup items
Fixed the dumper so that GT_LCL_VAR and GT_LCL_FLD use a common code path
and we now display (last use) correctly
Moved the checking for invalid GT_LISTs with an op1 arg of a GT_LIST from gtNewArgList to the constructor
and called IsListForMultiRegArg in the new assert
Renamed IsListofLclFlds to IsListForMultiRegArgs and added ARM64 support
Modifed the dump to display the GTF_MORPHED flag using a '+'
Fix dumper's gtGetLateArgMsg to display each register for a multireg struct passed using a GT_LIST
Modified the NYI_<target> macros to include the target in their message
Fixed the gtCosts for GT_LIST, GT_OBJ, GT_MKREFANY and GT_BOX nodes
When we construct a new GT_LCL_FLD, initialize the gtFieldSeq to NotAField rather than nullptr
Fix comment header for getStructGcPtrsFromOp
Removed the define on ARM64 that changed the asserts(p) macro to notYetImplemented
In NewPutArg renamed the "fp" argument to be called "info" instead
-rw-r--r-- | src/jit/compiler.cpp | 9 | ||||
-rw-r--r-- | src/jit/compiler.h | 1 | ||||
-rw-r--r-- | src/jit/error.h | 8 | ||||
-rw-r--r-- | src/jit/gentree.cpp | 180 | ||||
-rw-r--r-- | src/jit/gentree.h | 54 | ||||
-rw-r--r-- | src/jit/host.h | 6 | ||||
-rw-r--r-- | src/jit/lclvars.cpp | 58 | ||||
-rw-r--r-- | src/jit/lower.cpp | 78 | ||||
-rw-r--r-- | src/jit/lower.h | 2 | ||||
-rw-r--r-- | src/jit/morph.cpp | 10 |
10 files changed, 224 insertions, 182 deletions
diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp index 3b78d17a83..61605c7ef3 100644 --- a/src/jit/compiler.cpp +++ b/src/jit/compiler.cpp @@ -426,14 +426,15 @@ var_types Compiler::getJitGCType(BYTE gcType) } #if FEATURE_MULTIREG_ARGS -//------------------------------------------------------------------------ -// getStructGcPtrsFromOp: Given a GenTree node of TYP_STRUCT that represents a pass by value argument -// return the gcPtr layout for the pointers sized fields // +//--------------------------------------------------------------------------- +// getStructGcPtrsFromOp: Given a GenTree node of TYP_STRUCT that represents +// a pass by value argument, return the gcPtr layout +// for the pointers sized fields // Arguments: // op - the operand of TYP_STRUCT that is passed by value // gcPtrsOut - an array of BYTES that are written by this method // they will contain the VM's CorInfoGCType values -// for each pointer sized field// +// for each pointer sized field // Return Value: // Two [or more] values are written into the gcPtrs array // diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 9407419e66..0c18dba75f 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -2030,6 +2030,7 @@ public: void gtGetLateArgMsg (GenTreePtr call, GenTreePtr arg, int argNum, + int listCount, char* bufp, unsigned bufLength); void gtDispArgList (GenTreePtr tree, diff --git a/src/jit/error.h b/src/jit/error.h index 7b6cf10c30..d883fb08c9 100644 --- a/src/jit/error.h +++ b/src/jit/error.h @@ -92,7 +92,7 @@ extern void notYetImplemented(const char * msg, const char * file, unsigned line #ifdef _TARGET_AMD64_ -#define NYI_AMD64(msg) notYetImplemented("NYI: " # msg, __FILE__, __LINE__) +#define NYI_AMD64(msg) notYetImplemented("NYI_AMD64: " # msg, __FILE__, __LINE__) #define NYI_X86(msg) do { } while (0) #define NYI_ARM(msg) do { } while (0) #define NYI_ARM64(msg) do { } while (0) @@ -100,7 +100,7 @@ extern void notYetImplemented(const char * msg, const char * file, unsigned line #elif defined(_TARGET_X86_) #define NYI_AMD64(msg) do { } while (0) -#define NYI_X86(msg) notYetImplemented("NYI: " # msg, __FILE__, __LINE__) +#define NYI_X86(msg) notYetImplemented("NYI_X86: " # msg, __FILE__, __LINE__) #define NYI_ARM(msg) do { } while (0) #define NYI_ARM64(msg) do { } while (0) @@ -108,7 +108,7 @@ extern void notYetImplemented(const char * msg, const char * file, unsigned line #define NYI_AMD64(msg) do { } while (0) #define NYI_X86(msg) do { } while (0) -#define NYI_ARM(msg) notYetImplemented("NYI: " # msg, __FILE__, __LINE__) +#define NYI_ARM(msg) notYetImplemented("NYI_ARM: " # msg, __FILE__, __LINE__) #define NYI_ARM64(msg) do { } while (0) #elif defined(_TARGET_ARM64_) @@ -116,7 +116,7 @@ extern void notYetImplemented(const char * msg, const char * file, unsigned line #define NYI_AMD64(msg) do { } while (0) #define NYI_X86(msg) do { } while (0) #define NYI_ARM(msg) do { } while (0) -#define NYI_ARM64(msg) notYetImplemented("NYI: " # msg, __FILE__, __LINE__) +#define NYI_ARM64(msg) notYetImplemented("NYI_ARM64: " # msg, __FILE__, __LINE__) #else diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index 6d9f6febe3..ebc62eaf6b 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -3007,6 +3007,7 @@ COMMON_CNS: break; + case GT_LIST: case GT_NOP: costEx = 0; costSz = 0; @@ -3116,15 +3117,17 @@ COMMON_CNS: case GT_OBJ: level = gtSetEvalOrder(tree->gtOp.gtOp1); ftreg |= tree->gtOp.gtOp1->gtRsvdRegs; - costEx = tree->gtOp.gtOp1->gtCostEx + 1; - costSz = tree->gtOp.gtOp1->gtCostSz + 1; + // We estimate the cost of a GT_OBJ or GT_MKREFANY to be two loads (GT_INDs) + costEx = 2*IND_COST_EX; + costSz = 2*2; break; case GT_BOX: level = gtSetEvalOrder(tree->gtBox.BoxOp()); ftreg |= tree->gtBox.BoxOp()->gtRsvdRegs; - costEx = tree->gtBox.BoxOp()->gtCostEx; - costSz = tree->gtBox.BoxOp()->gtCostSz; + // We estimate the cost of a GT_BOX to be two stores (GT_INDs) + costEx = 2*IND_COST_EX; + costSz = 2*2; break; case GT_IND: @@ -5220,6 +5223,7 @@ GenTreeLclFld* Compiler::gtNewLclFldNode(unsigned lnum, //assert(lnum < lvaCount); + node->gtFieldSeq = FieldSeqStore::NotAField(); return node; } @@ -5260,17 +5264,9 @@ GenTreeArgList* Compiler::gtNewListNode(GenTreePtr op1, GenTreeArgList* op2) * Create a list out of one value. */ -GenTreeArgList* Compiler::gtNewArgList(GenTreePtr op) +GenTreeArgList* Compiler::gtNewArgList(GenTreePtr arg) { -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - // With structs passed in multiple args we could have the arg - // GT_LIST containing a list of LCL_FLDs - assert((op != NULL) && ((!op->IsList()) || (op->IsListOfLclFlds()))); -#else // !FEATURE_UNIX_AMD64_STRUCT_PASSING - assert((op != NULL) && (op->OperGet() != GT_LIST)); -#endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING - - return new (this, GT_LIST) GenTreeArgList(op); + return new (this, GT_LIST) GenTreeArgList(arg); } /***************************************************************************** @@ -5278,21 +5274,9 @@ GenTreeArgList* Compiler::gtNewArgList(GenTreePtr op) * Create a list out of the two values. */ -GenTreeArgList* Compiler::gtNewArgList(GenTreePtr op1, GenTreePtr op2) +GenTreeArgList* Compiler::gtNewArgList(GenTreePtr arg1, GenTreePtr arg2) { -#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - // With structs passed in multiple args we could have the arg - // GT_LIST containing a list of LCL_FLDs - assert((op1 != NULL) && ((!op1->IsList()) || (op1->IsListOfLclFlds()))); - assert((op2 != NULL) && ((!op2->IsList()) || (op2->IsListOfLclFlds()))); -#else // !FEATURE_UNIX_AMD64_STRUCT_PASSING - assert((op1 != NULL) && (!op1->IsList())); - assert((op2 != NULL) && (!op2->IsList())); -#endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING - - GenTreePtr tree; - - return new (this, GT_LIST) GenTreeArgList(op1, gtNewArgList(op2)); + return new (this, GT_LIST) GenTreeArgList(arg1, gtNewArgList(arg2)); } /***************************************************************************** @@ -7122,7 +7106,8 @@ GenTreePtr GenTree::GetChild(unsigned childNum) printf("%c", (flags & GTF_CALL ) ? 'C' : '-'); printf("%c", (flags & GTF_EXCEPT ) ? 'X' : '-'); printf("%c", (flags & GTF_GLOB_REF ) ? 'G' : '-'); - printf("%c", (flags & GTF_ORDER_SIDEEFF ) ? 'O' : '-'); + printf("%c", (flags & GTF_MORPHED ) ? '+' : // First print '+' if GTF_MORPHED is set + (flags & GTF_ORDER_SIDEEFF ) ? 'O' : '-'); // otherwise print 'O' or '-' printf("%c", (flags & GTF_COLON_COND ) ? '?' : '-'); printf("%c", (flags & GTF_DONT_CSE ) ? 'N' : // N is for No cse (flags & GTF_MAKE_CSE ) ? 'H' : '-'); // H is for Hoist this expr @@ -8038,17 +8023,27 @@ Compiler::gtDispLeaf(GenTree *tree, IndentStack* indentStack) return; } + bool isLclFld = false; + switch (tree->gtOper) { unsigned varNum; LclVarDsc * varDsc; + case GT_LCL_FLD: + case GT_LCL_FLD_ADDR: + case GT_STORE_LCL_FLD: + isLclFld = true; + __fallthrough; + case GT_PHI_ARG: case GT_LCL_VAR: case GT_LCL_VAR_ADDR: case GT_STORE_LCL_VAR: printf(" "); - gtDispLclVar(tree->gtLclVarCommon.gtLclNum); + varNum = tree->gtLclVarCommon.gtLclNum; + varDsc = &lvaTable[varNum]; + gtDispLclVar(varNum); if (tree->gtLclVarCommon.HasSsaName()) { if (tree->gtFlags & GTF_VAR_USEASG) @@ -8061,8 +8056,29 @@ Compiler::gtDispLeaf(GenTree *tree, IndentStack* indentStack) printf("%s:%d", (tree->gtFlags & GTF_VAR_DEF) ? "d" : "u", tree->gtLclVarCommon.gtSsaNum); } } - - varDsc = &lvaTable[tree->gtLclVarCommon.gtLclNum]; + + if (isLclFld) + { + printf("[+%u]", tree->gtLclFld.gtLclOffs); + gtDispFieldSeq(tree->gtLclFld.gtFieldSeq); + } + + if (varDsc->lvRegister) + { + printf(" "); + varDsc->PrintVarReg(); + } +#ifndef LEGACY_BACKEND + else if (tree->InReg()) + { +#if CPU_LONG_USES_REGPAIR + if (isRegPairType(tree->TypeGet())) + printf(" %s", compRegPairName(tree->gtRegPair)); + else +#endif + printf(" %s", compRegVarName(tree->gtRegNum)); + } +#endif // !LEGACY_BACKEND if (varDsc->lvPromoted) { @@ -8090,7 +8106,7 @@ Compiler::gtDispLeaf(GenTree *tree, IndentStack* indentStack) } printf("\n"); - printf(" "); + printf(" "); printIndent(indentStack); printf(" %-6s V%02u.%s (offs=0x%02x) -> ", varTypeName(fieldVarDsc->TypeGet()), @@ -8106,7 +8122,7 @@ Compiler::gtDispLeaf(GenTree *tree, IndentStack* indentStack) fieldVarDsc->PrintVarReg(); } - if ((fieldVarDsc->lvTracked) && + if (fieldVarDsc->lvTracked && fgLocalVarLivenessDone && // Includes local variable liveness ((tree->gtFlags & GTF_VAR_DEATH) != 0)) { @@ -8114,57 +8130,15 @@ Compiler::gtDispLeaf(GenTree *tree, IndentStack* indentStack) } } } - - goto LCL_COMMON; - - case GT_LCL_FLD: - case GT_LCL_FLD_ADDR: - case GT_STORE_LCL_FLD: - printf(" "); - gtDispLclVar(tree->gtLclVarCommon.gtLclNum); - if (tree->gtLclVarCommon.HasSsaName()) + else // a normal not-promoted lclvar { - if (tree->gtFlags & GTF_VAR_USEASG) + if (varDsc->lvTracked && + fgLocalVarLivenessDone && + ((tree->gtFlags & GTF_VAR_DEATH) != 0)) { - assert(tree->gtFlags & GTF_VAR_DEF); - printf("ud:%d->%d", tree->gtLclVarCommon.gtSsaNum, GetSsaNumForLocalVarDef(tree)); + printf(" (last use)"); } - else - { - printf("%s:%d", (tree->gtFlags & GTF_VAR_DEF) ? "d" : "u", tree->gtLclVarCommon.gtSsaNum); - } - } - printf("[+%u]", tree->gtLclFld.gtLclOffs); - gtDispFieldSeq(tree->gtLclFld.gtFieldSeq); - - LCL_COMMON: - - varNum = tree->gtLclVarCommon.gtLclNum; - varDsc = &lvaTable[varNum]; - - if (varDsc->lvRegister) - { - printf(" "); - varDsc->PrintVarReg(); } -#ifndef LEGACY_BACKEND - else if (tree->InReg()) - { -#if CPU_LONG_USES_REGPAIR - if (isRegPairType(tree->TypeGet())) - printf(" %s", compRegPairName(tree->gtRegPair)); - else -#endif - printf(" %s", compRegVarName(tree->gtRegNum)); - } -#endif // !LEGACY_BACKEND - - if (fgLocalVarLivenessDone && - ((tree->gtFlags & GTF_VAR_DEATH) != 0)) - { - printf(" (last use)"); - } - break; case GT_REG_VAR: @@ -8183,7 +8157,7 @@ Compiler::gtDispLeaf(GenTree *tree, IndentStack* indentStack) varNum = tree->gtRegVar.gtLclNum; varDsc = &lvaTable[varNum]; - if ((varDsc->lvTracked) && + if (varDsc->lvTracked && fgLocalVarLivenessDone && ((tree->gtFlags & GTF_VAR_DEATH) != 0)) { @@ -8663,7 +8637,7 @@ void Compiler::gtDispTree(GenTreePtr tree, argx = lateArgs->Current(); IndentInfo arcType = (lateArgs->Rest() == nullptr) ? IIArcBottom : IIArc; - gtGetLateArgMsg(tree, argx, lateArgIndex, bufp, sizeof(buf)); + gtGetLateArgMsg(tree, argx, lateArgIndex, -1, bufp, sizeof(buf)); gtDispChild(argx, indentStack, arcType, bufp, topOnly); } } @@ -8791,6 +8765,8 @@ void Compiler::gtGetArgMsg(GenTreePtr call, // call - The call for which 'arg' is an argument // argx - The argument for which a message should be constructed // lateArgIndex - The ordinal number of the arg in the lastArg list +// listCount - When printing in Linear form this is the count for a multireg GT_LIST +// or -1 if we are not printing in Linear form // bufp - A pointer to the buffer into which the message is written // bufLength - The length of the buffer pointed to by bufp // @@ -8804,6 +8780,7 @@ void Compiler::gtGetArgMsg(GenTreePtr call, void Compiler::gtGetLateArgMsg(GenTreePtr call, GenTreePtr argx, int lateArgIndex, + int listCount, char* bufp, unsigned bufLength) { @@ -8824,10 +8801,36 @@ void Compiler::gtGetLateArgMsg(GenTreePtr call, else #endif { - if (gtArgIsThisPtr(curArgTabEntry)) + if (gtArgIsThisPtr(curArgTabEntry)) + { sprintf_s(bufp, bufLength, "this in %s%c", compRegVarName(argReg), 0); - else - sprintf_s(bufp, bufLength, "arg%d in %s%c", curArgTabEntry->argNum, compRegVarName(argReg), 0); + } + else + { +#ifdef _TARGET_ARM64_ + if (curArgTabEntry->numRegs == 2) + { + regNumber argReg2 = REG_NEXT(argReg); + if (listCount == -1) + { + sprintf_s(bufp, bufLength, "arg%d %s,%s%c", curArgTabEntry->argNum, compRegVarName(argReg), compRegVarName(argReg2), 0); + } + else if (listCount == 1) + { + sprintf_s(bufp, bufLength, "arg%d hi %s%c", curArgTabEntry->argNum, compRegVarName(argReg2), 0); + } + else + { + assert(listCount == 0); + sprintf_s(bufp, bufLength, "arg%d lo %s%c", curArgTabEntry->argNum, compRegVarName(argReg), 0); + } + } + else +#endif + { + sprintf_s(bufp, bufLength, "arg%d in %s%c", curArgTabEntry->argNum, compRegVarName(argReg), 0); + } + } } } @@ -9082,6 +9085,7 @@ GenTreePtr Compiler::gtDispLinearTree(GenTreeStmt* curStmt, // print the nodes of the nested list and continue to the next argument. if (listElem->gtOper == GT_LIST) { + int listCount = 0; GenTreePtr nextListNested = nullptr; for (GenTreePtr listNested = listElem; listNested != nullptr; listNested = nextListNested) { @@ -9106,7 +9110,7 @@ GenTreePtr Compiler::gtDispLinearTree(GenTreeStmt* curStmt, else { assert(child == tree->gtCall.gtCallLateArgs); - gtGetLateArgMsg(tree, listNested, listElemNum, bufp, BufLength); + gtGetLateArgMsg(tree, listNested, listElemNum, listCount++, bufp, BufLength); } nextLinearNode = gtDispLinearTree(curStmt, nextLinearNode, listElemNested, indentStack, bufp); indentStack->Pop(); @@ -9130,7 +9134,7 @@ GenTreePtr Compiler::gtDispLinearTree(GenTreeStmt* curStmt, else { assert(child == tree->gtCall.gtCallLateArgs); - gtGetLateArgMsg(tree, listElem, listElemNum, bufp, BufLength); + gtGetLateArgMsg(tree, listElem, listElemNum, -1, bufp, BufLength); } } else diff --git a/src/jit/gentree.h b/src/jit/gentree.h index d1dbb77bd6..0c4b4e13cd 100644 --- a/src/jit/gentree.h +++ b/src/jit/gentree.h @@ -1320,7 +1320,7 @@ public: static inline bool RequiresNonNullOp2(genTreeOps oper); - bool IsListOfLclFlds(); + bool IsListForMultiRegArg(); #endif // DEBUG inline bool IsZero(); @@ -2302,16 +2302,21 @@ struct GenTreeArgList: public GenTreeOp GenTreeArgList() : GenTreeOp() {} #endif - GenTreeArgList(GenTreePtr arg ) : - GenTreeOp(GT_LIST, TYP_VOID, arg, NULL) - {} + GenTreeArgList(GenTreePtr arg) : + GenTreeArgList(arg, nullptr) {} GenTreeArgList(GenTreePtr arg, GenTreeArgList* rest) : GenTreeOp(GT_LIST, TYP_VOID, arg, rest) { - assert (arg != NULL); + // With structs passed in multiple args we could have an arg + // GT_LIST containing a list of LCL_FLDs, see IsListForMultiRegArg() + // + assert((arg != nullptr) && ((!arg->IsList()) || (arg->IsListForMultiRegArg()))); gtFlags |= arg->gtFlags & GTF_ALL_EFFECT; - if (rest != NULL) gtFlags |= rest->gtFlags & GTF_ALL_EFFECT; + if (rest != NULL) + { + gtFlags |= rest->gtFlags & GTF_ALL_EFFECT; + } } }; @@ -3680,18 +3685,43 @@ inline GenTreePtr GenTree::MoveNext() } #ifdef DEBUG -inline bool GenTree::IsListOfLclFlds() - +inline bool GenTree::IsListForMultiRegArg() { if (!IsList()) { return false; } +#if FEATURE_MULTIREG_ARGS + // We allow a GT_LIST of some nodes as an argument GenTree* gtListPtr = this; - while (gtListPtr->Current() != nullptr) + while (gtListPtr != nullptr) { - if (gtListPtr->Current()->OperGet() != GT_LCL_FLD) + bool allowed = false; +#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING + // ToDo: fix UNIX_AMD64 so that we do not generate this kind of a List + if (gtListPtr->Current() == nullptr) + break; + + // Only a list of GT_LCL_FLDs is allowed + if (gtListPtr->Current()->OperGet() == GT_LCL_FLD) + { + allowed = true; + } +#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING +#ifdef _TARGET_ARM64_ + // A list of GT_LCL_VARs is allowed + if (gtListPtr->Current()->OperGet() == GT_LCL_VAR) + { + allowed = true; + } + // A list of GT_LCL_FLDs is allowed + else if (gtListPtr->Current()->OperGet() == GT_LCL_FLD) + { + allowed = true; + } +#endif + if (!allowed) { return false; } @@ -3700,6 +3730,10 @@ inline bool GenTree::IsListOfLclFlds() } return true; +#else // FEATURE_MULTIREG_ARGS + // Not allowed to have a GT_LIST here unless we have FEATURE_MULTIREG_ARGS + return false; +#endif } #endif // DEBUG diff --git a/src/jit/host.h b/src/jit/host.h index cf207136fa..9948188637 100644 --- a/src/jit/host.h +++ b/src/jit/host.h @@ -51,13 +51,7 @@ extern "C" void __cdecl assertAbort(const char *why, const char *file, unsigned line); #undef assert -// TODO-ARM64-NYI: Temporarily make all asserts in the JIT use the NYI code path -#ifdef _TARGET_ARM64_ -extern void notYetImplemented(const char * msg, const char * file, unsigned line); -#define assert(p) (void)((p) || (notYetImplemented("assert: " #p, __FILE__, __LINE__),0)) -#else #define assert(p) (void)((p) || (assertAbort(#p, __FILE__, __LINE__),0)) -#endif #else // DEBUG diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp index 35810d147f..e6956cf3cf 100644 --- a/src/jit/lclvars.cpp +++ b/src/jit/lclvars.cpp @@ -1819,7 +1819,7 @@ unsigned Compiler::lvaGetFieldLocal(LclVarDsc * varDsc, unsigned int fldOffse } } - noway_assert(!"Cannot find field local."); + // This is the not-found error return path, the caller should check for BAD_VAR_NUM return BAD_VAR_NUM; } @@ -2770,9 +2770,9 @@ void LclVarDsc::lvaDisqualifyVar() #endif // ASSERTION_PROP #ifndef LEGACY_BACKEND -/********************************************************************************** - * Get type of a variable when passed as an argument. - */ +/********************************************************************************** +* Get type of a variable when passed as an argument. +*/ var_types LclVarDsc::lvaArgType() { var_types type = TypeGet(); @@ -2782,29 +2782,33 @@ var_types LclVarDsc::lvaArgType() { switch (lvExactSize) { - case 1: type = TYP_BYTE; break; - case 2: type = TYP_SHORT; break; - case 4: type = TYP_INT; break; - case 8: - switch (*lvGcLayout) - { - case TYPE_GC_NONE: - type = TYP_I_IMPL; - break; - case TYPE_GC_REF: - type = TYP_REF; - break; - case TYPE_GC_BYREF: - type = TYP_BYREF; - break; - default: - unreached(); - } - break; - - default: - type = TYP_BYREF; - break; + case 1: type = TYP_BYTE; break; + case 2: type = TYP_SHORT; break; + case 4: type = TYP_INT; break; + case 8: + switch (*lvGcLayout) + { + case TYPE_GC_NONE: + type = TYP_I_IMPL; + break; + + case TYPE_GC_REF: + type = TYP_REF; + break; + + case TYPE_GC_BYREF: + type = TYP_BYREF; + break; + + default: + unreached(); + } + break; + + default: + type = TYP_BYREF; + break; + } } #else diff --git a/src/jit/lower.cpp b/src/jit/lower.cpp index 6e228a2f3f..4e5eb5977e 100644 --- a/src/jit/lower.cpp +++ b/src/jit/lower.cpp @@ -1097,7 +1097,7 @@ void Lowering::SpliceInUnary(GenTreePtr parent, GenTreePtr* ppChild, GenTreePtr // Arguments: // call - the call whose arg is being rewritten. // arg - the arg being rewritten. -// fp - the ArgTabEntry for the argument. +// info - the ArgTabEntry information for the argument. // type - the type of the argument. // // Return Value: @@ -1105,7 +1105,7 @@ void Lowering::SpliceInUnary(GenTreePtr parent, GenTreePtr* ppChild, GenTreePtr // or the incoming arg if the arg tree was not rewritten. // // Assumptions: -// call, arg, and fp must be non-null. +// call, arg, and info must be non-null. // // Notes: // For System V systems with native struct passing (i.e. FEATURE_UNIX_AMD64_STRUCT_PASSING defined) @@ -1117,11 +1117,11 @@ void Lowering::SpliceInUnary(GenTreePtr parent, GenTreePtr* ppChild, GenTreePtr // layout object, so the codegen of the GT_PUTARG_STK could use this for optimizing copying to the stack by value. // (using block copy primitives for non GC pointers and a single TARGET_POINTER_SIZE copy with recording GC info.) // -GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryPtr fp, var_types type) +GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryPtr info, var_types type) { assert(call != nullptr); assert(arg != nullptr); - assert(fp != nullptr); + assert(info != nullptr); GenTreePtr putArg = nullptr; bool updateArgTable = true; @@ -1140,27 +1140,28 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING if (varTypeIsStruct(type)) { - isOnStack = !fp->structDesc.passedInRegisters; + isOnStack = !info->structDesc.passedInRegisters; } else { - isOnStack = fp->regNum == REG_STK; + isOnStack = info->regNum == REG_STK; } #else // !FEATURE_UNIX_AMD64_STRUCT_PASSING - isOnStack = fp->regNum == REG_STK; + isOnStack = info->regNum == REG_STK; #endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING if (!isOnStack) { #ifdef FEATURE_SIMD // TYP_SIMD8 is passed in an integer register. We need the putArg node to be of the int type. - if (type == TYP_SIMD8 && genIsValidIntReg(fp->regNum)) + if (type == TYP_SIMD8 && genIsValidIntReg(info->regNum)) { type = TYP_LONG; } #endif //FEATURE_SIMD + #if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) - if (fp->isStruct) + if (info->isStruct) { // The following code makes sure a register passed struct arg is moved to // the register before the call is made. @@ -1173,9 +1174,9 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP // The code creates a GT_PUTARG_REG node for each GT_LCL_FLD in the GT_LIST // and splices it in the list with the corresponding original GT_LCL_FLD tree as op1. - assert(fp->structDesc.eightByteCount != 0); + assert(info->structDesc.eightByteCount != 0); - if (fp->structDesc.eightByteCount == 1) + if (info->structDesc.eightByteCount == 1) { // Case 1 above: Create a GT_PUTARG_REG node with op1 of the original tree. // @@ -1207,17 +1208,17 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP putArg = comp->gtNewOperNode(GT_PUTARG_REG, type, arg); } - else if (fp->structDesc.eightByteCount == 2) + else if (info->structDesc.eightByteCount == 2) { // Case 2 above: Convert the LCL_FLDs to PUTARG_REG // // lowering call : - // N001(3, 2)[000025] ------ - N----Source / --* &lclVar byref V01 loc1 - // N003(3, 2)[000056] ------ - N----Destination + --* &lclVar byref V03 tmp1 - // N006(1, 1)[000058] ------------ + --* const int 16 + // N001(3, 2) [000025] ------ - N----Source / --* &lclVar byref V01 loc1 + // N003(3, 2) [000056] ------ - N----Destination + --* &lclVar byref V03 tmp1 + // N006(1, 1) [000058] ------------ + --* const int 16 // N007(12, 12)[000059] - A--G---- - L - arg0 SETUP / --* copyBlk void - // N009(3, 4)[000061] ------ - N----arg0 in rdi + --* lclFld long V03 tmp1[+0] - // N010(3, 4)[000063] ------------arg0 in rsi + --* lclFld long V03 tmp1[+8](last use) + // N009(3, 4) [000061] ------ - N----arg0 in rdi + --* lclFld long V03 tmp1[+0] + // N010(3, 4) [000063] ------------arg0 in rsi + --* lclFld long V03 tmp1[+8](last use) // N014(40, 31)[000026] --CXG------ - *call void Test.Foo.test2 // // args : @@ -1240,13 +1241,13 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP assert(arg->OperGet() == GT_LIST); GenTreeArgList* argListPtr = arg->AsArgList(); - + for (unsigned ctr = 0; argListPtr != nullptr; argListPtr = argListPtr->Rest(), ctr++) { // Create a new GT_PUTARG_REG node with op1 the original GT_LCL_FLD. GenTreePtr newOper = comp->gtNewOperNode( GT_PUTARG_REG, - comp->GetTypeFromClassificationAndSizes(fp->structDesc.eightByteClassifications[ctr], fp->structDesc.eightByteSizes[ctr]), + comp->GetTypeFromClassificationAndSizes(info->structDesc.eightByteClassifications[ctr], info->structDesc.eightByteSizes[ctr]), argListPtr->gtOp.gtOp1); // CopyCosts @@ -1263,11 +1264,12 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP else { assert(false && "Illegal count of eightbytes for the CLR type system"); // No more than 2 eightbytes for the CLR. - + } } else #endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) + { putArg = comp->gtNewOperNode(GT_PUTARG_REG, type, arg); } @@ -1278,24 +1280,24 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP // This provides the info to put this argument in in-coming arg area slot // instead of in out-going arg area slot. - FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY(assert(fp->isStruct == varTypeIsStruct(type))); // Make sure state is correct + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY(assert(info->isStruct == varTypeIsStruct(type))); // Make sure state is correct #if FEATURE_FASTTAILCALL putArg = new (comp, GT_PUTARG_STK) GenTreePutArgStk(GT_PUTARG_STK, type, arg, - fp->slotNum - FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(fp->numSlots) - FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(fp->isStruct), + info->slotNum + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(info->numSlots) + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(info->isStruct), call->IsFastTailCall() DEBUG_ARG(call)); #else putArg = new (comp, GT_PUTARG_STK) GenTreePutArgStk(GT_PUTARG_STK, type, arg, - fp->slotNum - FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(fp->numSlots) - FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(fp->isStruct) + info->slotNum + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(info->numSlots) + FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(info->isStruct) DEBUG_ARG(call)); #endif @@ -1307,10 +1309,10 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP // to be done (only for reference slots), so gcinfo is emitted. // For non-reference slots faster/smaller size instructions are used - // pair copying using XMM registers or rep mov instructions. - if (fp->isStruct) + if (info->isStruct) { unsigned numRefs = 0; - BYTE* gcLayout = new (comp, CMK_Codegen) BYTE[fp->numSlots]; + BYTE* gcLayout = new (comp, CMK_Codegen) BYTE[info->numSlots]; // We use GT_OBJ for non-SIMD struct arguments. However, for // SIMD arguments the GT_OBJ has already been transformed. if (arg->gtOper != GT_OBJ) @@ -1335,9 +1337,9 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP putArg->SetInReg(); } #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING - else if (fp->isStruct) + else if (info->isStruct) { - if (fp->structDesc.passedInRegisters) + if (info->structDesc.passedInRegisters) { putArg->SetInReg(); } @@ -1354,7 +1356,7 @@ GenTreePtr Lowering::NewPutArg(GenTreeCall* call, GenTreePtr arg, fgArgTabEntryP } else if (updateArgTable) { - fp->node = putArg; + info->node = putArg; } return putArg; } @@ -1386,9 +1388,9 @@ void Lowering::LowerArg(GenTreeCall* call, GenTreePtr* ppArg) #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING !arg->OperIsCopyBlkOp()) // these are de facto placeholders (apparently) { - fgArgTabEntryPtr fp = comp->gtArgEntryByNode(call, arg); - assert(fp->node == arg); - bool isReg = (fp->regNum != REG_STK); + fgArgTabEntryPtr info = comp->gtArgEntryByNode(call, arg); + assert(info->node == arg); + bool isReg = (info->regNum != REG_STK); var_types type = arg->TypeGet(); if (varTypeIsSmall(type)) @@ -1417,8 +1419,8 @@ void Lowering::LowerArg(GenTreeCall* call, GenTreePtr* ppArg) GenTreePtr argLo = arg->gtGetOp1(); GenTreePtr argHi = arg->gtGetOp2(); - GenTreePtr putArgLo = NewPutArg(call, argLo, fp, type); - GenTreePtr putArgHi = NewPutArg(call, argHi, fp, type); + GenTreePtr putArgLo = NewPutArg(call, argLo, info, type); + GenTreePtr putArgHi = NewPutArg(call, argHi, info, type); arg->gtOp.gtOp1 = putArgLo; arg->gtOp.gtOp2 = putArgHi; @@ -1456,7 +1458,7 @@ void Lowering::LowerArg(GenTreeCall* call, GenTreePtr* ppArg) else #endif // !defined(_TARGET_64BIT_) { - putArg = NewPutArg(call, arg, fp, type); + putArg = NewPutArg(call, arg, info, type); // In the case of register passable struct (in one or two registers) // the NewPutArg returns a new node (GT_PUTARG_REG or a GT_LIST with two GT_PUTARG_REGs.) diff --git a/src/jit/lower.h b/src/jit/lower.h index 128a3b7cbc..232c7b2bc0 100644 --- a/src/jit/lower.h +++ b/src/jit/lower.h @@ -77,7 +77,7 @@ private: GenTree* LowerVirtualVtableCall (GenTreeCall* call); GenTree* LowerVirtualStubCall (GenTreeCall* call); void LowerArgsForCall (GenTreeCall* call); - GenTree* NewPutArg (GenTreeCall* call, GenTreePtr arg, fgArgTabEntryPtr fp, var_types type); + GenTree* NewPutArg (GenTreeCall* call, GenTreePtr arg, fgArgTabEntryPtr info, var_types type); void LowerArg (GenTreeCall* call, GenTreePtr *ppTree); void InsertPInvokeCallProlog (GenTreeCall* call); void InsertPInvokeCallEpilog (GenTreeCall* call); diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index 78340f3ffa..cc642ec433 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -2932,7 +2932,6 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* callNode) unsigned argAlign = 1; #ifdef _TARGET_ARM_ - var_types hfaType = GetHfaType(argx); bool isHfaArg = varTypeIsFloating(hfaType); #endif // _TARGET_ARM_ @@ -4067,7 +4066,7 @@ void Compiler::fgMorphSystemVStructArgs(GenTreeCall* call, bool hasStructArgumen arg->gtOp.gtOp1->AsLclVarCommon() : arg->AsLclVarCommon(); if (fgEntryPtr->structDesc.passedInRegisters) { - if (fgEntryPtr->structDesc.eightByteCount == 1) + if (fgEntryPtr->structDesc.eightByteCount == 1) { // Change the type and below the code will change the LclVar to a LCL_FLD type = GetTypeFromClassificationAndSizes(fgEntryPtr->structDesc.eightByteClassifications[0], fgEntryPtr->structDesc.eightByteSizes[0]); @@ -4084,6 +4083,7 @@ void Compiler::fgMorphSystemVStructArgs(GenTreeCall* call, bool hasStructArgumen fgEntryPtr->structDesc.eightByteSizes[1]), lclCommon->gtLclNum, fgEntryPtr->structDesc.eightByteOffsets[1]); + // Note this should actually be: secondNode = gtNewArgList(newLclField) GenTreeArgList* secondNode = gtNewListNode(newLclField, nullptr); secondNode->gtType = originalType; // Preserve the type. It is a special case. newLclField->gtFieldSeq = FieldSeqStore::NotAField(); @@ -11054,7 +11054,7 @@ CM_ADD_OP: } // We will turn a GT_LCL_VAR into a GT_LCL_FLD with an gtLclOffs of 'ival' - // ot if we already have a GT_LCL_FLD we will adjust the gtLclOffs by adding 'ival' + // or if we already have a GT_LCL_FLD we will adjust the gtLclOffs by adding 'ival' // Then we change the type of the GT_LCL_FLD to match the orginal GT_IND type. // if (temp->OperGet() == GT_LCL_FLD) @@ -15255,7 +15255,7 @@ void Compiler::fgPromoteStructs() { if (structPromotionInfo.fieldCnt != 1) { - JITDUMP("Not promoting promotable struct local V%02u, because lvIsParam are true and #fields = %d.\n", + JITDUMP("Not promoting promotable struct local V%02u, because lvIsParam is true and #fields = %d.\n", lclNum, structPromotionInfo.fieldCnt); continue; } @@ -15333,6 +15333,7 @@ Compiler::fgWalkResult Compiler::fgMorphStructField(GenTreePtr tree, fgWalk // Promoted struct unsigned fldOffset = tree->gtField.gtFldOffset; unsigned fieldLclIndex = lvaGetFieldLocal(varDsc, fldOffset); + noway_assert(fieldLclIndex != BAD_VAR_NUM); tree->SetOper(GT_LCL_VAR); tree->gtLclVarCommon.SetLclNum(fieldLclIndex); @@ -15434,6 +15435,7 @@ Compiler::fgWalkResult Compiler::fgMorphLocalField(GenTreePtr tree, fgWalkD if (fldOffset != BAD_VAR_NUM) { fieldLclIndex = lvaGetFieldLocal(varDsc, fldOffset); + noway_assert(fieldLclIndex != BAD_VAR_NUM); fldVarDsc = &lvaTable[fieldLclIndex]; } |