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.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
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; }
|
public MethodDef MethodDef { get; set; }
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
|
|
||||||
public List<ParamInfo> ParamInfos { get; set; }
|
public List<ParamInfo> ParamInfos { get; set; }
|
||||||
|
|
||||||
|
private int _hashCode;
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
for(int i = 0; i < ParamInfos.Count; i++)
|
for(int i = 0; i < ParamInfos.Count; i++)
|
||||||
|
@ -58,10 +60,10 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
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)
|
if (other == null)
|
||||||
{
|
{
|
||||||
|
@ -88,6 +90,10 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
|
if (_hashCode != 0)
|
||||||
|
{
|
||||||
|
return _hashCode;
|
||||||
|
}
|
||||||
int hash = 17;
|
int hash = 17;
|
||||||
|
|
||||||
hash = hash * 23 + ReturnInfo.Type.GetHashCode();
|
hash = hash * 23 + ReturnInfo.Type.GetHashCode();
|
||||||
|
@ -97,7 +103,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
hash = hash * 23 + p.Type.GetHashCode();
|
hash = hash * 23 + p.Type.GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash;
|
return _hashCode = hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
namespace HybridCLR.Editor.ABI
|
||||||
{
|
{
|
||||||
|
|
||||||
public class ParamInfo
|
public class ParamInfo
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: f97bd67938e4a9c4b9c8ddcdad621f60
|
guid: f2ba16cf4bf82374c814789b6ced3abd
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -4,7 +4,7 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
namespace HybridCLR.Editor.ABI
|
||||||
{
|
{
|
||||||
public enum ParamOrReturnType
|
public enum ParamOrReturnType
|
||||||
{
|
{
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 6070162cd5afff74f99af129c50fda5a
|
guid: 80682e47c38a2f04f8af94d356688cf0
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -1,4 +1,4 @@
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
namespace HybridCLR.Editor.ABI
|
||||||
{
|
{
|
||||||
public enum PlatformABI
|
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
|
fileFormatVersion: 2
|
||||||
guid: 103704591750908419902643015e920a
|
guid: a22846b73022cb2458d1c40549ab6877
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -3,66 +3,35 @@ using HybridCLR.Editor.Meta;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using System.Reflection.Emit;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
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 abstract bool IsArch32 { get; }
|
||||||
|
|
||||||
public virtual bool IsSupportHFA => false;
|
public virtual bool IsSupportHFA => false;
|
||||||
|
|
||||||
public TypeInfo GetNativeIntTypeInfo() => IsArch32 ? TypeInfo.s_i4 : TypeInfo.s_i8;
|
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 (int Size, int Aligment) ComputeSizeAndAligment(TypeSig t)
|
||||||
|
|
||||||
public virtual void OptimizeMethod(MethodBridgeSig method)
|
|
||||||
{
|
{
|
||||||
method.TransfromSigTypes(OptimizeSigType);
|
if (_typeSizeCache.TryGetValue(t, out var sizeAndAligment))
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
return sizeAndAligment;
|
return sizeAndAligment;
|
||||||
}
|
}
|
||||||
sizeAndAligment = s_calculator64.SizeAndAligmentOf(t);
|
sizeAndAligment = Calculator.SizeAndAligmentOf(t);
|
||||||
_typeSizeCache64.Add(t, sizeAndAligment);
|
_typeSizeCache.Add(t, sizeAndAligment);
|
||||||
return 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)
|
public TypeInfo CreateTypeInfo(TypeSig type)
|
||||||
{
|
{
|
||||||
type = type.RemovePinnedAndModifiers();
|
type = type.RemovePinnedAndModifiers();
|
||||||
|
@ -70,7 +39,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
{
|
{
|
||||||
return GetNativeIntTypeInfo();
|
return GetNativeIntTypeInfo();
|
||||||
}
|
}
|
||||||
switch(type.ElementType)
|
switch (type.ElementType)
|
||||||
{
|
{
|
||||||
case ElementType.Void: return TypeInfo.s_void;
|
case ElementType.Void: return TypeInfo.s_void;
|
||||||
case ElementType.Boolean: return TypeInfo.s_u1;
|
case ElementType.Boolean: return TypeInfo.s_u1;
|
||||||
|
@ -87,7 +56,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
case ElementType.R8: return TypeInfo.s_r8;
|
case ElementType.R8: return TypeInfo.s_r8;
|
||||||
case ElementType.U: return IsArch32 ? TypeInfo.s_u4 : TypeInfo.s_u8;
|
case ElementType.U: return IsArch32 ? TypeInfo.s_u4 : TypeInfo.s_u8;
|
||||||
case ElementType.I:
|
case ElementType.I:
|
||||||
case ElementType.String:
|
case ElementType.String:
|
||||||
case ElementType.Ptr:
|
case ElementType.Ptr:
|
||||||
case ElementType.ByRef:
|
case ElementType.ByRef:
|
||||||
case ElementType.Class:
|
case ElementType.Class:
|
||||||
|
@ -98,7 +67,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
case ElementType.Module:
|
case ElementType.Module:
|
||||||
case ElementType.Var:
|
case ElementType.Var:
|
||||||
case ElementType.MVar:
|
case ElementType.MVar:
|
||||||
return GetNativeIntTypeInfo();
|
return GetNativeIntTypeInfo();
|
||||||
case ElementType.TypedByRef: return CreateValueType(type);
|
case ElementType.TypedByRef: return CreateValueType(type);
|
||||||
case ElementType.ValueType:
|
case ElementType.ValueType:
|
||||||
{
|
{
|
||||||
|
@ -147,7 +116,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TypeSig ftype = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
|
TypeSig ftype = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
|
||||||
switch(ftype.ElementType)
|
switch (ftype.ElementType)
|
||||||
{
|
{
|
||||||
case ElementType.R4:
|
case ElementType.R4:
|
||||||
case ElementType.R8:
|
case ElementType.R8:
|
||||||
|
@ -203,7 +172,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
|
|
||||||
protected static TypeInfo CreateGeneralValueType(TypeSig type, int size, int aligment)
|
protected static TypeInfo CreateGeneralValueType(TypeSig type, int size, int aligment)
|
||||||
{
|
{
|
||||||
Debug.Assert(size % aligment == 0);
|
System.Diagnostics.Debug.Assert(size % aligment == 0);
|
||||||
switch (aligment)
|
switch (aligment)
|
||||||
{
|
{
|
||||||
case 1: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, size);
|
case 1: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, size);
|
||||||
|
@ -216,7 +185,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
|
|
||||||
protected TypeInfo CreateValueType(TypeSig type)
|
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))
|
if (IsSupportHFA && ComputHFATypeInfo(type, typeSize, out HFATypeInfo hfaTypeInfo))
|
||||||
{
|
{
|
||||||
bool isFloat = hfaTypeInfo.Type.ElementType == ElementType.R4;
|
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($@"
|
method.TransfromSigTypes(OptimizeSigType);
|
||||||
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("};");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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 System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
namespace HybridCLR.Editor.ABI
|
||||||
{
|
{
|
||||||
public class TypeInfo : IEquatable<TypeInfo>
|
public class TypeInfo : IEquatable<TypeInfo>
|
||||||
{
|
{
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 804237f201e1f7a4da1729e0eb11f75f
|
guid: ffafce7f1f0bf614d95b48ca39385377
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -9,10 +9,14 @@ using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
namespace HybridCLR.Editor.ABI
|
||||||
{
|
{
|
||||||
public class ValueTypeSizeAligmentCalculator
|
public class ValueTypeSizeAligmentCalculator
|
||||||
{
|
{
|
||||||
|
public static ValueTypeSizeAligmentCalculator Caculator64 { get; } = new ValueTypeSizeAligmentCalculator(false);
|
||||||
|
|
||||||
|
public static ValueTypeSizeAligmentCalculator Caculator32 { get; } = new ValueTypeSizeAligmentCalculator(true);
|
||||||
|
|
||||||
public ValueTypeSizeAligmentCalculator(bool arch32)
|
public ValueTypeSizeAligmentCalculator(bool arch32)
|
||||||
{
|
{
|
||||||
_referenceSize = arch32 ? 4 : 8;
|
_referenceSize = arch32 ? 4 : 8;
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 40dd1d9a2278f7846a9baa2041f74858
|
guid: b7af32bdf1cf55c42bfc449820d401cb
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -32,8 +32,8 @@ namespace HybridCLR.Editor.AOT
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
ImplType o = (ImplType)obj;
|
ImplType o = (ImplType)obj;
|
||||||
return EqualityUtil.EqualsTypeSig(this.BaseType, o.BaseType)
|
return MetaUtil.EqualsTypeSig(this.BaseType, o.BaseType)
|
||||||
&& EqualityUtil.EqualsTypeSigArray(this.Interfaces, o.Interfaces)
|
&& MetaUtil.EqualsTypeSigArray(this.Interfaces, o.Interfaces)
|
||||||
&& this.ValueType == o.ValueType;
|
&& 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);
|
var refTypes = analyzer.CollectRefs(hotfixAssembles);
|
||||||
|
|
||||||
Debug.Log($"[LinkGeneratorCommand] hotfix assembly count:{hotfixAssembles.Count}, ref type count:{refTypes.Count} output:{Application.dataPath}/{ls.outputLinkFile}");
|
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;
|
||||||
|
using HybridCLR.Editor.ABI;
|
||||||
using HybridCLR.Editor.Meta;
|
using HybridCLR.Editor.Meta;
|
||||||
using HybridCLR.Editor.MethodBridge;
|
using HybridCLR.Editor.MethodBridge;
|
||||||
using System;
|
using System;
|
||||||
|
@ -45,7 +46,7 @@ namespace HybridCLR.Editor.Commands
|
||||||
{
|
{
|
||||||
var g = new Generator(new Generator.Options()
|
var g = new Generator(new Generator.Options()
|
||||||
{
|
{
|
||||||
CallConvention = platform,
|
PlatformABI = platform,
|
||||||
TemplateCode = templateCode,
|
TemplateCode = templateCode,
|
||||||
OutputFile = outputFile,
|
OutputFile = outputFile,
|
||||||
GenericMethods = analyzer.GenericMethods,
|
GenericMethods = analyzer.GenericMethods,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using HybridCLR.Editor.Link;
|
using HybridCLR.Editor.ABI;
|
||||||
using HybridCLR.Editor.ReversePInvokeWrap;
|
using HybridCLR.Editor.Link;
|
||||||
|
using HybridCLR.Editor.Meta;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
@ -19,13 +20,32 @@ namespace HybridCLR.Editor.Commands
|
||||||
[MenuItem("HybridCLR/Generate/ReversePInvokeWrapper", priority = 103)]
|
[MenuItem("HybridCLR/Generate/ReversePInvokeWrapper", priority = 103)]
|
||||||
public static void GenerateReversePInvokeWrapper()
|
public static void GenerateReversePInvokeWrapper()
|
||||||
{
|
{
|
||||||
string ReversePInvokeWrapperStubFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/metadata/ReversePInvokeMethodStub.cpp";
|
CompileDllCommand.CompileDllActiveBuildTarget();
|
||||||
string wrapperTemplateStr = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/ReversePInvokeMethodStub.cpp.txt");
|
using (var cache = new AssemblyCache(MetaUtil.CreateBuildTargetAssemblyResolver(EditorUserBuildSettings.activeBuildTarget)))
|
||||||
int wrapperCount = SettingsUtil.HybridCLRSettings.ReversePInvokeWrapperCount;
|
{
|
||||||
var generator = new Generator();
|
var analyzer = new ReversePInvokeWrap.Analyzer(cache, SettingsUtil.HotUpdateAssemblyNames);
|
||||||
generator.Generate(wrapperTemplateStr, wrapperCount,ReversePInvokeWrapperStubFile);
|
var methods = analyzer.CollectMonoPInvokeCallbackMethods();
|
||||||
Debug.Log($"GenerateReversePInvokeWrapper. wraperCount:{wrapperCount} output:{ReversePInvokeWrapperStubFile}");
|
foreach (var method in methods)
|
||||||
MethodBridgeGeneratorCommand.CleanIl2CppBuildCache();
|
{
|
||||||
|
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",
|
"name": "HybridCLR.Editor",
|
||||||
"rootNamespace": "",
|
"rootNamespace": "",
|
||||||
"references": [],
|
"references": [
|
||||||
|
"HybridCLR.Runtime"
|
||||||
|
],
|
||||||
"includePlatforms": [
|
"includePlatforms": [
|
||||||
"Editor"
|
"Editor"
|
||||||
],
|
],
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace HybridCLR.Editor.Meta
|
||||||
{
|
{
|
||||||
if (obj is GenericClass gc)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,8 @@ namespace HybridCLR.Editor.Meta
|
||||||
{
|
{
|
||||||
GenericMethod o = (GenericMethod)obj;
|
GenericMethod o = (GenericMethod)obj;
|
||||||
return Method == o.Method
|
return Method == o.Method
|
||||||
&& EqualityUtil.EqualsTypeSigArray(KlassInst, o.KlassInst)
|
&& MetaUtil.EqualsTypeSigArray(KlassInst, o.KlassInst)
|
||||||
&& EqualityUtil.EqualsTypeSigArray(MethodInst, o.MethodInst);
|
&& MetaUtil.EqualsTypeSigArray(MethodInst, o.MethodInst);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
|
|
|
@ -6,12 +6,49 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using IAssemblyResolver = HybridCLR.Editor.Meta.IAssemblyResolver;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor
|
namespace HybridCLR.Editor.Meta
|
||||||
{
|
{
|
||||||
public static class MetaUtil
|
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)
|
public static TypeSig Inflate(TypeSig sig, GenericArgumentContext ctx)
|
||||||
{
|
{
|
||||||
if (!sig.ContainsGenericParameter)
|
if (!sig.ContainsGenericParameter)
|
|
@ -1,4 +1,5 @@
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
|
using HybridCLR.Editor.ABI;
|
||||||
using HybridCLR.Editor.Meta;
|
using HybridCLR.Editor.Meta;
|
||||||
using HybridCLR.Editor.Template;
|
using HybridCLR.Editor.Template;
|
||||||
using System;
|
using System;
|
||||||
|
@ -10,6 +11,7 @@ using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using TypeInfo = HybridCLR.Editor.ABI.TypeInfo;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
namespace HybridCLR.Editor.MethodBridge
|
||||||
{
|
{
|
||||||
|
@ -17,7 +19,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
{
|
{
|
||||||
public class Options
|
public class Options
|
||||||
{
|
{
|
||||||
public PlatformABI CallConvention { get; set; }
|
public PlatformABI PlatformABI { get; set; }
|
||||||
|
|
||||||
public string TemplateCode { get; set; }
|
public string TemplateCode { get; set; }
|
||||||
|
|
||||||
|
@ -36,19 +38,21 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
|
|
||||||
private readonly string _outputFile;
|
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)
|
public Generator(Options options)
|
||||||
{
|
{
|
||||||
|
@ -56,21 +60,22 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
_genericMethods = options.GenericMethods;
|
_genericMethods = options.GenericMethods;
|
||||||
_templateCode = options.TemplateCode;
|
_templateCode = options.TemplateCode;
|
||||||
_outputFile = options.OutputFile;
|
_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)
|
switch (type)
|
||||||
{
|
{
|
||||||
case PlatformABI.Universal32: return new PlatformAdaptor_Universal32();
|
case PlatformABI.Universal32: return new PlatformGeneratorUniversal32();
|
||||||
case PlatformABI.Universal64: return new PlatformAdaptor_Universal64();
|
case PlatformABI.Universal64: return new PlatformGeneratorUniversal64();
|
||||||
case PlatformABI.Arm64: return new PlatformAdaptor_Arm64();
|
case PlatformABI.Arm64: return new PlatformGeneratorArm64();
|
||||||
default: throw new NotSupportedException();
|
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>();
|
var paramInfos = new List<ParamInfo>();
|
||||||
if (forceRemoveThis && !methodDef.IsStatic)
|
if (forceRemoveThis && !methodDef.IsStatic)
|
||||||
|
@ -79,19 +84,19 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
}
|
}
|
||||||
foreach (var paramInfo in parameters)
|
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,
|
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,
|
ParamInfos = paramInfos,
|
||||||
};
|
};
|
||||||
_platformAdaptor.OptimizeMethod(mbs);
|
_typeCreator.OptimizeMethod(mbs);
|
||||||
return mbs;
|
return mbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddManaged2NativeMethod(MethodBridgeSig method)
|
private void AddManaged2NativeMethod(MethodDesc method)
|
||||||
{
|
{
|
||||||
if (_managed2nativeMethodSet.Add(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))
|
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))
|
if (_adjustThunkMethodSet.Add(method))
|
||||||
{
|
{
|
||||||
|
@ -136,7 +141,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
parameters = method.Parameters.Select(p => MetaUtil.Inflate(p.Type, gc)).ToList();
|
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);
|
AddManaged2NativeMethod(m2nMethod);
|
||||||
|
|
||||||
if (method.IsVirtual)
|
if (method.IsVirtual)
|
||||||
|
@ -145,12 +150,12 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
{
|
{
|
||||||
AddAdjustThunkMethod(m2nMethod);
|
AddAdjustThunkMethod(m2nMethod);
|
||||||
}
|
}
|
||||||
//var adjustThunkMethod = CreateMethodBridgeSig(method, true, returnType, parameters);
|
//var adjustThunkMethod = CreateMethodDesc(method, true, returnType, parameters);
|
||||||
AddNative2ManagedMethod(m2nMethod);
|
AddNative2ManagedMethod(m2nMethod);
|
||||||
}
|
}
|
||||||
if (method.Name == "Invoke" && method.DeclaringType.IsDelegate)
|
if (method.Name == "Invoke" && method.DeclaringType.IsDelegate)
|
||||||
{
|
{
|
||||||
var openMethod = CreateMethodBridgeSig(method, true, returnType, parameters);
|
var openMethod = CreateMethodDesc(method, true, returnType, parameters);
|
||||||
AddNative2ManagedMethod(openMethod);
|
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)
|
foreach (var method in _managed2nativeMethodSet)
|
||||||
{
|
{
|
||||||
sortedMethods.Add(method.CreateCallSigName(), method);
|
sortedMethods.Add(method.CreateCallSigName(), method);
|
||||||
|
@ -176,7 +181,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
_managed2nativeMethodList = sortedMethods.Values.ToList();
|
_managed2nativeMethodList = sortedMethods.Values.ToList();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
|
var sortedMethods = new SortedDictionary<string, MethodDesc>();
|
||||||
foreach (var method in _native2managedMethodSet)
|
foreach (var method in _native2managedMethodSet)
|
||||||
{
|
{
|
||||||
sortedMethods.Add(method.CreateCallSigName(), method);
|
sortedMethods.Add(method.CreateCallSigName(), method);
|
||||||
|
@ -184,7 +189,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
_native2managedMethodList = sortedMethods.Values.ToList();
|
_native2managedMethodList = sortedMethods.Values.ToList();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var sortedMethods = new SortedDictionary<string, MethodBridgeSig>();
|
var sortedMethods = new SortedDictionary<string, MethodDesc>();
|
||||||
foreach (var method in _adjustThunkMethodSet)
|
foreach (var method in _adjustThunkMethodSet)
|
||||||
{
|
{
|
||||||
sortedMethods.Add(method.CreateCallSigName(), method);
|
sortedMethods.Add(method.CreateCallSigName(), method);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
|
using HybridCLR.Editor.ABI;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -10,48 +11,17 @@ using UnityEngine;
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
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 override void GenerateManaged2NativeMethod(MethodDesc method, List<string> lines)
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
if (!type.IsGeneralValueType)
|
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
|
||||||
{
|
|
||||||
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);
|
|
||||||
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
|
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($@"
|
lines.Add($@"
|
||||||
// {method.MethodDef}
|
// {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" }));
|
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
|
||||||
|
|
||||||
lines.Add($@"
|
lines.Add($@"
|
||||||
// {method.MethodDef}
|
// {method.MethodDef}
|
||||||
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
|
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)};
|
StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
|
||||||
Interpreter::Execute(method, args, ret);
|
Interpreter::Execute(method, args, ret);
|
||||||
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)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" }));
|
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}
|
// {method.MethodDef}
|
||||||
static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
|
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)};
|
StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
|
||||||
Interpreter::Execute(method, args, ret);
|
Interpreter::Execute(method, args, ret);
|
||||||
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)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 dnlib.DotNet;
|
||||||
|
using HybridCLR.Editor.ABI;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -9,11 +10,9 @@ using UnityEngine;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
namespace HybridCLR.Editor.MethodBridge
|
||||||
{
|
{
|
||||||
internal class PlatformAdaptor_Universal32 : PlatformAdaptorBase
|
public class PlatformGeneratorUniversal32 : PlatformGeneratorBase
|
||||||
{
|
{
|
||||||
public PlatformABI CallConventionType { get; } = PlatformABI.Universal32;
|
public override PlatformABI PlatformABI { get; } = PlatformABI.Universal32;
|
||||||
|
|
||||||
public override bool IsArch32 => true;
|
|
||||||
|
|
||||||
//protected override TypeInfo CreateValueType(TypeSig type, bool returnValue)
|
//protected override TypeInfo CreateValueType(TypeSig type, bool returnValue)
|
||||||
//{
|
//{
|
||||||
|
@ -22,19 +21,11 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
// return CreateGeneralValueType(type, typeSize, actualAliment);
|
// 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 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($@"
|
lines.Add($@"
|
||||||
// {method.MethodDef}
|
// {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" }));
|
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
|
||||||
|
|
||||||
lines.Add($@"
|
lines.Add($@"
|
||||||
// {method.MethodDef}
|
// {method.MethodDef}
|
||||||
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
|
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)};
|
StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
|
||||||
Interpreter::Execute(method, args, ret);
|
Interpreter::Execute(method, args, ret);
|
||||||
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)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" }));
|
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}
|
// {method.MethodDef}
|
||||||
static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
|
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)};
|
StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
|
||||||
Interpreter::Execute(method, args, ret);
|
Interpreter::Execute(method, args, ret);
|
||||||
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}
|
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)ret;" : "")}
|
|
@ -1,4 +1,5 @@
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
|
using HybridCLR.Editor.ABI;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -6,33 +7,21 @@ using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using TypeInfo = HybridCLR.Editor.ABI.TypeInfo;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
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 void GenerateManaged2NativeMethod(MethodDesc method, List<string> lines)
|
||||||
|
|
||||||
public override bool IsSupportHFA => true;
|
|
||||||
|
|
||||||
protected override TypeInfo OptimizeSigType(TypeInfo type, bool returnType)
|
|
||||||
{
|
{
|
||||||
if (type.PorType > ParamOrReturnType.STRUCTURE_ALIGN1 && type.PorType <= ParamOrReturnType.STRUCTURE_ALIGN8)
|
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
|
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 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($@"
|
lines.Add($@"
|
||||||
// {method.MethodDef}
|
// {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" }));
|
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
|
||||||
lines.Add($@"
|
lines.Add($@"
|
||||||
// {method.MethodDef}
|
// {method.MethodDef}
|
||||||
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
|
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)};
|
StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
|
||||||
Interpreter::Execute(method, args, ret);
|
Interpreter::Execute(method, args, ret);
|
||||||
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)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" }));
|
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
|
||||||
lines.Add($@"
|
lines.Add($@"
|
||||||
// {method.MethodDef}
|
// {method.MethodDef}
|
||||||
static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
|
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)};
|
StackObject* ret = {(method.ReturnInfo.IsVoid ? "nullptr" : "args + " + method.ParamInfos.Count)};
|
||||||
Interpreter::Execute(method, args, ret);
|
Interpreter::Execute(method, args, ret);
|
||||||
{(!method.ReturnInfo.IsVoid ? $"return *({method.ReturnInfo.Type.GetTypeName()}*)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