Skip to content

Commit 62cd176

Browse files
committed
Handle various edge cases that were technically UB
1 parent d30610a commit 62cd176

1 file changed

Lines changed: 40 additions & 33 deletions

File tree

src/coreclr/jit/gentree.cpp

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14985,7 +14985,7 @@ GenTree* Compiler::gtFoldExpr(GenTree* tree)
1498514985
}
1498614986

1498714987
//------------------------------------------------------------------------
14988-
// gtFoldExprUnary: see if an unary operation is foldable
14988+
// gtFoldExprUnary: see if a unary operation is foldable
1498914989
//
1499014990
// Arguments:
1499114991
// tree - tree to examine
@@ -16964,7 +16964,7 @@ GenTree* Compiler::gtFoldExprConst(GenTree* tree)
1696416964
}
1696516965

1696616966
//------------------------------------------------------------------------
16967-
// gtFoldExprUnaryConst: see if an unary const operation is foldable
16967+
// gtFoldExprUnaryConst: see if a unary const operation is foldable
1696816968
//
1696916969
// Arguments:
1697016970
// tree - tree to examine
@@ -17013,7 +17013,7 @@ GenTree* Compiler::gtFoldExprUnaryConst(GenTreeUnOp* tree)
1701317013
}
1701417014

1701517015
//------------------------------------------------------------------------
17016-
// gtFoldExprUnaryConst: see if an unary const operation for TYP_INT is foldable
17016+
// gtFoldExprUnaryConst: see if a unary const operation for TYP_INT is foldable
1701717017
//
1701817018
// Arguments:
1701917019
// tree - tree to examine
@@ -17050,14 +17050,15 @@ GenTree* Compiler::gtFoldExprUnaryConstInt(GenTreeUnOp* tree, GenTreeIntCon* int
1705017050

1705117051
case GT_NEG:
1705217052
{
17053-
iconVal = -iconVal;
17053+
iconVal = static_cast<int32_t>(0 - static_cast<uint32_t>(iconVal));
1705417054
break;
1705517055
}
1705617056

1705717057
case GT_BSWAP:
1705817058
{
17059-
iconVal = ((iconVal >> 24) & 0xFF) | ((iconVal >> 8) & 0xFF00) | ((iconVal << 8) & 0xFF0000) |
17060-
((iconVal << 24) & 0xFF000000);
17059+
uint32_t uconVal = static_cast<uint32_t>(iconVal);
17060+
iconVal = static_cast<int32_t>(((uconVal >> 24) & 0xFF) | ((uconVal >> 8) & 0xFF00) |
17061+
((uconVal << 8) & 0xFF0000) | ((uconVal << 24) & 0xFF000000));
1706117062
break;
1706217063
}
1706317064

@@ -17172,7 +17173,7 @@ GenTree* Compiler::gtFoldExprUnaryConstInt(GenTreeUnOp* tree, GenTreeIntCon* int
1717217173
}
1717317174

1717417175
//------------------------------------------------------------------------
17175-
// gtFoldExprUnaryConst: see if an unary const operation for TYP_LONG is foldable
17176+
// gtFoldExprUnaryConst: see if a unary const operation for TYP_LONG is foldable
1717617177
//
1717717178
// Arguments:
1717817179
// tree - tree to examine
@@ -17209,16 +17210,17 @@ GenTree* Compiler::gtFoldExprUnaryConstLng(GenTreeUnOp* tree, GenTreeIntConCommo
1720917210

1721017211
case GT_NEG:
1721117212
{
17212-
lconVal = -lconVal;
17213+
lconVal = static_cast<int64_t>(0 - static_cast<uint64_t>(lconVal));
1721317214
break;
1721417215
}
1721517216

1721617217
case GT_BSWAP:
1721717218
{
17218-
lconVal = ((lconVal >> 56) & 0xFF) | ((lconVal >> 40) & 0xFF00) | ((lconVal >> 24) & 0xFF0000) |
17219-
((lconVal >> 8) & 0xFF000000) | ((lconVal << 8) & 0xFF00000000) |
17220-
((lconVal << 24) & 0xFF0000000000) | ((lconVal << 40) & 0xFF000000000000) |
17221-
((lconVal << 56) & 0xFF00000000000000);
17219+
uint64_t uconVal = static_cast<uint64_t>(lconVal);
17220+
lconVal = static_cast<int64_t>(
17221+
((uconVal >> 56) & 0xFF) | ((uconVal >> 40) & 0xFF00) | ((uconVal >> 24) & 0xFF0000) |
17222+
((uconVal >> 8) & 0xFF000000) | ((uconVal << 8) & 0xFF00000000) | ((uconVal << 24) & 0xFF0000000000) |
17223+
((uconVal << 40) & 0xFF000000000000) | ((uconVal << 56) & 0xFF00000000000000));
1722217224
break;
1722317225
}
1722417226

@@ -17326,7 +17328,7 @@ GenTree* Compiler::gtFoldExprUnaryConstLng(GenTreeUnOp* tree, GenTreeIntConCommo
1732617328
}
1732717329

1732817330
//------------------------------------------------------------------------
17329-
// gtFoldExprUnaryConstDbl: see if an unary const operation for TYP_DOUBLE or TYP_FLOAT is foldable
17331+
// gtFoldExprUnaryConstDbl: see if a unary const operation for TYP_DOUBLE or TYP_FLOAT is foldable
1733017332
//
1733117333
// Arguments:
1733217334
// tree - tree to examine
@@ -17744,7 +17746,7 @@ GenTree* Compiler::gtFoldExprBinaryConstInt(GenTreeOp* tree, GenTreeIntCon* intC
1774417746
return gtFoldExprForOverflow(tree);
1774517747
}
1774617748

17747-
iconVal1 += iconVal2;
17749+
iconVal1 = static_cast<int32_t>(static_cast<uint32_t>(iconVal1) + static_cast<uint32_t>(iconVal2));
1774817750

1774917751
FieldSeq* fieldSeq = GetFieldSeqStore()->Append(intCon1->gtFieldSeq, intCon2->gtFieldSeq);
1775017752
return gtBashTreeToConstInt(tree, iconVal1, fieldSeq);
@@ -17757,7 +17759,7 @@ GenTree* Compiler::gtFoldExprBinaryConstInt(GenTreeOp* tree, GenTreeIntCon* intC
1775717759
return gtFoldExprForOverflow(tree);
1775817760
}
1775917761

17760-
iconVal1 -= iconVal2;
17762+
iconVal1 = static_cast<int32_t>(static_cast<uint32_t>(iconVal1) - static_cast<uint32_t>(iconVal2));
1776117763
break;
1776217764
}
1776317765

@@ -17768,7 +17770,7 @@ GenTree* Compiler::gtFoldExprBinaryConstInt(GenTreeOp* tree, GenTreeIntCon* intC
1776817770
return gtFoldExprForOverflow(tree);
1776917771
}
1777017772

17771-
iconVal1 *= iconVal2;
17773+
iconVal1 = static_cast<int32_t>(static_cast<uint32_t>(iconVal1) * static_cast<uint32_t>(iconVal2));
1777217774
break;
1777317775
}
1777417776

@@ -17810,17 +17812,17 @@ GenTree* Compiler::gtFoldExprBinaryConstInt(GenTreeOp* tree, GenTreeIntCon* intC
1781017812

1781117813
case GT_ROL:
1781217814
{
17815+
uint32_t uconVal1 = static_cast<uint32_t>(iconVal1);
1781317816
iconVal2 &= 0x1F;
17814-
iconVal1 = (iconVal1 << iconVal2) |
17815-
static_cast<int32_t>(static_cast<uint32_t>(iconVal1) >> ((32 - iconVal2) & 0x1F));
17817+
iconVal1 = static_cast<int32_t>((uconVal1 << iconVal2) | (uconVal1 >> ((32 - iconVal2) & 0x1F)));
1781617818
break;
1781717819
}
1781817820

1781917821
case GT_ROR:
1782017822
{
17823+
uint32_t uconVal1 = static_cast<uint32_t>(iconVal1);
1782117824
iconVal2 &= 0x1F;
17822-
iconVal1 = (iconVal1 << ((32 - iconVal2) & 0x1F)) |
17823-
static_cast<int32_t>(static_cast<uint32_t>(iconVal1) >> iconVal2);
17825+
iconVal1 = static_cast<int32_t>((uconVal1 << ((32 - iconVal2) & 0x1F)) | (uconVal1 >> iconVal2));
1782417826
break;
1782517827
}
1782617828

@@ -17872,7 +17874,7 @@ GenTree* Compiler::gtFoldExprBinaryConstInt(GenTreeOp* tree, GenTreeIntCon* intC
1787217874
}
1787317875

1787417876
//------------------------------------------------------------------------
17875-
// gtFoldExprBinaryConstInt: see if a binary const operation for TYP_LONG is foldable
17877+
// gtFoldExprBinaryConstLng: see if a binary const operation for TYP_LONG is foldable
1787617878
//
1787717879
// Arguments:
1787817880
// tree - tree to examine
@@ -17993,7 +17995,7 @@ GenTree* Compiler::gtFoldExprBinaryConstLng(GenTreeOp* tree,
1799317995
return gtFoldExprForOverflow(tree);
1799417996
}
1799517997

17996-
lconVal1 += lconVal2;
17998+
lconVal1 = static_cast<int64_t>(static_cast<uint64_t>(lconVal1) + static_cast<uint64_t>(lconVal2));
1799717999

1799818000
#if defined(TARGET_64BIT)
1799918001
FieldSeq* fieldSeq = GetFieldSeqStore()->Append(intConCommon1->AsIntCon()->gtFieldSeq,
@@ -18011,7 +18013,7 @@ GenTree* Compiler::gtFoldExprBinaryConstLng(GenTreeOp* tree,
1801118013
return gtFoldExprForOverflow(tree);
1801218014
}
1801318015

18014-
lconVal1 -= lconVal2;
18016+
lconVal1 = static_cast<int64_t>(static_cast<uint64_t>(lconVal1) - static_cast<uint64_t>(lconVal2));
1801518017
break;
1801618018
}
1801718019

@@ -18022,7 +18024,7 @@ GenTree* Compiler::gtFoldExprBinaryConstLng(GenTreeOp* tree,
1802218024
return gtFoldExprForOverflow(tree);
1802318025
}
1802418026

18025-
lconVal1 *= lconVal2;
18027+
lconVal1 = static_cast<int64_t>(static_cast<uint64_t>(lconVal1) * static_cast<uint64_t>(lconVal2));
1802618028
break;
1802718029
}
1802818030

@@ -18064,17 +18066,17 @@ GenTree* Compiler::gtFoldExprBinaryConstLng(GenTreeOp* tree,
1806418066

1806518067
case GT_ROL:
1806618068
{
18069+
uint64_t uconVal1 = static_cast<uint64_t>(lconVal1);
1806718070
lconVal2 &= 0x3F;
18068-
lconVal1 = (lconVal1 << lconVal2) |
18069-
static_cast<int64_t>(static_cast<uint64_t>(lconVal1) >> ((64 - lconVal2) & 0x3F));
18071+
lconVal1 = static_cast<int64_t>((uconVal1 << lconVal2) | (uconVal1 >> ((64 - lconVal2) & 0x3F)));
1807018072
break;
1807118073
}
1807218074

1807318075
case GT_ROR:
1807418076
{
18077+
uint64_t uconVal1 = static_cast<uint64_t>(lconVal1);
1807518078
lconVal2 &= 0x3F;
18076-
lconVal1 = (lconVal1 << ((64 - lconVal2) & 0x3F)) |
18077-
static_cast<int64_t>(static_cast<uint64_t>(lconVal1) >> lconVal2);
18079+
lconVal1 = static_cast<int64_t>((uconVal1 << ((64 - lconVal2) & 0x3F)) | (uconVal1 >> lconVal2));
1807818080
break;
1807918081
}
1808018082

@@ -18126,12 +18128,12 @@ GenTree* Compiler::gtFoldExprBinaryConstLng(GenTreeOp* tree,
1812618128
}
1812718129

1812818130
//------------------------------------------------------------------------
18129-
// gtFoldExprBinaryConstInt: see if a binary const operation for TYP_INT is foldable
18131+
// gtFoldExprBinaryConstDbl: see if a binary const operation for TYP_DOUBLE or TYP_FLOAT is foldable
1813018132
//
1813118133
// Arguments:
1813218134
// tree - tree to examine
18133-
// intCon1 - the first integer constant operand for tree
18134-
// intCon2 - the second integer constant operand for tree
18135+
// dblCon1 - the first floating-point constant operand for tree
18136+
// dblCon2 - the second floating-point constant operand for tree
1813518137
//
1813618138
// Returns:
1813718139
// The original tree if no folding happened.
@@ -18234,6 +18236,12 @@ GenTree* Compiler::gtFoldExprBinaryConstDbl(GenTreeOp* tree, GenTreeDblCon* dblC
1823418236

1823518237
case GT_DIV:
1823618238
{
18239+
if (dconVal2 == 0)
18240+
{
18241+
// We do not fold division by zero, even for floating point.
18242+
// This is because the result will be platform-dependent for an expression like 0d / 0d.
18243+
return tree;
18244+
}
1823718245
dconVal1 /= dconVal2;
1823818246
break;
1823918247
}
@@ -18325,7 +18333,6 @@ GenTree* Compiler::gtBashTreeToConstLng(GenTree* tree, int64_t lconVal, FieldSeq
1832518333
// Arguments:
1832618334
// tree - the tree to bash
1832718335
// dconVal - the value of the constant
18328-
// fieldSeq - the field sequence, if any
1832918336
//
1833018337
// Returns:
1833118338
// tree, bashed to GT_CNS_DBL node
@@ -33315,7 +33322,7 @@ bool GenTree::IsVectorPerElementMask(var_types simdBaseType, unsigned simdSize)
3331533322

3331633323
case GT_NOT:
3331733324
{
33318-
// We are an unary bitwise operation where the input is a per-element mask
33325+
// We are a unary bitwise operation where the input is a per-element mask
3331933326
return intrinsic->Op(1)->IsVectorPerElementMask(simdBaseType, simdSize);
3332033327
}
3332133328

0 commit comments

Comments
 (0)