1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288 |
- using dnlib.DotNet;
- using HybridCLR.Editor.ABI;
- using HybridCLR.Editor.Meta;
- using HybridCLR.Editor.Template;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.DataAnnotations;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading.Tasks;
- using UnityEditor;
- using UnityEngine;
- using TypeInfo = HybridCLR.Editor.ABI.TypeInfo;
- using CallingConvention = System.Runtime.InteropServices.CallingConvention;
- using TypeAttributes = dnlib.DotNet.TypeAttributes;
- using System.Runtime.InteropServices;
- namespace HybridCLR.Editor.MethodBridge
- {
- public class Generator
- {
- public class Options
- {
- public string TemplateCode { get; set; }
- public string OutputFile { get; set; }
- public IReadOnlyCollection<GenericMethod> GenericMethods { get; set; }
- public List<RawMonoPInvokeCallbackMethodInfo> ReversePInvokeMethods { get; set; }
- public IReadOnlyCollection<CallNativeMethodSignatureInfo> CalliMethodSignatures { get; set; }
- public bool Development { get; set; }
- }
- private class ABIReversePInvokeMethodInfo
- {
- public MethodDesc Method { get; set; }
- public CallingConvention Callvention { get; set; }
- public int Count { get; set; }
- public string Signature { get; set; }
- }
- private class CalliMethodInfo
- {
- public MethodDesc Method { get; set; }
- public CallingConvention Callvention { get; set; }
- public string Signature { get; set; }
- }
- private readonly List<GenericMethod> _genericMethods;
- private readonly List<RawMonoPInvokeCallbackMethodInfo> _originalReversePInvokeMethods;
- private readonly List<CallNativeMethodSignatureInfo> _originalCalliMethodSignatures;
- private readonly string _templateCode;
- private readonly string _outputFile;
- private readonly bool _development;
- private readonly TypeCreator _typeCreator;
- private readonly HashSet<MethodDesc> _managed2nativeMethodSet = new HashSet<MethodDesc>();
- private readonly HashSet<MethodDesc> _native2managedMethodSet = new HashSet<MethodDesc>();
- private readonly HashSet<MethodDesc> _adjustThunkMethodSet = new HashSet<MethodDesc>();
- private List<ABIReversePInvokeMethodInfo> _reversePInvokeMethods;
- private List<CalliMethodInfo> _callidMethods;
- public Generator(Options options)
- {
- List<(GenericMethod, string)> genericMethodInfo = options.GenericMethods.Select(m => (m, m.ToString())).ToList();
- genericMethodInfo.Sort((a, b) => string.CompareOrdinal(a.Item2, b.Item2));
- _genericMethods = genericMethodInfo.Select(m => m.Item1).ToList();
- _originalReversePInvokeMethods = options.ReversePInvokeMethods;
- _originalCalliMethodSignatures = options.CalliMethodSignatures.ToList();
- _templateCode = options.TemplateCode;
- _outputFile = options.OutputFile;
- _typeCreator = new TypeCreator();
- _development = options.Development;
- }
- private readonly Dictionary<string, TypeInfo> _sig2Types = new Dictionary<string, TypeInfo>();
- private TypeInfo GetSharedTypeInfo(TypeSig type)
- {
- var typeInfo = _typeCreator.CreateTypeInfo(type);
- if (!typeInfo.IsStruct)
- {
- return typeInfo;
- }
- string sigName = ToFullName(typeInfo.Klass);
- if (!_sig2Types.TryGetValue(sigName, out var sharedTypeInfo))
- {
- sharedTypeInfo = typeInfo;
- _sig2Types.Add(sigName, sharedTypeInfo);
- }
- return sharedTypeInfo;
- }
- private MethodDesc CreateMethodDesc(MethodDef methodDef, bool forceRemoveThis, TypeSig returnType, List<TypeSig> parameters)
- {
- var paramInfos = new List<ParamInfo>();
- if (forceRemoveThis && !methodDef.IsStatic)
- {
- parameters.RemoveAt(0);
- }
- if (returnType.ContainsGenericParameter)
- {
- throw new Exception($"[PreservedMethod] method:{methodDef} has generic parameters");
- }
- foreach (var paramInfo in parameters)
- {
- if (paramInfo.ContainsGenericParameter)
- {
- throw new Exception($"[PreservedMethod] method:{methodDef} has generic parameters");
- }
- paramInfos.Add(new ParamInfo() { Type = GetSharedTypeInfo(paramInfo) });
- }
- var mbs = new MethodDesc()
- {
- MethodDef = methodDef,
- ReturnInfo = new ReturnInfo() { Type = returnType != null ? GetSharedTypeInfo(returnType) : TypeInfo.s_void },
- ParamInfos = paramInfos,
- };
- return mbs;
- }
- private MethodDesc CreateMethodDesc(TypeSig returnType, List<TypeSig> parameters)
- {
- var paramInfos = new List<ParamInfo>();
- if (returnType.ContainsGenericParameter)
- {
- throw new Exception($"[PreservedMethod] method has generic parameters");
- }
- foreach (var paramInfo in parameters)
- {
- if (paramInfo.ContainsGenericParameter)
- {
- throw new Exception($"[PreservedMethod] method has generic parameters");
- }
- paramInfos.Add(new ParamInfo() { Type = GetSharedTypeInfo(paramInfo) });
- }
- var mbs = new MethodDesc()
- {
- MethodDef = null,
- ReturnInfo = new ReturnInfo() { Type = returnType != null ? GetSharedTypeInfo(returnType) : TypeInfo.s_void },
- ParamInfos = paramInfos,
- };
- return mbs;
- }
- private void AddManaged2NativeMethod(MethodDesc method)
- {
- method.Init();
- _managed2nativeMethodSet.Add(method);
- }
- private void AddNative2ManagedMethod(MethodDesc method)
- {
- method.Init();
- _native2managedMethodSet.Add(method);
- }
- private void AddAdjustThunkMethod(MethodDesc method)
- {
- method.Init();
- _adjustThunkMethodSet.Add(method);
- }
- private void ProcessMethod(MethodDef method, List<TypeSig> klassInst, List<TypeSig> methodInst)
- {
- if (method.IsPrivate || (method.IsAssembly && !method.IsPublic && !method.IsFamily))
- {
- if (klassInst == null && methodInst == null)
- {
- return;
- }
- else
- {
- //Debug.Log($"[PreservedMethod] method:{method}");
- }
- }
- ICorLibTypes corLibTypes = method.Module.CorLibTypes;
- TypeSig returnType;
- List<TypeSig> parameters;
- if (klassInst == null && methodInst == null)
- {
- if (method.HasGenericParameters)
- {
- 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
- {
- var gc = new GenericArgumentContext(klassInst, methodInst);
- returnType = MetaUtil.ToShareTypeSig(corLibTypes, MetaUtil.Inflate(method.ReturnType, gc));
- parameters = method.Parameters.Select(p => MetaUtil.ToShareTypeSig(corLibTypes, MetaUtil.Inflate(p.Type, gc))).ToList();
- }
- var m2nMethod = CreateMethodDesc(method, false, returnType, parameters);
- AddManaged2NativeMethod(m2nMethod);
- if (method.IsVirtual)
- {
- if (method.DeclaringType.IsInterface)
- {
- AddAdjustThunkMethod(m2nMethod);
- }
- //var adjustThunkMethod = CreateMethodDesc(method, true, returnType, parameters);
- AddNative2ManagedMethod(m2nMethod);
- }
- if (method.Name == "Invoke" && method.DeclaringType.IsDelegate)
- {
- var openMethod = CreateMethodDesc(method, true, returnType, parameters);
- AddNative2ManagedMethod(openMethod);
- }
- }
- private void PrepareMethodBridges()
- {
- foreach (var method in _genericMethods)
- {
- ProcessMethod(method.Method, method.KlassInst, method.MethodInst);
- }
- foreach (var reversePInvokeMethod in _originalReversePInvokeMethods)
- {
- MethodDef method = reversePInvokeMethod.Method;
- ICorLibTypes corLibTypes = method.Module.CorLibTypes;
- var returnType = MetaUtil.ToShareTypeSig(corLibTypes, method.ReturnType);
- var parameters = method.Parameters.Select(p => MetaUtil.ToShareTypeSig(corLibTypes, p.Type)).ToList();
- var sharedMethod = CreateMethodDesc(method, true, returnType, parameters);
- sharedMethod.Init();
- AddNative2ManagedMethod(sharedMethod);
- }
- }
- static void CheckUnique(IEnumerable<string> names)
- {
- var set = new HashSet<string>();
- foreach (var name in names)
- {
- if (!set.Add(name))
- {
- throw new Exception($"[CheckUnique] duplicate name:{name}");
- }
- }
- }
- private List<MethodDesc> _managed2NativeMethodList0;
- private List<MethodDesc> _native2ManagedMethodList0;
- private List<MethodDesc> _adjustThunkMethodList0;
- private List<TypeInfo> _structTypes0;
- private void CollectTypesAndMethods()
- {
- _managed2NativeMethodList0 = _managed2nativeMethodSet.ToList();
- _managed2NativeMethodList0.Sort((a, b) => string.CompareOrdinal(a.Sig, b.Sig));
- _native2ManagedMethodList0 = _native2managedMethodSet.ToList();
- _native2ManagedMethodList0.Sort((a, b) => string.CompareOrdinal(a.Sig, b.Sig));
- _adjustThunkMethodList0 = _adjustThunkMethodSet.ToList();
- _adjustThunkMethodList0.Sort((a, b) => string.CompareOrdinal(a.Sig, b.Sig));
- var structTypeSet = new HashSet<TypeInfo>();
- CollectStructDefs(_managed2NativeMethodList0, structTypeSet);
- CollectStructDefs(_native2ManagedMethodList0, structTypeSet);
- CollectStructDefs(_adjustThunkMethodList0, structTypeSet);
- CollectStructDefs(_originalCalliMethodSignatures.Select(m => m.MethodSig).ToList(), structTypeSet);
- _structTypes0 = structTypeSet.ToList();
- _structTypes0.Sort((a, b) => a.TypeId - b.TypeId);
- CheckUnique(_structTypes0.Select(t => ToFullName(t.Klass)));
- CheckUnique(_structTypes0.Select(t => t.CreateSigName()));
- Debug.LogFormat("== before optimization struct:{3} managed2native:{0} native2managed:{1} adjustThunk:{2}",
- _managed2NativeMethodList0.Count, _native2ManagedMethodList0.Count, _adjustThunkMethodList0.Count, _structTypes0.Count);
- }
- private class AnalyzeFieldInfo
- {
- public FieldDef field;
- public TypeInfo type;
- }
- private class AnalyzeTypeInfo
- {
- public TypeInfo isoType;
- public List<AnalyzeFieldInfo> fields;
- public string signature;
- public uint originalPackingSize;
- public uint packingSize;
- public uint classSize;
- public LayoutKind layout;
- public bool blittable;
- }
- private readonly Dictionary<TypeInfo, AnalyzeTypeInfo> _analyzeTypeInfos = new Dictionary<TypeInfo, AnalyzeTypeInfo>();
- private readonly Dictionary<string, TypeInfo> _signature2Type = new Dictionary<string, TypeInfo>();
- private bool IsBlittable(TypeSig typeSig)
- {
- typeSig = typeSig.RemovePinnedAndModifiers();
- if (typeSig.IsByRef)
- {
- return true;
- }
- switch (typeSig.ElementType)
- {
- case ElementType.Void: return false;
- case ElementType.Boolean:
- case ElementType.I1:
- case ElementType.U1:
- case ElementType.I2:
- case ElementType.Char:
- case ElementType.U2:
- case ElementType.I4:
- case ElementType.U4:
- case ElementType.I8:
- case ElementType.U8:
- case ElementType.R4:
- case ElementType.R8:
- case ElementType.I:
- case ElementType.U:
- case ElementType.Ptr:
- case ElementType.ByRef:
- case ElementType.FnPtr:
- case ElementType.TypedByRef: return true;
- case ElementType.String:
- case ElementType.Class:
- case ElementType.Array:
- case ElementType.SZArray:
- case ElementType.Object:
- case ElementType.Module:
- case ElementType.Var:
- case ElementType.MVar: return false;
- case ElementType.ValueType:
- {
- TypeDef typeDef = typeSig.ToTypeDefOrRef().ResolveTypeDef();
- if (typeDef == null)
- {
- throw new Exception($"type:{typeSig} definition could not be found. Please try `HybridCLR/Genergate/LinkXml`, then Build once to generate the AOT dll, and then regenerate the bridge function");
- }
- if (typeDef.IsEnum)
- {
- return true;
- }
- return CalculateAnalyzeTypeInfoBasic(GetSharedTypeInfo(typeSig)).blittable;
- }
- case ElementType.GenericInst:
- {
- GenericInstSig gis = (GenericInstSig)typeSig;
- if (!gis.GenericType.IsValueType)
- {
- return false;
- }
- TypeDef typeDef = gis.GenericType.ToTypeDefOrRef().ResolveTypeDef();
- if (typeDef.IsEnum)
- {
- return true;
- }
- return CalculateAnalyzeTypeInfoBasic(GetSharedTypeInfo(typeSig)).blittable;
- }
- default: throw new NotSupportedException($"{typeSig.ElementType}");
- }
- }
- private AnalyzeTypeInfo CalculateAnalyzeTypeInfoBasic(TypeInfo typeInfo)
- {
- Debug.Assert(typeInfo.IsStruct);
- if (_analyzeTypeInfos.TryGetValue(typeInfo, out var ati))
- {
- return ati;
- }
- TypeSig type = typeInfo.Klass;
- TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow();
- List<TypeSig> klassInst = type.ToGenericInstSig()?.GenericArguments?.ToList();
- GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null;
- var fields = new List<AnalyzeFieldInfo>();
- bool blittable = true;
- foreach (FieldDef field in typeDef.Fields)
- {
- if (field.IsStatic)
- {
- continue;
- }
- TypeSig fieldType = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType;
- blittable &= IsBlittable(fieldType);
- TypeInfo sharedFieldTypeInfo = GetSharedTypeInfo(fieldType);
- TypeInfo isoType = ToIsomorphicType(sharedFieldTypeInfo);
- fields.Add(new AnalyzeFieldInfo { field = field, type = isoType });
- }
- //analyzeTypeInfo.blittable = blittable;
- //analyzeTypeInfo.packingSize = blittable ? analyzeTypeInfo.originalPackingSize : 0;
- ClassLayout sa = typeDef.ClassLayout;
- uint originalPackingSize = sa?.PackingSize ?? 0;
- var analyzeTypeInfo = new AnalyzeTypeInfo()
- {
- originalPackingSize = originalPackingSize,
- packingSize = blittable && !typeDef.IsAutoLayout ? originalPackingSize : 0,
- classSize = sa?.ClassSize ?? 0,
- layout = typeDef.IsAutoLayout ? LayoutKind.Auto : (typeDef.IsExplicitLayout ? LayoutKind.Explicit : LayoutKind.Sequential),
- fields = fields,
- blittable = blittable,
- };
- _analyzeTypeInfos.Add(typeInfo, analyzeTypeInfo);
- analyzeTypeInfo.signature = GetOrCalculateTypeInfoSignature(typeInfo);
- if (_signature2Type.TryGetValue(analyzeTypeInfo.signature, out var sharedType))
- {
- // Debug.Log($"[ToIsomorphicType] type:{type.Klass} ==> sharedType:{sharedType.Klass} signature:{signature} ");
- analyzeTypeInfo.isoType = sharedType;
- }
- else
- {
- analyzeTypeInfo.isoType = typeInfo;
- _signature2Type.Add(analyzeTypeInfo.signature, typeInfo);
- }
- return analyzeTypeInfo;
- }
- private string GetOrCalculateTypeInfoSignature(TypeInfo typeInfo)
- {
- if (!typeInfo.IsStruct)
- {
- return typeInfo.CreateSigName();
- }
- var ati = _analyzeTypeInfos[typeInfo];
- //if (_analyzeTypeInfos.TryGetValue(typeInfo, out var ati))
- //{
- // return ati.signature;
- //}
- //ati = CalculateAnalyzeTypeInfoBasic(typeInfo);
- //_analyzeTypeInfos.Add(typeInfo, ati);
- if (ati.signature != null)
- {
- return ati.signature;
- }
- var sigBuf = new StringBuilder();
- if (ati.packingSize != 0 || ati.classSize != 0 || ati.layout != LayoutKind.Sequential || !ati.blittable)
- {
- sigBuf.Append($"[{ati.classSize}|{ati.packingSize}|{ati.layout}|{(ati.blittable ? 0 : 1)}]");
- }
- foreach (var field in ati.fields)
- {
- string fieldOffset = field.field.FieldOffset != null ? field.field.FieldOffset.ToString() + "|" : "";
- sigBuf.Append("{" + fieldOffset + GetOrCalculateTypeInfoSignature(ToIsomorphicType(field.type)) + "}");
- }
- return ati.signature = sigBuf.ToString();
- }
- private TypeInfo ToIsomorphicType(TypeInfo type)
- {
- if (!type.IsStruct)
- {
- return type;
- }
- return CalculateAnalyzeTypeInfoBasic(type).isoType;
- }
- private MethodDesc ToIsomorphicMethod(MethodDesc method)
- {
- var paramInfos = new List<ParamInfo>();
- foreach (var paramInfo in method.ParamInfos)
- {
- paramInfos.Add(new ParamInfo() { Type = ToIsomorphicType(paramInfo.Type) });
- }
- var mbs = new MethodDesc()
- {
- MethodDef = method.MethodDef,
- ReturnInfo = new ReturnInfo() { Type = ToIsomorphicType(method.ReturnInfo.Type) },
- ParamInfos = paramInfos,
- };
- mbs.Init();
- return mbs;
- }
- private List<MethodDesc> _managed2NativeMethodList;
- private List<MethodDesc> _native2ManagedMethodList;
- private List<MethodDesc> _adjustThunkMethodList;
- private List<TypeInfo> structTypes;
- private void BuildAnalyzeTypeInfos()
- {
- foreach (var type in _structTypes0)
- {
- ToIsomorphicType(type);
- }
- structTypes = _signature2Type.Values.ToList();
- structTypes.Sort((a, b) => a.TypeId - b.TypeId);
- }
- private List<MethodDesc> ToUniqueOrderedList(List<MethodDesc> methods)
- {
- var methodMap = new SortedDictionary<string, MethodDesc>();
- foreach (var method in methods)
- {
- var sharedMethod = ToIsomorphicMethod(method);
- var sig = sharedMethod.Sig;
- if (!methodMap.TryGetValue(sig, out var _))
- {
- methodMap.Add(sig, sharedMethod);
- }
- }
- return methodMap.Values.ToList();
- }
- private static string MakeReversePInvokeSignature(MethodDesc desc, CallingConvention CallingConventionention)
- {
- string convStr = ((char)('A' + (int)CallingConventionention - 1)).ToString();
- return $"{convStr}{desc.Sig}";
- }
- private static string MakeCalliSignature(MethodDesc desc, CallingConvention CallingConventionention)
- {
- string convStr = ((char)('A' + Math.Max((int)CallingConventionention - 1, 0))).ToString();
- return $"{convStr}{desc.Sig}";
- }
- private static CallingConvention GetCallingConvention(MethodDef method)
- {
- var monoPInvokeCallbackAttr = method.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.Name == "MonoPInvokeCallbackAttribute");
- if (monoPInvokeCallbackAttr == null)
- {
- return CallingConvention.Winapi;
- }
- object delegateTypeSig = monoPInvokeCallbackAttr.ConstructorArguments[0].Value;
- TypeDef delegateTypeDef;
- if (delegateTypeSig is ClassSig classSig)
- {
- delegateTypeDef = classSig.TypeDefOrRef.ResolveTypeDefThrow();
- }
- else if (delegateTypeSig is GenericInstSig genericInstSig)
- {
- delegateTypeDef = genericInstSig.GenericType.TypeDefOrRef.ResolveTypeDefThrow();
- }
- else
- {
- delegateTypeDef = null;
- }
- if (delegateTypeDef == null)
- {
- throw new NotSupportedException($"Unsupported delegate type: {delegateTypeSig}");
- }
- var attr = delegateTypeDef.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute");
- if (attr == null)
- {
- return CallingConvention.Winapi;
- }
- var conv = attr.ConstructorArguments[0].Value;
- return (CallingConvention)conv;
- }
- private List<ABIReversePInvokeMethodInfo> BuildABIMethods(List<RawMonoPInvokeCallbackMethodInfo> rawMethods)
- {
- var methodsBySig = new Dictionary<string, ABIReversePInvokeMethodInfo>();
- foreach (var method in rawMethods)
- {
- var sharedMethod = new MethodDesc
- {
- MethodDef = method.Method,
- ReturnInfo = new ReturnInfo { Type = GetSharedTypeInfo(method.Method.ReturnType) },
- ParamInfos = method.Method.Parameters.Select(p => new ParamInfo { Type = GetSharedTypeInfo(p.Type) }).ToList(),
- };
- sharedMethod.Init();
- sharedMethod = ToIsomorphicMethod(sharedMethod);
- CallingConvention callingConv = GetCallingConvention(method.Method);
- string signature = MakeReversePInvokeSignature(sharedMethod, callingConv);
- if (!methodsBySig.TryGetValue(signature, out var arm))
- {
- arm = new ABIReversePInvokeMethodInfo()
- {
- Method = sharedMethod,
- Signature = signature,
- Count = 0,
- Callvention = callingConv,
- };
- methodsBySig.Add(signature, arm);
- }
- int preserveCount = method.GenerationAttribute != null ? (int)method.GenerationAttribute.ConstructorArguments[0].Value : 1;
- arm.Count += preserveCount;
- }
- var newMethods = methodsBySig.Values.ToList();
- newMethods.Sort((a, b) => string.CompareOrdinal(a.Signature, b.Signature));
- return newMethods;
- }
- private List<CalliMethodInfo> BuildCalliMethods(List<CallNativeMethodSignatureInfo> rawMethods)
- {
- var methodsBySig = new Dictionary<string, CalliMethodInfo>();
- foreach (var method in rawMethods)
- {
- var sharedMethod = new MethodDesc
- {
- MethodDef = null,
- ReturnInfo = new ReturnInfo { Type = GetSharedTypeInfo(method.MethodSig.RetType) },
- ParamInfos = method.MethodSig.Params.Select(p => new ParamInfo { Type = GetSharedTypeInfo(p) }).ToList(),
- };
- sharedMethod.Init();
- sharedMethod = ToIsomorphicMethod(sharedMethod);
- CallingConvention callingConv = (CallingConvention)((int)((method.Callvention ?? method.MethodSig.CallingConvention) & dnlib.DotNet.CallingConvention.Mask) + 1);
- string signature = MakeCalliSignature(sharedMethod, callingConv);
- if (!methodsBySig.TryGetValue(signature, out var arm))
- {
- arm = new CalliMethodInfo()
- {
- Method = sharedMethod,
- Signature = signature,
- Callvention = callingConv,
- };
- methodsBySig.Add(signature, arm);
- }
- }
- var newMethods = methodsBySig.Values.ToList();
- newMethods.Sort((a, b) => string.CompareOrdinal(a.Signature, b.Signature));
- return newMethods;
- }
- private void BuildOptimizedMethods()
- {
- _managed2NativeMethodList = ToUniqueOrderedList(_managed2NativeMethodList0);
- _native2ManagedMethodList = ToUniqueOrderedList(_native2ManagedMethodList0);
- _adjustThunkMethodList = ToUniqueOrderedList(_adjustThunkMethodList0);
- _reversePInvokeMethods = BuildABIMethods(_originalReversePInvokeMethods);
- _callidMethods = BuildCalliMethods(_originalCalliMethodSignatures);
- }
- private void OptimizationTypesAndMethods()
- {
- BuildAnalyzeTypeInfos();
- BuildOptimizedMethods();
- Debug.LogFormat("== after optimization struct:{3} managed2native:{0} native2managed:{1} adjustThunk:{2}",
- _managed2NativeMethodList.Count, _native2ManagedMethodList.Count, _adjustThunkMethodList.Count, structTypes.Count);
- }
- private void GenerateCode()
- {
- var frr = new FileRegionReplace(_templateCode);
- List<string> lines = new List<string>(20_0000)
- {
- "\n",
- $"// DEVELOPMENT={(_development ? 1 : 0)}",
- "\n"
- };
- var classInfos = new List<ClassInfo>();
- var classTypeSet = new Dictionary<TypeInfo, ClassInfo>();
- foreach (var type in structTypes)
- {
- GenerateClassInfo(type, classTypeSet, classInfos);
- }
- GenerateStructDefines(classInfos, lines);
- // use structTypes0 to generate signature
- GenerateStructureSignatureStub(_structTypes0, lines);
- foreach (var method in _managed2NativeMethodList)
- {
- GenerateManaged2NativeMethod(method, lines);
- }
- GenerateManaged2NativeStub(_managed2NativeMethodList, lines);
- foreach (var method in _native2ManagedMethodList)
- {
- GenerateNative2ManagedMethod(method, lines);
- }
- GenerateNative2ManagedStub(_native2ManagedMethodList, lines);
- foreach (var method in _adjustThunkMethodList)
- {
- GenerateAdjustThunkMethod(method, lines);
- }
- GenerateAdjustThunkStub(_adjustThunkMethodList, lines);
- GenerateReversePInvokeWrappers(_reversePInvokeMethods, lines);
- foreach (var method in _callidMethods)
- {
- GenerateManaged2NativeFunctionPointerMethod(method, lines);
- }
- GenerateManaged2NativeFunctionPointerMethodStub(_callidMethods, lines);
- frr.Replace("CODE", string.Join("\n", lines));
- Directory.CreateDirectory(Path.GetDirectoryName(_outputFile));
- frr.Commit(_outputFile);
- }
- private static string GetIl2cppCallConventionName(CallingConvention conv)
- {
- switch (conv)
- {
- case 0:
- case CallingConvention.Winapi:
- return "DEFAULT_CALL";
- case CallingConvention.Cdecl:
- return "CDECL";
- case CallingConvention.StdCall:
- return "STDCALL";
- case CallingConvention.ThisCall:
- return "THISCALL";
- case CallingConvention.FastCall:
- return "FASTCALL";
- default:
- throw new NotSupportedException($"Unsupported CallingConvention {conv}");
- }
- }
- private void GenerateReversePInvokeWrappers(List<ABIReversePInvokeMethodInfo> methods, List<string> lines)
- {
- int methodIndex = 0;
- var stubCodes = new List<string>();
- foreach (var methodInfo in methods)
- {
- MethodDesc method = methodInfo.Method;
- string il2cppCallConventionName = GetIl2cppCallConventionName(methodInfo.Callvention);
- string paramDeclaringListWithoutMethodInfoStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}"));
- string paramNameListWithoutMethodInfoStr = string.Join(", ", method.ParamInfos.Select(p => $"__arg{p.Index}").Concat(new string[] { "method" }));
- string paramTypeListWithMethodInfoStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()}").Concat(new string[] { "const MethodInfo*" }));
- string methodTypeDef = $"typedef {method.ReturnInfo.Type.GetTypeName()} (*Callback)({paramTypeListWithMethodInfoStr})";
- for (int i = 0; i < methodInfo.Count; i++, methodIndex++)
- {
- lines.Add($@"
- {method.ReturnInfo.Type.GetTypeName()} {il2cppCallConventionName} __ReversePInvokeMethod_{methodIndex}({paramDeclaringListWithoutMethodInfoStr})
- {{
- il2cpp::vm::ScopedThreadAttacher _vmThreadHelper;
- const MethodInfo* method = InterpreterModule::GetMethodInfoByReversePInvokeWrapperIndex({methodIndex});
- {methodTypeDef};
- {(method.ReturnInfo.IsVoid ? "" : "return ")}((Callback)(method->methodPointerCallByInterp))({paramNameListWithoutMethodInfoStr});
- }}
- ");
- stubCodes.Add($"\t{{\"{methodInfo.Signature}\", (Il2CppMethodPointer)__ReversePInvokeMethod_{methodIndex}}},");
- }
- Debug.Log($"[ReversePInvokeWrap.Generator] method:{method.MethodDef} wrapperCount:{methodInfo.Count}");
- }
- lines.Add(@"
- const ReversePInvokeMethodData hybridclr::interpreter::g_reversePInvokeMethodStub[]
- {
- ");
- lines.AddRange(stubCodes);
- lines.Add(@"
- {nullptr, nullptr},
- };
- ");
- }
- public void Generate()
- {
- PrepareMethodBridges();
- CollectTypesAndMethods();
- OptimizationTypesAndMethods();
- GenerateCode();
- }
- 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");
- }
- }
- }
-
- }
- private void CollectStructDefs(List<MethodSig> methods, HashSet<TypeInfo> structTypes)
- {
- ICorLibTypes corLibTypes = _genericMethods[0].Method.Module.CorLibTypes;
- foreach (var method in methods)
- {
- foreach (var paramInfo in method.Params)
- {
- var paramType = GetSharedTypeInfo(MetaUtil.ToShareTypeSig(corLibTypes, paramInfo));
- if (paramType.IsStruct)
- {
- structTypes.Add(paramType);
- if (paramType.Klass.ContainsGenericParameter)
- {
- throw new Exception($"[CollectStructDefs] method:{method} type:{paramType.Klass} contains generic parameter");
- }
- }
- }
- var returnType = GetSharedTypeInfo(MetaUtil.ToShareTypeSig(corLibTypes, method.RetType));
- if (returnType.IsStruct)
- {
- structTypes.Add(returnType);
- if (returnType.Klass.ContainsGenericParameter)
- {
- throw new Exception($"[CollectStructDefs] method:{method} type:{returnType.Klass} contains generic parameter");
- }
- }
- }
- }
- class FieldInfo
- {
- public FieldDef field;
- public TypeInfo type;
- }
- class ClassInfo
- {
- public TypeInfo type;
- public List<AnalyzeFieldInfo> fields;
- public uint packingSize;
- public uint classSize;
- public LayoutKind layout;
- public bool blittable;
- }
- private void GenerateClassInfo(TypeInfo type, Dictionary<TypeInfo, ClassInfo> typeSet, List<ClassInfo> classInfos)
- {
- if (typeSet.ContainsKey(type))
- {
- return;
- }
- AnalyzeTypeInfo ati = CalculateAnalyzeTypeInfoBasic(type);
- //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;
- //bool blittable = true;
- //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 = ToIsomorphicType(GetSharedTypeInfo(fieldType));
- // if (fieldTypeInfo.IsStruct)
- // {
- // GenerateClassInfo(fieldTypeInfo, typeSet, classInfos);
- // }
- // blittable &= IsBlittable(fieldType, fieldTypeInfo, typeSet);
- // fields.Add(new FieldInfo { field = field, type = fieldTypeInfo });
- //}
- foreach (var field in ati.fields)
- {
- if (field.type.IsStruct)
- {
- GenerateClassInfo(field.type, typeSet, classInfos);
- }
- }
- var classInfo = new ClassInfo()
- {
- type = type,
- fields = ati.fields,
- packingSize = ati.packingSize,
- classSize = ati.classSize,
- layout = ati.layout,
- blittable = ati.blittable,
- };
- typeSet.Add(type, classInfo);
- classInfos.Add(classInfo);
- }
- private void GenerateStructDefines(List<ClassInfo> classInfos, List<string> lines)
- {
- foreach (var ci in classInfos)
- {
- lines.Add($"// {ci.type.Klass}");
- uint packingSize = ci.packingSize;
- uint classSize = ci.classSize;
-
- if (ci.layout == LayoutKind.Explicit)
- {
- lines.Add($"struct {ci.type.GetTypeName()} {{");
- lines.Add("\tunion {");
- 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 = $"__{index}";
- string commentFieldName = $"{field.field.Name}";
- lines.Add("\t#pragma pack(push, 1)");
- lines.Add($"\tstruct {{ {(offset > 0 ? $"char {fieldName}_offsetPadding[{offset}]; " : "")}{field.type.GetTypeName()} {fieldName};}}; // {commentFieldName}");
- lines.Add($"\t#pragma pack(pop)");
- if (packingSize > 0)
- {
- lines.Add($"\t#pragma pack(push, {packingSize})");
- }
- lines.Add($"\tstruct {{ {(offset > 0 ? $"char {fieldName}_offsetPadding_forAlignmentOnly[{offset}]; " : "")}{field.type.GetTypeName()} {fieldName}_forAlignmentOnly;}}; // {commentFieldName}");
- if (packingSize > 0)
- {
- lines.Add($"\t#pragma pack(pop)");
- }
- ++index;
- }
- lines.Add("\t};");
- lines.Add("};");
- }
- else
- {
- if (packingSize != 0)
- {
- lines.Add($"#pragma pack(push, {packingSize})");
- }
- 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 = $"__{index}";
- string commentFieldName = $"{field.field.Name}";
- lines.Add($"\t{field.type.GetTypeName()} {fieldName}; // {commentFieldName}");
- ++index;
- }
- if (classSize > 0)
- {
- lines.Add("\t};");
- }
- lines.Add("};");
- if (packingSize != 0)
- {
- lines.Add($"#pragma pack(pop)");
- }
- }
- }
- }
- private const string SigOfObj = "u";
- private 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 "u2";
- 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.I: return "i";
- case ElementType.U:
- 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 SigOfObj;
- 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} definition could not be found. Please try `HybridCLR/Genergate/LinkXml`, then Build once to generate the AOT dll, and then regenerate the bridge function");
- }
- if (typeDef.IsEnum)
- {
- return ToFullName(typeDef.GetEnumUnderlyingType());
- }
- return ToValueTypeFullName((ClassOrValueTypeSig)type);
- }
- case ElementType.GenericInst:
- {
- GenericInstSig gis = (GenericInstSig)type;
- if (!gis.GenericType.IsValueType)
- {
- return SigOfObj;
- }
- 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}";
- }
- private void GenerateStructureSignatureStub(List<TypeInfo> types, List<string> lines)
- {
- lines.Add("const FullName2Signature hybridclr::interpreter::g_fullName2SignatureStub[] = {");
- foreach (var type in types)
- {
- TypeInfo isoType = ToIsomorphicType(type);
- lines.Add($"\t{{\"{ToFullName(type.Klass)}\", \"{isoType.CreateSigName()}\"}},");
- }
- lines.Add("\t{ nullptr, nullptr},");
- lines.Add("};");
- }
- private void GenerateManaged2NativeStub(List<MethodDesc> methods, List<string> lines)
- {
- lines.Add($@"
- const 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("};");
- }
- private void GenerateNative2ManagedStub(List<MethodDesc> methods, List<string> lines)
- {
- lines.Add($@"
- const 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("};");
- }
- private void GenerateAdjustThunkStub(List<MethodDesc> methods, List<string> lines)
- {
- lines.Add($@"
- const 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})";
- }
- private 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});
- }}
- ");
- }
- private string GenerateArgumentSizeAndOffset(List<ParamInfo> paramInfos)
- {
- StringBuilder s = new StringBuilder();
- int index = 0;
- foreach (var param in paramInfos)
- {
- s.AppendLine($"\tconstexpr int __ARG_OFFSET_{index}__ = {(index > 0 ? $"__ARG_OFFSET_{index - 1}__ + __ARG_SIZE_{index-1}__" : "0")};");
- s.AppendLine($"\tconstexpr int __ARG_SIZE_{index}__ = (sizeof(__arg{index}) + 7)/8;");
- index++;
- }
- s.AppendLine($"\tconstexpr int __TOTAL_ARG_SIZE__ = {(paramInfos.Count > 0 ? $"__ARG_OFFSET_{index-1}__ + __ARG_SIZE_{index-1}__" : "1")};");
- return s.ToString();
- }
- private string GenerateCopyArgumentToInterpreterStack(List<ParamInfo> paramInfos)
- {
- StringBuilder s = new StringBuilder();
- int index = 0;
- foreach (var param in paramInfos)
- {
- if (param.Type.IsPrimitiveType)
- {
- if (param.Type.NeedExpandValue())
- {
- s.AppendLine($"\targs[__ARG_OFFSET_{index}__].u64 = __arg{index};");
- }
- else
- {
- s.AppendLine($"\t*({param.Type.GetTypeName()}*)(args + __ARG_OFFSET_{index}__) = __arg{index};");
- }
- }
- else
- {
- s.AppendLine($"\t*({param.Type.GetTypeName()}*)(args + __ARG_OFFSET_{index}__) = __arg{index};");
- }
- index++;
- }
- return s.ToString();
- }
- private void GenerateNative2ManagedMethod0(MethodDesc method, bool adjustorThunk, 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_{(adjustorThunk ? "AdjustorThunk_" : "")}{method.CreateCallSigName()}({paramListStr})
- {{
- {(adjustorThunk ? "__arg0 += sizeof(Il2CppObject);" : "")}
- {GenerateArgumentSizeAndOffset(method.ParamInfos)}
- StackObject args[__TOTAL_ARG_SIZE__];
- {GenerateCopyArgumentToInterpreterStack(method.ParamInfos)}
- {(method.ReturnInfo.IsVoid ? "Interpreter::Execute(method, args, nullptr);" : $"{method.ReturnInfo.Type.GetTypeName()} ret; Interpreter::Execute(method, args, &ret); return ret;")}
- }}
- ");
- }
- private void GenerateNative2ManagedMethod(MethodDesc method, List<string> lines)
- {
- GenerateNative2ManagedMethod0(method, false, lines);
- }
- private void GenerateAdjustThunkMethod(MethodDesc method, List<string> lines)
- {
- GenerateNative2ManagedMethod0(method, true, lines);
- }
- private void GenerateManaged2NativeFunctionPointerMethod(CalliMethodInfo methodInfo, List<string> lines)
- {
- MethodDesc method = methodInfo.Method;
- string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}"));
- string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => GetManaged2NativePassParam(p.Type, $"localVarBase+argVarIndexs[{p.Index}]")));
- string il2cppCallConventionName = GetIl2cppCallConventionName(methodInfo.Callvention);
- lines.Add($@"
- static void __M2NF_{methodInfo.Signature}(Il2CppMethodPointer methodPointer, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
- {{
- typedef {method.ReturnInfo.Type.GetTypeName()} ({il2cppCallConventionName} *NativeMethod)({paramListStr});
- {(!method.ReturnInfo.IsVoid ? $"*({method.ReturnInfo.Type.GetTypeName()}*)ret = " : "")}((NativeMethod)(methodPointer))({paramNameListStr});
- }}
- ");
- }
- private void GenerateManaged2NativeFunctionPointerMethodStub(List<CalliMethodInfo> calliMethodSignatures, List<string> lines)
- {
- lines.Add(@"
- const Managed2NativeFunctionPointerCallData hybridclr::interpreter::g_managed2NativeFunctionPointerCallStub[]
- {
- ");
- foreach (var method in calliMethodSignatures)
- {
- lines.Add($"\t{{\"{method.Signature}\", __M2NF_{method.Signature}}},");
- }
- lines.Add(@"
- {nullptr, nullptr},
- };
- ");
- }
- }
- }
|