Skip to content

Commit 4188648

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

1 file changed

Lines changed: 43 additions & 35 deletions

File tree

src/coreclr/jit/gentree.cpp

Lines changed: 43 additions & 35 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

@@ -17160,6 +17161,7 @@ GenTree* Compiler::gtFoldExprUnaryConstInt(GenTreeUnOp* tree, GenTreeIntCon* int
1716017161
return tree;
1716117162
}
1716217163
}
17164+
break;
1716317165
}
1716417166

1716517167
default:
@@ -17172,7 +17174,7 @@ GenTree* Compiler::gtFoldExprUnaryConstInt(GenTreeUnOp* tree, GenTreeIntCon* int
1717217174
}
1717317175

1717417176
//------------------------------------------------------------------------
17175-
// gtFoldExprUnaryConst: see if an unary const operation for TYP_LONG is foldable
17177+
// gtFoldExprUnaryConst: see if a unary const operation for TYP_LONG is foldable
1717617178
//
1717717179
// Arguments:
1717817180
// tree - tree to examine
@@ -17209,16 +17211,17 @@ GenTree* Compiler::gtFoldExprUnaryConstLng(GenTreeUnOp* tree, GenTreeIntConCommo
1720917211

1721017212
case GT_NEG:
1721117213
{
17212-
lconVal = -lconVal;
17214+
lconVal = static_cast<int64_t>(0 - static_cast<uint64_t>(lconVal));
1721317215
break;
1721417216
}
1721517217

1721617218
case GT_BSWAP:
1721717219
{
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);
17220+
uint64_t uconVal = static_cast<uint64_t>(lconVal);
17221+
lconVal = static_cast<int64_t>(
17222+
((uconVal >> 56) & 0xFF) | ((uconVal >> 40) & 0xFF00) | ((uconVal >> 24) & 0xFF0000) |
17223+
((uconVal >> 8) & 0xFF000000) | ((uconVal << 8) & 0xFF00000000) | ((uconVal << 24) & 0xFF0000000000) |
17224+
((uconVal << 40) & 0xFF000000000000) | ((uconVal << 56) & 0xFF00000000000000));
1722217225
break;
1722317226
}
1722417227

@@ -17326,7 +17329,7 @@ GenTree* Compiler::gtFoldExprUnaryConstLng(GenTreeUnOp* tree, GenTreeIntConCommo
1732617329
}
1732717330

1732817331
//------------------------------------------------------------------------
17329-
// gtFoldExprUnaryConstDbl: see if an unary const operation for TYP_DOUBLE or TYP_FLOAT is foldable
17332+
// gtFoldExprUnaryConstDbl: see if a unary const operation for TYP_DOUBLE or TYP_FLOAT is foldable
1733017333
//
1733117334
// Arguments:
1733217335
// tree - tree to examine
@@ -17744,7 +17747,7 @@ GenTree* Compiler::gtFoldExprBinaryConstInt(GenTreeOp* tree, GenTreeIntCon* intC
1774417747
return gtFoldExprForOverflow(tree);
1774517748
}
1774617749

17747-
iconVal1 += iconVal2;
17750+
iconVal1 = static_cast<int32_t>(static_cast<uint32_t>(iconVal1) + static_cast<uint32_t>(iconVal2));
1774817751

1774917752
FieldSeq* fieldSeq = GetFieldSeqStore()->Append(intCon1->gtFieldSeq, intCon2->gtFieldSeq);
1775017753
return gtBashTreeToConstInt(tree, iconVal1, fieldSeq);
@@ -17757,7 +17760,7 @@ GenTree* Compiler::gtFoldExprBinaryConstInt(GenTreeOp* tree, GenTreeIntCon* intC
1775717760
return gtFoldExprForOverflow(tree);
1775817761
}
1775917762

17760-
iconVal1 -= iconVal2;
17763+
iconVal1 = static_cast<int32_t>(static_cast<uint32_t>(iconVal1) - static_cast<uint32_t>(iconVal2));
1776117764
break;
1776217765
}
1776317766

@@ -17768,7 +17771,7 @@ GenTree* Compiler::gtFoldExprBinaryConstInt(GenTreeOp* tree, GenTreeIntCon* intC
1776817771
return gtFoldExprForOverflow(tree);
1776917772
}
1777017773

17771-
iconVal1 *= iconVal2;
17774+
iconVal1 = static_cast<int32_t>(static_cast<uint32_t>(iconVal1) * static_cast<uint32_t>(iconVal2));
1777217775
break;
1777317776
}
1777417777

@@ -17792,7 +17795,7 @@ GenTree* Compiler::gtFoldExprBinaryConstInt(GenTreeOp* tree, GenTreeIntCon* intC
1779217795

1779317796
case GT_LSH:
1779417797
{
17795-
iconVal1 <<= (iconVal2 & 0x1F);
17798+
iconVal1 = static_cast<int32_t>(static_cast<uint32_t>(iconVal1) << (iconVal2 & 0x1F));
1779617799
break;
1779717800
}
1779817801

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

1781117814
case GT_ROL:
1781217815
{
17816+
uint32_t uconVal1 = static_cast<uint32_t>(iconVal1);
1781317817
iconVal2 &= 0x1F;
17814-
iconVal1 = (iconVal1 << iconVal2) |
17815-
static_cast<int32_t>(static_cast<uint32_t>(iconVal1) >> ((32 - iconVal2) & 0x1F));
17818+
iconVal1 = static_cast<int32_t>((uconVal1 << iconVal2) | (uconVal1 >> ((32 - iconVal2) & 0x1F)));
1781617819
break;
1781717820
}
1781817821

1781917822
case GT_ROR:
1782017823
{
17824+
uint32_t uconVal1 = static_cast<uint32_t>(iconVal1);
1782117825
iconVal2 &= 0x1F;
17822-
iconVal1 = (iconVal1 << ((32 - iconVal2) & 0x1F)) |
17823-
static_cast<int32_t>(static_cast<uint32_t>(iconVal1) >> iconVal2);
17826+
iconVal1 = static_cast<int32_t>((uconVal1 << ((32 - iconVal2) & 0x1F)) | (uconVal1 >> iconVal2));
1782417827
break;
1782517828
}
1782617829

@@ -17872,7 +17875,7 @@ GenTree* Compiler::gtFoldExprBinaryConstInt(GenTreeOp* tree, GenTreeIntCon* intC
1787217875
}
1787317876

1787417877
//------------------------------------------------------------------------
17875-
// gtFoldExprBinaryConstInt: see if a binary const operation for TYP_LONG is foldable
17878+
// gtFoldExprBinaryConstLng: see if a binary const operation for TYP_LONG is foldable
1787617879
//
1787717880
// Arguments:
1787817881
// tree - tree to examine
@@ -17993,7 +17996,7 @@ GenTree* Compiler::gtFoldExprBinaryConstLng(GenTreeOp* tree,
1799317996
return gtFoldExprForOverflow(tree);
1799417997
}
1799517998

17996-
lconVal1 += lconVal2;
17999+
lconVal1 = static_cast<int64_t>(static_cast<uint64_t>(lconVal1) + static_cast<uint64_t>(lconVal2));
1799718000

1799818001
#if defined(TARGET_64BIT)
1799918002
FieldSeq* fieldSeq = GetFieldSeqStore()->Append(intConCommon1->AsIntCon()->gtFieldSeq,
@@ -18011,7 +18014,7 @@ GenTree* Compiler::gtFoldExprBinaryConstLng(GenTreeOp* tree,
1801118014
return gtFoldExprForOverflow(tree);
1801218015
}
1801318016

18014-
lconVal1 -= lconVal2;
18017+
lconVal1 = static_cast<int64_t>(static_cast<uint64_t>(lconVal1) - static_cast<uint64_t>(lconVal2));
1801518018
break;
1801618019
}
1801718020

@@ -18022,7 +18025,7 @@ GenTree* Compiler::gtFoldExprBinaryConstLng(GenTreeOp* tree,
1802218025
return gtFoldExprForOverflow(tree);
1802318026
}
1802418027

18025-
lconVal1 *= lconVal2;
18028+
lconVal1 = static_cast<int64_t>(static_cast<uint64_t>(lconVal1) * static_cast<uint64_t>(lconVal2));
1802618029
break;
1802718030
}
1802818031

@@ -18046,7 +18049,7 @@ GenTree* Compiler::gtFoldExprBinaryConstLng(GenTreeOp* tree,
1804618049

1804718050
case GT_LSH:
1804818051
{
18049-
lconVal1 <<= (lconVal2 & 0x3F);
18052+
lconVal1 = static_cast<int64_t>(static_cast<uint64_t>(lconVal1) << (lconVal2 & 0x3F));
1805018053
break;
1805118054
}
1805218055

@@ -18064,17 +18067,17 @@ GenTree* Compiler::gtFoldExprBinaryConstLng(GenTreeOp* tree,
1806418067

1806518068
case GT_ROL:
1806618069
{
18070+
uint64_t uconVal1 = static_cast<uint64_t>(lconVal1);
1806718071
lconVal2 &= 0x3F;
18068-
lconVal1 = (lconVal1 << lconVal2) |
18069-
static_cast<int64_t>(static_cast<uint64_t>(lconVal1) >> ((64 - lconVal2) & 0x3F));
18072+
lconVal1 = static_cast<int64_t>((uconVal1 << lconVal2) | (uconVal1 >> ((64 - lconVal2) & 0x3F)));
1807018073
break;
1807118074
}
1807218075

1807318076
case GT_ROR:
1807418077
{
18078+
uint64_t uconVal1 = static_cast<uint64_t>(lconVal1);
1807518079
lconVal2 &= 0x3F;
18076-
lconVal1 = (lconVal1 << ((64 - lconVal2) & 0x3F)) |
18077-
static_cast<int64_t>(static_cast<uint64_t>(lconVal1) >> lconVal2);
18080+
lconVal1 = static_cast<int64_t>((uconVal1 << ((64 - lconVal2) & 0x3F)) | (uconVal1 >> lconVal2));
1807818081
break;
1807918082
}
1808018083

@@ -18126,12 +18129,12 @@ GenTree* Compiler::gtFoldExprBinaryConstLng(GenTreeOp* tree,
1812618129
}
1812718130

1812818131
//------------------------------------------------------------------------
18129-
// gtFoldExprBinaryConstInt: see if a binary const operation for TYP_INT is foldable
18132+
// gtFoldExprBinaryConstDbl: see if a binary const operation for TYP_DOUBLE or TYP_FLOAT is foldable
1813018133
//
1813118134
// Arguments:
1813218135
// tree - tree to examine
18133-
// intCon1 - the first integer constant operand for tree
18134-
// intCon2 - the second integer constant operand for tree
18136+
// dblCon1 - the first floating-point constant operand for tree
18137+
// dblCon2 - the second floating-point constant operand for tree
1813518138
//
1813618139
// Returns:
1813718140
// The original tree if no folding happened.
@@ -18234,6 +18237,12 @@ GenTree* Compiler::gtFoldExprBinaryConstDbl(GenTreeOp* tree, GenTreeDblCon* dblC
1823418237

1823518238
case GT_DIV:
1823618239
{
18240+
if (dconVal2 == 0)
18241+
{
18242+
// We do not fold division by zero, even for floating point.
18243+
// This is because the result will be platform-dependent for an expression like 0d / 0d.
18244+
return tree;
18245+
}
1823718246
dconVal1 /= dconVal2;
1823818247
break;
1823918248
}
@@ -18325,7 +18334,6 @@ GenTree* Compiler::gtBashTreeToConstLng(GenTree* tree, int64_t lconVal, FieldSeq
1832518334
// Arguments:
1832618335
// tree - the tree to bash
1832718336
// dconVal - the value of the constant
18328-
// fieldSeq - the field sequence, if any
1832918337
//
1833018338
// Returns:
1833118339
// tree, bashed to GT_CNS_DBL node
@@ -33315,7 +33323,7 @@ bool GenTree::IsVectorPerElementMask(var_types simdBaseType, unsigned simdSize)
3331533323

3331633324
case GT_NOT:
3331733325
{
33318-
// We are an unary bitwise operation where the input is a per-element mask
33326+
// We are a unary bitwise operation where the input is a per-element mask
3331933327
return intrinsic->Op(1)->IsVectorPerElementMask(simdBaseType, simdSize);
3332033328
}
3332133329

0 commit comments

Comments
 (0)