You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
930 lines
27 KiB
930 lines
27 KiB
using System; |
|
using System.Diagnostics; |
|
using System.Runtime.CompilerServices; |
|
using System.Runtime.InteropServices; |
|
using Unity.Burst; |
|
using Unity.Collections; |
|
using Unity.Collections.LowLevel.Unsafe; |
|
using Unity.Jobs; |
|
using Unity.Mathematics; |
|
using UnityBenchShared; |
|
|
|
namespace Burst.Compiler.IL.Tests |
|
{ |
|
internal class Pointers |
|
{ |
|
#if UNITY_2019_1_OR_NEWER |
|
[TestCompiler(1)] |
|
[TestCompiler(4)] |
|
[TestCompiler(5)] |
|
public static int CheckAddressOf(int a) |
|
{ |
|
var value = new MyIntValue(a); |
|
ref int intValue = ref value.GetValuePtr(); |
|
return intValue * 10 + 1; |
|
} |
|
|
|
public struct MyIntValue |
|
{ |
|
public MyIntValue(int value) |
|
{ |
|
Value = value; |
|
} |
|
|
|
public int Value; |
|
|
|
public unsafe ref int GetValuePtr() |
|
{ |
|
fixed (void* ptr = &this) |
|
{ |
|
return ref *(int*) ptr; |
|
} |
|
} |
|
} |
|
#endif |
|
|
|
[TestCompiler(0, MyCastEnum.Value2)] |
|
[TestCompiler(1, MyCastEnum.Value0)] |
|
[TestCompiler(2, MyCastEnum.Value3)] |
|
public static unsafe MyCastEnum PointerCastEnum(int value, MyCastEnum newValue) |
|
{ |
|
var ptvalue = new IntPtr(&value); |
|
var pEnum = (MyCastEnum*) ptvalue; |
|
*pEnum = newValue; |
|
return *pEnum; |
|
} |
|
|
|
[TestCompiler(0, 0)] |
|
[TestCompiler(0, 1)] |
|
[TestCompiler(1, 0)] |
|
public static unsafe bool PointerCompare(IntPtr a, IntPtr b) |
|
{ |
|
return a == b; |
|
} |
|
|
|
[TestCompiler(0)] |
|
[TestCompiler(1)] |
|
[TestCompiler(2)] |
|
public static unsafe bool RawPointerCompare(IntPtr value) |
|
{ |
|
return (void*)value == (void*)1; |
|
} |
|
|
|
[TestCompiler(0)] |
|
[TestCompiler(1)] |
|
[TestCompiler(42424242)] |
|
public static unsafe int PointerHash(IntPtr value) |
|
{ |
|
return value.GetHashCode(); |
|
} |
|
|
|
[TestCompiler(0)] |
|
[TestCompiler(1)] |
|
[TestCompiler(42424242)] |
|
public static unsafe IntPtr PointerToPointer(IntPtr value) |
|
{ |
|
return new IntPtr(value.ToPointer()); |
|
} |
|
|
|
[TestCompiler(0, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_MethodNotSupported)] |
|
public static unsafe int PointerToString(IntPtr value) |
|
{ |
|
return value.ToString().Length; |
|
} |
|
|
|
[TestCompiler(1)] |
|
[TestCompiler(255)] |
|
[TestCompiler(12351235)] |
|
public static unsafe int PointerAdd(int a) |
|
{ |
|
var pA = (byte*)&a; |
|
var pDest = pA + 3; |
|
*pDest = (byte)a; |
|
return a; |
|
} |
|
|
|
[TestCompiler(1)] |
|
[TestCompiler(255)] |
|
[TestCompiler(12351235)] |
|
public static unsafe int PointerSub(int a) |
|
{ |
|
var pA = (byte*)&a; |
|
var pDest = pA + 3; |
|
*(pDest - 1) = (byte)a; |
|
return a; |
|
} |
|
|
|
[TestCompiler] |
|
public static unsafe int PointerPointerSub() |
|
{ |
|
var value = new StructForPointerPointerSub(); |
|
int* pa = &value.A; |
|
int* pb = &value.B; |
|
var auto = (pb - pa); |
|
return (int)auto; |
|
} |
|
|
|
[TestCompiler] |
|
public static unsafe int WhileWithPointer() |
|
{ |
|
var check = new CheckPointers { X = 1, Y = 2, Z = 3, W = 4 }; |
|
int* pstart = &check.X; |
|
int* pend = &check.W; |
|
int result = 0; |
|
while (pstart <= pend) |
|
{ |
|
result += *pstart; |
|
pstart++; |
|
} |
|
|
|
return result; |
|
} |
|
|
|
struct StructForPointerPointerSub |
|
{ |
|
public int A; |
|
public int B; |
|
} |
|
|
|
|
|
|
|
[TestCompiler(1)] |
|
[TestCompiler(255)] |
|
[TestCompiler(12351235)] |
|
public static IntPtr IntPtrConstructor(int a) |
|
{ |
|
return new IntPtr(a); |
|
} |
|
|
|
[TestCompiler(1U)] |
|
[TestCompiler(255U)] |
|
[TestCompiler(12351235U)] |
|
public static UIntPtr UIntPtrConstructor(uint a) |
|
{ |
|
return new UIntPtr(a); |
|
} |
|
|
|
[TestCompiler(1)] |
|
[TestCompiler(255)] |
|
[TestCompiler(12351235)] |
|
public static int IntPtrToInt32(int a) |
|
{ |
|
return new IntPtr(a).ToInt32(); |
|
} |
|
|
|
[TestCompiler(1)] |
|
[TestCompiler(255)] |
|
[TestCompiler(12351235)] |
|
public static long IntPtrToInt64(int a) |
|
{ |
|
return new IntPtr(a).ToInt64(); |
|
} |
|
|
|
[TestCompiler(OverrideOn32BitNative = 4)] |
|
public static int IntPtrSize() |
|
{ |
|
return IntPtr.Size; |
|
} |
|
|
|
// asserted in IntPtrProcessor |
|
[TestCompiler(OverrideOn32BitNative = true)] |
|
public static bool IntPtrSizeCompared() |
|
{ |
|
return IntPtr.Size == 4; |
|
} |
|
|
|
[TestCompiler] |
|
public static IntPtr IntPtrZero() |
|
{ |
|
return IntPtr.Zero; |
|
} |
|
|
|
[TestCompiler(1)] |
|
[TestCompiler(5)] |
|
public static IntPtr IntPtrAdd(IntPtr a) |
|
{ |
|
return IntPtr.Add(a, 1); |
|
} |
|
|
|
|
|
[TestCompiler(1)] |
|
[TestCompiler(5)] |
|
public static IntPtr IntPtrAdd2(IntPtr a) |
|
{ |
|
return a + 1; |
|
} |
|
|
|
[TestCompiler(1)] |
|
[TestCompiler(5)] |
|
public static IntPtr IntPtrSub(IntPtr a) |
|
{ |
|
return IntPtr.Subtract(a, 1); |
|
} |
|
|
|
|
|
[TestCompiler(1)] |
|
[TestCompiler(5)] |
|
public static IntPtr IntPtrSub2(IntPtr a) |
|
{ |
|
return a - 1; |
|
} |
|
|
|
[TestCompiler] |
|
public static UIntPtr UIntPtrZero() |
|
{ |
|
return UIntPtr.Zero; |
|
} |
|
|
|
[TestCompiler(1U)] |
|
[TestCompiler(5U)] |
|
public static UIntPtr UIntPtrAdd(UIntPtr a) |
|
{ |
|
return UIntPtr.Add(a, 1); |
|
} |
|
|
|
[TestCompiler(1U)] |
|
[TestCompiler(5U)] |
|
public static UIntPtr UIntPtrSubstract(UIntPtr a) |
|
{ |
|
return UIntPtr.Subtract(a, 1); |
|
} |
|
|
|
[TestCompiler(1)] |
|
public static unsafe int PointerAccess(int a) |
|
{ |
|
var value = a; |
|
var pValue = &value; |
|
pValue[0] = a + 5; |
|
return value; |
|
} |
|
|
|
[TestCompiler(0)] // Keep it at 0 only! |
|
public static unsafe int PointerAccess2(int a) |
|
{ |
|
int value = 15; |
|
var pValue = &value; |
|
pValue[a] = value + 5; |
|
return value; |
|
} |
|
|
|
[TestCompiler(0)] // Keep it at 0 only! |
|
public static unsafe float PointerAccess3(int a) |
|
{ |
|
float value = 15.0f; |
|
var pValue = &value; |
|
pValue[a] = value + 5.0f; |
|
return value; |
|
} |
|
|
|
[TestCompiler(0)] |
|
public static unsafe int PointerCompareViaInt(int a) |
|
{ |
|
int b; |
|
if (&a == &b) |
|
return 1; |
|
else |
|
return 0; |
|
} |
|
|
|
[TestCompiler(0)] |
|
public static unsafe int IntPtrCompare(int a) |
|
{ |
|
int b; |
|
IntPtr aPtr = (IntPtr)(&a); |
|
IntPtr bPtr = (IntPtr)(&b); |
|
if (aPtr == bPtr) |
|
return 1; |
|
else |
|
return 0; |
|
} |
|
|
|
[TestCompiler(typeof(IntPtrZeroProvider), 1)] |
|
[TestCompiler(typeof(IntPtrOneProvider), 2)] |
|
public static unsafe int UnsafeCompare(int* a, int b) |
|
{ |
|
if (a == null) |
|
{ |
|
return 1 + b; |
|
} |
|
|
|
return 2 + b; |
|
} |
|
|
|
unsafe struct NativeQueueBlockHeader |
|
{ |
|
#pragma warning disable 0649 |
|
public byte* nextBlock; |
|
public int itemsInBlock; |
|
#pragma warning restore 0649 |
|
} |
|
|
|
[TestCompiler] |
|
public static unsafe void PointerCastWithStruct() |
|
{ |
|
|
|
byte* currentWriteBlock = null; |
|
if (currentWriteBlock != null && ((NativeQueueBlockHeader*) currentWriteBlock)->itemsInBlock == 100) |
|
{ |
|
((NativeQueueBlockHeader*) currentWriteBlock)->itemsInBlock = 5; |
|
} |
|
} |
|
|
|
private class IntPtrZeroProvider : IArgumentProvider |
|
{ |
|
public object Value => IntPtr.Zero; |
|
} |
|
|
|
private class IntPtrOneProvider : IArgumentProvider |
|
{ |
|
public object Value => new IntPtr(1); |
|
} |
|
|
|
[TestCompiler] |
|
public static unsafe int FixedField() |
|
{ |
|
var fixedStruct = new MyStructWithFixed(); |
|
fixedStruct.Values[0] = 1; |
|
fixedStruct.Values[1] = 2; |
|
fixedStruct.Values[2] = 3; |
|
fixedStruct.Values[9] = 9; |
|
|
|
int result = 0; |
|
for (int i = 0; i < 10; i++) |
|
{ |
|
result += fixedStruct.Values[i]; |
|
} |
|
return result; |
|
} |
|
|
|
[TestCompiler(typeof(MyStructWithFixedProvider), 1)] |
|
//[TestCompiler(typeof(MyStructWithFixedProvider), 2)] |
|
public static unsafe int FixedFieldViaPointer(ref MyStructWithFixed fixedStruct, int i) |
|
{ |
|
fixed (MyStructWithFixed* check = &fixedStruct) |
|
{ |
|
int* data = check->Values; |
|
return data[i]; |
|
} |
|
} |
|
|
|
[TestCompiler(typeof(MyStructWithFixedProvider))] |
|
public static unsafe int FixedInt32AndRefInt32(ref MyStructWithFixed fixedStruct) |
|
{ |
|
fixed (int* data = &fixedStruct.Value) |
|
{ |
|
// We do a call to ProcessInt after with a ref int |
|
// to check that we don't collide with the PinnedType introduced by the previous |
|
// fixed statement |
|
ProcessInt(ref *data); |
|
} |
|
|
|
return fixedStruct.Value; |
|
} |
|
|
|
private static void ProcessInt(ref int value) |
|
{ |
|
value += 5; |
|
} |
|
|
|
public unsafe struct ConditionalTestStruct |
|
{ |
|
public void* a; |
|
public void* b; |
|
} |
|
|
|
public unsafe struct PointerConditional : IJob, IDisposable |
|
{ |
|
public ConditionalTestStruct* t; |
|
|
|
public void Execute() |
|
{ |
|
t->b = t->a != null ? t->a : null; |
|
} |
|
|
|
|
|
public struct Provider : IArgumentProvider |
|
{ |
|
public object Value |
|
{ |
|
get |
|
{ |
|
var value = new PointerConditional(); |
|
value.t = (ConditionalTestStruct*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf<ConditionalTestStruct>(), 4, Allocator.Persistent); |
|
value.t->a = (void*)0x12345678; |
|
value.t->b = null; |
|
return value; |
|
} |
|
} |
|
} |
|
|
|
public void Dispose() |
|
{ |
|
UnsafeUtility.Free(t, Allocator.Persistent); |
|
} |
|
} |
|
|
|
[TestCompiler(typeof(PointerConditional.Provider))] |
|
public static unsafe bool TestConditionalPointer([NoAlias] ref PointerConditional job) |
|
{ |
|
job.Execute(); |
|
return job.t->a == job.t->b; |
|
} |
|
|
|
#if BURST_TESTS_ONLY |
|
[TestCompiler] |
|
public static int TestFieldOffset() |
|
{ |
|
var t = default(StructWithFields); |
|
return (int)Unsafe.ByteOffset(ref Unsafe.As<int, bool>(ref t.a), ref t.d); |
|
} |
|
#endif |
|
|
|
public struct StructWithFields |
|
{ |
|
public int a; |
|
public int b; |
|
public bool c; |
|
public bool d; |
|
public bool e; |
|
public bool f; |
|
} |
|
|
|
public unsafe struct MyStructWithFixed |
|
{ |
|
public fixed int Values[10]; |
|
public int Value; |
|
} |
|
|
|
private struct MyStructWithFixedProvider : IArgumentProvider |
|
{ |
|
public unsafe object Value |
|
{ |
|
get |
|
{ |
|
var field = new MyStructWithFixed(); |
|
for (int i = 0; i < 10; i++) |
|
{ |
|
field.Values[i] = (i + 1) * 5; |
|
} |
|
|
|
field.Value = 1235; |
|
|
|
return field; |
|
} |
|
} |
|
} |
|
|
|
[TestCompiler(0)] |
|
public static unsafe void TestCellVisibleInternal(int length) |
|
{ |
|
int3* cellVisibleRequest = (int3*)0; |
|
bool*cellVisibleResult = (bool*)0; |
|
int3* visibleCells = (int3*)0; |
|
IsCellVisibleInternal(cellVisibleRequest, cellVisibleResult, visibleCells, length, length); |
|
} |
|
|
|
static unsafe void IsCellVisibleInternal(int3* cellVisibleRequest, bool* cellVisibleResult, int3* visibleCells, int requestLength, int visibleCellsLength) |
|
{ |
|
for (int r = 0; r < requestLength; r++) |
|
{ |
|
cellVisibleResult[r] = false; |
|
for (int i = 0; i < visibleCellsLength; i++) |
|
{ |
|
if (visibleCells[i].x == cellVisibleRequest[r].x && visibleCells[i].y == cellVisibleRequest[r].y && visibleCells[i].z == cellVisibleRequest[r].z) |
|
{ |
|
cellVisibleResult[r] = true; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
|
|
public enum MyCastEnum |
|
{ |
|
Value0 = 0, |
|
Value1 = 1, |
|
Value2 = 2, |
|
Value3 = 3, |
|
} |
|
|
|
public struct CheckPointers |
|
{ |
|
public int X; |
|
public int Y; |
|
public int Z; |
|
public int W; |
|
} |
|
|
|
// From https://github.com/Unity-Technologies/ECSJobDemos/issues/244 |
|
[TestCompiler] |
|
public static unsafe int InitialiseViaCastedPointer() |
|
{ |
|
int value = 0; |
|
|
|
void* ptr = &value; |
|
|
|
byte* asBytePtr = (byte*)ptr; |
|
|
|
((int*)asBytePtr)[0] = -1; |
|
|
|
return value; |
|
} |
|
|
|
[TestCompiler(1)] |
|
public static unsafe int PointerWriteArg(int a) |
|
{ |
|
return (int)TestPointerAndGeneric<float>((int*) a); |
|
} |
|
|
|
private static unsafe int* TestPointerAndGeneric<T>(int* p) where T : struct |
|
{ |
|
p = (int*)(IntPtr)26; |
|
return p; |
|
} |
|
|
|
|
|
[TestCompiler(ExpectedDiagnosticId = DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)] |
|
public static void TestBlobAssetReferenceData() |
|
{ |
|
var blob = new BlobAssetReferenceData(IntPtr.Zero); |
|
blob.Validate(); |
|
} |
|
|
|
|
|
[StructLayout(LayoutKind.Explicit, Size = 16)] |
|
internal unsafe struct BlobAssetHeader |
|
{ |
|
[FieldOffset(0)] public void* ValidationPtr; |
|
[FieldOffset(8)] public int Length; |
|
[FieldOffset(12)] public Allocator Allocator; |
|
} |
|
|
|
internal unsafe struct BlobAssetReferenceData |
|
{ |
|
[NativeDisableUnsafePtrRestriction] |
|
public byte* _ptr; |
|
|
|
public BlobAssetReferenceData(IntPtr zero) |
|
{ |
|
_ptr = (byte*)zero; |
|
} |
|
|
|
internal BlobAssetHeader* Header => ((BlobAssetHeader*)_ptr) - 1; |
|
|
|
public void Validate() |
|
{ |
|
if (_ptr != null) |
|
if (Header->ValidationPtr != _ptr) |
|
throw new InvalidOperationException("The BlobAssetReference is not valid. Likely it has already been unloaded or released"); |
|
} |
|
} |
|
|
|
internal unsafe struct StackAllocCheck |
|
{ |
|
public int* ptr; |
|
|
|
[MethodImpl(MethodImplOptions.NoInlining)] |
|
public void AddToPtr(int* otherPtr) |
|
{ |
|
*otherPtr = 42; |
|
*ptr += 1; |
|
*ptr += *otherPtr; |
|
} |
|
|
|
public class Provider : IArgumentProvider |
|
{ |
|
public object Value => new StackAllocCheck(); |
|
} |
|
} |
|
|
|
[TestCompiler(typeof(StackAllocCheck.Provider))] |
|
public static unsafe bool StackAllocAliasCheck([NoAlias] ref StackAllocCheck stackAllocCheck) |
|
{ |
|
int* ptr = stackalloc int[1]; |
|
*ptr = 13; |
|
|
|
stackAllocCheck.ptr = ptr; |
|
|
|
stackAllocCheck.AddToPtr(ptr); |
|
|
|
if (*ptr != 86) |
|
{ |
|
return false; |
|
} |
|
|
|
*stackAllocCheck.ptr = -4; |
|
*ptr += 1; |
|
*ptr += *stackAllocCheck.ptr; |
|
|
|
if (*ptr != -6) |
|
{ |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
[TestCompiler(1)] |
|
public static unsafe int NativeIntAddCheck(int a) |
|
{ |
|
return (int)(&a + 1) - (int)&a; |
|
} |
|
|
|
public unsafe struct PointerArithmetic : IJob, IDisposable |
|
{ |
|
[NativeDisableUnsafePtrRestriction] public int** pointers; |
|
|
|
public void Execute() |
|
{ |
|
pointers[10] = pointers[10] + +1; |
|
pointers[20] = pointers[20] - +1; |
|
pointers[30] = pointers[30] - -1; |
|
pointers[40] = pointers[40] + -1; |
|
} |
|
|
|
public struct Provider : IArgumentProvider |
|
{ |
|
public object Value |
|
{ |
|
get |
|
{ |
|
var value = new PointerArithmetic(); |
|
value.pointers = (int**)UnsafeUtility.Malloc(1000*sizeof(int*), 8, Allocator.Persistent); |
|
UnsafeUtility.MemClear(value.pointers, 1000 * sizeof(int*)); |
|
return value; |
|
} |
|
} |
|
} |
|
|
|
public void Dispose() |
|
{ |
|
UnsafeUtility.Free(pointers, Allocator.Persistent); |
|
} |
|
} |
|
|
|
// The arithmetic test has been split to make it easier to see the mismatched value (rather than true!=false) |
|
// According to : https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code#pointer-types |
|
// Conversion between pointers and integrals is "Implementation Defined". |
|
|
|
|
|
[TestCompiler(typeof(PointerArithmetic.Provider))] |
|
public static unsafe Int64 TestArithmeticPointerA(ref PointerArithmetic job) |
|
{ |
|
job.Execute(); |
|
if (sizeof(int*) == 4) |
|
return (Int64)(UInt32)(job.pointers[10]); // Workaround IL2CPP 32bit Bug : https://fogbugz.unity3d.com/f/cases/1254635/ |
|
return (Int64)job.pointers[10]; |
|
} |
|
|
|
[TestCompiler(typeof(PointerArithmetic.Provider))] |
|
public static unsafe Int64 TestArithmeticPointerB(ref PointerArithmetic job) |
|
{ |
|
job.Execute(); |
|
if (sizeof(int*) == 4) |
|
return (Int64)(UInt32)(job.pointers[20]); // Workaround IL2CPP 32bit Bug : https://fogbugz.unity3d.com/f/cases/1254635/ |
|
return (Int64)job.pointers[20]; |
|
} |
|
|
|
[TestCompiler(typeof(PointerArithmetic.Provider))] |
|
public static unsafe Int64 TestArithmeticPointerC(ref PointerArithmetic job) |
|
{ |
|
job.Execute(); |
|
if (sizeof(int*) == 4) |
|
return (Int64)(UInt32)(job.pointers[30]); // Workaround IL2CPP 32bit Bug : https://fogbugz.unity3d.com/f/cases/1254635/ |
|
return (Int64)job.pointers[30]; |
|
} |
|
|
|
[TestCompiler(typeof(PointerArithmetic.Provider))] |
|
public static unsafe Int64 TestArithmeticPointerD(ref PointerArithmetic job) |
|
{ |
|
job.Execute(); |
|
if (sizeof(int*) == 4) |
|
return (Int64)(UInt32)(job.pointers[40]); // Workaround IL2CPP 32bit Bug : https://fogbugz.unity3d.com/f/cases/1254635/ |
|
return (Int64)job.pointers[40]; |
|
} |
|
|
|
private struct TestData |
|
{ |
|
public int3 Min; |
|
public int Size; |
|
} |
|
|
|
[TestCompiler] |
|
public static unsafe int TestPointerWithIn() |
|
{ |
|
var foo = stackalloc TestData[1]; |
|
|
|
*foo = new TestData { Min = new int3(0, 1, 2), Size = 3 }; |
|
|
|
return SubFunctionWithInPointer(in foo); |
|
} |
|
|
|
private static unsafe int SubFunctionWithInPointer(in TestData* node) |
|
{ |
|
int3 data = node->Min; |
|
|
|
return node->Size + data.x + data.y + data.z; |
|
} |
|
|
|
[TestCompiler] |
|
public static unsafe int TestSystemBufferMemoryCopy() |
|
{ |
|
var a = stackalloc int[2]; |
|
a[0] = 42; |
|
System.Buffer.MemoryCopy(a + 0, a + 1, UnsafeUtility.SizeOf<int>(), UnsafeUtility.SizeOf<int>()); |
|
return a[1]; |
|
} |
|
|
|
[TestCompiler(0ul, byte.MinValue)] |
|
[TestCompiler(0ul, byte.MaxValue)] |
|
public static unsafe UInt64 PointerMathAddPNTypesByte(UInt64 p,byte a) |
|
{ |
|
var pointer = (byte*)p; |
|
return (UInt64)(pointer + a); // Pointer LHS |
|
} |
|
|
|
[TestCompiler(0ul, byte.MinValue)] |
|
[TestCompiler(0ul, byte.MaxValue)] |
|
public static unsafe UInt64 PointerMathAddNPTypesByte(UInt64 p,byte a) |
|
{ |
|
var pointer = (byte*)p; |
|
return (UInt64)(a + pointer); // Pointer RHS |
|
} |
|
|
|
[TestCompiler(0ul, byte.MinValue)] |
|
[TestCompiler(0ul, byte.MaxValue)] |
|
public static unsafe UInt64 PointerMathSubPNTypesByte(UInt64 p,byte a) |
|
{ |
|
var pointer = (byte*)p; |
|
return (UInt64)(pointer - a); // Pointer LHS (no RHS since not legal in C#) |
|
} |
|
|
|
[TestCompiler(0ul, sbyte.MinValue)] |
|
[TestCompiler(0ul, sbyte.MaxValue)] |
|
public static unsafe UInt64 PointerMathAddPNTypesSByte(UInt64 p,sbyte a) |
|
{ |
|
var pointer = (sbyte*)p; |
|
return (UInt64)(pointer + a); // Pointer LHS |
|
} |
|
|
|
[TestCompiler(0ul, sbyte.MinValue)] |
|
[TestCompiler(0ul, sbyte.MaxValue)] |
|
public static unsafe UInt64 PointerMathAddNPTypesSByte(UInt64 p,sbyte a) |
|
{ |
|
var pointer = (sbyte*)p; |
|
return (UInt64)(a + pointer); // Pointer RHS |
|
} |
|
|
|
[TestCompiler(0ul, sbyte.MinValue)] |
|
[TestCompiler(0ul, sbyte.MaxValue)] |
|
public static unsafe UInt64 PointerMathSubPNTypesSByte(UInt64 p,sbyte a) |
|
{ |
|
var pointer = (sbyte*)p; |
|
return (UInt64)(pointer - a); // Pointer LHS (no RHS since not legal in C#) |
|
} |
|
|
|
[TestCompiler(0ul, short.MinValue)] |
|
[TestCompiler(0ul, short.MaxValue)] |
|
public static unsafe UInt64 PointerMathAddPNTypesShort(UInt64 p,short a) |
|
{ |
|
var pointer = (short*)p; |
|
return (UInt64)(pointer + a); // Pointer LHS |
|
} |
|
|
|
[TestCompiler(0ul, short.MinValue)] |
|
[TestCompiler(0ul, short.MaxValue)] |
|
public static unsafe UInt64 PointerMathAddNPTypesShort(UInt64 p,short a) |
|
{ |
|
var pointer = (short*)p; |
|
return (UInt64)(a + pointer); // Pointer RHS |
|
} |
|
|
|
[TestCompiler(0ul, short.MinValue)] |
|
[TestCompiler(0ul, short.MaxValue)] |
|
public static unsafe UInt64 PointerMathSubPNTypesShort(UInt64 p,short a) |
|
{ |
|
var pointer = (short*)p; |
|
return (UInt64)(pointer - a); // Pointer LHS (no RHS since not legal in C#) |
|
} |
|
|
|
[TestCompiler(0ul, ushort.MinValue)] |
|
[TestCompiler(0ul, ushort.MaxValue)] |
|
public static unsafe UInt64 PointerMathAddPNTypesUShort(UInt64 p,ushort a) |
|
{ |
|
var pointer = (ushort*)p; |
|
return (UInt64)(pointer + a); // Pointer LHS |
|
} |
|
|
|
[TestCompiler(0ul, ushort.MinValue)] |
|
[TestCompiler(0ul, ushort.MaxValue)] |
|
public static unsafe UInt64 PointerMathAddNPTypesUShort(UInt64 p,ushort a) |
|
{ |
|
var pointer = (ushort*)p; |
|
return (UInt64)(a + pointer); // Pointer RHS |
|
} |
|
|
|
[TestCompiler(0ul, ushort.MinValue)] |
|
[TestCompiler(0ul, ushort.MaxValue)] |
|
public static unsafe UInt64 PointerMathSubPNTypesUShort(UInt64 p,ushort a) |
|
{ |
|
var pointer = (ushort*)p; |
|
return (UInt64)(pointer - a); // Pointer LHS (no RHS since not legal in C#) |
|
} |
|
|
|
[TestCompiler(0ul, int.MinValue)] |
|
[TestCompiler(0ul, int.MaxValue)] |
|
public static unsafe UInt64 PointerMathAddPNTypesInt(UInt64 p,int a) |
|
{ |
|
var pointer = (int*)p; |
|
return (UInt64)(pointer + a); // Pointer LHS |
|
} |
|
|
|
[TestCompiler(0ul, int.MinValue)] |
|
[TestCompiler(0ul, int.MaxValue)] |
|
public static unsafe UInt64 PointerMathAddNPTypesInt(UInt64 p,int a) |
|
{ |
|
var pointer = (int*)p; |
|
return (UInt64)(a + pointer); // Pointer RHS |
|
} |
|
|
|
[TestCompiler(0ul, int.MinValue)] |
|
[TestCompiler(0ul, int.MaxValue)] |
|
public static unsafe UInt64 PointerMathSubPNTypesInt(UInt64 p,int a) |
|
{ |
|
var pointer = (int*)p; |
|
return (UInt64)(pointer - a); // Pointer LHS (no RHS since not legal in C#) |
|
} |
|
|
|
[TestCompiler(0ul, uint.MinValue)] |
|
[TestCompiler(0ul, uint.MaxValue)] |
|
public static unsafe UInt64 PointerMathAddPNTypesUInt(UInt64 p,uint a) |
|
{ |
|
var pointer = (uint*)p; |
|
return (UInt64)(pointer + a); // Pointer LHS |
|
} |
|
|
|
[TestCompiler(0ul, uint.MinValue)] |
|
[TestCompiler(0ul, uint.MaxValue)] |
|
public static unsafe UInt64 PointerMathAddNPTypesUInt(UInt64 p,uint a) |
|
{ |
|
var pointer = (uint*)p; |
|
return (UInt64)(a + pointer); // Pointer RHS |
|
} |
|
|
|
[TestCompiler(0ul, uint.MinValue)] |
|
[TestCompiler(0ul, uint.MaxValue)] |
|
public static unsafe UInt64 PointerMathSubPNTypesUInt(UInt64 p,uint a) |
|
{ |
|
var pointer = (uint*)p; |
|
return (UInt64)(pointer - a); // Pointer LHS (no RHS since not legal in C#) |
|
} |
|
|
|
[TestCompiler(0ul, long.MinValue)] |
|
[TestCompiler(0ul, long.MaxValue)] |
|
public static unsafe UInt64 PolongerMathAddPNTypesLong(UInt64 p,long a) |
|
{ |
|
var polonger = (long*)p; |
|
return (UInt64)(polonger + a); // Polonger LHS |
|
} |
|
|
|
[TestCompiler(0ul, long.MinValue)] |
|
[TestCompiler(0ul, long.MaxValue)] |
|
public static unsafe UInt64 PolongerMathAddNPTypesLong(UInt64 p,long a) |
|
{ |
|
var polonger = (long*)p; |
|
return (UInt64)(a + polonger); // Polonger RHS |
|
} |
|
|
|
[TestCompiler(0ul, long.MinValue)] |
|
[TestCompiler(0ul, long.MaxValue)] |
|
public static unsafe UInt64 PolongerMathSubPNTypesLong(UInt64 p,long a) |
|
{ |
|
var polonger = (long*)p; |
|
return (UInt64)(polonger - a); // Polonger LHS (no RHS since not legal in C#) |
|
} |
|
|
|
[TestCompiler(0ul, ulong.MinValue)] |
|
[TestCompiler(0ul, ulong.MaxValue)] |
|
public static unsafe UInt64 PolongerMathAddPNTypesULong(UInt64 p,ulong a) |
|
{ |
|
var polonger = (ulong*)p; |
|
return (UInt64)(polonger + a); // Polonger LHS |
|
} |
|
|
|
[TestCompiler(0ul, ulong.MinValue)] |
|
[TestCompiler(0ul, ulong.MaxValue)] |
|
public static unsafe UInt64 PolongerMathAddNPTypesULong(UInt64 p,ulong a) |
|
{ |
|
var polonger = (ulong*)p; |
|
return (UInt64)(a + polonger); // Polonger RHS |
|
} |
|
|
|
[TestCompiler(0ul, ulong.MinValue)] |
|
[TestCompiler(0ul, ulong.MaxValue)] |
|
public static unsafe UInt64 PolongerMathSubPNTypesULong(UInt64 p,ulong a) |
|
{ |
|
var polonger = (ulong*)p; |
|
return (UInt64)(polonger - a); // Polonger LHS (no RHS since not legal in C#) |
|
} |
|
} |
|
}
|
|
|