forked from dotnet/corefx
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor Unsafe.cs to get it more in sync with CoreRT. (dotnet#15510)
* Refactor Unsafe.cs to get it more in sync with CoreRT. * Format the document. * Unifying the copies of Unsafe using ifdefs * Change exception thrown to PlatformNotSupportedException * Addressing PR feedback and moving Unsafe to shared. * Addressing PR feedback * Addressing PR review - adding intrinsic attribute Signed-off-by: dotnet-bot-corefx-mirror <dotnet-bot@microsoft.com>
- Loading branch information
Showing
2 changed files
with
316 additions
and
0 deletions.
There are no files selected for viewing
315 changes: 315 additions & 0 deletions
315
src/Common/src/CoreLib/Internal/Runtime/CompilerServices/Unsafe.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. | ||
// | ||
|
||
/// <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 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> | ||
/// 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(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters