Skip to content

Commit 778be98

Browse files
Ensure we throw NotSupportedException for any Vector<T> method taking or returning an unsupported T (#38241)
* Ensure we throw NotSupportedException for any Vector<T> method taking or returning an unsupported T * Exit early for SIMDAsHWIntrinsics if the baseType is unsupported
1 parent c4cef3a commit 778be98

File tree

6 files changed

+547
-107
lines changed

6 files changed

+547
-107
lines changed

src/coreclr/src/jit/simd.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1822,7 +1822,9 @@ GenTree* Compiler::impSIMDIntrinsic(OPCODE opcode,
18221822
unsigned argCount = 0;
18231823
const SIMDIntrinsicInfo* intrinsicInfo =
18241824
getSIMDIntrinsicInfo(&clsHnd, methodHnd, sig, (opcode == CEE_NEWOBJ), &argCount, &baseType, &size);
1825-
if (intrinsicInfo == nullptr || intrinsicInfo->id == SIMDIntrinsicInvalid)
1825+
1826+
// Exit early if the intrinsic is invalid or unrecognized
1827+
if ((intrinsicInfo == nullptr) || (intrinsicInfo->id == SIMDIntrinsicInvalid))
18261828
{
18271829
return nullptr;
18281830
}

src/coreclr/src/jit/simdashwintrinsic.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,13 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic,
207207
// if it isn't the basis for anything carried on the node.
208208
baseType = getBaseTypeAndSizeOfSIMDType(clsHnd, &simdSize);
209209

210+
if ((clsHnd != m_simdHandleCache->SIMDVectorHandle) && !varTypeIsArithmetic(baseType))
211+
{
212+
// We want to exit early if the clsHnd should have a base type and it isn't one
213+
// of the supported types. This handles cases like op_Explicit which take a Vector<T>
214+
return nullptr;
215+
}
216+
210217
if (retType == TYP_STRUCT)
211218
{
212219
baseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeSigClass, &simdSize);
Lines changed: 349 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Globalization;
6+
using System.Runtime.InteropServices;
7+
using Xunit;
8+
9+
namespace System.Numerics.Tests
10+
{
11+
public class GenericVectorUnsupportedTests
12+
{
13+
[Fact]
14+
public void CountTest()
15+
{
16+
Assert.Throws<NotSupportedException>(() => Vector<bool>.Count);
17+
}
18+
19+
[Fact]
20+
public void ZeroTest()
21+
{
22+
Assert.Throws<NotSupportedException>(() => Vector<bool>.Zero);
23+
}
24+
25+
[Fact]
26+
public void OneTest()
27+
{
28+
Assert.Throws<NotSupportedException>(() => Vector<bool>.One);
29+
}
30+
31+
[Fact]
32+
public void ConstructorValueTest()
33+
{
34+
Assert.Throws<NotSupportedException>(() => new Vector<bool>(false));
35+
}
36+
37+
[Fact]
38+
public void ConstructorArrayTest()
39+
{
40+
bool[] values = new bool[32];
41+
Assert.Throws<NotSupportedException>(() => new Vector<bool>(values));
42+
}
43+
44+
[Fact]
45+
public void ConstructorArrayIndexTest()
46+
{
47+
bool[] values = new bool[32];
48+
Assert.Throws<NotSupportedException>(() => new Vector<bool>(values, 1));
49+
}
50+
51+
[Fact]
52+
public void ConstructorReadOnlySpanByteTest()
53+
{
54+
Assert.Throws<NotSupportedException>(() => {
55+
ReadOnlySpan<byte> values = stackalloc byte[32];
56+
_ = new Vector<bool>(values);
57+
});
58+
}
59+
60+
[Fact]
61+
public void ConstructorReadOnlySpanTTest()
62+
{
63+
Assert.Throws<NotSupportedException>(() => {
64+
ReadOnlySpan<bool> values = stackalloc bool[32];
65+
_ = new Vector<bool>(values);
66+
});
67+
}
68+
69+
[Fact]
70+
public void ConstructorSpanTTest()
71+
{
72+
Assert.Throws<NotSupportedException>(() => {
73+
Span<bool> values = stackalloc bool[32];
74+
_ = new Vector<bool>(values);
75+
});
76+
}
77+
78+
[Fact]
79+
public void CopyToSpanByteTest()
80+
{
81+
Assert.Throws<NotSupportedException>(() => {
82+
Vector<bool> vector = default;
83+
Span<byte> destination = stackalloc byte[32];
84+
vector.CopyTo(destination);
85+
});
86+
}
87+
88+
[Fact]
89+
public void CopyToSpanTTest()
90+
{
91+
Assert.Throws<NotSupportedException>(() => {
92+
Vector<bool> vector = default;
93+
Span<bool> destination = stackalloc bool[32];
94+
vector.CopyTo(destination);
95+
});
96+
}
97+
98+
[Fact]
99+
public void CopyToArrayTest()
100+
{
101+
Vector<bool> vector = default;
102+
bool[] destination = new bool[32];
103+
Assert.Throws<NotSupportedException>(() => vector.CopyTo(destination));
104+
}
105+
106+
[Fact]
107+
public void CopyToArrayIndexTest()
108+
{
109+
Vector<bool> vector = default;
110+
bool[] destination = new bool[32];
111+
Assert.Throws<NotSupportedException>(() => vector.CopyTo(destination, 1));
112+
}
113+
114+
[Fact]
115+
public void IndexerTest()
116+
{
117+
Vector<bool> vector = default;
118+
Assert.Throws<NotSupportedException>(() => vector[0]);
119+
}
120+
121+
[Fact]
122+
public void EqualsObjectTest()
123+
{
124+
Vector<bool> vector1 = default;
125+
Vector<bool> vector2 = default;
126+
Assert.Throws<NotSupportedException>(() => vector1.Equals((object)vector2));
127+
}
128+
129+
[Fact]
130+
public void EqualsVectorTest()
131+
{
132+
Vector<bool> vector1 = default;
133+
Vector<bool> vector2 = default;
134+
Assert.Throws<NotSupportedException>(() => vector1.Equals(vector2));
135+
}
136+
137+
[Fact]
138+
public void GetHashCodeTest()
139+
{
140+
Vector<bool> vector = default;
141+
Assert.Throws<NotSupportedException>(() => vector.GetHashCode());
142+
}
143+
144+
[Fact]
145+
public void ToStringTest()
146+
{
147+
Vector<bool> vector = default;
148+
Assert.Throws<NotSupportedException>(() => vector.ToString());
149+
}
150+
151+
[Fact]
152+
public void ToStringFormatTest()
153+
{
154+
Vector<bool> vector = default;
155+
Assert.Throws<NotSupportedException>(() => vector.ToString("G"));
156+
}
157+
158+
[Fact]
159+
public void ToStringFormatFormatProviderTest()
160+
{
161+
Vector<bool> vector = default;
162+
Assert.Throws<NotSupportedException>(() => vector.ToString("G", CultureInfo.InvariantCulture));
163+
}
164+
165+
[Fact]
166+
public void TryCopyToSpanByteTest()
167+
{
168+
Assert.Throws<NotSupportedException>(() => {
169+
Vector<bool> vector = default;
170+
Span<byte> destination = stackalloc byte[32];
171+
vector.TryCopyTo(destination);
172+
});
173+
}
174+
175+
[Fact]
176+
public void TryCopyToSpanTTest()
177+
{
178+
Assert.Throws<NotSupportedException>(() => {
179+
Vector<bool> vector = default;
180+
Span<bool> destination = stackalloc bool[32];
181+
vector.TryCopyTo(destination);
182+
});
183+
}
184+
185+
[Fact]
186+
public void OpAdditionTest()
187+
{
188+
Vector<bool> vector1 = default;
189+
Vector<bool> vector2 = default;
190+
Assert.Throws<NotSupportedException>(() => vector1 + vector2);
191+
}
192+
193+
[Fact]
194+
public void OpSubtractionTest()
195+
{
196+
Vector<bool> vector1 = default;
197+
Vector<bool> vector2 = default;
198+
Assert.Throws<NotSupportedException>(() => vector1 - vector2);
199+
}
200+
201+
[Fact]
202+
public void OpMultiplicationTest()
203+
{
204+
Vector<bool> vector1 = default;
205+
Vector<bool> vector2 = default;
206+
Assert.Throws<NotSupportedException>(() => vector1 * vector2);
207+
}
208+
209+
[Fact]
210+
public void OpMultiplicationByScalarTest()
211+
{
212+
Vector<bool> vector = default;
213+
Assert.Throws<NotSupportedException>(() => vector * false);
214+
Assert.Throws<NotSupportedException>(() => false * vector);
215+
}
216+
217+
[Fact]
218+
public void OpDivideTest()
219+
{
220+
Vector<bool> vector1 = default;
221+
Vector<bool> vector2 = default;
222+
Assert.Throws<NotSupportedException>(() => vector1 / vector2);
223+
}
224+
225+
[Fact]
226+
public void OpNegateTest()
227+
{
228+
Vector<bool> vector = default;
229+
Assert.Throws<NotSupportedException>(() => -vector);
230+
}
231+
232+
[Fact]
233+
public void OpBitwiseAndTest()
234+
{
235+
Vector<bool> vector1 = default;
236+
Vector<bool> vector2 = default;
237+
Assert.Throws<NotSupportedException>(() => vector1 & vector2);
238+
}
239+
240+
[Fact]
241+
public void OpBitwiseOrTest()
242+
{
243+
Vector<bool> vector1 = default;
244+
Vector<bool> vector2 = default;
245+
Assert.Throws<NotSupportedException>(() => vector1 | vector2);
246+
}
247+
248+
[Fact]
249+
public void OpBitwiseXorTest()
250+
{
251+
Vector<bool> vector1 = default;
252+
Vector<bool> vector2 = default;
253+
Assert.Throws<NotSupportedException>(() => vector1 ^ vector2);
254+
}
255+
256+
[Fact]
257+
public void OpOnesComplementTest()
258+
{
259+
Vector<bool> vector = default;
260+
Assert.Throws<NotSupportedException>(() => ~vector);
261+
}
262+
263+
[Fact]
264+
public void OpEqualsTest()
265+
{
266+
Vector<bool> vector1 = default;
267+
Vector<bool> vector2 = default;
268+
Assert.Throws<NotSupportedException>(() => vector1 == vector2);
269+
}
270+
271+
[Fact]
272+
public void OpNotEqualsTest()
273+
{
274+
Vector<bool> vector1 = default;
275+
Vector<bool> vector2 = default;
276+
Assert.Throws<NotSupportedException>(() => vector1 != vector2);
277+
}
278+
279+
[Fact]
280+
public void ToVectorByteTest()
281+
{
282+
Vector<bool> vector = default;
283+
Assert.Throws<NotSupportedException>(() => (Vector<byte>)vector);
284+
}
285+
286+
[Fact]
287+
public void ToVectorSByteTest()
288+
{
289+
Vector<bool> vector = default;
290+
Assert.Throws<NotSupportedException>(() => (Vector<sbyte>)vector);
291+
}
292+
293+
[Fact]
294+
public void ToVectorInt16Test()
295+
{
296+
Vector<bool> vector = default;
297+
Assert.Throws<NotSupportedException>(() => (Vector<short>)vector);
298+
}
299+
300+
[Fact]
301+
public void ToVectorUInt16Test()
302+
{
303+
Vector<bool> vector = default;
304+
Assert.Throws<NotSupportedException>(() => (Vector<ushort>)vector);
305+
}
306+
307+
[Fact]
308+
public void ToVectorInt32Test()
309+
{
310+
Vector<bool> vector = default;
311+
Assert.Throws<NotSupportedException>(() => (Vector<int>)vector);
312+
}
313+
314+
[Fact]
315+
public void ToVectorUInt32Test()
316+
{
317+
Vector<bool> vector = default;
318+
Assert.Throws<NotSupportedException>(() => (Vector<uint>)vector);
319+
}
320+
321+
[Fact]
322+
public void ToVectorInt64Test()
323+
{
324+
Vector<bool> vector = default;
325+
Assert.Throws<NotSupportedException>(() => (Vector<long>)vector);
326+
}
327+
328+
[Fact]
329+
public void ToVectorUInt64Test()
330+
{
331+
Vector<bool> vector = default;
332+
Assert.Throws<NotSupportedException>(() => (Vector<ulong>)vector);
333+
}
334+
335+
[Fact]
336+
public void ToVectorSingleTest()
337+
{
338+
Vector<bool> vector = default;
339+
Assert.Throws<NotSupportedException>(() => (Vector<float>)vector);
340+
}
341+
342+
[Fact]
343+
public void ToVectorDoubleTest()
344+
{
345+
Vector<bool> vector = default;
346+
Assert.Throws<NotSupportedException>(() => (Vector<double>)vector);
347+
}
348+
}
349+
}

src/libraries/System.Numerics.Vectors/tests/System.Numerics.Vectors.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<DesignTime>True</DesignTime>
1616
<DependentUpon>GenericVectorTests.tt</DependentUpon>
1717
</Compile>
18+
<Compile Include="GenericVectorUnsupportedTests.cs" />
1819
<Compile Include="Util.cs" />
1920
<Compile Include="Vector2Tests.cs" />
2021
<Compile Include="Vector3Tests.cs" />

0 commit comments

Comments
 (0)