Skip to content

Add checks to prevent silent bad codegen from VN optimizations. #49504

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -10266,7 +10266,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
{
// Create a CompAllocator that labels sub-structure with CMK_FieldSeqStore, and use that for allocation.
CompAllocator ialloc(getAllocator(CMK_FieldSeqStore));
compRoot->m_fieldSeqStore = new (ialloc) FieldSeqStore(ialloc);
compRoot->m_fieldSeqStore = new (ialloc) FieldSeqStore(compRoot, ialloc);
}
return compRoot->m_fieldSeqStore;
}
Expand Down
61 changes: 59 additions & 2 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11201,7 +11201,7 @@ void Compiler::gtDispFieldSeq(FieldSeqNode* pfsn)
}
else
{
printf("%s", eeGetFieldName(fldHnd));
printf("%s, %#x", eeGetFieldName(fldHnd), dspPtr(fldHnd));
}
pfsn = pfsn->m_next;
if (pfsn != nullptr)
Expand Down Expand Up @@ -18758,7 +18758,8 @@ void GenTree::LabelIndex(Compiler* comp, bool isConst)
FieldSeqNode FieldSeqStore::s_notAField(nullptr, nullptr);

// FieldSeqStore methods.
FieldSeqStore::FieldSeqStore(CompAllocator alloc) : m_alloc(alloc), m_canonMap(new (alloc) FieldSeqNodeCanonMap(alloc))
FieldSeqStore::FieldSeqStore(Compiler* comp, CompAllocator alloc)
: m_compiler(comp), m_alloc(alloc), m_canonMap(new (alloc) FieldSeqNodeCanonMap(alloc))
{
}

Expand Down Expand Up @@ -18809,6 +18810,8 @@ FieldSeqNode* FieldSeqStore::Append(FieldSeqNode* a, FieldSeqNode* b)
// We should never add a duplicate FieldSeqNode
assert(a != b);

bool lastA = (a->m_next == nullptr);

FieldSeqNode* tmp = Append(a->m_next, b);
FieldSeqNode fsn(a->m_fieldHnd, tmp);
FieldSeqNode* res = nullptr;
Expand All @@ -18818,6 +18821,12 @@ FieldSeqNode* FieldSeqStore::Append(FieldSeqNode* a, FieldSeqNode* b)
}
else
{
if (lastA && !a->IsPseudoField())
{
CORINFO_CLASS_HANDLE nextStructHnd;
m_compiler->info.compCompHnd->getFieldType(a->m_fieldHnd, &nextStructHnd);
tmp->CheckFldBelongsToCls(m_compiler, nextStructHnd);
}
res = m_alloc.allocate<FieldSeqNode>(1);
*res = fsn;
m_canonMap->Set(fsn, res);
Expand Down Expand Up @@ -18850,6 +18859,41 @@ bool FieldSeqNode::IsPseudoField() const
return m_fieldHnd == FieldSeqStore::FirstElemPseudoField || m_fieldHnd == FieldSeqStore::ConstantIndexPseudoField;
}

//------------------------------------------------------------------------
// CheckFldBelongsToCls: Check that the field sequences belongs to the class.
//
// Arguments:
// comp - a compiler instance;
// clsHnd - the class handle.
//
// Return Value:
// True if the field sequence describe a correct field accesses of the class.
//
bool FieldSeqNode::CheckFldBelongsToCls(Compiler* comp, CORINFO_CLASS_HANDLE clsHnd) const
{
if (this == FieldSeqStore::NotAField())
{
return false;
}
if (clsHnd == NO_CLASS_HANDLE)
{
return false;
}
if (IsPseudoField())
{
// Not sure about it.
return true;
}
CORINFO_CLASS_HANDLE realClsHnd = comp->info.compCompHnd->getFieldClass(m_fieldHnd);
if (realClsHnd != clsHnd)
{
return false;
}

// The rest of FieldSeq should be already checked when it was created.
return true;
}

#ifdef FEATURE_SIMD
GenTreeSIMD* Compiler::gtNewSIMDNode(
var_types type, GenTree* op1, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size)
Expand Down Expand Up @@ -19654,6 +19698,19 @@ uint16_t GenTreeLclVarCommon::GetLclOffs() const
}
}

void GenTreeLclFld::SetFieldSeq(FieldSeqNode* fieldSeq)
{
#if defined(DEBUG)
if (fieldSeq != FieldSeqStore::NotAField())
{
Compiler* comp = JitTls::GetCompiler();
const LclVarDsc* varDsc = comp->lvaGetDesc(GetLclNum());
assert(fieldSeq->CheckFldBelongsToCls(comp, varDsc->GetStructHnd()));
}
#endif // DEBUG
m_fieldSeq = fieldSeq;
}

#ifdef TARGET_ARM
//------------------------------------------------------------------------
// IsOffsetMisaligned: check if the field needs a special handling on arm.
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ struct FieldSeqNode
return tail;
}

bool CheckFldBelongsToCls(Compiler* comp, CORINFO_CLASS_HANDLE clsHnd) const;

// Make sure this provides methods that allow it to be used as a KeyFuncs type in SimplerHash.
static int GetHashCode(FieldSeqNode fsn)
{
Expand All @@ -284,6 +286,7 @@ class FieldSeqStore
{
typedef JitHashTable<FieldSeqNode, /*KeyFuncs*/ FieldSeqNode, FieldSeqNode*> FieldSeqNodeCanonMap;

Compiler* m_compiler;
CompAllocator m_alloc;
FieldSeqNodeCanonMap* m_canonMap;

Expand All @@ -294,7 +297,7 @@ class FieldSeqStore
static int ConstantIndexPseudoFieldStruct;

public:
FieldSeqStore(CompAllocator alloc);
FieldSeqStore(Compiler* comp, CompAllocator alloc);

// Returns the (canonical in the store) singleton field sequence for the given handle.
FieldSeqNode* CreateSingleton(CORINFO_FIELD_HANDLE fieldHnd);
Expand Down Expand Up @@ -3433,10 +3436,7 @@ struct GenTreeLclFld : public GenTreeLclVarCommon
return m_fieldSeq;
}

void SetFieldSeq(FieldSeqNode* fieldSeq)
{
m_fieldSeq = fieldSeq;
}
void SetFieldSeq(FieldSeqNode* fieldSeq);

#ifdef TARGET_ARM
bool IsOffsetMisaligned() const;
Expand Down
13 changes: 12 additions & 1 deletion src/coreclr/jit/lclmorph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,14 @@ class LocalAddressVisitor final : public GenTreeVisitor<LocalAddressVisitor>
addr->ChangeOper(GT_LCL_FLD_ADDR);
addr->AsLclFld()->SetLclNum(val.LclNum());
addr->AsLclFld()->SetLclOffs(val.Offset());
addr->AsLclFld()->SetFieldSeq(val.FieldSeq());
if (varTypeIsStruct(varDsc) && val.FieldSeq()->CheckFldBelongsToCls(m_compiler, varDsc->GetStructHnd()))
{
addr->AsLclFld()->SetFieldSeq(val.FieldSeq());
}
else
{
addr->AsLclFld()->SetFieldSeq(FieldSeqStore::NotAField());
}
}
else
{
Expand Down Expand Up @@ -1032,6 +1039,10 @@ class LocalAddressVisitor final : public GenTreeVisitor<LocalAddressVisitor>
indir->ChangeOper(GT_LCL_FLD);
indir->AsLclFld()->SetLclNum(val.LclNum());
indir->AsLclFld()->SetLclOffs(val.Offset());
if (fieldSeq != nullptr && !fieldSeq->CheckFldBelongsToCls(m_compiler, varDsc->GetStructHnd()))
{
fieldSeq = nullptr;
}
indir->AsLclFld()->SetFieldSeq(fieldSeq == nullptr ? FieldSeqStore::NotAField() : fieldSeq);

// Promoted struct vars aren't currently handled here so the created LCL_FLD can't be
Expand Down
Loading