Skip to content

Commit

Permalink
Ensure we throw NotSupportedException for any Vector<T> method taking…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
tannergooding authored Jun 24, 2020
1 parent c4cef3a commit 778be98
Show file tree
Hide file tree
Showing 6 changed files with 547 additions and 107 deletions.
4 changes: 3 additions & 1 deletion src/coreclr/src/jit/simd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1822,7 +1822,9 @@ GenTree* Compiler::impSIMDIntrinsic(OPCODE opcode,
unsigned argCount = 0;
const SIMDIntrinsicInfo* intrinsicInfo =
getSIMDIntrinsicInfo(&clsHnd, methodHnd, sig, (opcode == CEE_NEWOBJ), &argCount, &baseType, &size);
if (intrinsicInfo == nullptr || intrinsicInfo->id == SIMDIntrinsicInvalid)

// Exit early if the intrinsic is invalid or unrecognized
if ((intrinsicInfo == nullptr) || (intrinsicInfo->id == SIMDIntrinsicInvalid))
{
return nullptr;
}
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/src/jit/simdashwintrinsic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,13 @@ GenTree* Compiler::impSimdAsHWIntrinsic(NamedIntrinsic intrinsic,
// if it isn't the basis for anything carried on the node.
baseType = getBaseTypeAndSizeOfSIMDType(clsHnd, &simdSize);

if ((clsHnd != m_simdHandleCache->SIMDVectorHandle) && !varTypeIsArithmetic(baseType))
{
// We want to exit early if the clsHnd should have a base type and it isn't one
// of the supported types. This handles cases like op_Explicit which take a Vector<T>
return nullptr;
}

if (retType == TYP_STRUCT)
{
baseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeSigClass, &simdSize);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,349 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Globalization;
using System.Runtime.InteropServices;
using Xunit;

namespace System.Numerics.Tests
{
public class GenericVectorUnsupportedTests
{
[Fact]
public void CountTest()
{
Assert.Throws<NotSupportedException>(() => Vector<bool>.Count);
}

[Fact]
public void ZeroTest()
{
Assert.Throws<NotSupportedException>(() => Vector<bool>.Zero);
}

[Fact]
public void OneTest()
{
Assert.Throws<NotSupportedException>(() => Vector<bool>.One);
}

[Fact]
public void ConstructorValueTest()
{
Assert.Throws<NotSupportedException>(() => new Vector<bool>(false));
}

[Fact]
public void ConstructorArrayTest()
{
bool[] values = new bool[32];
Assert.Throws<NotSupportedException>(() => new Vector<bool>(values));
}

[Fact]
public void ConstructorArrayIndexTest()
{
bool[] values = new bool[32];
Assert.Throws<NotSupportedException>(() => new Vector<bool>(values, 1));
}

[Fact]
public void ConstructorReadOnlySpanByteTest()
{
Assert.Throws<NotSupportedException>(() => {
ReadOnlySpan<byte> values = stackalloc byte[32];
_ = new Vector<bool>(values);
});
}

[Fact]
public void ConstructorReadOnlySpanTTest()
{
Assert.Throws<NotSupportedException>(() => {
ReadOnlySpan<bool> values = stackalloc bool[32];
_ = new Vector<bool>(values);
});
}

[Fact]
public void ConstructorSpanTTest()
{
Assert.Throws<NotSupportedException>(() => {
Span<bool> values = stackalloc bool[32];
_ = new Vector<bool>(values);
});
}

[Fact]
public void CopyToSpanByteTest()
{
Assert.Throws<NotSupportedException>(() => {
Vector<bool> vector = default;
Span<byte> destination = stackalloc byte[32];
vector.CopyTo(destination);
});
}

[Fact]
public void CopyToSpanTTest()
{
Assert.Throws<NotSupportedException>(() => {
Vector<bool> vector = default;
Span<bool> destination = stackalloc bool[32];
vector.CopyTo(destination);
});
}

[Fact]
public void CopyToArrayTest()
{
Vector<bool> vector = default;
bool[] destination = new bool[32];
Assert.Throws<NotSupportedException>(() => vector.CopyTo(destination));
}

[Fact]
public void CopyToArrayIndexTest()
{
Vector<bool> vector = default;
bool[] destination = new bool[32];
Assert.Throws<NotSupportedException>(() => vector.CopyTo(destination, 1));
}

[Fact]
public void IndexerTest()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => vector[0]);
}

[Fact]
public void EqualsObjectTest()
{
Vector<bool> vector1 = default;
Vector<bool> vector2 = default;
Assert.Throws<NotSupportedException>(() => vector1.Equals((object)vector2));
}

[Fact]
public void EqualsVectorTest()
{
Vector<bool> vector1 = default;
Vector<bool> vector2 = default;
Assert.Throws<NotSupportedException>(() => vector1.Equals(vector2));
}

[Fact]
public void GetHashCodeTest()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => vector.GetHashCode());
}

[Fact]
public void ToStringTest()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => vector.ToString());
}

[Fact]
public void ToStringFormatTest()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => vector.ToString("G"));
}

[Fact]
public void ToStringFormatFormatProviderTest()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => vector.ToString("G", CultureInfo.InvariantCulture));
}

[Fact]
public void TryCopyToSpanByteTest()
{
Assert.Throws<NotSupportedException>(() => {
Vector<bool> vector = default;
Span<byte> destination = stackalloc byte[32];
vector.TryCopyTo(destination);
});
}

[Fact]
public void TryCopyToSpanTTest()
{
Assert.Throws<NotSupportedException>(() => {
Vector<bool> vector = default;
Span<bool> destination = stackalloc bool[32];
vector.TryCopyTo(destination);
});
}

[Fact]
public void OpAdditionTest()
{
Vector<bool> vector1 = default;
Vector<bool> vector2 = default;
Assert.Throws<NotSupportedException>(() => vector1 + vector2);
}

[Fact]
public void OpSubtractionTest()
{
Vector<bool> vector1 = default;
Vector<bool> vector2 = default;
Assert.Throws<NotSupportedException>(() => vector1 - vector2);
}

[Fact]
public void OpMultiplicationTest()
{
Vector<bool> vector1 = default;
Vector<bool> vector2 = default;
Assert.Throws<NotSupportedException>(() => vector1 * vector2);
}

[Fact]
public void OpMultiplicationByScalarTest()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => vector * false);
Assert.Throws<NotSupportedException>(() => false * vector);
}

[Fact]
public void OpDivideTest()
{
Vector<bool> vector1 = default;
Vector<bool> vector2 = default;
Assert.Throws<NotSupportedException>(() => vector1 / vector2);
}

[Fact]
public void OpNegateTest()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => -vector);
}

[Fact]
public void OpBitwiseAndTest()
{
Vector<bool> vector1 = default;
Vector<bool> vector2 = default;
Assert.Throws<NotSupportedException>(() => vector1 & vector2);
}

[Fact]
public void OpBitwiseOrTest()
{
Vector<bool> vector1 = default;
Vector<bool> vector2 = default;
Assert.Throws<NotSupportedException>(() => vector1 | vector2);
}

[Fact]
public void OpBitwiseXorTest()
{
Vector<bool> vector1 = default;
Vector<bool> vector2 = default;
Assert.Throws<NotSupportedException>(() => vector1 ^ vector2);
}

[Fact]
public void OpOnesComplementTest()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => ~vector);
}

[Fact]
public void OpEqualsTest()
{
Vector<bool> vector1 = default;
Vector<bool> vector2 = default;
Assert.Throws<NotSupportedException>(() => vector1 == vector2);
}

[Fact]
public void OpNotEqualsTest()
{
Vector<bool> vector1 = default;
Vector<bool> vector2 = default;
Assert.Throws<NotSupportedException>(() => vector1 != vector2);
}

[Fact]
public void ToVectorByteTest()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => (Vector<byte>)vector);
}

[Fact]
public void ToVectorSByteTest()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => (Vector<sbyte>)vector);
}

[Fact]
public void ToVectorInt16Test()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => (Vector<short>)vector);
}

[Fact]
public void ToVectorUInt16Test()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => (Vector<ushort>)vector);
}

[Fact]
public void ToVectorInt32Test()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => (Vector<int>)vector);
}

[Fact]
public void ToVectorUInt32Test()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => (Vector<uint>)vector);
}

[Fact]
public void ToVectorInt64Test()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => (Vector<long>)vector);
}

[Fact]
public void ToVectorUInt64Test()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => (Vector<ulong>)vector);
}

[Fact]
public void ToVectorSingleTest()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => (Vector<float>)vector);
}

[Fact]
public void ToVectorDoubleTest()
{
Vector<bool> vector = default;
Assert.Throws<NotSupportedException>(() => (Vector<double>)vector);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<DesignTime>True</DesignTime>
<DependentUpon>GenericVectorTests.tt</DependentUpon>
</Compile>
<Compile Include="GenericVectorUnsupportedTests.cs" />
<Compile Include="Util.cs" />
<Compile Include="Vector2Tests.cs" />
<Compile Include="Vector3Tests.cs" />
Expand Down
Loading

0 comments on commit 778be98

Please sign in to comment.