initial commit

This commit is contained in:
Jo 2025-01-07 02:06:59 +01:00
parent 6715289efe
commit 788c3389af
37645 changed files with 2526849 additions and 80 deletions

View file

@ -0,0 +1,223 @@
using System;
using System.Diagnostics;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
/// <summary>
/// Shared class used for Unit tests and <see cref="MyBurstBehavior"/>
/// </summary>
[BurstCompile] // attribute added just to check that static methods are getting compiled
public class BurstJobTester2 : IDisposable
{
private NativeArray<float> _array;
private NativeArray<float> _arrayAsyncJobDefault;
private NativeArray<float> _arrayAsyncJobFast;
public BurstJobTester2()
{
_array = new NativeArray<float>(10, Allocator.Persistent);
_arrayAsyncJobDefault = new NativeArray<float>(10, Allocator.Persistent);
_arrayAsyncJobFast = new NativeArray<float>(10, Allocator.Persistent);
}
public void Dispose()
{
_array.Dispose();
_arrayAsyncJobDefault.Dispose();
_arrayAsyncJobFast.Dispose();
}
public float Calculate()
{
// Schedule the job on each frame to make sure that it will be compiled async on the next frame
_array[0] = 0.0f;
// Launch synchronous job
var job = new MyJob { Result = _array };
job.Schedule().Complete();
var rotation = job.Result[0];
// Launch an async compilation
var asyncJobNoOptim = new MyJobWithDefaultOptimizations() {Result = _arrayAsyncJobDefault};
var asyncJobFastOptim = new MyJobWithFastOptimizations() {Result = _arrayAsyncJobFast};
var asyncJobNoOptimHandle = asyncJobNoOptim.Schedule();
var asyncJobFastOptimHandle = asyncJobFastOptim.Schedule();
// Wait for async completion
asyncJobNoOptimHandle.Complete();
asyncJobFastOptimHandle.Complete();
return rotation;
}
public float CheckFunctionPointer()
{
var functionPointer1 = BurstCompiler.CompileFunctionPointer<Add2NumbersDelegate>(Add2Numbers);
var result = functionPointer1.Invoke(1.0f, 2.0f);
var functionPointer2 = BurstCompiler.CompileFunctionPointer<Add2NumbersDelegate>(Add2NumbersThrows);
return functionPointer2.Invoke(1.0f, 2.0f);
}
[BurstCompile(CompileSynchronously = true)] // attribute used for a static method
public static float Add2Numbers(float a, float b)
{
DiscardFunction(ref a);
DiscardFunction(ref b);
return a + b;
}
[BurstCompile(CompileSynchronously = true)] // attribute used for a static method
public static float Add2NumbersThrows(float a, float b)
{
DiscardFunction(ref a);
DiscardFunction(ref b);
if (a > 0) ThrowNewArgumentException();
return a + b;
}
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
private static void ThrowNewArgumentException()
{
throw new ArgumentException("Invalid a must be < 0");
}
[BurstDiscard]
private static void DiscardFunction(ref float x)
{
x = 0;
}
public delegate float Add2NumbersDelegate(float a, float b);
[BurstCompile(CompileSynchronously = true)]
public struct MyJob : IJob
{
[WriteOnly]
public NativeArray<float> Result;
public void Execute()
{
Result[0] = ChangeValue();
EraseRotation();
}
// Use an indirection: Execute -> instance method -> static method
// (to check caching manually, change "1.0f" in ChangeValue() and 2.0f in ChangeValueStatic())
private float ChangeValue()
{
return 1.0f + ChangeValueStatic();
}
private static float ChangeValueStatic()
{
return 2.0f;
}
// Use BurstDiscard, if burst is not available, this method will get executed and it will make the cube static on the screen.
[BurstDiscard]
private void EraseRotation()
{
Result[0] = 0.0f;
}
// static method in a burst job, but we still want to compile separately
[BurstCompile(FloatMode = FloatMode.Deterministic, CompileSynchronously = true)]
public static float CheckFmaSlow(float a, float b, float c)
{
return a * b + c + math.sin(c);
}
// static method in a burst job, but we still want to compile separately
// Used only to check that compilation is working for different burst compile options
[BurstCompile(FloatPrecision.Low, FloatMode.Fast, CompileSynchronously = true)]
public static float CheckFmaFast(float a, float b, float c)
{
return a * b + c + math.sin(c);
}
}
[BurstCompile(CompileSynchronously = false)]
public struct MyJobAsync : IJob
{
[WriteOnly]
public NativeArray<float> Result;
public void Execute()
{
Result[0] = ChangeValue();
EraseRotation();
}
private float ChangeValue()
{
return 1.0f + ChangeValueStatic();
}
private static float ChangeValueStatic()
{
return 2.0f;
}
[BurstDiscard]
private void EraseRotation()
{
Result[0] = 0.0f;
}
}
[BurstCompile]
public struct MyJobWithDefaultOptimizations : IJob
{
public NativeArray<float> Result;
public void Execute()
{
Result[0] = math.cos(Result[0]);
}
}
/// <summary>
/// This Job is checking that we can allocate and dispose a NativeArray from a Burst Job
/// </summary>
[BurstCompile(CompileSynchronously = true)]
public struct MyJobCreatingAndDisposingNativeArray : IJob
{
public int Length;
public NativeArray<int> Result;
public void Execute()
{
var array = new NativeArray<float>(Length, Allocator.Temp);
for (int i = 0; i < array.Length; i++)
{
array[i] = i;
}
int result = array.Length;
array.Dispose();
DiscardFromManaged(ref result);
Result[0] = result;
}
[BurstDiscard]
public static void DiscardFromManaged(ref int result)
{
result = 0;
}
}
// Used only to check that compilation is working for different burst compile options
[BurstCompile(FloatPrecision.Low, FloatMode.Fast)]
public struct MyJobWithFastOptimizations : IJob
{
public NativeArray<float> Result;
public void Execute()
{
Result[0] = math.cos(Result[0]);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3decc8d6366d3d668648f9b79f2a980f
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,237 @@
using System;
using System.Runtime.InteropServices;
using AOT;
using NUnit.Framework;
using Unity.Burst;
using UnityEngine;
using UnityEngine.TestTools;
#if UNITY_2021_2_OR_NEWER
using System.Runtime.CompilerServices;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
#if UNITY_EDITOR
using OverloadedFunctionPointers;
#endif
#endif
[TestFixture, BurstCompile]
public class FunctionPointerTests
{
[BurstCompile(CompileSynchronously = true)]
private static T StaticFunctionNoArgsGenericReturnType<T>()
{
return default;
}
private delegate int DelegateNoArgsIntReturnType();
[Test]
public void TestCompileFunctionPointerNoArgsGenericReturnType()
{
Assert.Throws<InvalidOperationException>(
() => BurstCompiler.CompileFunctionPointer<DelegateNoArgsIntReturnType>(StaticFunctionNoArgsGenericReturnType<int>),
"The method `Int32 StaticFunctionNoArgsGenericReturnType[Int32]()` must be a non-generic method");
}
[BurstCompile(CompileSynchronously = true)]
private static int StaticFunctionConcreteReturnType()
{
return default;
}
private delegate T DelegateGenericReturnType<T>();
[Test]
public void TestCompileFunctionPointerDelegateNoArgsGenericReturnType()
{
Assert.Throws<InvalidOperationException>(
() => BurstCompiler.CompileFunctionPointer<DelegateGenericReturnType<int>>(StaticFunctionConcreteReturnType),
"The delegate type `FunctionPointerTests+DelegateGenericReturnType`1[System.Int32]` must be a non-generic type");
}
private static class GenericClass<T>
{
public delegate int DelegateNoArgsIntReturnType();
}
[Test]
public void TestCompileFunctionPointerDelegateNoArgsGenericDeclaringType()
{
Assert.Throws<InvalidOperationException>(
() => BurstCompiler.CompileFunctionPointer<GenericClass<int>.DelegateNoArgsIntReturnType>(StaticFunctionConcreteReturnType),
"The delegate type `FunctionPointerTests+GenericClass`1+DelegateNoArgsIntReturnType[System.Int32]` must be a non-generic type");
}
// Doesn't work with IL2CPP yet - waiting for Unity fix to land. Once it does, remove `&& UNITY_EDITOR`
#if UNITY_2021_2_OR_NEWER && UNITY_EDITOR
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
[BurstCompile]
private static int CSharpFunctionPointerCallback(int value) => value * 2;
[BurstCompile(CompileSynchronously = true)]
public unsafe struct StructWithCSharpFunctionPointer : IJob
{
[NativeDisableUnsafePtrRestriction]
[ReadOnly]
public IntPtr Callback;
[ReadOnly]
public NativeArray<int> Input;
[WriteOnly]
public NativeArray<int> Output;
public void Execute()
{
delegate* unmanaged[Cdecl]<int, int> callback = (delegate* unmanaged[Cdecl]<int, int>)Callback;
Output[0] = callback(Input[0]);
}
}
[Test]
public unsafe void CSharpFunctionPointerInsideJobStructTest()
{
using (var input = new NativeArray<int>(new int[1] { 40 }, Allocator.Persistent))
using (var output = new NativeArray<int>(new int[1], Allocator.Persistent))
{
delegate* unmanaged[Cdecl]<int, int> callback = &CSharpFunctionPointerCallback;
var job = new StructWithCSharpFunctionPointer
{
Callback = (IntPtr)callback,
Input = input,
Output = output
};
job.Run();
Assert.AreEqual(40 * 2, output[0]);
}
}
[Test]
public unsafe void CSharpFunctionPointerInStaticMethodSignature()
{
var fp = BurstCompiler.CompileFunctionPointer<DelegateWithCSharpFunctionPointerParameter>(EntryPointWithCSharpFunctionPointerParameter);
delegate* unmanaged[Cdecl]<int, int> callback = &CSharpFunctionPointerCallback;
var result = fp.Invoke((IntPtr)callback);
Assert.AreEqual(10, result);
}
[BurstCompile(CompileSynchronously = true)]
private static unsafe int EntryPointWithCSharpFunctionPointerParameter(IntPtr callback)
{
delegate* unmanaged[Cdecl]<int, int> typedCallback = (delegate* unmanaged[Cdecl]<int, int>)callback;
return typedCallback(5);
}
private unsafe delegate int DelegateWithCSharpFunctionPointerParameter(IntPtr callback);
[Test]
public unsafe void FunctionPointerReturnedFromBurstFunction()
{
var fp = BurstCompiler.CompileFunctionPointer<DelegateWithCSharpFunctionPointerReturn>(EntryPointWithCSharpFunctionPointerReturn);
var fpInner = fp.Invoke();
delegate* unmanaged[Cdecl]<float, float, float, float, float, float, float> callback = (delegate* unmanaged[Cdecl]<float, float, float, float, float, float, float>)fpInner;
var result = callback(1, 2, 4, 8, 16, 32);
Assert.AreEqual((float)(1 + 2 + 4 + 8 + 16 + 32), result);
}
[BurstCompile(CompileSynchronously = true)]
private static unsafe IntPtr EntryPointWithCSharpFunctionPointerReturn()
{
delegate* unmanaged[Cdecl]<float, float, float, float, float, float, float> fp = &EntryPointWithCSharpFunctionPointerReturnHelper;
return (IntPtr)fp;
}
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
[BurstCompile(CompileSynchronously = true)]
private static unsafe float EntryPointWithCSharpFunctionPointerReturnHelper(float p1, float p2, float p3, float p4, float p5, float p6)
{
return p1 + p2 + p3 + p4 + p5 + p6;
}
[BurstCompile]
[UnmanagedCallersOnly(CallConvs = new [] {typeof(CallConvCdecl)})]
static long UnmanagedFunction(long burstCount) => 1;
[BurstCompile]
static unsafe void GetUnmanagedCallableWithReturn(out Callable fn)
{
fn = Callable.Create<long, long>(&UnmanagedFunction);
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
public void CallOverloadedFunctionWithFpArg()
{
GetUnmanagedCallableWithReturn(out var a);
Assert.AreEqual(3, a.Value);
}
private delegate int Doer(int x);
static int DoCompileFunctionPointerNestedStaticMethod(int x)
{
[BurstCompile]
static int DoIt(int x) => x * 2 - 1;
return BurstCompiler.CompileFunctionPointer<Doer>(DoIt).Invoke(x);
}
[Test]
public void TestCompileFunctionPointerNestedStaticMethod()
{
Assert.AreEqual(3, DoCompileFunctionPointerNestedStaticMethod(2));
}
private unsafe delegate IntPtr DelegateWithCSharpFunctionPointerReturn();
// Note that there are 6 float parameters to try to catch any issues with calling conventions.
private unsafe delegate float DelegateWithCSharpFunctionPointerReturnHelper(float p1, float p2, float p3, float p4, float p5, float p6);
#endif
[Test]
public void TestDelegateWithCustomAttributeThatIsNotUnmanagedFunctionPointerAttribute()
{
var fp = BurstCompiler.CompileFunctionPointer<TestDelegateWithCustomAttributeThatIsNotUnmanagedFunctionPointerAttributeDelegate>(TestDelegateWithCustomAttributeThatIsNotUnmanagedFunctionPointerAttributeHelper);
var result = fp.Invoke(42);
Assert.AreEqual(43, result);
}
[BurstCompile(CompileSynchronously = true)]
private static int TestDelegateWithCustomAttributeThatIsNotUnmanagedFunctionPointerAttributeHelper(int x) => x + 1;
[MyCustomAttribute("Foo")]
private delegate int TestDelegateWithCustomAttributeThatIsNotUnmanagedFunctionPointerAttributeDelegate(int x);
private sealed class MyCustomAttributeAttribute : Attribute
{
public MyCustomAttributeAttribute(string param) { }
}
}
#if UNITY_2021_2_OR_NEWER
// UnmanagedCallersOnlyAttribute is new in .NET 5.0. This attribute is required
// when you declare an unmanaged function pointer with an explicit calling convention.
// Fortunately, Roslyn lets us declare the attribute class ourselves, and it will be used.
// Users will need this same declaration in their own projects, in order to use
// C# 9.0 function pointers.
namespace System.Runtime.InteropServices
{
[AttributeUsage(System.AttributeTargets.Method, Inherited = false)]
public sealed class UnmanagedCallersOnlyAttribute : Attribute
{
public Type[] CallConvs;
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c02f830887253c6eaf1f7780c59c5432
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,433 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using NUnit.Framework;
using System.Text.RegularExpressions;
using Unity.Burst;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using UnityEngine;
using UnityEngine.TestTools;
using System.Runtime.CompilerServices;
namespace ExceptionsFromBurstJobs
{
[BurstCompile]
class ManagedExceptionsBurstJobs
{
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
private static void ThrowNewArgumentException()
{
throw new ArgumentException("A");
}
[BurstCompile(CompileSynchronously = true)]
struct ThrowArgumentExceptionJob : IJob
{
public void Execute()
{
ThrowNewArgumentException();
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void ThrowArgumentException()
{
LogAssert.Expect(LogType.Exception, new Regex("ArgumentException: A"));
var jobData = new ThrowArgumentExceptionJob();
jobData.Run();
}
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
private static void ThrowNewArgumentNullException()
{
throw new ArgumentNullException("N");
}
[BurstCompile(CompileSynchronously = true)]
struct ThrowArgumentNullExceptionJob : IJob
{
public void Execute()
{
ThrowNewArgumentNullException();
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void ThrowArgumentNullException()
{
LogAssert.Expect(LogType.Exception, new Regex("System.ArgumentNullException: N"));
var jobData = new ThrowArgumentNullExceptionJob();
jobData.Run();
}
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
private static void ThrowNewNullReferenceException()
{
throw new NullReferenceException("N");
}
[BurstCompile(CompileSynchronously = true)]
struct ThrowNullReferenceExceptionJob : IJob
{
public void Execute()
{
ThrowNewNullReferenceException();
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void ThrowNullReferenceException()
{
LogAssert.Expect(LogType.Exception, new Regex("NullReferenceException: N"));
var jobData = new ThrowNullReferenceExceptionJob();
jobData.Run();
}
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
private static void ThrowNewInvalidOperationException()
{
throw new InvalidOperationException("IO");
}
[BurstCompile(CompileSynchronously = true)]
struct ThrowInvalidOperationExceptionJob : IJob
{
public void Execute()
{
ThrowNewInvalidOperationException();
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void ThrowInvalidOperationException()
{
LogAssert.Expect(LogType.Exception, new Regex("InvalidOperationException: IO"));
var jobData = new ThrowInvalidOperationExceptionJob();
jobData.Run();
}
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
private static void ThrowNewNotSupportedException()
{
throw new NotSupportedException("NS");
}
[BurstCompile(CompileSynchronously = true)]
struct ThrowNotSupportedExceptionJob : IJob
{
public void Execute()
{
ThrowNewNotSupportedException();
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void ThrowNotSupportedException()
{
LogAssert.Expect(LogType.Exception, new Regex("NotSupportedException: NS"));
var jobData = new ThrowNotSupportedExceptionJob();
jobData.Run();
}
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
private static void ThrowNewUnityException()
{
throw new UnityException("UE");
}
[BurstCompile(CompileSynchronously = true)]
struct ThrowUnityExceptionJob : IJob
{
public void Execute()
{
ThrowNewUnityException();
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void ThrowUnityException()
{
LogAssert.Expect(LogType.Exception, new Regex("UnityException: UE"));
var jobData = new ThrowUnityExceptionJob();
jobData.Run();
}
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
private static void ThrowNewIndexOutOfRangeException()
{
throw new IndexOutOfRangeException("IOOR");
}
[BurstCompile(CompileSynchronously = true)]
struct ThrowIndexOutOfRangeExceptionJob : IJob
{
public void Execute()
{
ThrowNewIndexOutOfRangeException();
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void ThrowIndexOutOfRange()
{
LogAssert.Expect(LogType.Exception, new Regex("IndexOutOfRangeException: IOOR"));
var jobData = new ThrowIndexOutOfRangeExceptionJob();
jobData.Run();
}
[BurstCompile(CompileSynchronously = true)]
private unsafe struct ThrowFromDereferenceNullJob : IJob
{
[NativeDisableUnsafePtrRestriction]
public int* Ptr;
public void Execute()
{
*Ptr = 42;
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void ThrowFromDereferenceNull()
{
LogAssert.Expect(LogType.Exception, new Regex("NullReferenceException: Object reference not set to an instance of an object"));
var jobData = new ThrowFromDereferenceNullJob() { Ptr = null };
jobData.Run();
}
[BurstCompile(CompileSynchronously = true)]
private unsafe struct ThrowFromDivideByZeroJob : IJob
{
public int Int;
public void Execute()
{
Int = 42 / Int;
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void ThrowFromDivideByZero()
{
if (RuntimeInformation.OSArchitecture == Architecture.Arm64)
{
// Arm64 does not throw a divide-by-zero exception, instead it flushes the result to zero.
return;
}
LogAssert.Expect(LogType.Exception, new Regex("DivideByZeroException: Attempted to divide by zero"));
var jobData = new ThrowFromDivideByZeroJob() { Int = 0 };
jobData.Run();
}
private unsafe delegate void ExceptionDelegate(int* a);
[BurstCompile(CompileSynchronously = true)]
private static unsafe void DereferenceNull(int* a)
{
*a = 42;
}
[BurstCompile(CompileSynchronously = true)]
unsafe struct ThrowFromFunctionPointerJob : IJob
{
#pragma warning disable 649
[NativeDisableUnsafePtrRestriction] public IntPtr FuncPtr;
[NativeDisableUnsafePtrRestriction] public int* Ptr;
#pragma warning restore 649
public void Execute()
{
new FunctionPointer<ExceptionDelegate>(FuncPtr).Invoke(Ptr);
// Set Ptr to non null which should never be hit because the above will throw.
Ptr = (int*)0x42;
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public unsafe void ThrowFromFunctionPointer()
{
var funcPtr = BurstCompiler.CompileFunctionPointer<ExceptionDelegate>(DereferenceNull);
LogAssert.Expect(LogType.Exception, new Regex("NullReferenceException: Object reference not set to an instance of an object"));
var job = new ThrowFromFunctionPointerJob { FuncPtr = funcPtr.Value, Ptr = null };
job.Run();
Assert.AreEqual((IntPtr)job.Ptr, (IntPtr)0);
}
[BurstCompile(CompileSynchronously = true)]
private unsafe struct ThrowFromDereferenceNullParallelJob : IJobParallelFor
{
[NativeDisableUnsafePtrRestriction]
public int* Ptr;
public void Execute(int index)
{
*Ptr = index;
}
}
[Test]
// No RuntimePlatform.OSXEditor in this list because of a subtle Mojave only bug.
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void ThrowFromDereferenceNullParallel()
{
var messageCount = 0;
void OnMessage(string message, string stackTrace, LogType type)
{
Assert.AreEqual(LogType.Exception, type);
StringAssert.Contains("NullReferenceException: Object reference not set to an instance of an object", message);
messageCount++;
}
LogAssert.ignoreFailingMessages = true;
Application.logMessageReceivedThreaded += OnMessage;
try
{
var jobData = new ThrowFromDereferenceNullParallelJob() { Ptr = null };
jobData.Schedule(128, 1).Complete();
Assert.GreaterOrEqual(messageCount, 1);
}
finally
{
Application.logMessageReceivedThreaded -= OnMessage;
LogAssert.ignoreFailingMessages = false;
}
}
private unsafe struct ThrowFromDereferenceNullManagedJob : IJob
{
[NativeDisableUnsafePtrRestriction]
public int* Ptr;
public void Execute()
{
*Ptr = 42;
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void ThrowFromDereferenceNullManaged()
{
LogAssert.Expect(LogType.Exception, new Regex("NullReferenceException: Object reference not set to an instance of an object"));
var jobData = new ThrowFromDereferenceNullManagedJob() { Ptr = null };
jobData.Run();
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void ThrowFromDereferenceNullBurstDisabled()
{
var previous = BurstCompiler.Options.EnableBurstCompilation;
BurstCompiler.Options.EnableBurstCompilation = false;
LogAssert.Expect(LogType.Exception, new Regex("NullReferenceException: Object reference not set to an instance of an object"));
var jobData = new ThrowFromDereferenceNullJob() { Ptr = null };
jobData.Run();
BurstCompiler.Options.EnableBurstCompilation = previous;
}
[BurstCompile]
struct Thrower : IJob
{
public int X;
[BurstCompile(CompileSynchronously = true)]
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ConditionalThrowWithSideEffect(int x)
{
if (x == -1)
throw new InvalidOperationException();
UnityEngine.Debug.Log("wow");
throw new InvalidOperationException();
}
public void Execute()
{
ConditionalThrowWithSideEffect(X);
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void TestConditionalThrowWithSideEffect()
{
LogAssert.Expect(LogType.Log, "wow");
LogAssert.Expect(LogType.Exception, new Regex(".+InvalidOperation.+"));
new Thrower() { X = 0 }.Run();
}
private unsafe struct ThrowFromManagedStackOverflowJob : IJob
{
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
private static int DoStackOverflow(ref int x)
{
// Copy just to make the stack grow.
var copy = x;
return copy + DoStackOverflow(ref x);
}
public int Int;
public void Execute()
{
Int = DoStackOverflow(ref Int);
}
}
//[Test]
//[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
public void ThrowFromManagedStackOverflow()
{
LogAssert.Expect(LogType.Exception, new Regex("StackOverflowException: The requested operation caused a stack overflow"));
var jobData = new ThrowFromManagedStackOverflowJob() { Int = 1 };
jobData.Run();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d54dbb53d4313cc8b7d8289a75202585
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,94 @@
using NUnit.Framework;
using System.Text.RegularExpressions;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using UnityEngine;
using UnityEngine.TestTools;
namespace ExceptionsFromBurstJobs
{
class NativeTriggeredManagedExceptionsBurstJobs
{
[BurstCompile(CompileSynchronously = true)]
struct RaiseMonoExceptionJob : IJob
{
public float output;
public void Execute()
{
output = Time.deltaTime;
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void RaiseMonoException()
{
var job = new RaiseMonoExceptionJob();
LogAssert.Expect(LogType.Exception, new Regex(
"UnityEngine::UnityException: get_deltaTime can only be called from the main thread." + "[\\s]*" +
"Constructors and field initializers will be executed from the loading thread when loading a scene." + "[\\s]*" +
"Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function." + "[\\s]*" +
"This Exception was thrown from a job compiled with Burst, which has limited exception support."
));
job.Run();
}
[BurstCompile(CompileSynchronously = true)]
struct RaiseInvalidOperationExceptionJob : IJob
{
[ReadOnly]
public NativeArray<int> test;
public void Execute()
{
test[0] = 5;
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
public void RaiseInvalidOperationException()
{
var jobData = new RaiseInvalidOperationExceptionJob();
var testArray = new NativeArray<int>(1, Allocator.Persistent);
jobData.test = testArray;
LogAssert.Expect(LogType.Exception, new Regex(
"System::InvalidOperationException: The .+ has been declared as \\[ReadOnly\\] in the job( .+)?, but you are writing to it\\." + "[\\s]*" +
"This Exception was thrown from a job compiled with Burst, which has limited exception support."
));
jobData.Run();
testArray.Dispose();
}
[BurstCompile(CompileSynchronously = true)]
unsafe struct RaiseArgumentNullExceptionJob : IJob
{
#pragma warning disable 649
[NativeDisableUnsafePtrRestriction] public void* dst;
#pragma warning restore 649
public void Execute()
{
UnsafeUtility.MemCpy(dst, null, 10);
}
}
[Test]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
[Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
unsafe public void RaiseArgumentNullException()
{
var jobData = new RaiseArgumentNullExceptionJob();
jobData.dst = UnsafeUtility.Malloc(10, 4, Allocator.Temp);
LogAssert.Expect(LogType.Exception, new Regex(
"System.ArgumentNullException: source" + "[\\s]*" +
"This Exception was thrown from a job compiled with Burst, which has limited exception support."
));
jobData.Run();
UnsafeUtility.Free(jobData.dst, Allocator.Temp);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac74b11ef46b35938b5d3ca8a4109efa
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,289 @@
using System.Collections;
using NUnit.Framework;
using Unity.Burst;
using UnityEngine;
using Unity.Jobs.LowLevel.Unsafe;
using UnityEngine.TestTools;
using System;
using Unity.Jobs;
[TestFixture]
public class PlaymodeTest
{
// [UnityTest]
public IEnumerator CheckBurstJobEnabledDisabled()
{
BurstCompiler.Options.EnableBurstCompileSynchronously = true;
foreach(var item in CheckBurstJobDisabled()) yield return item;
foreach(var item in CheckBurstJobEnabled()) yield return item;
}
private IEnumerable CheckBurstJobEnabled()
{
BurstCompiler.Options.EnableBurstCompilation = true;
yield return null;
using (var jobTester = new BurstJobTester2())
{
var result = jobTester.Calculate();
Assert.AreNotEqual(0.0f, result);
}
}
private IEnumerable CheckBurstJobDisabled()
{
BurstCompiler.Options.EnableBurstCompilation = false;
yield return null;
using (var jobTester = new BurstJobTester2())
{
var result = jobTester.Calculate();
Assert.AreEqual(0.0f, result);
}
}
[BurstCompile(CompileSynchronously = true)]
private struct ThrowingJob : IJob
{
public int I;
public void Execute()
{
if (I < 0)
{
throw new System.Exception("Some Exception!");
}
}
}
[Test]
public void NoSafetyCheckExceptionWarningInEditor()
{
var job = new ThrowingJob { I = 42 };
job.Schedule().Complete();
// UNITY_BURST_DEBUG enables additional logging which messes with our check.
if (null == System.Environment.GetEnvironmentVariable("UNITY_BURST_DEBUG"))
{
LogAssert.NoUnexpectedReceived();
}
}
private struct MyKey { public struct MySubKey0 { } public struct MySubKey1 { } }
private struct SomeGenericStruct<T> {}
private static readonly SharedStatic<int> SharedStaticOneType = SharedStatic<int>.GetOrCreate<MyKey>();
private static readonly SharedStatic<double> SharedStaticTwoTypes0 = SharedStatic<double>.GetOrCreate<MyKey, MyKey.MySubKey0>();
private static readonly SharedStatic<double> SharedStaticTwoTypes1 = SharedStatic<double>.GetOrCreate<MyKey, MyKey.MySubKey1>();
private struct MyGenericContainingStruct<T>
{
public static readonly SharedStatic<int> Data0 = SharedStatic<int>.GetOrCreate<T>();
public static readonly SharedStatic<int> Data1 = SharedStatic<int>.GetOrCreate<SomeGenericStruct<MyKey>, T>();
public static readonly SharedStatic<int> Data2 = SharedStatic<int>.GetOrCreate<SomeGenericStruct<T>, MyKey>();
}
private static readonly SharedStatic<int> SharedStaticWithSystemTypes0 = SharedStatic<int>.GetOrCreate<IntPtr>();
private static readonly SharedStatic<int> SharedStaticWithSystemTypes1 = SharedStatic<int>.GetOrCreate<IntPtr, MyKey>();
private static readonly SharedStatic<int> SharedStaticWithSystemTypes2 = SharedStatic<int>.GetOrCreate<MyKey, IntPtr>();
private static readonly SharedStatic<int> SharedStaticWithSystemTypes3 = SharedStatic<int>.GetOrCreate<IntPtr, IntPtr>();
[Test]
public unsafe void SharedStaticPostProcessedTests()
{
var oneType = SharedStatic<int>.GetOrCreate(typeof(MyKey));
Assert.AreEqual((IntPtr)oneType.UnsafeDataPointer, (IntPtr)SharedStaticOneType.UnsafeDataPointer);
Assert.AreNotEqual((IntPtr)oneType.UnsafeDataPointer, (IntPtr)SharedStaticTwoTypes0.UnsafeDataPointer);
Assert.AreNotEqual((IntPtr)oneType.UnsafeDataPointer, (IntPtr)SharedStaticTwoTypes1.UnsafeDataPointer);
var twoTypes0 = SharedStatic<double>.GetOrCreate(typeof(MyKey), typeof(MyKey.MySubKey0));
Assert.AreEqual((IntPtr)twoTypes0.UnsafeDataPointer, (IntPtr)SharedStaticTwoTypes0.UnsafeDataPointer);
Assert.AreNotEqual((IntPtr)twoTypes0.UnsafeDataPointer, (IntPtr)SharedStaticOneType.UnsafeDataPointer);
Assert.AreNotEqual((IntPtr)twoTypes0.UnsafeDataPointer, (IntPtr)SharedStaticTwoTypes1.UnsafeDataPointer);
var twoTypes1 = SharedStatic<double>.GetOrCreate(typeof(MyKey), typeof(MyKey.MySubKey1));
Assert.AreEqual((IntPtr)twoTypes1.UnsafeDataPointer, (IntPtr)SharedStaticTwoTypes1.UnsafeDataPointer);
Assert.AreNotEqual((IntPtr)twoTypes1.UnsafeDataPointer, (IntPtr)SharedStaticOneType.UnsafeDataPointer);
Assert.AreNotEqual((IntPtr)twoTypes1.UnsafeDataPointer, (IntPtr)SharedStaticTwoTypes0.UnsafeDataPointer);
// A shared static in a generic struct, that uses the same type for `GetOrCreate`, will resolve to the same shared static.
Assert.AreEqual((IntPtr)oneType.UnsafeDataPointer, (IntPtr)MyGenericContainingStruct<MyKey>.Data0.UnsafeDataPointer);
// These two test partial evaluations of shared statics (where we can evaluate one of the template arguments at ILPP time
// but not both).
Assert.AreEqual(
(IntPtr)MyGenericContainingStruct<MyKey>.Data1.UnsafeDataPointer,
(IntPtr)MyGenericContainingStruct<MyKey>.Data2.UnsafeDataPointer);
// Check that system type evaluations all match up.
Assert.AreEqual(
(IntPtr)SharedStatic<int>.GetOrCreate(typeof(IntPtr)).UnsafeDataPointer,
(IntPtr)SharedStaticWithSystemTypes0.UnsafeDataPointer);
Assert.AreEqual(
(IntPtr)SharedStatic<int>.GetOrCreate(typeof(IntPtr), typeof(MyKey)).UnsafeDataPointer,
(IntPtr)SharedStaticWithSystemTypes1.UnsafeDataPointer);
Assert.AreEqual(
(IntPtr)SharedStatic<int>.GetOrCreate(typeof(MyKey), typeof(IntPtr)).UnsafeDataPointer,
(IntPtr)SharedStaticWithSystemTypes2.UnsafeDataPointer);
Assert.AreEqual(
(IntPtr)SharedStatic<int>.GetOrCreate(typeof(IntPtr), typeof(IntPtr)).UnsafeDataPointer,
(IntPtr)SharedStaticWithSystemTypes3.UnsafeDataPointer);
}
[BurstCompile]
public struct SomeFunctionPointers
{
[BurstDiscard]
private static void MessWith(ref int a) => a += 13;
[BurstCompile]
public static int A(int a, int b)
{
MessWith(ref a);
return a + b;
}
[BurstCompile(DisableDirectCall = true)]
public static int B(int a, int b)
{
MessWith(ref a);
return a - b;
}
[BurstCompile(CompileSynchronously = true)]
public static int C(int a, int b)
{
MessWith(ref a);
return a * b;
}
[BurstCompile(CompileSynchronously = true, DisableDirectCall = true)]
public static int D(int a, int b)
{
MessWith(ref a);
return a / b;
}
public delegate int Delegate(int a, int b);
}
[Test]
public void TestDirectCalls()
{
Assert.IsTrue(BurstCompiler.IsEnabled);
// a can either be (42 + 13) + 53 or 42 + 53 (depending on whether it was burst compiled).
var a = SomeFunctionPointers.A(42, 53);
Assert.IsTrue((a == ((42 + 13) + 53)) || (a == (42 + 53)));
// b can only be (42 + 13) - 53, because direct call is disabled and so we always call the managed method.
var b = SomeFunctionPointers.B(42, 53);
Assert.AreEqual((42 + 13) - 53, b);
// c can only be 42 * 53, because synchronous compilation is enabled.
var c = SomeFunctionPointers.C(42, 53);
Assert.AreEqual(42 * 53, c);
// d can only be (42 + 13) / 53, because even though synchronous compilation is enabled, direct call is disabled.
var d = SomeFunctionPointers.D(42, 53);
Assert.AreEqual((42 + 13) / 53, d);
}
[Test]
public void TestDirectCallInNamespacedClass()
{
void onCompileILPPMethod2()
{
Assert.Fail("BurstCompiler.CompileILPPMethod2 should not have been called at this time");
}
// We expect BurstCompiler.CompileILPPMethod2 to have been called at startup, via
// [InitializeOnLoad] or [RuntimeInitializeOnLoadMethod]. If it's called when we invoke
// N.C.A(), then something has gone wrong.
try
{
BurstCompiler.OnCompileILPPMethod2 += onCompileILPPMethod2;
var result = N.C.A();
Assert.AreEqual(42, result);
}
finally
{
BurstCompiler.OnCompileILPPMethod2 -= onCompileILPPMethod2;
}
}
[Test]
public void TestFunctionPointers()
{
Assert.IsTrue(BurstCompiler.IsEnabled);
var A = BurstCompiler.CompileFunctionPointer<SomeFunctionPointers.Delegate>(SomeFunctionPointers.A);
var B = BurstCompiler.CompileFunctionPointer<SomeFunctionPointers.Delegate>(SomeFunctionPointers.B);
var C = BurstCompiler.CompileFunctionPointer<SomeFunctionPointers.Delegate>(SomeFunctionPointers.C);
var D = BurstCompiler.CompileFunctionPointer<SomeFunctionPointers.Delegate>(SomeFunctionPointers.D);
// a can either be (42 + 13) + 53 or 42 + 53 (depending on whether it was burst compiled).
var a = A.Invoke(42, 53);
Assert.IsTrue((a == ((42 + 13) + 53)) || (a == (42 + 53)));
// b can either be (42 + 13) - 53 or 42 - 53 (depending on whether it was burst compiled).
var b = B.Invoke(42, 53);
Assert.IsTrue((b == ((42 + 13) - 53)) || (b == (42 - 53)));
// c can only be 42 * 53, because synchronous compilation is enabled.
var c = C.Invoke(42, 53);
Assert.AreEqual(42 * 53, c);
// d can only be 42 / 53, because synchronous compilation is enabled.
var d = D.Invoke(42, 53);
Assert.AreEqual(42 / 53, d);
}
[BurstCompile]
public static class GenericClass<T>
{
[BurstCompile]
public static int ConcreteMethod() => 3;
}
public delegate int NoArgsIntReturnDelegate();
[Test]
public void TestGenericClassConcreteMethodFunctionPointer()
{
Assert.IsTrue(BurstCompiler.IsEnabled);
var F = BurstCompiler.CompileFunctionPointer<NoArgsIntReturnDelegate>(GenericClass<int>.ConcreteMethod);
Assert.AreEqual(3, F.Invoke());
}
}
// This test class is intentionally in a namespace to ensure that our
// direct-call [RuntimeInitializeOnLoadMethod] works correctly in that
// scenario.
namespace N
{
[BurstCompile]
internal static class C
{
public static int A() => B();
[BurstCompile(CompileSynchronously = true)]
private static int B()
{
var x = 42;
DiscardedMethod(ref x);
return x;
}
[BurstDiscard]
private static void DiscardedMethod(ref int x)
{
x += 1;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb7078968c7e3322a80bb099e19fb2e8
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 30b8c33e57eb30adbfd9b640a4edaef8
folderAsset: yes

View file

@ -0,0 +1,246 @@
using NUnit.Framework;
using System;
using System.Runtime.InteropServices;
using Unity.Burst;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
/// <summary>
/// Tests types
/// </summary>
[BurstCompile]
internal class NotSupported
{
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_OnlyStaticMethodsAllowed)]
public int InstanceMethod()
{
return 1;
}
[TestCompiler(1, ExpectCompilerException = true, ExpectedDiagnosticIds = new[] { DiagnosticId.ERR_CallingManagedMethodNotSupported })]
public static int TestDelegate(int data)
{
return ProcessData(i => i + 1, data);
}
private static int ProcessData(Func<int, int> yo, int value)
{
return yo(value);
}
public struct HasMarshalAttribute
{
[MarshalAs(UnmanagedType.U1)] public bool A;
}
//[TestCompiler(ExpectCompilerException = true)]
[TestCompiler] // Because MarshalAs is used in mathematics we cannot disable it for now
public static void TestStructWithMarshalAs()
{
#pragma warning disable 0219
var x = new HasMarshalAttribute();
#pragma warning restore 0219
}
public struct HasMarshalAsSysIntAttribute
{
[MarshalAs(UnmanagedType.SysInt)] public bool A;
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_MarshalAsOnFieldNotSupported)]
public static void TestStructWithMarshalAsSysInt()
{
#pragma warning disable 0219
var x = new HasMarshalAsSysIntAttribute();
#pragma warning restore 0219
}
[TestCompiler(42, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_MarshalAsOnParameterNotSupported)]
public static void TestMethodWithMarshalAsParameter([MarshalAs(UnmanagedType.I8)] int x)
{
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_MarshalAsOnReturnTypeNotSupported)]
[return: MarshalAs(UnmanagedType.I8)]
public static int TestMethodWithMarshalAsReturnType()
{
return 42;
}
private static float3 a = new float3(1, 2, 3);
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_LoadingFromNonReadonlyStaticFieldNotSupported)]
public static bool TestStaticLoad()
{
var cmp = a == new float3(1, 2, 3);
return cmp.x && cmp.y && cmp.z;
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_LoadingFromManagedNonReadonlyStaticFieldNotSupported)]
public static void TestStaticStore()
{
a.x = 42;
}
private interface ISomething
{
void DoSomething();
}
private struct Something : ISomething
{
public byte A;
public void DoSomething()
{
A = 42;
}
}
private static ISomething something = new Something { A = 13 };
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_LoadingFromManagedNonReadonlyStaticFieldNotSupported)]
public static void TestStaticInterfaceStore()
{
something.DoSomething();
}
private static int i = 42;
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_LoadingFromNonReadonlyStaticFieldNotSupported)]
public static int TestStaticIntLoad()
{
return i;
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_InstructionStsfldNotSupported)]
public static void TestStaticIntStore()
{
i = 13;
}
public delegate char CharbyValueDelegate(char c);
#if BURST_TESTS_ONLY
[BurstCompile]
#endif
public static char CharbyValue(char c)
{
return c;
}
public struct CharbyValueFunc : IFunctionPointerProvider
{
public FunctionPointer<CharbyValueDelegate> FunctionPointer;
public object FromIntPtr(IntPtr ptr)
{
return new CharbyValueFunc() { FunctionPointer = new FunctionPointer<CharbyValueDelegate>(ptr) };
}
}
[TestCompiler(nameof(CharbyValue), 0x1234, ExpectCompilerException = true, ExpectedDiagnosticIds = new[] { DiagnosticId.ERR_TypeNotBlittableForFunctionPointer, DiagnosticId.ERR_StructsWithNonUnicodeCharsNotSupported })]
public static int TestCharbyValue(ref CharbyValueFunc fp, int i)
{
var c = (char)i;
return fp.FunctionPointer.Invoke(c);
}
struct Halfs
{
public static readonly half3 h3_h = new half3(new half(42.0f));
public static readonly half3 h3_d = new half3(0.5);
public static readonly half3 h3_v2s = new half3(new half2(new half(1.0f), new half(2.0f)), new half(0.5f));
public static readonly half3 h3_sv2 = new half3(new half(0.5f), new half2(new half(1.0f), new half(2.0f)));
public static readonly half3 h3_v3 = new half3(new half(0.5f), new half(42.0f), new half(13.0f));
}
[TestCompiler]
public static float TestStaticHalf3()
{
var result = (float3)Halfs.h3_h + Halfs.h3_d + Halfs.h3_v2s + Halfs.h3_sv2 + Halfs.h3_v3;
return result.x + result.y + result.z;
}
[TestCompiler(42, 13, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_AssertTypeNotSupported)]
public static void TestAreEqual(int a, int b)
{
Assert.AreEqual(a, b, "unsupported", new object[0]);
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_InstructionLdtokenTypeNotSupported)]
public static bool TestTypeof()
{
return typeof(int).IsPrimitive;
}
public class AwfulClass
{
public int Foo;
}
public struct BetterStruct
{
public int Foo;
}
public struct MixedStaticInits
{
public static readonly AwfulClass AC = new AwfulClass { Foo = 42 };
public static readonly BetterStruct BS = new BetterStruct { Foo = 42 };
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticIds = new[] { DiagnosticId.ERR_InstructionNewobjWithManagedTypeNotSupported, DiagnosticId.ERR_ManagedStaticConstructor })]
public static int TestMixedStaticInits()
{
return MixedStaticInits.BS.Foo;
}
public struct StaticArrayWrapper
{
private const int ArrayLength = 4;
public static readonly int[] StaticArray = new int[4];
static StaticArrayWrapper()
{
for (int i = 0; i < ArrayLength; ++i)
{
StaticArray[i] = i;
}
}
}
[TestCompiler]
public unsafe static int TestStaticArrayWrapper()
{
return StaticArrayWrapper.StaticArray[0];
}
class NestedArrayHolder
{
public static readonly int4[][] SomeOffsetThing =
{
new[] {new int4(0), new int4(0, 0, 1, 0), new int4(0, 1, 0, 0), new int4(0, 1, 1, 0)},
new[] {new int4(0), new int4(1, 0, 0, 0), new int4(0, 0, 1, 0), new int4(1, 0, 1, 0)},
new[] {new int4(0), new int4(0, 1, 0, 0), new int4(1, 0, 0, 0), new int4(1, 1, 0, 0)},
};
}
[TestCompiler]
public unsafe static int TestNestedManagedArrays()
{
return NestedArrayHolder.SomeOffsetThing[0][0].x;
}
public static readonly int[,] SomeMultiDimensionalThing = new int[2, 4]
{
{ 1, 2, 3, 4 },
{ -1, -2, -3, -4 },
};
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticIds = new[] { DiagnosticId.ERR_ConstructorNotSupported, DiagnosticId.ERR_MultiDimensionalArrayUnsupported })]
public static int TestMultiDimensionalArray() => SomeMultiDimensionalThing[1, 1];
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5eb12402c8b53dbaa40d67a6ccd1b4f6
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,158 @@
using System;
using Unity.Collections.LowLevel.Unsafe;
namespace Burst.Compiler.IL.Tests
{
#if UNITY_2021_2_OR_NEWER || BURST_INTERNAL
/// <summary>
/// Test <see cref="System.ReadOnlySpan{T}"/>.
/// </summary>
internal partial class ReadOnlySpan
{
[TestCompiler]
public static int CreateDefault()
{
var span = new ReadOnlySpan<int>();
return span.Length;
}
[TestCompiler]
public static int CreateStackalloc()
{
ReadOnlySpan<int> span = stackalloc int[42];
return span.Length;
}
[TestCompiler(42)]
public static int CreateFromNullPointer(int size)
{
ReadOnlySpan<double> span;
unsafe
{
span = new ReadOnlySpan<double>(null, size);
}
return span.Length;
}
[TestCompiler]
public static unsafe double CreateFromMalloc()
{
double* malloc = (double*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf<double>(), UnsafeUtility.AlignOf<double>(), Unity.Collections.Allocator.Persistent);
*malloc = 42.0f;
var span = new ReadOnlySpan<double>(malloc, 1);
double result = span[0];
UnsafeUtility.Free(malloc, Unity.Collections.Allocator.Persistent);
return result;
}
[TestCompiler]
public static int GetItem()
{
ReadOnlySpan<int> span = stackalloc int[42];
return span[41];
}
[TestCompiler]
public static int SliceFromStart()
{
ReadOnlySpan<int> span = stackalloc int[42];
var newSpan = span.Slice(10);
return newSpan[0] + newSpan.Length;
}
[TestCompiler]
public static int SliceFromStartWithLength()
{
ReadOnlySpan<int> span = stackalloc int[42];
var newSpan = span.Slice(10, 4);
return newSpan[3] + newSpan.Length;
}
[TestCompiler]
public static int CopyTo()
{
Span<int> span = stackalloc int[42];
for (int i = 0; i < span.Length; i++)
{
span[i] = i;
}
ReadOnlySpan<int> other = stackalloc int[4];
other.CopyTo(span);
int result = 0;
for (int i = 0; i < span.Length; i++)
{
result += span[i];
}
return result;
}
[TestCompiler]
public static int IsEmpty() => new ReadOnlySpan<int>().IsEmpty ? 1 : 0;
[TestCompiler]
public static int Empty() => ReadOnlySpan<double>.Empty.Length;
[TestCompiler]
public static int GetEnumerator()
{
ReadOnlySpan<int> span = stackalloc int[42];
int result = 0;
var enumerator = span.GetEnumerator();
while (enumerator.MoveNext())
{
result += enumerator.Current;
}
return result;
}
[TestCompiler]
public static int OperatorEquality() => new ReadOnlySpan<double>() == ReadOnlySpan<double>.Empty ? 1 : 0;
[TestCompiler]
public static int OperatorInEquality() => new ReadOnlySpan<double>() != ReadOnlySpan<double>.Empty ? 1 : 0;
[TestCompiler]
public static int Fixed()
{
Span<int> span = stackalloc int[42];
for (int i = 0; i < span.Length; i++)
{
span[i] = i;
}
ReadOnlySpan<int> readOnlySpan = span;
unsafe
{
fixed (int* ptr = readOnlySpan)
{
return ptr[41];
}
}
}
}
#endif
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0bed5c1e3949386481f894d4b987c939
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,227 @@
using System;
using Unity.Collections.LowLevel.Unsafe;
namespace Burst.Compiler.IL.Tests
{
#if UNITY_2021_2_OR_NEWER || BURST_INTERNAL
/// <summary>
/// Test <see cref="System.Span{T}"/>.
/// </summary>
internal partial class Span
{
[TestCompiler]
public static int CreateDefault()
{
var span = new Span<int>();
return span.Length;
}
[TestCompiler]
public static int CreateStackalloc()
{
Span<int> span = stackalloc int[42];
return span.Length;
}
[TestCompiler(42)]
public static int CreateFromNullPointer(int size)
{
Span<double> span;
unsafe
{
span = new Span<double>(null, size);
}
return span.Length;
}
[TestCompiler]
public static unsafe double CreateFromMalloc()
{
double* malloc = (double*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf<double>(), UnsafeUtility.AlignOf<double>(), Unity.Collections.Allocator.Persistent);
*malloc = 42.0f;
Span<double> span = new Span<double>(malloc, 1);
double result = span[0];
UnsafeUtility.Free(malloc, Unity.Collections.Allocator.Persistent);
return result;
}
[TestCompiler]
public static int GetItem()
{
Span<int> span = stackalloc int[42];
return span[41];
}
[TestCompiler]
public static int SetItem()
{
Span<int> span = stackalloc int[42];
span[41] = 13;
return span[41];
}
[TestCompiler]
public static int Clear()
{
Span<int> span = stackalloc int[42];
for (int i = 0; i < span.Length; i++)
{
span[i] = i;
}
span.Clear();
int result = 0;
for (int i = 0; i < span.Length; i++)
{
result += span[i];
}
return result;
}
[TestCompiler]
public static int SliceFromStart()
{
Span<int> span = stackalloc int[42];
for (int i = 0; i < span.Length; i++)
{
span[i] = i;
}
var newSpan = span.Slice(10);
return newSpan[0] + newSpan.Length;
}
[TestCompiler]
public static int SliceFromStartWithLength()
{
Span<int> span = stackalloc int[42];
for (int i = 0; i < span.Length; i++)
{
span[i] = i;
}
var newSpan = span.Slice(10, 4);
return newSpan[3] + newSpan.Length;
}
[TestCompiler]
public static int CopyTo()
{
Span<int> span = stackalloc int[42];
for (int i = 0; i < span.Length; i++)
{
span[i] = i;
}
Span<int> other = stackalloc int[4];
for (int i = 0; i < other.Length; i++)
{
other[i] = -i - 1;
}
other.CopyTo(span);
int result = 0;
for (int i = 0; i < span.Length; i++)
{
result += span[i];
}
return result;
}
[TestCompiler]
public static int Fill()
{
Span<int> span = stackalloc int[42];
span.Fill(123);
int result = 0;
for (int i = 0; i < span.Length; i++)
{
result += span[i];
}
return result;
}
[TestCompiler]
public static int IsEmpty() => new Span<int>().IsEmpty ? 1 : 0;
[TestCompiler]
public static int Empty() => Span<double>.Empty.Length;
[TestCompiler]
public static int GetEnumerator()
{
Span<int> span = stackalloc int[42];
int result = 0;
var enumerator = span.GetEnumerator();
while (enumerator.MoveNext())
{
result += enumerator.Current;
}
return result;
}
[TestCompiler]
public static int OperatorEquality() => new Span<double>() == Span<double>.Empty ? 1 : 0;
[TestCompiler]
public static int OperatorInEquality() => new Span<double>() != Span<double>.Empty ? 1 : 0;
[TestCompiler]
public static int OperatorImplicit()
{
ReadOnlySpan<double> span = new Span<double>();
return span.Length;
}
[TestCompiler]
public static int Fixed()
{
Span<int> span = stackalloc int[42];
for (int i = 0; i < span.Length; i++)
{
span[i] = i;
}
unsafe
{
fixed (int* ptr = span)
{
*ptr = 42;
return ptr[41];
}
}
}
}
#endif
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fec1bb67579b3feda3e2fddd7ecbc304
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,542 @@
using System;
using System.Runtime.InteropServices;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Burst;
using UnityBenchShared;
using System.Runtime.CompilerServices;
#if UNITY_2022_1_OR_NEWER
// Enables support for { init; } keyword globally: https://docs.unity3d.com/2022.1/Documentation/Manual/CSharpCompiler.html
namespace System.Runtime.CompilerServices
{
[ComponentModel.EditorBrowsable(ComponentModel.EditorBrowsableState.Never)]
public static class IsExternalInit { }
}
#endif
namespace Burst.Compiler.IL.Tests
{
/// <summary>
/// Tests types
/// </summary>
internal partial class Types
{
[TestCompiler]
public static int Bool()
{
return sizeof(bool);
}
[TestCompiler(true)]
[TestCompiler(false)]
public static bool BoolArgAndReturn(bool value)
{
return !value;
}
private static bool BoolArgAndReturnSubFunction(bool value)
{
return !value;
}
[TestCompiler(true)]
[TestCompiler(false)]
public static bool BoolArgAndReturnCall(bool value)
{
return BoolArgAndReturnSubFunction(value);
}
[MethodImpl(MethodImplOptions.NoInlining)]
[return: MarshalAs(UnmanagedType.U1)]
private static bool BoolMarshalAsU1(bool b) => b;
[TestCompiler(true)]
[TestCompiler(false)]
public static bool BoolMarshalAsU1Call(bool value)
{
return BoolMarshalAsU1(value);
}
[MethodImpl(MethodImplOptions.NoInlining)]
[return: MarshalAs(UnmanagedType.I1)]
private static bool BoolMarshalAsI1(bool b) => b;
[TestCompiler(true)]
[TestCompiler(false)]
public static bool BoolMarshalAsI1Call(bool value)
{
return BoolMarshalAsI1(value);
}
[MethodImpl(MethodImplOptions.NoInlining)]
[return: MarshalAs(UnmanagedType.R4)]
private static bool BoolMarshalAsR4(bool b) => b;
[TestCompiler(true, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_MarshalAsNativeTypeOnReturnTypeNotSupported)]
public static bool BoolMarshalAsR4Call(bool value)
{
return BoolMarshalAsR4(value);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool BoolMarshalAsU1Param([MarshalAs(UnmanagedType.U1)] bool b) => b;
[TestCompiler(true)]
[TestCompiler(false)]
public static bool BoolMarshalAsU1CallParam(bool value)
{
return BoolMarshalAsU1Param(value);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool BoolMarshalAsI1Param([MarshalAs(UnmanagedType.I1)] bool b) => b;
[TestCompiler(true)]
[TestCompiler(false)]
public static bool BoolMarshalAsI1CallParam(bool value)
{
return BoolMarshalAsI1Param(value);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool BoolMarshalAsR4Param([MarshalAs(UnmanagedType.R4)] bool b) => b;
[TestCompiler(true, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_MarshalAsOnParameterNotSupported)]
public static bool BoolMarshalAsR4CallParam(bool value)
{
return BoolMarshalAsR4Param(value);
}
[MethodImpl(MethodImplOptions.NoInlining)]
[return: MarshalAs(UnmanagedType.U1)]
private static bool BoolMarshalAsU1AndI1Param([MarshalAs(UnmanagedType.I1)] bool b) => b;
[TestCompiler(true)]
[TestCompiler(false)]
public static bool BoolMarshalAsU1AndI1CallParam(bool value)
{
return BoolMarshalAsU1AndI1Param(value);
}
[MethodImpl(MethodImplOptions.NoInlining)]
[return: MarshalAs(UnmanagedType.I1)]
private static bool BoolMarshalAsI1AndU1Param([MarshalAs(UnmanagedType.U1)] bool b) => b;
[TestCompiler(true)]
[TestCompiler(false)]
public static bool BoolMarshalAsI1AndU1CallParam(bool value)
{
return BoolMarshalAsI1AndU1Param(value);
}
[TestCompiler]
public static int Char()
{
return sizeof(char);
}
[TestCompiler]
public static int Int8()
{
return sizeof(sbyte);
}
[TestCompiler]
public static int Int16()
{
return sizeof(short);
}
[TestCompiler]
public static int Int32()
{
return sizeof(int);
}
[TestCompiler]
public static int Int64()
{
return sizeof(long);
}
[TestCompiler]
public static int UInt8()
{
return sizeof(byte);
}
[TestCompiler]
public static int UInt16()
{
return sizeof(ushort);
}
[TestCompiler]
public static int UInt32()
{
return sizeof(uint);
}
[TestCompiler]
public static int UInt64()
{
return sizeof(ulong);
}
[TestCompiler]
public static int EnumSizeOf()
{
return sizeof(MyEnum);
}
[TestCompiler]
public static int EnumByteSizeOf()
{
return sizeof(MyEnumByte);
}
[TestCompiler(MyEnumByte.Tada2)]
public static MyEnumByte CheckEnumByte(ref MyEnumByte value)
{
// Check stloc for enum
value = MyEnumByte.Tada1;
return value;
}
[TestCompiler(MyEnum.Value15)]
public static int EnumByParam(MyEnum value)
{
return 1 + (int)value;
}
[TestCompiler]
public static float Struct()
{
var value = new MyStruct(1,2,3,4);
return value.x + value.y + value.z + value.w;
}
[TestCompiler]
public static long StructAccess()
{
var s = new InterleavedBoolStruct();
s.b1 = true;
s.i2 = -1;
s.b3 = true;
s.i5 = 3;
return s.i5;
}
[TestCompiler(true)]
[TestCompiler(false)]
public static bool StructWithBool(bool value)
{
// This method test that storage of boolean between local and struct is working
// (as they could have different layout)
var b = new BoolStruct();
b.b1 = !value;
return b.b1;
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_CallingManagedMethodNotSupported)]
public static int TestUsingReferenceType()
{
return "this is not supported by burst".Length;
}
private struct MyStruct
{
public MyStruct(float x, float y, float z, float w)
{
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
public float x;
public float y;
public float z;
public float w;
}
private struct BoolStruct
{
#pragma warning disable 0649
public bool b1;
public bool b2;
#pragma warning restore 0649
}
private unsafe struct BoolFixedStruct
{
#pragma warning disable 0649
public fixed bool Values[16];
#pragma warning restore 0649
}
private struct InterleavedBoolStruct
{
#pragma warning disable 0649
public bool b1;
public int i2;
public bool b3;
public bool b4;
public long i5;
public MyEnum e6;
#pragma warning restore 0649
}
public enum MyEnum
{
Value1 = 1,
Value15 = 15,
}
[StructLayout(LayoutKind.Explicit)]
private struct ExplicitLayoutStruct
{
[FieldOffset(0)]
public int FieldA;
[FieldOffset(0)]
public int FieldB;
}
[StructLayout(LayoutKind.Sequential, Size = 1024)]
private struct StructWithSize
{
public int FieldA;
public int FieldB;
}
private struct EmptyStruct
{
}
public enum MyEnumByte : byte
{
Tada1 = 1,
Tada2 = 2
}
private static ValueTuple<int> ReturnValueTuple1() => ValueTuple.Create(42);
[TestCompiler]
public static long TestValueTuple1Return()
{
var tuple = ReturnValueTuple1();
return tuple.Item1;
}
private static (int, uint) ReturnValueTuple2() => (42, 13);
[TestCompiler]
public static long TestValueTuple2Return()
{
var tuple = ReturnValueTuple2();
return tuple.Item1 + tuple.Item2;
}
private static (int, uint, byte) ReturnValueTuple3() => (42, 13, 13);
[TestCompiler]
public static long TestValueTuple3Return()
{
var tuple = ReturnValueTuple3();
return tuple.Item1 + tuple.Item2 + tuple.Item3;
}
private static (int, uint, byte, sbyte) ReturnValueTuple4() => (42, 13, 13, -13);
[TestCompiler]
public static long TestValueTuple4Return()
{
var tuple = ReturnValueTuple4();
return tuple.Item1 + tuple.Item2 + tuple.Item3 + tuple.Item4;
}
private static (int, uint, byte, sbyte, long) ReturnValueTuple5() => (42, 13, 13, -13, 53);
[TestCompiler]
public static long TestValueTuple5Return()
{
var tuple = ReturnValueTuple5();
return tuple.Item1 + tuple.Item2 + tuple.Item3 + tuple.Item4 + tuple.Item5;
}
private struct SomeStruct
{
public int X;
}
private static (int, uint, byte, sbyte, long, SomeStruct) ReturnValueTuple6() => (42, 13, 13, -13, 535353, new SomeStruct { X = 42 } );
[TestCompiler]
public static long TestValueTuple6Return()
{
var tuple = ReturnValueTuple6();
return tuple.Item1 + tuple.Item2 + tuple.Item3 + tuple.Item4 + tuple.Item5 + tuple.Item6.X;
}
private static (int, uint, byte, sbyte, long, SomeStruct, short) ReturnValueTuple7() => (42, 13, 13, -13, 535353, new SomeStruct { X = 42 }, 400);
[TestCompiler]
public static long TestValueTuple7Return()
{
var tuple = ReturnValueTuple7();
return tuple.Item1 + tuple.Item2 + tuple.Item3 + tuple.Item4 + tuple.Item5 + tuple.Item6.X + tuple.Item7;
}
private static (int, uint, byte, sbyte, long, SomeStruct, short, int) ReturnValueTuple8() => (42, 13, 13, -13, 535353, new SomeStruct { X = 42 }, 400, -400);
[TestCompiler]
public static long TestValueTuple8Return()
{
var tuple = ReturnValueTuple8();
return tuple.Item1 + tuple.Item2 + tuple.Item3 + tuple.Item4 + tuple.Item5 + tuple.Item6.X + tuple.Item7 + tuple.Item8;
}
private static (int, uint, byte, sbyte, long, SomeStruct, short, int, long) ReturnValueTuple9() => (42, 13, 13, -13, 535353, new SomeStruct { X = 42 }, 400, -400, 48);
[TestCompiler]
public static long TestValueTuple9Return()
{
var tuple = ReturnValueTuple9();
return tuple.Item1 + tuple.Item2 + tuple.Item3 + tuple.Item4 + tuple.Item5 + tuple.Item6.X + tuple.Item7 + tuple.Item8 + tuple.Item9;
}
private static long ValueTuple1Arg(ValueTuple<int> tuple)
{
return tuple.Item1;
}
[TestCompiler]
public static long TestValueTuple1Arg()
{
return ValueTuple1Arg(ValueTuple.Create(42));
}
private static long ValueTuple2Arg((int, uint) tuple)
{
return tuple.Item1 + tuple.Item2;
}
[TestCompiler]
public static long TestValueTuple2Arg()
{
return ValueTuple2Arg((42, 13));
}
private static long ValueTuple3Arg((int, uint, byte) tuple)
{
return tuple.Item1 + tuple.Item2 + tuple.Item3;
}
[TestCompiler]
public static long TestValueTuple3Arg()
{
return ValueTuple3Arg((42, 13, 13));
}
private static long ValueTuple4Arg((int, uint, byte, sbyte) tuple)
{
return tuple.Item1 + tuple.Item2 + tuple.Item3 + tuple.Item4;
}
[TestCompiler]
public static long TestValueTuple4Arg()
{
return ValueTuple4Arg((42, 13, 13, -13));
}
private static long ValueTuple5Arg((int, uint, byte, sbyte, long) tuple)
{
return tuple.Item1 + tuple.Item2 + tuple.Item3 + tuple.Item4 + tuple.Item5;
}
[TestCompiler]
public static long TestValueTuple5Arg()
{
return ValueTuple5Arg((42, 13, 13, -13, 535353));
}
private static long ValueTuple6Arg((int, uint, byte, sbyte, long, SomeStruct) tuple)
{
return tuple.Item1 + tuple.Item2 + tuple.Item3 + tuple.Item4 + tuple.Item5 + tuple.Item6.X;
}
[TestCompiler]
public static long TestValueTuple6Arg()
{
return ValueTuple6Arg((42, 13, 13, -13, 535353, new SomeStruct { X = 42 }));
}
private static long ValueTuple7Arg((int, uint, byte, sbyte, long, SomeStruct, short) tuple)
{
return tuple.Item1 + tuple.Item2 + tuple.Item3 + tuple.Item4 + tuple.Item5 + tuple.Item6.X + tuple.Item7;
}
[TestCompiler]
public static long TestValueTuple7Arg()
{
return ValueTuple7Arg((42, 13, 13, -13, 535353, new SomeStruct { X = 42 }, 400));
}
private static long ValueTuple8Arg((int, uint, byte, sbyte, long, SomeStruct, short, int) tuple)
{
return tuple.Item1 + tuple.Item2 + tuple.Item3 + tuple.Item4 + tuple.Item5 + tuple.Item6.X + tuple.Item7 + tuple.Item8;
}
[TestCompiler]
public static long TestValueTuple8Arg()
{
return ValueTuple8Arg((42, 13, 13, -13, 535353, new SomeStruct { X = 42 }, 400, -400));
}
private static long ValueTuple9Arg((int, uint, byte, sbyte, long, SomeStruct, short, int, long) tuple)
{
return tuple.Item1 + tuple.Item2 + tuple.Item3 + tuple.Item4 + tuple.Item5 + tuple.Item6.X + tuple.Item7 + tuple.Item8 + tuple.Item9;
}
[TestCompiler]
public static long TestValueTuple9Arg()
{
return ValueTuple9Arg((42, 13, 13, -13, 535353, new SomeStruct { X = 42 }, 400, -400, 48));
}
// This needs to be here because the static delegate registry refers to it.
public struct SomeStructWithValueTuple
{
public ValueTuple<int, float> X;
public struct Provider : IArgumentProvider
{
public object Value => new SomeStructWithValueTuple { X = (42, 42.0f) };
}
}
#if UNITY_2022_1_OR_NEWER
public readonly struct InitOnly
{
public readonly float Value { get; init; }
}
[TestCompiler]
public static float TestInitOnly() => new InitOnly { Value = default }.Value;
#endif
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a0499a50a9b63d9a90fc428e1f5c89e9
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 953d1f4d7d69334fbc9657d7d82a855b
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,928 @@
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
{
[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;
}
}
}
[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 IntPtr PointerMathAddPNTypesByte(UInt64 p,byte a)
{
var pointer = (byte*)p;
return new IntPtr(pointer + a); // Pointer LHS
}
[TestCompiler(0ul, byte.MinValue)]
[TestCompiler(0ul, byte.MaxValue)]
public static unsafe IntPtr PointerMathAddNPTypesByte(UInt64 p,byte a)
{
var pointer = (byte*)p;
return new IntPtr(a + pointer); // Pointer RHS
}
[TestCompiler(0ul, byte.MinValue)]
[TestCompiler(0ul, byte.MaxValue)]
public static unsafe IntPtr PointerMathSubPNTypesByte(UInt64 p,byte a)
{
var pointer = (byte*)p;
return new IntPtr(pointer - a); // Pointer LHS (no RHS since not legal in C#)
}
[TestCompiler(0ul, sbyte.MinValue)]
[TestCompiler(0ul, sbyte.MaxValue)]
public static unsafe IntPtr PointerMathAddPNTypesSByte(UInt64 p,sbyte a)
{
var pointer = (sbyte*)p;
return new IntPtr(pointer + a); // Pointer LHS
}
[TestCompiler(0ul, sbyte.MinValue)]
[TestCompiler(0ul, sbyte.MaxValue)]
public static unsafe IntPtr PointerMathAddNPTypesSByte(UInt64 p,sbyte a)
{
var pointer = (sbyte*)p;
return new IntPtr(a + pointer); // Pointer RHS
}
[TestCompiler(0ul, sbyte.MinValue)]
[TestCompiler(0ul, sbyte.MaxValue)]
public static unsafe IntPtr PointerMathSubPNTypesSByte(UInt64 p,sbyte a)
{
var pointer = (sbyte*)p;
return new IntPtr(pointer - a); // Pointer LHS (no RHS since not legal in C#)
}
[TestCompiler(0ul, short.MinValue)]
[TestCompiler(0ul, short.MaxValue)]
public static unsafe IntPtr PointerMathAddPNTypesShort(UInt64 p,short a)
{
var pointer = (short*)p;
return new IntPtr(pointer + a); // Pointer LHS
}
[TestCompiler(0ul, short.MinValue)]
[TestCompiler(0ul, short.MaxValue)]
public static unsafe IntPtr PointerMathAddNPTypesShort(UInt64 p,short a)
{
var pointer = (short*)p;
return new IntPtr(a + pointer); // Pointer RHS
}
[TestCompiler(0ul, short.MinValue)]
[TestCompiler(0ul, short.MaxValue)]
public static unsafe IntPtr PointerMathSubPNTypesShort(UInt64 p,short a)
{
var pointer = (short*)p;
return new IntPtr(pointer - a); // Pointer LHS (no RHS since not legal in C#)
}
[TestCompiler(0ul, ushort.MinValue)]
[TestCompiler(0ul, ushort.MaxValue)]
public static unsafe IntPtr PointerMathAddPNTypesUShort(UInt64 p,ushort a)
{
var pointer = (ushort*)p;
return new IntPtr(pointer + a); // Pointer LHS
}
[TestCompiler(0ul, ushort.MinValue)]
[TestCompiler(0ul, ushort.MaxValue)]
public static unsafe IntPtr PointerMathAddNPTypesUShort(UInt64 p,ushort a)
{
var pointer = (ushort*)p;
return new IntPtr(a + pointer); // Pointer RHS
}
[TestCompiler(0ul, ushort.MinValue)]
[TestCompiler(0ul, ushort.MaxValue)]
public static unsafe IntPtr PointerMathSubPNTypesUShort(UInt64 p,ushort a)
{
var pointer = (ushort*)p;
return new IntPtr(pointer - a); // Pointer LHS (no RHS since not legal in C#)
}
[TestCompiler(0ul, int.MinValue)]
[TestCompiler(0ul, int.MaxValue)]
public static unsafe IntPtr PointerMathAddPNTypesInt(UInt64 p,int a)
{
var pointer = (int*)p;
return new IntPtr(pointer + a); // Pointer LHS
}
[TestCompiler(0ul, int.MinValue)]
[TestCompiler(0ul, int.MaxValue)]
public static unsafe IntPtr PointerMathAddNPTypesInt(UInt64 p,int a)
{
var pointer = (int*)p;
return new IntPtr(a + pointer); // Pointer RHS
}
[TestCompiler(0ul, int.MinValue)]
[TestCompiler(0ul, int.MaxValue)]
public static unsafe IntPtr PointerMathSubPNTypesInt(UInt64 p,int a)
{
var pointer = (int*)p;
return new IntPtr(pointer - a); // Pointer LHS (no RHS since not legal in C#)
}
[TestCompiler(0ul, uint.MinValue)]
[TestCompiler(0ul, uint.MaxValue)]
public static unsafe IntPtr PointerMathAddPNTypesUInt(UInt64 p,uint a)
{
var pointer = (uint*)p;
return new IntPtr(pointer + a); // Pointer LHS
}
[TestCompiler(0ul, uint.MinValue)]
[TestCompiler(0ul, uint.MaxValue)]
public static unsafe IntPtr PointerMathAddNPTypesUInt(UInt64 p,uint a)
{
var pointer = (uint*)p;
return new IntPtr(a + pointer); // Pointer RHS
}
[TestCompiler(0ul, uint.MinValue)]
[TestCompiler(0ul, uint.MaxValue)]
public static unsafe IntPtr PointerMathSubPNTypesUInt(UInt64 p,uint a)
{
var pointer = (uint*)p;
return new IntPtr(pointer - a); // Pointer LHS (no RHS since not legal in C#)
}
[TestCompiler(0ul, long.MinValue)]
[TestCompiler(0ul, long.MaxValue)]
public static unsafe IntPtr PolongerMathAddPNTypesLong(UInt64 p,long a)
{
var polonger = (long*)p;
return new IntPtr(polonger + a); // Polonger LHS
}
[TestCompiler(0ul, long.MinValue)]
[TestCompiler(0ul, long.MaxValue)]
public static unsafe IntPtr PolongerMathAddNPTypesLong(UInt64 p,long a)
{
var polonger = (long*)p;
return new IntPtr(a + polonger); // Polonger RHS
}
[TestCompiler(0ul, long.MinValue)]
[TestCompiler(0ul, long.MaxValue)]
public static unsafe IntPtr PolongerMathSubPNTypesLong(UInt64 p,long a)
{
var polonger = (long*)p;
return new IntPtr(polonger - a); // Polonger LHS (no RHS since not legal in C#)
}
[TestCompiler(0ul, ulong.MinValue)]
[TestCompiler(0ul, ulong.MaxValue)]
public static unsafe IntPtr PolongerMathAddPNTypesULong(UInt64 p,ulong a)
{
var polonger = (ulong*)p;
return new IntPtr(polonger + a); // Polonger LHS
}
[TestCompiler(0ul, ulong.MinValue)]
[TestCompiler(0ul, ulong.MaxValue)]
public static unsafe IntPtr PolongerMathAddNPTypesULong(UInt64 p,ulong a)
{
var polonger = (ulong*)p;
return new IntPtr(a + polonger); // Polonger RHS
}
[TestCompiler(0ul, ulong.MinValue)]
[TestCompiler(0ul, ulong.MaxValue)]
public static unsafe IntPtr PolongerMathSubPNTypesULong(UInt64 p,ulong a)
{
var polonger = (ulong*)p;
return new IntPtr(polonger - a); // Polonger LHS (no RHS since not legal in C#)
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3d218d6a948d3d8c98c40cca55189572
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,66 @@
namespace Burst.Compiler.IL.Tests.Shared
{
public class Patterns
{
[TestCompiler(2)]
[TestCompiler(1)]
[TestCompiler(0)]
public static int PropertyPattern(int x)
{
var point = new Point { X = x, Y = 5 };
return point switch
{
{ X: 2 } => 10,
{ X: 1 } => 5,
_ => 0
};
}
private struct Point
{
public int X;
public int Y;
}
[TestCompiler(1, 2)]
[TestCompiler(2, 4)]
[TestCompiler(0, 0)]
public static int TuplePattern(int x, int y)
{
return (x, y) switch
{
(1, 2) => 10,
(2, 4) => 5,
_ => 0
};
}
private struct DeconstructablePoint
{
public int X;
public int Y;
public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}
[TestCompiler(1, -1)]
[TestCompiler(-1, 1)]
[TestCompiler(1, 1)]
[TestCompiler(-1, -1)]
public static int PositionalPattern(int pointX, int pointY)
{
var point = new DeconstructablePoint { X = pointX, Y = pointY };
return point switch
{
(0, 0) => 0,
var (x, y) when x > 0 && y > 0 => 1,
var (x, y) when x < 0 && y > 0 => 2,
var (x, y) when x < 0 && y < 0 => 3,
var (x, y) when x > 0 && y < 0 => 4,
var (_, _) => 5
};
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 50c3d62ace6136cb9c85f8e2a44b7aec
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,144 @@
using System.Runtime.CompilerServices;
using Unity.Burst;
using Unity.Burst.CompilerServices;
using UnityBenchShared;
namespace Burst.Compiler.IL.Tests
{
internal class Functions
{
[TestCompiler]
public static int CheckFunctionCall()
{
return AnotherFunction();
}
private static int AnotherFunction()
{
return 150;
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_UnableToAccessManagedMethod)]
public static void Boxing()
{
var a = new CustomStruct();
// This will box CustomStruct, so this method should fail when compiling
a.GetType();
}
private struct CustomStruct
{
}
public static int NotDiscardable()
{
return 3;
}
[BurstDiscard]
public static void Discardable()
{
}
[TestCompiler]
public static int TestCallsOfDiscardedMethodRegression()
{
// The regression was that we would queue all calls of a method, but if we encountered a discardable one
// We would stop visiting pending methods. This resulting in method bodies not being visited.
Discardable();
return NotDiscardable();
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static int NoInline(int x)
{
return x;
}
[TestCompiler(42)]
public static int TestNoInline(int x)
{
return NoInline(x);
}
[MethodImpl(MethodImplOptions.NoOptimization)]
public static int NoOptimization(int x)
{
return x;
}
[TestCompiler(42)]
public static int TestNoOptimization(int x)
{
return NoOptimization(x);
}
[TestCompiler(42)]
public static int TestImplicitCapture(int x)
{
return SomeFunction();
int SomeFunction()
{
return x;
}
}
public struct Pair
{
public int X;
public int Y;
public struct Provider : IArgumentProvider
{
public object Value => new Pair { X = 13, Y = 42 };
}
}
[TestCompiler(42, typeof(Pair.Provider))]
public static int TestImplicitCaptureInLoop(int x, ref Pair rp)
{
int total = 0;
Pair p = rp;
for (int i = 0; i < x; i++)
{
total += SomeFunction(42, 42, 42, 42, 42, i);
int SomeFunction(int a, int b, int c, int d, int e, int otherI)
{
if (p.Y != 0)
{
return (otherI == i) ? 56 : -13;
}
return 0;
}
}
return total;
}
[TestCompiler(42)]
[IgnoreWarning((int)DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
public static void NoWarningsWithSingle(int i)
{
if ((6 * 8) == i)
{
throw new System.Exception("Not the meaning of life!");
}
}
[TestCompiler(42)]
[IgnoreWarning((int)DiagnosticId.WRN_LoopIntrinsicCalledButLoopOptimizedAway)]
[IgnoreWarning((int)DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
public static void NoWarningsWithMultiple(int i)
{
if ((6 * 8) == i)
{
throw new System.Exception("Not the meaning of life!");
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c6f9aa18fd4b3d1d9ef249e3c61af783
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,260 @@
// Doesn't work with IL2CPP yet - waiting for Unity fix to land.
#if BURST_INTERNAL //|| UNITY_2021_2_OR_NEWER
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using NUnit.Framework;
using Unity.Burst;
using UnityBenchShared;
#if BURST_INTERNAL
using System.IO;
using System.Reflection;
using Burst.Compiler.IL.Aot;
#endif
namespace Burst.Compiler.IL.Tests
{
[RestrictPlatform("Mono on linux crashes to what appears to be a mono bug", Platform.Linux, exclude: true)]
internal class TestCSharpFunctionPointers
{
[TestCompiler]
public static unsafe int TestCSharpFunctionPointer()
{
delegate* unmanaged[Cdecl]<int, int> callback = &TestCSharpFunctionPointerCallback;
return TestCSharpFunctionPointerHelper(callback);
}
private static unsafe int TestCSharpFunctionPointerHelper(delegate* unmanaged[Cdecl]<int, int> callback)
{
return callback(5);
}
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static int TestCSharpFunctionPointerCallback(int value) => value + 1;
[TestCompiler]
public static unsafe int TestCSharpFunctionPointerCastingParameterPtrFromVoid()
{
delegate* unmanaged[Cdecl]<void*, int> callback = &TestCSharpFunctionPointerCallbackVoidPtr;
delegate* unmanaged[Cdecl]<int*, int> callbackCasted = callback;
int i = 5;
return callbackCasted(&i);
}
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static unsafe int TestCSharpFunctionPointerCallbackVoidPtr(void* value) => *((int*)value) + 1;
[TestCompiler]
public static unsafe int TestCSharpFunctionPointerCastingParameterPtrToVoid()
{
delegate* unmanaged[Cdecl]<int*, int> callback = &TestCSharpFunctionPointerCallbackIntPtr;
delegate* unmanaged[Cdecl]<void*, int> callbackCasted = (delegate* unmanaged[Cdecl]<void*, int>)callback;
int i = 5;
return callbackCasted(&i);
}
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static unsafe int TestCSharpFunctionPointerCallbackIntPtr(int* value) => *value + 1;
[TestCompiler]
public static unsafe int TestCSharpFunctionPointerCastingToAndFromVoidPtr()
{
delegate* unmanaged[Cdecl]<int*, int> callback = &TestCSharpFunctionPointerCallbackIntPtr;
void* callbackAsVoidPtr = callback;
delegate* unmanaged[Cdecl]<int*, int> callbackCasted = (delegate* unmanaged[Cdecl]<int*, int>)callbackAsVoidPtr;
int i = 5;
return callbackCasted(&i);
}
public struct CSharpFunctionPointerProvider : IArgumentProvider
{
public unsafe object Value
{
get
{
delegate* unmanaged[Cdecl]<int, int> callback = &TestCSharpFunctionPointerCallback;
return (IntPtr)callback;
}
}
}
[TestCompiler(typeof(CSharpFunctionPointerProvider))]
public static unsafe int TestCSharpFunctionPointerPassedInFromOutside(IntPtr callbackAsIntPtr)
{
delegate* unmanaged[Cdecl]<int, int> callback = (delegate* unmanaged[Cdecl]<int, int>)callbackAsIntPtr;
return TestCSharpFunctionPointerHelper(callback);
}
private struct TestCSharpFunctionPointerWithStructParameterStruct
{
public int X;
}
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static int TestCSharpFunctionPointerWithStructParameterCallback(TestCSharpFunctionPointerWithStructParameterStruct value) => value.X + 1;
public struct CSharpFunctionPointerWithStructParameterProvider : IArgumentProvider
{
public unsafe object Value
{
get
{
delegate* unmanaged[Cdecl]<TestCSharpFunctionPointerWithStructParameterStruct, int> callback = &TestCSharpFunctionPointerWithStructParameterCallback;
return (IntPtr)callback;
}
}
}
[TestCompiler(typeof(CSharpFunctionPointerWithStructParameterProvider))]
public static unsafe int TestCSharpFunctionPointerPassedInFromOutsideWithStructParameter(IntPtr untypedFp)
{
return TestHashingFunctionPointerTypeHelper((delegate* unmanaged[Cdecl]<TestCSharpFunctionPointerWithStructParameterStruct, int>)untypedFp);
}
private static unsafe int TestHashingFunctionPointerTypeHelper(delegate* unmanaged[Cdecl]<TestCSharpFunctionPointerWithStructParameterStruct, int> fp)
{
return fp(new TestCSharpFunctionPointerWithStructParameterStruct { X = 42 });
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_CalliNonCCallingConventionNotSupported)]
public static unsafe int TestCSharpFunctionPointerInvalidCallingConvention()
{
delegate*<int, int> callback = &TestCSharpFunctionPointerInvalidCallingConventionCallback;
return callback(5);
}
private static int TestCSharpFunctionPointerInvalidCallingConventionCallback(int value) => value + 1;
[TestCompiler]
public static unsafe int TestCSharpFunctionPointerMissingBurstCompileAttribute()
{
delegate* unmanaged[Cdecl]<int, int> callback = &TestCSharpFunctionPointerCallbackMissingBurstCompileAttribute;
return callback(5);
}
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static int TestCSharpFunctionPointerCallbackMissingBurstCompileAttribute(int value) => value + 1;
[Test]
public unsafe void TestFunctionPointerReturnedFromBurstFunction()
{
#if BURST_INTERNAL
var libraryCacheFolderName = Path.Combine(
Path.GetDirectoryName(GetType().Assembly.Location),
nameof(TestCSharpFunctionPointers),
nameof(TestFunctionPointerReturnedFromBurstFunction));
if (Directory.Exists(libraryCacheFolderName))
{
Directory.Delete(libraryCacheFolderName, true);
}
using var globalContext = new Server.GlobalContext(libraryCacheFolderName);
var jitOptions = new AotCompilerOptions();
using var methodCompiler = new Helpers.MethodCompiler(globalContext, jitOptions.BackendName, name => IntPtr.Zero);
BurstCompiler.InternalCompiler = del =>
{
var getMethod = del.GetType().GetMethod("get_Method", BindingFlags.Public | BindingFlags.Instance);
var methodInfo = (MethodInfo)getMethod.Invoke(del, new object[0]);
var compiledResult = methodCompiler.CompileMethod(methodInfo, jitOptions);
return compiledResult.FunctionPointer;
};
#endif
var fp = BurstCompiler.CompileFunctionPointer<DelegateWithCSharpFunctionPointerReturn>(EntryPointWithCSharpFunctionPointerReturn);
var fpInner = fp.Invoke();
delegate* unmanaged[Cdecl]<float, float, float, float, float, float, float> callback = (delegate* unmanaged[Cdecl]<float, float, float, float, float, float, float>)fpInner;
var result = callback(1, 2, 4, 8, 16, 32);
Assert.AreEqual((float)(1 + 2 + 4 + 8 + 16 + 32), result);
}
[BurstCompile(CompileSynchronously = true)]
private static unsafe IntPtr EntryPointWithCSharpFunctionPointerReturn()
{
delegate* unmanaged[Cdecl]<float, float, float, float, float, float, float> fp = &EntryPointWithCSharpFunctionPointerReturnHelper;
return (IntPtr)fp;
}
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static unsafe float EntryPointWithCSharpFunctionPointerReturnHelper(float p1, float p2, float p3, float p4, float p5, float p6)
{
return p1 + p2 + p3 + p4 + p5 + p6;
}
private unsafe delegate IntPtr DelegateWithCSharpFunctionPointerReturn();
// Note that there are 6 float parameters to try to catch any issues with calling conventions.
private unsafe delegate float DelegateWithCSharpFunctionPointerReturnHelper(float p1, float p2, float p3, float p4, float p5, float p6);
// Note that this test previously had a `out int i` parameter, but a bugfix in Roslyn
// means that ref parameters in UnmanagedCallersOnly methods now result in a compilation error:
// https://github.com/dotnet/roslyn/issues/57025
// So we've updated this test to use a pointer.
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static unsafe void TestCSharpFunctionPointerCallbackWithOut(int* i)
{
TestCSharpFunctionPointerCallbackWithOut(out *i);
}
private static void TestCSharpFunctionPointerCallbackWithOut(out int i)
{
i = 42;
}
[TestCompiler]
public static unsafe int TestCSharpFunctionPointerWithOut()
{
delegate* unmanaged[Cdecl]<int*, void> callback = &TestCSharpFunctionPointerCallbackWithOut;
int i;
callback(&i);
return i;
}
#if BURST_TESTS_ONLY
[DllImport("burst-dllimport-native")]
private static extern unsafe int callFunctionPointer(delegate* unmanaged[Cdecl]<int, int> f);
// Ignored on wasm since dynamic linking is not supported at present.
// Override result on Mono because it throws a StackOverflowException for some reason related to the function pointer.
// We should use OverrideResultOnMono, but OverrideResultOnMono still runs the managed version, which causes a crash,
// so we use OverrideManagedResult.
[TestCompiler(IgnoreOnPlatform = Backend.TargetPlatform.Wasm, OverrideManagedResult = 43)]
public static unsafe int TestPassingFunctionPointerToNativeCode()
{
return callFunctionPointer(&TestCSharpFunctionPointerCallback);
}
#endif
}
}
// This attribute is also included in com.unity.burst/Tests/Runtime/FunctionPointerTests.cs,
// so we want to exclude it here when we're running inside Unity otherwise we'll get a
// duplicate definition error.
#if BURST_TESTS_ONLY
// UnmanagedCallersOnlyAttribute is new in .NET 5.0. This attribute is required
// when you declare an unmanaged function pointer with an explicit calling convention.
// Fortunately, Roslyn lets us declare the attribute class ourselves, and it will be used.
// Users will need this same declaration in their own projects, in order to use
// C# 9.0 function pointers.
namespace System.Runtime.InteropServices
{
[AttributeUsage(System.AttributeTargets.Method, Inherited = false)]
public sealed class UnmanagedCallersOnlyAttribute : Attribute
{
public Type[] CallConvs;
}
}
#endif
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7a3d2b4e287138d6b5a68635fcda35ae
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,112 @@
#if UNITY_ANDROID && !UNITY_EDITOR
using System.Runtime.InteropServices;
namespace Burst.Compiler.IL.Tests
{
public class DllImportAndroid
{
public unsafe struct HandleStruct
{
public void* Handle;
}
public struct NestedHandleStruct
{
public HandleStruct Handle;
}
public unsafe struct TypedHandleStruct
{
public byte* Handle;
}
public struct IntInStruct
{
public int Handle;
}
public struct LongInStruct
{
public long Handle;
}
[DllImport("burst-dllimport-native")]
public static extern void allVoid();
[TestCompiler]
public static void AllVoid()
{
allVoid();
}
[DllImport("burst-dllimport-native")]
public static extern int incrementByOne(int x);
[TestCompiler]
public static int UseDllImportedFunction()
{
return incrementByOne(41);
}
[DllImport("burst-dllimport-native")]
public static extern int readFromPtr(ref int x);
[TestCompiler]
public static int ReadFromPtr()
{
int x = 37;
return readFromPtr(ref x);
}
[DllImport("burst-dllimport-native")]
public static extern HandleStruct handleStruct(HandleStruct handle);
[TestCompiler]
public unsafe static long HandleStructByVal()
{
var handle = new HandleStruct { Handle = (void*)0x42 };
return (long)handleStruct(handle).Handle;
}
[DllImport("burst-dllimport-native")]
public static extern NestedHandleStruct nestedHandleStruct(NestedHandleStruct handle);
[TestCompiler]
public unsafe static long NestedHandleStructByVal()
{
var handle = new NestedHandleStruct { Handle = new HandleStruct { Handle = (void*)0x42 } };
return (long)nestedHandleStruct(handle).Handle.Handle;
}
[DllImport("burst-dllimport-native")]
public static extern TypedHandleStruct typedHandleStruct(TypedHandleStruct handle);
[TestCompiler]
public unsafe static long TypedHandleStructByVal()
{
var handle = new TypedHandleStruct { Handle = (byte*)0x42 };
return (long)typedHandleStruct(handle).Handle;
}
[DllImport("burst-dllimport-native")]
public static extern IntInStruct intInStruct(IntInStruct handle);
[TestCompiler]
public unsafe static long IntInStructByVal()
{
var handle = new IntInStruct { Handle = 0x42424242 };
return (long)intInStruct(handle).Handle;
}
[DllImport("burst-dllimport-native")]
public static extern LongInStruct longInStruct(LongInStruct handle);
[TestCompiler]
public unsafe static long LongInStructByVal()
{
var handle = new LongInStruct { Handle = 0x4242424242424242 };
return (long)longInStruct(handle).Handle;
}
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bb0c92e22ce4395fae3821dcc85a3113
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,852 @@
using System;
using NUnit.Framework;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
internal class ControlFlows
{
[TestCompiler]
public static int For()
{
var counter = 0;
for (var i = 0; i < 10; i++)
counter++;
return counter;
}
[TestCompiler(10)]
public static int ForBreak(int a)
{
int result = 0;
for (int i = 0; i < a; i++)
{
if (i == 5)
{
break;
}
result += 2;
}
return result;
}
[TestCompiler(10, 5)]
public static int ForContinue(int a, int b)
{
int result = 0;
for (int i = 0; i < a; i++)
{
if (i == b)
{
continue;
}
result += i;
}
return result;
}
[TestCompiler]
public static int ForBreak2()
{
int i = 0;
while (true)
{
if (i == 5)
{
break;
}
i++;
}
return i;
}
[TestCompiler(10)]
public static float ForDynamicCondition(ref int b)
{
var counter = 0.0f;
for (var i = 0; i < b; i++)
counter++;
return counter;
}
[TestCompiler(5, 5)]
public static int ForNestedIf(int a, int b)
{
var counter = 0;
for (var i = 0; i < a; i++)
for (var i2 = 0; i != b; i++)
{
counter += i;
counter += i2;
}
return counter;
}
[TestCompiler(5, 5)]
public static int DoWhileNested(int a, int b)
{
var total = 0;
var counter2 = 0;
do
{
var counter1 = 0;
do
{
total++;
counter1++;
} while (counter1 < a);
counter2++;
} while (counter2 < b);
return total;
}
[TestCompiler(5)]
public static int While(int a)
{
var i = 0;
var counter = 0;
while (i < a)
{
i++;
counter += i;
}
return counter;
}
[TestCompiler(5)]
public static int ForForIf(int a)
{
var counter = 0;
for (var i = 0; i != a; i++)
for (var j = 0; j < 4; j++)
if (j > 2)
counter = counter + i;
return counter;
}
[TestCompiler(5)]
public static int ForNestedComplex1(int a)
{
var x = 0;
var y = 0;
for (var i = 0; i < a; i++)
{
y = y + 1;
for (var j = 0; j < 4; j++)
{
if (y > 1)
{
x = x + i;
if (x > 2)
{
for (int k = 0; k < 3; k++)
{
y = y + 1;
if (y > 3)
{
x = x + 1;
}
else if (x > 6)
{
y = 1;
break;
}
}
}
else
{
continue;
}
}
else
{
x--;
}
x++;
}
if (y > 2)
{
x = x + 1;
}
}
return x;
}
[TestCompiler(5)]
public static int ForNestedComplex2(int a)
{
var x = 0;
for (var i = 0; i < a; i++)
{
var insideLoop1 = 0;
for (var j = 0; j < 4; j++)
{
x = x + i;
if (x > 2)
{
insideLoop1++;
for (int k = 0; k < 3; k++)
{
if (insideLoop1 > 3)
{
x = x + 1;
}
else if (x > 6)
{
break;
}
}
}
}
if (insideLoop1 > 2)
{
x = x + 1 + insideLoop1;
}
}
return x;
}
[TestCompiler(5)]
[TestCompiler(-5)]
public static int IfReturn(int a)
{
if (a < 0)
return 55;
return 111;
}
[TestCompiler(5)]
[TestCompiler(-5)]
public static int IfElseReturn(int a)
{
int b = 0;
if (a < 0)
{
b = 1;
}
else
{
b = 2;
}
return b;
}
[TestCompiler(5)]
[TestCompiler(-5)]
public static int IfElseReturnDynamic(int a)
{
int b;
if (a < 0)
{
b = a;
}
else
{
b = a + 1;
}
return b;
}
[TestCompiler(10)]
public static int WhileFunction(int a)
{
while (condition_helper(a))
{
a--;
}
return a;
}
[TestCompiler(10)]
public static int WhileDynamic(ref int a)
{
while (a > 2)
{
a--;
}
return a;
}
[TestCompiler(5, 6, 7)]
[TestCompiler(-5, -6, -7)]
public static int IfDeep(int a, int b, int c)
{
int result = 0;
if (a < 0)
{
if (b > 1)
{
if (c < 2)
{
result = 55;
}
else
{
result = 66;
}
}
else
{
result = 77;
}
}
else
{
if (b < 0)
{
if (c < -2)
{
result = 88;
}
else
{
result = 99;
}
}
else
{
result = 100;
}
}
return result;
}
[TestCompiler(5)]
public static int CallRecursive(int n)
{
return InternalCallRecursive(n);
}
private static int InternalCallRecursive(int n)
{
if (n <= 1)
return 1;
return n * InternalCallRecursive(n - 1);
}
[TestCompiler(3f, 8f)]
[TestCompiler(6f, 8f)]
public static float IfCompareFloat(float a, float b)
{
if (a > 5f)
return 10f;
return b;
}
[TestCompiler(10)]
[TestCompiler(0)]
public static float TernaryCompareFloat(int input)
{
return input > 5 ? 2.5f : 1.2F;
}
[TestCompiler(0)]
[TestCompiler(1)]
public static int TernaryMask(int a)
{
return (a & 1) != 0 ? 5 : 4;
}
[TestCompiler(0)]
[TestCompiler(1)]
public static int IfElseMash(int a)
{
if ((a & 1) != 0)
return 5;
else
return 4;
}
[TestCompiler(0)]
public static int IfCallCondition(int a)
{
if (a > 0 && condition_helper(++a))
{
return a;
}
return -10 + a;
}
[TestCompiler(1)]
[TestCompiler(0)]
[TestCompiler(-1)]
public static int IfIncrementCondition(int a)
{
if (a < 0 || condition_helper(++a))
{
return a;
}
return -10 + a;
}
private static bool condition_helper(int value)
{
return value > 2;
}
[TestCompiler(1, 8)]
public static int IfWhileGotoForward(int a, int b)
{
if (a > 0)
{
while (a < 10)
{
a++;
if (a == b)
{
a--;
goto TestLabel;
}
}
a++;
}
TestLabel:
a--;
return a;
}
[TestCompiler(1, 5)]
public static int IfWhileGotoBackward(int a, int b)
{
RewindLabel:
if (a > 0)
{
while (a < 10)
{
a++;
if (a == b)
{
a++;
goto RewindLabel;
}
}
a++;
}
a--;
return a;
}
[TestCompiler(-1, 0)]
[TestCompiler(0, 0)]
[TestCompiler(0, -1)]
public static int IfAssignCondition(int a, int b)
{
int result = 0;
if (++a > 0 && ++b > 0)
{
result = a + b;
}
else
{
result = a * 10 + b;
}
return result;
}
private static bool ProcessFirstInt(int a, out float b)
{
b = a + 1;
return b < 10;
}
private static bool ProcessNextInt(int a, ref float b)
{
b = a + 2;
return b < 20;
}
[TestCompiler(1, 10)]
public static float ForWhileNestedCall(int a, int b)
{
float value = 0;
for (int i = 0; i < b * 3; i++)
{
var flag = ProcessFirstInt(a, out value);
int num2 = 0;
while (flag && num2 < 2)
{
bool flag2 = i == a;
if (flag2)
{
flag = ProcessNextInt(a + i, ref value);
}
else
{
value++;
flag = ProcessNextInt(a + b + i, ref value);
}
num2++;
}
}
return value;
}
#if BURST_TESTS_ONLY
[TestCompiler(true)]
[TestCompiler(false)]
public static bool CheckDup(bool value)
{
return ILTestsHelper.CheckDupBeforeJump(value);
}
#endif
[TestCompiler(1)]
public static int WhileIfContinue(int a)
{
while (a > 10)
{
if (a < 5)
{
a++;
if (a == 8)
{
continue;
}
}
a++;
}
return a;
}
[TestCompiler(0)]
[TestCompiler(1)]
[TestCompiler(2)]
[TestCompiler(3)]
[TestCompiler(4)]
public static int SwitchReturn(int a)
{
switch (a)
{
case 1:
return 100;
case 2:
return 200;
case 3:
return 300;
case 10:
return 300;
default:
return 1000;
}
}
[TestCompiler(0)]
[TestCompiler(1)]
[TestCompiler(2)]
[TestCompiler(3)]
[TestCompiler(4)]
public static int SwitchBreak(int a)
{
switch (a)
{
case 1:
return 100;
case 2:
break;
default:
return 1000;
}
return 200;
}
[TestCompiler((byte)0)]
[TestCompiler((byte)1)]
[TestCompiler((byte)2)]
[TestCompiler((byte)3)]
[TestCompiler((byte)4)]
public static int SwitchBreakByte(byte a)
{
switch (a)
{
case 1:
return 100;
case 2:
break;
default:
return 1000;
}
return 200;
}
public static byte GetValueAsByte(int a)
{
return (byte)a;
}
[TestCompiler(0)]
[TestCompiler(1)]
[TestCompiler(2)]
[TestCompiler(3)]
public static byte SwitchByteReturnFromFunction(int a)
{
switch (GetValueAsByte(a))
{
case 0:
return 1;
case 1:
return 2;
case 2:
return 3;
default:
return 0;
}
}
[TestCompiler(long.MaxValue)]
[TestCompiler(long.MinValue)]
[TestCompiler(0)]
public static byte SwitchOnLong(long a)
{
switch (a)
{
case long.MaxValue:
return 1;
case long.MinValue:
return 2;
default:
return 0;
}
}
public static byte TestSwitchByteReturn(NativeArray<byte> _results, int a)
{
if (_results.Length > a)
{
switch (_results[a])
{
case 0:
return 1;
case 1:
return 2;
case 2:
return 3;
default:
return 0;
}
}
return 99;
}
[TestCompiler(EnumSwitch.Case1)]
[TestCompiler(EnumSwitch.Case2)]
[TestCompiler(EnumSwitch.Case3)]
public static int SwitchEnum(EnumSwitch a)
{
switch (a)
{
case EnumSwitch.Case1:
return 100;
case EnumSwitch.Case3:
break;
default:
return 1000;
}
return 200;
}
public enum EnumSwitch
{
Case1,
Case2,
Case3,
}
[TestCompiler(long.MaxValue)]
[TestCompiler(long.MinValue)]
[TestCompiler(0)]
public static byte SwitchExpression(long a)
{
return a switch
{
long.MaxValue => 1,
long.MinValue => 2,
_ => 0,
};
}
[TestCompiler(ExpectedException = typeof(InvalidOperationException), ExpectedDiagnosticId = DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
[MonoOnly(".NET CLR does not support burst.abort correctly")]
public static int ExceptionReachedReturn()
{
throw new InvalidOperationException("This is bad 1");
}
[TestCompiler(ExpectedException = typeof(InvalidOperationException), ExpectedDiagnosticId = DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
[MonoOnly(".NET CLR does not support burst.abort correctly")]
public static void ExceptionReached()
{
throw new InvalidOperationException("This is bad 2");
}
[TestCompiler(1, ExpectedDiagnosticId = DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
[TestCompiler(2, ExpectedDiagnosticId = DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
public static void ExceptionNotReached(int a)
{
if (a > 10)
{
throw new InvalidOperationException("This is bad 2");
}
}
[TestCompiler(1, ExpectedDiagnosticId = DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
[TestCompiler(2, ExpectedDiagnosticId = DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
public static void ExceptionMultipleNotReached(int a)
{
if (a > 10)
{
if (a > 15)
{
throw new InvalidOperationException("This is bad 2");
}
else
{
if (a < 8)
{
throw new NotSupportedException();
}
else
{
a = a + 1;
}
}
}
}
private struct SmallStruct
{
public int I;
public float F;
}
private static SmallStruct UnreachedException(bool b)
{
if (b)
{
throw new Exception("Never here!");
}
return new SmallStruct { I = 42, F = 42.0f };
}
[TestCompiler(0, ExpectedDiagnosticId = DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
public static double UnreachedExceptionInCalledFunction(int a)
{
var result = UnreachedException(a != 0);
return result.I + result.F;
}
[TestCompiler(1, ExpectedDiagnosticId = DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
public static int ExceptionNotReachedReturn(int a)
{
int b = a;
if (a > 10)
{
b = 5;
throw new InvalidOperationException("This is bad 2");
}
return b;
}
[TestCompiler(13, ExpectedDiagnosticId = DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
[TestCompiler(1, ExpectedDiagnosticId = DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
public static int ExceptionMultipleNotReachedReturn(int a)
{
if (a > 10)
{
if (a > 15)
{
throw new InvalidOperationException("This is bad 2");
}
else
{
if (a < 12)
{
throw new NotSupportedException();
}
else
{
a = a + 1;
}
}
}
return a;
}
[TestCompiler]
public static void TestInternalError()
{
var job = new InternalErrorVariableNotFound();
job.Execute();
}
public struct InternalErrorVariableNotFound : IJob
{
public void Execute()
{
CausesError(3);
}
static int CausesError(int x)
{
int y = 0;
while (y != 0 && y != 1)
{
if (x > 0)
x = y++;
}
return y;
}
}
[TestCompiler(true)]
public static int TestPopNonInitialTrailingPush(bool x)
{
return (x ? 1 : -1) * math.min(16, 1);
}
[TestCompiler]
// Check unsigned ternary comparison (Bxx_Un) opcodes
public static ulong TestUnsignedTernary()
{
ulong a = 0;
ulong b = ~0UL;
ulong c = (a < b) ? 1UL : 0;
ulong d = (a <= b) ? 1UL : 0;
ulong e = (a > b) ? 0: 1UL;
ulong f = (a >= b) ? 0: 1UL;
return c + d + e + f;
}
[TestCompiler((byte)0)]
[TestCompiler((byte) 1)]
public static int TestByteAndIntFlow(byte value)
{
var position = value == 0 ? -1 : value;
if (position < 0)
{
position = 17;
}
return position;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 945f727e6eb43c81ae49f4e92e3d98c2
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,372 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using System.Runtime.CompilerServices;
namespace Burst.Compiler.IL.Tests
{
internal class ControlFlowsTryCatchFinally
{
[TestCompiler(-10)]
[TestCompiler(0)]
[TestCompiler(10)]
public static int TryFinallySimple(int i)
{
try
{
if (i == 0) // case 0
{
return 1;
}
else if (i > 0) // case 10
{
i = i * 2;
}
else
{
i = i * 3; // case -10
}
}
finally
{
i = i + 1;
}
return i; // both case 10 and -10
}
static void Oof()
{
}
[TestCompiler]
public static void TryFinallyFirstBlock()
{
try
{
}
finally
{
Oof();
}
}
static int MagicA(int b, int f, int h, CustomBuffer s)
{
return b+s.Hash()+f-h;
}
static bool MagicB(int c,out int t)
{
t = 0;
if (c>10)
{
t = c;
return true;
}
return false;
}
// This test catches an issue with the de-stackifier. (see ILBuilder.cs:1254 (flushStack))
// Needs to be unoptimised to trigger
[TestCompiler(0)]
[TestCompiler(99)]
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
public static int TryUnbalancedFinally(int i)
{
// this if is required to force the destackifier to process the final block, before processing the block the contains the endfinally
if (i == 99)
{
return default;
}
int resultB = i;
using var buffer = new CustomBuffer(32);
return resultB + MagicA(i,
MagicB(i*2, out var r) ? r : default,
MagicB(i, out var t) ? t : default,
buffer);
}
[TestCompiler(-3)]
[TestCompiler(0)]
[TestCompiler(3)]
public static int TryFinallyComplex1(int i)
{
try
{
try
{
if (i == 0)
{
return i - 1;
}
i += 3;
}
finally
{
if (i == 0) // case i: -3
{
i = 1;
}
else
{
i = i * 10; // case i: 3
}
}
}
finally
{
i = i * 2; // both -3 and 3
}
return i + 1;
}
[TestCompiler(-10)]
[TestCompiler(0)] // case 0
[TestCompiler(10)]
public static int TryFinallyComplex2(int i)
{
// First block of nested try/catch
try
{
try
{
if (i == 0) // case 0
{
return i - 1;
}
i = i * 2;
}
finally
{
i++;
}
}
finally
{
i = i * 3;
}
// Second block of nested try/catch
try
{
i = i - 2;
try
{
if (i < 0) // case -10
{
return i * 5;
}
i += 3; // case 10
}
finally
{
i += 11;
}
}
finally
{
i = i * 3;
}
return i + 1; // case 10
}
[TestCompiler(0)]
[TestCompiler(1)]
[TestCompiler(10)]
[TestCompiler(20)]
public static int TryFinallyComplex3(int x)
{
bool k = true;
int num = 0;
try
{
while (k)
{
if (x < 10)
{
num |= 2;
try
{
if (x == 1) return num;
}
finally
{
k = false;
}
continue;
}
num |= 1;
try
{
if (x == 20) return num;
}
finally
{
k = false;
}
}
}
finally
{
num |= 4;
}
return num;
}
[TestCompiler]
public static int TryUsingDispose()
{
using (var buffer = new CustomBuffer(32))
{
return buffer.Hash();
}
}
[TestCompiler]
public static int ForEachTryFinally()
{
int hashCode = 0;
foreach (var value in new RangeEnumerable(1, 100))
{
hashCode = (hashCode * 397) ^ value;
}
return hashCode;
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_CatchConstructionNotSupported)]
public static int TryCatch()
{
try
{
return default(int);
}
catch (InvalidOperationException)
{
return 1;
}
}
private unsafe struct CustomBuffer : IDisposable
{
private readonly int _size;
private byte* _buffer;
public CustomBuffer(int size)
{
_size = size;
_buffer = (byte*)UnsafeUtility.Malloc(size, 4, Allocator.Persistent);
for (int i = 0; i < size; i++)
{
_buffer[i] = (byte)(i + 1);
}
}
public int Hash()
{
int hashCode = _size;
for (int i = 0; i < _size; i++)
{
hashCode = (hashCode * 397) ^ (byte)_buffer[i];
}
return hashCode;
}
public unsafe void Dispose()
{
if (_buffer != null)
{
UnsafeUtility.Free(_buffer, Allocator.Persistent);
_buffer = (byte*) 0;
}
}
}
private struct RangeEnumerable : IEnumerable<int>
{
private readonly int _from;
private readonly int _to;
public RangeEnumerable(int from, int to)
{
_from = @from;
_to = to;
}
public Enumerator GetEnumerator()
{
return new Enumerator();
}
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public struct Enumerator : IEnumerator<int>
{
private readonly int _from;
private readonly int _to;
public Enumerator(int from, int to)
{
_from = @from;
_to = to;
Current = -1;
}
public void Dispose()
{
// nothing to do
}
public bool MoveNext()
{
if (Current < 0)
{
Current = _from;
return true;
}
int nextIndex = Current + 1;
if (nextIndex >= _from && nextIndex <= _to)
{
Current = nextIndex;
return true;
}
return false;
}
public void Reset()
{
}
public int Current { get; private set; }
object IEnumerator.Current => Current;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 701a30a4d0f73d51a92f908b568cea9d
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 06cc7660b5c739eca022daad2ed2e0a4
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,731 @@
// -----------------------------------------------------------
// This file was generated automatically from 050-TestStructsLayout.cs
// DO NOT EDIT THIS FILE MANUALLY
// -----------------------------------------------------------
using Unity.Collections.LowLevel.Unsafe;
namespace Burst.Compiler.IL.Tests
{
partial class TestStructsLayout
{
[TestCompiler]
public static int Test_CheckHoleInner_Size()
{
return UnsafeUtility.SizeOf<CheckHoleInner>();
}
[TestCompiler]
public static unsafe int Test_CheckHoleInner_FieldOffset_m_Ptr()
{
var value = new CheckHoleInner();
var addressStart = &value;
var addressField = &value.m_Ptr;
return (int)((byte*)addressField - (byte*)addressStart);
}
// Commented out until upstream IL2CPP bug is fixed
#if BURST_TESTS_ONLY
[TestCompiler(OverrideOn32BitNative = 20)]
public static int Test_CheckHoleOuter_Size()
{
return UnsafeUtility.SizeOf<CheckHoleOuter>();
}
#endif
[TestCompiler]
public static unsafe int Test_CheckHoleOuter_FieldOffset_a()
{
var value = new CheckHoleOuter();
var addressStart = &value;
var addressField = &value.a;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_CheckHoleOuter_FieldOffset_b()
{
var value = new CheckHoleOuter();
var addressStart = &value;
var addressField = &value.b;
return (int)((byte*)addressField - (byte*)addressStart);
}
// Commented out until upstream IL2CPP bug is fixed
#if BURST_TESTS_ONLY
[TestCompiler(OverrideOn32BitNative = 12)]
public static unsafe int Test_CheckHoleOuter_FieldOffset_c()
{
var value = new CheckHoleOuter();
var addressStart = &value;
var addressField = &value.c;
return (int)((byte*)addressField - (byte*)addressStart);
}
#endif
[TestCompiler]
public static int Test_ExplicitStructWithoutSize2_Size()
{
return UnsafeUtility.SizeOf<ExplicitStructWithoutSize2>();
}
[TestCompiler]
public static unsafe int Test_ExplicitStructWithoutSize2_FieldOffset_a()
{
var value = new ExplicitStructWithoutSize2();
var addressStart = &value;
var addressField = &value.a;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_ExplicitStructWithoutSize2_FieldOffset_b()
{
var value = new ExplicitStructWithoutSize2();
var addressStart = &value;
var addressField = &value.b;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_ExplicitStructWithoutSize2_FieldOffset_c()
{
var value = new ExplicitStructWithoutSize2();
var addressStart = &value;
var addressField = &value.c;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_ExplicitStructWithoutSize_Size()
{
return UnsafeUtility.SizeOf<ExplicitStructWithoutSize>();
}
[TestCompiler]
public static unsafe int Test_ExplicitStructWithoutSize_FieldOffset_a()
{
var value = new ExplicitStructWithoutSize();
var addressStart = &value;
var addressField = &value.a;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_ExplicitStructWithoutSize_FieldOffset_b()
{
var value = new ExplicitStructWithoutSize();
var addressStart = &value;
var addressField = &value.b;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_ExplicitStructWithoutSize_FieldOffset_c()
{
var value = new ExplicitStructWithoutSize();
var addressStart = &value;
var addressField = &value.c;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_SequentialStructWithSize3_Size()
{
return UnsafeUtility.SizeOf<SequentialStructWithSize3>();
}
[TestCompiler]
public static unsafe int Test_SequentialStructWithSize3_FieldOffset_a()
{
var value = new SequentialStructWithSize3();
var addressStart = &value;
var addressField = &value.a;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_SequentialStructWithSize3_FieldOffset_b()
{
var value = new SequentialStructWithSize3();
var addressStart = &value;
var addressField = &value.b;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_SequentialStructWithSize3_FieldOffset_c()
{
var value = new SequentialStructWithSize3();
var addressStart = &value;
var addressField = &value.c;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_SequentialStructWithoutSize_Size()
{
return UnsafeUtility.SizeOf<SequentialStructWithoutSize>();
}
[TestCompiler]
public static unsafe int Test_SequentialStructWithoutSize_FieldOffset_a()
{
var value = new SequentialStructWithoutSize();
var addressStart = &value;
var addressField = &value.a;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_SequentialStructWithoutSize_FieldOffset_b()
{
var value = new SequentialStructWithoutSize();
var addressStart = &value;
var addressField = &value.b;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_SequentialStructWithoutSize_FieldOffset_c()
{
var value = new SequentialStructWithoutSize();
var addressStart = &value;
var addressField = &value.c;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_SequentialStructEmptyNoAttributes_Size()
{
return UnsafeUtility.SizeOf<SequentialStructEmptyNoAttributes>();
}
[TestCompiler]
public static int Test_ExplicitStructWithEmptySequentialFields_Size()
{
return UnsafeUtility.SizeOf<ExplicitStructWithEmptySequentialFields>();
}
[TestCompiler]
public static unsafe int Test_ExplicitStructWithEmptySequentialFields_FieldOffset_FieldA()
{
var value = new ExplicitStructWithEmptySequentialFields();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_ExplicitStructWithEmptySequentialFields_FieldOffset_FieldB()
{
var value = new ExplicitStructWithEmptySequentialFields();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_ExplicitStrictWithEmptyAndNonEmptySequentialFields_Size()
{
return UnsafeUtility.SizeOf<ExplicitStrictWithEmptyAndNonEmptySequentialFields>();
}
[TestCompiler]
public static unsafe int Test_ExplicitStrictWithEmptyAndNonEmptySequentialFields_FieldOffset_FieldA()
{
var value = new ExplicitStrictWithEmptyAndNonEmptySequentialFields();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_ExplicitStrictWithEmptyAndNonEmptySequentialFields_FieldOffset_FieldB()
{
var value = new ExplicitStrictWithEmptyAndNonEmptySequentialFields();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructWithPack8_Size()
{
return UnsafeUtility.SizeOf<StructWithPack8>();
}
[TestCompiler]
public static unsafe int Test_StructWithPack8_FieldOffset_FieldA()
{
var value = new StructWithPack8();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructWithPack8_FieldOffset_FieldB()
{
var value = new StructWithPack8();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructPack2WithBytesAndInt_Size()
{
return UnsafeUtility.SizeOf<StructPack2WithBytesAndInt>();
}
[TestCompiler]
public static unsafe int Test_StructPack2WithBytesAndInt_FieldOffset_FieldA()
{
var value = new StructPack2WithBytesAndInt();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructPack2WithBytesAndInt_FieldOffset_FieldB()
{
var value = new StructPack2WithBytesAndInt();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructPack2WithBytesAndInt_FieldOffset_FieldC()
{
var value = new StructPack2WithBytesAndInt();
var addressStart = &value;
var addressField = &value.FieldC;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructPack2WithBytesAndInts_Size()
{
return UnsafeUtility.SizeOf<StructPack2WithBytesAndInts>();
}
[TestCompiler]
public static unsafe int Test_StructPack2WithBytesAndInts_FieldOffset_FieldA()
{
var value = new StructPack2WithBytesAndInts();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructPack2WithBytesAndInts_FieldOffset_FieldB()
{
var value = new StructPack2WithBytesAndInts();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructPack2WithBytesAndInts_FieldOffset_FieldC()
{
var value = new StructPack2WithBytesAndInts();
var addressStart = &value;
var addressField = &value.FieldC;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructPack2WithBytesAndInts_FieldOffset_FieldD()
{
var value = new StructPack2WithBytesAndInts();
var addressStart = &value;
var addressField = &value.FieldD;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructPack1WithBytesAndInt_Size()
{
return UnsafeUtility.SizeOf<StructPack1WithBytesAndInt>();
}
[TestCompiler]
public static unsafe int Test_StructPack1WithBytesAndInt_FieldOffset_FieldA()
{
var value = new StructPack1WithBytesAndInt();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructPack1WithBytesAndInt_FieldOffset_FieldB()
{
var value = new StructPack1WithBytesAndInt();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructPack1WithBytesAndInt_FieldOffset_FieldC()
{
var value = new StructPack1WithBytesAndInt();
var addressStart = &value;
var addressField = &value.FieldC;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructPack1WithByteAndInt_Size()
{
return UnsafeUtility.SizeOf<StructPack1WithByteAndInt>();
}
[TestCompiler]
public static unsafe int Test_StructPack1WithByteAndInt_FieldOffset_FieldA()
{
var value = new StructPack1WithByteAndInt();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructPack1WithByteAndInt_FieldOffset_FieldB()
{
var value = new StructPack1WithByteAndInt();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructPack1WithByteAndIntWrapper_Size()
{
return UnsafeUtility.SizeOf<StructPack1WithByteAndIntWrapper>();
}
[TestCompiler]
public static unsafe int Test_StructPack1WithByteAndIntWrapper_FieldOffset_FieldA()
{
var value = new StructPack1WithByteAndIntWrapper();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructPack1WithByteAndIntWrapper_FieldOffset_FieldB()
{
var value = new StructPack1WithByteAndIntWrapper();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructPack1WithByteAndIntWrapper2_Size()
{
return UnsafeUtility.SizeOf<StructPack1WithByteAndIntWrapper2>();
}
[TestCompiler]
public static unsafe int Test_StructPack1WithByteAndIntWrapper2_FieldOffset_FieldA()
{
var value = new StructPack1WithByteAndIntWrapper2();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructPack1WithByteAndIntWrapper2_FieldOffset_FieldB()
{
var value = new StructPack1WithByteAndIntWrapper2();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructWithSizeAndPack_Size()
{
return UnsafeUtility.SizeOf<StructWithSizeAndPack>();
}
[TestCompiler]
public static unsafe int Test_StructWithSizeAndPack_FieldOffset_FieldA()
{
var value = new StructWithSizeAndPack();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructWithSizeAndPack_FieldOffset_FieldB()
{
var value = new StructWithSizeAndPack();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructWithSizeAndPackWrapper_Size()
{
return UnsafeUtility.SizeOf<StructWithSizeAndPackWrapper>();
}
[TestCompiler]
public static unsafe int Test_StructWithSizeAndPackWrapper_FieldOffset_FieldA()
{
var value = new StructWithSizeAndPackWrapper();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructWithSizeAndPackWrapper_FieldOffset_FieldB()
{
var value = new StructWithSizeAndPackWrapper();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructWithSizeAndPack4_Size()
{
return UnsafeUtility.SizeOf<StructWithSizeAndPack4>();
}
[TestCompiler]
public static unsafe int Test_StructWithSizeAndPack4_FieldOffset_FieldA()
{
var value = new StructWithSizeAndPack4();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructWithSizeAndPack4_FieldOffset_FieldB()
{
var value = new StructWithSizeAndPack4();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
// Commented out until upstream IL2CPP bug is fixed
#if BURST_TESTS_ONLY
[TestCompiler]
public static int Test_StructWithSizeAndPack4Wrapper_Size()
{
return UnsafeUtility.SizeOf<StructWithSizeAndPack4Wrapper>();
}
#endif
[TestCompiler]
public static unsafe int Test_StructWithSizeAndPack4Wrapper_FieldOffset_FieldA()
{
var value = new StructWithSizeAndPack4Wrapper();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
// Commented out until upstream IL2CPP bug is fixed
#if BURST_TESTS_ONLY
[TestCompiler]
public static unsafe int Test_StructWithSizeAndPack4Wrapper_FieldOffset_FieldB()
{
var value = new StructWithSizeAndPack4Wrapper();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
#endif
[TestCompiler]
public static int Test_StructExplicitPack1WithByteAndInt_Size()
{
return UnsafeUtility.SizeOf<StructExplicitPack1WithByteAndInt>();
}
[TestCompiler]
public static unsafe int Test_StructExplicitPack1WithByteAndInt_FieldOffset_FieldA()
{
var value = new StructExplicitPack1WithByteAndInt();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructExplicitPack1WithByteAndInt_FieldOffset_FieldB()
{
var value = new StructExplicitPack1WithByteAndInt();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructExplicitPack1WithByteAndIntWrapper_Size()
{
return UnsafeUtility.SizeOf<StructExplicitPack1WithByteAndIntWrapper>();
}
[TestCompiler]
public static unsafe int Test_StructExplicitPack1WithByteAndIntWrapper_FieldOffset_FieldA()
{
var value = new StructExplicitPack1WithByteAndIntWrapper();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructExplicitPack1WithByteAndIntWrapper_FieldOffset_FieldB()
{
var value = new StructExplicitPack1WithByteAndIntWrapper();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructExplicitPack1WithByteAndIntWrapper2_Size()
{
return UnsafeUtility.SizeOf<StructExplicitPack1WithByteAndIntWrapper2>();
}
[TestCompiler]
public static unsafe int Test_StructExplicitPack1WithByteAndIntWrapper2_FieldOffset_FieldA()
{
var value = new StructExplicitPack1WithByteAndIntWrapper2();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructExplicitPack1WithByteAndIntWrapper2_FieldOffset_FieldB()
{
var value = new StructExplicitPack1WithByteAndIntWrapper2();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructExplicitWithSizeAndPack_Size()
{
return UnsafeUtility.SizeOf<StructExplicitWithSizeAndPack>();
}
[TestCompiler]
public static unsafe int Test_StructExplicitWithSizeAndPack_FieldOffset_FieldA()
{
var value = new StructExplicitWithSizeAndPack();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructExplicitWithSizeAndPack_FieldOffset_FieldB()
{
var value = new StructExplicitWithSizeAndPack();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructExplicitWithSizeAndPackWrapper_Size()
{
return UnsafeUtility.SizeOf<StructExplicitWithSizeAndPackWrapper>();
}
[TestCompiler]
public static unsafe int Test_StructExplicitWithSizeAndPackWrapper_FieldOffset_FieldA()
{
var value = new StructExplicitWithSizeAndPackWrapper();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructExplicitWithSizeAndPackWrapper_FieldOffset_FieldB()
{
var value = new StructExplicitWithSizeAndPackWrapper();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static int Test_StructExplicitWithSizeAndPack4_Size()
{
return UnsafeUtility.SizeOf<StructExplicitWithSizeAndPack4>();
}
[TestCompiler]
public static unsafe int Test_StructExplicitWithSizeAndPack4_FieldOffset_FieldA()
{
var value = new StructExplicitWithSizeAndPack4();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
[TestCompiler]
public static unsafe int Test_StructExplicitWithSizeAndPack4_FieldOffset_FieldB()
{
var value = new StructExplicitWithSizeAndPack4();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
// Commented out until upstream IL2CPP bug is fixed
#if BURST_TESTS_ONLY
[TestCompiler]
public static int Test_StructExplicitWithSizeAndPack4Wrapper_Size()
{
return UnsafeUtility.SizeOf<StructExplicitWithSizeAndPack4Wrapper>();
}
#endif
[TestCompiler]
public static unsafe int Test_StructExplicitWithSizeAndPack4Wrapper_FieldOffset_FieldA()
{
var value = new StructExplicitWithSizeAndPack4Wrapper();
var addressStart = &value;
var addressField = &value.FieldA;
return (int)((byte*)addressField - (byte*)addressStart);
}
// Commented out until upstream IL2CPP bug is fixed
#if BURST_TESTS_ONLY
[TestCompiler]
public static unsafe int Test_StructExplicitWithSizeAndPack4Wrapper_FieldOffset_FieldB()
{
var value = new StructExplicitWithSizeAndPack4Wrapper();
var addressStart = &value;
var addressField = &value.FieldB;
return (int)((byte*)addressField - (byte*)addressStart);
}
#endif
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 10c2b0100e723deab40f35dc43e40cd5
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,248 @@
// NOTE: Please read this before adding or changing anything in this file.
//
// This file doesn't contain any actual tests. It only contains structs.
// Tests are automatically generated from all structs in this file,
// which test:
// - the size of the struct
// - the offsets of each field
//
// When a struct contains a pointer, the test needs to use
// OverrideOn32BitNative so that wasm tests can compare with the correct
// values when testing 32-bit wasm on a 64-bit host platform.
// While it would be possible to use Roslyn to calculate these
// values automatically, for simplicity we use a couple of
// generator-specific attributes to set these manually:
// - [TestGeneratorOverride32BitSize(20)] should be set on a struct
// - [TestGeneratorOverride32BitOffset(12)] should be set on a field
// See the file below for examples.
//
// The test generation code lives in Burst.Compiler.IL.Tests.CodeGen.
// After making changes to this file, please run that project.
//
// The generated tests are in 050-TestStructsLayout.Generated.cs.
using System;
using System.Runtime.InteropServices;
namespace Burst.Compiler.IL.Tests
{
partial class TestStructsLayout
{
[StructLayout(LayoutKind.Explicit, Size = 8)]
private unsafe struct CheckHoleInner
{
[FieldOffset(0)]
public byte* m_Ptr;
}
[TestGeneratorOverride32BitSize(20)]
private struct CheckHoleOuter
{
public CheckHoleInner a;
public int b;
[TestGeneratorOverride32BitOffset(12)]
public CheckHoleInner c;
}
[StructLayout(LayoutKind.Explicit)]
private struct ExplicitStructWithoutSize2
{
[FieldOffset(0)] public long a;
[FieldOffset(8)] public sbyte b;
[FieldOffset(9)] public int c;
}
[StructLayout(LayoutKind.Explicit)]
private struct ExplicitStructWithoutSize
{
[FieldOffset(0)] public int a;
[FieldOffset(4)] public sbyte b;
[FieldOffset(5)] public int c;
}
[StructLayout(LayoutKind.Sequential, Size = 12)]
private struct SequentialStructWithSize3
{
public int a;
public int b;
public sbyte c;
}
[StructLayout(LayoutKind.Sequential)]
private struct SequentialStructWithoutSize
{
public int a;
public int b;
public sbyte c;
}
private struct SequentialStructEmptyNoAttributes { }
[StructLayout(LayoutKind.Explicit)]
private struct ExplicitStructWithEmptySequentialFields
{
[FieldOffset(0)] public SequentialStructEmptyNoAttributes FieldA;
[FieldOffset(0)] public SequentialStructEmptyNoAttributes FieldB;
}
[StructLayout(LayoutKind.Explicit)]
private struct ExplicitStrictWithEmptyAndNonEmptySequentialFields
{
[FieldOffset(0)] public SequentialStructEmptyNoAttributes FieldA;
[FieldOffset(0)] public SequentialStructWithoutSize FieldB;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
private struct StructWithPack8
{
public int FieldA;
public int FieldB;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
private struct StructPack2WithBytesAndInt
{
public byte FieldA;
public byte FieldB;
public int FieldC;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
private struct StructPack2WithBytesAndInts
{
public byte FieldA;
public byte FieldB;
public int FieldC;
public int FieldD;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct StructPack1WithBytesAndInt
{
public byte FieldA;
public byte FieldB;
public int FieldC;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct StructPack1WithByteAndInt
{
public byte FieldA;
public int FieldB;
}
private struct StructPack1WithByteAndIntWrapper
{
public StructPack1WithByteAndInt FieldA;
public StructPack1WithByteAndInt FieldB;
}
private struct StructPack1WithByteAndIntWrapper2
{
public StructPack1WithByteAndIntWrapper FieldA;
public StructPack1WithByteAndIntWrapper FieldB;
}
[StructLayout(LayoutKind.Sequential, Size = 12, Pack = 1)]
private struct StructWithSizeAndPack
{
public double FieldA;
public int FieldB;
}
private struct StructWithSizeAndPackWrapper
{
public byte FieldA;
public StructWithSizeAndPack FieldB;
}
[StructLayout(LayoutKind.Explicit, Size = 12, Pack = 4)]
private struct StructWithSizeAndPack4
{
[FieldOffset(0)]
public double FieldA;
[FieldOffset(8)]
public int FieldB;
}
private struct StructWithSizeAndPack4Wrapper
{
public byte FieldA;
public StructWithSizeAndPack4 FieldB;
}
[StructLayout(LayoutKind.Explicit, Pack = 1)]
private struct StructExplicitPack1WithByteAndInt
{
[FieldOffset(0)]
public byte FieldA;
[FieldOffset(1)]
public int FieldB;
}
private struct StructExplicitPack1WithByteAndIntWrapper
{
public StructExplicitPack1WithByteAndInt FieldA;
public StructExplicitPack1WithByteAndInt FieldB;
}
private struct StructExplicitPack1WithByteAndIntWrapper2
{
public StructExplicitPack1WithByteAndIntWrapper FieldA;
public StructExplicitPack1WithByteAndIntWrapper FieldB;
}
[StructLayout(LayoutKind.Explicit, Size = 12, Pack = 1)]
private struct StructExplicitWithSizeAndPack
{
[FieldOffset(0)]
public double FieldA;
[FieldOffset(8)]
public int FieldB;
}
private struct StructExplicitWithSizeAndPackWrapper
{
public byte FieldA;
public StructExplicitWithSizeAndPack FieldB;
}
[StructLayout(LayoutKind.Explicit, Size = 12, Pack = 4)]
private struct StructExplicitWithSizeAndPack4
{
[FieldOffset(0)]
public double FieldA;
[FieldOffset(8)]
public int FieldB;
}
private struct StructExplicitWithSizeAndPack4Wrapper
{
public byte FieldA;
public StructExplicitWithSizeAndPack4 FieldB;
}
}
[AttributeUsage(AttributeTargets.Struct)]
internal sealed class TestGeneratorOverride32BitSizeAttribute : Attribute
{
public readonly int Size;
public TestGeneratorOverride32BitSizeAttribute(int size)
{
Size = size;
}
}
[AttributeUsage(AttributeTargets.Field)]
internal sealed class TestGeneratorOverride32BitOffsetAttribute : Attribute
{
public readonly int Offset;
public TestGeneratorOverride32BitOffsetAttribute(int offset)
{
Offset = offset;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 828266174e573a6da71055ba8f017778
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5eb3e1cf0e2a3614927c245069c69baf
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,183 @@
using UnityBenchShared;
namespace Burst.Compiler.IL.Tests
{
internal class TestFixed
{
public unsafe struct SomeStruct
{
public static readonly int[] Ints = new int[4] { 1, 2, 3, 4 };
public struct OtherStruct
{
public int x;
}
public static readonly OtherStruct[] Structs = new OtherStruct[2] { new OtherStruct { x = 42 }, new OtherStruct { x = 13 } };
public fixed ushort array[42];
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
var s = new SomeStruct();
for (ushort i = 0; i < 42; i++)
{
s.array[i] = i;
}
return s;
}
}
}
}
[TestCompiler]
public static unsafe int ReadInts()
{
fixed (int* ptr = SomeStruct.Ints)
{
return ptr[2];
}
}
[TestCompiler]
public static unsafe int ReadIntsElement()
{
fixed (int* ptr = &SomeStruct.Ints[1])
{
return ptr[0];
}
}
[TestCompiler]
public static unsafe int ReadStructs()
{
fixed (SomeStruct.OtherStruct* ptr = SomeStruct.Structs)
{
return ptr[1].x;
}
}
[TestCompiler]
public static unsafe int ReadStructsElement()
{
fixed (SomeStruct.OtherStruct* ptr = &SomeStruct.Structs[1])
{
return ptr[0].x;
}
}
[TestCompiler(typeof(SomeStruct.Provider))]
public static unsafe ushort ReadFromFixedArray(ref SomeStruct s)
{
fixed (ushort* ptr = s.array)
{
ushort total = 0;
for (ushort i = 0; i < 42; i++)
{
total += ptr[i];
}
return total;
}
}
// The below tests are designed to verify the indexer is treated correctly for various fixed arrays (only the smallest case)
//(the bug was actually to do with pointer addition, so see 031-Pointer.cs for additional coverage)
//Its not perfect as if the indexer is treated as signed, then in burst we will read off the beginning of the array
//which might be into another array or off the beginning of the struct... and the value might accidently be correct.
public unsafe struct IndexerStructTestSByte
{
public fixed sbyte sbyteArray[256];
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
var s = new IndexerStructTestSByte();
for (int a=0;a<256;a++)
{
s.sbyteArray[a] = sbyte.MinValue;
}
s.sbyteArray[127] = 127;
s.sbyteArray[128] = 63;
s.sbyteArray[255] = 23;
return s;
}
}
}
}
public unsafe struct IndexerStructTestByte
{
public fixed byte byteArray[256];
public struct Provider : IArgumentProvider
{
public object Value
{
get
{
var s = new IndexerStructTestByte();
for (int a=0;a<256;a++)
{
s.byteArray[a] = byte.MinValue;
}
s.byteArray[127] = 129;
s.byteArray[128] = 212;
s.byteArray[255] = 165;
return s;
}
}
}
}
// SByte array with different indexer types
[TestCompiler(typeof(IndexerStructTestSByte.Provider),(byte)0)]
[TestCompiler(typeof(IndexerStructTestSByte.Provider),(byte)128)]
[TestCompiler(typeof(IndexerStructTestSByte.Provider),(byte)255)]
public static unsafe sbyte IndexerReadFromSByteArrayWithByteOffset(ref IndexerStructTestSByte s, byte offset)
{
return s.sbyteArray[offset];
}
[TestCompiler(typeof(IndexerStructTestSByte.Provider),(sbyte)0)]
[TestCompiler(typeof(IndexerStructTestSByte.Provider),(sbyte)127)] // signed offset so limited
public static unsafe sbyte IndexerReadFromSByteArrayWithSByteOffset(ref IndexerStructTestSByte s, sbyte offset)
{
return s.sbyteArray[offset];
}
// Byte array with different indexer types
[TestCompiler(typeof(IndexerStructTestByte.Provider),(byte)0)]
[TestCompiler(typeof(IndexerStructTestByte.Provider),(byte)128)]
[TestCompiler(typeof(IndexerStructTestByte.Provider),(byte)255)]
public static unsafe byte IndexerReadFromByteArrayWithByteOffset(ref IndexerStructTestByte s, byte offset)
{
return s.byteArray[offset];
}
[TestCompiler(typeof(IndexerStructTestByte.Provider),(sbyte)0)]
[TestCompiler(typeof(IndexerStructTestByte.Provider),(sbyte)127)] // signed offset so limited
public static unsafe byte IndexerReadFromByteArrayWithSByteOffset(ref IndexerStructTestByte s, sbyte offset)
{
return s.byteArray[offset];
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 36990957b5d73a9681ce7dd9f4d5a7b0
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,313 @@
using NUnit.Framework;
using Unity.Burst;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
internal class TestConstArrays
{
[TestCompiler]
public static int ReadFromIntArray()
{
return StructWithConstArray1.IntValues[1];
}
[TestCompiler]
public static unsafe int ReadViaFixed()
{
fixed (int* ptr = StructWithConstArray1.IntValues)
{
return ptr[2];
}
}
[TestCompiler]
public static int ReadFromColorArray()
{
var color = StructWithConstArrayWithStruct1.Colors[1];
return ((color.R * 255) + color.G) * 255 + color.B;
}
[TestCompiler]
public static int ReadFromColorArray2()
{
var color = StaticArrayStruct.Colors[1];
return ((color.R * 255) + color.G) * 255 + color.B;
}
struct StructWithConstArray1
{
public static readonly int[] IntValues = new int[4] { 1, 2, 3, 4 };
}
struct StructWithConstArrayWithStruct1
{
public static readonly Color[] Colors = { new Color(), new Color(1, 2, 3, 255) };
}
private struct Color
{
public Color(byte r, byte g, byte b, byte a)
{
R = r;
G = g;
B = b;
A = a;
}
public byte R, G, B, A;
}
private struct StaticArrayStruct
{
public static readonly double[] Doubles = { 3, 6, 9, 42, 43 };
public static readonly byte[] Bytes = { 1, 2, 3 };
public static readonly ushort[] UShorts = { 2, 6, 8, 2, 0 };
public static readonly int[] Ints = { -6, 6, 50 };
public static readonly int[] ZeroData = { 0, 0, 0, 0 };
public static readonly int[] ZeroLength = { };
public static readonly Color[] ZeroLengthStruct = { };
public static readonly Color[] Colors = { new Color(), new Color(1, 2, 3, 255) };
public static readonly int3[] Positions = { new int3(0, 0, 1), new int3(0, 1, 0), new int3(1, 0, 0) };
}
[TestCompiler]
public static int TestStaticReadonlyArrayLength()
{
return StaticArrayStruct.Doubles.Length + StaticArrayStruct.Bytes.Length +
StaticArrayStruct.UShorts.Length + StaticArrayStruct.Ints.Length +
StaticArrayStruct.ZeroData.Length + StaticArrayStruct.ZeroLength.Length +
StaticArrayStruct.ZeroLengthStruct.Length + StaticArrayStruct.Colors.Length +
StaticArrayStruct.Positions.Length;
}
private struct StructP
{
public static readonly int[] Value = new int[One()];
public static int One()
{
return 1;
}
}
[TestCompiler]
public static int TestStaticReadonlyArrayNonConstantLength()
{
return StructP.Value.Length;
}
private struct StructQ
{
public static readonly int[] Value = new int[10];
public static int One()
{
return 1;
}
static StructQ()
{
Value[One()] = 1;
}
}
[TestCompiler]
public static int TestStaticReadonlyArrayWithNonConstantStelemIndex()
{
return StructQ.Value[1];
}
private struct StructR
{
#pragma warning disable 0649
public static int[] Value;
#pragma warning restore 0649
static StructR()
{
Value[0] = 1;
}
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_LoadingFromManagedNonReadonlyStaticFieldNotSupported)]
public static int TestStaticReadonlyArrayExplicitConstructionOfUninitialized()
{
return StructR.Value.Length;
}
private struct StructS
{
public static readonly int[] Value = new int[10];
static StructS()
{
Value[0] = 1;
Value[1] = 2;
Value[2] = 8;
Value[3] = 2;
Value[4] = 0;
Value[5] = 2;
Value[6] = 1;
Value[7] = 2;
Value[8] = 2;
Value[9] = 3;
}
}
[TestCompiler]
public static int TestStaticReadonlyArrayExplicitConstruction()
{
int sum = 0;
for (int i = 0; i < 10; i++) sum += StructS.Value[i];
return sum;
}
[TestCompiler]
public static int TestStaticReadonlyArrayLdelem()
{
var doubles = StaticArrayStruct.Doubles[0];
for (int i = 1; i < StaticArrayStruct.Doubles.Length; i++) doubles += StaticArrayStruct.Doubles[i];
var bytes = StaticArrayStruct.Bytes[0];
for (int i = 1; i < StaticArrayStruct.Bytes.Length; i++) bytes += StaticArrayStruct.Bytes[i];
var ushorts = StaticArrayStruct.UShorts[0];
for (int i = 1; i < StaticArrayStruct.UShorts.Length; i++) ushorts += StaticArrayStruct.UShorts[i];
var ints = StaticArrayStruct.Ints[0];
for (int i = 1; i < StaticArrayStruct.Ints.Length; i++) ints += StaticArrayStruct.Ints[i];
ints += StaticArrayStruct.ZeroData[0];
for (int i = 1; i < StaticArrayStruct.ZeroData.Length; i++) ints += StaticArrayStruct.ZeroData[i];
for (int i = 0; i < StaticArrayStruct.ZeroLength.Length; i++) doubles += StaticArrayStruct.ZeroLength[i];
bytes = (byte)(StaticArrayStruct.Colors[0].R + StaticArrayStruct.Colors[0].G
+ StaticArrayStruct.Colors[0].B
+ StaticArrayStruct.Colors[0].A);
for (int i = 1; i < StaticArrayStruct.Colors.Length; i++)
bytes += (byte)(StaticArrayStruct.Colors[i].R + StaticArrayStruct.Colors[i].G
+ StaticArrayStruct.Colors[i].B
+ StaticArrayStruct.Colors[i].A);
for (int i = 1; i < StaticArrayStruct.Positions.Length; i++)
ints += math.dot(StaticArrayStruct.Positions[i - 1], StaticArrayStruct.Positions[i]);
return (int)doubles + bytes + ushorts + ints;
}
private static T TakesRef<T>(ref T x)
{
return x;
}
[TestCompiler]
public static int TestStaticReadonlyArrayWithElementRef()
{
return TakesRef(ref StaticArrayStruct.Ints[1]);
}
[TestCompiler]
public static int TestStaticReadonlyArrayWithElementVectorRef()
{
var x = TakesRef(ref StaticArrayStruct.Positions[1]);
return math.dot(x, x);
}
[TestCompiler(1)]
[TestCompiler(2)]
[TestCompiler(3)]
[TestCompiler(4)]
public static int TestStaticReadonlyArrayWithDynamicLdelem(int count)
{
int sum = 0;
for (int i = 0; i < count; i++)
{
sum += (int)StaticArrayStruct.Doubles[i];
}
return sum;
}
public struct ContainerStruct
{
public SmallStruct A;
public SmallStruct B;
public static readonly ContainerStruct[] CoolStructs =
{
new ContainerStruct
{
A = new SmallStruct { a = 3, b = 5 },
B = new SmallStruct { a = 9, b = 10 }
},
new ContainerStruct
{
A = new SmallStruct { a = 1, b = 5 },
B = new SmallStruct { a = 7, b = 8 }
}
};
}
[TestCompiler]
public static int TestStaticReadonlyArrayOfStructOfStructs()
{
return ContainerStruct.CoolStructs[0].A.a + ContainerStruct.CoolStructs[0].A.b +
ContainerStruct.CoolStructs[0].B.a + ContainerStruct.CoolStructs[0].B.b +
ContainerStruct.CoolStructs[1].A.a + ContainerStruct.CoolStructs[1].A.b +
ContainerStruct.CoolStructs[1].B.a + ContainerStruct.CoolStructs[1].B.b;
}
/* There's currently no way of settings the safety checks on from here
[TestCompiler(0xFFFFFFF, ExpectedException = typeof(IndexOutOfRangeException))]
public static int TestStaticReadonlyLdelemDynamicIndexOfBounds(int x)
{
return StaticArrayStruct.Ints[x];
}
*/
public struct SmallStruct
{
public int a;
public int b;
}
public struct NullArrayHolder
{
public static readonly int[] Array = null;
}
[TestCompiler()]
public static int TestStaticReadonlyNullArray()
{
if (NullArrayHolder.Array == null)
{
return 40;
}
return 3;
}
private static readonly int[] SomeArray = { 42, 13 };
[TestCompiler(42)]
public static int StoreNullIntoLocalArray(int x)
{
int[] someArray;
if (x == 0)
{
someArray = SomeArray;
}
else
{
someArray = null;
}
return someArray?.Length ?? 0;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1b192164f6d13e9aaf88fbb6833566c4
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,201 @@
using Burst.Compiler.IL.Tests.Helpers;
using Unity.Burst.CompilerServices;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
internal class Peephole
{
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtEqualFast(float f)
{
return math.sqrt(f) == 2 ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtNotEqualFast(float f)
{
return math.sqrt(f) != 2 ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100)]
public static int SqrtLessThan(float f)
{
return math.sqrt(f) < 2 ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtLessThanFast(float f)
{
return math.sqrt(f) < 2 ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtLessThanLargeConstant(float f)
{
return math.sqrt(f) < float.MaxValue ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtLessThanFastVector(ref float4 f)
{
return math.all(math.sqrt(f) < 2) ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtLessThanLargeConstantVector(ref float4 f)
{
return math.all(math.sqrt(f) < new float4(1, 2, 3, float.MaxValue)) ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100)]
public static int SqrtGreaterThan(float f)
{
return math.sqrt(f) > 2 ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtGreaterThanFast(float f)
{
return math.sqrt(f) > 2 ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtGreaterThanLargeConstant(float f)
{
return math.sqrt(f) > float.MaxValue ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtGreaterThanFastVector(ref float4 f)
{
return math.all(math.sqrt(f) > 2) ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtGreaterThanLargeConstantVector(ref float4 f)
{
return math.all(math.sqrt(f) > new float4(1, 2, 3, float.MaxValue)) ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100)]
public static int SqrtLessThanEqual(float f)
{
return math.sqrt(f) <= 2 ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtLessThanEqualFast(float f)
{
return math.sqrt(f) <= 2 ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtLessThanEqualLargeConstant(float f)
{
return math.sqrt(f) <= float.MaxValue ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtLessThanEqualFastVector(ref float4 f)
{
return math.all(math.sqrt(f) <= 2) ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtLessThanEqualLargeConstantVector(ref float4 f)
{
return math.all(math.sqrt(f) <= new float4(1, 2, 3, float.MaxValue)) ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100)]
public static int SqrtGreaterThanEqual(float f)
{
return math.sqrt(f) >= 2 ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtGreaterThanEqualFast(float f)
{
return math.sqrt(f) >= 2 ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtGreaterThanEqualLargeConstant(float f)
{
return math.sqrt(f) >= float.MaxValue ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtGreaterThanEqualFastVector(ref float4 f)
{
return math.all(math.sqrt(f) >= 2) ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtGreaterThanEqualLargeConstantVector(ref float4 f)
{
return math.all(math.sqrt(f) >= new float4(1, 2, 3, float.MaxValue)) ? 42 : 13;
}
[TestCompiler(DataRange.ZeroExclusiveTo100, DataRange.ZeroExclusiveTo100, FastMath = true)]
public static int SqrtAndSqrtFast(ref float4 a, ref float4 b)
{
return math.all(math.sqrt(a) >= math.sqrt(b)) ? 42 : 13;
}
[TestCompiler(0)]
public static float FloatExp2FromInt(int a)
{
return math.exp2(a);
}
[TestCompiler(0)]
public static double DoubleExp2FromInt(int a)
{
return math.exp2((double)a);
}
[TestCompiler((ushort)0)]
public static float FloatExp2FromUShort(ushort a)
{
return math.exp2(a);
}
[TestCompiler((ushort)0)]
public static double DoubleExp2FromUShort(ushort a)
{
return math.exp2((double)a);
}
[TestCompiler(0)]
public static float FloatPowFromInt(int a)
{
return math.pow(2.0f, a);
}
[TestCompiler(0)]
public static double DoublePowFromInt(int a)
{
return math.pow(2.0, a);
}
[TestCompiler(0u)]
public static float FloatPowFromUInt(uint a)
{
return math.pow(2.0f, a);
}
[TestCompiler(0u)]
public static double DoublePowFromUInt(uint a)
{
return math.pow(2.0, a);
}
[TestCompiler(int.MaxValue)]
public static int AShrToLShr([AssumeRange(0, int.MaxValue)] int a)
{
return a >> 4;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1d15bef20cb43dc49f6156cde028d37a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,108 @@
namespace Burst.Compiler.IL.Tests.Shared
{
internal class TestStackalloc
{
[TestCompiler]
public static unsafe int Stackalloc1ByteWithInitializer()
{
var value = stackalloc byte[1] { 0xA4 };
return value[0];
}
[TestCompiler]
public static unsafe int Stackalloc16BytesWithInitializer()
{
// Roslyn generates quite different IL when the number of bytes is larger than 8.
var value = stackalloc byte[16] { 0xA4, 0xA1, 0x20, 0xA5, 0x80, 0x17, 0xF6, 0x4F, 0xBD, 0x18, 0x16, 0x73, 0x43, 0xC5, 0xAF, 0x16 };
return value[9];
}
[TestCompiler]
public static unsafe int Stackalloc16IntsWithInitializer()
{
var value = stackalloc int[16] { 0xA4, 0xA1, 0x20, 0xA5, 0x80, 0x17, 0xF6, 0x4F, 0xBD, 0x18, 0x16, 0x73, 0x43, 0xC5, 0xAF, 0x16 };
return value[9];
}
[TestCompiler(1)]
public static unsafe int StackallocInBranch(int takeBranch)
{
int* array = null;
if (takeBranch != 0)
{
int* elem = stackalloc int[1];
array = elem;
}
if (takeBranch != 0)
{
int* elem = stackalloc int[1];
if (array == elem)
{
return -1;
}
}
return 0;
}
[TestCompiler(4)]
public static unsafe int StackallocInLoop(int iterations)
{
int** array = stackalloc int*[iterations];
for (int i = 0; i < iterations; i++)
{
int* elem = stackalloc int[1];
array[i] = elem;
}
for (int i = 0; i < iterations; i++)
{
for (int k = i + 1; k < iterations; k++)
{
// Make sure all the stack allocations within the loop are unique addresses.
if (array[i] == array[k])
{
return -1;
}
}
}
return 0;
}
[TestCompiler]
public static unsafe int StackallocWithUnmanagedConstructedType()
{
var value = stackalloc[]
{
new Point<int> { X = 1, Y = 2 },
new Point<int> { X = 42, Y = 5 },
new Point<int> { X = 3, Y = -1 },
};
return value[1].X;
}
private struct Point<T>
{
public T X;
public T Y;
}
#if UNITY_2021_2_OR_NEWER || BURST_INTERNAL
[TestCompiler]
public static int StackallocInNestedExpression()
{
return StackallocInNestedExpressionHelper(stackalloc[] { 2, 4, 6, 8 });
}
private static int StackallocInNestedExpressionHelper(System.Span<int> span)
{
return span[2];
}
#endif
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 614354dff06f39c4b6ef0e21f5a45d23
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,151 @@
using System;
using NUnit.Framework;
using UnityBenchShared;
namespace Burst.Compiler.IL.Tests
{
/// <summary>
/// Test with enums.
/// </summary>
internal partial class TestEnums
{
[System.Flags]
public enum MyEnum
{
Hello = 5,
Something = 10
}
[TestCompiler]
public static int test_enum_cast_to_int()
{
MyEnum value = MyEnum.Hello;
return (int)value;
}
[TestCompiler(MyEnum.Hello)]
[TestCompiler(MyEnum.Something)]
public static int test_enum_compare(MyEnum value)
{
if (value == MyEnum.Hello)
return 0;
else
return 1;
}
//[TestCompiler(typeof(StructContainingEnumProvider))]
//public static int test_enum_in_struct(ref StructContainingEnum myStruct)
//{
// return myStruct.intValue + (int)myStruct.value;
//}
[TestCompiler(MyEnum.Hello)]
[TestCompiler(MyEnum.Something)]
[Ignore("Failure")]
public static int test_enum_has_flag(MyEnum value)
{
return value.HasFlag(MyEnum.Hello) ? 3 : 4;
}
[TestCompiler(MyEnum.Hello)]
[TestCompiler(MyEnum.Something)]
public static int test_enum_and_mask(MyEnum value)
{
return (value & MyEnum.Hello) != 0 ? 3 : 4;
}
[TestCompiler(1)]
[TestCompiler(2)]
public static int TestEnumSwitchCase(IntPtr value)
{
var enumValue = (SmallEnum) value.ToInt32();
// Need at least 3 cases to generate a proper switch
// otherwise Roslyn will generate an if/else
switch (enumValue)
{
case SmallEnum.One:
return 7;
case SmallEnum.Two:
return 8;
case SmallEnum.Three:
return 9;
default:
return 10;
}
}
private static int GetToInt32(int value)
{
return value;
}
[TestCompiler]
public static int test_enum_sizeof_small_enum()
{
return sizeof(SmallEnum);
}
[TestCompiler(SmallEnum.Three)]
public static int test_enum_sizeof_small_enum_in_struct_access(SmallEnum value)
{
var s = new MySmallEnumStruct
{
a = value,
b = value,
c = value
};
return (int)s.a + (int)s.b + (int)s.c;
}
public struct StructContainingEnum
{
public MyEnum value;
public int intValue;
}
public enum SmallEnum : byte
{
One,
Two,
Three
}
public struct MySmallEnumStruct
{
public SmallEnum a;
public SmallEnum b;
public SmallEnum c;
public SmallEnum d;
}
public enum SomeByteEnum : byte
{
First = 0,
Last = 255
}
public unsafe struct FixedByte4Struct
{
fixed byte bytes[4];
public SomeByteEnum this[SomeByteEnum index]
{
get { return (SomeByteEnum)bytes[(int)index]; }
}
public struct Provider : IArgumentProvider
{
public object Value => new FixedByte4Struct { };
}
}
[TestCompiler(typeof(FixedByte4Struct.Provider))]
public static SomeByteEnum test_enum_indexer(ref FixedByte4Struct bytes)
{
return bytes[0];
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7771e50c9f91376ca0db91c33bfccfda
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,173 @@
using System;
using System.Threading;
namespace Burst.Compiler.IL.Tests
{
/// <summary>
/// Tests of the <see cref="Interlocked"/> functions.
/// </summary>
internal class TestAtomics
{
[TestCompiler(1)]
[TestCompiler(-1)]
public static int test_atomic_increment_int(ref int value)
{
return Interlocked.Increment(ref value);
}
[TestCompiler(1L)]
[TestCompiler(-1L)]
public static long test_atomic_increment_long(ref long value)
{
return Interlocked.Increment(ref value);
}
[TestCompiler(1)]
[TestCompiler(-1)]
public static int test_atomic_add_int(ref int value)
{
return Interlocked.Add(ref value, 2);
}
[TestCompiler(1L)]
[TestCompiler(-1L)]
public static long test_atomic_add_long(ref long value)
{
return Interlocked.Add(ref value, 2);
}
[TestCompiler(1, 2, 1)]
[TestCompiler(1, 10, 1)]
[TestCompiler(1, 2, 2)]
[TestCompiler(7, 2, 1)]
[TestCompiler(7, 10, 1)]
[TestCompiler(7, 2, 2)]
public static int test_atomic_compare_and_exchange_int(ref int location, int value, int compareAnd)
{
return Interlocked.CompareExchange(ref location, value, compareAnd);
}
[TestCompiler(1L, 2L, 1L)]
[TestCompiler(1L, 10L, 1L)]
[TestCompiler(1L, 2L, 2L)]
[TestCompiler(7L, 2L, 1L)]
[TestCompiler(7L, 10L, 1L)]
[TestCompiler(7L, 2L, 2L)]
public static long test_atomic_compare_and_exchange_long(ref long location, long value, long compareAnd)
{
return Interlocked.CompareExchange(ref location, value, compareAnd);
}
[TestCompiler(1)]
[TestCompiler(-1)]
public static int test_atomic_decrement_int(ref int value)
{
return Interlocked.Decrement(ref value);
}
[TestCompiler(1L)]
[TestCompiler(-1L)]
public static long test_atomic_decrement_long(ref long value)
{
return Interlocked.Decrement(ref value);
}
[TestCompiler(1)]
public static int test_atomic_exchange_int(ref int value)
{
return Interlocked.Exchange(ref value, 5);
}
[TestCompiler(1L)]
public static long test_atomic_exchange_long(ref long value)
{
return Interlocked.Exchange(ref value, 5);
}
[TestCompiler(1)]
public static IntPtr ExchangeIntPtr(IntPtr value)
{
return Interlocked.Exchange(ref value, new IntPtr(5));
}
[TestCompiler(1, 2, 1)]
[TestCompiler(1, 10, 1)]
[TestCompiler(1, 2, 2)]
public static IntPtr CompareExchangeIntPtr(IntPtr location, IntPtr value, IntPtr compareAnd)
{
return Interlocked.CompareExchange(ref location, value, compareAnd);
}
[TestCompiler]
public static void test_atomic_memorybarrier()
{
Interlocked.MemoryBarrier();
}
[TestCompiler(0)]
public static int Case1111040(int val)
{
int test = val;
Interlocked.Increment(ref test);
Interlocked.Decrement(ref test);
return test;
}
[TestCompiler(42.0f)]
public static float ExchangeFloat(ref float f)
{
if (Interlocked.Exchange(ref f, 13) == 42)
{
return f;
}
return 0;
}
[TestCompiler(42.0)]
public static double ExchangeDouble(ref double d)
{
if (Interlocked.Exchange(ref d, 13) == 42)
{
return d;
}
return 0;
}
#if !BURST_APPLE_SILICON_TESTING // https://jira.unity3d.com/browse/UUM-9159
[TestCompiler(42.0f)]
public static float CompareExchangeFloat(ref float f)
{
if (Interlocked.CompareExchange(ref f, 13, 42) == 42)
{
return f;
}
return 0;
}
#endif
[TestCompiler(42.0)]
public static double CompareExchangeDouble(ref double d)
{
if (Interlocked.CompareExchange(ref d, 13, 42) == 42)
{
return d;
}
return 0;
}
[TestCompiler(42L)]
public static double Read(ref long l)
{
if (Interlocked.Read(ref l) == 42)
{
return l;
}
return 0;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a1bc4bf3e38931c9b2014cc764d03dea
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,265 @@
using System;
using Burst.Compiler.IL.Tests.Helpers;
namespace Burst.Compiler.IL.Tests
{
/// <summary>
/// Tests of the <see cref="System.Math"/> functions.
/// </summary>
internal class TestSystemMath
{
[TestCompiler(DataRange.Standard)]
public static double TestCos(float value)
{
return Math.Cos(value);
}
[TestCompiler(DataRange.Standard)]
public static double TestSin(float value)
{
return Math.Sin(value);
}
[TestCompiler(DataRange.Standard)]
public static float TestTan(float value)
{
return (float) Math.Tan(value);
}
[TestCompiler(DataRange.Standard11)]
public static double TestAcos(float value)
{
return Math.Acos(value);
}
[TestCompiler(DataRange.Standard11)]
public static double TestAsin(float value)
{
return Math.Asin(value);
}
[TestCompiler(DataRange.Standard11)]
public static float TestAtan(float value)
{
return (float)Math.Atan(value);
}
[TestCompiler(DataRange.ZeroExclusiveToOneInclusive, DataRange.ZeroExclusiveToOneInclusive)]
public static float TestAtan2(float y, float x)
{
return (float)Math.Atan2(y, x);
}
[TestCompiler(DataRange.Standard)]
public static double TestCosh(float value)
{
return Math.Cosh(value);
}
[TestCompiler(DataRange.Standard)]
public static double TestSinh(float value)
{
return Math.Sinh(value);
}
[TestCompiler(DataRange.Standard)]
public static float TestTanh(float value)
{
return (float)Math.Tanh(value);
}
[TestCompiler(DataRange.StandardPositive)]
public static double TestSqrt(float value)
{
return Math.Sqrt(value);
}
[TestCompiler(DataRange.StandardPositive & ~DataRange.Zero)]
public static double TestLog(float value)
{
return Math.Log(value);
}
[TestCompiler(DataRange.StandardPositive & ~DataRange.Zero)]
public static double TestLog10(float value)
{
return Math.Log10(value);
}
[TestCompiler(DataRange.StandardPositive)]
public static double TestExp(float value)
{
return Math.Exp(value);
}
[TestCompiler(DataRange.Standard & ~(DataRange.Zero|DataRange.NaN), DataRange.Standard)]
[TestCompiler(DataRange.Standard & ~DataRange.Zero, DataRange.Standard & ~DataRange.Zero)]
public static double TestPow(float value, float power)
{
return Math.Pow(value, power);
}
[TestCompiler(DataRange.Standard)]
public static sbyte TestAbsSByte(sbyte value)
{
return Math.Abs(value);
}
[TestCompiler(DataRange.Standard)]
public static short TestAbsShort(short value)
{
return Math.Abs(value);
}
[TestCompiler(DataRange.Standard)]
public static int TestAbsInt(int value)
{
return Math.Abs(value);
}
[TestCompiler(DataRange.Standard)]
public static long TestAbsLong(long value)
{
return Math.Abs(value);
}
[TestCompiler(DataRange.Standard)]
public static float TestAbsFloat(float value)
{
return Math.Abs(value);
}
[TestCompiler(DataRange.Standard)]
public static double TestAbsDouble(double value)
{
return Math.Abs(value);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int TestMaxInt(int left, int right)
{
return Math.Max(left, right);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int TestMinInt(int left, int right)
{
return Math.Min(left, right);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static double TestMaxDouble(double left, double right)
{
return Math.Max(left, right);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static double TestMinDouble(double left, double right)
{
return Math.Min(left, right);
}
[TestCompiler(DataRange.Standard)]
public static int TestSignInt(int value)
{
return Math.Sign(value);
}
[TestCompiler(DataRange.Standard & ~DataRange.NaN)]
public static int TestSignFloat(float value)
{
return Math.Sign(value);
}
[TestCompiler(float.NaN, ExpectedException = typeof(ArithmeticException))]
[MonoOnly(".NET CLR does not support burst.abort correctly")]
public static int TestSignException(float value)
{
return Math.Sign(value);
}
[TestCompiler(DataRange.Standard & ~DataRange.NaN)]
public static int TestSignDouble(double value)
{
return Math.Sign(value);
}
[TestCompiler(DataRange.Standard)]
public static double TestCeilingDouble(double value)
{
return Math.Ceiling(value);
}
[TestCompiler(DataRange.Standard)]
public static double TestFloorDouble(double value)
{
return Math.Floor(value);
}
[TestCompiler(DataRange.Standard)]
public static double TestRoundDouble(double value)
{
return Math.Round(value);
}
[TestCompiler(DataRange.Standard)]
public static double TestTruncateDouble(double value)
{
return Math.Truncate(value);
}
[TestCompiler(DataRange.Standard, DataRange.Standard & ~DataRange.Zero)]
public static int TestDivRemInt(int a, int b)
{
int remResult;
var divResult = Math.DivRem(a, b, out remResult);
return divResult + remResult * 7;
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
[TestCompiler(int.MaxValue, DataRange.Standard)]
public static long TestBigMulInt(int a, int b)
{
return Math.BigMul(a, b);
}
[TestCompiler(DataRange.Standard & ~DataRange.Zero, DataRange.Standard & ~DataRange.Zero)]
public static double TestLogWithBaseDouble(double a, double newBase)
{
return Math.Log(a, newBase);
}
//[TestCompiler(1.0, 2.0)]
//[TestCompiler(10.0, 3.0)]
//[TestCompiler(15.0, 4.0)]
//[Ignore("Not yet supported")]
//public static double TestIEEERemainder(double a, double newBase)
//{
// return Math.IEEERemainder(a, newBase);
//}
[TestCompiler(DataRange.Standard)]
public static bool TestIsNanDouble(double a)
{
return double.IsNaN(a);
}
[TestCompiler(DataRange.Standard)]
public static bool TestIsNanFloat(float a)
{
return float.IsNaN(a);
}
[TestCompiler(DataRange.Standard)]
public static bool TestIsInfinityDouble(double a)
{
return double.IsInfinity(a);
}
[TestCompiler(DataRange.Standard)]
public static bool TestIsInfinityFloat(float a)
{
return float.IsInfinity(a);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 47108b7d7a79385f98626b40f17ef46d
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,192 @@
using System;
using System.Threading;
using UnityBenchShared;
namespace Burst.Compiler.IL.Tests
{
/// <summary>
/// Tests of the <see cref="System.Threading"/> functions.
/// </summary>
internal class TestSystemThreading
{
[TestCompiler]
public static void TestMemoryBarrier()
{
Thread.MemoryBarrier();
}
[TestCompiler]
public static int TestReadBool()
{
var data = false;
return (Volatile.Read(ref data) ? 1 : 0) + (Volatile.Read(ref data) ? 1 : 0);
}
[TestCompiler((byte)42)]
public static int TestReadByte(ref byte data)
{
return Volatile.Read(ref data) + Volatile.Read(ref data);
}
[TestCompiler((sbyte)42)]
public static int TestReadSByte(ref sbyte data)
{
return Volatile.Read(ref data) + Volatile.Read(ref data);
}
[TestCompiler((short)42)]
public static int TestReadShort(ref short data)
{
return Volatile.Read(ref data) + Volatile.Read(ref data);
}
[TestCompiler((ushort)42)]
public static int TestReadUShort(ref ushort data)
{
return Volatile.Read(ref data) + Volatile.Read(ref data);
}
[TestCompiler(42)]
public static int TestReadInt(ref int data)
{
return Volatile.Read(ref data) + Volatile.Read(ref data);
}
[TestCompiler(42u)]
public static uint TestReadUInt(ref uint data)
{
return Volatile.Read(ref data) + Volatile.Read(ref data);
}
[TestCompiler((long)42)]
public static long TestReadLong(ref long data)
{
return Volatile.Read(ref data) + Volatile.Read(ref data);
}
[TestCompiler((ulong)42)]
public static ulong TestReadULong(ref ulong data)
{
return Volatile.Read(ref data) + Volatile.Read(ref data);
}
[TestCompiler(42.0f)]
public static float TestReadFloat(ref float data)
{
return Volatile.Read(ref data);
}
[TestCompiler(42.0)]
public static double TestReadDouble(ref double data)
{
return Volatile.Read(ref data);
}
public struct UIntPtrProvider : IArgumentProvider
{
public object Value => UIntPtr.Zero;
}
[TestCompiler(typeof(UIntPtrProvider))]
public static UIntPtr TestReadUIntPtr(ref UIntPtr data)
{
return Volatile.Read(ref data);
}
[TestCompiler]
public static int TestWriteBool()
{
var data = false;
Volatile.Write(ref data, true);
return data ? 1 : 0;
}
[TestCompiler((byte)42)]
public static int TestWriteByte(ref byte data)
{
var result = data;
Volatile.Write(ref data, 1);
return result + data;
}
[TestCompiler((sbyte)42)]
public static int TestWriteSByte(ref sbyte data)
{
var result = data;
Volatile.Write(ref data, 2);
return result + data;
}
[TestCompiler((short)42)]
public static int TestWriteShort(ref short data)
{
var result = data;
Volatile.Write(ref data, 3);
return result + data;
}
[TestCompiler((ushort)42)]
public static int TestWriteUShort(ref ushort data)
{
var result = data;
Volatile.Write(ref data, 4);
return result + data;
}
[TestCompiler(42)]
public static int TestWriteInt(ref int data)
{
var result = data;
Volatile.Write(ref data, 5);
return result + data;
}
[TestCompiler(42u)]
public static uint TestWriteUInt(ref uint data)
{
var result = data;
Volatile.Write(ref data, 6);
return result + data;
}
[TestCompiler((long)42)]
public static long TestWriteLong(ref long data)
{
var result = data;
Volatile.Write(ref data, 7);
return result + data;
}
[TestCompiler((ulong)42)]
public static ulong TestWriteULong(ref ulong data)
{
var result = data;
Volatile.Write(ref data, 8);
return result + data;
}
[TestCompiler(42.0f)]
public static float TestWriteFloat(ref float data)
{
var result = data;
Volatile.Write(ref data, 9);
return result + data;
}
[TestCompiler(42.0)]
public static double TestWriteDouble(ref double data)
{
var result = data;
Volatile.Write(ref data, 10);
return result + data;
}
[TestCompiler(typeof(UIntPtrProvider))]
public static UIntPtr TestWriteUIntPtr(ref UIntPtr data)
{
var result = data;
Volatile.Write(ref data, new UIntPtr(11));
return result;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 631a9c909a1e35999f140f79ef90911a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,351 @@
using Burst.Compiler.IL.Tests.Helpers;
using System.Linq.Expressions;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
/// <summary>
/// Tests a few single float functions for <see cref="Unity.Mathematics.math"/> functions.
/// </summary>
internal class TestUnityMath
{
[TestCompiler(DataRange.Standard)]
public static float TestCos(float value)
{
return math.cos(value);
}
[TestCompiler(DataRange.Standard)]
public static float TestSin(float value)
{
return math.sin(value);
}
[TestCompiler(DataRange.Standard)]
public static float TestTan(float value)
{
return (float) math.tan(value);
}
[TestCompiler(-1000000f)]
[TestCompiler(-1.2f)]
public static float TestTan2(float value)
{
return (float)math.tan(value);
}
[TestCompiler(DataRange.Standard11)]
public static float TestAcos(float value)
{
return math.acos(value);
}
[TestCompiler(DataRange.Standard11)]
public static float TestAsin(float value)
{
return math.asin(value);
}
[TestCompiler(DataRange.Standard11)]
public static float TestAtan(float value)
{
return (float)math.atan(value);
}
[TestCompiler(DataRange.Standard)]
public static float TestCosh(float value)
{
return math.cosh(value);
}
[TestCompiler(DataRange.Standard)]
public static float TestSinh(float value)
{
return math.sinh(value);
}
[TestCompiler(DataRange.Standard)]
public static float TestTanh(float value)
{
return (float)math.tanh(value);
}
[TestCompiler(DataRange.StandardPositive)]
public static float TestSqrt(float value)
{
return math.sqrt(value);
}
[TestCompiler(DataRange.StandardPositive & ~DataRange.Zero)]
public static float TestLog(float value)
{
return math.log(value);
}
[TestCompiler(DataRange.StandardPositive & ~DataRange.Zero)]
public static float TestLog10(float value)
{
return math.log10(value);
}
[TestCompiler(DataRange.StandardPositive)]
public static float TestExp(float value)
{
return math.exp(value);
}
[TestCompiler(DataRange.Standard & ~(DataRange.Zero|DataRange.NaN), DataRange.Standard)]
[TestCompiler(DataRange.Standard & ~DataRange.Zero, DataRange.Standard & ~DataRange.Zero)]
public static float TestPow(float value, float power)
{
return math.pow(value, power);
}
[TestCompiler(DataRange.Standard)]
public static float TestAbsFloat(float value)
{
return math.abs(value);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int TestMaxInt(int left, int right)
{
return math.max(left, right);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int TestMinInt(int left, int right)
{
return math.min(left, right);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float TestMaxfloat(float left, float right)
{
return math.max(left, right);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float TestMinfloat(float left, float right)
{
return math.min(left, right);
}
[TestCompiler(DataRange.Standard & ~DataRange.NaN)]
public static float TestSignFloat(float value)
{
return math.sign(value);
}
[TestCompiler(-123.45)]
[TestCompiler(-1E-20)]
[TestCompiler(0.0)]
[TestCompiler(1E-10)]
[TestCompiler(123.45)]
[TestCompiler(double.NegativeInfinity)]
[TestCompiler(double.NaN)]
[TestCompiler(double.PositiveInfinity)]
public static double TestSignDouble(double value)
{
return math.sign(value);
}
[TestCompiler(DataRange.Standard)]
public static float TestCeilingfloat(float value)
{
return math.ceil(value);
}
[TestCompiler(DataRange.Standard)]
public static float TestFloorfloat(float value)
{
return math.floor(value);
}
[TestCompiler(DataRange.Standard)]
public static float TestRoundfloat(float value)
{
return math.round(value);
}
[TestCompiler(DataRange.Standard)]
public static float TestTruncatefloat(float value)
{
return math.trunc(value);
}
private readonly static float3 a = new float3(1, 2, 3);
[TestCompiler]
public static bool TestStaticLoad()
{
var cmp = a == new float3(1, 2, 3);
return cmp.x && cmp.y && cmp.z;
}
[TestCompiler(42L)]
public static long TestLongCountbits(long value)
{
return math.countbits(value) - 1;
}
[TestCompiler(42L)]
public static long TestLongLzcnt(long value)
{
return math.lzcnt(value) - 1;
}
[TestCompiler(42L)]
public static long TestLongTzcnt(long value)
{
return math.tzcnt(value) - 1;
}
[TestCompiler(typeof(ReturnBox), (ushort)42)]
public static unsafe void TestUshortAddInt2(int2* o, ushort i)
{
*o = i + new int2(0, 0);
}
[TestCompiler(typeof(ReturnBox), (ushort)42)]
public static unsafe void TestInt2AddUshort(int2* o, ushort i)
{
*o = new int2(0, 0) + i;
}
[TestCompiler(typeof(ReturnBox), (ushort)42)]
public static unsafe void TestUshortSubInt2(int2* o, ushort i)
{
*o = i - new int2(0, 0);
}
[TestCompiler(typeof(ReturnBox), (ushort)42)]
public static unsafe void TestInt2SubUshort(int2* o, ushort i)
{
*o = new int2(0, 0) - i;
}
[TestCompiler(typeof(ReturnBox), (ushort)42)]
public static unsafe void TestUshortMulInt2(int2* o, ushort i)
{
*o = i * new int2(0, 0);
}
[TestCompiler(typeof(ReturnBox), (ushort)42)]
public static unsafe void TestInt2MulUshort(int2* o, ushort i)
{
*o = new int2(0, 0) * i;
}
[TestCompiler(typeof(ReturnBox), (ushort)42)]
public static unsafe void TestUshortDivInt2(int2* o, ushort i)
{
*o = i / new int2(1, 1);
}
[TestCompiler(typeof(ReturnBox), (ushort)42)]
public static unsafe void TestInt2DivUshort(int2* o, ushort i)
{
*o = new int2(0, 0) / i;
}
[TestCompiler(typeof(ReturnBox), (ushort)42)]
public static unsafe void TestUshortModInt2(int2* o, ushort i)
{
*o = i % new int2(1, 1);
}
[TestCompiler(typeof(ReturnBox), (ushort)42)]
public static unsafe void TestInt2ModUshort(int2* o, ushort i)
{
*o = new int2(0, 0) % i;
}
[TestCompiler((ushort)42)]
public static unsafe int TestUshortEqInt2(ushort i)
{
return math.all(i == new int2(0, 0)) ? 1 : 0;
}
[TestCompiler((ushort)42)]
public static unsafe int TestInt2EqUshort(ushort i)
{
return math.all(new int2(0, 0) == i) ? 1 : 0;
}
[TestCompiler((ushort)42)]
public static unsafe int TestUshortNeInt2(ushort i)
{
return math.all(i != new int2(0, 0)) ? 1 : 0;
}
[TestCompiler((ushort)42)]
public static unsafe int TestInt2NeUshort(ushort i)
{
return math.all(new int2(0, 0) != i) ? 1 : 0;
}
[TestCompiler((ushort)42)]
public static unsafe int TestUshortGeInt2(ushort i)
{
return math.all(i >= new int2(0, 0)) ? 1 : 0;
}
[TestCompiler((ushort)42)]
public static unsafe int TestInt2GeUshort(ushort i)
{
return math.all(new int2(0, 0) >= i) ? 1 : 0;
}
[TestCompiler((ushort)42)]
public static unsafe int TestUshortGtInt2(ushort i)
{
return math.all(i > new int2(0, 0)) ? 1 : 0;
}
[TestCompiler((ushort)42)]
public static unsafe int TestInt2GtUshort(ushort i)
{
return math.all(new int2(0, 0) > i) ? 1 : 0;
}
[TestCompiler((ushort)42)]
public static unsafe int TestUshortLtInt2(ushort i)
{
return math.all(i < new int2(0, 0)) ? 1 : 0;
}
[TestCompiler((ushort)42)]
public static unsafe int TestInt2LtUshort(ushort i)
{
return math.all(new int2(0, 0) < i) ? 1 : 0;
}
[TestCompiler((ushort)42)]
public static unsafe int TestUshortLeInt2(ushort i)
{
return math.all(i <= new int2(0, 0)) ? 1 : 0;
}
[TestCompiler((ushort)42)]
public static unsafe int TestInt2LeUshort(ushort i)
{
return math.all(new int2(0, 0) <= i) ? 1 : 0;
}
[TestCompiler(42.0f)]
public static float TestSqrtAndAcosIsDefinedBehaviour(float a)
{
// This sqrt call will get folded away, but we need it here because it exhibits the bug.
if (math.sqrt(4) == 2)
{
return math.acos(a);
}
else
{
return 42;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3d355504e32f39b89ef31f85cad154a5
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,184 @@
using Unity.Collections.LowLevel.Unsafe;
using Unity.Burst;
using Unity.Burst.CompilerServices;
#if BURST_TESTS_ONLY
namespace Unity.Collections.LowLevel.Unsafe
{
internal class DisposeSentinel
{
}
}
#endif
namespace Burst.Compiler.IL.Tests
{
/// <summary>
/// Tests related to usage of partial managed objects (e.g loading null or storing null
/// reference to a struct, typically used by NativeArray DisposeSentinel)
/// </summary>
internal class PartialManaged
{
#if BURST_TESTS_ONLY || ENABLE_UNITY_COLLECTIONS_CHECKS
[TestCompiler]
public static int TestWriteNullReference()
{
var element = new Element();
WriteNullReference(out element.Reference);
return element.Value;
}
[BurstDiscard]
private static void WriteNullReference(out DisposeSentinel reference)
{
reference = null;
}
private struct Element
{
#pragma warning disable 0649
public int Value;
public DisposeSentinel Reference;
#pragma warning restore 0649
}
#endif
[TestCompiler]
public static void AssignNullToLocalVariableClass()
{
MyClass x = null;
#pragma warning disable 0219
MyClass value = x;
#pragma warning restore 0219
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_CallingManagedMethodNotSupported)]
public static int GetIndexOfCharFomString()
{
return "abc".IndexOf('b');
}
struct StructWithManaged
{
#pragma warning disable 0649
public MyClass myClassValue;
public string stringValue;
public object objectValue;
public float[] arrayValue;
public int value;
#pragma warning restore 0649
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_TypeNotSupported)]
public static int AccessClassFromStruct()
{
var val = new StructWithManaged();
val.myClassValue.value = val.value;
return val.myClassValue.value;
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_TypeNotSupported)]
public static void AccessStringFromStruct()
{
var val = new StructWithManaged();
#pragma warning disable 0219
var p = val.stringValue = "abc";
#pragma warning restore 0219
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_TypeNotSupported)]
public static void AccessObjectFromStruct()
{
var val = new StructWithManaged();
#pragma warning disable 0219
var p = val.objectValue;
p = new object();
#pragma warning restore 0219
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_TypeNotSupported)]
public static void AccessArrayFromStruct()
{
var val = new StructWithManaged();
var p = val.arrayValue;
p[0] = val.value;
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_TypeNotSupported)]
public static int GetValueFromStructWithClassField()
{
var val = new StructWithManaged();
val.value = 5;
return val.value;
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_InstructionNewobjWithManagedTypeNotSupported)]
public static void NewMyClass()
{
#pragma warning disable 0219
var value = new MyClass();
#pragma warning restore 0219
}
private class MyClass
{
public int value;
}
private class SomeClassWithMixedStatics
{
public static int SomeInt = 42;
public static readonly SharedStatic<int> SomeSharedStatic = SharedStatic<int>.GetOrCreate<int>();
[BurstDiscard]
private static void DoSomethingWithStaticInt(ref int x) => x = SomeInt;
[IgnoreWarning(1371)]
public static int DoSomething()
{
ref var data = ref SomeSharedStatic.Data;
DoSomethingWithStaticInt(ref data);
return SomeSharedStatic.Data;
}
}
[TestCompiler(OverrideManagedResult = 0)]
public static int DoSomethingThatUsesMixedStatics()
{
return SomeClassWithMixedStatics.DoSomething();
}
private class SomeClassWithMixedStaticsWithExplicitStaticConstructor
{
public static int SomeInt = 42;
public static readonly SharedStatic<int> SomeSharedStatic = SharedStatic<int>.GetOrCreate<int>();
static SomeClassWithMixedStaticsWithExplicitStaticConstructor()
{
SomeInt = 1;
}
[BurstDiscard]
private static void DoSomethingWithStaticInt(ref int x) => x = SomeInt;
[IgnoreWarning(1371)]
public static int DoSomething()
{
ref var data = ref SomeSharedStatic.Data;
DoSomethingWithStaticInt(ref data);
return SomeSharedStatic.Data;
}
}
[TestCompiler(OverrideManagedResult = 0)]
public static int DoSomethingThatUsesMixedStaticsWithExplicitStaticConstructor()
{
return SomeClassWithMixedStaticsWithExplicitStaticConstructor.DoSomething();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 66f82e3041613b77861041e9b0479554
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,474 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityBenchShared;
using static Unity.Burst.CompilerServices.Aliasing;
namespace Burst.Compiler.IL.Tests
{
internal partial class Aliasing
{
public unsafe struct NoAliasField
{
[NoAlias]
public int* ptr1;
[NoAlias]
public int* ptr2;
public void Compare(ref NoAliasField other)
{
// Check that we can definitely alias with another struct of the same type as us.
ExpectAliased(in this, in other);
}
public void Compare(ref ContainerOfManyNoAliasFields other)
{
// Check that we can definitely alias with another struct which contains the same type as ourself.
ExpectAliased(in this, in other);
}
public class Provider : IArgumentProvider
{
public object Value => new NoAliasField { ptr1 = null, ptr2 = null };
}
}
public unsafe struct ContainerOfManyNoAliasFields
{
public NoAliasField s0;
public NoAliasField s1;
[NoAlias]
public NoAliasField s2;
[NoAlias]
public NoAliasField s3;
public class Provider : IArgumentProvider
{
public object Value => new ContainerOfManyNoAliasFields { s0 = new NoAliasField { ptr1 = null, ptr2 = null }, s1 = new NoAliasField { ptr1 = null, ptr2 = null }, s2 = new NoAliasField { ptr1 = null, ptr2 = null }, s3 = new NoAliasField { ptr1 = null, ptr2 = null } };
}
}
[StructLayout(LayoutKind.Explicit)]
public struct Union
{
[FieldOffset(0)]
public ulong a;
[FieldOffset(1)]
public int b;
[FieldOffset(5)]
public float c;
public class Provider : IArgumentProvider
{
public object Value => new Union { a = 4242424242424242, b = 13131313, c = 42.0f };
}
}
public unsafe struct LinkedList
{
public LinkedList* next;
public class Provider : IArgumentProvider
{
public object Value => new LinkedList { next = null };
}
}
[NoAlias]
public unsafe struct NoAliasWithContentsStruct
{
public void* ptr0;
public void* ptr1;
public class Provider : IArgumentProvider
{
public object Value => new NoAliasWithContentsStruct { ptr0 = null, ptr1 = null };
}
}
[NoAlias]
public unsafe struct DoesAliasWithSubStructPointersStruct : IDisposable
{
public NoAliasWithContentsStruct* s;
public void* ptr;
public class Provider : IArgumentProvider
{
public object Value
{
get
{
var noAliasSubStruct = (NoAliasWithContentsStruct*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf<NoAliasWithContentsStruct>(), UnsafeUtility.AlignOf<NoAliasWithContentsStruct>(), Allocator.Temp);
noAliasSubStruct->ptr0 = null;
noAliasSubStruct->ptr1 = null;
var s = new DoesAliasWithSubStructPointersStruct { s = noAliasSubStruct, ptr = null };
return s;
}
}
}
public void Dispose()
{
UnsafeUtility.Free(s, Allocator.Temp);
}
}
[TestCompiler(typeof(NoAliasField.Provider))]
public static unsafe void CheckNoAliasFieldWithItself(ref NoAliasField s)
{
// Check that they correctly alias with themselves.
ExpectAliased(s.ptr1, s.ptr1);
ExpectAliased(s.ptr2, s.ptr2);
}
[TestCompiler(typeof(NoAliasField.Provider))]
public static unsafe void CheckNoAliasFieldWithAnotherPointer(ref NoAliasField s)
{
// Check that they do not alias each other because of the [NoAlias] on the ptr1 field above.
ExpectNotAliased(s.ptr1, s.ptr2);
}
[TestCompiler(typeof(NoAliasField.Provider))]
public static unsafe void CheckNoAliasFieldWithNull(ref NoAliasField s)
{
// Check that comparing a pointer with null is no alias.
ExpectNotAliased(s.ptr1, null);
}
[TestCompiler(typeof(NoAliasField.Provider))]
public static unsafe void CheckAliasFieldWithNull(ref NoAliasField s)
{
// Check that comparing a pointer with null is no alias.
ExpectNotAliased(s.ptr2, null);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe void NoAliasInfoSubFunctionAlias(int* a, int* b)
{
ExpectAliased(a, b);
}
[TestCompiler(typeof(NoAliasField.Provider))]
public static unsafe void CheckNoAliasFieldSubFunctionAlias(ref NoAliasField s)
{
NoAliasInfoSubFunctionAlias(s.ptr1, s.ptr1);
}
[TestCompiler(typeof(NoAliasField.Provider))]
public static unsafe void CheckCompareWithItself(ref NoAliasField s)
{
s.Compare(ref s);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe void AliasInfoSubFunctionNoAlias([NoAlias] int* a, int* b)
{
ExpectNotAliased(a, b);
}
[TestCompiler(typeof(NoAliasField.Provider))]
public static unsafe void CheckNoAliasFieldSubFunctionWithNoAliasParameter(ref NoAliasField s)
{
AliasInfoSubFunctionNoAlias(s.ptr1, s.ptr1);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe void AliasInfoSubFunctionTwoSameTypedStructs(ref NoAliasField s0, ref NoAliasField s1)
{
// Check that they do not alias within their own structs.
ExpectNotAliased(s0.ptr1, s0.ptr2);
ExpectNotAliased(s1.ptr1, s1.ptr2);
// But that they do alias across structs.
ExpectAliased(s0.ptr1, s1.ptr1);
ExpectAliased(s0.ptr1, s1.ptr2);
ExpectAliased(s0.ptr2, s1.ptr1);
ExpectAliased(s0.ptr2, s1.ptr2);
}
[TestCompiler(typeof(NoAliasField.Provider), typeof(NoAliasField.Provider))]
public static unsafe void CheckNoAliasFieldAcrossTwoSameTypedStructs(ref NoAliasField s0, ref NoAliasField s1)
{
AliasInfoSubFunctionTwoSameTypedStructs(ref s0, ref s1);
}
[TestCompiler(4, 13)]
public static void CheckNoAliasRefs([NoAlias] ref int a, ref int b)
{
ExpectAliased(in a, in a);
ExpectAliased(in b, in b);
ExpectNotAliased(in a, in b);
}
[TestCompiler(4, 13.53f)]
public static void CheckNoAliasRefsAcrossTypes([NoAlias] ref int a, ref float b)
{
ExpectNotAliased(in a, in b);
}
[TestCompiler(typeof(Union.Provider))]
public static void CheckNoAliasRefsInUnion(ref Union u)
{
ExpectAliased(in u.a, in u.b);
ExpectAliased(in u.a, in u.c);
ExpectNotAliased(in u.b, in u.c);
}
[TestCompiler(typeof(ContainerOfManyNoAliasFields.Provider))]
public static unsafe void CheckNoAliasOfSubStructs(ref ContainerOfManyNoAliasFields s)
{
// Since ptr1 and ptr2 have [NoAlias], they do not alias within the same struct instance.
ExpectNotAliased(s.s0.ptr1, s.s0.ptr2);
ExpectNotAliased(s.s1.ptr1, s.s1.ptr2);
ExpectNotAliased(s.s2.ptr1, s.s2.ptr2);
ExpectNotAliased(s.s3.ptr1, s.s3.ptr2);
// Across s0 and s1 their pointers can alias each other though.
ExpectAliased(s.s0.ptr1, s.s1.ptr1);
ExpectAliased(s.s0.ptr1, s.s1.ptr2);
ExpectAliased(s.s0.ptr2, s.s1.ptr1);
ExpectAliased(s.s0.ptr2, s.s1.ptr2);
// Also s2 can alias with s0 and s1 (because they do not have [NoAlias]).
ExpectAliased(s.s2.ptr1, s.s0.ptr1);
ExpectAliased(s.s2.ptr1, s.s0.ptr2);
ExpectAliased(s.s2.ptr2, s.s1.ptr1);
ExpectAliased(s.s2.ptr2, s.s1.ptr2);
// Also s3 can alias with s0 and s1 (because they do not have [NoAlias]).
ExpectAliased(s.s3.ptr1, s.s0.ptr1);
ExpectAliased(s.s3.ptr1, s.s0.ptr2);
ExpectAliased(s.s3.ptr2, s.s1.ptr1);
ExpectAliased(s.s3.ptr2, s.s1.ptr2);
// But s2 and s3 cannot alias each other (they both have [NoAlias]).
ExpectNotAliased(s.s2.ptr1, s.s3.ptr1);
ExpectNotAliased(s.s2.ptr1, s.s3.ptr2);
ExpectNotAliased(s.s2.ptr2, s.s3.ptr1);
ExpectNotAliased(s.s2.ptr2, s.s3.ptr2);
}
[TestCompiler(typeof(ContainerOfManyNoAliasFields.Provider))]
public static unsafe void CheckNoAliasFieldCompareWithParentStruct(ref ContainerOfManyNoAliasFields s)
{
s.s0.Compare(ref s);
s.s1.Compare(ref s);
s.s2.Compare(ref s);
s.s3.Compare(ref s);
}
[TestCompiler(typeof(LinkedList.Provider))]
public static unsafe void CheckStructPointerOfSameTypeInStruct(ref LinkedList l)
{
ExpectAliased(in l, l.next);
}
[TestCompiler(typeof(NoAliasWithContentsStruct.Provider))]
public static unsafe void CheckStructWithNoAlias(ref NoAliasWithContentsStruct s)
{
// Since NoAliasWithContentsStruct has [NoAlias] on the struct definition, it cannot alias with any pointers within the struct.
ExpectNotAliased(in s, s.ptr0);
ExpectNotAliased(in s, s.ptr1);
}
[TestCompiler(typeof(DoesAliasWithSubStructPointersStruct.Provider))]
public static unsafe void CheckStructWithNoAliasAndSubStructs(ref DoesAliasWithSubStructPointersStruct s)
{
// Since DoesAliasWithSubStructPointersStruct has [NoAlias] on the struct definition, it cannot alias with any pointers within the struct.
ExpectNotAliased(in s, s.s);
ExpectNotAliased(in s, s.ptr);
// s.s is a [NoAlias] struct, so it shouldn't alias with pointers within it.
ExpectNotAliased(s.s, s.s->ptr0);
ExpectNotAliased(s.s, s.s->ptr1);
// But we don't know whether s.s and s.ptr alias.
ExpectAliased(s.s, s.ptr);
// And we cannot assume that s does not alias with the sub-pointers of s.s.
ExpectAliased(in s, s.s->ptr0);
ExpectAliased(in s, s.s->ptr1);
}
private unsafe struct AliasingWithSelf
{
public AliasingWithSelf* ptr;
[MethodImpl(MethodImplOptions.NoInlining)]
public void CheckAlias()
{
ExpectAliased(in this, ptr);
}
}
[TestCompiler]
public static unsafe void CheckAliasingWithSelf()
{
var s = new AliasingWithSelf { ptr = null };
s.ptr = (AliasingWithSelf*) &s;
s.CheckAlias();
}
private unsafe struct AliasingWithHiddenSelf
{
public void* ptr;
[MethodImpl(MethodImplOptions.NoInlining)]
public void CheckAlias()
{
ExpectAliased(in this, ptr);
}
}
[TestCompiler]
public static unsafe void CheckAliasingWithHiddenSelf()
{
var s = new AliasingWithHiddenSelf { ptr = null };
s.ptr = &s;
s.CheckAlias();
}
[MethodImpl(MethodImplOptions.NoInlining)]
[return: NoAlias]
private static unsafe int* NoAliasReturn(int size)
{
return (int*)UnsafeUtility.Malloc(size, 16, Allocator.Temp);
}
[TestCompiler(typeof(NoAliasField.Provider))]
public static unsafe void CheckNoAliasReturn(ref NoAliasField s)
{
int* ptr1 = NoAliasReturn(40);
int* ptr2 = NoAliasReturn(4);
int* ptr3 = ptr2 + 4;
byte* ptr4 = (byte*)ptr3 + 1;
// Obviously it still aliases with itself even it we bitcast.
ExpectAliased((char*)ptr1 + 4, ptr1 + 1);
// We know that both allocations can't point to the same memory as
// they are derived from Malloc!).
ExpectNotAliased(ptr1, ptr2);
// Since ptr3 derives from ptr2 it cannot alias with ptr1.
ExpectNotAliased(ptr3, ptr1);
// And the derefenced memory locations at ptr3 and ptr2 cannot alias
// since ptr3 does not overlap the allocation in ptr2.
ExpectNotAliased(in *ptr3, in *ptr2);
// The pointers pt4 and ptr3 have overlapping ranges so they do alias.
ExpectAliased(in *ptr4, in *ptr3);
// The pointers cannot alias with anything else too!
ExpectNotAliased(ptr1, in s);
ExpectNotAliased(ptr1, s.ptr1);
ExpectNotAliased(ptr1, s.ptr2);
ExpectNotAliased(ptr2, in s);
ExpectNotAliased(ptr2, s.ptr1);
ExpectNotAliased(ptr2, s.ptr2);
ExpectNotAliased(ptr3, in s);
ExpectNotAliased(ptr3, s.ptr1);
ExpectNotAliased(ptr3, s.ptr2);
ExpectNotAliased(ptr4, in s);
ExpectNotAliased(ptr4, s.ptr1);
ExpectNotAliased(ptr4, s.ptr2);
UnsafeUtility.Free(ptr1, Allocator.Temp);
UnsafeUtility.Free(ptr2, Allocator.Temp);
}
[TestCompiler]
public static unsafe void CheckMallocIsNoAlias()
{
int* ptr1 = (int*)UnsafeUtility.Malloc(sizeof(int) * 4, 16, Allocator.Temp);
int* ptr2 = (int*)UnsafeUtility.Malloc(sizeof(int), 16, Allocator.Temp);
ExpectNotAliased(ptr1, ptr2);
UnsafeUtility.Free(ptr1, Allocator.Temp);
UnsafeUtility.Free(ptr2, Allocator.Temp);
}
[MethodImpl(MethodImplOptions.NoInlining)]
[return: NoAlias]
private static unsafe int* BumpAlloc(int* alloca)
{
int location = alloca[0]++;
return alloca + location;
}
[TestCompiler]
public static unsafe void CheckBumpAllocIsNoAlias()
{
int* alloca = stackalloc int[128];
// Store our size at the start of the alloca.
alloca[0] = 1;
int* ptr1 = BumpAlloc(alloca);
int* ptr2 = BumpAlloc(alloca);
// Our bump allocator will never return the same address twice.
ExpectNotAliased(ptr1, ptr2);
}
[TestCompiler(42, 13, 56)]
public static unsafe void CheckInRefOut(in int a, ref int b, out int c)
{
c = 42;
// They obviously alias with themselves.
ExpectAliased(in a, in a);
ExpectAliased(in b, in b);
ExpectAliased(in c, in c);
// And alias with each other too.
ExpectAliased(in a, in b);
ExpectAliased(in a, in c);
ExpectAliased(in b, in c);
}
[TestCompiler(42, 13)]
public static unsafe void CheckOutOut(out int a, out int b)
{
a = 56;
b = -4;
ExpectAliased(in a, in b);
}
private struct SomeData
{
public int A;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe void OutOfBoundsGEPNoAlias(SomeData* someData)
{
ExpectNotAliased(in someData[0], in someData[1]);
}
[TestCompiler]
public static unsafe void CheckOutOfBoundsGEPNoAlias()
{
var someData = stackalloc SomeData[2];
someData[0].A = 42;
someData[1].A = 13;
ExpectNotAliased(in someData[0], in someData[1]);
OutOfBoundsGEPNoAlias(someData);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cb91adf0b099390483bffed46bc16fb1
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,65 @@
using System;
using static Unity.Burst.CompilerServices.Hint;
namespace Burst.Compiler.IL.Tests
{
internal class Hint
{
[TestCompiler(42)]
public static unsafe double CheckLikely(int val)
{
if (Likely(val < 42))
{
return Math.Pow(Math.Tan(val), 42.42);
}
else
{
return Math.Cos(val);
}
}
[TestCompiler(42)]
public static unsafe double CheckUnlikely(int val)
{
if (Unlikely(val < 42))
{
return Math.Pow(Math.Tan(val), 42.42);
}
else
{
return Math.Cos(val);
}
}
[TestCompiler(42)]
public static unsafe double CheckAssume(int val)
{
Assume(val >= 42);
if (val < 42)
{
return Math.Pow(Math.Tan(val), 42.42);
}
else
{
return Math.Cos(val);
}
}
[TestCompiler(0)]
[TestCompiler(1)]
public static int CheckLikelyMatches(int val)
{
var cond = val == 0;
return cond == Likely(cond) ? 1 : 0;
}
[TestCompiler(0)]
[TestCompiler(1)]
public static int CheckUnlikelyMatches(int val)
{
var cond = val == 0;
return cond == Unlikely(cond) ? 1 : 0;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fa0dd524a0c332f7948fb2cc410034b1
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,215 @@
using Burst.Compiler.IL.Tests.Helpers;
using System;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityBenchShared;
using static Unity.Burst.Intrinsics.Common;
namespace Burst.Compiler.IL.Tests
{
internal partial class IntrinsicsCommon
{
[TestCompiler]
public static int CheckBurstCompiler()
{
return BurstCompiler.IsEnabled ? 1 : 0;
}
[TestCompiler]
public static void CheckPause()
{
Pause();
}
public unsafe struct Buffer : IDisposable
{
public int* Data;
public int Length;
public void Dispose()
{
UnsafeUtility.Free(Data, Allocator.Persistent);
}
public class Provider : IArgumentProvider
{
public object Value
{
get
{
var length = 1024;
var data = (int*)UnsafeUtility.Malloc(sizeof(int) * length, UnsafeUtility.AlignOf<int>(), Allocator.Persistent);
for (var i = 0; i < length; i++)
{
data[i] = i;
}
return new Buffer { Data = data, Length = length };
}
}
}
}
#if BURST_INTERNAL || UNITY_BURST_EXPERIMENTAL_PREFETCH_INTRINSIC
[TestCompiler(typeof(Buffer.Provider))]
public static unsafe int CheckPrefetchReadNoTemporalLocality(ref Buffer buffer)
{
int total = 0;
for (int i = 0; i < buffer.Length; i++)
{
total += buffer.Data[i];
Prefetch(buffer.Data + i + 1, ReadWrite.Read, Locality.NoTemporalLocality);
}
return total;
}
[TestCompiler(typeof(Buffer.Provider))]
public static unsafe int CheckPrefetchReadLowTemporalLocality(ref Buffer buffer)
{
int total = 0;
for (int i = 0; i < buffer.Length; i++)
{
total += buffer.Data[i];
Prefetch(buffer.Data + i + 1, ReadWrite.Read, Locality.LowTemporalLocality);
}
return total;
}
[TestCompiler(typeof(Buffer.Provider))]
public static unsafe int CheckPrefetchReadModerateTemporalLocality(ref Buffer buffer)
{
int total = 0;
for (int i = 0; i < buffer.Length; i++)
{
total += buffer.Data[i];
Prefetch(buffer.Data + i + 1, ReadWrite.Read, Locality.ModerateTemporalLocality);
}
return total;
}
[TestCompiler(typeof(Buffer.Provider))]
public static unsafe int CheckPrefetchReadHighTemporalLocality(ref Buffer buffer)
{
int total = 0;
for (int i = 0; i < buffer.Length; i++)
{
total += buffer.Data[i];
Prefetch(buffer.Data + i + 1, ReadWrite.Read, Locality.HighTemporalLocality);
}
return total;
}
[TestCompiler(typeof(Buffer.Provider))]
public static unsafe void CheckPrefetchWriteNoTemporalLocality(ref Buffer buffer)
{
for (int i = 0; i < buffer.Length; i++)
{
buffer.Data[i] = i;
Prefetch(buffer.Data + i + 1, ReadWrite.Write, Locality.NoTemporalLocality);
}
}
[TestCompiler(typeof(Buffer.Provider))]
public static unsafe void CheckPrefetchWriteLowTemporalLocality(ref Buffer buffer)
{
for (int i = 0; i < buffer.Length; i++)
{
buffer.Data[i] = i;
Prefetch(buffer.Data + i + 1, ReadWrite.Write, Locality.LowTemporalLocality);
}
}
[TestCompiler(typeof(Buffer.Provider))]
public static unsafe void CheckPrefetchWriteModerateTemporalLocality(ref Buffer buffer)
{
for (int i = 0; i < buffer.Length; i++)
{
buffer.Data[i] = i;
Prefetch(buffer.Data + i + 1, ReadWrite.Write, Locality.ModerateTemporalLocality);
}
}
[TestCompiler(typeof(Buffer.Provider))]
public static unsafe void CheckPrefetchWriteHighTemporalLocality(ref Buffer buffer)
{
for (int i = 0; i < buffer.Length; i++)
{
buffer.Data[i] = i;
Prefetch(buffer.Data + i + 1, ReadWrite.Write, Locality.HighTemporalLocality);
}
}
#endif
[TestCompiler(typeof(ReturnBox), ulong.MaxValue, ulong.MaxValue)]
[TestCompiler(typeof(ReturnBox), ulong.MinValue, ulong.MaxValue)]
[TestCompiler(typeof(ReturnBox), ulong.MaxValue, ulong.MinValue)]
[TestCompiler(typeof(ReturnBox), ulong.MinValue, ulong.MinValue)]
[TestCompiler(typeof(ReturnBox), DataRange.Standard, DataRange.Standard)]
public static unsafe ulong Checkumul128(ulong* high, ulong x, ulong y)
{
var result = umul128(x, y, out var myHigh);
*high = myHigh;
return result;
}
#if BURST_INTERNAL || UNITY_BURST_EXPERIMENTAL_ATOMIC_INTRINSICS
[TestCompiler(42, 13)]
public static int CheckInterlockedAndInt(int x, int y)
{
InterlockedAnd(ref x, y);
return x;
}
[TestCompiler(42U, 13U)]
public static uint CheckInterlockedAndUint(uint x, uint y)
{
InterlockedAnd(ref x, y);
return x;
}
[TestCompiler(42L, 13L)]
public static long CheckInterlockedAndLong(long x, long y)
{
InterlockedAnd(ref x, y);
return x;
}
[TestCompiler(42UL, 13UL)]
public static ulong CheckInterlockedAndUlong(ulong x, ulong y)
{
InterlockedAnd(ref x, y);
return x;
}
[TestCompiler(42, 13)]
public static int CheckInterlockedOrInt(int x, int y)
{
InterlockedOr(ref x, y);
return x;
}
[TestCompiler(42U, 13U)]
public static uint CheckInterlockedOrUint(uint x, uint y)
{
InterlockedOr(ref x, y);
return x;
}
[TestCompiler(42L, 13L)]
public static long CheckInterlockedOrLong(long x, long y)
{
InterlockedOr(ref x, y);
return x;
}
[TestCompiler(42UL, 13UL)]
public static ulong CheckInterlockedOrUlong(ulong x, ulong y)
{
InterlockedOr(ref x, y);
return x;
}
#endif
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: df58129e92123044b15b889624e8868c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,302 @@
using System.Runtime.CompilerServices;
using Unity.Burst;
using Unity.Burst.CompilerServices;
namespace Burst.Compiler.IL.Tests
{
#if BURST_INTERNAL || UNITY_BURST_EXPERIMENTAL_LOOP_INTRINSICS
internal class LoopIntrinsics
{
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe void CheckExpectVectorizedImpl([NoAlias] int* a, [NoAlias] int* b, int count)
{
for (var i = 0; i < count; i++)
{
Loop.ExpectVectorized();
a[i] += b[i];
}
}
[TestCompiler(100, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
[OptimizationsOnly("Loops are not vectorized when optimizations are disabled")]
public static unsafe void CheckExpectVectorized(int count)
{
var a = stackalloc int[count];
var b = stackalloc int[count];
CheckExpectVectorizedImpl(a, b, count);
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
private static unsafe void CheckExpectVectorizedNoOptimizationsImpl([NoAlias] int* a, [NoAlias] int* b, int count)
{
for (var i = 0; i < count; i++)
{
Loop.ExpectVectorized();
a[i] += b[i];
}
}
[TestCompiler(100, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_LoopUnexpectedAutoVectorization, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
[OptimizationsOnly("Intrinsics are not evaluated when optimizations are disabled")]
public static unsafe void CheckExpectVectorizedNoOptimizations(int count)
{
var a = stackalloc int[count];
var b = stackalloc int[count];
CheckExpectVectorizedNoOptimizationsImpl(a, b, count);
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
private static unsafe void CheckExpectNotVectorizedNoOptimizationsImpl([NoAlias] int* a, [NoAlias] int* b, int count)
{
for (var i = 0; i < count; i++)
{
Loop.ExpectNotVectorized();
a[i] += b[i];
}
}
[TestCompiler(100, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
public static unsafe void CheckExpectNotVectorizedNoOptimizations(int count)
{
var a = stackalloc int[count];
var b = stackalloc int[count];
CheckExpectNotVectorizedNoOptimizationsImpl(a, b, count);
}
[MethodImpl(MethodImplOptions.NoOptimization)]
private static unsafe void CheckExpectVectorizedOptimizationsDisabledImpl([NoAlias] int* a, [NoAlias] int* b, int count)
{
for (var i = 0; i < count; i++)
{
Loop.ExpectVectorized();
a[i] += b[i];
}
}
[TestCompiler(100, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_LoopUnexpectedAutoVectorization, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
[OptimizationsOnly("We only validate loop intrinsics with optimizations enabled")]
public static unsafe void CheckExpectVectorizedOptimizationsDisabled(int count)
{
var a = stackalloc int[count];
var b = stackalloc int[count];
CheckExpectVectorizedOptimizationsDisabledImpl(a, b, count);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe void CheckExpectNotVectorizedImpl([NoAlias] int* a, [NoAlias] int* b, int count)
{
for (var i = 0; i < count; i++)
{
Loop.ExpectNotVectorized();
if (a[i] > b[i])
{
break;
}
a[i] += b[i];
}
}
[TestCompiler(100, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
public static unsafe void CheckExpectNotVectorized(int count)
{
var a = stackalloc int[count];
var b = stackalloc int[count];
CheckExpectNotVectorizedImpl(a, b, count);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe void CheckExpectVectorizedFailImpl([NoAlias] int* a, [NoAlias] int* b, int count)
{
for (var i = 0; i < count; i++)
{
Loop.ExpectVectorized();
if (a[i] > b[i])
{
break;
}
a[i] += b[i];
}
}
[TestCompiler(100, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_LoopUnexpectedAutoVectorization, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
[OptimizationsOnly("Intrinsics are not evaluated when optimizations are disabled")]
public static unsafe void CheckExpectVectorizedFail(int count)
{
var a = stackalloc int[count];
var b = stackalloc int[count];
CheckExpectVectorizedFailImpl(a, b, count);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe void CheckExpectNotVectorizedFailImpl([NoAlias] int* a, [NoAlias] int* b, int count)
{
for (var i = 0; i < count; i++)
{
Loop.ExpectNotVectorized();
a[i] += b[i];
}
}
[TestCompiler(100, ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_LoopUnexpectedAutoVectorization, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
[OptimizationsOnly("Loops are not vectorized when optimizations are disabled")]
public static unsafe void CheckExpectNotVectorizedFail(int count)
{
var a = stackalloc int[count];
var b = stackalloc int[count];
CheckExpectNotVectorizedFailImpl(a, b, count);
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_LoopIntrinsicMustBeCalledInsideLoop, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
[OptimizationsOnly("Intrinsics are not evaluated when optimizations are disabled")]
public static unsafe void CheckExpectVectorizedOutsideLoop()
{
Loop.ExpectVectorized();
}
[TestCompiler(ExpectCompilerException = true, ExpectedDiagnosticId = DiagnosticId.ERR_LoopIntrinsicMustBeCalledInsideLoop, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
[OptimizationsOnly("Intrinsics are not evaluated when optimizations are disabled")]
public static unsafe void CheckExpectNotVectorizedOutsideLoop()
{
Loop.ExpectNotVectorized();
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe void CheckExpectVectorizedMultipleCallsImpl([NoAlias] int* a, [NoAlias] int* b, int count)
{
for (var i = 0; i < count; i++)
{
Loop.ExpectVectorized();
a[i] += b[i];
Loop.ExpectVectorized();
}
}
[TestCompiler(100, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
[OptimizationsOnly("Loops are not vectorized when optimizations are disabled")]
public static unsafe void CheckExpectVectorizedMultipleCalls(int count)
{
var a = stackalloc int[count];
var b = stackalloc int[count];
CheckExpectVectorizedMultipleCallsImpl(a, b, count);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe void CheckExpectVectorizedUnrolledLoopImpl([NoAlias] int* a, [NoAlias] int* b)
{
for (var i = 0; i < 4; i++)
{
Loop.ExpectVectorized();
if (a[i] > b[i])
{
a[i] += b[i];
}
}
}
[TestCompiler(100, ExpectedDiagnosticId = DiagnosticId.WRN_LoopIntrinsicCalledButLoopOptimizedAway, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
[OptimizationsOnly("Loops are not vectorized when optimizations are disabled")]
public static unsafe void CheckExpectVectorizedUnrolledLoop(int count)
{
var a = stackalloc int[count];
var b = stackalloc int[count];
CheckExpectVectorizedUnrolledLoopImpl(a, b);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe int CheckExpectVectorizedPartiallyUnrolledLoopImpl(int* a, int count)
{
var sum = 0;
for (var i = 0; i < count; i++)
{
Loop.ExpectVectorized();
sum += a[i];
}
return sum;
}
[TestCompiler(100, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
[OptimizationsOnly("Loops are not vectorized when optimizations are disabled")]
public static unsafe int CheckExpectVectorizedPartiallyUnrolledLoop(int count)
{
var a = stackalloc int[count];
a[0] = 8;
a[10] = 16;
return CheckExpectVectorizedPartiallyUnrolledLoopImpl(a, count);
}
[TestCompiler(100, ExpectedDiagnosticId = DiagnosticId.WRN_LoopIntrinsicCalledButLoopOptimizedAway, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
[OptimizationsOnly("Loops are not vectorized when optimizations are disabled")]
public static unsafe void CheckExpectVectorizedRemovedLoop(int count)
{
for (var i = 0; i < count; i++)
{
Loop.ExpectVectorized();
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static unsafe void CheckExpectVectorizedNestedImpl(
[NoAlias] int* a, [NoAlias] int* b,
[NoAlias] int* c, [NoAlias] int* d,
int count)
{
for (var i = 0; i < count; i++)
{
Loop.ExpectNotVectorized();
if (a[i] > b[i])
{
break;
}
a[i] += b[i];
for (var j = i; j < count; j++)
{
Loop.ExpectVectorized();
c[j] += d[j];
}
}
}
[TestCompiler(100, IgnoreOnPlatform = Backend.TargetPlatform.Wasm)]
[OptimizationsOnly("Loops are not vectorized when optimizations are disabled")]
public static unsafe void CheckExpectVectorizedNested(int count)
{
var a = stackalloc int[count];
var b = stackalloc int[count];
var c = stackalloc int[count];
var d = stackalloc int[count];
CheckExpectVectorizedNestedImpl(a, b, c, d, count);
}
}
#endif
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1d871bf5a85e3baaa304966c127e87a7
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,279 @@
using Burst.Compiler.IL.Tests.Helpers;
using NUnit.Framework;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
internal partial class VectorsBinOpFloat2
{
[TestCompiler]
public static float Add()
{
var left = new float2(1.0f);
var right = new float2(1.0f, 2.0f);
var result = left + right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float AddFloatRight()
{
var left = new float2(1.0f);
var right = 2.0f;
var result = left + right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float AddFloatLeft()
{
var left = 2.0f;
var right = new float2(1.0f);
var result = left + right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float AddByArgs(ref float2 left, ref float2 right)
{
var result = left + right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Sub()
{
var left = new float2(1.0f);
var right = new float2(1.0f, 2.0f);
var result = left - right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float SubFloatLeft()
{
var left = 2.0f;
var right = new float2(1.0f, 2.0f);
var result = left - right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float SubFloatRight()
{
var left = new float2(1.0f, 2.0f);
var right = 2.0f;
var result = left - right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float SubByArgs(ref float2 left, ref float2 right)
{
var result = left - right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Mul()
{
var left = new float2(2.0f, 1.0f);
var right = new float2(1.0f, 2.0f);
var result = left * right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float MulFloatLeft()
{
var left = 2.0f;
var right = new float2(1.0f, 2.0f);
var result = left * right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float MulFloatRight()
{
var left = new float2(1.0f, 2.0f);
var right = 2.0f;
var result = left * right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float MulByArgs(ref float2 left, ref float2 right)
{
var result = left * right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Div()
{
var left = new float2(1.0f, 2.0f);
var right = new float2(2.0f, 1.0f);
var result = left / right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float DivFloatLeft()
{
var left = 15.0f;
var right = new float2(2.0f, 1.0f);
var result = left / right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float DivFloatRight()
{
var left = new float2(2.0f, 1.0f);
var right = 15.0f;
var result = left / right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float DivByArgs(ref float2 left, ref float2 right)
{
var result = left / right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Mod()
{
var left = new float2(1.0f, 2.0f);
var right = new float2(2.0f, 1.0f);
var result = left % right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float ModFloatLeft()
{
var left = 15.0f;
var right = new float2(2.0f, 1.0f);
var result = left % right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float ModFloatRight()
{
var left = new float2(2.0f, 1.0f);
var right = 15.0f;
var result = left % right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float ModByArgs(ref float2 left, ref float2 right)
{
var result = left % right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Neg()
{
var left = new float2(1.0f, 2.0f);
return Vectors.ConvertToFloat((-left));
}
[TestCompiler]
public static float Positive()
{
var left = new float2(1.0f, 2.0f);
return Vectors.ConvertToFloat((+left));
}
// Comparisons
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Equality(float a, float b)
{
return Vectors.ConvertToInt((new float2(a) == new float2(b)));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int EqualityFloat2(ref float2 a, ref float2 b)
{
return Vectors.ConvertToInt((a == b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Inequality(float a, float b)
{
return Vectors.ConvertToInt((new float2(a) != new float2(b)));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int InequalityFloat2(ref float2 a, ref float2 b)
{
return Vectors.ConvertToInt((a != b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThan(float a, float b)
{
return Vectors.ConvertToInt((new float2(a) > new float2(b)));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanFloat2(ref float2 a, ref float2 b)
{
return Vectors.ConvertToInt((a > b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanOrEqual(float a, float b)
{
return Vectors.ConvertToInt((new float2(a) >= new float2(b)));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanOrEqualFloat2(ref float2 a, ref float2 b)
{
return Vectors.ConvertToInt((a >= b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThan(float a, float b)
{
return Vectors.ConvertToInt((new float2(a) < new float2(b)));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanFloat2(ref float2 a, ref float2 b)
{
return Vectors.ConvertToInt((a < b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanOrEqual(float a, float b)
{
return Vectors.ConvertToInt((new float2(a) <= new float2(b)));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanOrEqualFloat2(ref float2 a, ref float2 b)
{
return Vectors.ConvertToInt((a <= b));
}
[TestCompiler(DataRange.Standard)]
public static float ImplicitFloat(float a)
{
// Let float -> float2 implicit conversion
return Vectors.ConvertToFloat((float2) a);
}
[TestCompiler(DataRange.Standard)]
public static float ImplicitInt4(ref int4 a)
{
// Let int4 -> float2 implicit conversion
return Vectors.ConvertToFloat(a);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8826f823d5c0312faae224801c9e8bd3
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,279 @@
using Burst.Compiler.IL.Tests.Helpers;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
internal partial class VectorsBinOpFloat3
{
[TestCompiler]
public static float Add()
{
var left = new float3(1.0f);
var right = new float3(1.0f, 2.0f, 3.0f);
var result = left + right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float AddFloatRight()
{
var left = new float3(1.0f);
var right = 2.0f;
var result = left + right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float AddFloatLeft()
{
var left = 2.0f;
var right = new float3(1.0f);
var result = left + right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float AddByArgs(ref float3 left, ref float3 right)
{
var result = left + right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Sub()
{
var left = new float3(1.0f);
var right = new float3(1.0f, 2.0f, 3.0f);
var result = left - right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float SubFloatLeft()
{
var left = 2.0f;
var right = new float3(1.0f, 2.0f, 3.0f);
var result = left - right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float SubFloatRight()
{
var left = new float3(1.0f, 2.0f, 3.0f);
var right = 2.0f;
var result = left - right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float SubByArgs(ref float3 left, ref float3 right)
{
var result = left - right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Mul()
{
var left = new float3(2.0f, 1.0f, 3.0f);
var right = new float3(1.0f, 2.0f, 3.0f);
var result = left * right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float MulFloatLeft()
{
var left = 2.0f;
var right = new float3(1.0f, 2.0f, 3.0f);
var result = left * right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float MulFloatRight()
{
var left = new float3(1.0f, 2.0f, 3.0f);
var right = 2.0f;
var result = left * right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float MulByArgs(ref float3 left, ref float3 right)
{
var result = left * right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Div()
{
var left = new float3(1.0f, 2.0f, 3.0f);
var right = new float3(2.0f, 1.0f, 3.0f);
var result = left / right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float DivFloatLeft()
{
var left = 15.0f;
var right = new float3(2.0f, 1.0f, 3.0f);
var result = left / right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float DivFloatRight()
{
var left = new float3(2.0f, 1.0f, 3.0f);
var right = 15.0f;
var result = left / right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float DivByArgs(ref float3 left, ref float3 right)
{
var result = left / right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Mod()
{
var left = new float3(1.0f, 2.0f, 3.0f);
var right = new float3(2.0f, 1.0f, 3.0f);
var result = left % right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float ModFloatLeft()
{
var left = 15.0f;
var right = new float3(2.0f, 1.0f, 3.0f);
var result = left % right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float ModFloatRight()
{
var left = new float3(2.0f, 1.0f, 3.0f);
var right = 15.0f;
var result = left % right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float ModByArgs(ref float3 left, ref float3 right)
{
var result = left % right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Neg()
{
var left = new float3(1.0f, 2.0f, 3.0f);
return Vectors.ConvertToFloat((-left));
}
[TestCompiler]
public static float Positive()
{
var left = new float3(1.0f, 2.0f, 3.0f);
return Vectors.ConvertToFloat((+left));
}
// Comparisons
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Equality(float a, float b)
{
return Vectors.ConvertToInt((new float3(a) == new float3(b)));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int EqualityFloat3(ref float3 a, ref float3 b)
{
return Vectors.ConvertToInt((a == b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Inequality(float a, float b)
{
return Vectors.ConvertToInt((new float3(a) != new float3(b)));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int InequalityFloat3(ref float3 a, ref float3 b)
{
return Vectors.ConvertToInt((a != b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThan(float a, float b)
{
return Vectors.ConvertToInt((new float3(a) > new float3(b)));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanFloat3(ref float3 a, ref float3 b)
{
return Vectors.ConvertToInt((a > b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanOrEqual(float a, float b)
{
return Vectors.ConvertToInt((new float3(a) >= new float3(b)));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanOrEqualFloat3(ref float3 a, ref float3 b)
{
return Vectors.ConvertToInt((a >= b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThan(float a, float b)
{
return Vectors.ConvertToInt((new float3(a) < new float3(b)));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanFloat3(ref float3 a, ref float3 b)
{
return Vectors.ConvertToInt((a < b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanOrEqual(float a, float b)
{
return Vectors.ConvertToInt((new float3(a) <= new float3(b)));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanOrEqualFloat3(ref float3 a, ref float3 b)
{
return Vectors.ConvertToInt((a <= b));
}
[TestCompiler(DataRange.Standard)]
public static float ImplicitFloat(float a)
{
// Let float -> float3 implicit conversion
return Vectors.ConvertToFloat((float3)a);
}
[TestCompiler(DataRange.Standard)]
public static float ImplicitInt4(ref int4 a)
{
// Let int4 -> float3 implicit conversion
return Vectors.ConvertToFloat(a);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4784d45bc93937ca93dc6578b3e58fc2
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,308 @@
using Burst.Compiler.IL.Tests.Helpers;
using NUnit.Framework;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
internal partial class VectorsBinOpFloat4
{
[TestCompiler]
public static float Add()
{
var left = new float4(1.0f);
var right = new float4(1.0f, 2.0f, 3.0f, 4.0f);
var result = left + right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float AddFloatRight()
{
var left = new float4(1.0f);
var right = 2.0f;
var result = left + right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float AddFloatLeft()
{
var left = 2.0f;
var right = new float4(1.0f);
var result = left + right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float AddByArgs(ref float4 left, ref float4 right)
{
var result = left + right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Sub()
{
var left = new float4(1.0f);
var right = new float4(1.0f, 2.0f, 3.0f, 4.0f);
var result = left - right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float SubFloatLeft()
{
var left = 2.0f;
var right = new float4(1.0f, 2.0f, 3.0f, 4.0f);
var result = left - right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float SubFloatRight()
{
var left = new float4(1.0f, 2.0f, 3.0f, 4.0f);
var right = 2.0f;
var result = left - right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float SubByArgs(ref float4 left, ref float4 right)
{
var result = left - right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Mul()
{
var left = new float4(2.0f, 1.0f, 3.0f, 5.0f);
var right = new float4(1.0f, 2.0f, 3.0f, 4.0f);
var result = left * right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float MulFloatLeft()
{
var left = 2.0f;
var right = new float4(1.0f, 2.0f, 3.0f, 4.0f);
var result = left * right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float MulFloatRight()
{
var left = new float4(1.0f, 2.0f, 3.0f, 4.0f);
var right = 2.0f;
var result = left * right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float MulByArgs(ref float4 left, ref float4 right)
{
var result = left * right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Div()
{
var left = new float4(1.0f, 2.0f, 3.0f, 4.0f);
var right = new float4(2.0f, 1.0f, 3.0f, 5.0f);
var result = left / right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float DivFloatLeft()
{
var left = 15.0f;
var right = new float4(2.0f, 1.0f, 3.0f, 5.0f);
var result = left / right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float DivFloatRight()
{
var left = new float4(2.0f, 1.0f, 3.0f, 5.0f);
var right = 15.0f;
var result = left / right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float DivByArgs(ref float4 left, ref float4 right)
{
var result = left / right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Mod()
{
var left = new float4(1.0f, 2.0f, 3.0f, 4.0f);
var right = new float4(2.0f, 1.0f, 3.0f, 5.0f);
var result = left % right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float ModFloatLeft()
{
var left = 15.0f;
var right = new float4(2.0f, 1.0f, 3.0f, 5.0f);
var result = left % right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float ModFloatRight()
{
var left = new float4(2.0f, 1.0f, 3.0f, 5.0f);
var right = 15.0f;
var result = left % right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static float ModByArgs(ref float4 left, ref float4 right)
{
var result = left % right;
return Vectors.ConvertToFloat(result);
}
[TestCompiler]
public static float Neg()
{
var left = new float4(1.0f, 2.0f, 3.0f, 4.0f);
return Vectors.ConvertToFloat((-left));
}
[TestCompiler]
public static float Positive()
{
var left = new float4(1.0f, 2.0f, 3.0f, 4.0f);
return Vectors.ConvertToFloat((+left));
}
// Comparisons
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Equality(float a, float b)
{
return Vectors.ConvertToInt(new float4(a) == new float4(b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int EqualityFloat4(ref float4 a, ref float4 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Inequality(float a, float b)
{
return Vectors.ConvertToInt(new float4(a) != new float4(b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int InequalityFloat4(ref float4 a, ref float4 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThan(float a, float b)
{
return Vectors.ConvertToInt(new float4(a) > new float4(b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanFloat4(ref float4 a, ref float4 b)
{
return Vectors.ConvertToInt(a > b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanFloat4Float(ref float4 a, float b)
{
return Vectors.ConvertToInt(a > b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static unsafe bool GreaterThanFloat4FloatUnsafe(ref float4 a, float b)
{
float4 x = a;
float4* start = &x;
int axis = 0;
return CompareViaIndexer(start, axis, b);
}
private static unsafe bool CompareViaIndexer(float4* start, int axis, float b)
{
float4 copy = *start;
return copy[axis] >= b;
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanOrEqual(float a, float b)
{
return Vectors.ConvertToInt(new float4(a) >= new float4(b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanOrEqualFloat4(ref float4 a, ref float4 b)
{
return Vectors.ConvertToInt(a >= b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThan(float a, float b)
{
return Vectors.ConvertToInt(new float4(a) < new float4(b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanFloat4(ref float4 a, ref float4 b)
{
return Vectors.ConvertToInt(a < b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanFloat4Float(ref float4 a, float b)
{
return Vectors.ConvertToInt(a < b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanOrEqual(float a, float b)
{
return Vectors.ConvertToInt(new float4(a) <= new float4(b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanOrEqualFloat4(ref float4 a, ref float4 b)
{
return Vectors.ConvertToInt(a <= b);
}
[TestCompiler(DataRange.Standard)]
public static float ImplicitFloat(float a)
{
// Let float -> float4 implicit conversion
return Vectors.ConvertToFloat((float4) a);
}
[TestCompiler(DataRange.Standard)]
public static float ImplicitInt4(ref int4 a)
{
// Let int4 -> float4 implicit conversion
return Vectors.ConvertToFloat(a);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dbb95f4d93ed32938db073fd04c6e1fd
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,290 @@
using System;
using Burst.Compiler.IL.Tests.Helpers;
using NUnit.Framework;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
internal partial class VectorsBinOpInt4
{
[TestCompiler]
public static int Add()
{
var left = new int4(1);
var right = new int4(1, 2, 3, 4);
var result = left + right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int AddIntRight()
{
var left = new int4(1);
var right = 2;
var result = left + right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int AddIntLeft()
{
var left = 2;
var right = new int4(1);
var result = left + right;
return Vectors.ConvertToInt(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int AddByArgs(ref int4 left, ref int4 right)
{
var result = left + right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int Sub()
{
var left = new int4(1);
var right = new int4(1, 2, 3, 4);
var result = left - right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int SubIntLeft()
{
var left = 2;
var right = new int4(1, 2, 3, 4);
var result = left - right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int SubIntRight()
{
var left = new int4(1, 2, 3, 4);
var right = 2;
var result = left - right;
return Vectors.ConvertToInt(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int SubByArgs(ref int4 left, ref int4 right)
{
var result = left - right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int Mul()
{
var left = new int4(2, 1, 3, 5);
var right = new int4(1, 2, 3, 4);
var result = left * right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int MulIntLeft()
{
var left = 2;
var right = new int4(1, 2, 3, 4);
var result = left * right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int MulIntRight()
{
var left = new int4(1, 2, 3, 4);
var right = 2;
var result = left * right;
return Vectors.ConvertToInt(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int MulByArgs(ref int4 left, ref int4 right)
{
var result = left * right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int Div()
{
var left = new int4(1, 2, 3, 4);
var right = new int4(2, 1, 3, 5);
var result = left / right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int DivIntLeft()
{
var left = 15;
var right = new int4(2, 1, 3, 5);
var result = left / right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int DivIntRight()
{
var left = new int4(2, 1, 3, 5);
var right = 15;
var result = left / right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int LeftShift()
{
var left = new int4(2, 1, 3, 5);
var right = 15;
var result = left << right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int RightShift()
{
var left = new int4(2, -17, 3, Int32.MinValue);
var right = 31;
var result = left >> right;
return Vectors.ConvertToInt(result);
}
[TestCompiler(DataRange.Standard, DataRange.Standard & ~DataRange.Zero)]
public static int DivByArgs(ref int4 left, ref int4 right)
{
var result = left / right;
return Vectors.ConvertToInt(result);
}
[TestCompiler]
public static int Neg()
{
var left = new int4(1, 2, 3, 4);
return Vectors.ConvertToInt((-left));
}
[TestCompiler]
public static int Positive()
{
var left = new int4(1, 2, 3, 4);
return Vectors.ConvertToInt((+left));
}
// Comparisons
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Equality(int a, int b)
{
return Vectors.ConvertToInt(new int4(a) == new int4(b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int EqualityInt4(ref int4 a, ref int4 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Inequality(int a, int b)
{
return Vectors.ConvertToInt(new int4(a) != new int4(b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int InequalityInt4(ref int4 a, ref int4 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThan(int a, int b)
{
return Vectors.ConvertToInt(new int4(a) > new int4(b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanInt4(ref int4 a, ref int4 b)
{
return Vectors.ConvertToInt(a > b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanOrEqual(int a, int b)
{
return Vectors.ConvertToInt(new int4(a) >= new int4(b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int GreaterThanOrEqualInt4(ref int4 a, ref int4 b)
{
return Vectors.ConvertToInt(a >= b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThan(int a, int b)
{
return Vectors.ConvertToInt(new int4(a) < new int4(b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanInt4(ref int4 a, ref int4 b)
{
return Vectors.ConvertToInt(a < b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanOrEqual(int a, int b)
{
return Vectors.ConvertToInt(new int4(a) <= new int4(b));
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int LessThanOrEqualInt4(ref int4 a, ref int4 b)
{
return Vectors.ConvertToInt(a <= b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int And(ref int4 a, ref int4 b)
{
return Vectors.ConvertToInt(a & b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Or(ref int4 a, ref int4 b)
{
return Vectors.ConvertToInt(a | b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Xor(ref int4 a, ref int4 b)
{
return Vectors.ConvertToInt(a ^ b);
}
[TestCompiler(DataRange.Standard)]
public static int ImplicitBitwiseNot(int a)
{
// Let int -> int4 implicit conversion
return Vectors.ConvertToInt(~(int4) a);
}
[TestCompiler(DataRange.Standard)]
public static int ImplicitInt(int a)
{
// Let int -> int4 implicit conversion
return Vectors.ConvertToInt((int4) a);
}
[TestCompiler(DataRange.Standard)]
public static int ImplicitInt4(ref int4 a)
{
// Let int4 -> int4 implicit conversion
return Vectors.ConvertToInt(a);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e07174e0c0ba3d269ad0936f514c3409
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,30 @@
using Burst.Compiler.IL.Tests.Helpers;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
internal partial class VectorsBools
{
// ---------------------------------------------------
// ! operator
// ---------------------------------------------------
[TestCompiler(DataRange.Standard)]
public static int Bool4Not(ref bool4 a)
{
return Vectors.ConvertToInt(!a);
}
[TestCompiler(DataRange.Standard)]
public static int Bool3Not(ref bool3 a)
{
return Vectors.ConvertToInt(!a);
}
[TestCompiler(DataRange.Standard)]
public static int Bool2Not(ref bool2 a)
{
return Vectors.ConvertToInt(!a);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: afa4d597c8db399ab071dfe6a3096516
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,441 @@
using Burst.Compiler.IL.Tests.Helpers;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
internal partial class VectorsConstructors
{
// ---------------------------------------------------
// float4
// ---------------------------------------------------
[TestCompiler(DataRange.Standard)]
public static float Float4Int(int a)
{
return Vectors.ConvertToFloat(new float4(a));
}
[TestCompiler(DataRange.Standard)]
public static float Float4Float3Float(float x)
{
return Vectors.ConvertToFloat(new float4(new float3(x), 5.0f));
}
[TestCompiler(DataRange.Standard)]
public static float Float4Float2Float2(float x)
{
return Vectors.ConvertToFloat(new float4(new float2(x), new float2(5.0f)));
}
[TestCompiler(DataRange.Standard)]
public static float Float44Floats(float a)
{
return Vectors.ConvertToFloat(new float4(1.0f, 2.0f, 3.0f + a, 4.0f));
}
[TestCompiler(DataRange.Standard)]
public static float Float4Float(float a)
{
return Vectors.ConvertToFloat(new float4(a));
}
[TestCompiler(DataRange.Standard)]
public static float Float4Int4(ref int4 a)
{
return Vectors.ConvertToFloat((float4) new float4(a).x);
}
[TestCompiler(DataRange.Standard)]
public static float Float4Half(float a)
{
var h = new half(a);
return Vectors.ConvertToFloat((float4)new float4(h).x);
}
[TestCompiler(DataRange.Standard)]
public static float Float4Half4(ref float4 a)
{
var h = new half4(a);
return Vectors.ConvertToFloat((float4)new float4(h).x);
}
[TestCompiler(DataRange.Standard)]
public static float Float4HalfExplicit(float a)
{
return Vectors.ConvertToFloat((float4) new half(a));
}
[TestCompiler(DataRange.Standard)]
public static float Float4HalfImplicit(float a)
{
float4 x =new half(a);
return Vectors.ConvertToFloat(x);
}
// ---------------------------------------------------
// float3
// ---------------------------------------------------
[TestCompiler(DataRange.Standard)]
public static float Float3Int(int a)
{
return Vectors.ConvertToFloat(new float3(a));
}
[TestCompiler(DataRange.Standard)]
public static float Float33Floats(float a)
{
return Vectors.ConvertToFloat(new float3(1.0f, 2.0f, 3.0f + a));
}
[TestCompiler(DataRange.Standard)]
public static float Float3Float(float a)
{
return Vectors.ConvertToFloat(new float3(a));
}
[TestCompiler(DataRange.Standard)]
public static float Float3Float2Float(float a)
{
return Vectors.ConvertToFloat(new float3(new float2(a), 5.0f));
}
[TestCompiler(DataRange.Standard)]
public static float Float3Half(float a)
{
var h = new half(a);
return Vectors.ConvertToFloat((float3)new float3(h).x);
}
[TestCompiler(DataRange.Standard)]
public static float Float3Half3(ref float3 a)
{
var h = new half3(a);
return Vectors.ConvertToFloat((float3)new float3(h).x);
}
// ---------------------------------------------------
// float2
// ---------------------------------------------------
[TestCompiler(DataRange.Standard)]
public static float Float2Int(int a)
{
return Vectors.ConvertToFloat(new float2(a));
}
[TestCompiler(DataRange.Standard)]
public static float Float22Floats(float a)
{
return Vectors.ConvertToFloat(new float2(1.0f, 3.0f + a));
}
[TestCompiler(DataRange.Standard)]
public static float Float2Float(float a)
{
return Vectors.ConvertToFloat(new float2(a));
}
[TestCompiler(DataRange.Standard)]
public static float Float2Half(float a)
{
var h = new half(a);
return Vectors.ConvertToFloat((float2)new float2(h).x);
}
[TestCompiler(DataRange.Standard)]
public static float Float2Half2(ref float2 a)
{
var h = new half2(a);
return Vectors.ConvertToFloat((float2)new float2(h).x);
}
// ---------------------------------------------------
// int4
// ---------------------------------------------------
[TestCompiler(DataRange.Standard)]
public static int Int4Int(int a)
{
return Vectors.ConvertToInt(new int4(a));
}
[TestCompiler(DataRange.Standard)]
public static int Int4Int3Int(int x)
{
return Vectors.ConvertToInt(new int4(new int3(x), 5));
}
[TestCompiler(DataRange.Standard)]
public static int Int44Ints(int a)
{
return Vectors.ConvertToInt(new int4(1, 2, 3 + a, 4));
}
// ---------------------------------------------------
// int3
// ---------------------------------------------------
[TestCompiler(DataRange.Standard)]
public static int Int3Int(int a)
{
return Vectors.ConvertToInt(new int3(a));
}
[TestCompiler(DataRange.Standard)]
public static int Int33Ints(int a)
{
return Vectors.ConvertToInt(new int3(1, 2, 3 + a));
}
[TestCompiler(DataRange.Standard)]
public static int Int3Int2Int(int a)
{
return Vectors.ConvertToInt(new int3(new int2(a), 5));
}
// ---------------------------------------------------
// int2
// ---------------------------------------------------
[TestCompiler(DataRange.Standard)]
public static int Int2Int(int a)
{
return Vectors.ConvertToInt(new int2(a));
}
[TestCompiler(DataRange.Standard)]
public static int Int22Ints(int a)
{
return Vectors.ConvertToInt(new int2(1, 3 + a));
}
// ---------------------------------------------------
// bool4
// ---------------------------------------------------
[TestCompiler(true)]
[TestCompiler(false)]
public static int Bool4(bool a)
{
return Vectors.ConvertToInt(new bool4(a));
}
[TestCompiler(true)]
[TestCompiler(false)]
public static int Bool4Bool3(bool x)
{
return Vectors.ConvertToInt(new bool4(new bool3(x), true));
}
[TestCompiler(false, false, false, false)]
[TestCompiler(true, false, false, false)]
[TestCompiler(false, true, false, false)]
[TestCompiler(false, false, true, false)]
[TestCompiler(false, false, false, true)]
public static int Bool44Bools(bool a, bool b, bool c, bool d)
{
return Vectors.ConvertToInt(new bool4(a, b, c, d));
}
// ---------------------------------------------------
// bool3
// ---------------------------------------------------
[TestCompiler(true)]
[TestCompiler(false)]
public static int Bool3(bool a)
{
return Vectors.ConvertToInt(new bool3(a));
}
[TestCompiler(true)]
[TestCompiler(false)]
public static int Bool3Bool2(bool a)
{
return Vectors.ConvertToInt(new bool3(new bool2(a), true));
}
[TestCompiler(false, false, false)]
[TestCompiler(true, false, false)]
[TestCompiler(false, true, false)]
[TestCompiler(false, false, true)]
public static int Bool33Bools(bool a, bool b, bool c)
{
return Vectors.ConvertToInt(new bool3(a, b, c));
}
// ---------------------------------------------------
// bool2
// ---------------------------------------------------
[TestCompiler(true)]
[TestCompiler(false)]
public static int Bool2(bool a)
{
return Vectors.ConvertToInt(new bool2(a));
}
[TestCompiler(true, false)]
[TestCompiler(false, false)]
[TestCompiler(false, true)]
public static int Bool22Ints(bool a, bool b)
{
return Vectors.ConvertToInt(new bool2(a, b));
}
// ---------------------------------------------------
// double4
// ---------------------------------------------------
[TestCompiler(DataRange.Standard)]
public static double Double4Int(int a)
{
return Vectors.ConvertToDouble(new double4(a));
}
[TestCompiler(DataRange.Standard)]
public static double Double4Double3Double(double x)
{
return Vectors.ConvertToDouble(new double4(new double3(x), 5.0f));
}
[TestCompiler(DataRange.Standard)]
public static double Double4Double2Double2(double x)
{
return Vectors.ConvertToDouble(new double4(new double2(x), new double2(5.0f)));
}
[TestCompiler(DataRange.Standard)]
public static double Double44Doubles(double a)
{
return Vectors.ConvertToDouble(new double4(1.0f, 2.0f, 3.0f + a, 4.0f));
}
[TestCompiler(DataRange.Standard)]
public static double Double4Double(double a)
{
return Vectors.ConvertToDouble(new double4(a));
}
[TestCompiler(DataRange.Standard)]
public static double Double4Int4(ref int4 a)
{
return Vectors.ConvertToDouble((double4)new double4(a).x);
}
[TestCompiler(DataRange.Standard)]
public static double Double4Half(double a)
{
var h = new half(a);
return Vectors.ConvertToDouble((double4)new double4(h).x);
}
[TestCompiler(DataRange.Standard)]
public static double Double4Half4(ref double4 a)
{
var h = new half4(a);
return Vectors.ConvertToDouble((double4)new double4(h).x);
}
// ---------------------------------------------------
// double3
// ---------------------------------------------------
[TestCompiler(DataRange.Standard)]
public static double Double3Int(int a)
{
return Vectors.ConvertToDouble(new double3(a));
}
[TestCompiler(DataRange.Standard)]
public static double Double33Doubles(double a)
{
return Vectors.ConvertToDouble(new double3(1.0f, 2.0f, 3.0f + a));
}
[TestCompiler(DataRange.Standard)]
public static double Double3Double(double a)
{
return Vectors.ConvertToDouble(new double3(a));
}
[TestCompiler(DataRange.Standard)]
public static double Double3Double2Double(double a)
{
return Vectors.ConvertToDouble(new double3(new double2(a), 5.0f));
}
[TestCompiler(DataRange.Standard)]
public static double Double3Half(double a)
{
var h = new half(a);
return Vectors.ConvertToDouble((double3)new double3(h).x);
}
[TestCompiler(DataRange.Standard)]
public static double Double3Half3(ref double3 a)
{
var h = new half3(a);
return Vectors.ConvertToDouble((double3)new double3(h).x);
}
// ---------------------------------------------------
// double2
// ---------------------------------------------------
[TestCompiler(DataRange.Standard)]
public static double Double2Int(int a)
{
return Vectors.ConvertToDouble(new double2(a));
}
[TestCompiler(DataRange.Standard)]
public static double Double22Doubles(double a)
{
return Vectors.ConvertToDouble(new double2(1.0f, 3.0f + a));
}
[TestCompiler(DataRange.Standard)]
public static double Double2Double(double a)
{
return Vectors.ConvertToDouble(new double2(a));
}
[TestCompiler(DataRange.Standard)]
public static double Double2Half(double a)
{
var h = new half(a);
return Vectors.ConvertToDouble((double2)new double2(h).x);
}
[TestCompiler(DataRange.Standard)]
public static double Double2Half2(ref double2 a)
{
var h = new half2(a);
return Vectors.ConvertToDouble((double2)new double2(h).x);
}
[TestCompiler(uint.MaxValue, uint.MaxValue / 2 + 1)]
public static float Float2UInt2(uint a, uint b)
{
return Vectors.ConvertToFloat(new float2(new uint2(a, b)));
}
[TestCompiler(uint.MaxValue, uint.MaxValue / 2 + 1)]
public static float Float4UIntUIntUInt2Implicit(uint a, uint b)
{
var u = new uint2(a, b);
return Vectors.ConvertToFloat(new float4(a, b, u));
}
[TestCompiler(uint.MaxValue, uint.MaxValue / 2 + 1)]
public static float Float4UIntUIntUInt2Explicit(uint a, uint b)
{
var u = new uint2(a, b);
return Vectors.ConvertToFloat(new float4(a, b, (float2) u));
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6a2963e730253fb7bc1f496becab35d1
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,49 @@
using Burst.Compiler.IL.Tests.Helpers;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
internal partial class VectorsDoubles
{
// ---------------------------------------------------
// double4
// ---------------------------------------------------
[TestCompiler(DataRange.Standard)]
public static double Double4Int(int a)
{
return Vectors.ConvertToDouble(new double4(a));
}
[TestCompiler(DataRange.Standard)]
public static double Double4Double3Double(double x)
{
return Vectors.ConvertToDouble(new double4(new double3(x), 5.0f));
}
[TestCompiler(DataRange.Standard)]
public static double Double4Double2Double2(double x)
{
return Vectors.ConvertToDouble(new double4(new double2(x), new double2(5.0f)));
}
[TestCompiler(DataRange.Standard)]
public static double Double44Doubles(double a)
{
return Vectors.ConvertToDouble(new double4(1.0f, 2.0f, 3.0f + a, 4.0f));
}
[TestCompiler(DataRange.Standard)]
public static double Double4Double(double a)
{
return Vectors.ConvertToDouble(new double4(a));
}
[TestCompiler(DataRange.Standard)]
public static double Double4Int4(ref int4 a)
{
return Vectors.ConvertToDouble(new double4(a));
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 93aa22b749c8358d8368db9527996503
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,384 @@
using Burst.Compiler.IL.Tests.Helpers;
using NUnit.Framework;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
[TestFixture]
internal partial class VectorsEquality
{
// Float4
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static bool Float4Equals(ref float4 a, ref float4 b)
{
return a.Equals(b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Float4Equality(ref float4 a, ref float4 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Float4Inequality(ref float4 a, ref float4 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Float4EqualityWithFloat(ref float4 a, float b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Float4InequalityWithFloat(ref float4 a, float b)
{
return Vectors.ConvertToInt(a != b);
}
// Float3
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static bool Float3Equals(ref float3 a, ref float3 b)
{
return a.Equals(b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Float3Equality(ref float3 a, ref float3 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Float3Inequality(ref float3 a, ref float3 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Float3EqualityWithFloat(ref float3 a, float b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Float3InequalityWithFloat(ref float3 a, float b)
{
return Vectors.ConvertToInt(a != b);
}
// Float2
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static bool Float2Equals(ref float2 a, ref float2 b)
{
return a.Equals(b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Float2Equality(ref float2 a, ref float2 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Float2Inequality(ref float2 a, ref float2 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Float2EqualityWithFloat(ref float2 a, float b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Float2InequalityWithFloat(ref float2 a, float b)
{
return Vectors.ConvertToInt(a != b);
}
// Int4
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static bool Int4Equals(ref int4 a, ref int4 b)
{
return a.Equals(b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Int4Equality(ref int4 a, ref int4 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Int4Inequality(ref int4 a, ref int4 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Int4EqualityWithScalar(ref int4 a, int b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Int4InequalityWithScalar(ref int4 a, int b)
{
return Vectors.ConvertToInt(a != b);
}
// Int3
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static bool Int3Equals(ref int3 a, ref int3 b)
{
return a.Equals(b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Int3Equality(ref int3 a, ref int3 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Int3Inequality(ref int3 a, ref int3 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Int3EqualityWithScalar(ref int3 a, int b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Int3InequalityWithScalar(ref int3 a, int b)
{
return Vectors.ConvertToInt(a != b);
}
// Int2
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static bool Int2Equals(ref int2 a, ref int2 b)
{
return a.Equals(b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Int2Equality(ref int2 a, ref int2 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Int2Inequality(ref int2 a, ref int2 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Int2EqualityWithScalar(ref int2 a, int b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Int2InequalityWithScalar(ref int2 a, int b)
{
return Vectors.ConvertToInt(a != b);
}
// UInt4
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static bool UInt4Equals(ref uint4 a, ref uint4 b)
{
return a.Equals(b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int UInt4Equality(ref uint4 a, ref uint4 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int UInt4Inequality(ref uint4 a, ref uint4 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int UInt4EqualityWithScalar(ref uint4 a, uint b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int UInt4InequalityWithScalar(ref uint4 a, uint b)
{
return Vectors.ConvertToInt(a != b);
}
// UInt3
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static bool UInt3Equals(ref uint3 a, ref uint3 b)
{
return a.Equals(b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int UInt3Equality(ref uint3 a, ref uint3 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int UInt3Inequality(ref uint3 a, ref uint3 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int UInt3EqualityWithScalar(ref uint3 a, uint b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int UInt3InequalityWithScalar(ref uint3 a, uint b)
{
return Vectors.ConvertToInt(a != b);
}
// Int2
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static bool UInt2Equals(ref uint2 a, ref uint2 b)
{
return a.Equals(b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int UInt2Equality(ref uint2 a, ref uint2 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int UInt2Inequality(ref uint2 a, ref uint2 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int UInt2EqualityWithScalar(ref uint2 a, uint b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int UInt2InequalityWithScalar(ref uint2 a, uint b)
{
return Vectors.ConvertToInt(a != b);
}
// Bool4
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static bool Bool4Equals(ref bool4 a, ref bool4 b)
{
return a.Equals(b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Bool4Equality(ref bool4 a, ref bool4 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Bool4Inequality(ref bool4 a, ref bool4 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Bool4EqualityWithScalar(ref bool4 a, bool b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Bool4InequalityWithScalar(ref bool4 a, bool b)
{
return Vectors.ConvertToInt(a != b);
}
// Bool3
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static bool Bool3Equals(ref bool3 a, ref bool3 b)
{
return a.Equals(b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Bool3Equality(ref bool3 a, ref bool3 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Bool3Inequality(ref bool3 a, ref bool3 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Bool3EqualityWithScalar(ref bool3 a, bool b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Bool3InequalityWithScalar(ref bool3 a, bool b)
{
return Vectors.ConvertToInt(a != b);
}
// Int2
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static bool Bool2Equals(ref bool2 a, ref bool2 b)
{
return a.Equals(b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Bool2Equality(ref bool2 a, ref bool2 b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Bool2Inequality(ref bool2 a, ref bool2 b)
{
return Vectors.ConvertToInt(a != b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Bool2EqualityWithScalar(ref bool2 a, bool b)
{
return Vectors.ConvertToInt(a == b);
}
[TestCompiler(DataRange.Standard, DataRange.Standard)]
public static int Bool2InequalityWithScalar(ref bool2 a, bool b)
{
return Vectors.ConvertToInt(a != b);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b9361007b00e3342b54a1eae06c8e797
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,25 @@
using System;
using Unity.Burst;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
internal partial class VectorsExceptions
{
[TestCompiler(1.0f, ExpectedDiagnosticId = DiagnosticId.WRN_ExceptionThrownInNonSafetyCheckGuardedFunction)]
public static float Float4WithException(float a)
{
return GetFloat4(a).x;
}
private static float4 GetFloat4(float value)
{
if (value < 0)
{
throw new ArgumentException();
// Here the generated code should have a burst.abort + a return zero float4 (SIMD type)
}
return new float4(value);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5e33ae893f1732ff836c7724c3cd2c53
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,43 @@
using Burst.Compiler.IL.Tests.Helpers;
using NUnit.Framework;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
[TestFixture]
internal partial class VectorsHashCodes
{
// TODO: Add tests for Uint4/3/2, Bool4/3/2
[TestCompiler(DataRange.Standard)]
public static int Float4GetHashCode(ref float4 a)
{
return a.GetHashCode();
}
[TestCompiler(DataRange.Standard)]
public static int Float3GetHashCode(ref float3 a)
{
return a.GetHashCode();
}
[TestCompiler(DataRange.Standard)]
public static int Float2GetHashCode(ref float2 a)
{
return a.GetHashCode();
}
[TestCompiler(DataRange.Standard)]
public static int Int4GetHashCode(ref int4 a)
{
return a.GetHashCode();
}
[TestCompiler(DataRange.Standard)]
public static int Int3GetHashCode(ref int3 a)
{
return a.GetHashCode();
}
[TestCompiler(DataRange.Standard)]
public static int Int2GetHashCode(ref int2 a)
{
return a.GetHashCode();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 23b96fd614e136e3bfc64d775335d0f0
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,95 @@
using Burst.Compiler.IL.Tests.Helpers;
using NUnit.Framework;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
[TestFixture]
internal partial class VectorsIndexers
{
[TestCompiler(0)]
[TestCompiler(1)]
[TestCompiler(2)]
[TestCompiler(3)]
public static float Float4_get_IndexerLocal(int i)
{
var vector = new float4(5.0f, 6.0f, 7.0f, 8.0f);
return vector[i];
}
[TestCompiler(DataRange.Standard)]
public static float Float4_get_IndexerByRef(ref float4 vector)
{
return vector[0] + vector[2];
}
[TestCompiler(0)]
[TestCompiler(1)]
[TestCompiler(2)]
[TestCompiler(3)]
public static float Float4_set_IndexerLocal(int i)
{
var vector = new float4(0.0f);
vector[i] = 2.0f * i;
return vector[0] + vector[2];
}
[TestCompiler(DataRange.Standard)]
public static float Float4_set_IndexerByRef(ref float4 vector)
{
vector[0] = 10.0f;
vector[2] = 15.0f;
return vector[0] + vector[2];
}
[TestCompiler(0)]
[TestCompiler(1)]
[TestCompiler(2)]
public static float Float3_get_IndexerLocal(int i)
{
var vector = new float3(5.0f, 6.0f, 7.0f);
return vector[i];
}
[TestCompiler(DataRange.Standard)]
public static float Float3_get_IndexerByRef(ref float3 vector)
{
return vector[0] + vector[2];
}
[TestCompiler(0)]
[TestCompiler(1)]
[TestCompiler(2)]
public static float Float3_set_IndexerLocal(int i)
{
var vector = new float3(0.0f);
vector[i] = 2.0f * i;
return vector[0] + vector[2];
}
[TestCompiler(DataRange.Standard)]
public static float Float3_set_IndexerByRef(ref float3 vector)
{
vector[0] = 10.0f;
vector[2] = 15.0f;
return vector[0] + vector[2];
}
[TestCompiler(DataRange.Standard)]
public static int Bool_set_Indexer_Indirect(ref float4 vec)
{
bool4 result = false;
for (int i = 0; i < 4; i++)
{
result[i] = CheckVector(vec[i]);
}
return Vectors.ConvertToInt(result);
}
public static bool CheckVector(float value)
{
return value < 10.0f;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: de7fc0987ef63c28b1f8500b817fd444
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,102 @@
using System.Runtime.CompilerServices;
using Burst.Compiler.IL.Tests.Helpers;
using NUnit.Framework;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
[TestFixture]
internal partial class VectorsLoadStore
{
public struct StructWithFloat4
{
public float4 Vec4;
}
[TestCompiler(DataRange.Standard)]
public static float TestReturnFloat4(ref float4 result)
{
var value = Process(result);
return value.x + value.y;
}
private static float4 Process(float4 vec)
{
vec.x += 5;
return vec;
}
[TestCompiler]
public static float FieldLoadStoreLocalFloat4()
{
var v = new float4(0);
var v1 = v.x;
v.y = 5;
return v.y + v1;
}
[TestCompiler]
public static float FieldLoadStoreIndirectFloat4()
{
var localStruct = new StructWithFloat4();
localStruct.Vec4 = new float4(1.0f, 2.0f, 3.0f, 4.0f);
return Vectors.ConvertToFloat(localStruct.Vec4);
}
[TestCompiler]
public static float FieldLoadStoreLocalByRefFloat4()
{
var v = new float4(2);
ChangeFloat4(ref v);
return Vectors.ConvertToFloat(v);
}
private static void ChangeFloat4(ref float4 vect)
{
vect.x += 5;
}
[TestCompiler]
public static float FieldStoreByOutFloat4()
{
float4 v;
OutputFloat4(out v);
return Vectors.ConvertToFloat(v);
}
private static void OutputFloat4(out float4 float4)
{
float4 = new float4(1, 2, 3, 4);
}
[TestCompiler]
public static float FieldLoadStoreLocalByRefFloat3()
{
var v = new float3(2);
ChangeFloat3(ref v);
return Vectors.ConvertToFloat(v);
}
private static void ChangeFloat3(ref float3 vect)
{
vect.z += 5;
}
[TestCompiler]
public static float FieldLoadStoreByRefFloat3()
{
var v = new float3(2);
float3 result;
LoadAndChangeFloat3(ref v, out result);
return Vectors.ConvertToFloat(result);
}
private static void LoadAndChangeFloat3(ref float3 vect, out float3 result)
{
var local = vect;
local.z += 5;
result = local;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7dd1c3c5e7f830fe9ce867cdb38d9108
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5db67d0b9e503a5c9ac1a4f14ee7b4a5
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,29 @@
using NUnit.Framework;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
[TestFixture]
internal partial class VectorsQuaternions
{
[TestCompiler]
public static float Normalize()
{
var v4 = new quaternion(1.0f, 2.0f, 3.0f, 4.0f);
var result = math.normalize(v4);
return Vectors.ConvertToFloat(result.value);
}
[TestCompiler]
public static float IdentityValue()
{
// Force ldsflda
return Vectors.ConvertToFloat(PassByRef(quaternion.identity.value));
}
private static float4 PassByRef(in float4 x)
{
return x;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 59be97c3fedf35d09af9a16655bb01e6
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,71 @@
using NUnit.Framework;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Mathematics;
namespace Burst.Compiler.IL.Tests
{
[TestFixture]
internal partial class VectorsSizeOfs
{
[TestCompiler]
public static int Float4()
{
return UnsafeUtility.SizeOf<float4>();
}
[TestCompiler]
public static int Float3()
{
return UnsafeUtility.SizeOf<float3>();
}
[TestCompiler]
public static int Float2()
{
return UnsafeUtility.SizeOf<float2>();
}
[TestCompiler]
public static int UInt4()
{
return UnsafeUtility.SizeOf<uint4>();
}
[TestCompiler]
public static int UInt3()
{
return UnsafeUtility.SizeOf<uint3>();
}
[TestCompiler]
public static int UInt2()
{
return UnsafeUtility.SizeOf<uint2>();
}
[TestCompiler]
public static int Int4()
{
return UnsafeUtility.SizeOf<int4>();
}
[TestCompiler]
public static int Int3()
{
return UnsafeUtility.SizeOf<int3>();
}
[TestCompiler]
public static int Int2()
{
return UnsafeUtility.SizeOf<int2>();
}
[TestCompiler]
public static int Bool4()
{
return UnsafeUtility.SizeOf<bool4>();
}
[TestCompiler]
public static int Bool3()
{
return UnsafeUtility.SizeOf<bool3>();
}
[TestCompiler]
public static int Bool2()
{
return UnsafeUtility.SizeOf<bool2>();
}
}
}

Some files were not shown because too many files have changed in this diff Show more