mirror of
https://github.com/Smaug123/WoofWare.PawPrint
synced 2025-10-05 14:18:40 +00:00
Better generics handling (#38)
This commit is contained in:
@@ -56,6 +56,12 @@ module TestCases =
|
||||
NativeImpls = NativeImpls.PassThru ()
|
||||
LocalVariablesOfMain = []
|
||||
}
|
||||
{
|
||||
FileName = "ResizeArray.cs"
|
||||
ExpectedReturnCode = 109
|
||||
NativeImpls = MockEnv.make ()
|
||||
LocalVariablesOfMain = [ CliType.Numeric (CliNumericType.Int32 10) ]
|
||||
}
|
||||
]
|
||||
|
||||
let cases : TestCase list =
|
||||
|
@@ -311,7 +311,7 @@ module Assembly =
|
||||
(fun i ->
|
||||
let i = i + 1
|
||||
let handle = MetadataTokens.MethodSpecificationHandle i
|
||||
KeyValuePair (handle, MethodSpec.make (metadataReader.GetMethodSpecification handle))
|
||||
KeyValuePair (handle, MethodSpec.make assy.Name (metadataReader.GetMethodSpecification handle))
|
||||
)
|
||||
|> ImmutableDictionary.CreateRange
|
||||
|
||||
@@ -320,7 +320,7 @@ module Assembly =
|
||||
|
||||
for i = 1 to metadataReader.GetTableRowCount TableIndex.TypeSpec do
|
||||
let handle = MetadataTokens.TypeSpecificationHandle i
|
||||
result.Add (handle, metadataReader.GetTypeSpecification handle |> TypeSpec.make handle)
|
||||
result.Add (handle, metadataReader.GetTypeSpecification handle |> TypeSpec.make assy.Name handle)
|
||||
|
||||
result.ToImmutable ()
|
||||
|
||||
@@ -334,6 +334,7 @@ module Assembly =
|
||||
metadataReader.GetBlobReader
|
||||
metadataReader.GetString
|
||||
MetadataToken.ofEntityHandle
|
||||
assy.Name
|
||||
(metadataReader.GetMemberReference c)
|
||||
)
|
||||
|
||||
|
@@ -141,7 +141,7 @@ module CliType =
|
||||
| TypeResolutionResult.FirstLoadAssy assy -> CliTypeResolutionResult.FirstLoad assy
|
||||
| SignatureTypeKind.Class -> CliType.ObjectRef None |> CliTypeResolutionResult.Resolved
|
||||
| _ -> raise (ArgumentOutOfRangeException ())
|
||||
| TypeDefn.FromDefinition (typeDefinitionHandle, signatureTypeKind) ->
|
||||
| TypeDefn.FromDefinition (typeDefinitionHandle, _, signatureTypeKind) ->
|
||||
match signatureTypeKind with
|
||||
| SignatureTypeKind.Unknown -> failwith "todo"
|
||||
| SignatureTypeKind.ValueType ->
|
||||
|
@@ -59,7 +59,12 @@ type RuntimeConcreteType = ConcreteType<TypeDefn>
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module ConcreteType =
|
||||
let make (assemblyName : AssemblyName) (defn : TypeDefinitionHandle) (generics : TypeDefn list) =
|
||||
let make
|
||||
(assemblyName : AssemblyName)
|
||||
(defn : TypeDefinitionHandle)
|
||||
(generics : TypeDefn list)
|
||||
: RuntimeConcreteType
|
||||
=
|
||||
{
|
||||
_AssemblyName = assemblyName
|
||||
_Definition = ComparableTypeDefinitionHandle.Make defn
|
||||
|
@@ -29,9 +29,81 @@ module Corelib =
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "ValueType" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
let boolean =
|
||||
corelib.TypeDefs
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Boolean" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
let char =
|
||||
corelib.TypeDefs
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Char" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
let byte =
|
||||
corelib.TypeDefs
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Byte" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
let sbyte =
|
||||
corelib.TypeDefs
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "SByte" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
let int16 =
|
||||
corelib.TypeDefs
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Int16" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
let int32 =
|
||||
corelib.TypeDefs
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Int32" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
let int64 =
|
||||
corelib.TypeDefs
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Int64" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
let uint16 =
|
||||
corelib.TypeDefs
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "UInt16" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
let uint32 =
|
||||
corelib.TypeDefs
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "UInt32" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
let uint64 =
|
||||
corelib.TypeDefs
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "UInt64" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
let single =
|
||||
corelib.TypeDefs
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Single" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
let double =
|
||||
corelib.TypeDefs
|
||||
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Double" then Some v else None)
|
||||
|> Seq.exactlyOne
|
||||
|
||||
{
|
||||
Corelib = corelib
|
||||
String = stringType
|
||||
Boolean = boolean
|
||||
Char = char
|
||||
SByte = sbyte
|
||||
Byte = byte
|
||||
Int16 = int16
|
||||
UInt16 = uint16
|
||||
Int32 = int32
|
||||
UInt32 = uint32
|
||||
Int64 = int64
|
||||
UInt64 = uint64
|
||||
Single = single
|
||||
Double = double
|
||||
Array = arrayType
|
||||
Enum = enumType
|
||||
ValueType = valueType
|
||||
|
@@ -45,14 +45,15 @@ module FieldInfo =
|
||||
: FieldInfo<FakeUnit>
|
||||
=
|
||||
let name = mr.GetString def.Name
|
||||
let fieldSig = def.DecodeSignature (TypeDefn.typeProvider, ())
|
||||
let fieldSig = def.DecodeSignature (TypeDefn.typeProvider assembly, ())
|
||||
let declaringType = def.GetDeclaringType ()
|
||||
let typeGenerics = mr.GetTypeDefinition(declaringType).GetGenericParameters().Count
|
||||
let declaringType = ConcreteType.make' assembly declaringType typeGenerics
|
||||
|
||||
{
|
||||
Name = name
|
||||
Signature = fieldSig
|
||||
DeclaringType = ConcreteType.make' assembly declaringType typeGenerics
|
||||
DeclaringType = declaringType
|
||||
Handle = handle
|
||||
Attributes = def.Attributes
|
||||
}
|
||||
@@ -63,10 +64,12 @@ module FieldInfo =
|
||||
(input : FieldInfo<'a>)
|
||||
: FieldInfo<'b>
|
||||
=
|
||||
let declaringType = input.DeclaringType |> ConcreteType.mapGeneric f
|
||||
|
||||
{
|
||||
Handle = input.Handle
|
||||
Name = input.Name
|
||||
DeclaringType = input.DeclaringType |> ConcreteType.mapGeneric f
|
||||
DeclaringType = declaringType
|
||||
Signature = input.Signature
|
||||
Attributes = input.Attributes
|
||||
|
||||
|
@@ -276,6 +276,7 @@ module IlMachineState =
|
||||
|
||||
let rec resolveTypeFromDefn
|
||||
(loggerFactory : ILoggerFactory)
|
||||
(corelib : BaseClassTypes<DumpedAssembly>)
|
||||
(ty : TypeDefn)
|
||||
(genericArgs : ImmutableArray<TypeDefn> option)
|
||||
(assy : DumpedAssembly)
|
||||
@@ -284,8 +285,45 @@ module IlMachineState =
|
||||
=
|
||||
match ty with
|
||||
| TypeDefn.GenericInstantiation (generic, args) ->
|
||||
resolveTypeFromDefn loggerFactory generic (Some args) assy state
|
||||
| TypeDefn.FromDefinition (defn, _typeKind) ->
|
||||
let args' = ImmutableArray.CreateBuilder ()
|
||||
|
||||
let state =
|
||||
(state, args)
|
||||
||> Seq.fold (fun state arg ->
|
||||
let state, assy, arg =
|
||||
resolveTypeFromDefn loggerFactory corelib arg genericArgs assy state
|
||||
|
||||
let baseType =
|
||||
arg.BaseType
|
||||
|> TypeInfo.resolveBaseType
|
||||
(fun (x : DumpedAssembly) -> x.Name)
|
||||
(fun x y -> x.TypeDefs.[y])
|
||||
corelib
|
||||
assy.Name
|
||||
|
||||
let signatureTypeKind =
|
||||
match baseType with
|
||||
| ResolvedBaseType.Enum
|
||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
||||
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
||||
| ResolvedBaseType.Delegate -> failwith "TODO: delegate"
|
||||
|
||||
args'.Add (
|
||||
TypeDefn.FromDefinition (
|
||||
ComparableTypeDefinitionHandle.Make arg.TypeDefHandle,
|
||||
assy.Name.FullName,
|
||||
signatureTypeKind
|
||||
)
|
||||
)
|
||||
|
||||
state
|
||||
)
|
||||
|
||||
let args' = args'.ToImmutable ()
|
||||
resolveTypeFromDefn loggerFactory corelib generic (Some args') assy state
|
||||
| TypeDefn.FromDefinition (defn, assy, _typeKind) ->
|
||||
let assy = state._LoadedAssemblies.[assy]
|
||||
|
||||
let defn =
|
||||
assy.TypeDefs.[defn.Get]
|
||||
|> TypeInfo.mapGeneric (fun param ->
|
||||
@@ -298,17 +336,48 @@ module IlMachineState =
|
||||
| TypeDefn.FromReference (ref, _typeKind) ->
|
||||
let state, assy, ty = resolveTypeFromRef loggerFactory assy ref genericArgs state
|
||||
state, assy, ty
|
||||
| TypeDefn.PrimitiveType prim ->
|
||||
let ty =
|
||||
match prim with
|
||||
| PrimitiveType.Boolean -> corelib.Boolean
|
||||
| PrimitiveType.Char -> corelib.Char
|
||||
| PrimitiveType.SByte -> corelib.SByte
|
||||
| PrimitiveType.Byte -> corelib.Byte
|
||||
| PrimitiveType.Int16 -> corelib.Int16
|
||||
| PrimitiveType.UInt16 -> corelib.UInt16
|
||||
| PrimitiveType.Int32 -> corelib.Int32
|
||||
| PrimitiveType.UInt32 -> corelib.UInt32
|
||||
| PrimitiveType.Int64 -> corelib.Int64
|
||||
| PrimitiveType.UInt64 -> corelib.UInt64
|
||||
| PrimitiveType.Single -> corelib.Single
|
||||
| PrimitiveType.Double -> corelib.Double
|
||||
| PrimitiveType.String -> corelib.String
|
||||
| PrimitiveType.TypedReference -> failwith "todo"
|
||||
| PrimitiveType.IntPtr -> failwith "todo"
|
||||
| PrimitiveType.UIntPtr -> failwith "todo"
|
||||
| PrimitiveType.Object -> failwith "todo"
|
||||
|> TypeInfo.mapGeneric (fun _ -> failwith "none of these types are generic")
|
||||
|
||||
state, corelib.Corelib, ty
|
||||
| TypeDefn.GenericTypeParameter param ->
|
||||
match genericArgs with
|
||||
| None -> failwith "tried to resolve generic parameter without generic args"
|
||||
| Some genericArgs ->
|
||||
let arg = genericArgs.[param]
|
||||
// TODO: this assembly is probably wrong?
|
||||
resolveTypeFromDefn loggerFactory corelib arg (Some genericArgs) assy state
|
||||
| s -> failwith $"TODO: resolveTypeFromDefn unimplemented for {s}"
|
||||
|
||||
let resolveTypeFromSpec
|
||||
(loggerFactory : ILoggerFactory)
|
||||
(corelib : BaseClassTypes<DumpedAssembly>)
|
||||
(ty : TypeSpecificationHandle)
|
||||
(assy : DumpedAssembly)
|
||||
(typeGenericArgs : TypeDefn ImmutableArray option)
|
||||
(state : IlMachineState)
|
||||
: IlMachineState * DumpedAssembly * WoofWare.PawPrint.TypeInfo<TypeDefn>
|
||||
=
|
||||
// Any necessary generics will be baked into the TypeDefn e.g. as a `GenericInstantiation`.
|
||||
resolveTypeFromDefn loggerFactory assy.TypeSpecs.[ty].Signature None assy state
|
||||
resolveTypeFromDefn loggerFactory corelib assy.TypeSpecs.[ty].Signature typeGenericArgs assy state
|
||||
|
||||
let rec cliTypeZeroOf
|
||||
(loggerFactory : ILoggerFactory)
|
||||
@@ -888,6 +957,8 @@ module IlMachineState =
|
||||
|
||||
let resolveMember
|
||||
(loggerFactory : ILoggerFactory)
|
||||
(corelib : BaseClassTypes<DumpedAssembly>)
|
||||
(currentThread : ThreadId)
|
||||
(assy : DumpedAssembly)
|
||||
(m : MemberReferenceHandle)
|
||||
(state : IlMachineState)
|
||||
@@ -903,7 +974,13 @@ module IlMachineState =
|
||||
let state, assy, targetType =
|
||||
match mem.Parent with
|
||||
| MetadataToken.TypeReference parent -> resolveType loggerFactory parent None assy state
|
||||
| MetadataToken.TypeSpecification parent -> resolveTypeFromSpec loggerFactory parent assy state
|
||||
| MetadataToken.TypeSpecification parent ->
|
||||
let typeGenerics =
|
||||
match state.ThreadState.[currentThread].MethodState.ExecutingMethod.DeclaringType.Generics with
|
||||
| [] -> None
|
||||
| l -> Some (ImmutableArray.CreateRange l)
|
||||
|
||||
resolveTypeFromSpec loggerFactory corelib parent assy typeGenerics state
|
||||
| parent -> failwith $"Unexpected: {parent}"
|
||||
|
||||
match mem.Signature with
|
||||
|
@@ -1,6 +1,7 @@
|
||||
namespace WoofWare.PawPrint
|
||||
|
||||
open System
|
||||
open System.Reflection
|
||||
open System.Reflection.Metadata
|
||||
|
||||
type MemberSignature =
|
||||
@@ -35,6 +36,7 @@ module MemberReference =
|
||||
(blobReader : BlobHandle -> BlobReader)
|
||||
(getString : StringHandle -> string)
|
||||
(makeParent : EntityHandle -> 'parent)
|
||||
(assemblyName : AssemblyName)
|
||||
(mr : System.Reflection.Metadata.MemberReference)
|
||||
: MemberReference<'parent>
|
||||
=
|
||||
@@ -45,8 +47,8 @@ module MemberReference =
|
||||
|
||||
let signature =
|
||||
match header.Kind with
|
||||
| SignatureKind.Method -> mr.DecodeMethodSignature (TypeDefn.typeProvider, ()) |> Choice1Of2
|
||||
| SignatureKind.Field -> mr.DecodeFieldSignature (TypeDefn.typeProvider, ()) |> Choice2Of2
|
||||
| SignatureKind.Method -> mr.DecodeMethodSignature (TypeDefn.typeProvider assemblyName, ()) |> Choice1Of2
|
||||
| SignatureKind.Field -> mr.DecodeFieldSignature (TypeDefn.typeProvider assemblyName, ()) |> Choice2Of2
|
||||
| SignatureKind.LocalVariables -> failwith "TODO: LocalVariables"
|
||||
| SignatureKind.Property -> failwith "TODO: Property"
|
||||
| SignatureKind.MethodSpecification -> failwith "TODO: MethodSpec"
|
||||
|
@@ -263,6 +263,7 @@ module MethodInfo =
|
||||
let private readMethodBody
|
||||
(peReader : PEReader)
|
||||
(metadataReader : MetadataReader)
|
||||
(assembly : AssemblyName)
|
||||
(methodDef : MethodDefinition)
|
||||
: MethodBody option
|
||||
=
|
||||
@@ -277,7 +278,7 @@ module MethodInfo =
|
||||
else
|
||||
|
||||
let s = methodBody.LocalSignature |> metadataReader.GetStandaloneSignature
|
||||
s.DecodeLocalSignature (TypeDefn.typeProvider, ()) |> Some
|
||||
s.DecodeLocalSignature (TypeDefn.typeProvider assembly, ()) |> Some
|
||||
|
||||
let ilBytes = methodBody.GetILBytes ()
|
||||
use bytes = fixed ilBytes
|
||||
@@ -584,7 +585,7 @@ module MethodInfo =
|
||||
let assemblyName = metadataReader.GetAssemblyDefinition().GetAssemblyName ()
|
||||
let methodDef = metadataReader.GetMethodDefinition methodHandle
|
||||
let methodName = metadataReader.GetString methodDef.Name
|
||||
let methodSig = methodDef.DecodeSignature (TypeDefn.typeProvider, ())
|
||||
let methodSig = methodDef.DecodeSignature (TypeDefn.typeProvider assemblyName, ())
|
||||
let implAttrs = methodDef.ImplAttributes
|
||||
|
||||
let methodBody =
|
||||
@@ -596,7 +597,7 @@ module MethodInfo =
|
||||
elif methodDef.Attributes.HasFlag MethodAttributes.PinvokeImpl then
|
||||
None
|
||||
else
|
||||
match readMethodBody peReader metadataReader methodDef with
|
||||
match readMethodBody peReader metadataReader assemblyName methodDef with
|
||||
| None ->
|
||||
logger.LogTrace $"no method body in {assemblyName.Name} {methodName}"
|
||||
None
|
||||
@@ -682,7 +683,7 @@ module MethodInfo =
|
||||
| TypeDefn.OneDimensionalArrayLowerBoundZero elements -> failwith "todo"
|
||||
| TypeDefn.Modified (original, afterMod, modificationRequired) -> failwith "todo"
|
||||
| TypeDefn.FromReference (typeRef, signatureTypeKind) -> failwith "todo"
|
||||
| TypeDefn.FromDefinition (comparableTypeDefinitionHandle, signatureTypeKind) -> failwith "todo"
|
||||
| TypeDefn.FromDefinition (comparableTypeDefinitionHandle, _, signatureTypeKind) -> failwith "todo"
|
||||
| TypeDefn.GenericInstantiation (generic, args) -> failwith "todo"
|
||||
| TypeDefn.FunctionPointer typeMethodSignature -> failwith "todo"
|
||||
| TypeDefn.GenericTypeParameter index ->
|
||||
|
@@ -1,6 +1,7 @@
|
||||
namespace WoofWare.PawPrint
|
||||
|
||||
open System.Collections.Immutable
|
||||
open System.Reflection
|
||||
open System.Reflection.Metadata
|
||||
|
||||
/// <summary>
|
||||
@@ -19,8 +20,8 @@ type MethodSpec =
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module MethodSpec =
|
||||
let make (p : MethodSpecification) : MethodSpec =
|
||||
let signature = p.DecodeSignature (TypeDefn.typeProvider, ())
|
||||
let make (assemblyName : AssemblyName) (p : MethodSpecification) : MethodSpec =
|
||||
let signature = p.DecodeSignature (TypeDefn.typeProvider assemblyName, ())
|
||||
|
||||
{
|
||||
// Horrible abuse to get this as an int
|
||||
|
@@ -1,6 +1,7 @@
|
||||
namespace WoofWare.PawPrint
|
||||
|
||||
open System.Collections.Immutable
|
||||
open System.Reflection
|
||||
open System.Reflection.Metadata
|
||||
open System.Reflection.Metadata.Ecma335
|
||||
open Microsoft.FSharp.Core
|
||||
@@ -106,7 +107,7 @@ type TypeDefn =
|
||||
| OneDimensionalArrayLowerBoundZero of elements : TypeDefn
|
||||
| Modified of original : TypeDefn * afterMod : TypeDefn * modificationRequired : bool
|
||||
| FromReference of TypeRef * SignatureTypeKind
|
||||
| FromDefinition of ComparableTypeDefinitionHandle * SignatureTypeKind
|
||||
| FromDefinition of ComparableTypeDefinitionHandle * assemblyFullName : string * SignatureTypeKind
|
||||
| GenericInstantiation of generic : TypeDefn * args : ImmutableArray<TypeDefn>
|
||||
| FunctionPointer of TypeMethodSignature<TypeDefn>
|
||||
| GenericTypeParameter of index : int
|
||||
@@ -126,7 +127,7 @@ module TypeDefn =
|
||||
| TypeDefn.OneDimensionalArrayLowerBoundZero elements -> failwith "todo"
|
||||
| TypeDefn.Modified (original, afterMod, modificationRequired) -> failwith "todo"
|
||||
| TypeDefn.FromReference _ -> true
|
||||
| TypeDefn.FromDefinition (_, signatureTypeKind) ->
|
||||
| TypeDefn.FromDefinition (_, _, signatureTypeKind) ->
|
||||
match signatureTypeKind with
|
||||
| SignatureTypeKind.Unknown -> failwith "todo"
|
||||
| SignatureTypeKind.ValueType -> false
|
||||
@@ -174,7 +175,7 @@ module TypeDefn =
|
||||
| SignatureTypeCode.Pinned -> failwith "todo"
|
||||
| x -> failwith $"Unrecognised type code: {x}"
|
||||
|
||||
let typeProvider : ISignatureTypeProvider<TypeDefn, unit> =
|
||||
let typeProvider (a : AssemblyName) : ISignatureTypeProvider<TypeDefn, unit> =
|
||||
{ new ISignatureTypeProvider<TypeDefn, unit> with
|
||||
member this.GetArrayType (elementType : TypeDefn, shape : ArrayShape) : TypeDefn =
|
||||
TypeDefn.Array (elementType, ())
|
||||
@@ -202,7 +203,7 @@ module TypeDefn =
|
||||
let handle' : EntityHandle = TypeDefinitionHandle.op_Implicit handle
|
||||
let typeKind = reader.ResolveSignatureTypeKind (handle', rawTypeKind)
|
||||
|
||||
TypeDefn.FromDefinition (ComparableTypeDefinitionHandle.Make handle, typeKind)
|
||||
TypeDefn.FromDefinition (ComparableTypeDefinitionHandle.Make handle, a.FullName, typeKind)
|
||||
|
||||
member this.GetTypeFromReference
|
||||
(reader : MetadataReader, handle : TypeReferenceHandle, rawTypeKind : byte)
|
||||
|
@@ -97,6 +97,18 @@ type BaseClassTypes<'corelib> =
|
||||
{
|
||||
Corelib : 'corelib
|
||||
String : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
Boolean : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
Char : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
SByte : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
Byte : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
Int16 : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
UInt16 : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
Int32 : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
UInt32 : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
Int64 : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
UInt64 : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
Single : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
Double : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
Array : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
Enum : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
ValueType : TypeInfo<WoofWare.PawPrint.GenericParameter>
|
||||
|
@@ -1,5 +1,6 @@
|
||||
namespace WoofWare.PawPrint
|
||||
|
||||
open System.Reflection
|
||||
open System.Reflection.Metadata
|
||||
|
||||
/// <summary>
|
||||
@@ -23,8 +24,8 @@ type TypeSpec =
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module TypeSpec =
|
||||
let make (handle : TypeSpecificationHandle) (r : TypeSpecification) : TypeSpec =
|
||||
let spec = r.DecodeSignature (TypeDefn.typeProvider, ())
|
||||
let make (assembly : AssemblyName) (handle : TypeSpecificationHandle) (r : TypeSpecification) : TypeSpec =
|
||||
let spec = r.DecodeSignature (TypeDefn.typeProvider assembly, ())
|
||||
|
||||
{
|
||||
Handle = handle
|
||||
|
@@ -2,6 +2,7 @@ namespace WoofWare.PawPrint
|
||||
|
||||
open System.Collections.Immutable
|
||||
open System.Reflection
|
||||
open System.Reflection.Metadata
|
||||
open Microsoft.Extensions.Logging
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
@@ -33,7 +34,13 @@ module internal UnaryMetadataIlOp =
|
||||
state, method, Some spec.Signature
|
||||
| MetadataToken.MemberReference ref ->
|
||||
let state, _, method =
|
||||
IlMachineState.resolveMember loggerFactory (state.ActiveAssembly thread) ref state
|
||||
IlMachineState.resolveMember
|
||||
loggerFactory
|
||||
baseClassTypes
|
||||
thread
|
||||
(state.ActiveAssembly thread)
|
||||
ref
|
||||
state
|
||||
|
||||
match method with
|
||||
| Choice2Of2 _field -> failwith "tried to Call a field"
|
||||
@@ -41,7 +48,13 @@ module internal UnaryMetadataIlOp =
|
||||
| k -> failwith $"Unrecognised kind: %O{k}"
|
||||
| MetadataToken.MemberReference h ->
|
||||
let state, _, method =
|
||||
IlMachineState.resolveMember loggerFactory (state.ActiveAssembly thread) h state
|
||||
IlMachineState.resolveMember
|
||||
loggerFactory
|
||||
baseClassTypes
|
||||
thread
|
||||
(state.ActiveAssembly thread)
|
||||
h
|
||||
state
|
||||
|
||||
match method with
|
||||
| Choice2Of2 _field -> failwith "tried to Call a field"
|
||||
@@ -140,7 +153,13 @@ module internal UnaryMetadataIlOp =
|
||||
state, activeAssy.Name, MethodInfo.mapTypeGenerics (fun _ -> failwith "non-generic method") method
|
||||
| MemberReference mr ->
|
||||
let state, name, method =
|
||||
IlMachineState.resolveMember loggerFactory (state.ActiveAssembly thread) mr state
|
||||
IlMachineState.resolveMember
|
||||
loggerFactory
|
||||
baseClassTypes
|
||||
thread
|
||||
(state.ActiveAssembly thread)
|
||||
mr
|
||||
state
|
||||
|
||||
match method with
|
||||
| Choice1Of2 mr -> state, name, mr
|
||||
@@ -217,38 +236,47 @@ module internal UnaryMetadataIlOp =
|
||||
| EvalStackValue.Int32 v -> v
|
||||
| popped -> failwith $"unexpectedly popped value %O{popped} to serve as array len"
|
||||
|
||||
let baseType =
|
||||
let elementType, assy =
|
||||
match metadataToken with
|
||||
| MetadataToken.TypeDefinition defn ->
|
||||
let assy = state.LoadedAssembly currentState.ActiveAssembly |> Option.get
|
||||
let elementType = assy.TypeDefs.[defn]
|
||||
let defn = assy.TypeDefs.[defn]
|
||||
|
||||
let baseType =
|
||||
elementType.BaseType
|
||||
defn.BaseType
|
||||
|> TypeInfo.resolveBaseType
|
||||
(fun (x : DumpedAssembly) -> x.Name)
|
||||
(fun x y -> x.TypeDefs.[y])
|
||||
baseClassTypes
|
||||
elementType.Assembly
|
||||
defn.Assembly
|
||||
|
||||
baseType
|
||||
let signatureTypeKind =
|
||||
match baseType with
|
||||
| ResolvedBaseType.Enum
|
||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
||||
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
||||
| ResolvedBaseType.Delegate -> failwith "TODO: delegate"
|
||||
|
||||
TypeDefn.FromDefinition (
|
||||
ComparableTypeDefinitionHandle.Make defn.TypeDefHandle,
|
||||
defn.Assembly.Name,
|
||||
signatureTypeKind
|
||||
),
|
||||
assy
|
||||
| MetadataToken.TypeSpecification spec ->
|
||||
let assy = state.LoadedAssembly currentState.ActiveAssembly |> Option.get
|
||||
let elementType = assy.TypeSpecs.[spec].Signature
|
||||
|
||||
MethodInfo.resolveBaseType newMethodState.Generics newMethodState.ExecutingMethod elementType
|
||||
assy.TypeSpecs.[spec].Signature, assy
|
||||
| x -> failwith $"TODO: Newarr element type resolution unimplemented for {x}"
|
||||
|
||||
let zeroOfType =
|
||||
match baseType with
|
||||
| ResolvedBaseType.Object ->
|
||||
// initialise with null references
|
||||
fun () -> CliType.ObjectRef None
|
||||
| ResolvedBaseType.Enum -> failwith "TODO: Newarr Enum array initialization unimplemented"
|
||||
| ResolvedBaseType.ValueType -> failwith "TODO: Newarr ValueType array initialization unimplemented"
|
||||
| ResolvedBaseType.Delegate -> failwith "TODO: Newarr Delegate array initialization unimplemented"
|
||||
let typeGenerics =
|
||||
match newMethodState.ExecutingMethod.DeclaringType.Generics with
|
||||
| [] -> None
|
||||
| l -> Some (ImmutableArray.CreateRange l)
|
||||
|
||||
let alloc, state = IlMachineState.allocateArray zeroOfType len state
|
||||
let state, zeroOfType =
|
||||
IlMachineState.cliTypeZeroOf loggerFactory assy elementType typeGenerics newMethodState.Generics state
|
||||
|
||||
let alloc, state = IlMachineState.allocateArray (fun () -> zeroOfType) len state
|
||||
|
||||
let state =
|
||||
{ state with
|
||||
@@ -284,14 +312,21 @@ module internal UnaryMetadataIlOp =
|
||||
| Stfld ->
|
||||
let activeAssy = state.ActiveAssembly thread
|
||||
|
||||
let state, declaringType, field =
|
||||
let state, field =
|
||||
match metadataToken with
|
||||
| MetadataToken.FieldDefinition f ->
|
||||
let field =
|
||||
activeAssy.Fields.[f]
|
||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "no generics allowed in FieldDefinition")
|
||||
|
||||
state, field.DeclaringType, field
|
||||
state, field
|
||||
| MetadataToken.MemberReference mr ->
|
||||
let state, _, field =
|
||||
IlMachineState.resolveMember loggerFactory baseClassTypes thread activeAssy mr state
|
||||
|
||||
match field with
|
||||
| Choice1Of2 _method -> failwith "member reference was unexpectedly a method"
|
||||
| Choice2Of2 field -> state, field
|
||||
| t -> failwith $"Unexpectedly asked to store to a non-field: {t}"
|
||||
|
||||
do
|
||||
@@ -308,7 +343,7 @@ module internal UnaryMetadataIlOp =
|
||||
let valueToStore, state = IlMachineState.popEvalStack thread state
|
||||
|
||||
let typeGenerics =
|
||||
match declaringType.Generics with
|
||||
match field.DeclaringType.Generics with
|
||||
| [] -> None
|
||||
| l -> Some (ImmutableArray.CreateRange l)
|
||||
|
||||
@@ -326,7 +361,7 @@ module internal UnaryMetadataIlOp =
|
||||
let currentObj, state = IlMachineState.popEvalStack thread state
|
||||
|
||||
if field.Attributes.HasFlag FieldAttributes.Static then
|
||||
let state = state.SetStatic declaringType field.Name valueToStore
|
||||
let state = state.SetStatic field.DeclaringType field.Name valueToStore
|
||||
|
||||
state, WhatWeDid.Executed
|
||||
else
|
||||
@@ -381,7 +416,13 @@ module internal UnaryMetadataIlOp =
|
||||
state, field
|
||||
| MetadataToken.MemberReference mr ->
|
||||
let state, _, method =
|
||||
IlMachineState.resolveMember loggerFactory (state.ActiveAssembly thread) mr state
|
||||
IlMachineState.resolveMember
|
||||
loggerFactory
|
||||
baseClassTypes
|
||||
thread
|
||||
(state.ActiveAssembly thread)
|
||||
mr
|
||||
state
|
||||
|
||||
match method with
|
||||
| Choice1Of2 methodInfo ->
|
||||
@@ -444,7 +485,7 @@ module internal UnaryMetadataIlOp =
|
||||
state, field
|
||||
| MetadataToken.MemberReference mr ->
|
||||
let state, assyName, field =
|
||||
IlMachineState.resolveMember loggerFactory activeAssembly mr state
|
||||
IlMachineState.resolveMember loggerFactory baseClassTypes thread activeAssembly mr state
|
||||
|
||||
match field with
|
||||
| Choice1Of2 _method -> failwith "member reference was unexpectedly a method"
|
||||
@@ -523,14 +564,24 @@ module internal UnaryMetadataIlOp =
|
||||
|
||||
let activeAssy = state.ActiveAssembly thread
|
||||
|
||||
let field =
|
||||
let state, field =
|
||||
match metadataToken with
|
||||
| MetadataToken.FieldDefinition fieldHandle ->
|
||||
match activeAssy.Fields.TryGetValue fieldHandle with
|
||||
| false, _ -> failwith "TODO: Ldsfld - throw MissingFieldException"
|
||||
| true, field ->
|
||||
field
|
||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "generics not allowed in FieldDefinition")
|
||||
let field =
|
||||
field
|
||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "generics not allowed in FieldDefinition")
|
||||
|
||||
state, field
|
||||
| MetadataToken.MemberReference mr ->
|
||||
let state, _, field =
|
||||
IlMachineState.resolveMember loggerFactory baseClassTypes thread activeAssy mr state
|
||||
|
||||
match field with
|
||||
| Choice1Of2 _method -> failwith "member reference was unexpectedly a method"
|
||||
| Choice2Of2 field -> state, field
|
||||
| t -> failwith $"Unexpectedly asked to load from a non-field: {t}"
|
||||
|
||||
do
|
||||
|
Reference in New Issue
Block a user