Files
TheDeclineOfWarriors/Assets/FishNet/CodeGenerating/cecil-0.11.4/Mono.Cecil/Import.cs
T
2026-03-30 20:11:57 +07:00

829 lines
30 KiB
C#

//
// Author:
// Jb Evain (jbevain@gmail.com)
//
// Copyright (c) 2008 - 2015 Jb Evain
// Copyright (c) 2008 - 2011 Novell, Inc.
//
// Licensed under the MIT/X11 license.
//
using MonoFN.Cecil.Metadata;
using MonoFN.Collections.Generic;
using System;
using System.Collections.Generic;
using SR = System.Reflection;
namespace MonoFN.Cecil
{
public interface IMetadataImporterProvider
{
IMetadataImporter GetMetadataImporter(ModuleDefinition module);
}
public interface IMetadataImporter
{
AssemblyNameReference ImportReference(AssemblyNameReference reference);
TypeReference ImportReference(TypeReference type, IGenericParameterProvider context);
FieldReference ImportReference(FieldReference field, IGenericParameterProvider context);
MethodReference ImportReference(MethodReference method, IGenericParameterProvider context);
}
public interface IReflectionImporterProvider
{
IReflectionImporter GetReflectionImporter(ModuleDefinition module);
}
public interface IReflectionImporter
{
AssemblyNameReference ImportReference(SR.AssemblyName reference);
TypeReference ImportReference(Type type, IGenericParameterProvider context);
FieldReference ImportReference(SR.FieldInfo field, IGenericParameterProvider context);
MethodReference ImportReference(SR.MethodBase method, IGenericParameterProvider context);
}
internal struct ImportGenericContext
{
private Collection<IGenericParameterProvider> stack;
public bool IsEmpty
{
get { return stack == null; }
}
public ImportGenericContext(IGenericParameterProvider provider)
{
if (provider == null)
throw new ArgumentNullException("provider");
stack = null;
Push(provider);
}
public void Push(IGenericParameterProvider provider)
{
if (stack == null)
stack = new(1) { provider };
else
stack.Add(provider);
}
public void Pop()
{
stack.RemoveAt(stack.Count - 1);
}
public TypeReference MethodParameter(string method, int position)
{
for (int i = stack.Count - 1; i >= 0; i--)
{
MethodReference candidate = stack[i] as MethodReference;
if (candidate == null)
continue;
if (method != NormalizeMethodName(candidate))
continue;
return candidate.GenericParameters[position];
}
throw new InvalidOperationException();
}
public string NormalizeMethodName(MethodReference method)
{
return method.DeclaringType.GetElementType().FullName + "." + method.Name;
}
public TypeReference TypeParameter(string type, int position)
{
for (int i = stack.Count - 1; i >= 0; i--)
{
TypeReference candidate = GenericTypeFor(stack[i]);
if (candidate.FullName != type)
continue;
return candidate.GenericParameters[position];
}
throw new InvalidOperationException();
}
private static TypeReference GenericTypeFor(IGenericParameterProvider context)
{
TypeReference type = context as TypeReference;
if (type != null)
return type.GetElementType();
MethodReference method = context as MethodReference;
if (method != null)
return method.DeclaringType.GetElementType();
throw new InvalidOperationException();
}
public static ImportGenericContext For(IGenericParameterProvider context)
{
return context != null ? new(context) : default(ImportGenericContext);
}
}
public class DefaultReflectionImporter : IReflectionImporter
{
protected readonly ModuleDefinition module;
public DefaultReflectionImporter(ModuleDefinition module)
{
Mixin.CheckModule(module);
this.module = module;
}
private enum ImportGenericKind
{
Definition,
Open
}
private static readonly Dictionary<Type, ElementType> type_etype_mapping = new(18)
{
{ typeof(void), ElementType.Void },
{ typeof(bool), ElementType.Boolean },
{ typeof(char), ElementType.Char },
{ typeof(sbyte), ElementType.I1 },
{ typeof(byte), ElementType.U1 },
{ typeof(short), ElementType.I2 },
{ typeof(ushort), ElementType.U2 },
{ typeof(int), ElementType.I4 },
{ typeof(uint), ElementType.U4 },
{ typeof(long), ElementType.I8 },
{ typeof(ulong), ElementType.U8 },
{ typeof(float), ElementType.R4 },
{ typeof(double), ElementType.R8 },
{ typeof(string), ElementType.String },
{ typeof(TypedReference), ElementType.TypedByRef },
{ typeof(IntPtr), ElementType.I },
{ typeof(UIntPtr), ElementType.U },
{ typeof(object), ElementType.Object }
};
private TypeReference ImportType(Type type, ImportGenericContext context)
{
return ImportType(type, context, ImportGenericKind.Open);
}
private TypeReference ImportType(Type type, ImportGenericContext context, ImportGenericKind import_kind)
{
if (IsTypeSpecification(type) || ImportOpenGenericType(type, import_kind))
return ImportTypeSpecification(type, context);
TypeReference reference = new(string.Empty, type.Name, module, ImportScope(type), type.IsValueType);
reference.etype = ImportElementType(type);
if (IsNestedType(type))
reference.DeclaringType = ImportType(type.DeclaringType, context, import_kind);
else
reference.Namespace = type.Namespace ?? string.Empty;
if (type.IsGenericType)
ImportGenericParameters(reference, type.GetGenericArguments());
return reference;
}
protected virtual IMetadataScope ImportScope(Type type)
{
return ImportScope(type.Assembly);
}
private static bool ImportOpenGenericType(Type type, ImportGenericKind import_kind)
{
return type.IsGenericType && type.IsGenericTypeDefinition && import_kind == ImportGenericKind.Open;
}
private static bool ImportOpenGenericMethod(SR.MethodBase method, ImportGenericKind import_kind)
{
return method.IsGenericMethod && method.IsGenericMethodDefinition && import_kind == ImportGenericKind.Open;
}
private static bool IsNestedType(Type type)
{
return type.IsNested;
}
private TypeReference ImportTypeSpecification(Type type, ImportGenericContext context)
{
if (type.IsByRef)
return new ByReferenceType(ImportType(type.GetElementType(), context));
if (type.IsPointer)
return new PointerType(ImportType(type.GetElementType(), context));
if (type.IsArray)
return new ArrayType(ImportType(type.GetElementType(), context), type.GetArrayRank());
if (type.IsGenericType)
return ImportGenericInstance(type, context);
if (type.IsGenericParameter)
return ImportGenericParameter(type, context);
throw new NotSupportedException(type.FullName);
}
private static TypeReference ImportGenericParameter(Type type, ImportGenericContext context)
{
if (context.IsEmpty)
throw new InvalidOperationException();
if (type.DeclaringMethod != null)
return context.MethodParameter(NormalizeMethodName(type.DeclaringMethod), type.GenericParameterPosition);
if (type.DeclaringType != null)
return context.TypeParameter(NormalizeTypeFullName(type.DeclaringType), type.GenericParameterPosition);
throw new InvalidOperationException();
}
private static string NormalizeMethodName(SR.MethodBase method)
{
return NormalizeTypeFullName(method.DeclaringType) + "." + method.Name;
}
private static string NormalizeTypeFullName(Type type)
{
if (IsNestedType(type))
return NormalizeTypeFullName(type.DeclaringType) + "/" + type.Name;
return type.FullName;
}
private TypeReference ImportGenericInstance(Type type, ImportGenericContext context)
{
TypeReference element_type = ImportType(type.GetGenericTypeDefinition(), context, ImportGenericKind.Definition);
Type[] arguments = type.GetGenericArguments();
GenericInstanceType instance = new(element_type, arguments.Length);
Collection<TypeReference> instance_arguments = instance.GenericArguments;
context.Push(element_type);
try
{
for (int i = 0; i < arguments.Length; i++)
instance_arguments.Add(ImportType(arguments[i], context));
return instance;
}
finally
{
context.Pop();
}
}
private static bool IsTypeSpecification(Type type)
{
return type.HasElementType || IsGenericInstance(type) || type.IsGenericParameter;
}
private static bool IsGenericInstance(Type type)
{
return type.IsGenericType && !type.IsGenericTypeDefinition;
}
private static ElementType ImportElementType(Type type)
{
ElementType etype;
if (!type_etype_mapping.TryGetValue(type, out etype))
return ElementType.None;
return etype;
}
protected AssemblyNameReference ImportScope(SR.Assembly assembly)
{
return ImportReference(assembly.GetName());
}
public virtual AssemblyNameReference ImportReference(SR.AssemblyName name)
{
Mixin.CheckName(name);
AssemblyNameReference reference;
if (TryGetAssemblyNameReference(name, out reference))
return reference;
reference = new(name.Name, name.Version)
{
PublicKeyToken = name.GetPublicKeyToken(),
Culture = name.CultureInfo.Name,
HashAlgorithm = (AssemblyHashAlgorithm)name.HashAlgorithm
};
module.AssemblyReferences.Add(reference);
return reference;
}
private bool TryGetAssemblyNameReference(SR.AssemblyName name, out AssemblyNameReference assembly_reference)
{
Collection<AssemblyNameReference> references = module.AssemblyReferences;
for (int i = 0; i < references.Count; i++)
{
AssemblyNameReference reference = references[i];
if (name.FullName != reference.FullName) // TODO compare field by field
continue;
assembly_reference = reference;
return true;
}
assembly_reference = null;
return false;
}
private FieldReference ImportField(SR.FieldInfo field, ImportGenericContext context)
{
TypeReference declaring_type = ImportType(field.DeclaringType, context);
if (IsGenericInstance(field.DeclaringType))
field = ResolveFieldDefinition(field);
context.Push(declaring_type);
try
{
return new()
{
Name = field.Name,
DeclaringType = declaring_type,
FieldType = ImportType(field.FieldType, context)
};
}
finally
{
context.Pop();
}
}
private static SR.FieldInfo ResolveFieldDefinition(SR.FieldInfo field)
{
return field.Module.ResolveField(field.MetadataToken);
}
private static SR.MethodBase ResolveMethodDefinition(SR.MethodBase method)
{
return method.Module.ResolveMethod(method.MetadataToken);
}
private MethodReference ImportMethod(SR.MethodBase method, ImportGenericContext context, ImportGenericKind import_kind)
{
if (IsMethodSpecification(method) || ImportOpenGenericMethod(method, import_kind))
return ImportMethodSpecification(method, context);
TypeReference declaring_type = ImportType(method.DeclaringType, context);
if (IsGenericInstance(method.DeclaringType))
method = ResolveMethodDefinition(method);
MethodReference reference = new()
{
Name = method.Name,
HasThis = HasCallingConvention(method, SR.CallingConventions.HasThis),
ExplicitThis = HasCallingConvention(method, SR.CallingConventions.ExplicitThis),
DeclaringType = ImportType(method.DeclaringType, context, ImportGenericKind.Definition)
};
if (HasCallingConvention(method, SR.CallingConventions.VarArgs))
reference.CallingConvention &= MethodCallingConvention.VarArg;
if (method.IsGenericMethod)
ImportGenericParameters(reference, method.GetGenericArguments());
context.Push(reference);
try
{
SR.MethodInfo method_info = method as SR.MethodInfo;
reference.ReturnType = method_info != null ? ImportType(method_info.ReturnType, context) : ImportType(typeof(void), default);
SR.ParameterInfo[] parameters = method.GetParameters();
Collection<ParameterDefinition> reference_parameters = reference.Parameters;
for (int i = 0; i < parameters.Length; i++)
reference_parameters.Add(new(ImportType(parameters[i].ParameterType, context)));
reference.DeclaringType = declaring_type;
return reference;
}
finally
{
context.Pop();
}
}
private static void ImportGenericParameters(IGenericParameterProvider provider, Type[] arguments)
{
Collection<GenericParameter> provider_parameters = provider.GenericParameters;
for (int i = 0; i < arguments.Length; i++)
provider_parameters.Add(new(arguments[i].Name, provider));
}
private static bool IsMethodSpecification(SR.MethodBase method)
{
return method.IsGenericMethod && !method.IsGenericMethodDefinition;
}
private MethodReference ImportMethodSpecification(SR.MethodBase method, ImportGenericContext context)
{
SR.MethodInfo method_info = method as SR.MethodInfo;
if (method_info == null)
throw new InvalidOperationException();
MethodReference element_method = ImportMethod(method_info.GetGenericMethodDefinition(), context, ImportGenericKind.Definition);
GenericInstanceMethod instance = new(element_method);
Type[] arguments = method.GetGenericArguments();
Collection<TypeReference> instance_arguments = instance.GenericArguments;
context.Push(element_method);
try
{
for (int i = 0; i < arguments.Length; i++)
instance_arguments.Add(ImportType(arguments[i], context));
return instance;
}
finally
{
context.Pop();
}
}
private static bool HasCallingConvention(SR.MethodBase method, SR.CallingConventions conventions)
{
return (method.CallingConvention & conventions) != 0;
}
public virtual TypeReference ImportReference(Type type, IGenericParameterProvider context)
{
Mixin.CheckType(type);
return ImportType(type, ImportGenericContext.For(context), context != null ? ImportGenericKind.Open : ImportGenericKind.Definition);
}
public virtual FieldReference ImportReference(SR.FieldInfo field, IGenericParameterProvider context)
{
Mixin.CheckField(field);
return ImportField(field, ImportGenericContext.For(context));
}
public virtual MethodReference ImportReference(SR.MethodBase method, IGenericParameterProvider context)
{
Mixin.CheckMethod(method);
return ImportMethod(method, ImportGenericContext.For(context), context != null ? ImportGenericKind.Open : ImportGenericKind.Definition);
}
}
public class DefaultMetadataImporter : IMetadataImporter
{
protected readonly ModuleDefinition module;
public DefaultMetadataImporter(ModuleDefinition module)
{
Mixin.CheckModule(module);
this.module = module;
}
private TypeReference ImportType(TypeReference type, ImportGenericContext context)
{
if (type.IsTypeSpecification())
return ImportTypeSpecification(type, context);
TypeReference reference = new(type.Namespace, type.Name, module, ImportScope(type), type.IsValueType);
MetadataSystem.TryProcessPrimitiveTypeReference(reference);
if (type.IsNested)
reference.DeclaringType = ImportType(type.DeclaringType, context);
if (type.HasGenericParameters)
ImportGenericParameters(reference, type);
return reference;
}
protected virtual IMetadataScope ImportScope(TypeReference type)
{
return ImportScope(type.Scope);
}
protected IMetadataScope ImportScope(IMetadataScope scope)
{
switch (scope.MetadataScopeType)
{
case MetadataScopeType.AssemblyNameReference:
return ImportReference((AssemblyNameReference)scope);
case MetadataScopeType.ModuleDefinition:
if (scope == module)
return scope;
return ImportReference(((ModuleDefinition)scope).Assembly.Name);
case MetadataScopeType.ModuleReference:
throw new NotImplementedException();
}
throw new NotSupportedException();
}
public virtual AssemblyNameReference ImportReference(AssemblyNameReference name)
{
Mixin.CheckName(name);
AssemblyNameReference reference;
if (module.TryGetAssemblyNameReference(name, out reference))
return reference;
reference = new(name.Name, name.Version)
{
Culture = name.Culture,
HashAlgorithm = name.HashAlgorithm,
IsRetargetable = name.IsRetargetable,
IsWindowsRuntime = name.IsWindowsRuntime
};
byte[] pk_token = !name.PublicKeyToken.IsNullOrEmpty() ? new byte[name.PublicKeyToken.Length] : Empty<byte>.Array;
if (pk_token.Length > 0)
Buffer.BlockCopy(name.PublicKeyToken, 0, pk_token, 0, pk_token.Length);
reference.PublicKeyToken = pk_token;
// Only add if not self.
if (CanAddAssemblyNameReference(module, reference))
module.AssemblyReferences.Add(reference);
return reference;
}
private bool CanAddAssemblyNameReference(ModuleDefinition module, AssemblyNameReference nameRef)
{
return true;
// return (module.assembly.FullName != nameRef.FullName);
}
private static void ImportGenericParameters(IGenericParameterProvider imported, IGenericParameterProvider original)
{
Collection<GenericParameter> parameters = original.GenericParameters;
Collection<GenericParameter> imported_parameters = imported.GenericParameters;
for (int i = 0; i < parameters.Count; i++)
imported_parameters.Add(new(parameters[i].Name, imported));
}
private TypeReference ImportTypeSpecification(TypeReference type, ImportGenericContext context)
{
switch (type.etype)
{
case ElementType.SzArray:
ArrayType vector = (ArrayType)type;
return new ArrayType(ImportType(vector.ElementType, context));
case ElementType.Ptr:
PointerType pointer = (PointerType)type;
return new PointerType(ImportType(pointer.ElementType, context));
case ElementType.ByRef:
ByReferenceType byref = (ByReferenceType)type;
return new ByReferenceType(ImportType(byref.ElementType, context));
case ElementType.Pinned:
PinnedType pinned = (PinnedType)type;
return new PinnedType(ImportType(pinned.ElementType, context));
case ElementType.Sentinel:
SentinelType sentinel = (SentinelType)type;
return new SentinelType(ImportType(sentinel.ElementType, context));
case ElementType.FnPtr:
FunctionPointerType fnptr = (FunctionPointerType)type;
FunctionPointerType imported_fnptr = new()
{
HasThis = fnptr.HasThis,
ExplicitThis = fnptr.ExplicitThis,
CallingConvention = fnptr.CallingConvention,
ReturnType = ImportType(fnptr.ReturnType, context)
};
if (!fnptr.HasParameters)
return imported_fnptr;
for (int i = 0; i < fnptr.Parameters.Count; i++)
imported_fnptr.Parameters.Add(new(ImportType(fnptr.Parameters[i].ParameterType, context)));
return imported_fnptr;
case ElementType.CModOpt:
OptionalModifierType modopt = (OptionalModifierType)type;
return new OptionalModifierType(ImportType(modopt.ModifierType, context), ImportType(modopt.ElementType, context));
case ElementType.CModReqD:
RequiredModifierType modreq = (RequiredModifierType)type;
return new RequiredModifierType(ImportType(modreq.ModifierType, context), ImportType(modreq.ElementType, context));
case ElementType.Array:
ArrayType array = (ArrayType)type;
ArrayType imported_array = new(ImportType(array.ElementType, context));
if (array.IsVector)
return imported_array;
Collection<ArrayDimension> dimensions = array.Dimensions;
Collection<ArrayDimension> imported_dimensions = imported_array.Dimensions;
imported_dimensions.Clear();
for (int i = 0; i < dimensions.Count; i++)
{
ArrayDimension dimension = dimensions[i];
imported_dimensions.Add(new(dimension.LowerBound, dimension.UpperBound));
}
return imported_array;
case ElementType.GenericInst:
GenericInstanceType instance = (GenericInstanceType)type;
TypeReference element_type = ImportType(instance.ElementType, context);
Collection<TypeReference> arguments = instance.GenericArguments;
GenericInstanceType imported_instance = new(element_type, arguments.Count);
Collection<TypeReference> imported_arguments = imported_instance.GenericArguments;
for (int i = 0; i < arguments.Count; i++)
imported_arguments.Add(ImportType(arguments[i], context));
return imported_instance;
case ElementType.Var:
GenericParameter var_parameter = (GenericParameter)type;
if (var_parameter.DeclaringType == null)
throw new InvalidOperationException();
return context.TypeParameter(var_parameter.DeclaringType.FullName, var_parameter.Position);
case ElementType.MVar:
GenericParameter mvar_parameter = (GenericParameter)type;
if (mvar_parameter.DeclaringMethod == null)
throw new InvalidOperationException();
return context.MethodParameter(context.NormalizeMethodName(mvar_parameter.DeclaringMethod), mvar_parameter.Position);
}
throw new NotSupportedException(type.etype.ToString());
}
private FieldReference ImportField(FieldReference field, ImportGenericContext context)
{
TypeReference declaring_type = ImportType(field.DeclaringType, context);
context.Push(declaring_type);
try
{
return new()
{
Name = field.Name,
DeclaringType = declaring_type,
FieldType = ImportType(field.FieldType, context)
};
}
finally
{
context.Pop();
}
}
private MethodReference ImportMethod(MethodReference method, ImportGenericContext context)
{
if (method.IsGenericInstance)
return ImportMethodSpecification(method, context);
TypeReference declaring_type = ImportType(method.DeclaringType, context);
MethodReference reference = new()
{
Name = method.Name,
HasThis = method.HasThis,
ExplicitThis = method.ExplicitThis,
DeclaringType = declaring_type,
CallingConvention = method.CallingConvention
};
if (method.HasGenericParameters)
ImportGenericParameters(reference, method);
context.Push(reference);
try
{
reference.ReturnType = ImportType(method.ReturnType, context);
if (!method.HasParameters)
return reference;
Collection<ParameterDefinition> parameters = method.Parameters;
ParameterDefinitionCollection reference_parameters = reference.parameters = new(reference, parameters.Count);
for (int i = 0; i < parameters.Count; i++)
reference_parameters.Add(new(ImportType(parameters[i].ParameterType, context)));
return reference;
}
finally
{
context.Pop();
}
}
private MethodSpecification ImportMethodSpecification(MethodReference method, ImportGenericContext context)
{
if (!method.IsGenericInstance)
throw new NotSupportedException();
GenericInstanceMethod instance = (GenericInstanceMethod)method;
MethodReference element_method = ImportMethod(instance.ElementMethod, context);
GenericInstanceMethod imported_instance = new(element_method);
Collection<TypeReference> arguments = instance.GenericArguments;
Collection<TypeReference> imported_arguments = imported_instance.GenericArguments;
for (int i = 0; i < arguments.Count; i++)
imported_arguments.Add(ImportType(arguments[i], context));
return imported_instance;
}
public virtual TypeReference ImportReference(TypeReference type, IGenericParameterProvider context)
{
Mixin.CheckType(type);
return ImportType(type, ImportGenericContext.For(context));
}
public virtual FieldReference ImportReference(FieldReference field, IGenericParameterProvider context)
{
Mixin.CheckField(field);
return ImportField(field, ImportGenericContext.For(context));
}
public virtual MethodReference ImportReference(MethodReference method, IGenericParameterProvider context)
{
Mixin.CheckMethod(method);
return ImportMethod(method, ImportGenericContext.For(context));
}
}
internal static partial class Mixin
{
public static void CheckModule(ModuleDefinition module)
{
if (module == null)
throw new ArgumentNullException(Argument.module.ToString());
}
public static bool TryGetAssemblyNameReference(this ModuleDefinition module, AssemblyNameReference name_reference, out AssemblyNameReference assembly_reference)
{
Collection<AssemblyNameReference> references = module.AssemblyReferences;
for (int i = 0; i < references.Count; i++)
{
AssemblyNameReference reference = references[i];
if (!Equals(name_reference, reference))
continue;
assembly_reference = reference;
return true;
}
assembly_reference = null;
return false;
}
private static bool Equals(byte[] a, byte[] b)
{
if (ReferenceEquals(a, b))
return true;
if (a == null)
return false;
if (a.Length != b.Length)
return false;
for (int i = 0; i < a.Length; i++)
if (a[i] != b[i])
return false;
return true;
}
private static bool Equals<T>(T a, T b) where T : class, IEquatable<T>
{
if (ReferenceEquals(a, b))
return true;
if (a == null)
return false;
return a.Equals(b);
}
private static bool Equals(AssemblyNameReference a, AssemblyNameReference b)
{
if (ReferenceEquals(a, b))
return true;
if (a.Name != b.Name)
return false;
if (!Equals(a.Version, b.Version))
return false;
if (a.Culture != b.Culture)
return false;
if (!Equals(a.PublicKeyToken, b.PublicKeyToken))
return false;
return true;
}
}
}