|
@@ -20,7 +20,9 @@ namespace HybridCLR.Generators.MethodBridge
|
|
|
|
|
|
public class MethodBridgeGeneratorOptions
|
|
public class MethodBridgeGeneratorOptions
|
|
{
|
|
{
|
|
- public List<Assembly> Assemblies { get; set; }
|
|
|
|
|
|
+ public List<Assembly> HotfixAssemblies { get; set; }
|
|
|
|
+
|
|
|
|
+ public List<Assembly> AllAssemblies { get; set; }
|
|
|
|
|
|
public PlatformABI CallConvention { get; set; }
|
|
public PlatformABI CallConvention { get; set; }
|
|
|
|
|
|
@@ -29,6 +31,8 @@ namespace HybridCLR.Generators.MethodBridge
|
|
|
|
|
|
public class MethodBridgeGenerator
|
|
public class MethodBridgeGenerator
|
|
{
|
|
{
|
|
|
|
+ private readonly HashSet<Assembly> _hotfixAssemblies;
|
|
|
|
+
|
|
private readonly List<Assembly> _assemblies;
|
|
private readonly List<Assembly> _assemblies;
|
|
|
|
|
|
private readonly PlatformABI _callConvention;
|
|
private readonly PlatformABI _callConvention;
|
|
@@ -37,17 +41,27 @@ namespace HybridCLR.Generators.MethodBridge
|
|
|
|
|
|
private readonly IPlatformAdaptor _platformAdaptor;
|
|
private readonly IPlatformAdaptor _platformAdaptor;
|
|
|
|
|
|
- private readonly HashSet<MethodBridgeSig> _callMethodSet = new HashSet<MethodBridgeSig>();
|
|
|
|
|
|
+ private readonly HashSet<MethodBridgeSig> _managed2nativeMethodSet = new HashSet<MethodBridgeSig>();
|
|
|
|
+
|
|
|
|
+ private List<MethodBridgeSig> _managed2nativeMethodList;
|
|
|
|
|
|
- private List<MethodBridgeSig> _callMethodList;
|
|
|
|
|
|
+ private readonly HashSet<MethodBridgeSig> _native2managedMethodSet = new HashSet<MethodBridgeSig>();
|
|
|
|
|
|
- private readonly HashSet<MethodBridgeSig> _invokeMethodSet = new HashSet<MethodBridgeSig>();
|
|
|
|
|
|
+ private List<MethodBridgeSig> _native2managedMethodList;
|
|
|
|
|
|
- private List<MethodBridgeSig> _invokeMethodList;
|
|
|
|
|
|
+ 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)
|
|
public MethodBridgeGenerator(MethodBridgeGeneratorOptions options)
|
|
{
|
|
{
|
|
- _assemblies = options.Assemblies;
|
|
|
|
|
|
+ _hotfixAssemblies = new HashSet<Assembly>(options.HotfixAssemblies);
|
|
|
|
+ _assemblies = options.AllAssemblies;
|
|
_callConvention = options.CallConvention;
|
|
_callConvention = options.CallConvention;
|
|
_outputFile = options.OutputFile;
|
|
_outputFile = options.OutputFile;
|
|
_platformAdaptor = CreatePlatformAdaptor(options.CallConvention);
|
|
_platformAdaptor = CreatePlatformAdaptor(options.CallConvention);
|
|
@@ -101,17 +115,25 @@ namespace HybridCLR.Generators.MethodBridge
|
|
return mbs;
|
|
return mbs;
|
|
}
|
|
}
|
|
|
|
|
|
- private void AddCallMethod(MethodBridgeSig method)
|
|
|
|
|
|
+ private void AddManaged2NativeMethod(MethodBridgeSig method)
|
|
{
|
|
{
|
|
- if (_callMethodSet.Add(method))
|
|
|
|
|
|
+ if (_managed2nativeMethodSet.Add(method))
|
|
{
|
|
{
|
|
method.Init();
|
|
method.Init();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private void AddInvokeMethod(MethodBridgeSig method)
|
|
|
|
|
|
+ private void AddNative2ManagedMethod(MethodBridgeSig method)
|
|
{
|
|
{
|
|
- if (_invokeMethodSet.Add(method))
|
|
|
|
|
|
+ if (_native2managedMethodSet.Add(method))
|
|
|
|
+ {
|
|
|
|
+ method.Init();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void AddAdjustThunkMethod(MethodBridgeSig method)
|
|
|
|
+ {
|
|
|
|
+ if (_adjustThunkMethodSet.Add(method))
|
|
{
|
|
{
|
|
method.Init();
|
|
method.Init();
|
|
}
|
|
}
|
|
@@ -123,6 +145,20 @@ namespace HybridCLR.Generators.MethodBridge
|
|
{
|
|
{
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+ if (!type.IsNested)
|
|
|
|
+ {
|
|
|
|
+ if (!type.IsPublic)
|
|
|
|
+ {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ if (type.IsNestedPrivate)
|
|
|
|
+ {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
var typeDel = typeof(MulticastDelegate);
|
|
var typeDel = typeof(MulticastDelegate);
|
|
if (typeDel.IsAssignableFrom(type))
|
|
if (typeDel.IsAssignableFrom(type))
|
|
{
|
|
{
|
|
@@ -132,13 +168,14 @@ namespace HybridCLR.Generators.MethodBridge
|
|
//Debug.LogError($"delegate:{typeDel.FullName} Invoke not exists");
|
|
//Debug.LogError($"delegate:{typeDel.FullName} Invoke not exists");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+ // Debug.Log($"== delegate:{type}");
|
|
var instanceCallMethod = CreateMethodBridgeSig(false, method.ReturnParameter, method.GetParameters());
|
|
var instanceCallMethod = CreateMethodBridgeSig(false, method.ReturnParameter, method.GetParameters());
|
|
- AddCallMethod(instanceCallMethod);
|
|
|
|
- var staticCallMethod = CreateMethodBridgeSig(true, method.ReturnParameter, method.GetParameters());
|
|
|
|
- AddCallMethod(staticCallMethod);
|
|
|
|
|
|
+ AddManaged2NativeMethod(instanceCallMethod);
|
|
|
|
+ AddNative2ManagedMethod(instanceCallMethod);
|
|
|
|
|
|
- var invokeMethod = CreateMethodBridgeSig(true, method.ReturnParameter, method.GetParameters());
|
|
|
|
- AddInvokeMethod(invokeMethod);
|
|
|
|
|
|
+ var staticCallMethod = CreateMethodBridgeSig(true, method.ReturnParameter, method.GetParameters());
|
|
|
|
+ AddManaged2NativeMethod(staticCallMethod);
|
|
|
|
+ AddNative2ManagedMethod(staticCallMethod);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public
|
|
foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public
|
|
@@ -148,21 +185,49 @@ namespace HybridCLR.Generators.MethodBridge
|
|
{
|
|
{
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
- var callMethod = CreateMethodBridgeSig(method.IsStatic, method.ReturnParameter, method.GetParameters());
|
|
|
|
- AddCallMethod(callMethod);
|
|
|
|
|
|
|
|
- var invokeMethod = CreateMethodBridgeSig(true, method.ReturnParameter, method.GetParameters());
|
|
|
|
- AddInvokeMethod(invokeMethod);
|
|
|
|
|
|
+ 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
|
|
foreach (var method in type.GetConstructors(BindingFlags.Instance | BindingFlags.Public
|
|
| BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy))
|
|
| BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy))
|
|
{
|
|
{
|
|
- var callMethod = CreateMethodBridgeSig(false, null, method.GetParameters());
|
|
|
|
- AddCallMethod(callMethod);
|
|
|
|
|
|
+ if (method.IsPrivate || (method.IsAssembly && !method.IsPublic && !method.IsFamily))
|
|
|
|
+ {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (method.IsFamily || method.IsPublic)
|
|
|
|
+ {
|
|
|
|
+ var callMethod = CreateMethodBridgeSig(false, null, method.GetParameters());
|
|
|
|
+ AddManaged2NativeMethod(callMethod);
|
|
|
|
|
|
- var invokeMethod = CreateMethodBridgeSig(true, null, method.GetParameters());
|
|
|
|
- AddInvokeMethod(invokeMethod);
|
|
|
|
|
|
+ if (type.IsValueType && !method.IsStatic)
|
|
|
|
+ {
|
|
|
|
+ var invokeMethod = CreateMethodBridgeSig(true, null, method.GetParameters());
|
|
|
|
+ AddAdjustThunkMethod(invokeMethod);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
foreach (var subType in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
|
|
foreach (var subType in type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
|
|
@@ -175,6 +240,10 @@ namespace HybridCLR.Generators.MethodBridge
|
|
{
|
|
{
|
|
foreach (var ass in _assemblies)
|
|
foreach (var ass in _assemblies)
|
|
{
|
|
{
|
|
|
|
+ if (_hotfixAssemblies.Contains(ass))
|
|
|
|
+ {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
//Debug.Log("prepare assembly:" + ass.FullName);
|
|
//Debug.Log("prepare assembly:" + ass.FullName);
|
|
foreach (var type in ass.GetTypes())
|
|
foreach (var type in ass.GetTypes())
|
|
{
|
|
{
|
|
@@ -183,67 +252,6 @@ namespace HybridCLR.Generators.MethodBridge
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- 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()
|
|
private void PrepareMethodsFromCustomeGenericTypes()
|
|
{
|
|
{
|
|
foreach (var type in GeneratorConfig.PrepareCustomGenericTypes())
|
|
foreach (var type in GeneratorConfig.PrepareCustomGenericTypes())
|
|
@@ -254,39 +262,40 @@ namespace HybridCLR.Generators.MethodBridge
|
|
|
|
|
|
public void PrepareMethods()
|
|
public void PrepareMethods()
|
|
{
|
|
{
|
|
- PrepareCommon1();
|
|
|
|
- PrepareCommon2();
|
|
|
|
PrepareMethodsFromCustomeGenericTypes();
|
|
PrepareMethodsFromCustomeGenericTypes();
|
|
|
|
|
|
|
|
|
|
foreach(var methodSig in _platformAdaptor.IsArch32 ? GeneratorConfig.PrepareCustomMethodSignatures32() : GeneratorConfig.PrepareCustomMethodSignatures64())
|
|
foreach(var methodSig in _platformAdaptor.IsArch32 ? GeneratorConfig.PrepareCustomMethodSignatures32() : GeneratorConfig.PrepareCustomMethodSignatures64())
|
|
{
|
|
{
|
|
var method = MethodBridgeSig.CreateBySignatuer(methodSig);
|
|
var method = MethodBridgeSig.CreateBySignatuer(methodSig);
|
|
- AddCallMethod(method);
|
|
|
|
- AddInvokeMethod(method);
|
|
|
|
- }
|
|
|
|
- foreach(var method in _platformAdaptor.GetPreserveMethods())
|
|
|
|
- {
|
|
|
|
- AddCallMethod(method);
|
|
|
|
- AddInvokeMethod(method);
|
|
|
|
|
|
+ AddManaged2NativeMethod(method);
|
|
|
|
+ AddAdjustThunkMethod(method);
|
|
}
|
|
}
|
|
PrepareFromAssemblies();
|
|
PrepareFromAssemblies();
|
|
|
|
|
|
{
|
|
{
|
|
var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
|
|
var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
|
|
- foreach (var method in _callMethodSet)
|
|
|
|
|
|
+ foreach (var method in _managed2nativeMethodSet)
|
|
{
|
|
{
|
|
sortedMethods.Add(method.CreateCallSigName(), method);
|
|
sortedMethods.Add(method.CreateCallSigName(), method);
|
|
}
|
|
}
|
|
- _callMethodList = sortedMethods.Values.ToList();
|
|
|
|
|
|
+ _managed2nativeMethodList = sortedMethods.Values.ToList();
|
|
}
|
|
}
|
|
{
|
|
{
|
|
var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
|
|
var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
|
|
- foreach (var method in _invokeMethodSet)
|
|
|
|
|
|
+ foreach (var method in _native2managedMethodSet)
|
|
{
|
|
{
|
|
sortedMethods.Add(method.CreateCallSigName(), method);
|
|
sortedMethods.Add(method.CreateCallSigName(), method);
|
|
}
|
|
}
|
|
- _invokeMethodList = sortedMethods.Values.ToList();
|
|
|
|
|
|
+ _native2managedMethodList = sortedMethods.Values.ToList();
|
|
|
|
+ }
|
|
|
|
+ {
|
|
|
|
+ var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
|
|
|
|
+ foreach (var method in _adjustThunkMethodSet)
|
|
|
|
+ {
|
|
|
|
+ sortedMethods.Add(method.CreateCallSigName(), method);
|
|
|
|
+ }
|
|
|
|
+ _adjustThunkMethodList = sortedMethods.Values.ToList();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -296,21 +305,32 @@ namespace HybridCLR.Generators.MethodBridge
|
|
|
|
|
|
List<string> lines = new List<string>(20_0000);
|
|
List<string> lines = new List<string>(20_0000);
|
|
|
|
|
|
- Debug.LogFormat("== call method count:{0}", _callMethodList.Count);
|
|
|
|
|
|
+ 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 _callMethodList)
|
|
|
|
|
|
+ foreach (var method in _native2managedMethodList)
|
|
{
|
|
{
|
|
- _platformAdaptor.GenerateCall(method, lines);
|
|
|
|
|
|
+ _platformAdaptor.GenerateNative2ManagedMethod(method, lines);
|
|
}
|
|
}
|
|
|
|
|
|
- Debug.LogFormat("== invoke method count:{0}", _invokeMethodList.Count);
|
|
|
|
- foreach (var method in _invokeMethodList)
|
|
|
|
|
|
+ _platformAdaptor.GenerateNative2ManagedStub(_native2managedMethodList, lines);
|
|
|
|
+
|
|
|
|
+ Debug.LogFormat("== adjustThunk method count:{0}", _adjustThunkMethodList.Count);
|
|
|
|
+
|
|
|
|
+ foreach (var method in _adjustThunkMethodList)
|
|
{
|
|
{
|
|
- _platformAdaptor.GenerateInvoke(method, lines);
|
|
|
|
|
|
+ _platformAdaptor.GenerateAdjustThunkMethod(method, lines);
|
|
}
|
|
}
|
|
|
|
|
|
- _platformAdaptor.GenCallStub(_callMethodList, lines);
|
|
|
|
- _platformAdaptor.GenInvokeStub(_invokeMethodList, lines);
|
|
|
|
|
|
+ _platformAdaptor.GenerateAdjustThunkStub(_adjustThunkMethodList, lines);
|
|
|
|
|
|
frr.Replace("INVOKE_STUB", string.Join("\n", lines));
|
|
frr.Replace("INVOKE_STUB", string.Join("\n", lines));
|
|
|
|
|