Skip to content

Commit

Permalink
Add unsafe operations for ref returns and locals
Browse files Browse the repository at this point in the history
Fixes #10451
  • Loading branch information
jkotas committed Jul 30, 2016
1 parent 29a6c39 commit fbb1e62
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
.class public abstract auto ansi sealed beforefieldinit System.Runtime.CompilerServices.Unsafe
extends [System.Runtime]System.Object
{
.method public hidebysig static !!T Read<T>(void* source) cil managed aggressiveinlining
.method public hidebysig static !!T Read<T>(void* source) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 1
Expand Down Expand Up @@ -157,6 +157,37 @@
ret
} // end of method Unsafe::AsRef

.method public hidebysig static !!U& AsRef<T,U>(!!T& source) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 1
ldarg.0
ret
} // end of method Unsafe::AsRef

.method public hidebysig static !!T& RefAdd<T>(!!T& pointer, int32 offset) cil managed aggressiveinlining

This comment has been minimized.

Copy link
@mikedn

mikedn Jul 30, 2016

Probably it's just me but offset makes me think of bytes, not elements. That said, I can't think of a better parameter name.

A possible alternative might be ref T RefIndex(ref T pointer, int index) but that sounds a bit fishy.

{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 2
ldarg.1
sizeof !!T
conv.i
mul
ldarg.0
add
ret
}

.method public hidebysig static bool RefEquals<T>(!!T& refA, !!T& refB) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 2
ldarg.0
ldarg.1
ceq
ret
}

} // end of class System.Runtime.CompilerServices.Unsafe

.class private auto ansi sealed beforefieldinit System.Runtime.Versioning.NonVersionableAttribute
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<AssemblyVersion>4.0.1.0</AssemblyVersion>
<AssemblyVersion>4.0.2.0</AssemblyVersion>
<PackageTargetFramework>netstandard1.0</PackageTargetFramework>
<DocumentationFile>$(MSBuildThisFileDirectory)System.Runtime.CompilerServices.Unsafe.xml</DocumentationFile>
</PropertyGroup>
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions src/System.Runtime.CompilerServices.Unsafe/tests/UnsafeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,56 @@ public static void DangerousAs()
object o = new Object();
Assert.IsType(typeof(Object), Unsafe.As<string>(o));
}

[Fact]
public unsafe static void AsRef_Pointer()
{
byte[] b = new byte[4] { 0x42, 0x42, 0x42, 0x42 };
fixed (byte * p = b)
{
ref int r = ref Unsafe.AsRef<int>(p);
Assert.Equal(r, 0x42424242);

r = 0x0EF00EF0;
Assert.Equal(b[0] | b[1] | b[2] | b[3], 0xFE);
}
}

[Fact]
public static void AsRef_Ref()
{
byte[] b = new byte[4] { 0x42, 0x42, 0x42, 0x42 };

ref int r = ref Unsafe.AsRef<byte, int>(ref b[0]);
Assert.Equal(r, 0x42424242);

r = 0x0EF00EF0;
Assert.Equal(b[0] | b[1] | b[2] | b[3], 0xFE);
}

[Fact]
public static void RefAdd()
{
int[] a = new int[] { 0x123, 0x234, 0x345, 0x456 };

ref int r1 = ref Unsafe.RefAdd(ref a[0], 1);
Assert.Equal(r1, 0x234);

ref int r2 = ref Unsafe.RefAdd(ref r1, 2);
Assert.Equal(r2, 0x456);

ref int r3 = ref Unsafe.RefAdd(ref r2, -3);
Assert.Equal(r3, 0x123);
}

[Fact]
public static void RefEquals()
{
long[] a = new long[2];

Assert.True(Unsafe.RefEquals(ref a[0], ref a[0]));
Assert.False(Unsafe.RefEquals(ref a[0], ref a[1]));
}
}

[StructLayout(LayoutKind.Explicit)]
Expand Down

0 comments on commit fbb1e62

Please sign in to comment.