[refactor] 重构桥接函数,彻底解决跨平台问题
parent
10e0568251
commit
9eb6dda71b
|
@ -13,8 +13,6 @@
|
||||||
|
|
||||||
using namespace hybridclr::interpreter;
|
using namespace hybridclr::interpreter;
|
||||||
|
|
||||||
#if {PLATFORM_ABI}
|
|
||||||
//!!!{{CODE
|
//!!!{{CODE
|
||||||
|
|
||||||
//!!!}}CODE
|
//!!!}}CODE
|
||||||
#endif
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ namespace hybridclr
|
||||||
{
|
{
|
||||||
namespace metadata
|
namespace metadata
|
||||||
{
|
{
|
||||||
#if {PLATFORM_ABI}
|
|
||||||
|
|
||||||
//!!!{{CODE
|
//!!!{{CODE
|
||||||
|
|
||||||
|
@ -27,6 +26,5 @@ namespace metadata
|
||||||
};
|
};
|
||||||
|
|
||||||
//!!!}}CODE
|
//!!!}}CODE
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,20 +14,6 @@ namespace HybridCLR.Editor.ABI
|
||||||
|
|
||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
|
|
||||||
//public bool IsNative2ManagedByAddress => Type.PorType >= ParamOrReturnType.STRUCT_NOT_PASS_AS_VALUE;
|
|
||||||
public bool IsPassToManagedByAddress => Type.GetParamSlotNum() > 1;
|
|
||||||
|
|
||||||
public bool IsPassToNativeByAddress => Type.PorType == ParamOrReturnType.STRUCTURE_AS_REF_PARAM;
|
|
||||||
|
|
||||||
public string Native2ManagedParamValue(PlatformABI canv)
|
|
||||||
{
|
|
||||||
return IsPassToManagedByAddress ? $"(uint64_t)&__arg{Index}" : $"*(uint64_t*)&__arg{Index}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Managed2NativeParamValue(PlatformABI canv)
|
|
||||||
{
|
|
||||||
return IsPassToNativeByAddress ? $"(uint64_t)(localVarBase+argVarIndexs[{Index}])" : $"*({Type.GetTypeName()}*)(localVarBase+argVarIndexs[{Index}])";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReturnInfo
|
public class ReturnInfo
|
||||||
|
@ -36,11 +22,6 @@ namespace HybridCLR.Editor.ABI
|
||||||
|
|
||||||
public bool IsVoid => Type.PorType == ParamOrReturnType.VOID;
|
public bool IsVoid => Type.PorType == ParamOrReturnType.VOID;
|
||||||
|
|
||||||
public int GetParamSlotNum(PlatformABI canv)
|
|
||||||
{
|
|
||||||
return Type.GetParamSlotNum();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Type.GetTypeName();
|
return Type.GetTypeName();
|
||||||
|
|
|
@ -19,25 +19,9 @@ namespace HybridCLR.Editor.ABI
|
||||||
U8,
|
U8,
|
||||||
R4,
|
R4,
|
||||||
R8,
|
R8,
|
||||||
ARM64_HFA_FLOAT_2,
|
I,
|
||||||
VALUE_TYPE_SIZE_LESS_EQUAL_8,
|
U,
|
||||||
I16, // 8 < size <= 16
|
TYPEDBYREF,
|
||||||
STRUCT_NOT_PASS_AS_VALUE, // struct pass not as value
|
STRUCT,
|
||||||
STRUCTURE_AS_REF_PARAM, // size > 16
|
|
||||||
ARM64_HFA_FLOAT_3,
|
|
||||||
ARM64_HFA_FLOAT_4,
|
|
||||||
ARM64_HFA_DOUBLE_2,
|
|
||||||
ARM64_HFA_DOUBLE_3,
|
|
||||||
ARM64_HFA_DOUBLE_4,
|
|
||||||
ARM64_HVA_8,
|
|
||||||
ARM64_HVA_16,
|
|
||||||
STRUCTURE_ALIGN1, // size > 16
|
|
||||||
STRUCTURE_ALIGN2,
|
|
||||||
STRUCTURE_ALIGN4,
|
|
||||||
STRUCTURE_ALIGN8,
|
|
||||||
SPECIAL_STRUCTURE_ALIGN1,
|
|
||||||
SPECIAL_STRUCTURE_ALIGN2,
|
|
||||||
SPECIAL_STRUCTURE_ALIGN4,
|
|
||||||
SPECIAL_STRUCTURE_ALIGN8,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,39 +9,21 @@ using UnityEngine;
|
||||||
|
|
||||||
namespace HybridCLR.Editor.ABI
|
namespace HybridCLR.Editor.ABI
|
||||||
{
|
{
|
||||||
public abstract class TypeCreatorBase
|
public class TypeCreator
|
||||||
{
|
{
|
||||||
public abstract bool IsArch32 { get; }
|
|
||||||
|
|
||||||
public TypeInfo GetNativeIntTypeInfo() => IsArch32 ? TypeInfo.s_i4 : TypeInfo.s_i8;
|
|
||||||
|
|
||||||
public ValueTypeSizeAligmentCalculator Calculator => IsArch32 ? ValueTypeSizeAligmentCalculator.Caculator32 : ValueTypeSizeAligmentCalculator.Caculator64;
|
|
||||||
|
|
||||||
|
|
||||||
private readonly Dictionary<TypeSig, (int, int)> _typeSizeCache = new Dictionary<TypeSig, (int, int)>(TypeEqualityComparer.Instance);
|
|
||||||
|
|
||||||
|
|
||||||
private readonly Dictionary<TypeSig, TypeInfo> _typeInfoCache = new Dictionary<TypeSig, TypeInfo>(TypeEqualityComparer.Instance);
|
private readonly Dictionary<TypeSig, TypeInfo> _typeInfoCache = new Dictionary<TypeSig, TypeInfo>(TypeEqualityComparer.Instance);
|
||||||
|
|
||||||
public (int Size, int Aligment) ComputeSizeAndAligment(TypeSig t)
|
private int _nextStructId = 0;
|
||||||
{
|
|
||||||
if (_typeSizeCache.TryGetValue(t, out var sizeAndAligment))
|
|
||||||
{
|
|
||||||
return sizeAndAligment;
|
|
||||||
}
|
|
||||||
sizeAndAligment = Calculator.SizeAndAligmentOf(t);
|
|
||||||
_typeSizeCache.Add(t, sizeAndAligment);
|
|
||||||
return sizeAndAligment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeInfo CreateTypeInfo(TypeSig type)
|
public TypeInfo CreateTypeInfo(TypeSig type)
|
||||||
{
|
{
|
||||||
|
type = type.RemovePinnedAndModifiers();
|
||||||
if (!_typeInfoCache.TryGetValue(type, out var typeInfo))
|
if (!_typeInfoCache.TryGetValue(type, out var typeInfo))
|
||||||
{
|
{
|
||||||
typeInfo = CreateTypeInfo0(type);
|
typeInfo = CreateTypeInfo0(type);
|
||||||
_typeInfoCache.Add(type, typeInfo);
|
_typeInfoCache.Add(type, typeInfo);
|
||||||
}
|
}
|
||||||
return new TypeInfo(typeInfo.PorType, typeInfo.Size);
|
return typeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeInfo CreateTypeInfo0(TypeSig type)
|
TypeInfo CreateTypeInfo0(TypeSig type)
|
||||||
|
@ -49,7 +31,7 @@ namespace HybridCLR.Editor.ABI
|
||||||
type = type.RemovePinnedAndModifiers();
|
type = type.RemovePinnedAndModifiers();
|
||||||
if (type.IsByRef)
|
if (type.IsByRef)
|
||||||
{
|
{
|
||||||
return GetNativeIntTypeInfo();
|
return TypeInfo.s_i;
|
||||||
}
|
}
|
||||||
switch (type.ElementType)
|
switch (type.ElementType)
|
||||||
{
|
{
|
||||||
|
@ -66,7 +48,7 @@ namespace HybridCLR.Editor.ABI
|
||||||
case ElementType.U8: return TypeInfo.s_u8;
|
case ElementType.U8: return TypeInfo.s_u8;
|
||||||
case ElementType.R4: return TypeInfo.s_r4;
|
case ElementType.R4: return TypeInfo.s_r4;
|
||||||
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 TypeInfo.s_u;
|
||||||
case ElementType.I:
|
case ElementType.I:
|
||||||
case ElementType.String:
|
case ElementType.String:
|
||||||
case ElementType.Ptr:
|
case ElementType.Ptr:
|
||||||
|
@ -79,8 +61,8 @@ namespace HybridCLR.Editor.ABI
|
||||||
case ElementType.Module:
|
case ElementType.Module:
|
||||||
case ElementType.Var:
|
case ElementType.Var:
|
||||||
case ElementType.MVar:
|
case ElementType.MVar:
|
||||||
return GetNativeIntTypeInfo();
|
return TypeInfo.s_i;
|
||||||
case ElementType.TypedByRef: return CreateValueType(type);
|
case ElementType.TypedByRef: return TypeInfo.s_typedByRef;
|
||||||
case ElementType.ValueType:
|
case ElementType.ValueType:
|
||||||
{
|
{
|
||||||
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef();
|
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef();
|
||||||
|
@ -99,7 +81,7 @@ namespace HybridCLR.Editor.ABI
|
||||||
GenericInstSig gis = (GenericInstSig)type;
|
GenericInstSig gis = (GenericInstSig)type;
|
||||||
if (!gis.GenericType.IsValueType)
|
if (!gis.GenericType.IsValueType)
|
||||||
{
|
{
|
||||||
return GetNativeIntTypeInfo();
|
return TypeInfo.s_i;
|
||||||
}
|
}
|
||||||
TypeDef typeDef = gis.GenericType.ToTypeDefOrRef().ResolveTypeDef();
|
TypeDef typeDef = gis.GenericType.ToTypeDefOrRef().ResolveTypeDef();
|
||||||
if (typeDef.IsEnum)
|
if (typeDef.IsEnum)
|
||||||
|
@ -112,46 +94,9 @@ namespace HybridCLR.Editor.ABI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static TypeInfo CreateGeneralValueType(TypeSig type, int size, int aligment)
|
|
||||||
{
|
|
||||||
System.Diagnostics.Debug.Assert(size % aligment == 0);
|
|
||||||
switch (aligment)
|
|
||||||
{
|
|
||||||
case 1: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN1, size);
|
|
||||||
case 2: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN2, size);
|
|
||||||
case 4: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN4, size);
|
|
||||||
case 8: return new TypeInfo(ParamOrReturnType.STRUCTURE_ALIGN8, size);
|
|
||||||
default: throw new NotSupportedException($"type:{type} not support aligment:{aligment}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual bool TryCreateCustomValueTypeInfo(TypeSig type, int typeSize, int typeAligment, out TypeInfo typeInfo)
|
|
||||||
{
|
|
||||||
typeInfo = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TypeInfo CreateValueType(TypeSig type)
|
protected TypeInfo CreateValueType(TypeSig type)
|
||||||
{
|
{
|
||||||
(int typeSize, int typeAligment) = ComputeSizeAndAligment(type);
|
return new TypeInfo(ParamOrReturnType.STRUCT, type, _nextStructId++);
|
||||||
if (TryCreateCustomValueTypeInfo(type, typeSize, typeAligment, out var typeInfo))
|
|
||||||
{
|
|
||||||
//Debug.Log($"[{GetType().Name}] CustomeValueType:{type} => {typeInfo.CreateSigName()}");
|
|
||||||
return typeInfo;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 64位下结构体内存对齐规则是一样的
|
|
||||||
return CreateGeneralValueType(type, typeSize, typeAligment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected abstract TypeInfo OptimizeSigType(TypeInfo type, bool returnType);
|
|
||||||
|
|
||||||
public virtual void OptimizeMethod(MethodDesc method)
|
|
||||||
{
|
|
||||||
method.TransfromSigTypes(OptimizeSigType);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: fe1634f74b7ca2e42bd07233b451cd94
|
guid: 0b1df5760b488fa43a68843c46fda63a
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -1,138 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static bool IsNotHFAFastCheck(int typeSize)
|
|
||||||
{
|
|
||||||
return typeSize % 4 != 0 || typeSize > 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool ComputHFATypeInfo0(TypeSig type, HFATypeInfo typeInfo)
|
|
||||||
{
|
|
||||||
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
||||||
|
|
||||||
List<TypeSig> klassInst = type.ToGenericInstSig()?.GenericArguments?.ToList();
|
|
||||||
GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null;
|
|
||||||
|
|
||||||
var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
||||||
foreach (FieldDef field in fields)
|
|
||||||
{
|
|
||||||
if (field.IsStatic)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
TypeSig ftype = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
|
|
||||||
switch (ftype.ElementType)
|
|
||||||
{
|
|
||||||
case ElementType.R4:
|
|
||||||
case ElementType.R8:
|
|
||||||
{
|
|
||||||
if (ftype == typeInfo.Type || typeInfo.Type == null)
|
|
||||||
{
|
|
||||||
typeInfo.Type = ftype;
|
|
||||||
++typeInfo.Count;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ElementType.ValueType:
|
|
||||||
{
|
|
||||||
if (!ComputHFATypeInfo0(ftype, typeInfo))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ElementType.GenericInst:
|
|
||||||
{
|
|
||||||
if (!ftype.IsValueType || !ComputHFATypeInfo0(ftype, typeInfo))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return typeInfo.Count <= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool ComputHFATypeInfo(TypeSig type, int typeSize, out HFATypeInfo typeInfo)
|
|
||||||
{
|
|
||||||
typeInfo = new HFATypeInfo();
|
|
||||||
if (IsNotHFAFastCheck(typeSize))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool ok = ComputHFATypeInfo0(type, typeInfo);
|
|
||||||
if (ok && typeInfo.Count >= 1 && typeInfo.Count <= 4)
|
|
||||||
{
|
|
||||||
int fieldSize = typeInfo.Type.ElementType == ElementType.R4 ? 4 : 8;
|
|
||||||
return typeSize == fieldSize * typeInfo.Count;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool TryCreateCustomValueTypeInfo(TypeSig type, int typeSize, int typeAligment, out TypeInfo typeInfo)
|
|
||||||
{
|
|
||||||
if (ComputHFATypeInfo(type, typeSize, out HFATypeInfo hfaTypeInfo))
|
|
||||||
{
|
|
||||||
bool isFloat = hfaTypeInfo.Type.ElementType == ElementType.R4;
|
|
||||||
switch (hfaTypeInfo.Count)
|
|
||||||
{
|
|
||||||
case 1: typeInfo = isFloat ? TypeInfo.s_r4 : TypeInfo.s_r8; break;
|
|
||||||
case 2: typeInfo = isFloat ? TypeInfo.s_vf2 : TypeInfo.s_vd2; break;
|
|
||||||
case 3: typeInfo = isFloat ? TypeInfo.s_vf3 : TypeInfo.s_vd3; break;
|
|
||||||
case 4: typeInfo = isFloat ? TypeInfo.s_vf4 : TypeInfo.s_vd4; break;
|
|
||||||
default: throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
typeInfo = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: a22846b73022cb2458d1c40549ab6877
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: b63c5bf995a6d624dbd10d9df6cb6a7a
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,23 +0,0 @@
|
||||||
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();
|
|
||||||
case PlatformABI.WebGL32: return new TypeCreatorWebGL32();
|
|
||||||
default: throw new NotSupportedException(abi.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 1eb9e19189731a344aad024a43e795bc
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,23 +0,0 @@
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 7867dfe20d27e324e90bc13b9d4f05bb
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,220 +0,0 @@
|
||||||
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 SingletonStruct
|
|
||||||
{
|
|
||||||
public TypeSig Type { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TypeCreatorWebGL32 : TypeCreatorBase
|
|
||||||
{
|
|
||||||
public override bool IsArch32 => true;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsEmptyOrSpeicalValueType(TypeSig type)
|
|
||||||
{
|
|
||||||
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
||||||
if (typeDef.IsEnum)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
||||||
if (fields.Count == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (fields.All(f => f.IsStatic))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (typeDef.IsExplicitLayout && fields.Count(f => !f.IsStatic) > 1)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryComputSingletonStructTypeInfo(TypeSig type, int typeAligment, int typeSize, out TypeInfo typeInfo)
|
|
||||||
{
|
|
||||||
typeInfo = null;
|
|
||||||
if (typeAligment > 8 || typeSize > 8)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var ss = new SingletonStruct();
|
|
||||||
if (!TryComputSingletonStruct0(type, ss) || ss.Type == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (ss.Type.IsByRef)
|
|
||||||
{
|
|
||||||
typeInfo = TypeInfo.s_i4;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
switch (ss.Type.ElementType)
|
|
||||||
{
|
|
||||||
case ElementType.Boolean:
|
|
||||||
case ElementType.Char:
|
|
||||||
case ElementType.I1:
|
|
||||||
case ElementType.U1:
|
|
||||||
case ElementType.I2:
|
|
||||||
case ElementType.U2:
|
|
||||||
case ElementType.I4:
|
|
||||||
case ElementType.U4:
|
|
||||||
case ElementType.I:
|
|
||||||
case ElementType.U:
|
|
||||||
case ElementType.String:
|
|
||||||
case ElementType.Ptr:
|
|
||||||
case ElementType.Class:
|
|
||||||
case ElementType.Array:
|
|
||||||
case ElementType.GenericInst:
|
|
||||||
case ElementType.FnPtr:
|
|
||||||
case ElementType.Object:
|
|
||||||
case ElementType.SZArray:
|
|
||||||
{
|
|
||||||
if (typeAligment <= 4 && typeSize <= 4)
|
|
||||||
{
|
|
||||||
typeInfo = TypeInfo.s_i4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ElementType.I8:
|
|
||||||
case ElementType.U8:
|
|
||||||
{
|
|
||||||
if (typeAligment <= 8 && typeSize <= 8)
|
|
||||||
{
|
|
||||||
typeInfo = TypeInfo.s_i8;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ElementType.R4:
|
|
||||||
{
|
|
||||||
if (typeAligment <= 4 && typeSize <= 4)
|
|
||||||
{
|
|
||||||
typeInfo = TypeInfo.s_r4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ElementType.R8:
|
|
||||||
{
|
|
||||||
if (typeAligment <= 8 && typeSize <= 8)
|
|
||||||
{
|
|
||||||
typeInfo = TypeInfo.s_r8;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
return typeInfo != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryComputSingletonStruct(TypeSig type, out SingletonStruct result)
|
|
||||||
{
|
|
||||||
result = new SingletonStruct();
|
|
||||||
return TryComputSingletonStruct0(type, result) && result.Type != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryComputSingletonStruct0(TypeSig type, SingletonStruct result)
|
|
||||||
{
|
|
||||||
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
||||||
if (typeDef.IsEnum)
|
|
||||||
{
|
|
||||||
if (result.Type == null)
|
|
||||||
{
|
|
||||||
result.Type = typeDef.GetEnumUnderlyingType();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<TypeSig> klassInst = type.ToGenericInstSig()?.GenericArguments?.ToList();
|
|
||||||
GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null;
|
|
||||||
|
|
||||||
var fields = typeDef.Fields;// typeDef.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
||||||
foreach (FieldDef field in fields)
|
|
||||||
{
|
|
||||||
if (field.IsStatic)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
TypeSig ftype = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
|
|
||||||
|
|
||||||
switch (ftype.ElementType)
|
|
||||||
{
|
|
||||||
case ElementType.TypedByRef: return false;
|
|
||||||
case ElementType.ValueType:
|
|
||||||
{
|
|
||||||
if (!TryComputSingletonStruct0(ftype, result))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ElementType.GenericInst:
|
|
||||||
{
|
|
||||||
if (!ftype.IsValueType)
|
|
||||||
{
|
|
||||||
goto default;
|
|
||||||
}
|
|
||||||
if (!TryComputSingletonStruct0(ftype, result))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
if (result.Type != null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
result.Type = ftype;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool TryCreateCustomValueTypeInfo(TypeSig type, int typeSize, int typeAligment, out TypeInfo typeInfo)
|
|
||||||
{
|
|
||||||
typeInfo = null;
|
|
||||||
if (IsEmptyOrSpeicalValueType(type))
|
|
||||||
{
|
|
||||||
switch (typeAligment)
|
|
||||||
{
|
|
||||||
case 1: typeInfo = new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN1, typeSize); break;
|
|
||||||
case 2: typeInfo = new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN2, typeSize); break;
|
|
||||||
case 4: typeInfo = new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN4, typeSize); break;
|
|
||||||
case 8: typeInfo = new TypeInfo(ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN8, typeSize); break;
|
|
||||||
default: throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (TryComputSingletonStructTypeInfo(type, typeAligment, typeSize, out typeInfo))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 4790a87aacda1a14d813570e9e0f35ca
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,4 +1,5 @@
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
|
using HybridCLR.Editor.Meta;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
@ -20,37 +21,32 @@ namespace HybridCLR.Editor.ABI
|
||||||
public static readonly TypeInfo s_u8 = new TypeInfo(ParamOrReturnType.U8);
|
public static readonly TypeInfo s_u8 = new TypeInfo(ParamOrReturnType.U8);
|
||||||
public static readonly TypeInfo s_r4 = new TypeInfo(ParamOrReturnType.R4);
|
public static readonly TypeInfo s_r4 = new TypeInfo(ParamOrReturnType.R4);
|
||||||
public static readonly TypeInfo s_r8 = new TypeInfo(ParamOrReturnType.R8);
|
public static readonly TypeInfo s_r8 = new TypeInfo(ParamOrReturnType.R8);
|
||||||
public static readonly TypeInfo s_i16 = new TypeInfo(ParamOrReturnType.I16);
|
public static readonly TypeInfo s_i = new TypeInfo(ParamOrReturnType.I);
|
||||||
public static readonly TypeInfo s_ref = new TypeInfo(ParamOrReturnType.STRUCTURE_AS_REF_PARAM);
|
public static readonly TypeInfo s_u = new TypeInfo(ParamOrReturnType.U);
|
||||||
|
public static readonly TypeInfo s_typedByRef = new TypeInfo(ParamOrReturnType.TYPEDBYREF);
|
||||||
|
|
||||||
public static readonly TypeInfo s_vf2 = new TypeInfo(ParamOrReturnType.ARM64_HFA_FLOAT_2);
|
public const string strTypedByRef = "typedbyref";
|
||||||
public static readonly TypeInfo s_vf3 = new TypeInfo(ParamOrReturnType.ARM64_HFA_FLOAT_3);
|
|
||||||
public static readonly TypeInfo s_vf4 = new TypeInfo(ParamOrReturnType.ARM64_HFA_FLOAT_4);
|
|
||||||
public static readonly TypeInfo s_vd2 = new TypeInfo(ParamOrReturnType.ARM64_HFA_DOUBLE_2);
|
|
||||||
public static readonly TypeInfo s_vd3 = new TypeInfo(ParamOrReturnType.ARM64_HFA_DOUBLE_3);
|
|
||||||
public static readonly TypeInfo s_vd4 = new TypeInfo(ParamOrReturnType.ARM64_HFA_DOUBLE_4);
|
|
||||||
|
|
||||||
public TypeInfo(ParamOrReturnType portype)
|
public TypeInfo(ParamOrReturnType portype, TypeSig klass = null, int typeId = 0)
|
||||||
{
|
{
|
||||||
PorType = portype;
|
PorType = portype;
|
||||||
Size = 0;
|
Klass = klass;
|
||||||
}
|
_typeId = typeId;
|
||||||
|
|
||||||
public TypeInfo(ParamOrReturnType portype, int size)
|
|
||||||
{
|
|
||||||
PorType = portype;
|
|
||||||
Size = size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParamOrReturnType PorType { get; }
|
public ParamOrReturnType PorType { get; }
|
||||||
|
|
||||||
public bool IsGeneralValueType => PorType >= ParamOrReturnType.STRUCTURE_ALIGN1 && PorType <= ParamOrReturnType.STRUCTURE_ALIGN8;
|
public TypeSig Klass { get; }
|
||||||
|
|
||||||
public int Size { get; }
|
public bool IsStruct => PorType == ParamOrReturnType.STRUCT;
|
||||||
|
|
||||||
|
private readonly int _typeId;
|
||||||
|
|
||||||
|
public int TypeId => _typeId;
|
||||||
|
|
||||||
public bool Equals(TypeInfo other)
|
public bool Equals(TypeInfo other)
|
||||||
{
|
{
|
||||||
return PorType == other.PorType && Size == other.Size;
|
return PorType == other.PorType && object.Equals(Klass, other.Klass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
|
@ -60,7 +56,12 @@ namespace HybridCLR.Editor.ABI
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return (int)PorType * 23 + Size;
|
return (int)PorType * 23 + (Klass?.GetHashCode() ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool NeedExpandValue()
|
||||||
|
{
|
||||||
|
return PorType >= ParamOrReturnType.I1 && PorType <= ParamOrReturnType.U2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string CreateSigName()
|
public string CreateSigName()
|
||||||
|
@ -78,22 +79,10 @@ namespace HybridCLR.Editor.ABI
|
||||||
case ParamOrReturnType.U8: return "u8";
|
case ParamOrReturnType.U8: return "u8";
|
||||||
case ParamOrReturnType.R4: return "r4";
|
case ParamOrReturnType.R4: return "r4";
|
||||||
case ParamOrReturnType.R8: return "r8";
|
case ParamOrReturnType.R8: return "r8";
|
||||||
case ParamOrReturnType.I16: return "i16";
|
case ParamOrReturnType.I: return "i";
|
||||||
case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return "sr";
|
case ParamOrReturnType.U: return "u";
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_2: return "vf2";
|
case ParamOrReturnType.TYPEDBYREF: return strTypedByRef;
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_3: return "vf3";
|
case ParamOrReturnType.STRUCT: return $"s{_typeId}";
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_4: return "vf4";
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_2: return "vd2";
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_3: return "vd3";
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_4: return "vd4";
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN1: return "S" + Size;
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN2: return "A" + Size;
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN4: return "B" + Size;
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN8: return "C" + Size;
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN1: return "X" + Size;
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN2: return "Y" + Size;
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN4: return "Z" + Size;
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN8: return "W" + Size;
|
|
||||||
default: throw new NotSupportedException(PorType.ToString());
|
default: throw new NotSupportedException(PorType.ToString());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -113,55 +102,13 @@ namespace HybridCLR.Editor.ABI
|
||||||
case ParamOrReturnType.U8: return "uint64_t";
|
case ParamOrReturnType.U8: return "uint64_t";
|
||||||
case ParamOrReturnType.R4: return "float";
|
case ParamOrReturnType.R4: return "float";
|
||||||
case ParamOrReturnType.R8: return "double";
|
case ParamOrReturnType.R8: return "double";
|
||||||
case ParamOrReturnType.I16: return "ValueTypeSize16";
|
case ParamOrReturnType.I: return "intptr_t";
|
||||||
case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return "uint64_t";
|
case ParamOrReturnType.U: return "uintptr_t";
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_2: return "HtVector2f";
|
case ParamOrReturnType.TYPEDBYREF: return "Il2CppTypedRef";
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_3: return "HtVector3f";
|
case ParamOrReturnType.STRUCT: return $"__struct_{_typeId}__";
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_4: return "HtVector4f";
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_2: return "HtVector2d";
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_3: return "HtVector3d";
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_4: return "HtVector4d";
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN1: return $"ValueTypeSize<{Size}>";
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN2: return $"ValueTypeSizeAlign2<{Size}>";
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN4: return $"ValueTypeSizeAlign4<{Size}>";
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN8: return $"ValueTypeSizeAlign8<{Size}>";
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN1: return $"WebGLSpeicalValueType<{Size}>";
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN2: return $"WebGLSpeicalValueTypeAlign2<{Size}>";
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN4: return $"WebGLSpeicalValueTypeAlign4<{Size}>";
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN8: return $"WebGLSpeicalValueTypeAlign8<{Size}>";
|
|
||||||
default: throw new NotImplementedException(PorType.ToString());
|
default: throw new NotImplementedException(PorType.ToString());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
public int GetParamSlotNum()
|
|
||||||
{
|
|
||||||
switch (PorType)
|
|
||||||
{
|
|
||||||
case ParamOrReturnType.VOID: return 0;
|
|
||||||
case ParamOrReturnType.I16: return 2;
|
|
||||||
case ParamOrReturnType.STRUCTURE_AS_REF_PARAM: return 1;
|
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_3: return 2;
|
|
||||||
case ParamOrReturnType.ARM64_HFA_FLOAT_4: return 2;
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_2: return 2;
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_3: return 3;
|
|
||||||
case ParamOrReturnType.ARM64_HFA_DOUBLE_4: return 4;
|
|
||||||
case ParamOrReturnType.ARM64_HVA_8:
|
|
||||||
case ParamOrReturnType.ARM64_HVA_16: throw new NotSupportedException();
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN1:
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN2:
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN4:
|
|
||||||
case ParamOrReturnType.STRUCTURE_ALIGN8:
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN1:
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN2:
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN4:
|
|
||||||
case ParamOrReturnType.SPECIAL_STRUCTURE_ALIGN8:
|
|
||||||
return (Size + 7) / 8;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
Debug.Assert(PorType < ParamOrReturnType.STRUCT_NOT_PASS_AS_VALUE);
|
|
||||||
Debug.Assert(Size <= 8);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,16 +29,13 @@ namespace HybridCLR.Editor.Commands
|
||||||
Directory.Delete(il2cppBuildCachePath, true);
|
Directory.Delete(il2cppBuildCachePath, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateMethodBridgeCppFile(Analyzer analyzer, PlatformABI platform, string templateCode, string outputFile)
|
private static void GenerateMethodBridgeCppFile(Analyzer analyzer, string templateCode, string outputFile)
|
||||||
{
|
{
|
||||||
var g = new Generator(new Generator.Options()
|
var g = new Generator(new Generator.Options()
|
||||||
{
|
{
|
||||||
PlatformABI = platform,
|
|
||||||
TemplateCode = templateCode,
|
TemplateCode = templateCode,
|
||||||
OutputFile = outputFile,
|
OutputFile = outputFile,
|
||||||
GenericMethods = analyzer.GenericMethods,
|
GenericMethods = analyzer.GenericMethods,
|
||||||
NotGenericMethods = analyzer.NotGenericMethods,
|
|
||||||
SpeicalPreserveMethods = analyzer.SpeicalPreserveMethods,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
g.PrepareMethods();
|
g.PrepareMethods();
|
||||||
|
@ -66,18 +63,9 @@ namespace HybridCLR.Editor.Commands
|
||||||
});
|
});
|
||||||
|
|
||||||
analyzer.Run();
|
analyzer.Run();
|
||||||
|
|
||||||
var tasks = new List<Task>();
|
|
||||||
string templateCode = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/MethodBridgeStub.cpp");
|
string templateCode = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/MethodBridgeStub.cpp");
|
||||||
foreach (PlatformABI platform in Enum.GetValues(typeof(PlatformABI)))
|
string outputFile = $"{SettingsUtil.GeneratedCppDir}/MethodBridge.cpp";
|
||||||
{
|
GenerateMethodBridgeCppFile(analyzer, templateCode, outputFile);
|
||||||
string outputFile = $"{SettingsUtil.GeneratedCppDir}/MethodBridge_{platform}.cpp";
|
|
||||||
tasks.Add(Task.Run(() =>
|
|
||||||
{
|
|
||||||
GenerateMethodBridgeCppFile(analyzer, platform, templateCode, outputFile);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
Task.WaitAll(tasks.ToArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CleanIl2CppBuildCache();
|
CleanIl2CppBuildCache();
|
||||||
|
|
|
@ -35,17 +35,13 @@ namespace HybridCLR.Editor.Commands
|
||||||
var analyzer = new ReversePInvokeWrap.Analyzer(cache, hotUpdateDlls);
|
var analyzer = new ReversePInvokeWrap.Analyzer(cache, hotUpdateDlls);
|
||||||
analyzer.Run();
|
analyzer.Run();
|
||||||
|
|
||||||
|
|
||||||
string templateCode = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/ReversePInvokeMethodStub.cpp");
|
string templateCode = File.ReadAllText($"{SettingsUtil.TemplatePathInPackage}/ReversePInvokeMethodStub.cpp");
|
||||||
foreach (PlatformABI abi in Enum.GetValues(typeof(PlatformABI)))
|
string outputFile = $"{SettingsUtil.GeneratedCppDir}/ReversePInvokeMethodStub.cpp";
|
||||||
{
|
|
||||||
string outputFile = $"{SettingsUtil.GeneratedCppDir}/ReversePInvokeMethodStub_{abi}.cpp";
|
|
||||||
|
|
||||||
List<ABIReversePInvokeMethodInfo> methods = analyzer.BuildABIMethods(abi);
|
List<ABIReversePInvokeMethodInfo> methods = analyzer.BuildABIMethods();
|
||||||
Debug.Log($"GenerateReversePInvokeWrapper. abi:{abi} wraperCount:{methods.Sum(m => m.Count)} output:{outputFile}");
|
Debug.Log($"GenerateReversePInvokeWrapper. wraperCount:{methods.Sum(m => m.Count)} output:{outputFile}");
|
||||||
var generator = new Generator();
|
var generator = new Generator();
|
||||||
generator.Generate(templateCode, abi, methods, outputFile);
|
generator.Generate(templateCode, methods, outputFile);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
MethodBridgeGeneratorCommand.CleanIl2CppBuildCache();
|
MethodBridgeGeneratorCommand.CleanIl2CppBuildCache();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace HybridCLR.Editor.Meta
|
||||||
|
|
||||||
public GenericClass ToGenericShare()
|
public GenericClass ToGenericShare()
|
||||||
{
|
{
|
||||||
return new GenericClass(Type, MetaUtil.ToShareTypeSigs(KlassInst));
|
return new GenericClass(Type, MetaUtil.ToShareTypeSigs(Type.Module.CorLibTypes, KlassInst));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
|
|
|
@ -26,7 +26,8 @@ namespace HybridCLR.Editor.Meta
|
||||||
|
|
||||||
public GenericMethod ToGenericShare()
|
public GenericMethod ToGenericShare()
|
||||||
{
|
{
|
||||||
return new GenericMethod(Method, MetaUtil.ToShareTypeSigs(KlassInst), MetaUtil.ToShareTypeSigs(MethodInst));
|
ICorLibTypes corLibTypes = Method.Module.CorLibTypes;
|
||||||
|
return new GenericMethod(Method, MetaUtil.ToShareTypeSigs(corLibTypes, KlassInst), MetaUtil.ToShareTypeSigs(corLibTypes, MethodInst));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
|
|
|
@ -59,13 +59,8 @@ namespace HybridCLR.Editor.Meta
|
||||||
return ctx.Resolve(sig);
|
return ctx.Resolve(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeSig ToShareTypeSig(TypeSig typeSig)
|
public static TypeSig ToShareTypeSig(ICorLibTypes corTypes, TypeSig typeSig)
|
||||||
{
|
{
|
||||||
var corTypes = typeSig?.Module?.CorLibTypes;
|
|
||||||
if (corTypes == null)
|
|
||||||
{
|
|
||||||
return typeSig;
|
|
||||||
}
|
|
||||||
var a = typeSig.RemovePinnedAndModifiers();
|
var a = typeSig.RemovePinnedAndModifiers();
|
||||||
switch (a.ElementType)
|
switch (a.ElementType)
|
||||||
{
|
{
|
||||||
|
@ -92,18 +87,39 @@ namespace HybridCLR.Editor.Meta
|
||||||
case ElementType.ByRef: return corTypes.IntPtr;
|
case ElementType.ByRef: return corTypes.IntPtr;
|
||||||
case ElementType.SZArray: return corTypes.Object;
|
case ElementType.SZArray: return corTypes.Object;
|
||||||
case ElementType.Array: return corTypes.Object;
|
case ElementType.Array: return corTypes.Object;
|
||||||
case ElementType.ValueType: return typeSig;
|
case ElementType.ValueType:
|
||||||
|
{
|
||||||
|
TypeDef typeDef = a.ToTypeDefOrRef().ResolveTypeDef();
|
||||||
|
if (typeDef == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"type:{a} 未能找到定义");
|
||||||
|
}
|
||||||
|
if (typeDef.IsEnum)
|
||||||
|
{
|
||||||
|
return ToShareTypeSig(corTypes, typeDef.GetEnumUnderlyingType());
|
||||||
|
}
|
||||||
|
return typeSig;
|
||||||
|
}
|
||||||
case ElementType.Var:
|
case ElementType.Var:
|
||||||
case ElementType.MVar:
|
case ElementType.MVar:
|
||||||
case ElementType.Class: return corTypes.Object;
|
case ElementType.Class: return corTypes.Object;
|
||||||
case ElementType.GenericInst:
|
case ElementType.GenericInst:
|
||||||
{
|
{
|
||||||
var gia = (GenericInstSig)a;
|
var gia = (GenericInstSig)a;
|
||||||
if (gia.GenericType.IsClassSig)
|
TypeDef typeDef = gia.GenericType.ToTypeDefOrRef().ResolveTypeDef();
|
||||||
{
|
if (typeDef == null)
|
||||||
return corTypes.Object;
|
{
|
||||||
}
|
throw new Exception($"type:{a} 未能找到定义");
|
||||||
return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => ToShareTypeSig(ga)).ToList());
|
}
|
||||||
|
if (typeDef.IsEnum)
|
||||||
|
{
|
||||||
|
return ToShareTypeSig(corTypes, typeDef.GetEnumUnderlyingType());
|
||||||
|
}
|
||||||
|
if (!typeDef.IsValueType)
|
||||||
|
{
|
||||||
|
return corTypes.Object;
|
||||||
|
}
|
||||||
|
return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => ToShareTypeSig(corTypes, ga)).ToList());
|
||||||
}
|
}
|
||||||
case ElementType.FnPtr: return corTypes.IntPtr;
|
case ElementType.FnPtr: return corTypes.IntPtr;
|
||||||
case ElementType.ValueArray: return typeSig;
|
case ElementType.ValueArray: return typeSig;
|
||||||
|
@ -113,13 +129,13 @@ namespace HybridCLR.Editor.Meta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<TypeSig> ToShareTypeSigs(IList<TypeSig> typeSigs)
|
public static List<TypeSig> ToShareTypeSigs(ICorLibTypes corTypes, IList<TypeSig> typeSigs)
|
||||||
{
|
{
|
||||||
if (typeSigs == null)
|
if (typeSigs == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return typeSigs.Select(s => ToShareTypeSig(s)).ToList();
|
return typeSigs.Select(s => ToShareTypeSig(corTypes, s)).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IAssemblyResolver CreateHotUpdateAssemblyResolver(BuildTarget target, List<string> hotUpdateDlls)
|
public static IAssemblyResolver CreateHotUpdateAssemblyResolver(BuildTarget target, List<string> hotUpdateDlls)
|
||||||
|
@ -156,5 +172,17 @@ namespace HybridCLR.Editor.Meta
|
||||||
CreateAOTAssemblyResolver(target)
|
CreateAOTAssemblyResolver(target)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static List<TypeSig> CreateDefaultGenericParams(ModuleDef module, int genericParamCount)
|
||||||
|
{
|
||||||
|
var methodGenericParams = new List<TypeSig>();
|
||||||
|
for (int i = 0; i < genericParamCount; i++)
|
||||||
|
{
|
||||||
|
methodGenericParams.Add(module.CorLibTypes.Object);
|
||||||
|
}
|
||||||
|
return methodGenericParams;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,22 +25,15 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
private readonly object _lock = new object();
|
private readonly object _lock = new object();
|
||||||
|
|
||||||
private readonly List<TypeDef> _typeDefs = new List<TypeDef>();
|
private readonly List<TypeDef> _typeDefs = new List<TypeDef>();
|
||||||
private readonly List<MethodDef> _notGenericMethods = new List<MethodDef>();
|
|
||||||
|
|
||||||
private readonly HashSet<GenericClass> _genericTypes = new HashSet<GenericClass>();
|
private readonly HashSet<GenericClass> _genericTypes = new HashSet<GenericClass>();
|
||||||
private readonly HashSet<GenericMethod> _genericMethods = new HashSet<GenericMethod>();
|
private readonly HashSet<GenericMethod> _genericMethods = new HashSet<GenericMethod>();
|
||||||
|
|
||||||
private readonly HashSet<GenericMethod> _speicalPreserveMethods = new HashSet<GenericMethod>();
|
|
||||||
|
|
||||||
private List<GenericMethod> _processingMethods = new List<GenericMethod>();
|
private List<GenericMethod> _processingMethods = new List<GenericMethod>();
|
||||||
private List<GenericMethod> _newMethods = new List<GenericMethod>();
|
private List<GenericMethod> _newMethods = new List<GenericMethod>();
|
||||||
|
|
||||||
public IReadOnlyList<TypeDef> TypeDefs => _typeDefs;
|
public IReadOnlyList<TypeDef> TypeDefs => _typeDefs;
|
||||||
|
|
||||||
public IReadOnlyList<MethodDef> NotGenericMethods => _notGenericMethods;
|
|
||||||
|
|
||||||
public HashSet<GenericMethod> SpeicalPreserveMethods => _speicalPreserveMethods;
|
|
||||||
|
|
||||||
public IReadOnlyCollection<GenericClass> GenericTypes => _genericTypes;
|
public IReadOnlyCollection<GenericClass> GenericTypes => _genericTypes;
|
||||||
|
|
||||||
public IReadOnlyCollection<GenericMethod> GenericMethods => _genericMethods;
|
public IReadOnlyCollection<GenericMethod> GenericMethods => _genericMethods;
|
||||||
|
@ -63,7 +56,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
}
|
}
|
||||||
lock(_lock)
|
lock(_lock)
|
||||||
{
|
{
|
||||||
gc = gc.ToGenericShare();
|
gc = StandardizeClass(gc);
|
||||||
if (_genericTypes.Add(gc))
|
if (_genericTypes.Add(gc))
|
||||||
{
|
{
|
||||||
WalkType(gc);
|
WalkType(gc);
|
||||||
|
@ -71,18 +64,32 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GenericClass StandardizeClass(GenericClass gc)
|
||||||
|
{
|
||||||
|
TypeDef typeDef = gc.Type;
|
||||||
|
ICorLibTypes corLibTypes = typeDef.Module.CorLibTypes;
|
||||||
|
List<TypeSig> klassGenericParams = gc.KlassInst != null ? MetaUtil.ToShareTypeSigs(corLibTypes, gc.KlassInst) : (typeDef.GenericParameters.Count > 0 ? MetaUtil.CreateDefaultGenericParams(typeDef.Module, typeDef.GenericParameters.Count) : null);
|
||||||
|
return new GenericClass(typeDef, klassGenericParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GenericMethod StandardizeMethod(GenericMethod gm)
|
||||||
|
{
|
||||||
|
TypeDef typeDef = gm.Method.DeclaringType;
|
||||||
|
ICorLibTypes corLibTypes = typeDef.Module.CorLibTypes;
|
||||||
|
List<TypeSig> klassGenericParams = gm.KlassInst != null ? MetaUtil.ToShareTypeSigs(corLibTypes, gm.KlassInst) : (typeDef.GenericParameters.Count > 0 ? MetaUtil.CreateDefaultGenericParams(typeDef.Module, typeDef.GenericParameters.Count) : null);
|
||||||
|
List<TypeSig> methodGenericParams = gm.MethodInst != null ? MetaUtil.ToShareTypeSigs(corLibTypes, gm.MethodInst) : (gm.Method.GenericParameters.Count > 0 ? MetaUtil.CreateDefaultGenericParams(typeDef.Module, gm.Method.GenericParameters.Count) : null);
|
||||||
|
return new GenericMethod(gm.Method, klassGenericParams, methodGenericParams);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnNewMethod(MethodDef methodDef, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst, GenericMethod method)
|
private void OnNewMethod(MethodDef methodDef, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst, GenericMethod method)
|
||||||
{
|
{
|
||||||
lock(_lock)
|
lock(_lock)
|
||||||
{
|
{
|
||||||
|
method = StandardizeMethod(method);
|
||||||
if (_genericMethods.Add(method))
|
if (_genericMethods.Add(method))
|
||||||
{
|
{
|
||||||
_newMethods.Add(method);
|
_newMethods.Add(method);
|
||||||
}
|
}
|
||||||
if (methodDef.HasGenericParameters)
|
|
||||||
{
|
|
||||||
_speicalPreserveMethods.Add(method);
|
|
||||||
}
|
|
||||||
if (method.KlassInst != null)
|
if (method.KlassInst != null)
|
||||||
{
|
{
|
||||||
TryAddAndWalkGenericType(new GenericClass(method.Method.DeclaringType, method.KlassInst));
|
TryAddAndWalkGenericType(new GenericClass(method.Method.DeclaringType, method.KlassInst));
|
||||||
|
@ -102,11 +109,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
}
|
}
|
||||||
foreach (var method in gc.Type.Methods)
|
foreach (var method in gc.Type.Methods)
|
||||||
{
|
{
|
||||||
if (method.HasGenericParameters)
|
var gm = StandardizeMethod(new GenericMethod(method, gc.KlassInst, null));
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var gm = new GenericMethod(method, gc.KlassInst, null).ToGenericShare();
|
|
||||||
//Debug.Log($"add method:{gm.Method} {gm.KlassInst}");
|
//Debug.Log($"add method:{gm.Method} {gm.KlassInst}");
|
||||||
|
|
||||||
if (_genericMethods.Add(gm))
|
if (_genericMethods.Add(gm))
|
||||||
|
@ -131,7 +134,8 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
foreach (var method in typeDef.Methods)
|
foreach (var method in typeDef.Methods)
|
||||||
{
|
{
|
||||||
// 对于带泛型的参数,统一泛型共享为object
|
// 对于带泛型的参数,统一泛型共享为object
|
||||||
_notGenericMethods.Add(method);
|
var gm = StandardizeMethod(new GenericMethod(method, null, null));
|
||||||
|
_genericMethods.Add(gm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +153,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
for (uint rid = 1, n = ass.Metadata.TablesStream.TypeSpecTable.Rows; rid <= n; rid++)
|
for (uint rid = 1, n = ass.Metadata.TablesStream.TypeSpecTable.Rows; rid <= n; rid++)
|
||||||
{
|
{
|
||||||
var ts = ass.ResolveTypeSpec(rid);
|
var ts = ass.ResolveTypeSpec(rid);
|
||||||
var cs = GenericClass.ResolveClass(ts, null)?.ToGenericShare();
|
var cs = GenericClass.ResolveClass(ts, null);
|
||||||
if (cs != null)
|
if (cs != null)
|
||||||
{
|
{
|
||||||
TryAddAndWalkGenericType(cs);
|
TryAddAndWalkGenericType(cs);
|
||||||
|
@ -164,14 +168,14 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
gm = StandardizeMethod(gm);
|
||||||
if (_genericMethods.Add(gm))
|
if (_genericMethods.Add(gm))
|
||||||
{
|
{
|
||||||
_newMethods.Add(gm);
|
_newMethods.Add(gm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Debug.Log($"PostPrepare allMethods:{_notGenericMethods.Count} newMethods:{_newMethods.Count}");
|
Debug.Log($"PostPrepare allMethods:{_genericMethods.Count} newMethods:{_newMethods.Count}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecursiveCollect()
|
private void RecursiveCollect()
|
||||||
|
@ -187,7 +191,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
{
|
{
|
||||||
_methodReferenceAnalyzer.WalkMethod(method.Method, method.KlassInst, method.MethodInst);
|
_methodReferenceAnalyzer.WalkMethod(method.Method, method.KlassInst, method.MethodInst);
|
||||||
})).ToArray());
|
})).ToArray());
|
||||||
Debug.Log($"iteration:[{i}] allMethods:{_notGenericMethods.Count} genericClass:{_genericTypes.Count} genericMethods:{_genericMethods.Count} newMethods:{_newMethods.Count}");
|
Debug.Log($"iteration:[{i}] genericClass:{_genericTypes.Count} genericMethods:{_genericMethods.Count} newMethods:{_newMethods.Count}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,34 +20,20 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
{
|
{
|
||||||
public class Options
|
public class Options
|
||||||
{
|
{
|
||||||
public PlatformABI PlatformABI { get; set; }
|
|
||||||
|
|
||||||
public string TemplateCode { get; set; }
|
public string TemplateCode { get; set; }
|
||||||
|
|
||||||
public string OutputFile { get; set; }
|
public string OutputFile { get; set; }
|
||||||
|
|
||||||
public IReadOnlyList<MethodDef> NotGenericMethods { get; set; }
|
|
||||||
|
|
||||||
public IReadOnlyCollection<GenericMethod> GenericMethods { get; set; }
|
public IReadOnlyCollection<GenericMethod> GenericMethods { get; set; }
|
||||||
|
|
||||||
public HashSet<GenericMethod> SpeicalPreserveMethods { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlatformABI _platformABI;
|
|
||||||
|
|
||||||
private readonly List<MethodDef> _notGenericMethods;
|
|
||||||
|
|
||||||
private readonly List<GenericMethod> _genericMethods;
|
private readonly List<GenericMethod> _genericMethods;
|
||||||
|
|
||||||
private readonly HashSet<GenericMethod> _preservedMethods;
|
|
||||||
|
|
||||||
private readonly string _templateCode;
|
private readonly string _templateCode;
|
||||||
|
|
||||||
private readonly string _outputFile;
|
private readonly string _outputFile;
|
||||||
|
|
||||||
private readonly PlatformGeneratorBase _platformAdaptor;
|
private readonly TypeCreator _typeCreator;
|
||||||
|
|
||||||
private readonly TypeCreatorBase _typeCreator;
|
|
||||||
|
|
||||||
private readonly HashSet<MethodDesc> _managed2nativeMethodSet = new HashSet<MethodDesc>();
|
private readonly HashSet<MethodDesc> _managed2nativeMethodSet = new HashSet<MethodDesc>();
|
||||||
|
|
||||||
|
@ -57,34 +43,15 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
|
|
||||||
public Generator(Options options)
|
public Generator(Options options)
|
||||||
{
|
{
|
||||||
_platformABI = options.PlatformABI;
|
|
||||||
|
|
||||||
List<(MethodDef, string)> notGenericMethodInfo = options.NotGenericMethods.Select(m => (m, m.FullName)).ToList();
|
|
||||||
notGenericMethodInfo.Sort((a, b) => string.Compare(a.Item2, b.Item2, StringComparison.Ordinal));
|
|
||||||
_notGenericMethods = notGenericMethodInfo.Select(m => m.Item1).ToList();
|
|
||||||
|
|
||||||
List<(GenericMethod, string)> genericMethodInfo = options.GenericMethods.Select(m => (m, m.ToString())).ToList();
|
List<(GenericMethod, string)> genericMethodInfo = options.GenericMethods.Select(m => (m, m.ToString())).ToList();
|
||||||
genericMethodInfo.Sort((a, b) => string.CompareOrdinal(a.Item2, b.Item2));
|
genericMethodInfo.Sort((a, b) => string.CompareOrdinal(a.Item2, b.Item2));
|
||||||
_genericMethods = genericMethodInfo.Select(m => m.Item1).ToList();
|
_genericMethods = genericMethodInfo.Select(m => m.Item1).ToList();
|
||||||
|
|
||||||
_preservedMethods = options.SpeicalPreserveMethods;
|
|
||||||
_templateCode = options.TemplateCode;
|
_templateCode = options.TemplateCode;
|
||||||
_outputFile = options.OutputFile;
|
_outputFile = options.OutputFile;
|
||||||
_platformAdaptor = CreatePlatformAdaptor(options.PlatformABI);
|
_typeCreator = new TypeCreator();
|
||||||
_typeCreator = TypeCreatorFactory.CreateTypeCreator(options.PlatformABI);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PlatformGeneratorBase CreatePlatformAdaptor(PlatformABI type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case PlatformABI.Universal32: return new PlatformGeneratorUniversal32();
|
|
||||||
case PlatformABI.Universal64: return new PlatformGeneratorUniversal64();
|
|
||||||
case PlatformABI.Arm64: return new PlatformGeneratorArm64();
|
|
||||||
case PlatformABI.WebGL32: return new PlatformGeneratorWebGL32();
|
|
||||||
default: throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MethodDesc CreateMethodDesc(MethodDef methodDef, bool forceRemoveThis, TypeSig returnType, List<TypeSig> parameters)
|
private MethodDesc CreateMethodDesc(MethodDef methodDef, bool forceRemoveThis, TypeSig returnType, List<TypeSig> parameters)
|
||||||
{
|
{
|
||||||
|
@ -93,8 +60,16 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
{
|
{
|
||||||
parameters.RemoveAt(0);
|
parameters.RemoveAt(0);
|
||||||
}
|
}
|
||||||
|
if (returnType.ContainsGenericParameter)
|
||||||
|
{
|
||||||
|
throw new Exception($"[PreservedMethod] method:{methodDef} has generic parameters");
|
||||||
|
}
|
||||||
foreach (var paramInfo in parameters)
|
foreach (var paramInfo in parameters)
|
||||||
{
|
{
|
||||||
|
if (paramInfo.ContainsGenericParameter)
|
||||||
|
{
|
||||||
|
throw new Exception($"[PreservedMethod] method:{methodDef} has generic parameters");
|
||||||
|
}
|
||||||
paramInfos.Add(new ParamInfo() { Type = _typeCreator.CreateTypeInfo(paramInfo) });
|
paramInfos.Add(new ParamInfo() { Type = _typeCreator.CreateTypeInfo(paramInfo) });
|
||||||
}
|
}
|
||||||
var mbs = new MethodDesc()
|
var mbs = new MethodDesc()
|
||||||
|
@ -103,7 +78,6 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
ReturnInfo = new ReturnInfo() { Type = returnType != null ? _typeCreator.CreateTypeInfo(returnType) : TypeInfo.s_void },
|
ReturnInfo = new ReturnInfo() { Type = returnType != null ? _typeCreator.CreateTypeInfo(returnType) : TypeInfo.s_void },
|
||||||
ParamInfos = paramInfos,
|
ParamInfos = paramInfos,
|
||||||
};
|
};
|
||||||
_typeCreator.OptimizeMethod(mbs);
|
|
||||||
return mbs;
|
return mbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +103,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
{
|
{
|
||||||
if (method.IsPrivate || (method.IsAssembly && !method.IsPublic && !method.IsFamily))
|
if (method.IsPrivate || (method.IsAssembly && !method.IsPublic && !method.IsFamily))
|
||||||
{
|
{
|
||||||
if (!_preservedMethods.Contains(new GenericMethod(method, klassInst, methodInst)))
|
if (klassInst == null && methodInst == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -138,19 +112,23 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
//Debug.Log($"[PreservedMethod] method:{method}");
|
//Debug.Log($"[PreservedMethod] method:{method}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ICorLibTypes corLibTypes = method.Module.CorLibTypes;
|
||||||
TypeSig returnType;
|
TypeSig returnType;
|
||||||
List<TypeSig> parameters;
|
List<TypeSig> parameters;
|
||||||
if (klassInst == null && methodInst == null)
|
if (klassInst == null && methodInst == null)
|
||||||
{
|
{
|
||||||
returnType = method.ReturnType;
|
if (method.HasGenericParameters)
|
||||||
parameters = method.Parameters.Select(p => p.Type).ToList();
|
{
|
||||||
|
throw new Exception($"[PreservedMethod] method:{method} has generic parameters");
|
||||||
|
}
|
||||||
|
returnType = MetaUtil.ToShareTypeSig(corLibTypes, method.ReturnType);
|
||||||
|
parameters = method.Parameters.Select(p => MetaUtil.ToShareTypeSig(corLibTypes, p.Type)).ToList();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var gc = new GenericArgumentContext(klassInst, methodInst);
|
var gc = new GenericArgumentContext(klassInst, methodInst);
|
||||||
returnType = MetaUtil.Inflate(method.ReturnType, gc);
|
returnType = MetaUtil.ToShareTypeSig(corLibTypes, MetaUtil.Inflate(method.ReturnType, gc));
|
||||||
parameters = method.Parameters.Select(p => MetaUtil.Inflate(p.Type, gc)).ToList();
|
parameters = method.Parameters.Select(p => MetaUtil.ToShareTypeSig(corLibTypes, MetaUtil.Inflate(p.Type, gc))).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
var m2nMethod = CreateMethodDesc(method, false, returnType, parameters);
|
var m2nMethod = CreateMethodDesc(method, false, returnType, parameters);
|
||||||
|
@ -174,11 +152,6 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
|
|
||||||
public void PrepareMethods()
|
public void PrepareMethods()
|
||||||
{
|
{
|
||||||
foreach(var method in _notGenericMethods)
|
|
||||||
{
|
|
||||||
ProcessMethod(method, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(var method in _genericMethods)
|
foreach(var method in _genericMethods)
|
||||||
{
|
{
|
||||||
ProcessMethod(method.Method, method.KlassInst, method.MethodInst);
|
ProcessMethod(method.Method, method.KlassInst, method.MethodInst);
|
||||||
|
@ -187,7 +160,7 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
|
|
||||||
public void Generate()
|
public void Generate()
|
||||||
{
|
{
|
||||||
var frr = new FileRegionReplace(_templateCode.Replace("{PLATFORM_ABI}", ABIUtil.GetHybridCLRPlatformMacro(_platformABI)));
|
var frr = new FileRegionReplace(_templateCode);
|
||||||
|
|
||||||
List<string> lines = new List<string>(20_0000);
|
List<string> lines = new List<string>(20_0000);
|
||||||
|
|
||||||
|
@ -203,26 +176,44 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
Debug.LogFormat("== managed2native:{0} native2managed:{1} adjustThunk:{2}",
|
Debug.LogFormat("== managed2native:{0} native2managed:{1} adjustThunk:{2}",
|
||||||
managed2NativeMethodList.Count, native2ManagedMethodList.Count, adjustThunkMethodList.Count);
|
managed2NativeMethodList.Count, native2ManagedMethodList.Count, adjustThunkMethodList.Count);
|
||||||
|
|
||||||
foreach(var method in managed2NativeMethodList)
|
|
||||||
|
var structTypeSet = new HashSet<TypeInfo>();
|
||||||
|
CollectStructDefs(managed2NativeMethodList, structTypeSet);
|
||||||
|
CollectStructDefs(native2ManagedMethodList, structTypeSet);
|
||||||
|
CollectStructDefs(adjustThunkMethodList, structTypeSet);
|
||||||
|
List<TypeInfo> structTypes = structTypeSet.ToList();
|
||||||
|
structTypes.Sort((a, b) => a.TypeId - b.TypeId);
|
||||||
|
|
||||||
|
var classInfos = new List<ClassInfo>();
|
||||||
|
var classTypeSet = new HashSet<TypeInfo>();
|
||||||
|
foreach (var type in structTypes)
|
||||||
{
|
{
|
||||||
_platformAdaptor.GenerateManaged2NativeMethod(method, lines);
|
GenerateClassInfo(type, classTypeSet, classInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
_platformAdaptor.GenerateManaged2NativeStub(managed2NativeMethodList, lines);
|
GenerateStructDefines(classInfos, lines);
|
||||||
|
GenerateStructureSignatureStub(structTypes, lines);
|
||||||
|
|
||||||
|
foreach(var method in managed2NativeMethodList)
|
||||||
|
{
|
||||||
|
GenerateManaged2NativeMethod(method, lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
GenerateManaged2NativeStub(managed2NativeMethodList, lines);
|
||||||
|
|
||||||
foreach (var method in native2ManagedMethodList)
|
foreach (var method in native2ManagedMethodList)
|
||||||
{
|
{
|
||||||
_platformAdaptor.GenerateNative2ManagedMethod(method, lines);
|
GenerateNative2ManagedMethod(method, lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
_platformAdaptor.GenerateNative2ManagedStub(native2ManagedMethodList, lines);
|
GenerateNative2ManagedStub(native2ManagedMethodList, lines);
|
||||||
|
|
||||||
foreach (var method in adjustThunkMethodList)
|
foreach (var method in adjustThunkMethodList)
|
||||||
{
|
{
|
||||||
_platformAdaptor.GenerateAdjustThunkMethod(method, lines);
|
GenerateAdjustThunkMethod(method, lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
_platformAdaptor.GenerateAdjustThunkStub(adjustThunkMethodList, lines);
|
GenerateAdjustThunkStub(adjustThunkMethodList, lines);
|
||||||
|
|
||||||
frr.Replace("CODE", string.Join("\n", lines));
|
frr.Replace("CODE", string.Join("\n", lines));
|
||||||
|
|
||||||
|
@ -231,5 +222,348 @@ namespace HybridCLR.Editor.MethodBridge
|
||||||
frr.Commit(_outputFile);
|
frr.Commit(_outputFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CollectStructDefs(List<MethodDesc> methods, HashSet<TypeInfo> structTypes)
|
||||||
|
{
|
||||||
|
foreach (var method in methods)
|
||||||
|
{
|
||||||
|
foreach(var paramInfo in method.ParamInfos)
|
||||||
|
{
|
||||||
|
if (paramInfo.Type.IsStruct)
|
||||||
|
{
|
||||||
|
structTypes.Add(paramInfo.Type);
|
||||||
|
if (paramInfo.Type.Klass.ContainsGenericParameter)
|
||||||
|
{
|
||||||
|
throw new Exception($"[CollectStructDefs] method:{method.MethodDef} type:{paramInfo.Type.Klass} contains generic parameter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (method.ReturnInfo.Type.IsStruct)
|
||||||
|
{
|
||||||
|
structTypes.Add(method.ReturnInfo.Type);
|
||||||
|
if (method.ReturnInfo.Type.Klass.ContainsGenericParameter)
|
||||||
|
{
|
||||||
|
throw new Exception($"[CollectStructDefs] method:{method.MethodDef} type:{method.ReturnInfo.Type.Klass} contains generic parameter");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class FieldInfo
|
||||||
|
{
|
||||||
|
public FieldDef field;
|
||||||
|
public TypeInfo type;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassInfo
|
||||||
|
{
|
||||||
|
public TypeInfo type;
|
||||||
|
|
||||||
|
public TypeDef typeDef;
|
||||||
|
|
||||||
|
public List<FieldInfo> fields = new List<FieldInfo>();
|
||||||
|
|
||||||
|
public ClassLayout layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateClassInfo(TypeInfo type, HashSet<TypeInfo> typeSet, List<ClassInfo> classInfos)
|
||||||
|
{
|
||||||
|
if (!typeSet.Add(type))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TypeSig typeSig = type.Klass;
|
||||||
|
var fields = new List<FieldInfo>();
|
||||||
|
|
||||||
|
TypeDef typeDef = typeSig.ToTypeDefOrRef().ResolveTypeDefThrow();
|
||||||
|
|
||||||
|
List<TypeSig> klassInst = typeSig.ToGenericInstSig()?.GenericArguments?.ToList();
|
||||||
|
GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null;
|
||||||
|
|
||||||
|
ClassLayout sa = typeDef.ClassLayout;
|
||||||
|
|
||||||
|
ICorLibTypes corLibTypes = typeDef.Module.CorLibTypes;
|
||||||
|
foreach (FieldDef field in typeDef.Fields)
|
||||||
|
{
|
||||||
|
if (field.IsStatic)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TypeSig fieldType = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
|
||||||
|
fieldType = MetaUtil.ToShareTypeSig(corLibTypes, fieldType);
|
||||||
|
var fieldTypeInfo = _typeCreator.CreateTypeInfo(fieldType);
|
||||||
|
if (fieldTypeInfo.IsStruct)
|
||||||
|
{
|
||||||
|
GenerateClassInfo(fieldTypeInfo, typeSet, classInfos);
|
||||||
|
}
|
||||||
|
fields.Add(new FieldInfo { field = field, type = fieldTypeInfo });
|
||||||
|
}
|
||||||
|
classInfos.Add(new ClassInfo() { type = type, typeDef = typeDef, fields = fields, layout = sa });
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateStructDefines(List<ClassInfo> classInfos, List<string> lines)
|
||||||
|
{
|
||||||
|
foreach (var ci in classInfos)
|
||||||
|
{
|
||||||
|
lines.Add($"// {ci.type.Klass}");
|
||||||
|
uint packingSize = ci.layout?.PackingSize ?? 0;
|
||||||
|
if (packingSize != 0)
|
||||||
|
{
|
||||||
|
lines.Add($"#pragma pack(push, {packingSize})");
|
||||||
|
}
|
||||||
|
uint classSize = ci.layout?.ClassSize ?? 0;
|
||||||
|
|
||||||
|
if (ci.typeDef.IsExplicitLayout)
|
||||||
|
{
|
||||||
|
lines.Add($"union {ci.type.GetTypeName()} {{");
|
||||||
|
if (classSize > 0)
|
||||||
|
{
|
||||||
|
lines.Add($"\tstruct {{ char __fieldSize_offsetPadding[{classSize}];}};");
|
||||||
|
}
|
||||||
|
int index = 0;
|
||||||
|
foreach (var field in ci.fields)
|
||||||
|
{
|
||||||
|
uint offset = field.field.FieldOffset.Value;
|
||||||
|
string fieldName = $"__{field.field.Name.Replace('<', '_').Replace('>', '_')}_{index}";
|
||||||
|
lines.Add("\t#pragma pack(push, 1)");
|
||||||
|
lines.Add($"\tstruct {{ {(offset > 0 ? $"char {fieldName}_offsetPadding[{offset}];" : "")} {field.type.GetTypeName()} {fieldName};}};");
|
||||||
|
lines.Add($"\t#pragma pack(pop)");
|
||||||
|
lines.Add($"\tstruct {{ {field.type.GetTypeName()} {fieldName}_forAlignmentOnly;}};");
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lines.Add($"{(classSize > 0 ? "union" : "struct")} {ci.type.GetTypeName()} {{");
|
||||||
|
if (classSize > 0)
|
||||||
|
{
|
||||||
|
lines.Add($"\tstruct {{ char __fieldSize_offsetPadding[{classSize}];}};");
|
||||||
|
lines.Add("\tstruct {");
|
||||||
|
}
|
||||||
|
int index = 0;
|
||||||
|
foreach (var field in ci.fields)
|
||||||
|
{
|
||||||
|
string fieldName = $"__{field.field.Name.Replace('<', '_').Replace('>', '_')}_{index}";
|
||||||
|
lines.Add($"\t{field.type.GetTypeName()} {fieldName};");
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
if (classSize > 0)
|
||||||
|
{
|
||||||
|
lines.Add("\t};");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lines.Add("};");
|
||||||
|
if (packingSize != 0)
|
||||||
|
{
|
||||||
|
lines.Add($"#pragma pack(pop)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToFullName(TypeSig type)
|
||||||
|
{
|
||||||
|
type = type.RemovePinnedAndModifiers();
|
||||||
|
switch (type.ElementType)
|
||||||
|
{
|
||||||
|
case ElementType.Void: return "v";
|
||||||
|
case ElementType.Boolean: return "u1";
|
||||||
|
case ElementType.I1: return "i1";
|
||||||
|
case ElementType.U1: return "u1";
|
||||||
|
case ElementType.I2: return "i2";
|
||||||
|
case ElementType.Char:
|
||||||
|
case ElementType.U2: return "i2";
|
||||||
|
case ElementType.I4: return "i4";
|
||||||
|
case ElementType.U4: return "u4";
|
||||||
|
case ElementType.I8: return "i8";
|
||||||
|
case ElementType.U8: return "u8";
|
||||||
|
case ElementType.R4: return "r4";
|
||||||
|
case ElementType.R8: return "r8";
|
||||||
|
case ElementType.U: return "u";
|
||||||
|
case ElementType.I:
|
||||||
|
case ElementType.String:
|
||||||
|
case ElementType.Ptr:
|
||||||
|
case ElementType.ByRef:
|
||||||
|
case ElementType.Class:
|
||||||
|
case ElementType.Array:
|
||||||
|
case ElementType.SZArray:
|
||||||
|
case ElementType.FnPtr:
|
||||||
|
case ElementType.Object:
|
||||||
|
return "i";
|
||||||
|
case ElementType.Module:
|
||||||
|
case ElementType.Var:
|
||||||
|
case ElementType.MVar:
|
||||||
|
throw new NotSupportedException($"ToFullName type:{type}");
|
||||||
|
case ElementType.TypedByRef: return TypeInfo.strTypedByRef;
|
||||||
|
case ElementType.ValueType:
|
||||||
|
{
|
||||||
|
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef();
|
||||||
|
if (typeDef == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"type:{type} 未能找到定义。请尝试 `HybridCLR/Genergate/LinkXml`,然后Build一次生成AOT dll,再重新生成桥接函数");
|
||||||
|
}
|
||||||
|
if (typeDef.IsEnum)
|
||||||
|
{
|
||||||
|
return ToFullName(typeDef.GetEnumUnderlyingType());
|
||||||
|
}
|
||||||
|
return ToValueTypeFullName((ClassOrValueTypeSig)type);
|
||||||
|
}
|
||||||
|
case ElementType.GenericInst:
|
||||||
|
{
|
||||||
|
GenericInstSig gis = (GenericInstSig)type;
|
||||||
|
if (!gis.GenericType.IsValueType)
|
||||||
|
{
|
||||||
|
return "i";
|
||||||
|
}
|
||||||
|
TypeDef typeDef = gis.GenericType.ToTypeDefOrRef().ResolveTypeDef();
|
||||||
|
if (typeDef.IsEnum)
|
||||||
|
{
|
||||||
|
return ToFullName(typeDef.GetEnumUnderlyingType());
|
||||||
|
}
|
||||||
|
return $"{ToValueTypeFullName(gis.GenericType)}<{string.Join(",", gis.GenericArguments.Select(a => ToFullName(a)))}>";
|
||||||
|
}
|
||||||
|
default: throw new NotSupportedException($"{type.ElementType}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsSystemOrUnityAssembly(ModuleDef module)
|
||||||
|
{
|
||||||
|
if (module.IsCoreLibraryModule == true)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
string assName = module.Assembly.Name.String;
|
||||||
|
return assName.StartsWith("System.") || assName.StartsWith("UnityEngine.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ToValueTypeFullName(ClassOrValueTypeSig type)
|
||||||
|
{
|
||||||
|
TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef();
|
||||||
|
if (typeDef == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"type:{type} resolve fail");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeDef.DeclaringType != null)
|
||||||
|
{
|
||||||
|
return $"{ToValueTypeFullName((ClassOrValueTypeSig)typeDef.DeclaringType.ToTypeSig())}/{typeDef.Name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsSystemOrUnityAssembly(typeDef.Module))
|
||||||
|
{
|
||||||
|
return type.FullName;
|
||||||
|
}
|
||||||
|
return $"{Path.GetFileNameWithoutExtension(typeDef.Module.Name)}:{typeDef.FullName}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenerateStructureSignatureStub(List<TypeInfo> types, List<string> lines)
|
||||||
|
{
|
||||||
|
lines.Add("FullName2Signature hybridclr::interpreter::g_fullName2SignatureStub[] = {");
|
||||||
|
foreach (var type in types)
|
||||||
|
{
|
||||||
|
lines.Add($"\t{{\"{ToFullName(type.Klass)}\", \"{type.CreateSigName()}\"}},");
|
||||||
|
}
|
||||||
|
lines.Add("\t{ nullptr, nullptr},");
|
||||||
|
lines.Add("};");
|
||||||
|
}
|
||||||
|
|
||||||
|
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("};");
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetManaged2NativePassParam(TypeInfo type, string varName)
|
||||||
|
{
|
||||||
|
return $"M2NFromValueOrAddress<{type.GetTypeName()}>({varName})";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetNative2ManagedPassParam(TypeInfo type, string varName)
|
||||||
|
{
|
||||||
|
return type.NeedExpandValue() ? $"(uint64_t)({varName})" : $"N2MAsUint64ValueOrAddress<{type.GetTypeName()}>({varName})";
|
||||||
|
}
|
||||||
|
|
||||||
|
public 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 => GetManaged2NativePassParam(p.Type, $"localVarBase+argVarIndexs[{p.Index}]")).Concat(new string[] { "method" }));
|
||||||
|
|
||||||
|
lines.Add($@"
|
||||||
|
static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
|
||||||
|
{{
|
||||||
|
typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr});
|
||||||
|
{(!method.ReturnInfo.IsVoid ? $"*({method.ReturnInfo.Type.GetTypeName()}*)ret = " : "")}((NativeMethod)(method->methodPointerCallByInterp))({paramNameListStr});
|
||||||
|
}}
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenerateNative2ManagedMethod(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" }));
|
||||||
|
|
||||||
|
lines.Add($@"
|
||||||
|
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
|
||||||
|
{{
|
||||||
|
StackObject args[{Math.Max(1, method.ParamInfos.Count)}] = {{{string.Join(", ", method.ParamInfos.Select(p => GetNative2ManagedPassParam(p.Type, $"__arg{p.Index}")))} }};
|
||||||
|
{(method.ReturnInfo.IsVoid ? "Interpreter::Execute(method, args, nullptr);" : $"{method.ReturnInfo.Type.GetTypeName()} ret; Interpreter::Execute(method, args, &ret); return ret;")}
|
||||||
|
}}
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenerateAdjustThunkMethod(MethodDesc method, List<string> lines)
|
||||||
|
{
|
||||||
|
int totalQuadWordNum = method.ParamInfos.Count;
|
||||||
|
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
|
||||||
|
|
||||||
|
lines.Add($@"
|
||||||
|
static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
|
||||||
|
{{
|
||||||
|
StackObject args[] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : GetNative2ManagedPassParam(p.Type, $"__arg{p.Index}"))))} }};
|
||||||
|
{(method.ReturnInfo.IsVoid ? "Interpreter::Execute(method, args, nullptr);" : $"{method.ReturnInfo.Type.GetTypeName()} ret; Interpreter::Execute(method, args, &ret); return ret;")}
|
||||||
|
}}
|
||||||
|
");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
using dnlib.DotNet;
|
|
||||||
using HybridCLR.Editor.ABI;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class PlatformGeneratorArm64 : PlatformGeneratorBase
|
|
||||||
{
|
|
||||||
public override PlatformABI PlatformABI { get; } = PlatformABI.Universal64;
|
|
||||||
|
|
||||||
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.PlatformABI)).Concat(new string[] { "method" }));
|
|
||||||
|
|
||||||
lines.Add($@"
|
|
||||||
static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
|
|
||||||
{{
|
|
||||||
typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr});
|
|
||||||
{(!method.ReturnInfo.IsVoid ? $"*({method.ReturnInfo.Type.GetTypeName()}*)ret = " : "")}((NativeMethod)(method->methodPointerCallByInterp))({paramNameListStr});
|
|
||||||
}}
|
|
||||||
");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void GenerateNative2ManagedMethod(MethodDesc method, List<string> lines)
|
|
||||||
{
|
|
||||||
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($@"
|
|
||||||
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
|
|
||||||
{{
|
|
||||||
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(MethodDesc method, List<string> lines)
|
|
||||||
{
|
|
||||||
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($@"
|
|
||||||
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.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,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 4bd8c3b77879ac44b8921a67b5216ca6
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,75 +0,0 @@
|
||||||
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,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 2d2e42e9b08396e42bbaaab79865529f
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,64 +0,0 @@
|
||||||
using dnlib.DotNet;
|
|
||||||
using HybridCLR.Editor.ABI;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
|
||||||
{
|
|
||||||
public class PlatformGeneratorUniversal32 : PlatformGeneratorBase
|
|
||||||
{
|
|
||||||
public override PlatformABI PlatformABI { get; } = PlatformABI.Universal32;
|
|
||||||
|
|
||||||
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.PlatformABI)).Concat(new string[] { "method" }));
|
|
||||||
|
|
||||||
lines.Add($@"
|
|
||||||
static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
|
|
||||||
{{
|
|
||||||
typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr});
|
|
||||||
{(!method.ReturnInfo.IsVoid ? $"*({method.ReturnInfo.Type.GetTypeName()}*)ret = " : "")}((NativeMethod)(method->methodPointerCallByInterp))({paramNameListStr});
|
|
||||||
}}
|
|
||||||
");
|
|
||||||
}
|
|
||||||
public override void GenerateNative2ManagedMethod(MethodDesc method, List<string> lines)
|
|
||||||
{
|
|
||||||
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($@"
|
|
||||||
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
|
|
||||||
{{
|
|
||||||
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(MethodDesc method, List<string> lines)
|
|
||||||
{
|
|
||||||
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($@"
|
|
||||||
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.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,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: cee9b0142fca88747b2414ca4b3d2b7a
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,62 +0,0 @@
|
||||||
using dnlib.DotNet;
|
|
||||||
using HybridCLR.Editor.ABI;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
using TypeInfo = HybridCLR.Editor.ABI.TypeInfo;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
|
||||||
{
|
|
||||||
public class PlatformGeneratorUniversal64 : PlatformGeneratorBase
|
|
||||||
{
|
|
||||||
public override PlatformABI PlatformABI { get; } = PlatformABI.Universal64;
|
|
||||||
|
|
||||||
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 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.PlatformABI)).Concat(new string[] { "method" }));
|
|
||||||
|
|
||||||
lines.Add($@"
|
|
||||||
static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
|
|
||||||
{{
|
|
||||||
typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr});
|
|
||||||
{(!method.ReturnInfo.IsVoid ? $"*({method.ReturnInfo.Type.GetTypeName()}*)ret = " : "")}((NativeMethod)(method->methodPointerCallByInterp))({paramNameListStr});
|
|
||||||
}}
|
|
||||||
");
|
|
||||||
}
|
|
||||||
public override void GenerateNative2ManagedMethod(MethodDesc method, List<string> lines)
|
|
||||||
{
|
|
||||||
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($@"
|
|
||||||
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
|
|
||||||
{{
|
|
||||||
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(MethodDesc method, List<string> lines)
|
|
||||||
{
|
|
||||||
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($@"
|
|
||||||
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.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,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 96d94c3da2c6a394590218ce38eaec72
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,65 +0,0 @@
|
||||||
using dnlib.DotNet;
|
|
||||||
using HybridCLR.Editor.ABI;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace HybridCLR.Editor.MethodBridge
|
|
||||||
{
|
|
||||||
public class PlatformGeneratorWebGL32 : PlatformGeneratorBase
|
|
||||||
{
|
|
||||||
public override PlatformABI PlatformABI { get; } = PlatformABI.WebGL32;
|
|
||||||
|
|
||||||
|
|
||||||
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.PlatformABI)).Concat(new string[] { "method" }));
|
|
||||||
|
|
||||||
lines.Add($@"
|
|
||||||
static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
|
|
||||||
{{
|
|
||||||
typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr});
|
|
||||||
{(!method.ReturnInfo.IsVoid ? $"*({method.ReturnInfo.Type.GetTypeName()}*)ret = " : "")}((NativeMethod)(method->methodPointerCallByInterp))({paramNameListStr});
|
|
||||||
}}
|
|
||||||
");
|
|
||||||
}
|
|
||||||
public override void GenerateNative2ManagedMethod(MethodDesc method, List<string> lines)
|
|
||||||
{
|
|
||||||
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($@"
|
|
||||||
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
|
|
||||||
{{
|
|
||||||
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(MethodDesc method, List<string> lines)
|
|
||||||
{
|
|
||||||
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($@"
|
|
||||||
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.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,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 2912d21f60f4c684785c31efcf2d9b29
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -70,10 +70,10 @@ namespace HybridCLR.Editor.ReversePInvokeWrap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ABIReversePInvokeMethodInfo> BuildABIMethods(PlatformABI abi)
|
public List<ABIReversePInvokeMethodInfo> BuildABIMethods()
|
||||||
{
|
{
|
||||||
var methodsBySig = new Dictionary<string, ABIReversePInvokeMethodInfo>();
|
var methodsBySig = new Dictionary<string, ABIReversePInvokeMethodInfo>();
|
||||||
var typeCreator = TypeCreatorFactory.CreateTypeCreator(abi);
|
var typeCreator = new TypeCreator();
|
||||||
foreach(var method in _reversePInvokeMethods)
|
foreach(var method in _reversePInvokeMethods)
|
||||||
{
|
{
|
||||||
MethodDesc desc = new MethodDesc
|
MethodDesc desc = new MethodDesc
|
||||||
|
@ -82,7 +82,6 @@ namespace HybridCLR.Editor.ReversePInvokeWrap
|
||||||
ReturnInfo = new ReturnInfo { Type = typeCreator.CreateTypeInfo(method.Method.ReturnType)},
|
ReturnInfo = new ReturnInfo { Type = typeCreator.CreateTypeInfo(method.Method.ReturnType)},
|
||||||
ParamInfos = method.Method.Parameters.Select(p => new ParamInfo { Type = typeCreator.CreateTypeInfo(p.Type)}).ToList(),
|
ParamInfos = method.Method.Parameters.Select(p => new ParamInfo { Type = typeCreator.CreateTypeInfo(p.Type)}).ToList(),
|
||||||
};
|
};
|
||||||
typeCreator.OptimizeMethod(desc);
|
|
||||||
desc.Init();
|
desc.Init();
|
||||||
if (!methodsBySig.TryGetValue(desc.Sig, out var arm))
|
if (!methodsBySig.TryGetValue(desc.Sig, out var arm))
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,9 +9,8 @@ namespace HybridCLR.Editor.ReversePInvokeWrap
|
||||||
{
|
{
|
||||||
public class Generator
|
public class Generator
|
||||||
{
|
{
|
||||||
public void Generate(string template, PlatformABI abi, List<ABIReversePInvokeMethodInfo> methods, string outputFile)
|
public void Generate(string template, List<ABIReversePInvokeMethodInfo> methods, string outputFile)
|
||||||
{
|
{
|
||||||
template = template.Replace("{PLATFORM_ABI}", ABIUtil.GetHybridCLRPlatformMacro(abi));
|
|
||||||
var frr = new FileRegionReplace(template);
|
var frr = new FileRegionReplace(template);
|
||||||
var codes = new List<string>();
|
var codes = new List<string>();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue