Skip to content

[API Proposal]: Mark Vector-related APIs as caller-unsafe #128075

@EgorBo

Description

@EgorBo

Background and motivation

#125145 Annotate All Vector-related APIs as caller-unsafe because all of these either:

  • Perform memory accesses without bound checks
  • May return uninitialized memory in their components.

I'm using a diff format where + indicates that it's now caller-unsafe and - indicates the unsafe modifier has been removed (a non-breaking change).

API Proposal

namespace System.Runtime.Intrinsics

namespace System.Runtime.Intrinsics

public static partial class Vector64
{
+   public static unsafe Vector64<byte> CreateScalarUnsafe(byte value)
+   public static unsafe Vector64<double> CreateScalarUnsafe(double value)
+   public static unsafe Vector64<short> CreateScalarUnsafe(short value)
+   public static unsafe Vector64<int> CreateScalarUnsafe(int value)
+   public static unsafe Vector64<long> CreateScalarUnsafe(long value)
+   public static unsafe Vector64<nint> CreateScalarUnsafe(nint value)
+   public static unsafe Vector64<nuint> CreateScalarUnsafe(nuint value)
+   public static unsafe Vector64<sbyte> CreateScalarUnsafe(sbyte value)
+   public static unsafe Vector64<float> CreateScalarUnsafe(float value)
+   public static unsafe Vector64<ushort> CreateScalarUnsafe(ushort value)
+   public static unsafe Vector64<uint> CreateScalarUnsafe(uint value)
+   public static unsafe Vector64<ulong> CreateScalarUnsafe(ulong valuw)
+   public static unsafe Vector64<T> CreateScalarUnsafe<T>(T value)

+   public static unsafe Vector64<T> LoadUnsafe<T>(ref readonly T source)
+   public static unsafe Vector64<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset)

+   public static unsafe void StoreUnsafe<T>(this Vector64<T> source, ref T destination)
+   public static unsafe void StoreUnsafe<T>(this Vector64<T> source, ref T destination, nuint elementOffset)

+   public static unsafe Vector128<T> ToVector128Unsafe<T>(this Vector64<T> vector)
}

public static partial class Vector128
{
+   public static unsafe Vector128<float> AsVector128Unsafe(this System.Numerics.Vector2 value)
+   public static unsafe Vector128<float> AsVector128Unsafe(this System.Numerics.Vector3 value)

+   public static unsafe Vector128<byte> CreateScalarUnsafe(byte value)
+   public static unsafe Vector128<double> CreateScalarUnsafe(double value)
+   public static unsafe Vector128<short> CreateScalarUnsafe(short value)
+   public static unsafe Vector128<int> CreateScalarUnsafe(int value)
+   public static unsafe Vector128<long> CreateScalarUnsafe(long value)
+   public static unsafe Vector128<nint> CreateScalarUnsafe(nint value)
+   public static unsafe Vector128<nuint> CreateScalarUnsafe(nuint value)
+   public static unsafe Vector128<sbyte> CreateScalarUnsafe(sbyte value)
+   public static unsafe Vector128<float> CreateScalarUnsafe(float value)
+   public static unsafe Vector128<ushort> CreateScalarUnsafe(ushort value)
+   public static unsafe Vector128<uint> CreateScalarUnsafe(uint value)
+   public static unsafe Vector128<ulong> CreateScalarUnsafe(ulong value)
+   public static unsafe Vector128<T> CreateScalarUnsafe<T>(T value)

+   public static unsafe Vector128<T> LoadUnsafe<T>(ref readonly T source)
+   public static unsafe Vector128<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset)

+   public static unsafe void StoreUnsafe<T>(this Vector128<T> source, ref T destination)
+   public static unsafe void StoreUnsafe<T>(this Vector128<T> source, ref T destination, nuint elementOffset)

+   public static unsafe Vector256<T> ToVector256Unsafe<T>(this Vector128<T> vector)
}

public static partial class Vector256
{
+   public static unsafe Vector256<byte> CreateScalarUnsafe(byte value)
+   public static unsafe Vector256<double> CreateScalarUnsafe(double value)
+   public static unsafe Vector256<short> CreateScalarUnsafe(short value)
+   public static unsafe Vector256<int> CreateScalarUnsafe(int value)
+   public static unsafe Vector256<long> CreateScalarUnsafe(long value)
+   public static unsafe Vector256<nint> CreateScalarUnsafe(nint value)
+   public static unsafe Vector256<nuint> CreateScalarUnsafe(nuint value)
+   public static unsafe Vector256<sbyte> CreateScalarUnsafe(sbyte value)
+   public static unsafe Vector256<float> CreateScalarUnsafe(float value)
+   public static unsafe Vector256<ushort> CreateScalarUnsafe(ushort value)
+   public static unsafe Vector256<uint> CreateScalarUnsafe(uint value)
+   public static unsafe Vector256<ulong> CreateScalarUnsafe(ulong value)
+   public static unsafe Vector256<T> CreateScalarUnsafe<T>(T value)

+   public static unsafe Vector256<T> LoadUnsafe<T>(ref readonly T source)
+   public static unsafe Vector256<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset)

+   public static unsafe void StoreUnsafe<T>(this Vector256<T> source, ref T destination)
+   public static unsafe void StoreUnsafe<T>(this Vector256<T> source, ref T destination, nuint elementOffset)

+   public static unsafe Vector512<T> ToVector512Unsafe<T>(this Vector256<T> vector)
}

public static partial class Vector512
{
+   public static unsafe Vector512<byte> CreateScalarUnsafe(byte value)
+   public static unsafe Vector512<double> CreateScalarUnsafe(double value)
+   public static unsafe Vector512<short> CreateScalarUnsafe(short value)
+   public static unsafe Vector512<int> CreateScalarUnsafe(int value)
+   public static unsafe Vector512<long> CreateScalarUnsafe(long value)
+   public static unsafe Vector512<nint> CreateScalarUnsafe(nint value)
+   public static unsafe Vector512<nuint> CreateScalarUnsafe(nuint value)
+   public static unsafe Vector512<sbyte> CreateScalarUnsafe(sbyte value)
+   public static unsafe Vector512<float> CreateScalarUnsafe(float value)
+   public static unsafe Vector512<ushort> CreateScalarUnsafe(ushort value)
+   public static unsafe Vector512<uint> CreateScalarUnsafe(uint value)
+   public static unsafe Vector512<ulong> CreateScalarUnsafe(ulong value)
+   public static unsafe Vector512<T> CreateScalarUnsafe<T>(T value)

+   public static unsafe Vector512<T> LoadUnsafe<T>(ref readonly T source)
+   public static unsafe Vector512<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset)

+   public static unsafe void StoreUnsafe<T>(this Vector512<T> source, ref T destination)
+   public static unsafe void StoreUnsafe<T>(this Vector512<T> source, ref T destination, nuint elementOffset)
}

namespace System.Numerics

namespace System.Numerics

public static partial class Vector
{
+   public static unsafe Vector3 AsVector3Unsafe(this Vector2 value)
+   public static unsafe Vector4 AsVector4Unsafe(this Vector2 value)
+   public static unsafe Vector4 AsVector4Unsafe(this Vector3 value)

+   public static unsafe Vector<T> CreateScalarUnsafe<T>(T value)

+   public static unsafe Vector<T> LoadUnsafe<T>(ref readonly T source)
+   public static unsafe Vector<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset)

+   public static unsafe void StoreUnsafe<T>(this Vector<T> source, ref T destination)
+   public static unsafe void StoreUnsafe(this Vector2 source, ref float destination)
+   public static unsafe void StoreUnsafe(this Vector3 source, ref float destination)
+   public static unsafe void StoreUnsafe(this Vector4 source, ref float destination)
+   public static unsafe void StoreUnsafe<T>(this Vector<T> source, ref T destination, nuint elementOffset)
+   public static unsafe void StoreUnsafe(this Vector2 source, ref float destination, nuint elementOffset)
+   public static unsafe void StoreUnsafe(this Vector3 source, ref float destination, nuint elementOffset)
+   public static unsafe void StoreUnsafe(this Vector4 source, ref float destination, nuint elementOffset)
}

public partial struct Vector2
{
+   public static unsafe Vector2 CreateScalarUnsafe(float x)

+   public static unsafe Vector2 LoadUnsafe(ref readonly float source)
+   public static unsafe Vector2 LoadUnsafe(ref readonly float source, nuint elementOffset)
}

public partial struct Vector3
{
+   public static unsafe Vector3 CreateScalarUnsafe(float x)

+   public static unsafe Vector3 LoadUnsafe(ref readonly float source)
+   public static unsafe Vector3 LoadUnsafe(ref readonly float source, nuint elementOffset)
}

public partial struct Vector4
{
+   public static unsafe Vector4 CreateScalarUnsafe(float x)

+   public static unsafe Vector4 LoadUnsafe(ref readonly float source)
+   public static unsafe Vector4 LoadUnsafe(ref readonly float source, nuint elementOffset)
}

API Usage

All these apis now require an unsafe context to call them.

Alternative Designs

No response

Risks

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-System.Runtime.IntrinsicsuntriagedNew issue has not been triaged by the area owner

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions