123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- 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> Assemblies { get; set; }
- public PlatformABI CallConvention { get; set; }
- public string OutputFile { get; set; }
- }
- public class MethodBridgeGenerator
- {
- private readonly List<Assembly> _assemblies;
- private readonly PlatformABI _callConvention;
- private readonly string _outputFile;
- private readonly IPlatformAdaptor _platformAdaptor;
- private readonly HashSet<MethodBridgeSig> _callMethodSet = new HashSet<MethodBridgeSig>();
- private List<MethodBridgeSig> _callMethodList;
- private readonly HashSet<MethodBridgeSig> _invokeMethodSet = new HashSet<MethodBridgeSig>();
- private List<MethodBridgeSig> _invokeMethodList;
- public MethodBridgeGenerator(MethodBridgeGeneratorOptions options)
- {
- _assemblies = options.Assemblies;
- _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 AddCallMethod(MethodBridgeSig method)
- {
- if (_callMethodSet.Add(method))
- {
- method.Init();
- }
- }
- private void AddInvokeMethod(MethodBridgeSig method)
- {
- if (_invokeMethodSet.Add(method))
- {
- method.Init();
- }
- }
- private void ScanType(Type type)
- {
- if (type.IsGenericTypeDefinition)
- {
- 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;
- }
- var instanceCallMethod = CreateMethodBridgeSig(false, method.ReturnParameter, method.GetParameters());
- AddCallMethod(instanceCallMethod);
- var staticCallMethod = CreateMethodBridgeSig(true, method.ReturnParameter, method.GetParameters());
- AddCallMethod(staticCallMethod);
- var invokeMethod = CreateMethodBridgeSig(true, method.ReturnParameter, method.GetParameters());
- AddInvokeMethod(invokeMethod);
- 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;
- }
- var callMethod = CreateMethodBridgeSig(method.IsStatic, method.ReturnParameter, method.GetParameters());
- AddCallMethod(callMethod);
- var invokeMethod = CreateMethodBridgeSig(true, method.ReturnParameter, method.GetParameters());
- AddInvokeMethod(invokeMethod);
- }
- foreach (var method in type.GetConstructors(BindingFlags.Instance | BindingFlags.Public
- | BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy))
- {
- var callMethod = CreateMethodBridgeSig(false, null, method.GetParameters());
- AddCallMethod(callMethod);
- var invokeMethod = CreateMethodBridgeSig(true, null, method.GetParameters());
- AddInvokeMethod(invokeMethod);
- }
- foreach (var subType in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
- {
- ScanType(subType);
- }
- }
- public void PrepareFromAssemblies()
- {
- foreach (var ass in _assemblies)
- {
- //Debug.Log("prepare assembly:" + ass.FullName);
- foreach (var type in ass.GetTypes())
- {
- ScanType(type);
- }
- }
- }
- public void PrepareCommon1()
- {
- // (void + int64 + float) * (int64 + float) * (0 - 20) = 120
- TypeInfo typeVoid = new TypeInfo(typeof(void), ParamOrReturnType.VOID);
- TypeInfo typeLong = new TypeInfo(typeof(long), ParamOrReturnType.I8_U8);
- TypeInfo typeDouble = new TypeInfo(typeof(double), ParamOrReturnType.R8);
- int maxParamCount = 20;
-
- foreach (var returnType in new TypeInfo[] { typeVoid, typeLong, typeDouble })
- {
- var rt = new ReturnInfo() { Type = returnType };
- foreach (var argType in new TypeInfo[] { typeLong, typeDouble })
- {
- for (int paramCount = 0; paramCount <= maxParamCount; paramCount++)
- {
- var paramInfos = new List<ParamInfo>();
- for (int i = 0; i < paramCount; i++)
- {
- paramInfos.Add(new ParamInfo() { Type = argType });
- }
- var mbs = new MethodBridgeSig() { ReturnInfo = rt, ParamInfos = paramInfos};
- AddCallMethod(mbs);
- }
- }
- }
- }
- public void PrepareCommon2()
- {
- // (void + int64 + float) * (int64 + float + sr) ^ (0 - 4) = 363
- TypeInfo typeVoid = new TypeInfo(typeof(void), ParamOrReturnType.VOID);
- TypeInfo typeLong = new TypeInfo(typeof(long), ParamOrReturnType.I8_U8);
- TypeInfo typeDouble = new TypeInfo(typeof(double), ParamOrReturnType.R8);
- int maxParamCount = 4;
- var argTypes = new TypeInfo[] { typeLong, typeDouble };
- int paramTypeNum = argTypes.Length;
- foreach (var returnType in new TypeInfo[] { typeVoid, typeLong, typeDouble })
- {
- var rt = new ReturnInfo() { Type = returnType };
- for(int paramCount = 1; paramCount <= maxParamCount; paramCount++)
- {
- int totalCombinationNum = (int)Math.Pow(paramTypeNum, paramCount);
- for (int k = 0; k < totalCombinationNum; k++)
- {
- var paramInfos = new List<ParamInfo>();
- int c = k;
- for(int i = 0; i < paramCount; i++)
- {
- paramInfos.Add(new ParamInfo { Type = argTypes[c % paramTypeNum] });
- c /= paramTypeNum;
- }
- var mbs = new MethodBridgeSig() { ReturnInfo = rt, ParamInfos = paramInfos };
- AddCallMethod(mbs);
- }
- }
- }
- }
- private void PrepareMethodsFromCustomeGenericTypes()
- {
- foreach (var type in GeneratorConfig.PrepareCustomGenericTypes())
- {
- ScanType(type);
- }
- }
- public void PrepareMethods()
- {
- PrepareCommon1();
- PrepareCommon2();
- PrepareMethodsFromCustomeGenericTypes();
- foreach(var methodSig in _platformAdaptor.IsArch32 ? GeneratorConfig.PrepareCustomMethodSignatures32() : GeneratorConfig.PrepareCustomMethodSignatures64())
- {
- var method = MethodBridgeSig.CreateBySignatuer(methodSig);
- AddCallMethod(method);
- AddInvokeMethod(method);
- }
- foreach(var method in _platformAdaptor.GetPreserveMethods())
- {
- AddCallMethod(method);
- AddInvokeMethod(method);
- }
- PrepareFromAssemblies();
- {
- var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
- foreach (var method in _callMethodSet)
- {
- sortedMethods.Add(method.CreateCallSigName(), method);
- }
- _callMethodList = sortedMethods.Values.ToList();
- }
- {
- var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
- foreach (var method in _invokeMethodSet)
- {
- sortedMethods.Add(method.CreateCallSigName(), method);
- }
- _invokeMethodList = sortedMethods.Values.ToList();
- }
- }
- public void Generate()
- {
- var frr = new FileRegionReplace(GetTemplateFile());
- List<string> lines = new List<string>(20_0000);
- Debug.LogFormat("== call method count:{0}", _callMethodList.Count);
- foreach(var method in _callMethodList)
- {
- _platformAdaptor.GenerateCall(method, lines);
- }
- Debug.LogFormat("== invoke method count:{0}", _invokeMethodList.Count);
- foreach (var method in _invokeMethodList)
- {
- _platformAdaptor.GenerateInvoke(method, lines);
- }
- _platformAdaptor.GenCallStub(_callMethodList, lines);
- _platformAdaptor.GenInvokeStub(_invokeMethodList, lines);
- frr.Replace("INVOKE_STUB", string.Join("\n", lines));
- Directory.CreateDirectory(Path.GetDirectoryName(_outputFile));
- frr.Commit(_outputFile);
- }
- }
- }
|