* Move CodeGen::indirForm and IntForm to common.
* GenTreeFieldList: SetContained only for the head.
* delete the workaround.
* move check from isContained to CheckLIR
`isContained` can't determinate does node has user or not. Move this check to the appropriate place.
* check that SetContained and IsContained are consistent.
genProduceReg(arrOffset);
}
-//------------------------------------------------------------------------
-// indirForm: Make a temporary indir we can feed to pattern matching routines
-// in cases where we don't want to instantiate all the indirs that happen.
-//
-GenTreeIndir CodeGen::indirForm(var_types type, GenTree* base)
-{
- GenTreeIndir i(GT_IND, type, base, nullptr);
- i.gtRegNum = REG_NA;
- i.SetContained();
- // has to be nonnull (because contained nodes can't be the last in block)
- // but don't want it to be a valid pointer
- i.gtNext = (GenTree*)(-1);
- return i;
-}
-
-//------------------------------------------------------------------------
-// intForm: Make a temporary int we can feed to pattern matching routines
-// in cases where we don't want to instantiate.
-//
-GenTreeIntCon CodeGen::intForm(var_types type, ssize_t value)
-{
- GenTreeIntCon i(type, value);
- i.gtRegNum = REG_NA;
- // has to be nonnull (because contained nodes can't be the last in block)
- // but don't want it to be a valid pointer
- i.gtNext = (GenTree*)(-1);
- return i;
-}
-
//------------------------------------------------------------------------
// genCodeForShift: Generates the code sequence for a GenTree node that
// represents a bit shift or rotate operation (<<, >>, >>>, rol, ror).
GenTreeAddrMode arrLenAddr(base->TypeGet(), base, nullptr, 0, static_cast<unsigned>(node->gtLenOffset));
arrLenAddr.gtRegNum = REG_NA;
arrLenAddr.SetContained();
- arrLenAddr.gtNext = (GenTree*)(-1);
GenTreeIndir arrLen = indirForm(TYP_INT, &arrLenAddr);
arrLen.gtRegNum = tmpReg;
#endif // !defined(DEBUG)
#endif // defined(LATE_DISASM)
/*****************************************************************************/
+
+#ifndef LEGACY_BACKEND
+
+//------------------------------------------------------------------------
+// indirForm: Make a temporary indir we can feed to pattern matching routines
+// in cases where we don't want to instantiate all the indirs that happen.
+//
+GenTreeIndir CodeGen::indirForm(var_types type, GenTree* base)
+{
+ GenTreeIndir i(GT_IND, type, base, nullptr);
+ i.gtRegNum = REG_NA;
+ i.SetContained();
+ return i;
+}
+
+//------------------------------------------------------------------------
+// intForm: Make a temporary int we can feed to pattern matching routines
+// in cases where we don't want to instantiate.
+//
+GenTreeIntCon CodeGen::intForm(var_types type, ssize_t value)
+{
+ GenTreeIntCon i(type, value);
+ i.gtRegNum = REG_NA;
+ return i;
+}
+
+#endif // !LEGACY_BACKEND
genProduceReg(arrOffset);
}
-// make a temporary indir we can feed to pattern matching routines
-// in cases where we don't want to instantiate all the indirs that happen
-//
-GenTreeIndir CodeGen::indirForm(var_types type, GenTree* base)
-{
- GenTreeIndir i(GT_IND, type, base, nullptr);
- i.gtRegNum = REG_NA;
- i.SetContained();
- // has to be nonnull (because contained nodes can't be the last in block)
- // but don't want it to be a valid pointer
- i.gtNext = (GenTree*)(-1);
- return i;
-}
-
-// make a temporary int we can feed to pattern matching routines
-// in cases where we don't want to instantiate
-//
-GenTreeIntCon CodeGen::intForm(var_types type, ssize_t value)
-{
- GenTreeIntCon i(type, value);
- i.gtRegNum = REG_NA;
- // has to be nonnull (because contained nodes can't be the last in block)
- // but don't want it to be a valid pointer
- i.gtNext = (GenTree*)(-1);
- return i;
-}
-
instruction CodeGen::genGetInsForOper(genTreeOps oper, var_types type)
{
instruction ins;
GenTreeAddrMode arrLenAddr(base->TypeGet(), base, nullptr, 0, node->gtLenOffset);
arrLenAddr.gtRegNum = REG_NA;
arrLenAddr.SetContained();
- arrLenAddr.gtNext = (GenTree*)(-1);
GenTreeIndir arrLen = indirForm(TYP_INT, &arrLenAddr);
arrLen.gtRegNum = REG_NA;
arrLen.SetContained();
- arrLen.gtNext = (GenTree*)(-1);
}
// Generate the range check.
assert(!isMarkedContained);
}
- // if it's contained it better have a user
+ // if it's contained it can't be unused.
if (isMarkedContained)
{
- assert(gtNext != nullptr);
+ assert(!IsUnusedValue());
}
#endif // DEBUG
return isMarkedContained;
{
assert(IsValue());
gtFlags |= GTF_CONTAINED;
+ assert(isContained());
}
void ClearContained()
if (prevList == nullptr)
{
gtFlags |= GTF_FIELD_LIST_HEAD;
+#ifndef LEGACY_BACKEND
+ // A GT_FIELD_LIST head is always contained. Other nodes return false from IsValue()
+ // and should not be marked as contained.
+ SetContained();
+#endif
}
else
{
prevList->gtOp2 = this;
}
-#ifndef LEGACY_BACKEND
- // A GT_FIELD_LIST is always contained. Note that this should only matter for the head node, but
- // the list may be reordered.
- gtFlags |= GTF_CONTAINED;
-#endif
}
};
{
GenTree* node = kvp.Key();
assert(node->IsUnusedValue() && "found an unmarked unused value");
+ assert(!node->isContained() && "a contained node should have a user");
}
}
if (head != fieldList)
{
head->gtFlags |= GTF_FIELD_LIST_HEAD;
+ head->SetContained();
+
+ fieldList->ClearContained();
fieldList->gtFlags &= ~GTF_FIELD_LIST_HEAD;
#ifdef DEBUG