123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading.Tasks;
- using UnityEditor;
- using UnityEngine;
- namespace HybridCLR.Generators.MethodBridge
- {
- public class TypeGenInfo
- {
- public Type Type { get; set; }
- public List<MethodInfo> GenericMethods { get; set; }
- }
- public class MethodBridgeGeneratorOptions
- {
- public List<Assembly> HotfixAssemblies { get; set; }
- public List<Assembly> AllAssemblies { get; set; }
- public PlatformABI CallConvention { get; set; }
- public string OutputFile { get; set; }
- }
- public class MethodBridgeGenerator
- {
- private readonly HashSet<Assembly> _hotfixAssemblies;
- private readonly List<Assembly> _assemblies;
- private readonly PlatformABI _callConvention;
- private readonly string _outputFile;
- private readonly IPlatformAdaptor _platformAdaptor;
- private readonly HashSet<MethodBridgeSig> _managed2nativeMethodSet = new HashSet<MethodBridgeSig>();
- private List<MethodBridgeSig> _managed2nativeMethodList;
- private readonly HashSet<MethodBridgeSig> _native2managedMethodSet = new HashSet<MethodBridgeSig>();
- private List<MethodBridgeSig> _native2managedMethodList;
- private readonly HashSet<MethodBridgeSig> _adjustThunkMethodSet = new HashSet<MethodBridgeSig>();
- private List<MethodBridgeSig> _adjustThunkMethodList;
- public bool IsHotFixType(Type type)
- {
- return _hotfixAssemblies.Contains(type.Assembly);
- }
- public MethodBridgeGenerator(MethodBridgeGeneratorOptions options)
- {
- _hotfixAssemblies = new HashSet<Assembly>(options.HotfixAssemblies);
- _assemblies = options.AllAssemblies;
- _callConvention = options.CallConvention;
- _outputFile = options.OutputFile;
- _platformAdaptor = CreatePlatformAdaptor(options.CallConvention);
- }
- private static IPlatformAdaptor CreatePlatformAdaptor(PlatformABI type)
- {
- return type switch
- {
- PlatformABI.Universal32 => new PlatformAdaptor_Universal32(),
- PlatformABI.Universal64 => new PlatformAdaptor_Universal64(),
- PlatformABI.Arm64 => new PlatformAdaptor_Arm64(),
- _ => throw new NotSupportedException(),
- };
- }
- private string GetTemplateFile()
- {
- string tplFile = _callConvention switch
- {
- PlatformABI.Universal32 => "Universal32",
- PlatformABI.Universal64 => "Universal64",
- PlatformABI.Arm64 => "Arm64",
- _ => throw new NotSupportedException(),
- };
- return $"{Application.dataPath}/Editor/HybridCLR/Generators/Templates/MethodBridge_{tplFile}.cpp";
- }
- public IEnumerable<TypeGenInfo> GetGenerateTypes()
- {
- return new List<TypeGenInfo>();
- }
- private MethodBridgeSig CreateMethodBridgeSig(bool isStatic, ParameterInfo returnType, ParameterInfo[] parameters)
- {
- var paramInfos = new List<ParamInfo>();
- if (!isStatic)
- {
- // FIXME arm32 is s_i4u4
- paramInfos.Add(new ParamInfo() { Type = _platformAdaptor.IsArch32 ? TypeInfo.s_i4u4 : TypeInfo.s_i8u8 });
- }
- foreach (var paramInfo in parameters)
- {
- paramInfos.Add(new ParamInfo() { Type = _platformAdaptor.CreateTypeInfo(paramInfo.ParameterType, false) });
- }
- var mbs = new MethodBridgeSig()
- {
- ReturnInfo = new ReturnInfo() { Type = returnType != null ? _platformAdaptor.CreateTypeInfo(returnType.ParameterType, true) : TypeInfo.s_void },
- ParamInfos = paramInfos,
- };
- return mbs;
- }
- private void AddManaged2NativeMethod(MethodBridgeSig method)
- {
- if (_managed2nativeMethodSet.Add(method))
- {
- method.Init();
- }
- }
- private void AddNative2ManagedMethod(MethodBridgeSig method)
- {
- if (_native2managedMethodSet.Add(method))
- {
- method.Init();
- }
- }
- private void AddAdjustThunkMethod(MethodBridgeSig method)
- {
- if (_adjustThunkMethodSet.Add(method))
- {
- method.Init();
- }
- }
- private void ScanType(Type type)
- {
- if (type.IsGenericTypeDefinition)
- {
- return;
- }
- if (!type.IsNested)
- {
- if (!type.IsPublic)
- {
- return;
- }
- }
- else
- {
- if (type.IsNestedPrivate)
- {
- return;
- }
- }
- var typeDel = typeof(MulticastDelegate);
- if (typeDel.IsAssignableFrom(type))
- {
- var method = type.GetMethod("Invoke");
- if (method == null)
- {
- //Debug.LogError($"delegate:{typeDel.FullName} Invoke not exists");
- return;
- }
- // Debug.Log($"== delegate:{type}");
- var instanceCallMethod = CreateMethodBridgeSig(false, method.ReturnParameter, method.GetParameters());
- AddManaged2NativeMethod(instanceCallMethod);
- AddNative2ManagedMethod(instanceCallMethod);
- var staticCallMethod = CreateMethodBridgeSig(true, method.ReturnParameter, method.GetParameters());
- AddManaged2NativeMethod(staticCallMethod);
- AddNative2ManagedMethod(staticCallMethod);
- return;
- }
- foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public
- | BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy))
- {
- if (method.IsGenericMethodDefinition)
- {
- continue;
- }
- if (method.IsPrivate || (method.IsAssembly && !method.IsPublic && !method.IsFamily))
- {
- continue;
- }
- if (method.IsFamily || method.IsPublic)
- {
- var m2nMethod = CreateMethodBridgeSig(method.IsStatic, method.ReturnParameter, method.GetParameters());
- AddManaged2NativeMethod(m2nMethod);
- if (type.IsValueType && !method.IsStatic)
- {
- var adjustThunkMethod = CreateMethodBridgeSig(true, method.ReturnParameter, method.GetParameters());
- AddAdjustThunkMethod(adjustThunkMethod);
- }
- if (method.IsVirtual)
- {
- AddNative2ManagedMethod(m2nMethod);
- }
- }
- }
- foreach (var method in type.GetConstructors(BindingFlags.Instance | BindingFlags.Public
- | BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy))
- {
- if (method.IsPrivate || (method.IsAssembly && !method.IsPublic && !method.IsFamily))
- {
- continue;
- }
- if (method.IsFamily || method.IsPublic)
- {
- var callMethod = CreateMethodBridgeSig(false, null, method.GetParameters());
- AddManaged2NativeMethod(callMethod);
- if (type.IsValueType && !method.IsStatic)
- {
- var invokeMethod = CreateMethodBridgeSig(true, null, method.GetParameters());
- AddAdjustThunkMethod(invokeMethod);
- }
- }
- }
- foreach (var subType in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
- {
- ScanType(subType);
- }
- }
- public void PrepareFromAssemblies()
- {
- foreach (var ass in _assemblies)
- {
- if (_hotfixAssemblies.Contains(ass))
- {
- continue;
- }
- //Debug.Log("prepare assembly:" + ass.FullName);
- foreach (var type in ass.GetTypes())
- {
- ScanType(type);
- }
- }
- }
- private void PrepareMethodsFromCustomeGenericTypes()
- {
- foreach (var type in GeneratorConfig.PrepareCustomGenericTypes())
- {
- ScanType(type);
- }
- }
- public void PrepareMethods()
- {
- PrepareMethodsFromCustomeGenericTypes();
- foreach(var methodSig in _platformAdaptor.IsArch32 ? GeneratorConfig.PrepareCustomMethodSignatures32() : GeneratorConfig.PrepareCustomMethodSignatures64())
- {
- var method = MethodBridgeSig.CreateBySignatuer(methodSig);
- AddManaged2NativeMethod(method);
- AddAdjustThunkMethod(method);
- }
- PrepareFromAssemblies();
- {
- var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
- foreach (var method in _managed2nativeMethodSet)
- {
- sortedMethods.Add(method.CreateCallSigName(), method);
- }
- _managed2nativeMethodList = sortedMethods.Values.ToList();
- }
- {
- var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
- foreach (var method in _native2managedMethodSet)
- {
- sortedMethods.Add(method.CreateCallSigName(), method);
- }
- _native2managedMethodList = sortedMethods.Values.ToList();
- }
- {
- var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
- foreach (var method in _adjustThunkMethodSet)
- {
- sortedMethods.Add(method.CreateCallSigName(), method);
- }
- _adjustThunkMethodList = sortedMethods.Values.ToList();
- }
- }
- public void Generate()
- {
- var frr = new FileRegionReplace(GetTemplateFile());
- List<string> lines = new List<string>(20_0000);
- Debug.LogFormat("== managed2native method count:{0}", _managed2nativeMethodList.Count);
- foreach(var method in _managed2nativeMethodList)
- {
- _platformAdaptor.GenerateManaged2NativeMethod(method, lines);
- }
- _platformAdaptor.GenerateManaged2NativeStub(_managed2nativeMethodList, lines);
- Debug.LogFormat("== native2managed method count:{0}", _native2managedMethodList.Count);
- foreach (var method in _native2managedMethodList)
- {
- _platformAdaptor.GenerateNative2ManagedMethod(method, lines);
- }
- _platformAdaptor.GenerateNative2ManagedStub(_native2managedMethodList, lines);
- Debug.LogFormat("== adjustThunk method count:{0}", _adjustThunkMethodList.Count);
- foreach (var method in _adjustThunkMethodList)
- {
- _platformAdaptor.GenerateAdjustThunkMethod(method, lines);
- }
- _platformAdaptor.GenerateAdjustThunkStub(_adjustThunkMethodList, lines);
- frr.Replace("INVOKE_STUB", string.Join("\n", lines));
- Directory.CreateDirectory(Path.GetDirectoryName(_outputFile));
- frr.Commit(_outputFile);
- }
- }
- }
|