using System; using System.Runtime.CompilerServices; using Burst.Compiler.IL.Tests.Helpers; using NUnit.Framework; using Unity.Mathematics; namespace Burst.Compiler.IL.Tests { internal partial class Expressions { [TestCompiler((uint)(1 << 20))] [TestCompiler((uint)(1 << 15))] [TestCompiler(UInt32.MaxValue)] public static float ConvertUIntToFloat(uint rx) { var x = 2 * ((float)rx / uint.MaxValue - 0.5f); return x; } [TestCompiler((int)(1 << 20))] [TestCompiler((int)(1 << 15))] [TestCompiler(int.MinValue)] [TestCompiler(int.MaxValue)] public static float ConvertIntToFloat(int rx) { return (float) rx / -((float) int.MinValue); } [TestCompiler((uint)(1 << 20))] [TestCompiler((uint)(1 << 15))] [TestCompiler(UInt32.MaxValue)] public static float ConvertIntToFloat2(uint rx) { return 4.656613E-10f * (float)(int)rx; } [TestCompiler((uint)(1 << 20))] [TestCompiler((uint)(1 << 15))] [TestCompiler(UInt32.MaxValue)] public static float ConvertUIntToFloat2(uint rx) { return 4.656613E-10f * (float)rx; } [TestCompiler((int)-1, (uint)17)] [TestCompiler((int)(1 << 20), (uint)17)] [TestCompiler((int)(1 << 15), (uint)17)] [TestCompiler(int.MinValue, (uint)17)] [TestCompiler(int.MaxValue, (uint)17)] public static double ConvertIntToDouble(int rx, uint ry) { return (double)(rx + (int)ry) * 0.5; } [TestCompiler((int)-1, (uint)17)] [TestCompiler((int)(1 << 20), (uint)17)] [TestCompiler((int)(1 << 15), (uint)17)] [TestCompiler(int.MinValue, (uint)17)] [TestCompiler(int.MaxValue, (uint)17)] public static double ConvertIntToDouble2(int rx, uint ry) { return (double)((uint)rx + ry) * 0.5; } [TestCompiler(int.MinValue)] [TestCompiler(-15)] [TestCompiler(-1)] [TestCompiler(1)] [TestCompiler(15)] [TestCompiler(int.MaxValue)] public static long ConvertIntToLong(int value) { return value; } [TestCompiler(int.MinValue)] [TestCompiler(-15)] [TestCompiler(-1)] [TestCompiler(1)] [TestCompiler(15)] [TestCompiler(int.MaxValue)] public static ulong ConvertIntToULong(int value) { return (ulong)value; } [TestCompiler] public static ulong ConvertIntToLongConst() { return int.MaxValue; } [TestCompiler(1U)] [TestCompiler(15U)] [TestCompiler(uint.MaxValue)] public static long ConvertUIntToLong(uint value) { return value; } [TestCompiler] public static ulong ConvertUIntToLongConst() { return uint.MaxValue; } [TestCompiler(1U)] [TestCompiler(15U)] [TestCompiler(uint.MaxValue)] public static ulong ConvertUIntToULong(uint value) { return value; } [TestCompiler] public static ulong ConvertUIntToULongConst() { return uint.MaxValue; } [TestCompiler((uint)10)] [TestCompiler((uint)0xFFFFFFF6)] public static float NegateUIntToFloat(uint val) { return (float)-val; } [TestCompiler((uint)10)] [TestCompiler((uint)0xFFFFFFF6)] public static double NegateUIntToDouble(uint val) { return (double)-val; } [TestCompiler((ushort)10)] [TestCompiler((ushort)0xFFF6)] public static float NegateUInt16ToFloat(ushort val) { return (float)-val; } [TestCompiler((ushort)10)] [TestCompiler((ushort)0xFFF6)] public static double NegateUInt16ToDouble(ushort val) { return (double)-val; } [TestCompiler((Byte)100)] [TestCompiler((Byte)1)] [TestCompiler((Byte)0xF6)] public static float NegateByteToFloat(Byte val) { return (float)-val; } [TestCompiler((Byte)100)] [TestCompiler((Byte)1)] [TestCompiler((Byte)0xF6)] public static double NegateByteToDouble(Byte val) { return (double)-val; } [TestCompiler((Byte)'a')] [TestCompiler((Byte)0xF6)] public static float NegateCharToFloat(Byte val) { return (float)(-(char)val); } [TestCompiler((Byte)'a')] [TestCompiler((Byte)0xF6)] public static double NegateCharToDouble(Byte val) { return (double)-((char)val); } [TestCompiler((Byte)100)] [TestCompiler((Byte)1)] public static float RandomFloatFromByte(Byte deviation) => new Unity.Mathematics.Random(8189782u) .NextFloat(-deviation, deviation); [TestCompiler(short.MinValue)] [TestCompiler((short)-15)] [TestCompiler((short)-1)] [TestCompiler((short)1)] [TestCompiler((short)15)] [TestCompiler(short.MaxValue)] public static int ConvertShortToInt(short value) { return value; } [TestCompiler] public static int ConvertShortToIntConstMin() { return short.MinValue; } [TestCompiler] public static int ConvertShortToIntConstMax() { return short.MaxValue; } [TestCompiler] public static int ConvertUShortToIntConstMax() { return ushort.MaxValue; } [TestCompiler] public static uint ConvertUShortToUIntConstMax() { return ushort.MaxValue; } [TestCompiler(short.MinValue)] [TestCompiler((short)-15)] [TestCompiler((short)-1)] [TestCompiler((short)1)] [TestCompiler((short)15)] [TestCompiler(short.MaxValue)] public static long ConvertShortToLong(short value) { return value; } [TestCompiler] public static long ConvertShortToLongConstMin() { return short.MinValue; } [TestCompiler] public static long ConvertShortToLongConstMax() { return short.MaxValue; } [TestCompiler(short.MinValue)] [TestCompiler((short)-15)] [TestCompiler((short)-1)] [TestCompiler((short)1)] [TestCompiler((short)15)] [TestCompiler(short.MaxValue)] public static ulong ConvertShortToULong(short value) { return (ulong)value; } [TestCompiler] public static ulong ConvertShortToULongConstMin() { return unchecked((ulong)short.MinValue); } [TestCompiler] public static ulong ConvertShortToULongConstMax() { return (ulong)short.MaxValue; } [TestCompiler(sbyte.MinValue)] [TestCompiler((sbyte)-15)] [TestCompiler((sbyte)-1)] [TestCompiler((sbyte)1)] [TestCompiler((sbyte)15)] [TestCompiler(sbyte.MaxValue)] public static long ConvertSbyteToLong(sbyte value) { return value; } [TestCompiler] public static long ConvertSbyteToLongConstMin() { return sbyte.MinValue; } [TestCompiler] public static long ConvertSbyteToLongConstMax() { return sbyte.MinValue; } [TestCompiler(sbyte.MinValue)] [TestCompiler((sbyte)-15)] [TestCompiler((sbyte)-1)] [TestCompiler((sbyte)1)] [TestCompiler((sbyte)15)] [TestCompiler(sbyte.MaxValue)] public static uint ConvertSbyteToUInt(sbyte value) { return (uint)value; } [TestCompiler] public static uint ConvertSbyteToUIntConstMin() { return unchecked((uint)sbyte.MinValue); } [TestCompiler] public static uint ConvertSbyteToUIntConstMax() { return unchecked((uint)sbyte.MinValue); } [Ignore("Incorrect results in mono")] [TestCompiler(0.0f)] [TestCompiler(1.0f)] [TestCompiler(0.5f)] [TestCompiler(0.1f)] [TestCompiler(0.9f, OverrideResultOnMono = 135)] public static byte ConvertFloatToByte(float value) { return (byte) (150 * value); } [TestCompiler(true, true)] [TestCompiler(true, false)] [TestCompiler(false, true)] [TestCompiler(false, false)] public static bool CompareEqualBool(bool left, bool right) { return left == right; } [TestCompiler(true, true)] [TestCompiler(true, false)] [TestCompiler(false, true)] [TestCompiler(false, false)] public static bool CompareNotEqualBool(bool left, bool right) { return left != right; } [TestCompiler(true)] [TestCompiler(false)] public static bool CompareBoolWithConst(bool left) { return left == false; } [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(-1, -1)] [TestCompiler(0, 0)] public static bool CompareEqualInt32(int left, int right) { return left == right; } [TestCompiler(1)] [TestCompiler(0)] [TestCompiler(-1)] public static bool CompareEqualInt32WithConst(int left) { return left == -1; } [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(-1, -1)] [TestCompiler(0, 0)] public static bool CompareNotEqualInt32(int left, int right) { return left != right; } [TestCompiler(1, 5)] [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(-1, 1)] [TestCompiler(0, 1)] public static bool CompareLessThanInt32(int left, int right) { return left < right; } [TestCompiler(1L, 5)] [TestCompiler(1L, 1)] [TestCompiler(0L, -1)] [TestCompiler(-1L, 1)] [TestCompiler(0L, 1)] public static bool CompareLessThanInt64Int32(long left, int right) { return left < right; } [TestCompiler(1U, 5)] [TestCompiler(1U, 1)] [TestCompiler(0U, -1)] [TestCompiler(0x80000000U, 1)] [TestCompiler(0xFFFFFFFFU, 1)] [TestCompiler(0U, 1)] public static bool CompareLessThanUInt32Int32(uint left, int right) { return left < right; } [TestCompiler(1U, 5)] [TestCompiler(1U, 1)] [TestCompiler(0U, -1)] [TestCompiler(0x80000000U, 1)] [TestCompiler(0xFFFFFFFFU, 1)] [TestCompiler(0U, 1)] public static bool CompareGreaterThanUInt32Int32(uint left, int right) { return left > right; } [TestCompiler(5, 1U)] [TestCompiler(1, 1U)] [TestCompiler(-1, 0U)] [TestCompiler(1, 0x80000000U)] [TestCompiler(1, 0xFFFFFFFFU)] [TestCompiler(1, 0U)] public static bool CompareLessThanInt32UInt32(int left, uint right) { return left < right; } [TestCompiler(5, 1U)] [TestCompiler(1, 1U)] [TestCompiler(-1, 0U)] [TestCompiler(1, 0x80000000U)] [TestCompiler(1, 0xFFFFFFFFU)] [TestCompiler(1, 0U)] public static bool CompareGreaterThanInt32UInt32(int left, uint right) { return left > right; } [TestCompiler(1, 5)] [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(-1, 1)] [TestCompiler(0, 1)] public static bool CompareGreaterThanInt32(int left, int right) { return left > right; } [TestCompiler(1, 5)] [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(40, -1)] [TestCompiler(-10, 3)] [TestCompiler(0, 13)] [TestCompiler(4, 7)] [TestCompiler(125, 7)] public static bool CompareGreaterOrEqualInt32(int left, int right) { return left >= right; } [TestCompiler(1, 5)] [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(40, -1)] [TestCompiler(-10, 3)] [TestCompiler(0, 13)] [TestCompiler(4, 7)] [TestCompiler(125, 7)] public static bool CompareLessOrEqualInt32(int left, int right) { return left <= right; } [TestCompiler] public static bool CompareEqualFloatConstant() { return 0 == float.NaN; } [TestCompiler] public static bool CompareNotEqualFloatConstant() { return 0 != float.NaN; } [TestCompiler] public static bool CompareLessThanFloatConstant() { return 0 < float.NaN; } [TestCompiler] public static bool CompareLessThanEqualFloatConstant() { return 0 <= float.NaN; } [TestCompiler] public static bool CompareGreaterThanFloatConstant() { return 0 > float.NaN; } [TestCompiler] public static bool CompareLGreaterThanEqualFloatConstant() { return 0 >= float.NaN; } [TestCompiler(DataRange.Minus100To100, DataRange.Minus100To100)] [TestCompiler(0, float.NaN)] [TestCompiler(float.NaN, float.NaN)] [TestCompiler(float.PositiveInfinity, float.NegativeInfinity)] [TestCompiler(float.PositiveInfinity, float.PositiveInfinity)] [TestCompiler(float.NegativeInfinity, float.NegativeInfinity)] public static bool CompareEqualFloat(float left, float right) { return left == right; } [TestCompiler(DataRange.Minus100To100, DataRange.Minus100To100)] [TestCompiler(0, -0)] [TestCompiler(0, float.NaN)] [TestCompiler(float.NaN, float.NaN)] [TestCompiler(float.PositiveInfinity, float.NegativeInfinity)] [TestCompiler(float.PositiveInfinity, float.PositiveInfinity)] [TestCompiler(float.NegativeInfinity, float.NegativeInfinity)] public static bool CompareNotEqualFloat(float left, float right) { return left != right; } [TestCompiler(DataRange.Minus100To100, DataRange.Minus100To100)] [TestCompiler(0, -0)] [TestCompiler(0, float.NaN)] [TestCompiler(float.NaN, float.NaN)] [TestCompiler(float.PositiveInfinity, float.NegativeInfinity)] [TestCompiler(float.PositiveInfinity, float.PositiveInfinity)] [TestCompiler(float.NegativeInfinity, float.NegativeInfinity)] public static bool CompareLessThanFloat(float left, float right) { return left < right; } [TestCompiler(DataRange.Minus100To100, DataRange.Minus100To100)] [TestCompiler(0, -0)] [TestCompiler(0, float.NaN)] [TestCompiler(float.NaN, float.NaN)] [TestCompiler(float.PositiveInfinity, float.NegativeInfinity)] [TestCompiler(float.PositiveInfinity, float.PositiveInfinity)] [TestCompiler(float.NegativeInfinity, float.NegativeInfinity)] public static bool CompareLessThanEqualFloat(float left, float right) { return left <= right; } [TestCompiler(DataRange.Minus100To100, DataRange.Minus100To100)] [TestCompiler(0, -0)] [TestCompiler(0, float.NaN)] [TestCompiler(float.NaN, float.NaN)] [TestCompiler(float.PositiveInfinity, float.NegativeInfinity)] [TestCompiler(float.PositiveInfinity, float.PositiveInfinity)] [TestCompiler(float.NegativeInfinity, float.NegativeInfinity)] public static bool CompareGreaterThanFloat(float left, float right) { return left > right; } [TestCompiler(DataRange.Minus100To100, DataRange.Minus100To100)] [TestCompiler(0, -0)] [TestCompiler(0, float.NaN)] [TestCompiler(float.NaN, float.NaN)] [TestCompiler(float.PositiveInfinity, float.NegativeInfinity)] [TestCompiler(float.PositiveInfinity, float.PositiveInfinity)] [TestCompiler(float.NegativeInfinity, float.NegativeInfinity)] public static bool CompareGreaterThanEqualFloat(float left, float right) { return left >= right; } #if UNITY_2021_3_OR_NEWER [TestCompiler(12321)] public static nint BitwiseNotNInt(int x) { var y = (nint)x; return ~y; } [TestCompiler(0x3213522U)] public static nuint BitwiseNUint(uint x) { var y = (nuint)x; return ~y; } [TestCompiler(12321)] public static nint NegateNInt(int x) { var y = (nint)x; return -y; } #if !ENABLE_IL2CPP [TestCompiler(0x3213522U)] public static unsafe uint NotNintToPtr(uint x) { var ptr = (void*)x; static void* Op(void* ptr) => (void*)~(nint)ptr; return (uint)Op(ptr); } [TestCompiler(0x3213522U)] public static unsafe uint NotNUintToPtr(uint x) { var ptr = (void*)x; static void* Op(void* ptr) => (void*)~(nuint)ptr; return (uint)Op(ptr); } [TestCompiler(0x3213522U)] public static unsafe uint NegateNintToPtr(uint x) { var ptr = (void*)x; static void* Op(void* ptr) => (void*)-(nint)ptr; return (uint)Op(ptr); } [TestCompiler(0x3213522U, 0x3221312U)] public static unsafe uint AddNintToPtr(uint x, uint y) { var ptr = (void*)x; static void* Op(void* ptr, uint y) => (void*)((nint)ptr + (nint)y); return (uint)Op(ptr, y); } [TestCompiler(0x3213522U, 0x3221312U)] public static unsafe uint SubNintToPtr(uint x, uint y) { var ptr = (void*)x; static void* Op(void* ptr, uint y) => (void*)((nint)ptr - (nint)y); return (uint)Op(ptr, y); } #endif #endif [TestCompiler(1, 5)] [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(40, -1)] [TestCompiler(-10, 3)] [TestCompiler(0, 13)] [TestCompiler(4, 7)] [TestCompiler(125, 7)] public static int BinaryNumericAdd(int left, int right) { return left + right; } [TestCompiler(1, 5)] [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(40, -1)] [TestCompiler(-10, 3)] [TestCompiler(0, 13)] [TestCompiler(4, 7)] [TestCompiler(125, 7)] public static int BinaryNumericSub(int left, int right) { return left - right; } [TestCompiler(1, 5)] [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(40, -1)] [TestCompiler(-10, 3)] [TestCompiler(0, 13)] [TestCompiler(4, 7)] [TestCompiler(125, 7)] public static int BinaryNumericDiv(int left, int right) { return left / right; } [TestCompiler(1L, 5)] [TestCompiler(1L, 1)] [TestCompiler(0L, -1)] [TestCompiler(40L, -1)] [TestCompiler(-10L, 3)] [TestCompiler(0L, 13)] [TestCompiler(4L, 7)] [TestCompiler(125L, 7)] public static long BinaryNumericDiv64(long left, int right) { return left / right; } [TestCompiler(1, 5)] [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(40, -1)] [TestCompiler(-10, 3)] [TestCompiler(0, 13)] [TestCompiler(4, 7)] [TestCompiler(125, 7)] public static int BinaryNumericRem(int left, int right) { return left % right; } [TestCompiler(1, 5)] [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(40, -1)] [TestCompiler(-10, 3)] [TestCompiler(0, 13)] [TestCompiler(4, 7)] [TestCompiler(125, 7)] public static int BinaryNumericMul(int left, int right) { return left * right; } [TestCompiler(1, 5)] [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(40, -1)] [TestCompiler(-10, 3)] [TestCompiler(0, 13)] [TestCompiler(4, 7)] [TestCompiler(125, 7)] public static int BinaryNumericAnd(int left, int right) { return left & right; } [TestCompiler(1, 5)] [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(40, -1)] [TestCompiler(-10, 3)] [TestCompiler(0, 13)] [TestCompiler(4, 7)] [TestCompiler(125, 7)] public static int BinaryNumericOr(int left, int right) { return left | right; } [TestCompiler(1, 5)] [TestCompiler(1, 1)] [TestCompiler(0, -1)] [TestCompiler(40, -1)] [TestCompiler(-10, 3)] [TestCompiler(0, 13)] [TestCompiler(4, 7)] [TestCompiler(125, 7)] public static int BinaryNumericXor(int left, int right) { return left ^ right; } [TestCompiler(1, 0)] [TestCompiler(1, 5)] [TestCompiler(7, 10)] [TestCompiler(-1, 1)] public static int BinaryNumericShiftLeft(int left, int right) { return left << right; } [TestCompiler(1, 0)] [TestCompiler(1, 5)] [TestCompiler(7, 10)] [TestCompiler(-1, 1)] public static int BinaryNumericShiftRight(int left, int right) { return left >> right; } [TestCompiler(1U, 0)] [TestCompiler(1U, 5)] [TestCompiler(7U, 10)] [TestCompiler(0xFFFFFFFFU, 1)] public static uint BinaryNumericShiftLeftUInt32(uint left, int right) { return left << right; } [TestCompiler(1U, 0)] [TestCompiler(1U, 5)] [TestCompiler(7U, 10)] [TestCompiler(0x80000000U, 1)] [TestCompiler(0xFFFFFFFFU, 1)] public static uint BinaryNumericShiftRightUInt32(uint left, int right) { return left >> right; } [TestCompiler(1U, 0)] [TestCompiler(1U, 5)] [TestCompiler(7U, 10)] [TestCompiler(0x80000000U, 1)] [TestCompiler(0xFFFFFFFFU, 1)] public static int BinaryNumericShiftRightUIntToInt32(uint left, int right) { return ((int)left) >> right; } #if UNITY_2021_3_OR_NEWER [TestCompiler(0U)] [TestCompiler(1U)] [TestCompiler(0x212412U)] public static nuint UnderflowNUInt(uint i) { return Not((nuint)i); [MethodImpl(MethodImplOptions.NoInlining)] static nuint Not(nuint n) => 0 - n - 1; } [TestCompiler(0)] [TestCompiler(1)] [TestCompiler(0x212412)] public static nint UnderflowNInt(int i) { return Not((nint)i); [MethodImpl(MethodImplOptions.NoInlining)] static nint Not(nint n) => 0 - n - 1; } [TestCompiler(2, 3)] [TestCompiler(5, -2)] public static nint BinaryNInt(int i, int j) { var m = (nint)i; var n = (nint)j; var r = ((m + n) << 0) + ((m * n) << 4) + ((m / n) << 8) + ((m - n) << 12) + ((m % n) << 16) + ((m | n) << 20) + ((m & n) << 24) + ((m ^ n) << 28); return r; } [TestCompiler(2U, 3U)] [TestCompiler(5U, 2U)] public static nuint BinaryNUInt(uint i, uint j) { var m = (nuint)i; var n = (nuint)j; var r = ((m + n) << 0) + ((m * n) << 4) + ((m / n) << 8) + ((m - n) << 12) + ((m % n) << 16) + ((m | n) << 20) + ((m & n) << 24) + ((m ^ n) << 28); return r; } #endif [TestCompiler] public static int ConstantMinus1() { return -1; } [TestCompiler] public static int Constant1() { return 1; } [TestCompiler] public static int Constant2() { return 2; } [TestCompiler] public static int Constant3() { return 3; } [TestCompiler] public static int Constant4() { return 4; } [TestCompiler] public static int Constant5() { return 5; } [TestCompiler] public static int Constant6() { return 6; } [TestCompiler] public static int Constant7() { return 7; } [TestCompiler] public static int Constant8() { return 8; } [TestCompiler] public static int Constant121() { return 121; } [TestCompiler] public static bool ReturnBoolTrue() { return true; } [TestCompiler] public static bool ReturnBoolFalse() { return false; } [TestCompiler((int)0x10203040)] [TestCompiler((int)0x20203040)] [TestCompiler((int)0x30203040)] [TestCompiler((int)0x40203040)] [TestCompiler((int)0x50203040)] [TestCompiler((int)0x60203040)] [TestCompiler((int)0x70203040)] public static int AddOverflowInt(int x) { x += 0x70506070; return x; } [TestCompiler] public static int test_expr_add_one_to_zero() { var x = 0; x++; return x; } [TestCompiler(1f)] public static float test_expr_add_multiples(float a) { return a + a + a + a; } [TestCompiler(1f, 2f)] public static float test_expr_add_two_arguments(float a, float b) { return a + b; } [TestCompiler(3f, 4f)] public static float test_expr_multiply_two_arguments(float a, float b) { return a * b; } [TestCompiler(3f)] [TestCompiler(-4f)] [TestCompiler(0f)] public static float test_expr_negateResult_float(float a) { return -a; } [TestCompiler((sbyte)3)] [TestCompiler((sbyte)-4)] [TestCompiler((sbyte)0)] [TestCompiler(sbyte.MinValue)] [TestCompiler(sbyte.MaxValue)] public static int test_expr_negateResult_sbyte(sbyte a) { return -a; } [TestCompiler((byte)3)] [TestCompiler((byte)0)] [TestCompiler(byte.MaxValue, OverrideManagedResult = -255)] // TODO: IL2CPP on macOS currently produces incorrect result of "1". Remove this OverrideManagedResult when that bug is fixed. public static int test_expr_negateResult_byte(byte a) { return -a; } [TestCompiler((short)3)] [TestCompiler((short)-4)] [TestCompiler((short)0)] [TestCompiler(short.MinValue)] [TestCompiler(short.MaxValue)] public static int test_expr_negateResult_short(short a) { return -a; } [TestCompiler((ushort)3)] [TestCompiler((ushort)0)] [TestCompiler(ushort.MaxValue, OverrideManagedResult = -65535)] // TODO: IL2CPP on macOS currently produces incorrect result of "1". Remove this OverrideManagedResult when that bug is fixed. public static int test_expr_negateResult_ushort(ushort a) { return -a; } [TestCompiler(3)] [TestCompiler(-4)] [TestCompiler(0)] [TestCompiler(int.MinValue)] [TestCompiler(int.MaxValue)] public static int test_expr_negateResult_int(int a) { return -a; } [TestCompiler(3u)] [TestCompiler(0u)] [TestCompiler(uint.MaxValue)] public static long test_expr_negateResult_uint(uint a) { return -a; } [TestCompiler((long)3)] [TestCompiler((long)-4)] [TestCompiler((long)0)] [TestCompiler(long.MinValue)] [TestCompiler(long.MaxValue)] public static long test_expr_negateResult_long(long a) { return -a; } [TestCompiler] public static float test_expr_return_constant() { return 12f; } [TestCompiler] public static float test_multiple_assigment() { float x, y, z; x = y = z = 5.0F; return x + y + z; } [TestCompiler(4f, 9f)] public static float test_expr_various_math(float a, float b) { return (a + b) * b * b * 0.4f / (a + a + a * 0.2f); } [TestCompiler(4.1f)] public static float test_expr_multiply_int_by_float(float a) { var i = 18; return i * a; } [TestCompiler(4f)] public static int test_expr_cast_float_to_int(float a) { return (int)a; } [TestCompiler(4)] public static float test_expr_cast_int_to_float(int a) { return a; } [TestCompiler(5)] public static int test_expr_assign_to_argument(int a) { a = a * a; return a; } [TestCompiler(7)] public static int test_expr_postincrement(int input) { var a = input++; return a + input; } [TestCompiler(2)] [TestCompiler(3)] public static int test_expr_mod(int input) { return input % 2; } [TestCompiler(0, 0)] [TestCompiler(0, 1)] [TestCompiler(1, 0)] [TestCompiler(1, 1)] public static int test_expr_xor(int a, int b) { return a ^ b; } [TestCompiler(1, 2)] [TestCompiler(0, 0)] [TestCompiler(1, 0)] [TestCompiler(1, 1)] public static int test_expr_or(int a, int b) { return a | b; } [TestCompiler(1, 3)] [TestCompiler(0, 0)] [TestCompiler(1, 0)] [TestCompiler(1, 1)] public static int test_expr_and(int a, int b) { return a & b; } [TestCompiler(-100000.0F)] public static float test_math_large_values(float a) { return (a * a) + ((a + 3.0F) * a); } [TestCompiler(1)] [TestCompiler(150)] [TestCompiler(-1)] [TestCompiler(-150)] public static int test_expr_shift_right(int n) { return n >> 3; } [TestCompiler(1)] [TestCompiler(31)] public static int test_expr_shift(int n) { int a = 5; a <<= n; a += (a >> 31); return a; } [TestCompiler(2)] [TestCompiler(-3)] public static int test_expr_complement(int input) { return ~input; } [TestCompiler] public static int test_expr_sizeof_int() { return sizeof(int); } [TestCompiler(-1)] [TestCompiler(0)] [TestCompiler(12)] public static int test_expr_generic_equatable(int a) { if (EqualityTester.Check(a, 12)) return 1; else return 0; } struct EqualityTester where TKey : IEquatable { public static bool Check(TKey value1, TKey value2) { return value1.Equals(value2); } } [TestCompiler(0)] [TestCompiler(1)] [TestCompiler(-1)] public static bool test_expr_bool_passing(int a) { return a == 0; } const int ConstValue = 5; [TestCompiler] public static int test_expr_load_static_constant() { return ConstValue; } [TestCompiler(1)] [TestCompiler(-1)] public static int OutInt32(int a) { int b; OutputInt32(out b); return a + b; } [TestCompiler(-1)] [TestCompiler(1)] public static int CallPushAndPop(int a) { int result = 0; int value; TryAdd(a, out value); result += value * 10; TryAdd(a * 2, out value); result += value * 10; TryAdd(a * 3, out value); result += value * 10; TryAdd(a * 4, out value); result += value * 10; return result; } private static readonly Yoyo[] StaticArray2 = new Yoyo[5]; struct Yoyo { #pragma warning disable 0169, 0649 public int a; private int b; #pragma warning restore 0169, 0649 } private static bool TryAdd(int a, out int result) { result = a + 5; return true; } public static void OutputInt32(out int value) { value = 5; } [TestCompiler] public static long TypeConversionAndOverflow() { byte ba = 0xFF; byte bb = 1; sbyte sba = 127; sbyte sbb = 1; short sa = 0x7FFF; short sb = 1; ushort usa = 0xFFFF; ushort usb = 1; uint x = 0xFFFFFFFF; int y = 1; long z = 1; return (ba + bb) + (sba + sbb) + (sa + sb) + (usa + usb) + (x + y) + (x + z); } private static void AssignValue(int switchValue, ref float value) { value = 0.0F; if (switchValue == 0) return; value = 1.0F; if (switchValue == 1) return; value = 2.0F; return; } [TestCompiler(0)] [TestCompiler(1)] [TestCompiler(2)] public static float test_expr_return_from_branch(int test) { float ret_val = -1.0F; AssignValue(test, ref ret_val); return ret_val; } [TestCompiler(DataRange.Standard, DataRange.Standard)] public static bool BoolOrFunction(bool left, int x) { return left | ReturnBool(x); } private static bool ReturnBool(int x) { return x > 5; } [TestCompiler] public static unsafe uint TestStackAlloc() { uint* result = stackalloc uint[4]; for (uint i = 0; i < 4; i++) { result[i] = i + 1; } uint sum = 0; for (uint i = 0; i < 4; i++) { sum += result[i]; } return sum; } public static int BoolRefUser(ref bool isDone) { return 1; } [TestCompiler] public static int LocalBoolPassedByRef() { var isDone = false; return BoolRefUser(ref isDone); } public enum TestEnum { v0 = 0, v1 = 1, v2 = 2, v3 = 3, v4 = 4, v5 = 5, v6 = 6, } public static float SameCode(TestEnum val1, TestEnum val2) { float diff = val2 - val1; return diff; } [TestCompiler] public static float EnumToFloatConversion() { return SameCode(TestEnum.v6, TestEnum.v0); } public enum SByteEnum : sbyte { A = 0, B = 6, C = -128 } [TestCompiler(SByteEnum.C)] public static float TestSByteEnum(SByteEnum a) { return (float) a; } public enum UnsignedEnum : uint { A = 0, B = 6, C = 0xFFFFFFFF } [TestCompiler(UnsignedEnum.C)] public static float TestUnsignedEnum(UnsignedEnum a) { return (float) a; } [TestCompiler(1)] public static int AddOvf(int x) { return checked(x + 1); } [TestCompiler(1)] public static int MulOvf(int x) { return checked(x * 2); } [TestCompiler(1)] public static int SubOvf(int x) { return checked(x - 1); } [TestCompiler(1u)] public static uint SubOvfUn(uint x) { return checked(x - 1); } [TestCompiler(1u)] public static uint BgeUn(uint x) { // We need a non-short opcode, therefore the branch has to be big enough for the offset to not fit in a byte: return x >= 1 ? 1 : x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x; } [TestCompiler(1)] public static int Bgt(int x) { // We need a non-short opcode, therefore the branch has to be big enough for the offset to not fit in a byte: return x > 1 ? 1 : x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x; } [TestCompiler(1)] public static int Beq(int x) { // We need a non-short opcode, therefore the branch has to be big enough for the offset to not fit in a byte: return x == 1 ? 1 : x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x; } [TestCompiler(1)] public static int Bge(int x) { // We need a non-short opcode, therefore the branch has to be big enough for the offset to not fit in a byte: return x >= 1 ? 1 : x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x; } [TestCompiler(1)] public static int Ble(int x) { // We need a non-short opcode, therefore the branch has to be big enough for the offset to not fit in a byte: return x <= 1 ? 1 : x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x; } [TestCompiler(1)] public static int Blt(int x) { // We need a non-short opcode, therefore the branch has to be big enough for the offset to not fit in a byte: return x < 1 ? 1 : x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x; } [TestCompiler(1u)] public static uint BgtUn(uint x) { // We need a non-short opcode, therefore the branch has to be big enough for the offset to not fit in a byte: return x > 1 ? 1 : x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x; } [TestCompiler(1u)] public static uint BgtUnS(uint x) { return x > 1 ? 1 : x; } [TestCompiler(1u)] public static uint BleUn(uint x) { // We need a non-short opcode, therefore the branch has to be big enough for the offset to not fit in a byte: return x <= 1 ? 1 : x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x; } [TestCompiler(1u)] public static uint BltUn(uint x) { // We need a non-short opcode, therefore the branch has to be big enough for the offset to not fit in a byte: return x < 1 ? 1 : x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x; } [TestCompiler(1u)] public static uint BltUnS(uint x) { // We need a non-short opcode, therefore the branch has to be big enough for the offset to not fit in a byte: return x < 1 ? 1 : 0u; } [TestCompiler(true)] public static int Brtrue(bool x) { return x ? 1 : 0; } [TestCompiler(false)] public static int Brfalse(bool x) { return !x ? 1 : 0; } [TestCompiler(1)] public static sbyte ConvI1(int x) { return (sbyte) x; } [TestCompiler(1)] public static short ConvI2(int x) { return (short) x; } [TestCompiler(1u)] public static sbyte ConvOvfI1Un(uint x) { return checked((sbyte) x); } [TestCompiler(1u)] public static short ConvOvfI2Un(uint x) { return checked((short) x); } [TestCompiler(1u)] public static int ConvOvfI4Un(uint x) { return checked((int) x); } [TestCompiler(1ul)] public static long ConvOvfI8Un(ulong x) { return checked((long) x); } [TestCompiler(1u)] public static byte ConvOvfU1Un(uint x) { return checked((byte) x); } [TestCompiler(1u)] public static ushort ConvOvfU2Un(uint x) { return checked((ushort) x); } [TestCompiler(1ul)] public static uint ConvOvfU4Un(ulong x) { return checked((uint) x); } [TestCompiler(1)] public static sbyte ConvOvfI1(int x) { return checked((sbyte) x); } [TestCompiler(1)] public static short ConvOvfI2(int x) { return checked((short) x); } [TestCompiler(1)] public static int ConvOvfI4(long x) { return checked((int) x); } [TestCompiler(1)] public static long ConvOvfI8(double x) { return checked((long) x); } [TestCompiler(1)] public static byte ConvOvfU1(int x) { return checked((byte) x); } [TestCompiler(1)] public static ushort ConvOvfU2(int x) { return checked((ushort) x); } [TestCompiler(1)] public static uint ConvOvfU4(int x) { return checked((uint) x); } [TestCompiler(1)] public static ulong ConvOvfU8(double x) { return checked((ulong) x); } private static readonly int[] MyArray = { 0, 1, 2 }; [TestCompiler((byte)0)] public static int LdelemByte(byte index) => MyArray[index]; [TestCompiler((ushort)0)] public static int LdelemUInt16(ushort index) => MyArray[index]; [TestCompiler((uint)0)] public static int LdelemUInt32(uint index) => MyArray[index]; [TestCompiler((ulong)0)] public static int LdelemUInt64(ulong index) => MyArray[index]; [TestCompiler((short)0)] public static int LdelemInt16(short index) => MyArray[index]; [TestCompiler(0)] public static int LdelemInt32(int index) => MyArray[index]; [TestCompiler((long)0)] public static int LdelemInt64(long index) => MyArray[index]; [TestCompiler(1.0f)] public static float FSubByDenormBecomesFAdd(float x) { return x - 1.40129846432481707092e-45f; } [TestCompiler(1.0f)] public static float FSubByDenormBecomesFAddWithVec(float x) { var r = x - new float2(1.40129846432481707092e-45f, -1.40129846432481707092e-45f); return r.x * r.y; } private struct SomeStructWithCasts { public int I; public static implicit operator int(SomeStructWithCasts s) { return s.I; } public static implicit operator int4x4(SomeStructWithCasts s) { return s.I; } public static explicit operator double(SomeStructWithCasts s) { return s.I; } public static explicit operator double4x4(SomeStructWithCasts s) { return s.I; } } [TestCompiler(0)] public static int ImplicitCastsWork(int i) { var something = new SomeStructWithCasts { I = i }; if (i < 0) { return something; } else { int4x4 s = something; return s.c0.x; } } [TestCompiler(0)] public static double ExplicitCastsWork(int i) { var something = new SomeStructWithCasts { I = i }; if (i < 0) { return (double)something; } else { var s = (double4x4)something; return s.c0.x; } } } }