summaryrefslogtreecommitdiff
path: root/src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs')
-rw-r--r--src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs371
1 files changed, 371 insertions, 0 deletions
diff --git a/src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs b/src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs
new file mode 100644
index 0000000000..aeff3ce2ca
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs
@@ -0,0 +1,371 @@
+// 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.
+ //
+
+ /// <summary>
+ /// For internal use only. Contains generic, low-level functionality for manipulating pointers.
+ /// </summary>
+ [CLSCompliant(false)]
+ public static unsafe class Unsafe
+ {
+ /// <summary>
+ /// Returns a pointer to the given by-ref parameter.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void* AsPointer<T>(ref T value)
+ {
+ throw new PlatformNotSupportedException();
+
+ // ldarg.0
+ // conv.u
+ // ret
+ }
+
+ /// <summary>
+ /// Returns the size of an object of the given type parameter.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int SizeOf<T>()
+ {
+#if CORECLR
+ typeof(T).ToString(); // Type token used by the actual method body
+#endif
+ throw new PlatformNotSupportedException();
+
+ // sizeof !!0
+ // ret
+ }
+
+ /// <summary>
+ /// Casts the given object to the specified type, performs no dynamic type checking.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T As<T>(object value) where T : class
+ {
+ throw new PlatformNotSupportedException();
+
+ // ldarg.0
+ // ret
+ }
+
+ /// <summary>
+ /// Reinterprets the given reference as a reference to a value of type <typeparamref name="TTo"/>.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref TTo As<TFrom, TTo>(ref TFrom source)
+ {
+ throw new PlatformNotSupportedException();
+
+ // ldarg.0
+ // ret
+ }
+
+ /// <summary>
+ /// Adds an element offset to the given reference.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref T Add<T>(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<T>()));
+#endif
+ }
+
+ /// <summary>
+ /// Adds an element offset to the given reference.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref T Add<T>(ref T source, IntPtr elementOffset)
+ {
+#if CORECLR
+ typeof(T).ToString(); // Type token used by the actual method body
+ throw new PlatformNotSupportedException();
+#else
+ return ref AddByteOffset(ref source, (IntPtr)((nint)elementOffset * (nint)SizeOf<T>()));
+#endif
+ }
+
+ /// <summary>
+ /// Adds an element offset to the given pointer.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void* Add<T>(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<T>());
+#endif
+ }
+
+ /// <summary>
+ /// Adds an element offset to the given reference.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static ref T AddByteOffset<T>(ref T source, nuint byteOffset)
+ {
+ return ref AddByteOffset(ref source, (IntPtr)(void*)byteOffset);
+ }
+
+ /// <summary>
+ /// Determines whether the specified references point to the same location.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool AreSame<T>(ref T left, ref T right)
+ {
+ throw new PlatformNotSupportedException();
+
+ // ldarg.0
+ // ldarg.1
+ // ceq
+ // ret
+ }
+
+ /// <summary>
+ /// Determines whether the memory address referenced by <paramref name="left"/> is greater than
+ /// the memory address referenced by <paramref name="right"/>.
+ /// </summary>
+ /// <remarks>
+ /// This check is conceptually similar to "(void*)(&amp;left) &gt; (void*)(&amp;right)".
+ /// </remarks>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsAddressGreaterThan<T>(ref T left, ref T right)
+ {
+ throw new PlatformNotSupportedException();
+
+ // ldarg.0
+ // ldarg.1
+ // cgt.un
+ // ret
+ }
+
+ /// <summary>
+ /// Determines whether the memory address referenced by <paramref name="left"/> is less than
+ /// the memory address referenced by <paramref name="right"/>.
+ /// </summary>
+ /// <remarks>
+ /// This check is conceptually similar to "(void*)(&amp;left) &lt; (void*)(&amp;right)".
+ /// </remarks>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsAddressLessThan<T>(ref T left, ref T right)
+ {
+ throw new PlatformNotSupportedException();
+
+ // ldarg.0
+ // ldarg.1
+ // clt.un
+ // ret
+ }
+
+ /// <summary>
+ /// Initializes a block of memory at the given location with a given initial value
+ /// without assuming architecture dependent alignment of the address.
+ /// </summary>
+ [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;
+ }
+
+ /// <summary>
+ /// Reads a value of type <typeparamref name="T"/> from the given location.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T ReadUnaligned<T>(void* source)
+ {
+#if CORECLR
+ typeof(T).ToString(); // Type token used by the actual method body
+ throw new PlatformNotSupportedException();
+#else
+ return Unsafe.As<byte, T>(ref *(byte*)source);
+#endif
+ }
+
+ /// <summary>
+ /// Reads a value of type <typeparamref name="T"/> from the given location.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T ReadUnaligned<T>(ref byte source)
+ {
+#if CORECLR
+ typeof(T).ToString(); // Type token used by the actual method body
+ throw new PlatformNotSupportedException();
+#else
+ return Unsafe.As<byte, T>(ref source);
+#endif
+ }
+
+ /// <summary>
+ /// Writes a value of type <typeparamref name="T"/> to the given location.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void WriteUnaligned<T>(void* destination, T value)
+ {
+#if CORECLR
+ typeof(T).ToString(); // Type token used by the actual method body
+ throw new PlatformNotSupportedException();
+#else
+ Unsafe.As<byte, T>(ref *(byte*)destination) = value;
+#endif
+ }
+
+ /// <summary>
+ /// Writes a value of type <typeparamref name="T"/> to the given location.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void WriteUnaligned<T>(ref byte destination, T value)
+ {
+#if CORECLR
+ typeof(T).ToString(); // Type token used by the actual method body
+ throw new PlatformNotSupportedException();
+#else
+ Unsafe.As<byte, T>(ref destination) = value;
+#endif
+ }
+
+ /// <summary>
+ /// Adds an element offset to the given reference.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref T AddByteOffset<T>(ref T source, IntPtr byteOffset)
+ {
+ // This method is implemented by the toolchain
+ throw new PlatformNotSupportedException();
+
+ // ldarg.0
+ // ldarg.1
+ // add
+ // ret
+ }
+
+ /// <summary>
+ /// Reads a value of type <typeparamref name="T"/> from the given location.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T Read<T>(void* source)
+ {
+ return Unsafe.As<byte, T>(ref *(byte*)source);
+ }
+
+ /// <summary>
+ /// Reads a value of type <typeparamref name="T"/> from the given location.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T Read<T>(ref byte source)
+ {
+ return Unsafe.As<byte, T>(ref source);
+ }
+
+ /// <summary>
+ /// Writes a value of type <typeparamref name="T"/> to the given location.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Write<T>(void* destination, T value)
+ {
+ Unsafe.As<byte, T>(ref *(byte*)destination) = value;
+ }
+
+ /// <summary>
+ /// Writes a value of type <typeparamref name="T"/> to the given location.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Write<T>(ref byte destination, T value)
+ {
+ Unsafe.As<byte, T>(ref destination) = value;
+ }
+
+ /// <summary>
+ /// Reinterprets the given location as a reference to a value of type <typeparamref name="T"/>.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref T AsRef<T>(void* source)
+ {
+ return ref Unsafe.As<byte, T>(ref *(byte*)source);
+ }
+
+ /// <summary>
+ /// Determines the byte offset from origin to target from the given references.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static IntPtr ByteOffset<T>(ref T origin, ref T target)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+}