main
parent
d7a1765146
commit
9ea240ab82
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d26c8b77c84f09442a05f2c67e5e09b8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f97bd67938e4a9c4b9c8ddcdad621f60
|
||||
guid: f2ba16cf4bf82374c814789b6ced3abd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
|
@ -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
|
||||
{
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6070162cd5afff74f99af129c50fda5a
|
||||
guid: 80682e47c38a2f04f8af94d356688cf0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
|
@ -1,4 +1,4 @@
|
|||
namespace HybridCLR.Editor.MethodBridge
|
||||
namespace HybridCLR.Editor.ABI
|
||||
{
|
||||
public enum PlatformABI
|
||||
{
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 103704591750908419902643015e920a
|
||||
guid: a22846b73022cb2458d1c40549ab6877
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b63c5bf995a6d624dbd10d9df6cb6a7a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fe1634f74b7ca2e42bd07233b451cd94
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1eb9e19189731a344aad024a43e795bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7867dfe20d27e324e90bc13b9d4f05bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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>
|
||||
{
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 804237f201e1f7a4da1729e0eb11f75f
|
||||
guid: ffafce7f1f0bf614d95b48ca39385377
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
|
@ -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;
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 40dd1d9a2278f7846a9baa2041f74858
|
||||
guid: b7af32bdf1cf55c42bfc449820d401cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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}");
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
{
|
||||
"name": "HybridCLR.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"references": [
|
||||
"HybridCLR.Runtime"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
|
@ -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);
|
||||
|
|
|
@ -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;" : "")}
|
|
@ -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("};");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;" : "")}
|
|
@ -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;" : "")}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c172068b408c0e349b2ceee4c4635085
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f99dd22d9d81b2540b4663b3bcdf0a79
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Reference in New Issue