@@ -11591,38 +11591,39 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
11591
11591
}
11592
11592
else
11593
11593
{
11594
+ GenTree* dstFldAddr;
11594
11595
if (addrSpill)
11595
11596
{
11596
11597
assert(addrSpillTemp != BAD_VAR_NUM);
11597
- dstFld = gtNewLclvNode(addrSpillTemp, TYP_BYREF);
11598
+ dstFldAddr = gtNewLclvNode(addrSpillTemp, TYP_BYREF);
11598
11599
}
11599
11600
else
11600
11601
{
11601
11602
if (i == 0)
11602
11603
{
11603
11604
// Use the orginal destAddr tree when i == 0
11604
- dstFld = destAddr;
11605
+ dstFldAddr = destAddr;
11605
11606
}
11606
11607
else
11607
11608
{
11608
11609
// We can't clone multiple copies of a tree with persistent side effects
11609
11610
noway_assert((destAddr->gtFlags & GTF_PERSISTENT_SIDE_EFFECTS) == 0);
11610
11611
11611
- dstFld = gtCloneExpr(destAddr);
11612
- noway_assert(dstFld != nullptr);
11612
+ dstFldAddr = gtCloneExpr(destAddr);
11613
+ noway_assert(dstFldAddr != nullptr);
11613
11614
11614
- JITDUMP("dstFld - Multiple Fields Clone created:\n");
11615
- DISPTREE(dstFld );
11615
+ JITDUMP("dstFldAddr - Multiple Fields Clone created:\n");
11616
+ DISPTREE(dstFldAddr );
11616
11617
11617
11618
// Morph the newly created tree
11618
- dstFld = fgMorphTree(dstFld );
11619
+ dstFldAddr = fgMorphTree(dstFldAddr );
11619
11620
}
11620
11621
11621
11622
// Is the address of a local?
11622
11623
GenTreeLclVarCommon* lclVarTree = nullptr;
11623
11624
bool isEntire = false;
11624
11625
bool* pIsEntire = (blockWidthIsConst ? &isEntire : nullptr);
11625
- if (dstFld ->DefinesLocalAddr(this, blockWidth, &lclVarTree, pIsEntire))
11626
+ if (dstFldAddr ->DefinesLocalAddr(this, blockWidth, &lclVarTree, pIsEntire))
11626
11627
{
11627
11628
lclVarTree->gtFlags |= GTF_VAR_DEF;
11628
11629
if (!isEntire)
@@ -11636,33 +11637,44 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
11636
11637
unsigned srcFieldLclNum = srcVarDsc->lvFieldLclStart + i;
11637
11638
LclVarDsc* srcFieldVarDsc = lvaGetDesc(srcFieldLclNum);
11638
11639
11639
- // Have to set the field sequence -- which means we need the field handle.
11640
- CORINFO_CLASS_HANDLE classHnd = srcVarDsc->GetStructHnd();
11641
- CORINFO_FIELD_HANDLE fieldHnd =
11642
- info.compCompHnd->getFieldInClass(classHnd, srcFieldVarDsc->lvFldOrdinal);
11643
- FieldSeqNode* curFieldSeq = GetFieldSeqStore()->CreateSingleton(fieldHnd);
11640
+ CORINFO_CLASS_HANDLE srcClassHnd = srcVarDsc->GetStructHnd();
11641
+ CORINFO_CLASS_HANDLE dstClassHnd = gtGetStructHandleIfPresent(dest);
11642
+
11643
+ FieldSeqNode* curFieldSeq;
11644
+
11645
+ if (srcClassHnd == dstClassHnd)
11646
+ {
11647
+ CORINFO_FIELD_HANDLE fieldHnd =
11648
+ info.compCompHnd->getFieldInClass(dstClassHnd, srcFieldVarDsc->lvFldOrdinal);
11649
+ curFieldSeq = GetFieldSeqStore()->CreateSingleton(fieldHnd);
11650
+ }
11651
+ else
11652
+ {
11653
+ // source field handle won't match an actual field in the dst.
11654
+ curFieldSeq = FieldSeqStore::NotAField();
11655
+ }
11644
11656
11645
11657
unsigned srcFieldOffset = lvaGetDesc(srcFieldLclNum)->lvFldOffset;
11646
11658
11647
11659
if (srcFieldOffset == 0)
11648
11660
{
11649
- fgAddFieldSeqForZeroOffset(dstFld , curFieldSeq);
11661
+ fgAddFieldSeqForZeroOffset(dstFldAddr , curFieldSeq);
11650
11662
}
11651
11663
else
11652
11664
{
11653
11665
GenTree* fieldOffsetNode = gtNewIconNode(srcFieldVarDsc->lvFldOffset, curFieldSeq);
11654
- dstFld = gtNewOperNode(GT_ADD, TYP_BYREF, dstFld , fieldOffsetNode);
11666
+ dstFldAddr = gtNewOperNode(GT_ADD, TYP_BYREF, dstFldAddr , fieldOffsetNode);
11655
11667
}
11656
11668
11657
- dstFld = gtNewIndir(srcFieldVarDsc->TypeGet(), dstFld );
11669
+ dstFld = gtNewIndir(srcFieldVarDsc->TypeGet(), dstFldAddr );
11658
11670
11659
11671
// !!! The destination could be on stack. !!!
11660
11672
// This flag will let us choose the correct write barrier.
11661
11673
dstFld->gtFlags |= GTF_IND_TGTANYWHERE;
11662
11674
}
11663
11675
}
11664
11676
11665
- GenTree* srcFld;
11677
+ GenTree* srcFld = DUMMY_INIT(NULL) ;
11666
11678
if (srcDoFldAsg)
11667
11679
{
11668
11680
noway_assert(srcLclNum != BAD_VAR_NUM);
@@ -11688,39 +11700,53 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
11688
11700
}
11689
11701
else
11690
11702
{
11703
+ GenTree* srcFldAddr = nullptr;
11691
11704
if (addrSpill)
11692
11705
{
11693
11706
assert(addrSpillTemp != BAD_VAR_NUM);
11694
- srcFld = gtNewLclvNode(addrSpillTemp, TYP_BYREF);
11707
+ srcFldAddr = gtNewLclvNode(addrSpillTemp, TYP_BYREF);
11695
11708
}
11696
11709
else
11697
11710
{
11698
11711
if (i == 0)
11699
11712
{
11700
11713
// Use the orginal srcAddr tree when i == 0
11701
- srcFld = srcAddr;
11714
+ srcFldAddr = srcAddr;
11702
11715
}
11703
11716
else
11704
11717
{
11705
11718
// We can't clone multiple copies of a tree with persistent side effects
11706
11719
noway_assert((srcAddr->gtFlags & GTF_PERSISTENT_SIDE_EFFECTS) == 0);
11707
11720
11708
- srcFld = gtCloneExpr(srcAddr);
11709
- noway_assert(srcFld != nullptr);
11721
+ srcFldAddr = gtCloneExpr(srcAddr);
11722
+ noway_assert(srcFldAddr != nullptr);
11710
11723
11711
11724
JITDUMP("srcFld - Multiple Fields Clone created:\n");
11712
- DISPTREE(srcFld );
11725
+ DISPTREE(srcFldAddr );
11713
11726
11714
11727
// Morph the newly created tree
11715
- srcFld = fgMorphTree(srcFld );
11728
+ srcFldAddr = fgMorphTree(srcFldAddr );
11716
11729
}
11717
11730
}
11718
11731
11719
- CORINFO_CLASS_HANDLE classHnd = lvaTable[destLclNum].GetStructHnd();
11720
- CORINFO_FIELD_HANDLE fieldHnd =
11721
- info.compCompHnd->getFieldInClass(classHnd, lvaTable[dstFieldLclNum].lvFldOrdinal);
11722
- FieldSeqNode* curFieldSeq = GetFieldSeqStore()->CreateSingleton(fieldHnd);
11723
- var_types destType = lvaGetDesc(dstFieldLclNum)->lvType;
11732
+ CORINFO_CLASS_HANDLE dstClassHnd = lvaTable[destLclNum].GetStructHnd();
11733
+ CORINFO_CLASS_HANDLE srcClassHnd = gtGetStructHandleIfPresent(src);
11734
+
11735
+ FieldSeqNode* curFieldSeq;
11736
+
11737
+ if (srcClassHnd == dstClassHnd)
11738
+ {
11739
+ CORINFO_FIELD_HANDLE fieldHnd =
11740
+ info.compCompHnd->getFieldInClass(dstClassHnd, lvaTable[dstFieldLclNum].lvFldOrdinal);
11741
+ curFieldSeq = GetFieldSeqStore()->CreateSingleton(fieldHnd);
11742
+ }
11743
+ else
11744
+ {
11745
+ // source field handle won't match an actual field in the dst.
11746
+ curFieldSeq = FieldSeqStore::NotAField();
11747
+ }
11748
+
11749
+ var_types destType = lvaGetDesc(dstFieldLclNum)->lvType;
11724
11750
11725
11751
bool done = false;
11726
11752
if (lvaGetDesc(dstFieldLclNum)->lvFldOffset == 0)
@@ -11740,7 +11766,7 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
11740
11766
srcLclVarTree->gtFlags |= GTF_VAR_CAST;
11741
11767
srcLclVarTree->ChangeOper(GT_LCL_FLD);
11742
11768
srcLclVarTree->gtType = destType;
11743
- srcLclVarTree->AsLclFld()->SetFieldSeq(curFieldSeq );
11769
+ srcLclVarTree->AsLclFld()->SetFieldSeq(FieldSeqStore::NotAField() );
11744
11770
srcFld = srcLclVarTree;
11745
11771
done = true;
11746
11772
}
@@ -11751,14 +11777,14 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
11751
11777
unsigned fldOffset = lvaGetDesc(dstFieldLclNum)->lvFldOffset;
11752
11778
if (fldOffset == 0)
11753
11779
{
11754
- fgAddFieldSeqForZeroOffset(srcFld , curFieldSeq);
11780
+ fgAddFieldSeqForZeroOffset(srcFldAddr , curFieldSeq);
11755
11781
}
11756
11782
else
11757
11783
{
11758
11784
GenTreeIntCon* fldOffsetNode = gtNewIconNode(fldOffset, curFieldSeq);
11759
- srcFld = gtNewOperNode(GT_ADD, TYP_BYREF, srcFld , fldOffsetNode);
11785
+ srcFldAddr = gtNewOperNode(GT_ADD, TYP_BYREF, srcFldAddr , fldOffsetNode);
11760
11786
}
11761
- srcFld = gtNewIndir(destType, srcFld );
11787
+ srcFld = gtNewIndir(destType, srcFldAddr );
11762
11788
}
11763
11789
}
11764
11790
}
@@ -14604,19 +14630,29 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
14604
14630
lclFld = temp->AsLclFld();
14605
14631
lclFld->SetLclOffs(static_cast<unsigned>(ival1));
14606
14632
14633
+ FieldSeqNode* newFldSeq;
14634
+
14607
14635
if (lclFld->GetFieldSeq() == FieldSeqStore::NotAField())
14608
14636
{
14609
14637
if (fieldSeq != nullptr)
14610
14638
{
14611
- // If it does represent a field, note that.
14612
- lclFld->SetFieldSeq(fieldSeq);
14639
+ newFldSeq = fieldSeq;
14640
+ }
14641
+ else
14642
+ {
14643
+ newFldSeq = FieldSeqStore::NotAField();
14613
14644
}
14614
14645
}
14615
14646
else
14616
14647
{
14617
- // Append 'fieldSeq' to the existing one
14618
- lclFld->SetFieldSeq(GetFieldSeqStore()->Append(lclFld->GetFieldSeq(), fieldSeq));
14648
+ newFldSeq = GetFieldSeqStore()->Append(lclFld->GetFieldSeq(), fieldSeq);
14649
+ }
14650
+ const LclVarDsc* varDsc = lvaGetDesc(lclFld);
14651
+ if (!varTypeIsStruct(varDsc) || !newFldSeq->CheckFldBelongsToCls(this, varDsc->GetStructHnd()))
14652
+ {
14653
+ newFldSeq = FieldSeqStore::NotAField();
14619
14654
}
14655
+ lclFld->SetFieldSeq(newFldSeq);
14620
14656
}
14621
14657
temp->gtType = tree->gtType;
14622
14658
foldAndReturnTemp = true;
0 commit comments