diff options
Diffstat (limited to 'src/coreclr/jit/gentree.cpp')
-rw-r--r-- | src/coreclr/jit/gentree.cpp | 107 |
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); } |