diff options
author | jfrijters <jfrijters> | 2011-12-01 11:37:48 +0400 |
---|---|---|
committer | jfrijters <jfrijters> | 2011-12-01 11:37:48 +0400 |
commit | b1d03c25d3dc212e64e855214d1ebe98b5b1259c (patch) | |
tree | 7636ee293228040bad214d8f8ab33cdb34db50c7 | |
parent | 3c49c20346609d4c397dff93d25bb68297301516 (diff) |
Added support for function pointer types.
-rw-r--r-- | reflect/Module.cs | 11 | ||||
-rw-r--r-- | reflect/Reader/GenericTypeParameter.cs | 2 | ||||
-rw-r--r-- | reflect/Signature.cs | 27 | ||||
-rw-r--r-- | reflect/StandAloneMethodSig.cs | 22 | ||||
-rw-r--r-- | reflect/Type.cs | 107 | ||||
-rw-r--r-- | reflect/Universe.cs | 41 |
6 files changed, 187 insertions, 23 deletions
diff --git a/reflect/Module.cs b/reflect/Module.cs index 3530e5af..429fc39b 100644 --- a/reflect/Module.cs +++ b/reflect/Module.cs @@ -451,17 +451,6 @@ namespace IKVM.Reflection return GetCustomAttributes(token, null); } - internal Type CanonicalizeType(Type type) - { - Type canon; - if (!universe.canonicalizedTypes.TryGetValue(type, out canon)) - { - canon = type; - universe.canonicalizedTypes.Add(canon, canon); - } - return canon; - } - internal abstract Type GetModuleType(); internal abstract ByteReader GetBlob(int blobIndex); diff --git a/reflect/Reader/GenericTypeParameter.cs b/reflect/Reader/GenericTypeParameter.cs index d99e1af8..3b7fbd3e 100644 --- a/reflect/Reader/GenericTypeParameter.cs +++ b/reflect/Reader/GenericTypeParameter.cs @@ -169,7 +169,7 @@ namespace IKVM.Reflection.Reader internal static Type Make(int position) { - return module.CanonicalizeType(new UnboundGenericMethodParameter(position)); + return module.universe.CanonicalizeType(new UnboundGenericMethodParameter(position)); } private UnboundGenericMethodParameter(int position) diff --git a/reflect/Signature.cs b/reflect/Signature.cs index 787de5f7..ff6031e8 100644 --- a/reflect/Signature.cs +++ b/reflect/Signature.cs @@ -129,10 +129,16 @@ namespace IKVM.Reflection private static Type ReadFunctionPointer(ModuleReader module, ByteReader br, IGenericContext context) { - // TODO like .NET we return System.IntPtr here, but ideally we should fire an event in Universe that - // the user can hook to provide a custom type (or we simply should build in full support for function pointer types) - MethodSignature.ReadStandAloneMethodSig(module, br, context); - return module.universe.System_IntPtr; + __StandAloneMethodSig sig = MethodSignature.ReadStandAloneMethodSig(module, br, context); + if (module.universe.EnableFunctionPointers) + { + return FunctionPointerType.Make(module.universe, sig); + } + else + { + // by default, like .NET we return System.IntPtr here + return module.universe.System_IntPtr; + } } internal static Type[] ReadMethodSpec(ModuleReader module, ByteReader br, IGenericContext context) @@ -445,6 +451,19 @@ namespace IKVM.Reflection { WriteGenericSignature(module, bb, type); } + else if (type.__IsFunctionPointer) + { + bb.Write(ELEMENT_TYPE_FNPTR); + __StandAloneMethodSig sig = type.__MethodSignature; + if (sig.IsUnmanaged) + { + WriteStandAloneMethodSig(module, bb, sig.UnmanagedCallingConvention, sig.ReturnType, sig.ParameterTypes); + } + else + { + WriteStandAloneMethodSig(module, bb, sig.CallingConvention, sig.ReturnType, sig.ParameterTypes, sig.OptionalParameterTypes); + } + } else { if (type.IsValueType) diff --git a/reflect/StandAloneMethodSig.cs b/reflect/StandAloneMethodSig.cs index 007e5757..74d58d15 100644 --- a/reflect/StandAloneMethodSig.cs +++ b/reflect/StandAloneMethodSig.cs @@ -46,6 +46,28 @@ namespace IKVM.Reflection this.optionalParameterTypes = optionalParameterTypes; } + public bool Equals(__StandAloneMethodSig other) + { + return other != null + && other.unmanaged == unmanaged + && other.unmanagedCallingConvention == unmanagedCallingConvention + && other.callingConvention == callingConvention + && other.returnType == returnType + && Util.ArrayEquals(other.parameterTypes, parameterTypes) + && Util.ArrayEquals(other.optionalParameterTypes, optionalParameterTypes); + } + + public override bool Equals(object obj) + { + return Equals(obj as __StandAloneMethodSig); + } + + public override int GetHashCode() + { + return returnType.GetHashCode() + ^ Util.GetHashCode(parameterTypes); + } + public bool IsUnmanaged { get { return unmanaged; } diff --git a/reflect/Type.cs b/reflect/Type.cs index 43e84d50..6c0badaf 100644 --- a/reflect/Type.cs +++ b/reflect/Type.cs @@ -163,6 +163,11 @@ namespace IKVM.Reflection return __GetCustomModifiers().GetOptional(); } + public virtual __StandAloneMethodSig __MethodSignature + { + get { throw new InvalidOperationException(); } + } + public virtual bool HasElementType { get { return false; } @@ -188,6 +193,11 @@ namespace IKVM.Reflection get { return false; } } + public virtual bool __IsFunctionPointer + { + get { return false; } + } + public virtual bool IsValueType { get @@ -1064,7 +1074,7 @@ namespace IKVM.Reflection { get { - Universe u = this.Module.universe; + Universe u = this.Universe; return this == u.System_Boolean || this == u.System_Byte || this == u.System_SByte @@ -1819,6 +1829,11 @@ namespace IKVM.Reflection { throw new NotSupportedException(); } + + internal virtual Universe Universe + { + get { return Module.universe; } + } } abstract class ElementHolderType : Type @@ -1937,6 +1952,11 @@ namespace IKVM.Reflection return CustomAttributeData.EmptyList; } + internal sealed override Universe Universe + { + get { return elementType.Universe; } + } + internal abstract string GetSuffix(); protected abstract Type Wrap(Type type, CustomModifiers mods); @@ -1946,7 +1966,7 @@ namespace IKVM.Reflection { internal static Type Make(Type type, CustomModifiers mods) { - return type.Module.CanonicalizeType(new ArrayType(type, mods)); + return type.Universe.CanonicalizeType(new ArrayType(type, mods)); } private ArrayType(Type type, CustomModifiers mods) @@ -2034,7 +2054,7 @@ namespace IKVM.Reflection internal static Type Make(Type type, int rank, int[] sizes, int[] lobounds, CustomModifiers mods) { - return type.Module.CanonicalizeType(new MultiArrayType(type, rank, sizes, lobounds, mods)); + return type.Universe.CanonicalizeType(new MultiArrayType(type, rank, sizes, lobounds, mods)); } private MultiArrayType(Type type, int rank, int[] sizes, int[] lobounds, CustomModifiers mods) @@ -2252,7 +2272,7 @@ namespace IKVM.Reflection { internal static Type Make(Type type, CustomModifiers mods) { - return type.Module.CanonicalizeType(new ByRefType(type, mods)); + return type.Universe.CanonicalizeType(new ByRefType(type, mods)); } private ByRefType(Type type, CustomModifiers mods) @@ -2300,7 +2320,7 @@ namespace IKVM.Reflection { internal static Type Make(Type type, CustomModifiers mods) { - return type.Module.CanonicalizeType(new PointerType(type, mods)); + return type.Universe.CanonicalizeType(new PointerType(type, mods)); } private PointerType(Type type, CustomModifiers mods) @@ -2379,7 +2399,7 @@ namespace IKVM.Reflection } else { - return type.Module.CanonicalizeType(new GenericTypeInstance(type, typeArguments, mods)); + return type.Universe.CanonicalizeType(new GenericTypeInstance(type, typeArguments, mods)); } } @@ -2701,4 +2721,79 @@ namespace IKVM.Reflection return type.GetCustomAttributesData(attributeType); } } + + sealed class FunctionPointerType : Type + { + private readonly Universe universe; + private readonly __StandAloneMethodSig sig; + + internal static Type Make(Universe universe, __StandAloneMethodSig sig) + { + return universe.CanonicalizeType(new FunctionPointerType(universe, sig)); + } + + private FunctionPointerType(Universe universe, __StandAloneMethodSig sig) + { + this.universe = universe; + this.sig = sig; + } + + public override bool Equals(object obj) + { + FunctionPointerType other = obj as FunctionPointerType; + return other != null + && other.universe == universe + && other.sig.Equals(sig); + } + + public override int GetHashCode() + { + return sig.GetHashCode(); + } + + public override bool __IsFunctionPointer + { + get { return true; } + } + + public override __StandAloneMethodSig __MethodSignature + { + get { return sig; } + } + + public override Type BaseType + { + get { return null; } + } + + public override TypeAttributes Attributes + { + get { return 0; } + } + + public override string Name + { + get { throw new InvalidOperationException(); } + } + + public override string FullName + { + get { throw new InvalidOperationException(); } + } + + public override Module Module + { + get { throw new InvalidOperationException(); } + } + + internal override Universe Universe + { + get { return universe; } + } + + public override string ToString() + { + return "<FunctionPtr>"; + } + } } diff --git a/reflect/Universe.cs b/reflect/Universe.cs index 4ad9e465..d2f7e926 100644 --- a/reflect/Universe.cs +++ b/reflect/Universe.cs @@ -77,15 +77,23 @@ namespace IKVM.Reflection public delegate Assembly ResolveEventHandler(object sender, ResolveEventArgs args); + [Flags] + public enum UniverseOptions + { + None = 0, + EnableFunctionPointers = 1, + } + public sealed class Universe : IDisposable { - internal readonly Dictionary<Type, Type> canonicalizedTypes = new Dictionary<Type, Type>(); + private readonly Dictionary<Type, Type> canonicalizedTypes = new Dictionary<Type, Type>(); private readonly List<Assembly> assemblies = new List<Assembly>(); private readonly List<AssemblyBuilder> dynamicAssemblies = new List<AssemblyBuilder>(); private readonly Dictionary<string, Assembly> assembliesByName = new Dictionary<string, Assembly>(); private readonly Dictionary<System.Type, Type> importedTypes = new Dictionary<System.Type, Type>(); private Dictionary<ScopedTypeName, Type> missingTypes; private bool resolveMissingMembers; + private readonly bool enableFunctionPointers; private Type typeof_System_Object; private Type typeof_System_ValueType; private Type typeof_System_Enum; @@ -146,6 +154,16 @@ namespace IKVM.Reflection private Type typeof_System_Security_Permissions_SecurityAction; private List<ResolveEventHandler> resolvers = new List<ResolveEventHandler>(); + public Universe() + : this(UniverseOptions.None) + { + } + + public Universe(UniverseOptions options) + { + enableFunctionPointers = (options & UniverseOptions.EnableFunctionPointers) != 0; + } + internal Assembly Mscorlib { get { return Load("mscorlib"); } @@ -856,6 +874,11 @@ namespace IKVM.Reflection get { return resolveMissingMembers; } } + internal bool EnableFunctionPointers + { + get { return enableFunctionPointers; } + } + private struct ScopedTypeName : IEquatable<ScopedTypeName> { private readonly object scope; @@ -942,5 +965,21 @@ namespace IKVM.Reflection } throw new System.MissingMemberException(declaringType.ToString(), name); } + + internal Type CanonicalizeType(Type type) + { + Type canon; + if (!canonicalizedTypes.TryGetValue(type, out canon)) + { + canon = type; + canonicalizedTypes.Add(canon, canon); + } + return canon; + } + + public Type MakeFunctionPointer(__StandAloneMethodSig sig) + { + return FunctionPointerType.Make(this, sig); + } } } |