initial commit
This commit is contained in:
parent
6715289efe
commit
788c3389af
37645 changed files with 2526849 additions and 80 deletions
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3decc8d6366d3d668648f9b79f2a980f
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c02f830887253c6eaf1f7780c59c5432
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d54dbb53d4313cc8b7d8289a75202585
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ac74b11ef46b35938b5d3ca8a4109efa
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: eb7078968c7e3322a80bb099e19fb2e8
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 30b8c33e57eb30adbfd9b640a4edaef8
|
||||
folderAsset: yes
|
|
@ -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];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5eb12402c8b53dbaa40d67a6ccd1b4f6
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0bed5c1e3949386481f894d4b987c939
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fec1bb67579b3feda3e2fddd7ecbc304
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a0499a50a9b63d9a90fc428e1f5c89e9
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 953d1f4d7d69334fbc9657d7d82a855b
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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#)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3d218d6a948d3d8c98c40cca55189572
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 50c3d62ace6136cb9c85f8e2a44b7aec
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c6f9aa18fd4b3d1d9ef249e3c61af783
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7a3d2b4e287138d6b5a68635fcda35ae
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bb0c92e22ce4395fae3821dcc85a3113
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 945f727e6eb43c81ae49f4e92e3d98c2
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 701a30a4d0f73d51a92f908b568cea9d
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 06cc7660b5c739eca022daad2ed2e0a4
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 10c2b0100e723deab40f35dc43e40cd5
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 828266174e573a6da71055ba8f017778
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5eb3e1cf0e2a3614927c245069c69baf
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 36990957b5d73a9681ce7dd9f4d5a7b0
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1b192164f6d13e9aaf88fbb6833566c4
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1d15bef20cb43dc49f6156cde028d37a
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 614354dff06f39c4b6ef0e21f5a45d23
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7771e50c9f91376ca0db91c33bfccfda
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a1bc4bf3e38931c9b2014cc764d03dea
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 47108b7d7a79385f98626b40f17ef46d
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 631a9c909a1e35999f140f79ef90911a
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3d355504e32f39b89ef31f85cad154a5
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 66f82e3041613b77861041e9b0479554
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cb91adf0b099390483bffed46bc16fb1
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fa0dd524a0c332f7948fb2cc410034b1
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: df58129e92123044b15b889624e8868c
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1d871bf5a85e3baaa304966c127e87a7
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8826f823d5c0312faae224801c9e8bd3
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4784d45bc93937ca93dc6578b3e58fc2
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dbb95f4d93ed32938db073fd04c6e1fd
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e07174e0c0ba3d269ad0936f514c3409
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: afa4d597c8db399ab071dfe6a3096516
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6a2963e730253fb7bc1f496becab35d1
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 93aa22b749c8358d8368db9527996503
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b9361007b00e3342b54a1eae06c8e797
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5e33ae893f1732ff836c7724c3cd2c53
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 23b96fd614e136e3bfc64d775335d0f0
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: de7fc0987ef63c28b1f8500b817fd444
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7dd1c3c5e7f830fe9ce867cdb38d9108
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5db67d0b9e503a5c9ac1a4f14ee7b4a5
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 59be97c3fedf35d09af9a16655bb01e6
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue