main
walon 2022-10-17 12:16:18 +08:00
parent d7a1765146
commit 9ea240ab82
46 changed files with 542 additions and 288 deletions

8
Editor/ABI.meta Normal file
View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d26c8b77c84f09442a05f2c67e5e09b8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -7,9 +7,9 @@ using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace HybridCLR.Editor.MethodBridge
namespace HybridCLR.Editor.ABI
{
public class MethodBridgeSig : IEquatable<MethodBridgeSig>
public class MethodDesc : IEquatable<MethodDesc>
{
public MethodDef MethodDef { get; set; }
@ -17,6 +17,8 @@ namespace HybridCLR.Editor.MethodBridge
public List<ParamInfo> ParamInfos { get; set; }
private int _hashCode;
public void Init()
{
for(int i = 0; i < ParamInfos.Count; i++)
@ -58,10 +60,10 @@ namespace HybridCLR.Editor.MethodBridge
public override bool Equals(object obj)
{
return Equals((MethodBridgeSig)obj);
return Equals((MethodDesc)obj);
}
public bool Equals(MethodBridgeSig other)
public bool Equals(MethodDesc other)
{
if (other == null)
{
@ -88,6 +90,10 @@ namespace HybridCLR.Editor.MethodBridge
public override int GetHashCode()
{
if (_hashCode != 0)
{
return _hashCode;
}
int hash = 17;
hash = hash * 23 + ReturnInfo.Type.GetHashCode();
@ -97,7 +103,7 @@ namespace HybridCLR.Editor.MethodBridge
hash = hash * 23 + p.Type.GetHashCode();
}
return hash;
return _hashCode = hash;
}
}
}

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HybridCLR.Editor.MethodBridge
namespace HybridCLR.Editor.ABI
{
public class ParamInfo

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: f97bd67938e4a9c4b9c8ddcdad621f60
guid: f2ba16cf4bf82374c814789b6ced3abd
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HybridCLR.Editor.MethodBridge
namespace HybridCLR.Editor.ABI
{
public enum ParamOrReturnType
{

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 6070162cd5afff74f99af129c50fda5a
guid: 80682e47c38a2f04f8af94d356688cf0
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -1,4 +1,4 @@
namespace HybridCLR.Editor.MethodBridge
namespace HybridCLR.Editor.ABI
{
public enum PlatformABI
{

View File

@ -0,0 +1,46 @@
using dnlib.DotNet;
using HybridCLR.Editor.Meta;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HybridCLR.Editor.ABI
{
public class HFATypeInfo
{
public TypeSig Type { get; set; }
public int Count { get; set; }
}
public class TypeCreatorArm64 : TypeCreatorBase
{
public override bool IsArch32 => false;
public override bool IsSupportHFA => true;
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
{
if (!type.IsGeneralValueType)
{
return type;
}
int typeSize = type.Size;
if (typeSize <= 8)
{
return TypeInfo.s_i8;
}
if (typeSize <= 16)
{
return TypeInfo.s_i16;
}
if (returnType)
{
return type.PorType != ParamOrReturnType.STRUCTURE_ALIGN1 ? new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, typeSize) : type;
}
return TypeInfo.s_ref;
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 103704591750908419902643015e920a
guid: a22846b73022cb2458d1c40549ab6877
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -3,66 +3,35 @@ using HybridCLR.Editor.Meta;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace HybridCLR.Editor.MethodBridge
namespace HybridCLR.Editor.ABI
{
public abstract class PlatformAdaptorBase
public abstract class TypeCreatorBase
{
private static readonly ValueTypeSizeAligmentCalculator s_calculator64 = new ValueTypeSizeAligmentCalculator(false);
private static readonly ValueTypeSizeAligmentCalculator s_calculator32 = new ValueTypeSizeAligmentCalculator(true);
public abstract bool IsArch32 { get; }
public virtual bool IsSupportHFA => false;
public TypeInfo GetNativeIntTypeInfo() => IsArch32 ? TypeInfo.s_i4 : TypeInfo.s_i8;
public abstract void GenerateManaged2NativeMethod(MethodBridgeSig method, List<string> lines);
public ValueTypeSizeAligmentCalculator Calculator => IsArch32 ? ValueTypeSizeAligmentCalculator.Caculator32 : ValueTypeSizeAligmentCalculator.Caculator64;
public abstract void GenerateNative2ManagedMethod(MethodBridgeSig method, List<string> lines);
public abstract void GenerateAdjustThunkMethod(MethodBridgeSig method, List<string> outputLines);
private readonly Dictionary<TypeSig, (int, int)> _typeSizeCache = new Dictionary<TypeSig, (int, int)>(TypeEqualityComparer.Instance);
protected abstract TypeInfo OptimizeSigType(TypeInfo type, bool returnType);
public virtual void OptimizeMethod(MethodBridgeSig method)
public (int Size, int Aligment) ComputeSizeAndAligment(TypeSig t)
{
method.TransfromSigTypes(OptimizeSigType);
}
private readonly Dictionary<TypeSig, (int, int)> _typeSizeCache64 = new Dictionary<TypeSig, (int, int)>(TypeEqualityComparer.Instance);
private readonly Dictionary<TypeSig, (int, int)> _typeSizeCache32 = new Dictionary<TypeSig, (int, int)>(TypeEqualityComparer.Instance);
public (int Size, int Aligment) ComputeSizeAndAligmentOfArch64(TypeSig t)
{
if (_typeSizeCache64.TryGetValue(t, out var sizeAndAligment))
if (_typeSizeCache.TryGetValue(t, out var sizeAndAligment))
{
return sizeAndAligment;
}
sizeAndAligment = s_calculator64.SizeAndAligmentOf(t);
_typeSizeCache64.Add(t, sizeAndAligment);
sizeAndAligment = Calculator.SizeAndAligmentOf(t);
_typeSizeCache.Add(t, sizeAndAligment);
return sizeAndAligment;
}
protected (int Size, int Aligment) ComputeSizeAndAligmentOfArch32(TypeSig t)
{
if (_typeSizeCache32.TryGetValue(t, out var sa))
{
return sa;
}
// all this just to invoke one opcode with no arguments!
sa = s_calculator32.SizeAndAligmentOf(t);
_typeSizeCache32.Add(t, sa);
return sa;
}
public TypeInfo CreateTypeInfo(TypeSig type)
{
type = type.RemovePinnedAndModifiers();
@ -70,7 +39,7 @@ namespace HybridCLR.Editor.MethodBridge
{
return GetNativeIntTypeInfo();
}
switch(type.ElementType)
switch (type.ElementType)
{
case ElementType.Void: return TypeInfo.s_void;
case ElementType.Boolean: return TypeInfo.s_u1;
@ -87,7 +56,7 @@ namespace HybridCLR.Editor.MethodBridge
case ElementType.R8: return TypeInfo.s_r8;
case ElementType.U: return IsArch32 ? TypeInfo.s_u4 : TypeInfo.s_u8;
case ElementType.I:
case ElementType.String:
case ElementType.String:
case ElementType.Ptr:
case ElementType.ByRef:
case ElementType.Class:
@ -98,7 +67,7 @@ namespace HybridCLR.Editor.MethodBridge
case ElementType.Module:
case ElementType.Var:
case ElementType.MVar:
return GetNativeIntTypeInfo();
return GetNativeIntTypeInfo();
case ElementType.TypedByRef: return CreateValueType(type);
case ElementType.ValueType:
{
@ -147,7 +116,7 @@ namespace HybridCLR.Editor.MethodBridge
continue;
}
TypeSig ftype = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
switch(ftype.ElementType)
switch (ftype.ElementType)
{
case ElementType.R4:
case ElementType.R8:
@ -203,7 +172,7 @@ namespace HybridCLR.Editor.MethodBridge
protected static TypeInfo CreateGeneralValueType(TypeSig type, int size, int aligment)
{
Debug.Assert(size % aligment == 0);
System.Diagnostics.Debug.Assert(size % aligment == 0);
switch (aligment)
{
case 1: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, size);
@ -216,7 +185,7 @@ namespace HybridCLR.Editor.MethodBridge
protected TypeInfo CreateValueType(TypeSig type)
{
(int typeSize, int typeAligment) = IsArch32 ? ComputeSizeAndAligmentOfArch32(type) : ComputeSizeAndAligmentOfArch64(type);
(int typeSize, int typeAligment) = ComputeSizeAndAligment(type);
if (IsSupportHFA && ComputHFATypeInfo(type, typeSize, out HFATypeInfo hfaTypeInfo))
{
bool isFloat = hfaTypeInfo.Type.ElementType == ElementType.R4;
@ -235,52 +204,12 @@ namespace HybridCLR.Editor.MethodBridge
}
}
public void GenerateManaged2NativeStub(List<MethodBridgeSig> methods, List<string> lines)
protected abstract TypeInfo OptimizeSigType(TypeInfo type, bool returnType);
public virtual void OptimizeMethod(MethodDesc method)
{
lines.Add($@"
Managed2NativeMethodInfo hybridclr::interpreter::g_managed2nativeStub[] =
{{
");
foreach (var method in methods)
{
lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", __M2N_{method.CreateInvokeSigName()}}},");
}
lines.Add($"\t{{nullptr, nullptr}},");
lines.Add("};");
}
public void GenerateNative2ManagedStub(List<MethodBridgeSig> methods, List<string> lines)
{
lines.Add($@"
Native2ManagedMethodInfo hybridclr::interpreter::g_native2managedStub[] =
{{
");
foreach (var method in methods)
{
lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", (Il2CppMethodPointer)__N2M_{method.CreateInvokeSigName()}}},");
}
lines.Add($"\t{{nullptr, nullptr}},");
lines.Add("};");
}
public void GenerateAdjustThunkStub(List<MethodBridgeSig> methods, List<string> lines)
{
lines.Add($@"
NativeAdjustThunkMethodInfo hybridclr::interpreter::g_adjustThunkStub[] =
{{
");
foreach (var method in methods)
{
lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", (Il2CppMethodPointer)__N2M_AdjustorThunk_{method.CreateCallSigName()}}},");
}
lines.Add($"\t{{nullptr, nullptr}},");
lines.Add("};");
method.TransfromSigTypes(OptimizeSigType);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b63c5bf995a6d624dbd10d9df6cb6a7a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HybridCLR.Editor.ABI
{
public static class TypeCreatorFactory
{
public static TypeCreatorBase CreateTypeCreator(PlatformABI abi)
{
switch(abi)
{
case PlatformABI.Arm64: return new TypeCreatorArm64();
case PlatformABI.Universal32: return new TypeCreatorUniversal32();
case PlatformABI.Universal64: return new TypeCreatorUniversal64();
default: throw new NotSupportedException(abi.ToString());
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fe1634f74b7ca2e42bd07233b451cd94
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HybridCLR.Editor.ABI
{
public class TypeCreatorUniversal32 : TypeCreatorBase
{
public override bool IsArch32 => true;
public override bool IsSupportHFA => false;
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
{
if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN4)
{
return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, type.Size);
}
return type;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1eb9e19189731a344aad024a43e795bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HybridCLR.Editor.ABI
{
public class TypeCreatorUniversal64 : TypeCreatorBase
{
public override bool IsArch32 => false;
public override bool IsSupportHFA => true;
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
{
if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN8)
{
return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, type.Size);
}
return type;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7867dfe20d27e324e90bc13b9d4f05bb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -4,7 +4,7 @@ using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace HybridCLR.Editor.MethodBridge
namespace HybridCLR.Editor.ABI
{
public class TypeInfo : IEquatable<TypeInfo>
{

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 804237f201e1f7a4da1729e0eb11f75f
guid: ffafce7f1f0bf614d95b48ca39385377
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -9,10 +9,14 @@ using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace HybridCLR.Editor.MethodBridge
namespace HybridCLR.Editor.ABI
{
public class ValueTypeSizeAligmentCalculator
{
public static ValueTypeSizeAligmentCalculator Caculator64 { get; } = new ValueTypeSizeAligmentCalculator(false);
public static ValueTypeSizeAligmentCalculator Caculator32 { get; } = new ValueTypeSizeAligmentCalculator(true);
public ValueTypeSizeAligmentCalculator(bool arch32)
{
_referenceSize = arch32 ? 4 : 8;

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 40dd1d9a2278f7846a9baa2041f74858
guid: b7af32bdf1cf55c42bfc449820d401cb
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -32,8 +32,8 @@ namespace HybridCLR.Editor.AOT
public override bool Equals(object obj)
{
ImplType o = (ImplType)obj;
return EqualityUtil.EqualsTypeSig(this.BaseType, o.BaseType)
&& EqualityUtil.EqualsTypeSigArray(this.Interfaces, o.Interfaces)
return MetaUtil.EqualsTypeSig(this.BaseType, o.BaseType)
&& MetaUtil.EqualsTypeSigArray(this.Interfaces, o.Interfaces)
&& this.ValueType == o.ValueType;
}

View File

@ -45,7 +45,7 @@ namespace HybridCLR.Editor.Commands
}
}
var analyzer = new Analyzer(MetaUtil.CreateBuildTargetAssemblyResolver(EditorUserBuildSettings.activeBuildTarget), HybridCLRSettings.Instance.collectAssetReferenceTypes);
var analyzer = new Analyzer(Meta.MetaUtil.CreateBuildTargetAssemblyResolver(EditorUserBuildSettings.activeBuildTarget), HybridCLRSettings.Instance.collectAssetReferenceTypes);
var refTypes = analyzer.CollectRefs(hotfixAssembles);
Debug.Log($"[LinkGeneratorCommand] hotfix assembly count:{hotfixAssembles.Count}, ref type count:{refTypes.Count} output:{Application.dataPath}/{ls.outputLinkFile}");

View File

@ -1,4 +1,5 @@
using HybridCLR.Editor;
using HybridCLR.Editor.ABI;
using HybridCLR.Editor.Meta;
using HybridCLR.Editor.MethodBridge;
using System;
@ -45,7 +46,7 @@ namespace HybridCLR.Editor.Commands
{
var g = new Generator(new Generator.Options()
{
CallConvention = platform,
PlatformABI = platform,
TemplateCode = templateCode,
OutputFile = outputFile,
GenericMethods = analyzer.GenericMethods,

View File

@ -1,5 +1,6 @@
using HybridCLR.Editor.Link;
using HybridCLR.Editor.ReversePInvokeWrap;
using HybridCLR.Editor.ABI;
using HybridCLR.Editor.Link;
using HybridCLR.Editor.Meta;
using System;
using System.Collections.Generic;
using System.IO;
@ -19,13 +20,32 @@ namespace HybridCLR.Editor.Commands
[MenuItem("HybridCLR/Generate/ReversePInvokeWrapper", priority = 103)]
public static void GenerateReversePInvokeWrapper()
{
string ReversePInvokeWrapperStubFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/metadata/ReversePInvokeMethodStub.cpp";
string wrapperTemplateStr = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/ReversePInvokeMethodStub.cpp.txt");
int wrapperCount = SettingsUtil.HybridCLRSettings.ReversePInvokeWrapperCount;
var generator = new Generator();
generator.Generate(wrapperTemplateStr, wrapperCount,ReversePInvokeWrapperStubFile);
Debug.Log($"GenerateReversePInvokeWrapper. wraperCount:{wrapperCount} output:{ReversePInvokeWrapperStubFile}");
MethodBridgeGeneratorCommand.CleanIl2CppBuildCache();
CompileDllCommand.CompileDllActiveBuildTarget();
using (var cache = new AssemblyCache(MetaUtil.CreateBuildTargetAssemblyResolver(EditorUserBuildSettings.activeBuildTarget)))
{
var analyzer = new ReversePInvokeWrap.Analyzer(cache, SettingsUtil.HotUpdateAssemblyNames);
var methods = analyzer.CollectMonoPInvokeCallbackMethods();
foreach (var method in methods)
{
Debug.Log($"method:{method.Method}");
}
var generateJobs = new List<(PlatformABI, string)>()
{
(PlatformABI.Arm64, "HYBRIDCLR_ABI_ARM_64"),
(PlatformABI.Universal64, "HYBRIDCLR_ABI_UNIVERSAL_64"),
(PlatformABI.Universal32, "HYBRIDCLR_ABI_UNIVERSAL_32"),
};
}
return;
//string ReversePInvokeWrapperStubFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/metadata/ReversePInvokeMethodStub.cpp";
//string wrapperTemplateStr = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/ReversePInvokeMethodStub.cpp.txt");
//int wrapperCount = SettingsUtil.HybridCLRSettings.ReversePInvokeWrapperCount;
//var generator = new Generator();
//generator.Generate(wrapperTemplateStr, wrapperCount,ReversePInvokeWrapperStubFile);
//Debug.Log($"GenerateReversePInvokeWrapper. wraperCount:{wrapperCount} output:{ReversePInvokeWrapperStubFile}");
//MethodBridgeGeneratorCommand.CleanIl2CppBuildCache();
}
}
}

View File

@ -1,49 +0,0 @@
using dnlib.DotNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HybridCLR.Editor
{
public static class EqualityUtil
{
public static bool EqualsTypeSig(TypeSig a, TypeSig b)
{
if (a == b)
{
return true;
}
if (a != null && b != null)
{
return TypeEqualityComparer.Instance.Equals(a, b);
}
return false;
}
public static bool EqualsTypeSigArray(List<TypeSig> a, List<TypeSig> b)
{
if (a == b)
{
return true;
}
if (a != null && b != null)
{
if (a.Count != b.Count)
{
return false;
}
for (int i = 0; i < a.Count; i++)
{
if (!TypeEqualityComparer.Instance.Equals(a[i], b[i]))
{
return false;
}
}
return true;
}
return false;
}
}
}

View File

@ -1,7 +1,9 @@
{
"name": "HybridCLR.Editor",
"rootNamespace": "",
"references": [],
"references": [
"HybridCLR.Runtime"
],
"includePlatforms": [
"Editor"
],

View File

@ -29,7 +29,7 @@ namespace HybridCLR.Editor.Meta
{
if (obj is GenericClass gc)
{
return Type == gc.Type && EqualityUtil.EqualsTypeSigArray(KlassInst, gc.KlassInst);
return Type == gc.Type && MetaUtil.EqualsTypeSigArray(KlassInst, gc.KlassInst);
}
return false;
}

View File

@ -33,8 +33,8 @@ namespace HybridCLR.Editor.Meta
{
GenericMethod o = (GenericMethod)obj;
return Method == o.Method
&& EqualityUtil.EqualsTypeSigArray(KlassInst, o.KlassInst)
&& EqualityUtil.EqualsTypeSigArray(MethodInst, o.MethodInst);
&& MetaUtil.EqualsTypeSigArray(KlassInst, o.KlassInst)
&& MetaUtil.EqualsTypeSigArray(MethodInst, o.MethodInst);
}
public override int GetHashCode()

View File

@ -6,12 +6,49 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IAssemblyResolver = HybridCLR.Editor.Meta.IAssemblyResolver;
namespace HybridCLR.Editor
namespace HybridCLR.Editor.Meta
{
public static class MetaUtil
{
public static bool EqualsTypeSig(TypeSig a, TypeSig b)
{
if (a == b)
{
return true;
}
if (a != null && b != null)
{
return TypeEqualityComparer.Instance.Equals(a, b);
}
return false;
}
public static bool EqualsTypeSigArray(List<TypeSig> a, List<TypeSig> b)
{
if (a == b)
{
return true;
}
if (a != null && b != null)
{
if (a.Count != b.Count)
{
return false;
}
for (int i = 0; i < a.Count; i++)
{
if (!TypeEqualityComparer.Instance.Equals(a[i], b[i]))
{
return false;
}
}
return true;
}
return false;
}
public static TypeSig Inflate(TypeSig sig, GenericArgumentContext ctx)
{
if (!sig.ContainsGenericParameter)

View File

@ -1,4 +1,5 @@
using dnlib.DotNet;
using HybridCLR.Editor.ABI;
using HybridCLR.Editor.Meta;
using HybridCLR.Editor.Template;
using System;
@ -10,6 +11,7 @@ using System.Text;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
using TypeInfo = HybridCLR.Editor.ABI.TypeInfo;
namespace HybridCLR.Editor.MethodBridge
{
@ -17,7 +19,7 @@ namespace HybridCLR.Editor.MethodBridge
{
public class Options
{
public PlatformABI CallConvention { get; set; }
public PlatformABI PlatformABI { get; set; }
public string TemplateCode { get; set; }
@ -36,19 +38,21 @@ namespace HybridCLR.Editor.MethodBridge
private readonly string _outputFile;
private readonly PlatformAdaptorBase _platformAdaptor;
private readonly PlatformGeneratorBase _platformAdaptor;
private readonly HashSet<MethodBridgeSig> _managed2nativeMethodSet = new HashSet<MethodBridgeSig>();
private readonly TypeCreatorBase _typeCreator;
private List<MethodBridgeSig> _managed2nativeMethodList;
private readonly HashSet<MethodDesc> _managed2nativeMethodSet = new HashSet<MethodDesc>();
private readonly HashSet<MethodBridgeSig> _native2managedMethodSet = new HashSet<MethodBridgeSig>();
private List<MethodDesc> _managed2nativeMethodList;
private List<MethodBridgeSig> _native2managedMethodList;
private readonly HashSet<MethodDesc> _native2managedMethodSet = new HashSet<MethodDesc>();
private readonly HashSet<MethodBridgeSig> _adjustThunkMethodSet = new HashSet<MethodBridgeSig>();
private List<MethodDesc> _native2managedMethodList;
private List<MethodBridgeSig> _adjustThunkMethodList;
private readonly HashSet<MethodDesc> _adjustThunkMethodSet = new HashSet<MethodDesc>();
private List<MethodDesc> _adjustThunkMethodList;
public Generator(Options options)
{
@ -56,21 +60,22 @@ namespace HybridCLR.Editor.MethodBridge
_genericMethods = options.GenericMethods;
_templateCode = options.TemplateCode;
_outputFile = options.OutputFile;
_platformAdaptor = CreatePlatformAdaptor(options.CallConvention);
_platformAdaptor = CreatePlatformAdaptor(options.PlatformABI);
_typeCreator = TypeCreatorFactory.CreateTypeCreator(options.PlatformABI);
}
private static PlatformAdaptorBase CreatePlatformAdaptor(PlatformABI type)
private static PlatformGeneratorBase CreatePlatformAdaptor(PlatformABI type)
{
switch (type)
{
case PlatformABI.Universal32: return new PlatformAdaptor_Universal32();
case PlatformABI.Universal64: return new PlatformAdaptor_Universal64();
case PlatformABI.Arm64: return new PlatformAdaptor_Arm64();
case PlatformABI.Universal32: return new PlatformGeneratorUniversal32();
case PlatformABI.Universal64: return new PlatformGeneratorUniversal64();
case PlatformABI.Arm64: return new PlatformGeneratorArm64();
default: throw new NotSupportedException();
}
}
private MethodBridgeSig CreateMethodBridgeSig(MethodDef methodDef, bool forceRemoveThis, TypeSig returnType, List<TypeSig> parameters)
private MethodDesc CreateMethodDesc(MethodDef methodDef, bool forceRemoveThis, TypeSig returnType, List<TypeSig> parameters)
{
var paramInfos = new List<ParamInfo>();
if (forceRemoveThis && !methodDef.IsStatic)
@ -79,19 +84,19 @@ namespace HybridCLR.Editor.MethodBridge
}
foreach (var paramInfo in parameters)
{
paramInfos.Add(new ParamInfo() { Type = _platformAdaptor.CreateTypeInfo(paramInfo) });
paramInfos.Add(new ParamInfo() { Type = _typeCreator.CreateTypeInfo(paramInfo) });
}
var mbs = new MethodBridgeSig()
var mbs = new MethodDesc()
{
MethodDef = methodDef,
ReturnInfo = new ReturnInfo() { Type = returnType != null ? _platformAdaptor.CreateTypeInfo(returnType) : TypeInfo.s_void },
ReturnInfo = new ReturnInfo() { Type = returnType != null ? _typeCreator.CreateTypeInfo(returnType) : TypeInfo.s_void },
ParamInfos = paramInfos,
};
_platformAdaptor.OptimizeMethod(mbs);
_typeCreator.OptimizeMethod(mbs);
return mbs;
}
private void AddManaged2NativeMethod(MethodBridgeSig method)
private void AddManaged2NativeMethod(MethodDesc method)
{
if (_managed2nativeMethodSet.Add(method))
{
@ -99,7 +104,7 @@ namespace HybridCLR.Editor.MethodBridge
}
}
private void AddNative2ManagedMethod(MethodBridgeSig method)
private void AddNative2ManagedMethod(MethodDesc method)
{
if (_native2managedMethodSet.Add(method))
{
@ -107,7 +112,7 @@ namespace HybridCLR.Editor.MethodBridge
}
}
private void AddAdjustThunkMethod(MethodBridgeSig method)
private void AddAdjustThunkMethod(MethodDesc method)
{
if (_adjustThunkMethodSet.Add(method))
{
@ -136,7 +141,7 @@ namespace HybridCLR.Editor.MethodBridge
parameters = method.Parameters.Select(p => MetaUtil.Inflate(p.Type, gc)).ToList();
}
var m2nMethod = CreateMethodBridgeSig(method, false, returnType, parameters);
var m2nMethod = CreateMethodDesc(method, false, returnType, parameters);
AddManaged2NativeMethod(m2nMethod);
if (method.IsVirtual)
@ -145,12 +150,12 @@ namespace HybridCLR.Editor.MethodBridge
{
AddAdjustThunkMethod(m2nMethod);
}
//var adjustThunkMethod = CreateMethodBridgeSig(method, true, returnType, parameters);
//var adjustThunkMethod = CreateMethodDesc(method, true, returnType, parameters);
AddNative2ManagedMethod(m2nMethod);
}
if (method.Name == "Invoke" && method.DeclaringType.IsDelegate)
{
var openMethod = CreateMethodBridgeSig(method, true, returnType, parameters);
var openMethod = CreateMethodDesc(method, true, returnType, parameters);
AddNative2ManagedMethod(openMethod);
}
}
@ -168,7 +173,7 @@ namespace HybridCLR.Editor.MethodBridge
}
{
var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
var sortedMethods = new SortedDictionary<string, MethodDesc>();
foreach (var method in _managed2nativeMethodSet)
{
sortedMethods.Add(method.CreateCallSigName(), method);
@ -176,7 +181,7 @@ namespace HybridCLR.Editor.MethodBridge
_managed2nativeMethodList = sortedMethods.Values.ToList();
}
{
var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
var sortedMethods = new SortedDictionary<string, MethodDesc>();
foreach (var method in _native2managedMethodSet)
{
sortedMethods.Add(method.CreateCallSigName(), method);
@ -184,7 +189,7 @@ namespace HybridCLR.Editor.MethodBridge
_native2managedMethodList = sortedMethods.Values.ToList();
}
{
var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
var sortedMethods = new SortedDictionary<string, MethodDesc>();
foreach (var method in _adjustThunkMethodSet)
{
sortedMethods.Add(method.CreateCallSigName(), method);

View File

@ -1,4 +1,5 @@
using dnlib.DotNet;
using HybridCLR.Editor.ABI;
using System;
using System.Collections.Generic;
using System.Linq;
@ -10,48 +11,17 @@ using UnityEngine;
namespace HybridCLR.Editor.MethodBridge
{
public class HFATypeInfo
public class PlatformGeneratorArm64 : PlatformGeneratorBase
{
public TypeSig Type { get; set; }
public override PlatformABI PlatformABI { get; } = PlatformABI.Universal64;
public int Count { get; set; }
}
public class PlatformAdaptor_Arm64 : PlatformAdaptorBase
{
public PlatformABI CallConventionType { get; } = PlatformABI.Universal64;
public override bool IsArch32 => false;
public override bool IsSupportHFA => true;
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
public override void GenerateManaged2NativeMethod(MethodDesc method, List<string> lines)
{
if (!type.IsGeneralValueType)
{
return type;
}
int typeSize = type.Size;
if (typeSize <= 8)
{
return TypeInfo.s_i8;
}
if (typeSize <= 16)
{
return TypeInfo.s_i16;
}
if (returnType)
{
return type.PorType != ParamOrReturnType.STRUCTURE_ALIGN1 ? new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, typeSize) : type;
}
return TypeInfo.s_ref;
}
public override void GenerateManaged2NativeMethod(MethodBridgeSig method, List<string> lines)
{
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.CallConventionType)).Concat(new string[] { "method" }));
string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.PlatformABI)).Concat(new string[] { "method" }));
lines.Add($@"
// {method.MethodDef}
@ -63,16 +33,16 @@ static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_
");
}
public override void GenerateNative2ManagedMethod(MethodBridgeSig method, List<string> lines)
public override void GenerateNative2ManagedMethod(MethodDesc method, List<string> lines)
{
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
lines.Add($@"
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
{{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.CallConventionType)))} }};
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.PlatformABI)))} }};
StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
Interpreter::Execute(method, args, ret);
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}
@ -80,9 +50,9 @@ static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}
");
}
public override void GenerateAdjustThunkMethod(MethodBridgeSig method, List<string> lines)
public override void GenerateAdjustThunkMethod(MethodDesc method, List<string> lines)
{
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
@ -90,7 +60,7 @@ static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
{{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.CallConventionType))))} }};
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.PlatformABI))))} }};
StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
Interpreter::Execute(method, args, ret);
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}

View File

@ -0,0 +1,75 @@
using dnlib.DotNet;
using HybridCLR.Editor.ABI;
using HybridCLR.Editor.Meta;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using TypeInfo = HybridCLR.Editor.ABI.TypeInfo;
namespace HybridCLR.Editor.MethodBridge
{
public abstract class PlatformGeneratorBase
{
public abstract PlatformABI PlatformABI { get; }
public abstract void GenerateManaged2NativeMethod(MethodDesc method, List<string> lines);
public abstract void GenerateNative2ManagedMethod(MethodDesc method, List<string> lines);
public abstract void GenerateAdjustThunkMethod(MethodDesc method, List<string> outputLines);
public void GenerateManaged2NativeStub(List<MethodDesc> methods, List<string> lines)
{
lines.Add($@"
Managed2NativeMethodInfo hybridclr::interpreter::g_managed2nativeStub[] =
{{
");
foreach (var method in methods)
{
lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", __M2N_{method.CreateInvokeSigName()}}},");
}
lines.Add($"\t{{nullptr, nullptr}},");
lines.Add("};");
}
public void GenerateNative2ManagedStub(List<MethodDesc> methods, List<string> lines)
{
lines.Add($@"
Native2ManagedMethodInfo hybridclr::interpreter::g_native2managedStub[] =
{{
");
foreach (var method in methods)
{
lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", (Il2CppMethodPointer)__N2M_{method.CreateInvokeSigName()}}},");
}
lines.Add($"\t{{nullptr, nullptr}},");
lines.Add("};");
}
public void GenerateAdjustThunkStub(List<MethodDesc> methods, List<string> lines)
{
lines.Add($@"
NativeAdjustThunkMethodInfo hybridclr::interpreter::g_adjustThunkStub[] =
{{
");
foreach (var method in methods)
{
lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", (Il2CppMethodPointer)__N2M_AdjustorThunk_{method.CreateCallSigName()}}},");
}
lines.Add($"\t{{nullptr, nullptr}},");
lines.Add("};");
}
}
}

View File

@ -1,4 +1,5 @@
using dnlib.DotNet;
using HybridCLR.Editor.ABI;
using System;
using System.Collections.Generic;
using System.Linq;
@ -9,11 +10,9 @@ using UnityEngine;
namespace HybridCLR.Editor.MethodBridge
{
internal class PlatformAdaptor_Universal32 : PlatformAdaptorBase
public class PlatformGeneratorUniversal32 : PlatformGeneratorBase
{
public PlatformABI CallConventionType { get; } = PlatformABI.Universal32;
public override bool IsArch32 => true;
public override PlatformABI PlatformABI { get; } = PlatformABI.Universal32;
//protected override TypeInfo CreateValueType(TypeSig type, bool returnValue)
//{
@ -22,19 +21,11 @@ namespace HybridCLR.Editor.MethodBridge
// return CreateGeneralValueType(type, typeSize, actualAliment);
//}
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
{
if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN4)
{
return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, type.Size);
}
return type;
}
public override void GenerateManaged2NativeMethod(MethodBridgeSig method, List<string> lines)
public override void GenerateManaged2NativeMethod(MethodDesc method, List<string> lines)
{
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.CallConventionType)).Concat(new string[] { "method" }));
string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.PlatformABI)).Concat(new string[] { "method" }));
lines.Add($@"
// {method.MethodDef}
@ -45,25 +36,25 @@ static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_
}}
");
}
public override void GenerateNative2ManagedMethod(MethodBridgeSig method, List<string> lines)
public override void GenerateNative2ManagedMethod(MethodDesc method, List<string> lines)
{
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
lines.Add($@"
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
{{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.CallConventionType)))} }};
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.PlatformABI)))} }};
StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
Interpreter::Execute(method, args, ret);
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}
}}
");
}
public override void GenerateAdjustThunkMethod(MethodBridgeSig method, List<string> lines)
public override void GenerateAdjustThunkMethod(MethodDesc method, List<string> lines)
{
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
@ -71,7 +62,7 @@ static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
{{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.CallConventionType))))} }};
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.PlatformABI))))} }};
StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
Interpreter::Execute(method, args, ret);
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}

View File

@ -1,4 +1,5 @@
using dnlib.DotNet;
using HybridCLR.Editor.ABI;
using System;
using System.Collections.Generic;
using System.Linq;
@ -6,33 +7,21 @@ using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using TypeInfo = HybridCLR.Editor.ABI.TypeInfo;
namespace HybridCLR.Editor.MethodBridge
{
public class PlatformAdaptor_Universal64 : PlatformAdaptorBase
public class PlatformGeneratorUniversal64 : PlatformGeneratorBase
{
public PlatformABI CallConventionType { get; } = PlatformABI.Universal64;
public override PlatformABI PlatformABI { get; } = PlatformABI.Universal64;
public override bool IsArch32 => false;
public override bool IsSupportHFA => true;
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
public override void GenerateManaged2NativeMethod(MethodDesc method, List<string> lines)
{
if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN8)
{
return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, type.Size);
}
return type;
}
public override void GenerateManaged2NativeMethod(MethodBridgeSig method, List<string> lines)
{
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
string paramTypeListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()}").Concat(new string[] { "const MethodInfo*" })); ;
string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.CallConventionType)).Concat(new string[] { "method" }));
string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.PlatformABI)).Concat(new string[] { "method" }));
lines.Add($@"
// {method.MethodDef}
@ -43,15 +32,15 @@ static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_
}}
");
}
public override void GenerateNative2ManagedMethod(MethodBridgeSig method, List<string> lines)
public override void GenerateNative2ManagedMethod(MethodDesc method, List<string> lines)
{
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
lines.Add($@"
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
{{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.CallConventionType)))} }};
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.PlatformABI)))} }};
StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
Interpreter::Execute(method, args, ret);
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}
@ -59,15 +48,15 @@ static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}
");
}
public override void GenerateAdjustThunkMethod(MethodBridgeSig method, List<string> lines)
public override void GenerateAdjustThunkMethod(MethodDesc method, List<string> lines)
{
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.CallConventionType);
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
lines.Add($@"
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
{{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.CallConventionType))))} }};
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.PlatformABI))))} }};
StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
Interpreter::Execute(method, args, ret);
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}

View File

@ -0,0 +1,65 @@
using dnlib.DotNet;
using HybridCLR.Editor.Meta;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace HybridCLR.Editor.ReversePInvokeWrap
{
public class ReversePInvokeMethodInfo
{
public MethodDef Method { get; set; }
public CustomAttribute GenerationAttribute { get; set; }
}
public class Analyzer
{
private readonly List<ModuleDefMD> _rootModules = new List<ModuleDefMD>();
public Analyzer(AssemblyCache cache, List<string> assemblyNames)
{
foreach(var assemblyName in assemblyNames)
{
_rootModules.Add(cache.LoadModule(assemblyName));
}
}
public List<ReversePInvokeMethodInfo> CollectMonoPInvokeCallbackMethods()
{
var wrapperMethods = new List<ReversePInvokeMethodInfo>();
foreach(var mod in _rootModules)
{
Debug.Log($"ass:{mod.FullName} methodcount:{mod.Metadata.TablesStream.MethodTable.Rows}");
for (uint rid = 1, n = mod.Metadata.TablesStream.MethodTable.Rows; rid <= n; rid++)
{
var method = mod.ResolveMethod(rid);
//Debug.Log($"method:{method}");
if (!method.IsStatic || !method.HasCustomAttributes)
{
continue;
}
CustomAttribute wa = method.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "AOT.MonoPInvokeCallbackAttribute");
if (wa == null)
{
continue;
}
//foreach (var ca in method.CustomAttributes)
//{
// Debug.Log($"{ca.AttributeType.FullName} {ca.TypeFullName}");
//}
wrapperMethods.Add(new ReversePInvokeMethodInfo()
{
Method = method,
GenerationAttribute = method.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "HybridCLR.ReversePInvokeWrapperGenerationAttribute"),
});
}
}
return wrapperMethods;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c172068b408c0e349b2ceee4c4635085
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HybridCLR
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class ReversePInvokeWrapperGenerationAttribute : Attribute
{
public int ReserveWrapperCount { get; }
public ReversePInvokeWrapperGenerationAttribute(int reserveWrapperCount)
{
ReserveWrapperCount = reserveWrapperCount;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f99dd22d9d81b2540b4663b3bcdf0a79
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: