You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
4.2 KiB
100 lines
4.2 KiB
#if BURST_TESTS_ONLY |
|
using System; |
|
using System.Collections.Generic; |
|
using System.Reflection; |
|
using System.Reflection.Emit; |
|
using System.Runtime.InteropServices; |
|
|
|
namespace Burst.Compiler.IL.Tests.Helpers |
|
{ |
|
internal static class DelegateHelper |
|
{ |
|
private static readonly Type[] _DelegateCtorSignature = new Type[2] |
|
{ |
|
typeof(object), |
|
typeof(IntPtr) |
|
}; |
|
|
|
private static readonly Dictionary<DelegateKey, Type> DelegateTypes = new(); |
|
|
|
public static Type NewDelegateType(Type ret, Type[] parameters) |
|
{ |
|
lock (DelegateTypes) |
|
{ |
|
var key = new DelegateKey(ret, (Type[])parameters.Clone()); |
|
Type delegateType; |
|
if (!DelegateTypes.TryGetValue(key, out delegateType)) |
|
{ |
|
var assemblyName = Guid.NewGuid().ToString(); |
|
|
|
var name = new AssemblyName(assemblyName); |
|
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run); |
|
var moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name); |
|
assemblyBuilder.DefineVersionInfoResource(); |
|
|
|
var typeBuilder = moduleBuilder.DefineType("CustomDelegate", System.Reflection.TypeAttributes.Public | System.Reflection.TypeAttributes.Sealed | System.Reflection.TypeAttributes.AutoClass, typeof(MulticastDelegate)); |
|
var constructor = typeof(UnmanagedFunctionPointerAttribute).GetConstructors()[0]; |
|
|
|
// Make sure that we setup the C calling convention on the unmanaged delegate |
|
var customAttribute = new CustomAttributeBuilder(constructor, new object[] { CallingConvention.Cdecl }); |
|
typeBuilder.SetCustomAttribute(customAttribute); |
|
typeBuilder.DefineConstructor(System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.HideBySig | System.Reflection.MethodAttributes.RTSpecialName, CallingConventions.Standard, _DelegateCtorSignature).SetImplementationFlags(System.Reflection.MethodImplAttributes.CodeTypeMask); |
|
typeBuilder.DefineMethod("Invoke", System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.Virtual | System.Reflection.MethodAttributes.HideBySig | System.Reflection.MethodAttributes.VtableLayoutMask, ret, parameters).SetImplementationFlags(System.Reflection.MethodImplAttributes.CodeTypeMask); |
|
delegateType = typeBuilder.CreateType(); |
|
|
|
DelegateTypes.Add(key, delegateType); |
|
} |
|
return delegateType; |
|
} |
|
} |
|
|
|
private struct DelegateKey : IEquatable<DelegateKey> |
|
{ |
|
public DelegateKey(Type returnType, Type[] arguments) |
|
{ |
|
ReturnType = returnType; |
|
Arguments = arguments; |
|
} |
|
|
|
public readonly Type ReturnType; |
|
|
|
public readonly Type[] Arguments; |
|
|
|
public bool Equals(DelegateKey other) |
|
{ |
|
if (ReturnType.Equals(other.ReturnType) && Arguments.Length == other.Arguments.Length) |
|
{ |
|
for (int i = 0; i < Arguments.Length; i++) |
|
{ |
|
if (Arguments[i] != other.Arguments[i]) |
|
{ |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
public override bool Equals(object obj) |
|
{ |
|
if (ReferenceEquals(null, obj)) return false; |
|
return obj is DelegateKey && Equals((DelegateKey) obj); |
|
} |
|
|
|
public override int GetHashCode() |
|
{ |
|
unchecked |
|
{ |
|
int hashcode = (ReturnType.GetHashCode() * 397) ^ Arguments.Length.GetHashCode(); |
|
for (int i = 0; i < Arguments.Length; i++) |
|
{ |
|
hashcode = (hashcode * 397) ^ Arguments[i].GetHashCode(); |
|
} |
|
return hashcode; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
#endif |