上传新的package
This commit is contained in:
20
Assets/01.HybridCLR/Editor/Meta/AssemblyCache.cs
Normal file
20
Assets/01.HybridCLR/Editor/Meta/AssemblyCache.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class AssemblyCache : AssemblyCacheBase
|
||||
{
|
||||
|
||||
public AssemblyCache(IAssemblyResolver assemblyResolver) : base(assemblyResolver)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/01.HybridCLR/Editor/Meta/AssemblyCache.cs.meta
Normal file
11
Assets/01.HybridCLR/Editor/Meta/AssemblyCache.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9916e9cd98115a4e813f9d227f4d524
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
107
Assets/01.HybridCLR/Editor/Meta/AssemblyCacheBase.cs
Normal file
107
Assets/01.HybridCLR/Editor/Meta/AssemblyCacheBase.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public abstract class AssemblyCacheBase : IDisposable
|
||||
{
|
||||
private readonly IAssemblyResolver _assemblyPathResolver;
|
||||
private readonly ModuleContext _modCtx;
|
||||
private readonly AssemblyResolver _asmResolver;
|
||||
private bool disposedValue;
|
||||
private bool _loadedNetstandard;
|
||||
|
||||
public Dictionary<string, ModuleDefMD> LoadedModules { get; } = new Dictionary<string, ModuleDefMD>();
|
||||
|
||||
private readonly List<ModuleDefMD> _loadedModulesIncludeNetstandard = new List<ModuleDefMD>();
|
||||
|
||||
protected AssemblyCacheBase(IAssemblyResolver assemblyResolver)
|
||||
{
|
||||
_assemblyPathResolver = assemblyResolver;
|
||||
_modCtx = ModuleDef.CreateModuleContext();
|
||||
_asmResolver = (AssemblyResolver)_modCtx.AssemblyResolver;
|
||||
_asmResolver.EnableTypeDefCache = true;
|
||||
_asmResolver.UseGAC = false;
|
||||
}
|
||||
|
||||
public ModuleDefMD LoadModule(string moduleName, bool loadReferenceAssemblies = true)
|
||||
{
|
||||
// Debug.Log($"load module:{moduleName}");
|
||||
if (LoadedModules.TryGetValue(moduleName, out var mod))
|
||||
{
|
||||
return mod;
|
||||
}
|
||||
if (moduleName == "netstandard")
|
||||
{
|
||||
if (!_loadedNetstandard)
|
||||
{
|
||||
LoadNetStandard();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
mod = DoLoadModule(_assemblyPathResolver.ResolveAssembly(moduleName, true));
|
||||
LoadedModules.Add(moduleName, mod);
|
||||
|
||||
if (loadReferenceAssemblies)
|
||||
{
|
||||
foreach (var refAsm in mod.GetAssemblyRefs())
|
||||
{
|
||||
LoadModule(refAsm.Name);
|
||||
}
|
||||
}
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
private void LoadNetStandard()
|
||||
{
|
||||
string netstandardDllPath = _assemblyPathResolver.ResolveAssembly("netstandard", false);
|
||||
if (!string.IsNullOrEmpty(netstandardDllPath))
|
||||
{
|
||||
DoLoadModule(netstandardDllPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoLoadModule(MetaUtil.ResolveNetStandardAssemblyPath("netstandard2.0"));
|
||||
DoLoadModule(MetaUtil.ResolveNetStandardAssemblyPath("netstandard2.1"));
|
||||
}
|
||||
_loadedNetstandard = true;
|
||||
}
|
||||
|
||||
private ModuleDefMD DoLoadModule(string dllPath)
|
||||
{
|
||||
//Debug.Log($"do load module:{dllPath}");
|
||||
ModuleDefMD mod = ModuleDefMD.Load(dllPath, _modCtx);
|
||||
_asmResolver.AddToCache(mod);
|
||||
_loadedModulesIncludeNetstandard.Add(mod);
|
||||
return mod;
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
foreach (var mod in _loadedModulesIncludeNetstandard)
|
||||
{
|
||||
mod.Dispose();
|
||||
}
|
||||
_loadedModulesIncludeNetstandard.Clear();
|
||||
LoadedModules.Clear();
|
||||
}
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/01.HybridCLR/Editor/Meta/AssemblyCacheBase.cs.meta
Normal file
11
Assets/01.HybridCLR/Editor/Meta/AssemblyCacheBase.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e640f5657ae667947b7330b660191943
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,50 @@
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class AssemblyReferenceDeepCollector : AssemblyCacheBase
|
||||
{
|
||||
private readonly List<string> _rootAssemblies;
|
||||
|
||||
public IReadOnlyList<string> GetRootAssemblyNames()
|
||||
{
|
||||
return _rootAssemblies;
|
||||
}
|
||||
|
||||
public List<ModuleDefMD> GetLoadedModulesExcludeRootAssemblies()
|
||||
{
|
||||
return LoadedModules.Where(e => !_rootAssemblies.Contains(e.Key)).Select(e => e.Value).ToList();
|
||||
}
|
||||
|
||||
public List<ModuleDefMD> GetLoadedModules()
|
||||
{
|
||||
return LoadedModules.Select(e => e.Value).ToList();
|
||||
}
|
||||
|
||||
public List<ModuleDefMD> GetLoadedModulesOfRootAssemblies()
|
||||
{
|
||||
return _rootAssemblies.Select(ass => LoadedModules[ass]).ToList();
|
||||
}
|
||||
|
||||
public AssemblyReferenceDeepCollector(IAssemblyResolver assemblyResolver, List<string> rootAssemblies) : base(assemblyResolver)
|
||||
{
|
||||
_rootAssemblies = rootAssemblies;
|
||||
LoadAllAssembiles();
|
||||
}
|
||||
|
||||
private void LoadAllAssembiles()
|
||||
{
|
||||
foreach (var asm in _rootAssemblies)
|
||||
{
|
||||
LoadModule(asm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8242ecc75b20deb489e7d9cadbb4d478
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
33
Assets/01.HybridCLR/Editor/Meta/AssemblyResolverBase.cs
Normal file
33
Assets/01.HybridCLR/Editor/Meta/AssemblyResolverBase.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public abstract class AssemblyResolverBase : IAssemblyResolver
|
||||
{
|
||||
public string ResolveAssembly(string assemblyName, bool throwExIfNotFind)
|
||||
{
|
||||
if (TryResolveAssembly(assemblyName, out string assemblyPath))
|
||||
{
|
||||
return assemblyPath;
|
||||
}
|
||||
if (throwExIfNotFind)
|
||||
{
|
||||
if (SettingsUtil.HotUpdateAssemblyNamesIncludePreserved.Contains(assemblyName))
|
||||
{
|
||||
throw new Exception($"resolve Hot update dll:{assemblyName} failed! Please make sure that this hot update dll exists or the search path is configured in the external hot update path.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"resolve AOT dll:{assemblyName} failed! Please make sure that the AOT project has referenced the dll and generated the trimmed AOT dll correctly.");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected abstract bool TryResolveAssembly(string assemblyName, out string assemblyPath);
|
||||
}
|
||||
}
|
||||
11
Assets/01.HybridCLR/Editor/Meta/AssemblyResolverBase.cs.meta
Normal file
11
Assets/01.HybridCLR/Editor/Meta/AssemblyResolverBase.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd22e83fb27da4d49a6a22b4e724b789
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
33
Assets/01.HybridCLR/Editor/Meta/CombinedAssemblyResolver.cs
Normal file
33
Assets/01.HybridCLR/Editor/Meta/CombinedAssemblyResolver.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class CombinedAssemblyResolver : AssemblyResolverBase
|
||||
{
|
||||
private readonly IAssemblyResolver[] _resolvers;
|
||||
|
||||
public CombinedAssemblyResolver(params IAssemblyResolver[] resolvers)
|
||||
{
|
||||
_resolvers = resolvers;
|
||||
}
|
||||
|
||||
protected override bool TryResolveAssembly(string assemblyName, out string assemblyPath)
|
||||
{
|
||||
foreach(var resolver in _resolvers)
|
||||
{
|
||||
var assembly = resolver.ResolveAssembly(assemblyName, false);
|
||||
if (assembly != null)
|
||||
{
|
||||
assemblyPath = assembly;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
assemblyPath = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e5b98951f11c35e44884fea72fb99e56
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
37
Assets/01.HybridCLR/Editor/Meta/FixedSetAssemblyResolver.cs
Normal file
37
Assets/01.HybridCLR/Editor/Meta/FixedSetAssemblyResolver.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class FixedSetAssemblyResolver : AssemblyResolverBase
|
||||
{
|
||||
private readonly string _rootDir;
|
||||
private readonly HashSet<string> _fileNames;
|
||||
|
||||
public FixedSetAssemblyResolver(string rootDir, IEnumerable<string> fileNameNotExts)
|
||||
{
|
||||
_rootDir = rootDir;
|
||||
_fileNames = new HashSet<string>(fileNameNotExts);
|
||||
}
|
||||
|
||||
protected override bool TryResolveAssembly(string assemblyName, out string assemblyPath)
|
||||
{
|
||||
if (_fileNames.Contains(assemblyName))
|
||||
{
|
||||
assemblyPath = $"{_rootDir}/{assemblyName}.dll";
|
||||
if (File.Exists(assemblyPath))
|
||||
{
|
||||
Debug.Log($"[FixedSetAssemblyResolver] resolve:{assemblyName} path:{assemblyPath}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
assemblyPath = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b53789283b21a240a8fa65b68900dfe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
104
Assets/01.HybridCLR/Editor/Meta/GenericArgumentContext.cs
Normal file
104
Assets/01.HybridCLR/Editor/Meta/GenericArgumentContext.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
/// <summary>
|
||||
/// Replaces generic type/method var with its generic argument
|
||||
/// </summary>
|
||||
public sealed class GenericArgumentContext
|
||||
{
|
||||
List<TypeSig> typeArgsStack = new List<TypeSig>();
|
||||
List<TypeSig> methodArgsStack = new List<TypeSig>();
|
||||
|
||||
public GenericArgumentContext(List<TypeSig> typeArgsStack, List<TypeSig> methodArgsStack)
|
||||
{
|
||||
this.typeArgsStack = typeArgsStack;
|
||||
this.methodArgsStack = methodArgsStack;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Replaces a generic type/method var with its generic argument (if any). If
|
||||
/// <paramref name="typeSig"/> isn't a generic type/method var or if it can't
|
||||
/// be resolved, it itself is returned. Else the resolved type is returned.
|
||||
/// </summary>
|
||||
/// <param name="typeSig">Type signature</param>
|
||||
/// <returns>New <see cref="TypeSig"/> which is never <c>null</c> unless
|
||||
/// <paramref name="typeSig"/> is <c>null</c></returns>
|
||||
public TypeSig Resolve(TypeSig typeSig)
|
||||
{
|
||||
if (!typeSig.ContainsGenericParameter)
|
||||
{
|
||||
return typeSig;
|
||||
}
|
||||
typeSig = typeSig.RemovePinnedAndModifiers();
|
||||
switch (typeSig.ElementType)
|
||||
{
|
||||
case ElementType.Ptr: return new PtrSig(Resolve(typeSig.Next));
|
||||
case ElementType.ByRef: return new PtrSig(Resolve(typeSig.Next));
|
||||
|
||||
case ElementType.SZArray: return new PtrSig(Resolve(typeSig.Next));
|
||||
case ElementType.Array:
|
||||
{
|
||||
var ara = (ArraySig)typeSig;
|
||||
return new ArraySig(Resolve(typeSig.Next), ara.Rank, ara.Sizes, ara.LowerBounds);
|
||||
}
|
||||
|
||||
case ElementType.Var:
|
||||
{
|
||||
GenericVar genericVar = (GenericVar)typeSig;
|
||||
var newSig = Resolve(typeArgsStack, genericVar.Number, true);
|
||||
if (newSig == null)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
return newSig;
|
||||
}
|
||||
|
||||
case ElementType.MVar:
|
||||
{
|
||||
GenericMVar genericVar = (GenericMVar)typeSig;
|
||||
var newSig = Resolve(methodArgsStack, genericVar.Number, true);
|
||||
if (newSig == null)
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
return newSig;
|
||||
}
|
||||
case ElementType.GenericInst:
|
||||
{
|
||||
var gia = (GenericInstSig)typeSig;
|
||||
return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => Resolve(ga)).ToList());
|
||||
}
|
||||
|
||||
case ElementType.FnPtr:
|
||||
{
|
||||
throw new NotSupportedException(typeSig.ToString());
|
||||
}
|
||||
|
||||
case ElementType.ValueArray:
|
||||
{
|
||||
var vas = (ValueArraySig)typeSig;
|
||||
return new ValueArraySig(Resolve(vas.Next), vas.Size);
|
||||
}
|
||||
default: return typeSig;
|
||||
}
|
||||
}
|
||||
|
||||
private TypeSig Resolve(List<TypeSig> args, uint number, bool isTypeVar)
|
||||
{
|
||||
var typeSig = args[(int)number];
|
||||
var gvar = typeSig as GenericSig;
|
||||
if (gvar is null || gvar.IsTypeVar != isTypeVar)
|
||||
return typeSig;
|
||||
return gvar;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8fb1ac43c73a55e4d98e853efca62e46
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
74
Assets/01.HybridCLR/Editor/Meta/GenericClass.cs
Normal file
74
Assets/01.HybridCLR/Editor/Meta/GenericClass.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using dnlib.DotNet;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class GenericClass
|
||||
{
|
||||
public TypeDef Type { get; }
|
||||
|
||||
public List<TypeSig> KlassInst { get; }
|
||||
|
||||
private readonly int _hashCode;
|
||||
|
||||
public GenericClass(TypeDef type, List<TypeSig> classInst)
|
||||
{
|
||||
Type = type;
|
||||
KlassInst = classInst;
|
||||
_hashCode = ComputHashCode();
|
||||
}
|
||||
|
||||
public GenericClass ToGenericShare()
|
||||
{
|
||||
return new GenericClass(Type, MetaUtil.ToShareTypeSigs(Type.Module.CorLibTypes, KlassInst));
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is GenericClass gc)
|
||||
{
|
||||
return Type == gc.Type && MetaUtil.EqualsTypeSigArray(KlassInst, gc.KlassInst);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _hashCode;
|
||||
}
|
||||
|
||||
private int ComputHashCode()
|
||||
{
|
||||
int hash = TypeEqualityComparer.Instance.GetHashCode(Type);
|
||||
if (KlassInst != null)
|
||||
{
|
||||
hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(KlassInst));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public TypeSig ToTypeSig()
|
||||
{
|
||||
return new GenericInstSig(this.Type.ToTypeSig().ToClassOrValueTypeSig(), this.KlassInst);
|
||||
}
|
||||
|
||||
public static GenericClass ResolveClass(TypeSpec type, GenericArgumentContext ctx)
|
||||
{
|
||||
var sig = type.TypeSig.ToGenericInstSig();
|
||||
if (sig == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
TypeDef def = type.ResolveTypeDef();
|
||||
if (def == null)
|
||||
{
|
||||
Debug.LogWarning($"type:{type} ResolveTypeDef() == null");
|
||||
return null;
|
||||
}
|
||||
var klassInst = ctx != null ? sig.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList() : sig.GenericArguments.ToList();
|
||||
return new GenericClass(def, klassInst);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/01.HybridCLR/Editor/Meta/GenericClass.cs.meta
Normal file
11
Assets/01.HybridCLR/Editor/Meta/GenericClass.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 72167574ca223e34cb0b704882225877
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
109
Assets/01.HybridCLR/Editor/Meta/GenericMethod.cs
Normal file
109
Assets/01.HybridCLR/Editor/Meta/GenericMethod.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class GenericMethod
|
||||
{
|
||||
public MethodDef Method { get; }
|
||||
|
||||
public List<TypeSig> KlassInst { get; }
|
||||
|
||||
public List<TypeSig> MethodInst { get; }
|
||||
|
||||
private readonly int _hashCode;
|
||||
|
||||
public GenericMethod(MethodDef method, List<TypeSig> classInst, List<TypeSig> methodInst)
|
||||
{
|
||||
Method = method;
|
||||
KlassInst = classInst;
|
||||
MethodInst = methodInst;
|
||||
_hashCode = ComputHashCode();
|
||||
}
|
||||
|
||||
public GenericMethod ToGenericShare()
|
||||
{
|
||||
ICorLibTypes corLibTypes = Method.Module.CorLibTypes;
|
||||
return new GenericMethod(Method, MetaUtil.ToShareTypeSigs(corLibTypes, KlassInst), MetaUtil.ToShareTypeSigs(corLibTypes, MethodInst));
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
GenericMethod o = (GenericMethod)obj;
|
||||
return Method == o.Method
|
||||
&& MetaUtil.EqualsTypeSigArray(KlassInst, o.KlassInst)
|
||||
&& MetaUtil.EqualsTypeSigArray(MethodInst, o.MethodInst);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _hashCode;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Method}|{string.Join(",", (IEnumerable<TypeSig>)KlassInst ?? Array.Empty<TypeSig>())}|{string.Join(",", (IEnumerable<TypeSig>)MethodInst ?? Array.Empty<TypeSig>())}";
|
||||
}
|
||||
|
||||
private int ComputHashCode()
|
||||
{
|
||||
int hash = MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(Method);
|
||||
if (KlassInst != null)
|
||||
{
|
||||
hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(KlassInst));
|
||||
}
|
||||
if (MethodInst != null)
|
||||
{
|
||||
hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(MethodInst));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public MethodSpec ToMethodSpec()
|
||||
{
|
||||
IMethodDefOrRef mt = KlassInst != null ?
|
||||
(IMethodDefOrRef)new MemberRefUser(this.Method.Module, Method.Name, Method.MethodSig, new TypeSpecUser(new GenericInstSig(this.Method.DeclaringType.ToTypeSig().ToClassOrValueTypeSig(), this.KlassInst)))
|
||||
: this.Method;
|
||||
return new MethodSpecUser(mt, new GenericInstMethodSig(MethodInst));
|
||||
}
|
||||
|
||||
public static GenericMethod ResolveMethod(IMethod method, GenericArgumentContext ctx)
|
||||
{
|
||||
//Debug.Log($"== resolve method:{method}");
|
||||
TypeDef typeDef = null;
|
||||
List<TypeSig> klassInst = null;
|
||||
List<TypeSig> methodInst = null;
|
||||
|
||||
MethodDef methodDef = null;
|
||||
|
||||
|
||||
var decalringType = method.DeclaringType;
|
||||
typeDef = decalringType.ResolveTypeDef();
|
||||
if (typeDef == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
GenericInstSig gis = decalringType.TryGetGenericInstSig();
|
||||
if (gis != null)
|
||||
{
|
||||
klassInst = ctx != null ? gis.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList() : gis.GenericArguments.ToList();
|
||||
}
|
||||
methodDef = method.ResolveMethodDef();
|
||||
if (methodDef == null)
|
||||
{
|
||||
Debug.LogWarning($"method:{method} ResolveMethodDef() == null");
|
||||
return null;
|
||||
}
|
||||
if (method is MethodSpec methodSpec)
|
||||
{
|
||||
methodInst = ctx != null ? methodSpec.GenericInstMethodSig.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList()
|
||||
: methodSpec.GenericInstMethodSig.GenericArguments.ToList();
|
||||
}
|
||||
return new GenericMethod(methodDef, klassInst, methodInst);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
11
Assets/01.HybridCLR/Editor/Meta/GenericMethod.cs.meta
Normal file
11
Assets/01.HybridCLR/Editor/Meta/GenericMethod.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5110d4398a0b6504c94ed3c37b0da2e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
13
Assets/01.HybridCLR/Editor/Meta/IAssemblyResolver.cs
Normal file
13
Assets/01.HybridCLR/Editor/Meta/IAssemblyResolver.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public interface IAssemblyResolver
|
||||
{
|
||||
string ResolveAssembly(string assemblyName, bool throwExIfNotFind);
|
||||
}
|
||||
}
|
||||
11
Assets/01.HybridCLR/Editor/Meta/IAssemblyResolver.cs.meta
Normal file
11
Assets/01.HybridCLR/Editor/Meta/IAssemblyResolver.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cbf06fa49b97cf48a56cb6aeefc7563
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
193
Assets/01.HybridCLR/Editor/Meta/MetaUtil.cs
Normal file
193
Assets/01.HybridCLR/Editor/Meta/MetaUtil.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
using dnlib.DotNet;
|
||||
using HybridCLR.Editor.Meta;
|
||||
using HybridCLR.Editor.Settings;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public static class MetaUtil
|
||||
{
|
||||
|
||||
public static bool EqualsTypeSig(TypeSig a, TypeSig b)
|
||||
{
|
||||
if (a == b)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (a != null && b != null)
|
||||
{
|
||||
return TypeEqualityComparer.Instance.Equals(a, b);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool EqualsTypeSigArray(List<TypeSig> a, List<TypeSig> b)
|
||||
{
|
||||
if (a == b)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (a != null && b != null)
|
||||
{
|
||||
if (a.Count != b.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < a.Count; i++)
|
||||
{
|
||||
if (!TypeEqualityComparer.Instance.Equals(a[i], b[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static TypeSig Inflate(TypeSig sig, GenericArgumentContext ctx)
|
||||
{
|
||||
if (!sig.ContainsGenericParameter)
|
||||
{
|
||||
return sig;
|
||||
}
|
||||
return ctx.Resolve(sig);
|
||||
}
|
||||
|
||||
public static TypeSig ToShareTypeSig(ICorLibTypes corTypes, TypeSig typeSig)
|
||||
{
|
||||
var a = typeSig.RemovePinnedAndModifiers();
|
||||
switch (a.ElementType)
|
||||
{
|
||||
case ElementType.Void: return corTypes.Void;
|
||||
case ElementType.Boolean: return corTypes.Byte;
|
||||
case ElementType.Char: return corTypes.UInt16;
|
||||
case ElementType.I1: return corTypes.SByte;
|
||||
case ElementType.U1:return corTypes.Byte;
|
||||
case ElementType.I2: return corTypes.Int16;
|
||||
case ElementType.U2: return corTypes.UInt16;
|
||||
case ElementType.I4: return corTypes.Int32;
|
||||
case ElementType.U4: return corTypes.UInt32;
|
||||
case ElementType.I8: return corTypes.Int64;
|
||||
case ElementType.U8: return corTypes.UInt64;
|
||||
case ElementType.R4: return corTypes.Single;
|
||||
case ElementType.R8: return corTypes.Double;
|
||||
case ElementType.String: return corTypes.Object;
|
||||
case ElementType.TypedByRef: return corTypes.TypedReference;
|
||||
case ElementType.I: return corTypes.IntPtr;
|
||||
case ElementType.U: return corTypes.UIntPtr;
|
||||
case ElementType.Object: return corTypes.Object;
|
||||
case ElementType.Sentinel: return typeSig;
|
||||
case ElementType.Ptr: return corTypes.UIntPtr;
|
||||
case ElementType.ByRef: return corTypes.UIntPtr;
|
||||
case ElementType.SZArray: return corTypes.Object;
|
||||
case ElementType.Array: return corTypes.Object;
|
||||
case ElementType.ValueType:
|
||||
{
|
||||
TypeDef typeDef = a.ToTypeDefOrRef().ResolveTypeDef();
|
||||
if (typeDef == null)
|
||||
{
|
||||
throw new Exception($"type:{a} definition could not be found");
|
||||
}
|
||||
if (typeDef.IsEnum)
|
||||
{
|
||||
return ToShareTypeSig(corTypes, typeDef.GetEnumUnderlyingType());
|
||||
}
|
||||
return typeSig;
|
||||
}
|
||||
case ElementType.Var:
|
||||
case ElementType.MVar:
|
||||
case ElementType.Class: return corTypes.Object;
|
||||
case ElementType.GenericInst:
|
||||
{
|
||||
var gia = (GenericInstSig)a;
|
||||
TypeDef typeDef = gia.GenericType.ToTypeDefOrRef().ResolveTypeDef();
|
||||
if (typeDef == null)
|
||||
{
|
||||
throw new Exception($"type:{a} definition could not be found");
|
||||
}
|
||||
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.ValueArray: return typeSig;
|
||||
case ElementType.Module: return typeSig;
|
||||
default:
|
||||
throw new NotSupportedException(typeSig.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public static List<TypeSig> ToShareTypeSigs(ICorLibTypes corTypes, IList<TypeSig> typeSigs)
|
||||
{
|
||||
if (typeSigs == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return typeSigs.Select(s => ToShareTypeSig(corTypes, s)).ToList();
|
||||
}
|
||||
|
||||
public static IAssemblyResolver CreateHotUpdateAssemblyResolver(BuildTarget target, List<string> hotUpdateDlls)
|
||||
{
|
||||
var externalDirs = HybridCLRSettings.Instance.externalHotUpdateAssembliyDirs;
|
||||
var defaultHotUpdateOutputDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
|
||||
IAssemblyResolver defaultHotUpdateResolver = new FixedSetAssemblyResolver(defaultHotUpdateOutputDir, hotUpdateDlls);
|
||||
if (externalDirs == null || externalDirs.Length == 0)
|
||||
{
|
||||
return defaultHotUpdateResolver;
|
||||
}
|
||||
else
|
||||
{
|
||||
var resolvers = new List<IAssemblyResolver>();
|
||||
foreach (var dir in externalDirs)
|
||||
{
|
||||
resolvers.Add(new FixedSetAssemblyResolver($"{dir}/{target}", hotUpdateDlls));
|
||||
resolvers.Add(new FixedSetAssemblyResolver(dir, hotUpdateDlls));
|
||||
}
|
||||
resolvers.Add(defaultHotUpdateResolver);
|
||||
return new CombinedAssemblyResolver(resolvers.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public static IAssemblyResolver CreateAOTAssemblyResolver(BuildTarget target)
|
||||
{
|
||||
return new PathAssemblyResolver(SettingsUtil.GetAssembliesPostIl2CppStripDir(target));
|
||||
}
|
||||
|
||||
public static IAssemblyResolver CreateHotUpdateAndAOTAssemblyResolver(BuildTarget target, List<string> hotUpdateDlls)
|
||||
{
|
||||
return new CombinedAssemblyResolver(
|
||||
CreateHotUpdateAssemblyResolver(target, hotUpdateDlls),
|
||||
CreateAOTAssemblyResolver(target)
|
||||
);
|
||||
}
|
||||
|
||||
public static string ResolveNetStandardAssemblyPath(string assemblyName)
|
||||
{
|
||||
return $"{SettingsUtil.HybridCLRDataPathInPackage}/NetStandard/{assemblyName}.dll";
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/01.HybridCLR/Editor/Meta/MetaUtil.cs.meta
Normal file
11
Assets/01.HybridCLR/Editor/Meta/MetaUtil.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2e0aa5795138414ea5139e7691e0185
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
79
Assets/01.HybridCLR/Editor/Meta/MethodReferenceAnalyzer.cs
Normal file
79
Assets/01.HybridCLR/Editor/Meta/MethodReferenceAnalyzer.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using dnlib.DotNet;
|
||||
using HybridCLR.Editor.ABI;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class MethodReferenceAnalyzer
|
||||
{
|
||||
private readonly Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> _onNewMethod;
|
||||
|
||||
private readonly ConcurrentDictionary<MethodDef, List<IMethod>> _methodEffectInsts = new ConcurrentDictionary<MethodDef, List<IMethod>>();
|
||||
|
||||
public MethodReferenceAnalyzer(Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> onNewMethod)
|
||||
{
|
||||
_onNewMethod = onNewMethod;
|
||||
}
|
||||
|
||||
public void WalkMethod(MethodDef method, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst)
|
||||
{
|
||||
var ctx = new GenericArgumentContext(klassGenericInst, methodGenericInst);
|
||||
|
||||
if (_methodEffectInsts.TryGetValue(method, out var effectInsts))
|
||||
{
|
||||
foreach (var met in effectInsts)
|
||||
{
|
||||
var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();
|
||||
_onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var body = method.Body;
|
||||
if (body == null || !body.HasInstructions)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
effectInsts = new List<IMethod>();
|
||||
foreach (var inst in body.Instructions)
|
||||
{
|
||||
if (inst.Operand == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (inst.Operand)
|
||||
{
|
||||
case IMethod met:
|
||||
{
|
||||
if (!met.IsMethod)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare();
|
||||
if (resolveMet == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
effectInsts.Add(met);
|
||||
_onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet);
|
||||
break;
|
||||
}
|
||||
case ITokenOperand token:
|
||||
{
|
||||
//GenericParamContext paramContext = method.HasGenericParameters || method.DeclaringType.HasGenericParameters ?
|
||||
// new GenericParamContext(method.DeclaringType, method) : default;
|
||||
//method.Module.ResolveToken(token.MDToken, paramContext);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_methodEffectInsts.TryAdd(method, effectInsts);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c41435d2422e114eac193c405264d1d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
35
Assets/01.HybridCLR/Editor/Meta/PathAssemblyResolver.cs
Normal file
35
Assets/01.HybridCLR/Editor/Meta/PathAssemblyResolver.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HybridCLR.Editor.Meta
|
||||
{
|
||||
public class PathAssemblyResolver : AssemblyResolverBase
|
||||
{
|
||||
private readonly string[] _searchPaths;
|
||||
public PathAssemblyResolver(params string[] searchPaths)
|
||||
{
|
||||
_searchPaths = searchPaths;
|
||||
}
|
||||
|
||||
protected override bool TryResolveAssembly(string assemblyName, out string assemblyPath)
|
||||
{
|
||||
foreach(var path in _searchPaths)
|
||||
{
|
||||
string assPath = Path.Combine(path, assemblyName + ".dll");
|
||||
if (File.Exists(assPath))
|
||||
{
|
||||
Debug.Log($"resolve {assemblyName} at {assPath}");
|
||||
assemblyPath = assPath;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
assemblyPath = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/01.HybridCLR/Editor/Meta/PathAssemblyResolver.cs.meta
Normal file
11
Assets/01.HybridCLR/Editor/Meta/PathAssemblyResolver.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94848f63e75d660448de23b230886219
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user