}
#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
//
void gtGetLateArgMsg (GenTreePtr call,
GenTreePtr arg,
int argNum,
+ int listCount,
char* bufp,
unsigned bufLength);
void gtDispArgList (GenTreePtr tree,
#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)
#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)
#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_)
#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
break;
+ case GT_LIST:
case GT_NOP:
costEx = 0;
costSz = 0;
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:
//assert(lnum < lvaCount);
+ node->gtFieldSeq = FieldSeqStore::NotAField();
return node;
}
* 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);
}
/*****************************************************************************
* 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));
}
/*****************************************************************************
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
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)
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)
{
}
printf("\n");
- printf(" ");
+ printf(" ");
printIndent(indentStack);
printf(" %-6s V%02u.%s (offs=0x%02x) -> ",
varTypeName(fieldVarDsc->TypeGet()),
fieldVarDsc->PrintVarReg();
}
- if ((fieldVarDsc->lvTracked) &&
+ if (fieldVarDsc->lvTracked &&
fgLocalVarLivenessDone && // Includes local variable liveness
((tree->gtFlags & GTF_VAR_DEATH) != 0))
{
}
}
}
-
- 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:
varNum = tree->gtRegVar.gtLclNum;
varDsc = &lvaTable[varNum];
- if ((varDsc->lvTracked) &&
+ if (varDsc->lvTracked &&
fgLocalVarLivenessDone &&
((tree->gtFlags & GTF_VAR_DEATH) != 0))
{
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);
}
}
// 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
//
void Compiler::gtGetLateArgMsg(GenTreePtr call,
GenTreePtr argx,
int lateArgIndex,
+ int listCount,
char* bufp,
unsigned bufLength)
{
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);
+ }
+ }
}
}
// 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)
{
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();
else
{
assert(child == tree->gtCall.gtCallLateArgs);
- gtGetLateArgMsg(tree, listElem, listElemNum, bufp, BufLength);
+ gtGetLateArgMsg(tree, listElem, listElemNum, -1, bufp, BufLength);
}
}
else
static
inline bool RequiresNonNullOp2(genTreeOps oper);
- bool IsListOfLclFlds();
+ bool IsListForMultiRegArg();
#endif // DEBUG
inline bool IsZero();
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;
+ }
}
};
}
#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;
}
}
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
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
}
}
- 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;
}
#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();
{
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
// 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:
// 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)
// 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;
#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.
// 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.
//
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 :
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
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);
}
// 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
// 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)
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();
}
}
else if (updateArgTable)
{
- fp->node = putArg;
+ info->node = putArg;
}
return putArg;
}
#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))
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;
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.)
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);
unsigned argAlign = 1;
#ifdef _TARGET_ARM_
-
var_types hfaType = GetHfaType(argx);
bool isHfaArg = varTypeIsFloating(hfaType);
#endif // _TARGET_ARM_
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]);
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();
}
// 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)
{
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;
}
// 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);
if (fldOffset != BAD_VAR_NUM)
{
fieldLclIndex = lvaGetFieldLocal(varDsc, fldOffset);
+ noway_assert(fieldLclIndex != BAD_VAR_NUM);
fldVarDsc = &lvaTable[fieldLclIndex];
}