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 Aug 3, 2016
1 parent 14ddfbd commit 1775337
Show file tree
Hide file tree
Showing 4 changed files with 151 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,50 @@
ret
} // end of method Unsafe::AsRef

.method public hidebysig static !!TTo& As<TFrom,TTo>(!!TFrom& 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& Add<T>(!!T& source, int32 elementOffset) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 3
ldarg.0
ldarg.1
sizeof !!T
conv.i
mul
add
ret
}

.method public hidebysig static !!T& Subtract<T>(!!T& source, int32 elementOffset) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 3
ldarg.0
ldarg.1
sizeof !!T
conv.i
mul
sub
ret
}

.method public hidebysig static bool AreSame<T>(!!T& left, !!T& right) 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.

69 changes: 69 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,75 @@ public static void DangerousAs()
object o = new Object();
Assert.IsType(typeof(Object), Unsafe.As<string>(o));
}

// Active Issue: https://github.com/dotnet/coreclr/issues/6505
// These tests require C# compiler with support for ref returns and locals
#if false
[Fact]
public unsafe static void AsRef()
{
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 RefAs()
{
byte[] b = new byte[4] { 0x42, 0x42, 0x42, 0x42 };

ref int r = ref Unsafe.As<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.Add(ref a[0], 1);
Assert.Equal(r1, 0x234);

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

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

[Fact]
public static void RefSubtract()
{
string[] a = new string[] { "abc", "def", "ghi", "jkl" };

ref string r1 = ref Unsafe.Subtract(ref a[0], -2);
Assert.Equal(r1, "ghi");

ref string r2 = ref Unsafe.Subtract(ref r1, -1);
Assert.Equal(r2, "jkl");

ref string r3 = ref Unsafe.Subtract(ref r2, 3);
Assert.Equal(r3, "abc");
}

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

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

[StructLayout(LayoutKind.Explicit)]
Expand Down

0 comments on commit 1775337

Please sign in to comment.