diff --git a/src/Common/src/CoreLib/Internal/Runtime/CompilerServices/Unsafe.cs b/src/Common/src/CoreLib/Internal/Runtime/CompilerServices/Unsafe.cs new file mode 100644 index 000000000000..8e6c5da47bf5 --- /dev/null +++ b/src/Common/src/CoreLib/Internal/Runtime/CompilerServices/Unsafe.cs @@ -0,0 +1,315 @@ +// 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; +using System.Runtime.CompilerServices; +using System.Runtime.Versioning; + +#if BIT64 +using nuint = System.UInt64; +using nint = System.Int64; +#else +using nuint = System.UInt32; +using nint = System.Int32; +#endif + +// +// The implementations of most the methods in this file are provided as intrinsics. +// In CoreCLR, the body of the functions are replaced by the EE with unsafe code. See see getILIntrinsicImplementationForUnsafe for details. +// In CoreRT, see Internal.IL.Stubs.UnsafeIntrinsics for details. +// + +namespace Internal.Runtime.CompilerServices +{ + // + // Subsetted clone of System.Runtime.CompilerServices.Unsafe for internal runtime use. + // Keep in sync with https://github.com/dotnet/corefx/tree/master/src/System.Runtime.CompilerServices.Unsafe. + // + + /// + /// For internal use only. Contains generic, low-level functionality for manipulating pointers. + /// + [CLSCompliant(false)] + public static unsafe class Unsafe + { + /// + /// Returns a pointer to the given by-ref parameter. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void* AsPointer(ref T value) + { + throw new PlatformNotSupportedException(); + + // ldarg.0 + // conv.u + // ret + } + + /// + /// Returns the size of an object of the given type parameter. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SizeOf() + { +#if CORECLR + typeof(T).ToString(); // Type token used by the actual method body +#endif + throw new PlatformNotSupportedException(); + + // sizeof !!0 + // ret + } + + /// + /// Casts the given object to the specified type, performs no dynamic type checking. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T As(object value) where T : class + { + throw new PlatformNotSupportedException(); + + // ldarg.0 + // ret + } + + /// + /// Reinterprets the given reference as a reference to a value of type . + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref TTo As(ref TFrom source) + { + throw new PlatformNotSupportedException(); + + // ldarg.0 + // ret + } + + /// + /// Adds an element offset to the given reference. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref T Add(ref T source, int elementOffset) + { +#if CORECLR + typeof(T).ToString(); // Type token used by the actual method body + throw new PlatformNotSupportedException(); +#else + return ref AddByteOffset(ref source, (IntPtr)(elementOffset * (nint)SizeOf())); +#endif + } + + /// + /// Adds an element offset to the given pointer. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void* Add(void* source, int elementOffset) + { +#if CORECLR + typeof(T).ToString(); // Type token used by the actual method body + throw new PlatformNotSupportedException(); +#else + return (byte*)source + (elementOffset * (nint)SizeOf()); +#endif + } + + /// + /// Adds an element offset to the given reference. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static ref T AddByteOffset(ref T source, nuint byteOffset) + { + return ref AddByteOffset(ref source, (IntPtr)(void*)byteOffset); + } + + /// + /// Determines whether the specified references point to the same location. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool AreSame(ref T left, ref T right) + { + throw new PlatformNotSupportedException(); + + // ldarg.0 + // ldarg.1 + // ceq + // ret + } + + /// + /// Initializes a block of memory at the given location with a given initial value + /// without assuming architecture dependent alignment of the address. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void InitBlockUnaligned(ref byte startAddress, byte value, uint byteCount) + { + for (uint i = 0; i < byteCount; i++) + AddByteOffset(ref startAddress, i) = value; + } + + /// + /// Reads a value of type from the given location. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ReadUnaligned(void* source) + { +#if CORECLR + typeof(T).ToString(); // Type token used by the actual method body + throw new PlatformNotSupportedException(); +#else + return Unsafe.As(ref *(byte*)source); +#endif + } + + /// + /// Reads a value of type from the given location. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ReadUnaligned(ref byte source) + { +#if CORECLR + typeof(T).ToString(); // Type token used by the actual method body + throw new PlatformNotSupportedException(); +#else + return Unsafe.As(ref source); +#endif + } + + /// + /// Writes a value of type to the given location. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteUnaligned(void* destination, T value) + { +#if CORECLR + typeof(T).ToString(); // Type token used by the actual method body + throw new PlatformNotSupportedException(); +#else + Unsafe.As(ref *(byte*)destination) = value; +#endif + } + + /// + /// Writes a value of type to the given location. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteUnaligned(ref byte destination, T value) + { +#if CORECLR + typeof(T).ToString(); // Type token used by the actual method body + throw new PlatformNotSupportedException(); +#else + Unsafe.As(ref destination) = value; +#endif + } + + /// + /// Adds an element offset to the given reference. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref T AddByteOffset(ref T source, IntPtr byteOffset) + { + // This method is implemented by the toolchain + throw new PlatformNotSupportedException(); + + // ldarg.0 + // ldarg.1 + // add + // ret + } + + /// + /// Reads a value of type from the given location. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Read(void* source) + { + return Unsafe.As(ref *(byte*)source); + } + + /// + /// Reads a value of type from the given location. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T Read(ref byte source) + { + return Unsafe.As(ref source); + } + + /// + /// Writes a value of type to the given location. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Write(void* destination, T value) + { + Unsafe.As(ref *(byte*)destination) = value; + } + + /// + /// Writes a value of type to the given location. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Write(ref byte destination, T value) + { + Unsafe.As(ref destination) = value; + } + + /// + /// Reinterprets the given location as a reference to a value of type . + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ref T AsRef(void* source) + { + return ref Unsafe.As(ref *(byte*)source); + } + + /// + /// Determines the byte offset from origin to target from the given references. + /// + [Intrinsic] + [NonVersionable] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static IntPtr ByteOffset(ref T origin, ref T target) + { + throw new PlatformNotSupportedException(); + } + } +} diff --git a/src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems b/src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems index 20bf4353a25f..90587d2bd0ab 100644 --- a/src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems +++ b/src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems @@ -19,6 +19,7 @@ +