Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/coreclr/jit/gentree.cpp')
-rw-r--r--src/coreclr/jit/gentree.cpp107
1 files changed, 92 insertions, 15 deletions
diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp
index 28f5a7c1ce2..8535f0e90c5 100644
--- a/src/coreclr/jit/gentree.cpp
+++ b/src/coreclr/jit/gentree.cpp
@@ -265,6 +265,7 @@ void GenTree::InitNodeSize()
GenTree::s_gtNodeSizes[GT_ARR_OFFSET] = TREE_NODE_SZ_LARGE;
GenTree::s_gtNodeSizes[GT_RET_EXPR] = TREE_NODE_SZ_LARGE;
GenTree::s_gtNodeSizes[GT_FIELD] = TREE_NODE_SZ_LARGE;
+ GenTree::s_gtNodeSizes[GT_FIELD_ADDR] = TREE_NODE_SZ_LARGE;
GenTree::s_gtNodeSizes[GT_CMPXCHG] = TREE_NODE_SZ_LARGE;
GenTree::s_gtNodeSizes[GT_QMARK] = TREE_NODE_SZ_LARGE;
GenTree::s_gtNodeSizes[GT_STORE_DYN_BLK] = TREE_NODE_SZ_LARGE;
@@ -2345,9 +2346,6 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK)
genTreeOps oper;
unsigned kind;
-// printf("tree1:\n"); gtDispTree(op1);
-// printf("tree2:\n"); gtDispTree(op2);
-
AGAIN:
if (op1 == nullptr)
@@ -2526,6 +2524,7 @@ AGAIN:
break;
case GT_FIELD:
+ case GT_FIELD_ADDR:
if (op1->AsField()->gtFldHnd != op2->AsField()->gtFldHnd)
{
return false;
@@ -3011,6 +3010,7 @@ AGAIN:
break;
case GT_FIELD:
+ case GT_FIELD_ADDR:
hash = genTreeHashAdd(hash, tree->AsField()->gtFldHnd);
break;
@@ -6578,19 +6578,13 @@ ExceptionSetFlags GenTree::OperExceptions(Compiler* comp)
return ExceptionSetFlags::IndexOutOfRangeException;
case GT_FIELD:
- {
- GenTree* fldObj = this->AsField()->GetFldObj();
-
- if (fldObj != nullptr)
+ case GT_FIELD_ADDR:
+ if (AsField()->IsInstance() && comp->fgAddrCouldBeNull(AsField()->GetFldObj()))
{
- if (comp->fgAddrCouldBeNull(fldObj))
- {
- return ExceptionSetFlags::NullReferenceException;
- }
+ return ExceptionSetFlags::NullReferenceException;
}
return ExceptionSetFlags::None;
- }
case GT_BOUNDS_CHECK:
case GT_INDEX_ADDR:
@@ -7517,6 +7511,86 @@ GenTreeRetExpr* Compiler::gtNewInlineCandidateReturnExpr(GenTreeCall* inlineCand
return node;
}
+//------------------------------------------------------------------------
+// gtNewFieldRef: Create a new GT_FIELD node.
+//
+// Normalizes struct types (for SIMD vectors). Sets GTF_GLOB_REF for fields
+// that may be pointing into globally visible memory.
+//
+// Arguments:
+// type - type for the field node
+// fldHnd - the field handle
+// obj - the instance, an address
+// offset - the field offset
+//
+// Return Value:
+// The created node.
+//
+GenTreeField* Compiler::gtNewFieldRef(var_types type, CORINFO_FIELD_HANDLE fldHnd, GenTree* obj, DWORD offset)
+{
+ // GT_FIELD nodes are transformed into GT_IND nodes.
+ assert(GenTree::s_gtNodeSizes[GT_IND] <= GenTree::s_gtNodeSizes[GT_FIELD]);
+
+ if (type == TYP_STRUCT)
+ {
+ CORINFO_CLASS_HANDLE structHnd;
+ eeGetFieldType(fldHnd, &structHnd);
+ type = impNormStructType(structHnd);
+ }
+
+ GenTreeField* fieldNode = new (this, GT_FIELD) GenTreeField(GT_FIELD, type, obj, fldHnd, offset);
+
+ // If "obj" is the address of a local, note that a field of that struct local has been accessed.
+ if ((obj != nullptr) && obj->OperIs(GT_ADDR) && varTypeIsStruct(obj->AsUnOp()->gtOp1) &&
+ obj->AsUnOp()->gtOp1->OperIs(GT_LCL_VAR))
+ {
+ LclVarDsc* varDsc = lvaGetDesc(obj->AsUnOp()->gtOp1->AsLclVarCommon());
+
+ varDsc->lvFieldAccessed = 1;
+
+ if (lvaIsImplicitByRefLocal(lvaGetLclNum(varDsc)))
+ {
+ // These structs are passed by reference and can easily become global references if those
+ // references are exposed. We clear out address-exposure information for these parameters
+ // when they are converted into references in fgRetypeImplicitByRefArgs() so we do not have
+ // the necessary information in morph to know if these indirections are actually global
+ // references, so we have to be conservative here.
+ fieldNode->gtFlags |= GTF_GLOB_REF;
+ }
+ }
+ else
+ {
+ fieldNode->gtFlags |= GTF_GLOB_REF;
+ }
+
+ return fieldNode;
+}
+
+//------------------------------------------------------------------------
+// gtNewFieldRef: Create a new GT_FIELD_ADDR node.
+//
+// Arguments:
+// type - type for the address node
+// fldHnd - the field handle
+// obj - the instance, an address
+// offset - the field offset
+//
+// Return Value:
+// The created node.
+//
+GenTreeField* Compiler::gtNewFieldAddrNode(var_types type, CORINFO_FIELD_HANDLE fldHnd, GenTree* obj, DWORD offset)
+{
+ assert(varTypeIsI(genActualType(type)));
+
+ GenTreeField* fieldNode = new (this, GT_FIELD_ADDR) GenTreeField(GT_FIELD_ADDR, type, obj, fldHnd, offset);
+
+ // TODO-ADDR: add GTF_EXCEPT handling here and delete it from callers.
+ // TODO-ADDR: delete this zero-diff quirk.
+ fieldNode->gtFlags |= GTF_GLOB_REF;
+
+ return fieldNode;
+}
+
/*****************************************************************************
*
* Create a node that will assign 'src' to 'dst'.
@@ -8627,8 +8701,10 @@ GenTree* Compiler::gtCloneExpr(
break;
case GT_FIELD:
- copy = new (this, GT_FIELD) GenTreeField(tree->TypeGet(), tree->AsField()->GetFldObj(),
- tree->AsField()->gtFldHnd, tree->AsField()->gtFldOffset);
+ case GT_FIELD_ADDR:
+ copy = new (this, tree->OperGet())
+ GenTreeField(tree->OperGet(), tree->TypeGet(), tree->AsField()->GetFldObj(),
+ tree->AsField()->gtFldHnd, tree->AsField()->gtFldOffset);
copy->AsField()->gtFldMayOverlap = tree->AsField()->gtFldMayOverlap;
#ifdef FEATURE_READYTORUN
copy->AsField()->gtFieldLookup = tree->AsField()->gtFieldLookup;
@@ -9429,6 +9505,7 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node)
// Unary operators with an optional operand
case GT_NOP:
case GT_FIELD:
+ case GT_FIELD_ADDR:
case GT_RETURN:
case GT_RETFILT:
if (m_node->AsUnOp()->gtOp1 == nullptr)
@@ -11863,7 +11940,7 @@ void Compiler::gtDispTree(GenTree* tree,
#endif // FEATURE_ARG_SPLIT
#endif // FEATURE_PUT_STRUCT_ARG_STK
- if (tree->OperIs(GT_FIELD))
+ if (tree->OperIs(GT_FIELD, GT_FIELD_ADDR))
{
printf(" %s", eeGetFieldName(tree->AsField()->gtFldHnd), 0);
}