Skip to content

Commit

Permalink
Add unsigned overloads for Unsafe Add/Subtract and Add/SubtractByteOf…
Browse files Browse the repository at this point in the history
…fset (dotnet#40715)

* Implement unsigned reference math in IL.

* Update reference source for Unsafe.

* Copy docs to UIntPtr overloads.

* Add tests for UIntPtr.

* Use nuint instead of UIntPtr.

* Fix reference to CORE_ASSEMBLY.
  • Loading branch information
huoyaoyuan authored Sep 6, 2020
1 parent 4b80546 commit b3bc0a7
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ namespace System.Runtime.CompilerServices
public static partial class Unsafe
{
public static ref T AddByteOffset<T>(ref T source, System.IntPtr byteOffset) { throw null; }
public static ref T AddByteOffset<T>(ref T source, nuint byteOffset) { throw null; }
public unsafe static void* Add<T>(void* source, int elementOffset) { throw null; }
public static ref T Add<T>(ref T source, int elementOffset) { throw null; }
public static ref T Add<T>(ref T source, System.IntPtr elementOffset) { throw null; }
public static ref T Add<T>(ref T source, nuint elementOffset) { throw null; }
public static bool AreSame<T>([System.Diagnostics.CodeAnalysis.AllowNull] ref T left, [System.Diagnostics.CodeAnalysis.AllowNull] ref T right) { throw null; }
public unsafe static void* AsPointer<T>(ref T value) { throw null; }
public unsafe static ref T AsRef<T>(void* source) { throw null; }
Expand Down Expand Up @@ -42,9 +44,11 @@ public unsafe static void InitBlockUnaligned(void* startAddress, byte value, uin
public static void SkipInit<T>(out T value) { throw null; }
public static int SizeOf<T>() { throw null; }
public static ref T SubtractByteOffset<T>(ref T source, System.IntPtr byteOffset) { throw null; }
public static ref T SubtractByteOffset<T>(ref T source, nuint byteOffset) { throw null; }
public unsafe static void* Subtract<T>(void* source, int elementOffset) { throw null; }
public static ref T Subtract<T>(ref T source, int elementOffset) { throw null; }
public static ref T Subtract<T>(ref T source, System.IntPtr elementOffset) { throw null; }
public static ref T Subtract<T>(ref T source, nuint elementOffset) { throw null; }
public static ref T Unbox<T>(object box) where T : struct { throw null; }
public static void WriteUnaligned<T>(ref byte destination, T value) { }
public unsafe static void WriteUnaligned<T>(void* destination, T value) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,22 @@
ret
} // end of method Unsafe::Add

.method public hidebysig static !!T& Add<T>(!!T& source, native uint elementOffset) cil managed aggressiveinlining
{
.param [2]
.custom instance void System.Runtime.CompilerServices.NativeIntegerAttribute::.ctor() = (
01 00 00 00
)
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 3
ldarg.0
ldarg.1
sizeof !!T
mul
add
ret
} // end of method Unsafe::Add

.method public hidebysig static !!T& AddByteOffset<T>(!!T& source, native int byteOffset) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
Expand All @@ -370,6 +386,20 @@
ret
} // end of method Unsafe::AddByteOffset

.method public hidebysig static !!T& AddByteOffset<T>(!!T& source, native uint byteOffset) cil managed aggressiveinlining
{
.param [2]
.custom instance void System.Runtime.CompilerServices.NativeIntegerAttribute::.ctor() = (
01 00 00 00
)
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 2
ldarg.0
ldarg.1
add
ret
} // end of method Unsafe::AddByteOffset

.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 )
Expand Down Expand Up @@ -408,6 +438,22 @@
ret
} // end of method Unsafe::Subtract

.method public hidebysig static !!T& Subtract<T>(!!T& source, native uint elementOffset) cil managed aggressiveinlining
{
.param [2]
.custom instance void System.Runtime.CompilerServices.NativeIntegerAttribute::.ctor() = (
01 00 00 00
)
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 3
ldarg.0
ldarg.1
sizeof !!T
mul
sub
ret
} // end of method Unsafe::Subtract

.method public hidebysig static !!T& SubtractByteOffset<T>(!!T& source, native int byteOffset) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
Expand All @@ -418,6 +464,20 @@
ret
} // end of method Unsafe::SubtractByteOffset

.method public hidebysig static !!T& SubtractByteOffset<T>(!!T& source, native uint byteOffset) cil managed aggressiveinlining
{
.param [2]
.custom instance void System.Runtime.CompilerServices.NativeIntegerAttribute::.ctor() = (
01 00 00 00
)
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 2
ldarg.0
ldarg.1
sub
ret
} // end of method Unsafe::SubtractByteOffset

.method public hidebysig static native int ByteOffset<T>(!!T& origin, !!T& target) cil managed aggressiveinlining
{
.custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
Expand Down Expand Up @@ -513,3 +573,72 @@

} // end of class System.Runtime.CompilerServices.IsReadOnlyAttribute
#endif

.class private auto ansi sealed beforefieldinit Microsoft.CodeAnalysis.EmbeddedAttribute
extends [CORE_ASSEMBLY]System.Attribute
{
.custom instance void [CORE_ASSEMBLY]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = (
01 00 00 00
)
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [CORE_ASSEMBLY]System.Attribute::.ctor()
IL_0006: ret
} // end of method EmbeddedAttribute::.ctor

} // end of class Microsoft.CodeAnalysis.EmbeddedAttribute

.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.NativeIntegerAttribute
extends [CORE_ASSEMBLY]System.Attribute
{
.custom instance void [CORE_ASSEMBLY]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [CORE_ASSEMBLY]System.AttributeUsageAttribute::.ctor(valuetype [CORE_ASSEMBLY]System.AttributeTargets) = (
01 00 84 6b 00 00 02 00 54 02 0d 41 6c 6c 6f 77
4d 75 6c 74 69 70 6c 65 00 54 02 09 49 6e 68 65
72 69 74 65 64 00
)
.field public initonly bool[] TransformFlags

.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [CORE_ASSEMBLY]System.Attribute::.ctor()
IL_0006: ldarg.0
IL_0007: ldc.i4.1
IL_0008: newarr [CORE_ASSEMBLY]System.Boolean
IL_000d: dup
IL_000e: ldc.i4.0
IL_000f: ldc.i4.1
IL_0010: stelem.i1
IL_0011: stfld bool[] System.Runtime.CompilerServices.NativeIntegerAttribute::TransformFlags
IL_0016: ret
} // end of method NativeIntegerAttribute::.ctor

.method public hidebysig specialname rtspecialname
instance void .ctor (
bool[] ''
) cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [CORE_ASSEMBLY]System.Attribute::.ctor()
IL_0006: ldarg.0
IL_0007: ldarg.1
IL_0008: stfld bool[] System.Runtime.CompilerServices.NativeIntegerAttribute::TransformFlags
IL_000d: ret
} // end of method NativeIntegerAttribute::.ctor

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

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

Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,18 @@ public static void RefAddIntPtr()
Assert.Equal(0x123, r3);
}

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

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

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

[Fact]
public static void RefAddByteOffset()
{
Expand All @@ -519,6 +531,18 @@ public static void RefAddByteOffset()
Assert.Equal(0x12, r3);
}

[Fact]
public static void RefAddNuintByteOffset()
{
byte[] a = new byte[] { 0x12, 0x34, 0x56, 0x78 };

ref byte r1 = ref Unsafe.AddByteOffset(ref a[0], (nuint)1);
Assert.Equal(0x34, r1);

ref byte r2 = ref Unsafe.AddByteOffset(ref r1, (nuint)2);
Assert.Equal(0x78, r2);
}

[Fact]
public static void RefSubtract()
{
Expand Down Expand Up @@ -576,6 +600,15 @@ public static void RefSubtractIntPtr()
Assert.Equal("abc", r3);
}

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

ref string r3 = ref Unsafe.Subtract(ref a[3], (nuint)3);
Assert.Equal("abc", r3);
}

[Fact]
public static void RefSubtractByteOffset()
{
Expand All @@ -591,6 +624,15 @@ public static void RefSubtractByteOffset()
Assert.Equal(0x12, r3);
}

[Fact]
public static void RefSubtractNuintByteOffset()
{
byte[] a = new byte[] { 0x12, 0x34, 0x56, 0x78 };

ref byte r3 = ref Unsafe.SubtractByteOffset(ref a[3], (nuint)3);
Assert.Equal(0x12, r3);
}

[Fact]
public static void RefAreSame()
{
Expand Down

0 comments on commit b3bc0a7

Please sign in to comment.