mirror of
https://github.com/Smaug123/WoofWare.PawPrint
synced 2025-10-13 09:38:40 +00:00
Merge commit '9afc7efea128e46f9cd1a00adcce8e7e50aa7418' into generic-edge-cases
This commit is contained in:
@@ -183,6 +183,40 @@ module ConcreteActivePatterns =
|
|||||||
| _ -> None
|
| _ -> None
|
||||||
| _ -> None
|
| _ -> None
|
||||||
|
|
||||||
|
let (|ConcreteObj|_|) (concreteTypes : AllConcreteTypes) (handle : ConcreteTypeHandle) : unit option =
|
||||||
|
match handle with
|
||||||
|
| ConcreteTypeHandle.Concrete id ->
|
||||||
|
match concreteTypes.Mapping |> Map.tryFind id with
|
||||||
|
| Some ct ->
|
||||||
|
if
|
||||||
|
ct.Assembly.Name = "System.Private.CoreLib"
|
||||||
|
&& ct.Namespace = "System"
|
||||||
|
&& ct.Name = "Object"
|
||||||
|
&& ct.Generics.IsEmpty
|
||||||
|
then
|
||||||
|
Some ()
|
||||||
|
else
|
||||||
|
None
|
||||||
|
| None -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
|
let (|ConcreteValueType|_|) (concreteTypes : AllConcreteTypes) (handle : ConcreteTypeHandle) : unit option =
|
||||||
|
match handle with
|
||||||
|
| ConcreteTypeHandle.Concrete id ->
|
||||||
|
match concreteTypes.Mapping |> Map.tryFind id with
|
||||||
|
| Some ct ->
|
||||||
|
if
|
||||||
|
ct.Assembly.Name = "System.Private.CoreLib"
|
||||||
|
&& ct.Namespace = "System"
|
||||||
|
&& ct.Name = "ValueType"
|
||||||
|
&& ct.Generics.IsEmpty
|
||||||
|
then
|
||||||
|
Some ()
|
||||||
|
else
|
||||||
|
None
|
||||||
|
| None -> None
|
||||||
|
| _ -> None
|
||||||
|
|
||||||
let (|ConcreteBool|_|) (concreteTypes : AllConcreteTypes) (handle : ConcreteTypeHandle) : unit option =
|
let (|ConcreteBool|_|) (concreteTypes : AllConcreteTypes) (handle : ConcreteTypeHandle) : unit option =
|
||||||
match handle with
|
match handle with
|
||||||
| ConcreteTypeHandle.Concrete id ->
|
| ConcreteTypeHandle.Concrete id ->
|
||||||
@@ -339,7 +373,7 @@ module TypeConcretization =
|
|||||||
(key : AssemblyName * string * string)
|
(key : AssemblyName * string * string)
|
||||||
: ConcreteTypeHandle option
|
: ConcreteTypeHandle option
|
||||||
=
|
=
|
||||||
let (asm, ns, name) = key
|
let asm, ns, name = key
|
||||||
findExistingType concreteTypes asm ns name ImmutableArray.Empty
|
findExistingType concreteTypes asm ns name ImmutableArray.Empty
|
||||||
|
|
||||||
// Helper function to create and add a ConcreteType to the context
|
// Helper function to create and add a ConcreteType to the context
|
||||||
@@ -394,7 +428,7 @@ module TypeConcretization =
|
|||||||
// Need to load the assembly
|
// Need to load the assembly
|
||||||
match typeRef.ResolutionScope with
|
match typeRef.ResolutionScope with
|
||||||
| TypeRefResolutionScope.Assembly assyRef ->
|
| TypeRefResolutionScope.Assembly assyRef ->
|
||||||
let newAssemblies, loadedAssy = loadAssembly currentAssembly assyRef
|
let newAssemblies, _ = loadAssembly currentAssembly assyRef
|
||||||
|
|
||||||
let newCtx =
|
let newCtx =
|
||||||
{ ctx with
|
{ ctx with
|
||||||
@@ -578,8 +612,8 @@ module TypeConcretization =
|
|||||||
(loadAssembly :
|
(loadAssembly :
|
||||||
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
||||||
(assembly : AssemblyName)
|
(assembly : AssemblyName)
|
||||||
(typeGenerics : ConcreteTypeHandle ImmutableArray)
|
(typeGenerics : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(methodGenerics : ConcreteTypeHandle ImmutableArray)
|
(methodGenerics : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(typeDefn : TypeDefn)
|
(typeDefn : TypeDefn)
|
||||||
: ConcreteTypeHandle * ConcretizationContext<'corelib>
|
: ConcreteTypeHandle * ConcretizationContext<'corelib>
|
||||||
=
|
=
|
||||||
@@ -675,8 +709,8 @@ module TypeConcretization =
|
|||||||
(loadAssembly :
|
(loadAssembly :
|
||||||
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
||||||
(assembly : AssemblyName)
|
(assembly : AssemblyName)
|
||||||
(typeGenerics : ConcreteTypeHandle ImmutableArray)
|
(typeGenerics : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(methodGenerics : ConcreteTypeHandle ImmutableArray)
|
(methodGenerics : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(genericDef : TypeDefn)
|
(genericDef : TypeDefn)
|
||||||
(args : ImmutableArray<TypeDefn>)
|
(args : ImmutableArray<TypeDefn>)
|
||||||
: ConcreteTypeHandle * ConcretizationContext<'corelib>
|
: ConcreteTypeHandle * ConcretizationContext<'corelib>
|
||||||
@@ -834,8 +868,8 @@ module Concretization =
|
|||||||
(loadAssembly :
|
(loadAssembly :
|
||||||
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
||||||
(assembly : AssemblyName)
|
(assembly : AssemblyName)
|
||||||
(typeArgs : ConcreteTypeHandle ImmutableArray)
|
(typeArgs : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(methodArgs : ConcreteTypeHandle ImmutableArray)
|
(methodArgs : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(types : ImmutableArray<TypeDefn>)
|
(types : ImmutableArray<TypeDefn>)
|
||||||
: ImmutableArray<ConcreteTypeHandle> * TypeConcretization.ConcretizationContext<'corelib>
|
: ImmutableArray<ConcreteTypeHandle> * TypeConcretization.ConcretizationContext<'corelib>
|
||||||
=
|
=
|
||||||
@@ -858,8 +892,8 @@ module Concretization =
|
|||||||
(loadAssembly :
|
(loadAssembly :
|
||||||
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
||||||
(assembly : AssemblyName)
|
(assembly : AssemblyName)
|
||||||
(typeArgs : ConcreteTypeHandle ImmutableArray)
|
(typeArgs : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(methodArgs : ConcreteTypeHandle ImmutableArray)
|
(methodArgs : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(signature : TypeMethodSignature<TypeDefn>)
|
(signature : TypeMethodSignature<TypeDefn>)
|
||||||
: TypeMethodSignature<ConcreteTypeHandle> * TypeConcretization.ConcretizationContext<'corelib>
|
: TypeMethodSignature<ConcreteTypeHandle> * TypeConcretization.ConcretizationContext<'corelib>
|
||||||
=
|
=
|
||||||
@@ -876,7 +910,7 @@ module Concretization =
|
|||||||
let handle, newCtx =
|
let handle, newCtx =
|
||||||
TypeConcretization.concretizeType ctx loadAssembly assembly typeArgs methodArgs paramType
|
TypeConcretization.concretizeType ctx loadAssembly assembly typeArgs methodArgs paramType
|
||||||
|
|
||||||
paramHandles.Add (handle)
|
paramHandles.Add handle
|
||||||
ctx <- newCtx
|
ctx <- newCtx
|
||||||
|
|
||||||
let newSignature =
|
let newSignature =
|
||||||
@@ -893,7 +927,7 @@ module Concretization =
|
|||||||
/// Helper to ensure base type assembly is loaded
|
/// Helper to ensure base type assembly is loaded
|
||||||
let rec private ensureBaseTypeAssembliesLoaded
|
let rec private ensureBaseTypeAssembliesLoaded
|
||||||
(loadAssembly :
|
(loadAssembly :
|
||||||
AssemblyName -> AssemblyReferenceHandle -> (ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly))
|
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
||||||
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
|
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
|
||||||
(assyName : AssemblyName)
|
(assyName : AssemblyName)
|
||||||
(baseTypeInfo : BaseTypeInfo option)
|
(baseTypeInfo : BaseTypeInfo option)
|
||||||
@@ -927,9 +961,9 @@ module Concretization =
|
|||||||
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
||||||
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
|
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
|
||||||
(baseTypes : BaseClassTypes<DumpedAssembly>)
|
(baseTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
(method : WoofWare.PawPrint.MethodInfo<TypeDefn, GenericParamFromMetadata, TypeDefn>)
|
(method : WoofWare.PawPrint.MethodInfo<'ty, GenericParamFromMetadata, TypeDefn>)
|
||||||
(typeArgs : ConcreteTypeHandle ImmutableArray)
|
(typeArgs : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(methodArgs : ConcreteTypeHandle ImmutableArray)
|
(methodArgs : ImmutableArray<ConcreteTypeHandle>)
|
||||||
: WoofWare.PawPrint.MethodInfo<ConcreteTypeHandle, ConcreteTypeHandle, ConcreteTypeHandle> *
|
: WoofWare.PawPrint.MethodInfo<ConcreteTypeHandle, ConcreteTypeHandle, ConcreteTypeHandle> *
|
||||||
AllConcreteTypes *
|
AllConcreteTypes *
|
||||||
ImmutableDictionary<string, DumpedAssembly>
|
ImmutableDictionary<string, DumpedAssembly>
|
||||||
@@ -1059,10 +1093,9 @@ module Concretization =
|
|||||||
// Map generics to handles
|
// Map generics to handles
|
||||||
let genericHandles =
|
let genericHandles =
|
||||||
method.Generics
|
method.Generics
|
||||||
|> Seq.mapi (fun i _ -> methodArgs.[i])
|
|> ImmutableArray.map (fun (gp, md) -> methodArgs.[gp.SequenceNumber])
|
||||||
|> ImmutableArray.CreateRange
|
|
||||||
|
|
||||||
let concretizedMethod : MethodInfo<_, _, ConcreteTypeHandle> =
|
let concretizedMethod : MethodInfo<_, _, _> =
|
||||||
{
|
{
|
||||||
DeclaringType = concretizedDeclaringType
|
DeclaringType = concretizedDeclaringType
|
||||||
Handle = method.Handle
|
Handle = method.Handle
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
namespace WoofWare.PawPrint
|
namespace WoofWare.PawPrint
|
||||||
|
|
||||||
|
open System
|
||||||
open System.Collections.Generic
|
open System.Collections.Generic
|
||||||
open System.Collections.Immutable
|
open System.Collections.Immutable
|
||||||
open System.Reflection
|
open System.Reflection
|
||||||
@@ -80,6 +81,8 @@ type TypeInfo<'generic, 'fieldGeneric> =
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
TypeDefHandle : TypeDefinitionHandle
|
TypeDefHandle : TypeDefinitionHandle
|
||||||
|
|
||||||
|
DeclaringType : TypeDefinitionHandle
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The assembly in which this type is defined.
|
/// The assembly in which this type is defined.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -92,6 +95,19 @@ type TypeInfo<'generic, 'fieldGeneric> =
|
|||||||
ImplementedInterfaces : InterfaceImplementation ImmutableArray
|
ImplementedInterfaces : InterfaceImplementation ImmutableArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
member this.IsInterface = this.TypeAttributes.HasFlag TypeAttributes.Interface
|
||||||
|
|
||||||
|
member this.IsNested =
|
||||||
|
[
|
||||||
|
TypeAttributes.NestedPublic
|
||||||
|
TypeAttributes.NestedPrivate
|
||||||
|
TypeAttributes.NestedFamily
|
||||||
|
TypeAttributes.NestedAssembly
|
||||||
|
TypeAttributes.NestedFamANDAssem
|
||||||
|
TypeAttributes.NestedFamORAssem
|
||||||
|
]
|
||||||
|
|> List.exists this.TypeAttributes.HasFlag
|
||||||
|
|
||||||
override this.ToString () =
|
override this.ToString () =
|
||||||
$"%s{this.Assembly.Name}.%s{this.Namespace}.%s{this.Name}"
|
$"%s{this.Assembly.Name}.%s{this.Namespace}.%s{this.Name}"
|
||||||
|
|
||||||
@@ -172,6 +188,15 @@ type BaseClassTypes<'corelib> =
|
|||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module TypeInfo =
|
module TypeInfo =
|
||||||
|
let rec fullName (get : TypeDefinitionHandle -> TypeInfo<_, _>) (ty : TypeInfo<'a, 'b>) =
|
||||||
|
if ty.IsNested then
|
||||||
|
let parent = get ty.DeclaringType |> fullName get
|
||||||
|
$"%s{parent}.{ty.Name}"
|
||||||
|
else if not (String.IsNullOrEmpty ty.Namespace) then
|
||||||
|
$"{ty.Namespace}.{ty.Name}"
|
||||||
|
else
|
||||||
|
ty.Name
|
||||||
|
|
||||||
let withGenerics<'a, 'b, 'field> (gen : 'b ImmutableArray) (t : TypeInfo<'a, 'field>) : TypeInfo<'b, 'field> =
|
let withGenerics<'a, 'b, 'field> (gen : 'b ImmutableArray) (t : TypeInfo<'a, 'field>) : TypeInfo<'b, 'field> =
|
||||||
{
|
{
|
||||||
Namespace = t.Namespace
|
Namespace = t.Namespace
|
||||||
@@ -183,6 +208,7 @@ module TypeInfo =
|
|||||||
TypeAttributes = t.TypeAttributes
|
TypeAttributes = t.TypeAttributes
|
||||||
Attributes = t.Attributes
|
Attributes = t.Attributes
|
||||||
TypeDefHandle = t.TypeDefHandle
|
TypeDefHandle = t.TypeDefHandle
|
||||||
|
DeclaringType = t.DeclaringType
|
||||||
Assembly = t.Assembly
|
Assembly = t.Assembly
|
||||||
Generics = gen
|
Generics = gen
|
||||||
Events = t.Events
|
Events = t.Events
|
||||||
@@ -201,6 +227,7 @@ module TypeInfo =
|
|||||||
: TypeInfo<GenericParamFromMetadata, TypeDefn>
|
: TypeInfo<GenericParamFromMetadata, TypeDefn>
|
||||||
=
|
=
|
||||||
let typeDef = metadataReader.GetTypeDefinition typeHandle
|
let typeDef = metadataReader.GetTypeDefinition typeHandle
|
||||||
|
let declaringType = typeDef.GetDeclaringType ()
|
||||||
let methods = typeDef.GetMethods ()
|
let methods = typeDef.GetMethods ()
|
||||||
|
|
||||||
let methodImpls =
|
let methodImpls =
|
||||||
@@ -295,6 +322,7 @@ module TypeInfo =
|
|||||||
Generics = genericParams
|
Generics = genericParams
|
||||||
Events = events
|
Events = events
|
||||||
ImplementedInterfaces = interfaces
|
ImplementedInterfaces = interfaces
|
||||||
|
DeclaringType = declaringType
|
||||||
}
|
}
|
||||||
|
|
||||||
let isBaseType<'corelib>
|
let isBaseType<'corelib>
|
||||||
|
@@ -61,11 +61,6 @@ module TestPureCases =
|
|||||||
ExpectedReturnCode = 0
|
ExpectedReturnCode = 0
|
||||||
NativeImpls = MockEnv.make ()
|
NativeImpls = MockEnv.make ()
|
||||||
}
|
}
|
||||||
{
|
|
||||||
FileName = "InterfaceDispatch.cs"
|
|
||||||
ExpectedReturnCode = 0
|
|
||||||
NativeImpls = MockEnv.make ()
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
let cases : EndToEndTestCase list =
|
let cases : EndToEndTestCase list =
|
||||||
@@ -170,6 +165,11 @@ module TestPureCases =
|
|||||||
ExpectedReturnCode = 0
|
ExpectedReturnCode = 0
|
||||||
NativeImpls = MockEnv.make ()
|
NativeImpls = MockEnv.make ()
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
FileName = "InterfaceDispatch.cs"
|
||||||
|
ExpectedReturnCode = 0
|
||||||
|
NativeImpls = MockEnv.make ()
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
let runTest (case : EndToEndTestCase) : unit =
|
let runTest (case : EndToEndTestCase) : unit =
|
||||||
|
@@ -14,8 +14,11 @@ public class InterfaceDispatchTests
|
|||||||
result |= TestGenericInterface() << 5;
|
result |= TestGenericInterface() << 5;
|
||||||
result |= TestCovariantInterface() << 6;
|
result |= TestCovariantInterface() << 6;
|
||||||
result |= TestReimplementation() << 7;
|
result |= TestReimplementation() << 7;
|
||||||
|
// TODO
|
||||||
|
/*
|
||||||
result |= TestStructInterface() << 8;
|
result |= TestStructInterface() << 8;
|
||||||
result |= TestNullDispatch() << 9;
|
result |= TestNullDispatch() << 9;
|
||||||
|
*/
|
||||||
result |= TestSharedMethodSignature() << 10;
|
result |= TestSharedMethodSignature() << 10;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@@ -110,6 +110,7 @@ module AbstractMachine =
|
|||||||
constructing
|
constructing
|
||||||
false
|
false
|
||||||
false
|
false
|
||||||
|
false
|
||||||
methodGenerics
|
methodGenerics
|
||||||
methodPtr
|
methodPtr
|
||||||
thread
|
thread
|
||||||
|
@@ -369,3 +369,5 @@ type EvalStack =
|
|||||||
let v = EvalStackValue.ofCliType v
|
let v = EvalStackValue.ofCliType v
|
||||||
|
|
||||||
EvalStack.Push' v stack
|
EvalStack.Push' v stack
|
||||||
|
|
||||||
|
static member PeekNthFromTop (n : int) (stack : EvalStack) : EvalStackValue option = stack.Values |> List.tryItem n
|
||||||
|
@@ -34,7 +34,7 @@ module ExceptionHandling =
|
|||||||
|
|
||||||
/// Check if an exception type matches a catch handler type
|
/// Check if an exception type matches a catch handler type
|
||||||
let private isExceptionAssignableTo
|
let private isExceptionAssignableTo
|
||||||
(exceptionTypeCrate : TypeInfoCrate)
|
(exceptionType : ConcreteTypeHandle)
|
||||||
(catchTypeToken : MetadataToken)
|
(catchTypeToken : MetadataToken)
|
||||||
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
|
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
|
||||||
: bool
|
: bool
|
||||||
@@ -46,7 +46,7 @@ module ExceptionHandling =
|
|||||||
/// Also returns `isFinally : bool`: whether this is a `finally` block (as opposed to e.g. a `catch`).
|
/// Also returns `isFinally : bool`: whether this is a `finally` block (as opposed to e.g. a `catch`).
|
||||||
let findExceptionHandler
|
let findExceptionHandler
|
||||||
(currentPC : int)
|
(currentPC : int)
|
||||||
(exceptionTypeCrate : TypeInfoCrate)
|
(exceptionType : ConcreteTypeHandle)
|
||||||
(method : WoofWare.PawPrint.MethodInfo<'typeGen, 'methodGeneric, 'methodVar>)
|
(method : WoofWare.PawPrint.MethodInfo<'typeGen, 'methodGeneric, 'methodVar>)
|
||||||
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
|
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
|
||||||
: (WoofWare.PawPrint.ExceptionRegion * bool) option // handler, isFinally
|
: (WoofWare.PawPrint.ExceptionRegion * bool) option // handler, isFinally
|
||||||
@@ -62,7 +62,7 @@ module ExceptionHandling =
|
|||||||
| ExceptionRegion.Catch (typeToken, offset) ->
|
| ExceptionRegion.Catch (typeToken, offset) ->
|
||||||
if currentPC >= offset.TryOffset && currentPC < offset.TryOffset + offset.TryLength then
|
if currentPC >= offset.TryOffset && currentPC < offset.TryOffset + offset.TryLength then
|
||||||
// Check if exception type matches
|
// Check if exception type matches
|
||||||
if isExceptionAssignableTo exceptionTypeCrate typeToken assemblies then
|
if isExceptionAssignableTo exceptionType typeToken assemblies then
|
||||||
Some (region, false)
|
Some (region, false)
|
||||||
else
|
else
|
||||||
None
|
None
|
||||||
|
@@ -772,12 +772,17 @@ module IlMachineState =
|
|||||||
// Otherwise, extract the now-complete object from the heap and push it to the stack directly.
|
// Otherwise, extract the now-complete object from the heap and push it to the stack directly.
|
||||||
let constructed = state.ManagedHeap.NonArrayObjects.[constructing]
|
let constructed = state.ManagedHeap.NonArrayObjects.[constructing]
|
||||||
|
|
||||||
|
let ty =
|
||||||
|
AllConcreteTypes.lookup constructed.ConcreteType state.ConcreteTypes
|
||||||
|
|> Option.get
|
||||||
|
|
||||||
|
let ty' =
|
||||||
|
state.LoadedAssembly (ty.Assembly)
|
||||||
|
|> Option.get
|
||||||
|
|> fun a -> a.TypeDefs.[ty.Definition.Get]
|
||||||
|
|
||||||
let resolvedBaseType =
|
let resolvedBaseType =
|
||||||
DumpedAssembly.resolveBaseType
|
DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies ty.Assembly ty'.BaseType
|
||||||
baseClassTypes
|
|
||||||
state._LoadedAssemblies
|
|
||||||
constructed.Type.Assembly
|
|
||||||
constructed.Type.BaseType
|
|
||||||
|
|
||||||
match resolvedBaseType with
|
match resolvedBaseType with
|
||||||
| ResolvedBaseType.Delegate
|
| ResolvedBaseType.Delegate
|
||||||
@@ -817,11 +822,62 @@ module IlMachineState =
|
|||||||
|
|
||||||
|> Some
|
|> Some
|
||||||
|
|
||||||
|
let concretizeMethodWithAllGenerics
|
||||||
|
(loggerFactory : ILoggerFactory)
|
||||||
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
|
(typeGenerics : ImmutableArray<ConcreteTypeHandle>)
|
||||||
|
(methodToCall : WoofWare.PawPrint.MethodInfo<'ty, GenericParamFromMetadata, TypeDefn>)
|
||||||
|
(methodGenerics : ImmutableArray<ConcreteTypeHandle>)
|
||||||
|
(state : IlMachineState)
|
||||||
|
: IlMachineState *
|
||||||
|
WoofWare.PawPrint.MethodInfo<ConcreteTypeHandle, ConcreteTypeHandle, ConcreteTypeHandle> *
|
||||||
|
ConcreteTypeHandle
|
||||||
|
=
|
||||||
|
// Now concretize the entire method
|
||||||
|
let concretizedMethod, newConcreteTypes, newAssemblies =
|
||||||
|
Concretization.concretizeMethod
|
||||||
|
state.ConcreteTypes
|
||||||
|
(fun assyName ref ->
|
||||||
|
match state.LoadedAssembly assyName with
|
||||||
|
| Some currentAssy ->
|
||||||
|
let targetAssyRef = currentAssy.AssemblyReferences.[ref]
|
||||||
|
|
||||||
|
match state.LoadedAssembly targetAssyRef.Name with
|
||||||
|
| Some _ ->
|
||||||
|
// Assembly already loaded, return existing state
|
||||||
|
state._LoadedAssemblies, state._LoadedAssemblies.[targetAssyRef.Name.FullName]
|
||||||
|
| None ->
|
||||||
|
// Need to load the assembly
|
||||||
|
let newState, loadedAssy, _ = loadAssembly loggerFactory currentAssy ref state
|
||||||
|
newState._LoadedAssemblies, loadedAssy
|
||||||
|
| None ->
|
||||||
|
failwithf "Current assembly %s not loaded when trying to resolve reference" assyName.FullName
|
||||||
|
)
|
||||||
|
state._LoadedAssemblies
|
||||||
|
baseClassTypes
|
||||||
|
methodToCall
|
||||||
|
typeGenerics
|
||||||
|
methodGenerics
|
||||||
|
|
||||||
|
let state =
|
||||||
|
{ state with
|
||||||
|
ConcreteTypes = newConcreteTypes
|
||||||
|
_LoadedAssemblies = newAssemblies
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the handle for the declaring type
|
||||||
|
let declaringTypeHandle =
|
||||||
|
match AllConcreteTypes.lookup' concretizedMethod.DeclaringType state.ConcreteTypes with
|
||||||
|
| Some handle -> handle
|
||||||
|
| None -> failwith "Concretized method's declaring type not found in ConcreteTypes"
|
||||||
|
|
||||||
|
state, concretizedMethod, declaringTypeHandle
|
||||||
|
|
||||||
let concretizeMethodWithTypeGenerics
|
let concretizeMethodWithTypeGenerics
|
||||||
(loggerFactory : ILoggerFactory)
|
(loggerFactory : ILoggerFactory)
|
||||||
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
(typeGenerics : ImmutableArray<ConcreteTypeHandle>)
|
(typeGenerics : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(methodToCall : WoofWare.PawPrint.MethodInfo<TypeDefn, GenericParamFromMetadata, TypeDefn>)
|
(methodToCall : WoofWare.PawPrint.MethodInfo<'ty, GenericParamFromMetadata, TypeDefn>)
|
||||||
(methodGenerics : TypeDefn ImmutableArray option)
|
(methodGenerics : TypeDefn ImmutableArray option)
|
||||||
(callingAssembly : AssemblyName)
|
(callingAssembly : AssemblyName)
|
||||||
(currentExecutingMethodGenerics : ImmutableArray<ConcreteTypeHandle>)
|
(currentExecutingMethodGenerics : ImmutableArray<ConcreteTypeHandle>)
|
||||||
@@ -855,50 +911,20 @@ module IlMachineState =
|
|||||||
state, handles.ToImmutable ()
|
state, handles.ToImmutable ()
|
||||||
|
|
||||||
// Now concretize the entire method
|
// Now concretize the entire method
|
||||||
let concretizedMethod, newConcreteTypes, newAssemblies =
|
concretizeMethodWithAllGenerics
|
||||||
Concretization.concretizeMethod
|
loggerFactory
|
||||||
state.ConcreteTypes
|
baseClassTypes
|
||||||
(fun assyName ref ->
|
typeGenerics
|
||||||
match state.LoadedAssembly assyName with
|
methodToCall
|
||||||
| Some currentAssy ->
|
concretizedMethodGenerics
|
||||||
let targetAssyRef = currentAssy.AssemblyReferences.[ref]
|
state
|
||||||
|
|
||||||
match state.LoadedAssembly targetAssyRef.Name with
|
|
||||||
| Some _ ->
|
|
||||||
// Assembly already loaded, return existing state
|
|
||||||
state._LoadedAssemblies, state._LoadedAssemblies.[targetAssyRef.Name.FullName]
|
|
||||||
| None ->
|
|
||||||
// Need to load the assembly
|
|
||||||
let newState, loadedAssy, _ = loadAssembly loggerFactory currentAssy ref state
|
|
||||||
newState._LoadedAssemblies, loadedAssy
|
|
||||||
| None ->
|
|
||||||
failwithf "Current assembly %s not loaded when trying to resolve reference" assyName.FullName
|
|
||||||
)
|
|
||||||
state._LoadedAssemblies
|
|
||||||
baseClassTypes
|
|
||||||
methodToCall
|
|
||||||
typeGenerics
|
|
||||||
concretizedMethodGenerics
|
|
||||||
|
|
||||||
let state =
|
|
||||||
{ state with
|
|
||||||
ConcreteTypes = newConcreteTypes
|
|
||||||
_LoadedAssemblies = newAssemblies
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the handle for the declaring type
|
|
||||||
let declaringTypeHandle =
|
|
||||||
match AllConcreteTypes.lookup' concretizedMethod.DeclaringType state.ConcreteTypes with
|
|
||||||
| Some handle -> handle
|
|
||||||
| None -> failwith "Concretized method's declaring type not found in ConcreteTypes"
|
|
||||||
|
|
||||||
state, concretizedMethod, declaringTypeHandle
|
|
||||||
|
|
||||||
|
/// Returns also the declaring type.
|
||||||
let concretizeMethodForExecution
|
let concretizeMethodForExecution
|
||||||
(loggerFactory : ILoggerFactory)
|
(loggerFactory : ILoggerFactory)
|
||||||
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
(thread : ThreadId)
|
(thread : ThreadId)
|
||||||
(methodToCall : WoofWare.PawPrint.MethodInfo<TypeDefn, GenericParamFromMetadata, TypeDefn>)
|
(methodToCall : WoofWare.PawPrint.MethodInfo<'ty, GenericParamFromMetadata, TypeDefn>)
|
||||||
(methodGenerics : TypeDefn ImmutableArray option)
|
(methodGenerics : TypeDefn ImmutableArray option)
|
||||||
(typeArgsFromMetadata : TypeDefn ImmutableArray option)
|
(typeArgsFromMetadata : TypeDefn ImmutableArray option)
|
||||||
(state : IlMachineState)
|
(state : IlMachineState)
|
||||||
@@ -1163,8 +1189,8 @@ module IlMachineState =
|
|||||||
ManagedHeap = heap
|
ManagedHeap = heap
|
||||||
}
|
}
|
||||||
|
|
||||||
let allocateManagedObject<'generic, 'field>
|
let allocateManagedObject
|
||||||
(typeInfo : WoofWare.PawPrint.TypeInfo<'generic, 'field>)
|
(ty : ConcreteTypeHandle)
|
||||||
(fields : CliField list)
|
(fields : CliField list)
|
||||||
(state : IlMachineState)
|
(state : IlMachineState)
|
||||||
: ManagedHeapAddress * IlMachineState
|
: ManagedHeapAddress * IlMachineState
|
||||||
@@ -1172,7 +1198,7 @@ module IlMachineState =
|
|||||||
let o =
|
let o =
|
||||||
{
|
{
|
||||||
Fields = fields
|
Fields = fields
|
||||||
Type = TypeInfoCrate.make typeInfo
|
ConcreteType = ty
|
||||||
SyncBlock = SyncBlock.Free
|
SyncBlock = SyncBlock.Free
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1358,7 +1384,9 @@ module IlMachineState =
|
|||||||
| [] ->
|
| [] ->
|
||||||
failwith
|
failwith
|
||||||
$"Could not find field member {memberName} with the right signature on {targetType.Namespace}.{targetType.Name}"
|
$"Could not find field member {memberName} with the right signature on {targetType.Namespace}.{targetType.Name}"
|
||||||
| [ x ] -> x |> FieldInfo.mapTypeGenerics (fun index _ -> targetType.Generics.[index])
|
| [ x ] ->
|
||||||
|
x
|
||||||
|
|> FieldInfo.mapTypeGenerics (fun _ (par, md) -> targetType.Generics.[par.SequenceNumber])
|
||||||
| _ ->
|
| _ ->
|
||||||
failwith
|
failwith
|
||||||
$"Multiple overloads matching signature for {targetType.Namespace}.{targetType.Name}'s field {memberName}!"
|
$"Multiple overloads matching signature for {targetType.Namespace}.{targetType.Name}'s field {memberName}!"
|
||||||
@@ -1515,16 +1543,24 @@ module IlMachineState =
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the type handle and an allocated System.RuntimeType.
|
/// Returns the type handle and an allocated System.RuntimeType.
|
||||||
let getOrAllocateType<'corelib>
|
let getOrAllocateType
|
||||||
(baseClassTypes : BaseClassTypes<'corelib>)
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
(defn : ConcreteTypeHandle)
|
(defn : ConcreteTypeHandle)
|
||||||
(state : IlMachineState)
|
(state : IlMachineState)
|
||||||
: ManagedHeapAddress * IlMachineState
|
: ManagedHeapAddress * IlMachineState
|
||||||
=
|
=
|
||||||
|
let state, runtimeType =
|
||||||
|
TypeDefn.FromDefinition (
|
||||||
|
ComparableTypeDefinitionHandle.Make baseClassTypes.RuntimeType.TypeDefHandle,
|
||||||
|
baseClassTypes.Corelib.Name.FullName,
|
||||||
|
SignatureTypeKind.Class
|
||||||
|
)
|
||||||
|
|> concretizeType baseClassTypes state baseClassTypes.Corelib.Name ImmutableArray.Empty ImmutableArray.Empty
|
||||||
|
|
||||||
let result, reg, state =
|
let result, reg, state =
|
||||||
TypeHandleRegistry.getOrAllocate
|
TypeHandleRegistry.getOrAllocate
|
||||||
state
|
state
|
||||||
(fun fields state -> allocateManagedObject baseClassTypes.RuntimeType fields state)
|
(fun fields state -> allocateManagedObject runtimeType fields state)
|
||||||
defn
|
defn
|
||||||
state.TypeHandles
|
state.TypeHandles
|
||||||
|
|
||||||
@@ -1536,9 +1572,9 @@ module IlMachineState =
|
|||||||
result, state
|
result, state
|
||||||
|
|
||||||
/// Returns a System.RuntimeFieldHandle.
|
/// Returns a System.RuntimeFieldHandle.
|
||||||
let getOrAllocateField<'corelib>
|
let getOrAllocateField
|
||||||
(loggerFactory : ILoggerFactory)
|
(loggerFactory : ILoggerFactory)
|
||||||
(baseClassTypes : BaseClassTypes<'corelib>)
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
(declaringAssy : AssemblyName)
|
(declaringAssy : AssemblyName)
|
||||||
(fieldHandle : FieldDefinitionHandle)
|
(fieldHandle : FieldDefinitionHandle)
|
||||||
(state : IlMachineState)
|
(state : IlMachineState)
|
||||||
@@ -1557,11 +1593,19 @@ module IlMachineState =
|
|||||||
let declaringType, state =
|
let declaringType, state =
|
||||||
concretizeFieldDeclaringType loggerFactory baseClassTypes declaringTypeWithGenerics state
|
concretizeFieldDeclaringType loggerFactory baseClassTypes declaringTypeWithGenerics state
|
||||||
|
|
||||||
|
let state, runtimeType =
|
||||||
|
TypeDefn.FromDefinition (
|
||||||
|
ComparableTypeDefinitionHandle.Make baseClassTypes.RuntimeType.TypeDefHandle,
|
||||||
|
baseClassTypes.Corelib.Name.FullName,
|
||||||
|
SignatureTypeKind.Class
|
||||||
|
)
|
||||||
|
|> concretizeType baseClassTypes state baseClassTypes.Corelib.Name ImmutableArray.Empty ImmutableArray.Empty
|
||||||
|
|
||||||
let result, reg, state =
|
let result, reg, state =
|
||||||
FieldHandleRegistry.getOrAllocate
|
FieldHandleRegistry.getOrAllocate
|
||||||
baseClassTypes
|
baseClassTypes
|
||||||
state
|
state
|
||||||
(fun fields state -> allocateManagedObject baseClassTypes.RuntimeType fields state)
|
(fun fields state -> allocateManagedObject runtimeType fields state)
|
||||||
declaringAssy
|
declaringAssy
|
||||||
declaringType
|
declaringType
|
||||||
fieldHandle
|
fieldHandle
|
||||||
@@ -1613,3 +1657,97 @@ module IlMachineState =
|
|||||||
match obj with
|
match obj with
|
||||||
| CliType.ValueType vt -> vt |> CliValueType.DereferenceField name
|
| CliType.ValueType vt -> vt |> CliValueType.DereferenceField name
|
||||||
| v -> failwith $"could not find field {name} on object {v}"
|
| v -> failwith $"could not find field {name} on object {v}"
|
||||||
|
|
||||||
|
let lookupTypeDefn
|
||||||
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
|
(state : IlMachineState)
|
||||||
|
(activeAssy : DumpedAssembly)
|
||||||
|
(typeDef : TypeDefinitionHandle)
|
||||||
|
: IlMachineState * TypeDefn
|
||||||
|
=
|
||||||
|
let defn = activeAssy.TypeDefs.[typeDef]
|
||||||
|
|
||||||
|
let baseType =
|
||||||
|
defn.BaseType
|
||||||
|
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies defn.Assembly
|
||||||
|
|
||||||
|
let signatureTypeKind =
|
||||||
|
match baseType with
|
||||||
|
| ResolvedBaseType.Enum
|
||||||
|
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
||||||
|
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
||||||
|
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
||||||
|
|
||||||
|
let result =
|
||||||
|
if defn.Generics.IsEmpty then
|
||||||
|
TypeDefn.FromDefinition (
|
||||||
|
ComparableTypeDefinitionHandle.Make defn.TypeDefHandle,
|
||||||
|
defn.Assembly.FullName,
|
||||||
|
signatureTypeKind
|
||||||
|
)
|
||||||
|
else
|
||||||
|
// Preserve the generic instantiation by converting GenericParameters to TypeDefn.GenericTypeParameter
|
||||||
|
let genericDef =
|
||||||
|
TypeDefn.FromDefinition (
|
||||||
|
ComparableTypeDefinitionHandle.Make defn.TypeDefHandle,
|
||||||
|
defn.Assembly.FullName,
|
||||||
|
signatureTypeKind
|
||||||
|
)
|
||||||
|
|
||||||
|
let genericArgs =
|
||||||
|
defn.Generics
|
||||||
|
|> Seq.mapi (fun i _ -> TypeDefn.GenericTypeParameter i)
|
||||||
|
|> ImmutableArray.CreateRange
|
||||||
|
|
||||||
|
TypeDefn.GenericInstantiation (genericDef, genericArgs)
|
||||||
|
|
||||||
|
state, result
|
||||||
|
|
||||||
|
let lookupTypeRef
|
||||||
|
(loggerFactory : ILoggerFactory)
|
||||||
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
|
(state : IlMachineState)
|
||||||
|
(activeAssy : DumpedAssembly)
|
||||||
|
typeGenerics
|
||||||
|
(ref : TypeReferenceHandle)
|
||||||
|
: IlMachineState * TypeDefn * DumpedAssembly
|
||||||
|
=
|
||||||
|
let ref = activeAssy.TypeRefs.[ref]
|
||||||
|
|
||||||
|
// Convert ConcreteTypeHandles back to TypeDefn for metadata operations
|
||||||
|
let typeGenerics =
|
||||||
|
typeGenerics
|
||||||
|
|> Seq.map (fun handle ->
|
||||||
|
Concretization.concreteHandleToTypeDefn
|
||||||
|
baseClassTypes
|
||||||
|
handle
|
||||||
|
state.ConcreteTypes
|
||||||
|
state._LoadedAssemblies
|
||||||
|
)
|
||||||
|
|> ImmutableArray.CreateRange
|
||||||
|
|
||||||
|
let state, assy, resolved =
|
||||||
|
resolveTypeFromRef loggerFactory activeAssy ref typeGenerics state
|
||||||
|
|
||||||
|
let baseType =
|
||||||
|
resolved.BaseType
|
||||||
|
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies assy.Name
|
||||||
|
|
||||||
|
let signatureTypeKind =
|
||||||
|
match baseType with
|
||||||
|
| ResolvedBaseType.Enum
|
||||||
|
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
||||||
|
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
||||||
|
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
||||||
|
|
||||||
|
let result =
|
||||||
|
TypeDefn.FromDefinition (
|
||||||
|
ComparableTypeDefinitionHandle.Make resolved.TypeDefHandle,
|
||||||
|
assy.Name.FullName,
|
||||||
|
signatureTypeKind
|
||||||
|
)
|
||||||
|
|
||||||
|
if resolved.Generics.IsEmpty then
|
||||||
|
state, result, assy
|
||||||
|
else
|
||||||
|
failwith "TODO: add generics"
|
||||||
|
@@ -1,15 +1,105 @@
|
|||||||
namespace WoofWare.PawPrint
|
namespace WoofWare.PawPrint
|
||||||
|
|
||||||
|
open System
|
||||||
open System.Collections.Immutable
|
open System.Collections.Immutable
|
||||||
|
open System.Reflection
|
||||||
open System.Reflection.Metadata
|
open System.Reflection.Metadata
|
||||||
|
open System.Runtime.CompilerServices
|
||||||
open Microsoft.Extensions.Logging
|
open Microsoft.Extensions.Logging
|
||||||
|
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
module IlMachineStateExecution =
|
module IlMachineStateExecution =
|
||||||
|
let getTypeOfObj
|
||||||
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
|
(state : IlMachineState)
|
||||||
|
(esv : EvalStackValue)
|
||||||
|
: IlMachineState * ConcreteTypeHandle
|
||||||
|
=
|
||||||
|
match esv with
|
||||||
|
| EvalStackValue.Int32 _ ->
|
||||||
|
TypeDefn.FromDefinition (
|
||||||
|
ComparableTypeDefinitionHandle.Make baseClassTypes.Int32.TypeDefHandle,
|
||||||
|
baseClassTypes.Corelib.Name.FullName,
|
||||||
|
SignatureTypeKind.ValueType
|
||||||
|
)
|
||||||
|
|> IlMachineState.concretizeType
|
||||||
|
baseClassTypes
|
||||||
|
state
|
||||||
|
baseClassTypes.Corelib.Name
|
||||||
|
ImmutableArray.Empty
|
||||||
|
ImmutableArray.Empty
|
||||||
|
| EvalStackValue.Int64 _ ->
|
||||||
|
TypeDefn.FromDefinition (
|
||||||
|
ComparableTypeDefinitionHandle.Make baseClassTypes.Int64.TypeDefHandle,
|
||||||
|
baseClassTypes.Corelib.Name.FullName,
|
||||||
|
SignatureTypeKind.ValueType
|
||||||
|
)
|
||||||
|
|> IlMachineState.concretizeType
|
||||||
|
baseClassTypes
|
||||||
|
state
|
||||||
|
baseClassTypes.Corelib.Name
|
||||||
|
ImmutableArray.Empty
|
||||||
|
ImmutableArray.Empty
|
||||||
|
| EvalStackValue.NativeInt nativeIntSource -> failwith "todo"
|
||||||
|
| EvalStackValue.Float _ ->
|
||||||
|
TypeDefn.FromDefinition (
|
||||||
|
ComparableTypeDefinitionHandle.Make baseClassTypes.Double.TypeDefHandle,
|
||||||
|
baseClassTypes.Corelib.Name.FullName,
|
||||||
|
SignatureTypeKind.ValueType
|
||||||
|
)
|
||||||
|
|> IlMachineState.concretizeType
|
||||||
|
baseClassTypes
|
||||||
|
state
|
||||||
|
baseClassTypes.Corelib.Name
|
||||||
|
ImmutableArray.Empty
|
||||||
|
ImmutableArray.Empty
|
||||||
|
| EvalStackValue.ManagedPointer src ->
|
||||||
|
match src with
|
||||||
|
| ManagedPointerSource.LocalVariable (sourceThread, methodFrame, whichVar) -> failwith "todo"
|
||||||
|
| ManagedPointerSource.Argument (sourceThread, methodFrame, whichVar) -> failwith "todo"
|
||||||
|
| ManagedPointerSource.Heap addr ->
|
||||||
|
let o = ManagedHeap.get addr state.ManagedHeap
|
||||||
|
state, o.ConcreteType
|
||||||
|
| ManagedPointerSource.ArrayIndex (arr, index) -> failwith "todo"
|
||||||
|
| ManagedPointerSource.Null -> failwith "todo"
|
||||||
|
| ManagedPointerSource.Field (managedPointerSource, fieldName) -> failwith "todo"
|
||||||
|
| EvalStackValue.ObjectRef addr ->
|
||||||
|
let o = ManagedHeap.get addr state.ManagedHeap
|
||||||
|
state, o.ConcreteType
|
||||||
|
| EvalStackValue.UserDefinedValueType tuples -> failwith "todo"
|
||||||
|
|
||||||
|
let isAssignableFrom
|
||||||
|
(objToCast : ConcreteTypeHandle)
|
||||||
|
(possibleTargetType : ConcreteTypeHandle)
|
||||||
|
(state : IlMachineState)
|
||||||
|
: bool
|
||||||
|
=
|
||||||
|
if objToCast = possibleTargetType then
|
||||||
|
true
|
||||||
|
else
|
||||||
|
|
||||||
|
let objToCast' = AllConcreteTypes.lookup objToCast state.ConcreteTypes |> Option.get
|
||||||
|
|
||||||
|
let possibleTargetType' =
|
||||||
|
AllConcreteTypes.lookup possibleTargetType state.ConcreteTypes |> Option.get
|
||||||
|
|
||||||
|
// TODO: null can be assigned to any reference type; might not be relevant here?
|
||||||
|
|
||||||
|
match possibleTargetType with
|
||||||
|
| ConcreteObj state.ConcreteTypes -> true
|
||||||
|
| ConcreteValueType state.ConcreteTypes when failwith "check if objToCast inherits ValueType" -> true
|
||||||
|
| _ ->
|
||||||
|
// Claude describes the algorithm here:
|
||||||
|
// https://claude.ai/chat/f15e23f6-a27b-4655-9e69-e4d445dd1249
|
||||||
|
failwith
|
||||||
|
$"TODO: check inheritance chain and interfaces: is {objToCast'} assignable from {possibleTargetType'}?"
|
||||||
|
|
||||||
let callMethod
|
let callMethod
|
||||||
(loggerFactory : ILoggerFactory)
|
(loggerFactory : ILoggerFactory)
|
||||||
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
(wasInitialising : ConcreteTypeHandle option)
|
(wasInitialising : ConcreteTypeHandle option)
|
||||||
(wasConstructing : ManagedHeapAddress option)
|
(wasConstructing : ManagedHeapAddress option)
|
||||||
|
(performInterfaceResolution : bool)
|
||||||
(wasClassConstructor : bool)
|
(wasClassConstructor : bool)
|
||||||
(advanceProgramCounterOfCaller : bool)
|
(advanceProgramCounterOfCaller : bool)
|
||||||
(methodGenerics : ImmutableArray<ConcreteTypeHandle>)
|
(methodGenerics : ImmutableArray<ConcreteTypeHandle>)
|
||||||
@@ -19,6 +109,7 @@ module IlMachineStateExecution =
|
|||||||
(state : IlMachineState)
|
(state : IlMachineState)
|
||||||
: IlMachineState
|
: IlMachineState
|
||||||
=
|
=
|
||||||
|
let logger = loggerFactory.CreateLogger "CallMethod"
|
||||||
let activeAssy = state.ActiveAssembly thread
|
let activeAssy = state.ActiveAssembly thread
|
||||||
|
|
||||||
// Check for intrinsics first
|
// Check for intrinsics first
|
||||||
@@ -41,6 +132,9 @@ module IlMachineStateExecution =
|
|||||||
| Some result -> result
|
| Some result -> result
|
||||||
| None ->
|
| None ->
|
||||||
|
|
||||||
|
if methodToCall.Name = "GetValue" then
|
||||||
|
printfn ""
|
||||||
|
|
||||||
// Get zero values for all parameters
|
// Get zero values for all parameters
|
||||||
let state, argZeroObjects =
|
let state, argZeroObjects =
|
||||||
((state, []), methodToCall.Signature.ParameterTypes)
|
((state, []), methodToCall.Signature.ParameterTypes)
|
||||||
@@ -53,6 +147,247 @@ module IlMachineStateExecution =
|
|||||||
|
|
||||||
let activeMethodState = threadState.MethodStates.[threadState.ActiveMethodState]
|
let activeMethodState = threadState.MethodStates.[threadState.ActiveMethodState]
|
||||||
|
|
||||||
|
let state, methodToCall =
|
||||||
|
match methodToCall.Instructions, performInterfaceResolution, methodToCall.IsStatic with
|
||||||
|
| None, true, false ->
|
||||||
|
logger.LogDebug (
|
||||||
|
"Identifying target of virtual call for {TypeName}.{MethodName}",
|
||||||
|
methodToCall.DeclaringType.Name,
|
||||||
|
methodToCall.Name
|
||||||
|
)
|
||||||
|
// This might be an interface implementation, or implemented by native code.
|
||||||
|
// If native code, we'll deal with that when we actually start implementing.
|
||||||
|
|
||||||
|
// Since we're not static, there's a `this` on the eval stack.
|
||||||
|
// It comes *below* all the arguments.
|
||||||
|
let callingObj =
|
||||||
|
match
|
||||||
|
activeMethodState.EvaluationStack
|
||||||
|
|> EvalStack.PeekNthFromTop methodToCall.Parameters.Length
|
||||||
|
with
|
||||||
|
| None -> failwith "unexpectedly no `this` on the eval stack of instance method"
|
||||||
|
| Some this -> this
|
||||||
|
|
||||||
|
let state, callingObjTyHandle = getTypeOfObj baseClassTypes state callingObj
|
||||||
|
|
||||||
|
let callingObjTy =
|
||||||
|
let ty =
|
||||||
|
AllConcreteTypes.lookup callingObjTyHandle state.ConcreteTypes |> Option.get
|
||||||
|
|
||||||
|
state.LoadedAssembly(ty.Assembly).Value.TypeDefs.[ty.Definition.Get]
|
||||||
|
|
||||||
|
let declaringAssy = state.LoadedAssembly(methodToCall.DeclaringType.Assembly).Value
|
||||||
|
|
||||||
|
let methodDeclaringType =
|
||||||
|
declaringAssy.TypeDefs.[methodToCall.DeclaringType.Definition.Get]
|
||||||
|
|
||||||
|
let interfaceExplicitNamedMethod =
|
||||||
|
if methodDeclaringType.IsInterface then
|
||||||
|
Some
|
||||||
|
$"{TypeInfo.fullName (fun h -> declaringAssy.TypeDefs.[h]) methodDeclaringType}.{methodToCall.Name}"
|
||||||
|
else
|
||||||
|
None
|
||||||
|
|
||||||
|
// Does type `callingObjTy` implement this method? If so, this is probably a JIT intrinsic or
|
||||||
|
// is supplied by the runtime.
|
||||||
|
let selfImplementation, state =
|
||||||
|
(state, callingObjTy.Methods)
|
||||||
|
||> List.mapFold (fun state meth ->
|
||||||
|
if
|
||||||
|
meth.Signature.GenericParameterCount
|
||||||
|
<> methodToCall.Signature.GenericParameterCount
|
||||||
|
|| meth.Signature.RequiredParameterCount
|
||||||
|
<> methodToCall.Signature.RequiredParameterCount
|
||||||
|
then
|
||||||
|
None, state
|
||||||
|
else if
|
||||||
|
|
||||||
|
meth.Name <> methodToCall.Name && Some meth.Name <> interfaceExplicitNamedMethod
|
||||||
|
then
|
||||||
|
None, state
|
||||||
|
else
|
||||||
|
|
||||||
|
// TODO: check if methodToCall's declaringtype is an interface; if so, check the possible prefixed name first
|
||||||
|
|
||||||
|
let state, retType =
|
||||||
|
meth.Signature.ReturnType
|
||||||
|
|> IlMachineState.concretizeType
|
||||||
|
baseClassTypes
|
||||||
|
state
|
||||||
|
meth.DeclaringType.Assembly
|
||||||
|
methodToCall.DeclaringType.Generics
|
||||||
|
methodToCall.Generics
|
||||||
|
|
||||||
|
let paramTypes, state =
|
||||||
|
(state, meth.Signature.ParameterTypes)
|
||||||
|
||> Seq.mapFold (fun state ty ->
|
||||||
|
ty
|
||||||
|
|> IlMachineState.concretizeType
|
||||||
|
baseClassTypes
|
||||||
|
state
|
||||||
|
meth.DeclaringType.Assembly
|
||||||
|
methodToCall.DeclaringType.Generics
|
||||||
|
methodToCall.Generics
|
||||||
|
|> fun (a, b) -> b, a
|
||||||
|
)
|
||||||
|
|
||||||
|
let paramTypes = List.ofSeq paramTypes
|
||||||
|
|
||||||
|
if
|
||||||
|
isAssignableFrom retType methodToCall.Signature.ReturnType state
|
||||||
|
&& paramTypes = methodToCall.Signature.ParameterTypes
|
||||||
|
then
|
||||||
|
Some (meth, Some meth.Name = interfaceExplicitNamedMethod), state
|
||||||
|
else
|
||||||
|
None, state
|
||||||
|
)
|
||||||
|
|
||||||
|
let selfImplementation =
|
||||||
|
selfImplementation
|
||||||
|
|> List.choose id
|
||||||
|
|> List.sortBy (fun (_, isInterface) -> if isInterface then -1 else 0)
|
||||||
|
|
||||||
|
match selfImplementation with
|
||||||
|
| (impl, true) :: l when (l |> List.forall (fun (_, b) -> not b)) ->
|
||||||
|
logger.LogDebug "Found concrete implementation from an interface"
|
||||||
|
|
||||||
|
let typeGenerics =
|
||||||
|
AllConcreteTypes.lookup callingObjTyHandle state.ConcreteTypes
|
||||||
|
|> Option.get
|
||||||
|
|> _.Generics
|
||||||
|
|
||||||
|
let state, meth, _ =
|
||||||
|
IlMachineState.concretizeMethodWithAllGenerics
|
||||||
|
loggerFactory
|
||||||
|
baseClassTypes
|
||||||
|
typeGenerics
|
||||||
|
impl
|
||||||
|
methodGenerics
|
||||||
|
state
|
||||||
|
|
||||||
|
state, meth
|
||||||
|
| [ impl, false ] ->
|
||||||
|
logger.LogDebug "Found concrete implementation"
|
||||||
|
// Yes, callingObjTy implements the method directly. No need to look up interfaces.
|
||||||
|
let typeGenerics =
|
||||||
|
AllConcreteTypes.lookup callingObjTyHandle state.ConcreteTypes
|
||||||
|
|> Option.get
|
||||||
|
|> _.Generics
|
||||||
|
|
||||||
|
let state, meth, _ =
|
||||||
|
IlMachineState.concretizeMethodWithAllGenerics
|
||||||
|
loggerFactory
|
||||||
|
baseClassTypes
|
||||||
|
typeGenerics
|
||||||
|
impl
|
||||||
|
methodGenerics
|
||||||
|
state
|
||||||
|
|
||||||
|
state, meth
|
||||||
|
| _ :: _ ->
|
||||||
|
selfImplementation
|
||||||
|
|> List.map (fun (m, _) -> m.Name)
|
||||||
|
|> String.concat ", "
|
||||||
|
|> failwithf "multiple options: %s"
|
||||||
|
| [] ->
|
||||||
|
|
||||||
|
logger.LogDebug "No concrete implementation found; scanning interfaces"
|
||||||
|
|
||||||
|
// If not, what interfaces does it implement, and do any of those implement the method?
|
||||||
|
let possibleInterfaceMethods, state =
|
||||||
|
(state, callingObjTy.ImplementedInterfaces)
|
||||||
|
||> Seq.mapFold (fun state impl ->
|
||||||
|
let assy = state.LoadedAssembly impl.RelativeToAssembly |> Option.get
|
||||||
|
|
||||||
|
let state, defn =
|
||||||
|
match impl.InterfaceHandle with
|
||||||
|
| MetadataToken.TypeDefinition defn ->
|
||||||
|
let state, defn = IlMachineState.lookupTypeDefn baseClassTypes state assy defn
|
||||||
|
|
||||||
|
let state, _, defn =
|
||||||
|
// TODO: generics
|
||||||
|
IlMachineState.resolveTypeFromDefn
|
||||||
|
loggerFactory
|
||||||
|
baseClassTypes
|
||||||
|
defn
|
||||||
|
ImmutableArray.Empty
|
||||||
|
ImmutableArray.Empty
|
||||||
|
assy
|
||||||
|
state
|
||||||
|
|
||||||
|
state, defn
|
||||||
|
| MetadataToken.TypeReference ty ->
|
||||||
|
let state, defn, assy =
|
||||||
|
IlMachineState.lookupTypeRef loggerFactory baseClassTypes state assy Seq.empty ty
|
||||||
|
|
||||||
|
state, failwith "TODO"
|
||||||
|
| MetadataToken.TypeSpecification spec ->
|
||||||
|
// TODO: generics
|
||||||
|
let state, assy, defn =
|
||||||
|
IlMachineState.resolveTypeFromSpec
|
||||||
|
loggerFactory
|
||||||
|
baseClassTypes
|
||||||
|
spec
|
||||||
|
assy
|
||||||
|
ImmutableArray.Empty
|
||||||
|
ImmutableArray.Empty
|
||||||
|
state
|
||||||
|
|
||||||
|
state, defn
|
||||||
|
| handle -> failwith $"unexpected: {handle}"
|
||||||
|
|
||||||
|
logger.LogDebug (
|
||||||
|
"Interface {InterfaceName} (generics: {InterfaceGenerics})",
|
||||||
|
defn.Name,
|
||||||
|
defn.Generics
|
||||||
|
)
|
||||||
|
|
||||||
|
let s, state =
|
||||||
|
defn.Methods
|
||||||
|
|> Seq.filter (fun mi -> mi.Name = methodToCall.Name
|
||||||
|
// TODO: also the rest of the signature
|
||||||
|
)
|
||||||
|
|> Seq.mapFold
|
||||||
|
(fun state meth ->
|
||||||
|
// TODO: generics
|
||||||
|
let state, mi, _ =
|
||||||
|
IlMachineState.concretizeMethodForExecution
|
||||||
|
loggerFactory
|
||||||
|
baseClassTypes
|
||||||
|
thread
|
||||||
|
meth
|
||||||
|
None
|
||||||
|
(if defn.Generics.IsEmpty then None else Some defn.Generics)
|
||||||
|
state
|
||||||
|
|
||||||
|
mi, state
|
||||||
|
)
|
||||||
|
state
|
||||||
|
|
||||||
|
s, state
|
||||||
|
)
|
||||||
|
|
||||||
|
let possibleInterfaceMethods = possibleInterfaceMethods |> Seq.concat |> Seq.toList
|
||||||
|
|
||||||
|
match possibleInterfaceMethods with
|
||||||
|
| [] ->
|
||||||
|
logger.LogDebug "No interface implementation found either"
|
||||||
|
state, methodToCall
|
||||||
|
| [ meth ] ->
|
||||||
|
logger.LogDebug (
|
||||||
|
"Exactly one interface implementation found {DeclaringTypeNamespace}.{DeclaringTypeName}.{MethodName} ({MethodGenerics})",
|
||||||
|
meth.DeclaringType.Namespace,
|
||||||
|
meth.DeclaringType.Name,
|
||||||
|
meth.Name,
|
||||||
|
meth.Generics
|
||||||
|
)
|
||||||
|
|
||||||
|
state, meth
|
||||||
|
| _ -> failwith "TODO: handle overloads"
|
||||||
|
| _, _, true
|
||||||
|
| _, false, _
|
||||||
|
| Some _, _, _ -> state, methodToCall
|
||||||
|
|
||||||
// Helper to pop and coerce a single argument
|
// Helper to pop and coerce a single argument
|
||||||
let popAndCoerceArg zeroType methodState =
|
let popAndCoerceArg zeroType methodState =
|
||||||
let value, newState = MethodState.popFromStack methodState
|
let value, newState = MethodState.popFromStack methodState
|
||||||
@@ -425,6 +760,7 @@ module IlMachineStateExecution =
|
|||||||
None
|
None
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
|
false
|
||||||
// constructor is surely not generic
|
// constructor is surely not generic
|
||||||
ImmutableArray.Empty
|
ImmutableArray.Empty
|
||||||
fullyConvertedMethod
|
fullyConvertedMethod
|
||||||
@@ -471,6 +807,7 @@ module IlMachineStateExecution =
|
|||||||
(loggerFactory : ILoggerFactory)
|
(loggerFactory : ILoggerFactory)
|
||||||
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
(thread : ThreadId)
|
(thread : ThreadId)
|
||||||
|
(performInterfaceResolution : bool)
|
||||||
(advanceProgramCounterOfCaller : bool)
|
(advanceProgramCounterOfCaller : bool)
|
||||||
(methodGenerics : TypeDefn ImmutableArray option)
|
(methodGenerics : TypeDefn ImmutableArray option)
|
||||||
(methodToCall : WoofWare.PawPrint.MethodInfo<TypeDefn, GenericParamFromMetadata, TypeDefn>)
|
(methodToCall : WoofWare.PawPrint.MethodInfo<TypeDefn, GenericParamFromMetadata, TypeDefn>)
|
||||||
@@ -501,6 +838,7 @@ module IlMachineStateExecution =
|
|||||||
baseClassTypes
|
baseClassTypes
|
||||||
None
|
None
|
||||||
weAreConstructingObj
|
weAreConstructingObj
|
||||||
|
performInterfaceResolution
|
||||||
false
|
false
|
||||||
advanceProgramCounterOfCaller
|
advanceProgramCounterOfCaller
|
||||||
concretizedMethod.Generics
|
concretizedMethod.Generics
|
||||||
|
@@ -224,6 +224,16 @@ module Intrinsics =
|
|||||||
|> IlMachineState.advanceProgramCounter currentThread
|
|> IlMachineState.advanceProgramCounter currentThread
|
||||||
|> Some
|
|> Some
|
||||||
else
|
else
|
||||||
|
|
||||||
|
let arg1 = ManagedHeap.get arg1 state.ManagedHeap
|
||||||
|
let arg2 = ManagedHeap.get arg2 state.ManagedHeap
|
||||||
|
|
||||||
|
if AllocatedNonArrayObject.DereferenceField "_firstChar" arg1 <> AllocatedNonArrayObject.DereferenceField "_firstChar" arg2 then
|
||||||
|
state
|
||||||
|
|> IlMachineState.pushToEvalStack (CliType.ofBool false) currentThread
|
||||||
|
|> IlMachineState.advanceProgramCounter currentThread
|
||||||
|
|> Some
|
||||||
|
else
|
||||||
failwith "TODO"
|
failwith "TODO"
|
||||||
| _ -> None
|
| _ -> None
|
||||||
| "System.Private.CoreLib", "Unsafe", "ReadUnaligned" ->
|
| "System.Private.CoreLib", "Unsafe", "ReadUnaligned" ->
|
||||||
@@ -332,6 +342,14 @@ module Intrinsics =
|
|||||||
Some state
|
Some state
|
||||||
| "System.Private.CoreLib", "RuntimeHelpers", "InitializeArray" ->
|
| "System.Private.CoreLib", "RuntimeHelpers", "InitializeArray" ->
|
||||||
// https://github.com/dotnet/runtime/blob/9e5e6aa7bc36aeb2a154709a9d1192030c30a2ef/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs#L18
|
// https://github.com/dotnet/runtime/blob/9e5e6aa7bc36aeb2a154709a9d1192030c30a2ef/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs#L18
|
||||||
|
match methodToCall.Signature.ParameterTypes, methodToCall.Signature.ReturnType with
|
||||||
|
| [ ConcreteNonGenericArray state.ConcreteTypes ; ConcreteRuntimeFieldHandle state.ConcreteTypes ],
|
||||||
|
ConcreteVoid state.ConcreteTypes -> ()
|
||||||
|
| _ -> failwith "bad signature for System.Private.CoreLib.RuntimeHelpers.InitializeArray"
|
||||||
|
|
||||||
|
failwith "TODO: if arg0 is null, throw NRE"
|
||||||
|
failwith "TODO: if arg1 contains null handle, throw ArgumentException"
|
||||||
|
|
||||||
failwith "TODO: array initialization"
|
failwith "TODO: array initialization"
|
||||||
| "System.Private.CoreLib", "Unsafe", "As" ->
|
| "System.Private.CoreLib", "Unsafe", "As" ->
|
||||||
// https://github.com/dotnet/runtime/blob/721fdf6dcb032da1f883d30884e222e35e3d3c99/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs#L64
|
// https://github.com/dotnet/runtime/blob/721fdf6dcb032da1f883d30884e222e35e3d3c99/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs#L64
|
||||||
@@ -387,5 +405,8 @@ module Intrinsics =
|
|||||||
| "System.Private.CoreLib", "RuntimeHelpers", "CreateSpan" ->
|
| "System.Private.CoreLib", "RuntimeHelpers", "CreateSpan" ->
|
||||||
// https://github.com/dotnet/runtime/blob/9e5e6aa7bc36aeb2a154709a9d1192030c30a2ef/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs#L153
|
// https://github.com/dotnet/runtime/blob/9e5e6aa7bc36aeb2a154709a9d1192030c30a2ef/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs#L153
|
||||||
None
|
None
|
||||||
|
| "System.Private.CoreLib", "Type", "op_Equality" ->
|
||||||
|
// https://github.com/dotnet/runtime/blob/ec11903827fc28847d775ba17e0cd1ff56cfbc2e/src/libraries/System.Private.CoreLib/src/System/Type.cs#L703
|
||||||
|
None
|
||||||
| a, b, c -> failwith $"TODO: implement JIT intrinsic {a}.{b}.{c}"
|
| a, b, c -> failwith $"TODO: implement JIT intrinsic {a}.{b}.{c}"
|
||||||
|> Option.map (fun s -> s.WithThreadSwitchedToAssembly callerAssy currentThread |> fst)
|
|> Option.map (fun s -> s.WithThreadSwitchedToAssembly callerAssy currentThread |> fst)
|
||||||
|
@@ -9,7 +9,7 @@ type SyncBlock =
|
|||||||
type AllocatedNonArrayObject =
|
type AllocatedNonArrayObject =
|
||||||
{
|
{
|
||||||
Fields : CliField list
|
Fields : CliField list
|
||||||
Type : WoofWare.PawPrint.TypeInfoCrate
|
ConcreteType : ConcreteTypeHandle
|
||||||
SyncBlock : SyncBlock
|
SyncBlock : SyncBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +121,10 @@ module ManagedHeap =
|
|||||||
|
|
||||||
arr.Elements.[offset]
|
arr.Elements.[offset]
|
||||||
|
|
||||||
|
let get (alloc : ManagedHeapAddress) (heap : ManagedHeap) : AllocatedNonArrayObject =
|
||||||
|
// TODO: arrays too
|
||||||
|
heap.NonArrayObjects.[alloc]
|
||||||
|
|
||||||
let setArrayValue (alloc : ManagedHeapAddress) (offset : int) (v : CliType) (heap : ManagedHeap) : ManagedHeap =
|
let setArrayValue (alloc : ManagedHeapAddress) (offset : int) (v : CliType) (heap : ManagedHeap) : ManagedHeap =
|
||||||
let newArrs =
|
let newArrs =
|
||||||
heap.Arrays
|
heap.Arrays
|
||||||
|
@@ -766,7 +766,7 @@ module NullaryIlOp =
|
|||||||
match
|
match
|
||||||
ExceptionHandling.findExceptionHandler
|
ExceptionHandling.findExceptionHandler
|
||||||
currentMethodState.IlOpIndex
|
currentMethodState.IlOpIndex
|
||||||
heapObject.Type
|
heapObject.ConcreteType
|
||||||
currentMethodState.ExecutingMethod
|
currentMethodState.ExecutingMethod
|
||||||
state._LoadedAssemblies
|
state._LoadedAssemblies
|
||||||
with
|
with
|
||||||
|
@@ -3,6 +3,7 @@ namespace WoofWare.PawPrint
|
|||||||
open System
|
open System
|
||||||
open System.Collections.Immutable
|
open System.Collections.Immutable
|
||||||
open System.IO
|
open System.IO
|
||||||
|
open System.Reflection.Metadata
|
||||||
open Microsoft.Extensions.Logging
|
open Microsoft.Extensions.Logging
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
@@ -14,10 +15,23 @@ module Program =
|
|||||||
(state : IlMachineState)
|
(state : IlMachineState)
|
||||||
: ManagedHeapAddress * IlMachineState
|
: ManagedHeapAddress * IlMachineState
|
||||||
=
|
=
|
||||||
|
let state, stringType =
|
||||||
|
TypeDefn.FromDefinition (
|
||||||
|
ComparableTypeDefinitionHandle.Make corelib.String.TypeDefHandle,
|
||||||
|
corelib.Corelib.Name.FullName,
|
||||||
|
SignatureTypeKind.Class
|
||||||
|
)
|
||||||
|
|> IlMachineState.concretizeType
|
||||||
|
corelib
|
||||||
|
state
|
||||||
|
corelib.Corelib.Name
|
||||||
|
ImmutableArray.Empty
|
||||||
|
ImmutableArray.Empty
|
||||||
|
|
||||||
let argsAllocations, state =
|
let argsAllocations, state =
|
||||||
(state, args)
|
(state, args)
|
||||||
||> Seq.mapFold (fun state arg ->
|
||> Seq.mapFold (fun state arg ->
|
||||||
IlMachineState.allocateManagedObject corelib.String (failwith "TODO: assert fields and populate") state
|
IlMachineState.allocateManagedObject stringType (failwith "TODO: assert fields and populate") state
|
||||||
// TODO: set the char values in memory
|
// TODO: set the char values in memory
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -7,100 +7,6 @@ open Microsoft.Extensions.Logging
|
|||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal UnaryMetadataIlOp =
|
module internal UnaryMetadataIlOp =
|
||||||
let lookupTypeDefn
|
|
||||||
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
|
||||||
(state : IlMachineState)
|
|
||||||
(activeAssy : DumpedAssembly)
|
|
||||||
(typeDef : TypeDefinitionHandle)
|
|
||||||
: IlMachineState * TypeDefn
|
|
||||||
=
|
|
||||||
let defn = activeAssy.TypeDefs.[typeDef]
|
|
||||||
|
|
||||||
let baseType =
|
|
||||||
defn.BaseType
|
|
||||||
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies defn.Assembly
|
|
||||||
|
|
||||||
let signatureTypeKind =
|
|
||||||
match baseType with
|
|
||||||
| ResolvedBaseType.Enum
|
|
||||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
|
||||||
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
|
||||||
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
|
||||||
|
|
||||||
let result =
|
|
||||||
if defn.Generics.IsEmpty then
|
|
||||||
TypeDefn.FromDefinition (
|
|
||||||
ComparableTypeDefinitionHandle.Make defn.TypeDefHandle,
|
|
||||||
defn.Assembly.FullName,
|
|
||||||
signatureTypeKind
|
|
||||||
)
|
|
||||||
else
|
|
||||||
// Preserve the generic instantiation by converting GenericParameters to TypeDefn.GenericTypeParameter
|
|
||||||
let genericDef =
|
|
||||||
TypeDefn.FromDefinition (
|
|
||||||
ComparableTypeDefinitionHandle.Make defn.TypeDefHandle,
|
|
||||||
defn.Assembly.FullName,
|
|
||||||
signatureTypeKind
|
|
||||||
)
|
|
||||||
|
|
||||||
let genericArgs =
|
|
||||||
defn.Generics
|
|
||||||
|> Seq.mapi (fun i _ -> TypeDefn.GenericTypeParameter i)
|
|
||||||
|> ImmutableArray.CreateRange
|
|
||||||
|
|
||||||
TypeDefn.GenericInstantiation (genericDef, genericArgs)
|
|
||||||
|
|
||||||
state, result
|
|
||||||
|
|
||||||
let lookupTypeRef
|
|
||||||
(loggerFactory : ILoggerFactory)
|
|
||||||
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
|
||||||
(state : IlMachineState)
|
|
||||||
(activeAssy : DumpedAssembly)
|
|
||||||
typeGenerics
|
|
||||||
(ref : TypeReferenceHandle)
|
|
||||||
: IlMachineState * TypeDefn * DumpedAssembly
|
|
||||||
=
|
|
||||||
let ref = activeAssy.TypeRefs.[ref]
|
|
||||||
|
|
||||||
// Convert ConcreteTypeHandles back to TypeDefn for metadata operations
|
|
||||||
let typeGenerics =
|
|
||||||
typeGenerics
|
|
||||||
|> Seq.map (fun handle ->
|
|
||||||
Concretization.concreteHandleToTypeDefn
|
|
||||||
baseClassTypes
|
|
||||||
handle
|
|
||||||
state.ConcreteTypes
|
|
||||||
state._LoadedAssemblies
|
|
||||||
)
|
|
||||||
|> ImmutableArray.CreateRange
|
|
||||||
|
|
||||||
let state, assy, resolved =
|
|
||||||
IlMachineState.resolveTypeFromRef loggerFactory activeAssy ref typeGenerics state
|
|
||||||
|
|
||||||
let baseType =
|
|
||||||
resolved.BaseType
|
|
||||||
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies assy.Name
|
|
||||||
|
|
||||||
let signatureTypeKind =
|
|
||||||
match baseType with
|
|
||||||
| ResolvedBaseType.Enum
|
|
||||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
|
||||||
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
|
||||||
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
|
||||||
|
|
||||||
let result =
|
|
||||||
TypeDefn.FromDefinition (
|
|
||||||
ComparableTypeDefinitionHandle.Make resolved.TypeDefHandle,
|
|
||||||
assy.Name.FullName,
|
|
||||||
signatureTypeKind
|
|
||||||
)
|
|
||||||
|
|
||||||
if resolved.Generics.IsEmpty then
|
|
||||||
state, result, assy
|
|
||||||
else
|
|
||||||
failwith "TODO: add generics"
|
|
||||||
|
|
||||||
let execute
|
let execute
|
||||||
(loggerFactory : ILoggerFactory)
|
(loggerFactory : ILoggerFactory)
|
||||||
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
@@ -209,6 +115,7 @@ module internal UnaryMetadataIlOp =
|
|||||||
None
|
None
|
||||||
None
|
None
|
||||||
false
|
false
|
||||||
|
false
|
||||||
true
|
true
|
||||||
concretizedMethod.Generics
|
concretizedMethod.Generics
|
||||||
concretizedMethod
|
concretizedMethod
|
||||||
@@ -310,6 +217,7 @@ module internal UnaryMetadataIlOp =
|
|||||||
baseClassTypes
|
baseClassTypes
|
||||||
thread
|
thread
|
||||||
true
|
true
|
||||||
|
true
|
||||||
methodGenerics
|
methodGenerics
|
||||||
methodToCall
|
methodToCall
|
||||||
None
|
None
|
||||||
@@ -414,7 +322,15 @@ module internal UnaryMetadataIlOp =
|
|||||||
// On completion of the constructor, we'll copy the value back off the heap,
|
// On completion of the constructor, we'll copy the value back off the heap,
|
||||||
// and put it on the eval stack directly.
|
// and put it on the eval stack directly.
|
||||||
let allocatedAddr, state =
|
let allocatedAddr, state =
|
||||||
IlMachineState.allocateManagedObject ctorType fields state
|
let ty =
|
||||||
|
(concretizedCtor.DeclaringType.Assembly,
|
||||||
|
concretizedCtor.DeclaringType.Namespace,
|
||||||
|
concretizedCtor.DeclaringType.Name,
|
||||||
|
concretizedCtor.DeclaringType.Generics)
|
||||||
|
|> AllConcreteTypes.findExistingConcreteType state.ConcreteTypes
|
||||||
|
|> Option.get
|
||||||
|
|
||||||
|
IlMachineState.allocateManagedObject ty fields state
|
||||||
|
|
||||||
let state =
|
let state =
|
||||||
state
|
state
|
||||||
@@ -429,6 +345,7 @@ module internal UnaryMetadataIlOp =
|
|||||||
loggerFactory
|
loggerFactory
|
||||||
baseClassTypes
|
baseClassTypes
|
||||||
thread
|
thread
|
||||||
|
false
|
||||||
true
|
true
|
||||||
None
|
None
|
||||||
ctor
|
ctor
|
||||||
@@ -461,11 +378,19 @@ module internal UnaryMetadataIlOp =
|
|||||||
let state, elementType, assy =
|
let state, elementType, assy =
|
||||||
match metadataToken with
|
match metadataToken with
|
||||||
| MetadataToken.TypeDefinition defn ->
|
| MetadataToken.TypeDefinition defn ->
|
||||||
let state, resolved = lookupTypeDefn baseClassTypes state activeAssy defn
|
let state, resolved =
|
||||||
|
IlMachineState.lookupTypeDefn baseClassTypes state activeAssy defn
|
||||||
|
|
||||||
state, resolved, activeAssy
|
state, resolved, activeAssy
|
||||||
| MetadataToken.TypeSpecification spec -> state, activeAssy.TypeSpecs.[spec].Signature, activeAssy
|
| MetadataToken.TypeSpecification spec -> state, activeAssy.TypeSpecs.[spec].Signature, activeAssy
|
||||||
| MetadataToken.TypeReference ref ->
|
| MetadataToken.TypeReference ref ->
|
||||||
lookupTypeRef loggerFactory baseClassTypes state activeAssy currentMethod.DeclaringType.Generics ref
|
IlMachineState.lookupTypeRef
|
||||||
|
loggerFactory
|
||||||
|
baseClassTypes
|
||||||
|
state
|
||||||
|
activeAssy
|
||||||
|
currentMethod.DeclaringType.Generics
|
||||||
|
ref
|
||||||
| x -> failwith $"TODO: Newarr element type resolution unimplemented for {x}"
|
| x -> failwith $"TODO: Newarr element type resolution unimplemented for {x}"
|
||||||
|
|
||||||
let state, zeroOfType =
|
let state, zeroOfType =
|
||||||
@@ -524,7 +449,7 @@ module internal UnaryMetadataIlOp =
|
|||||||
| Isinst ->
|
| Isinst ->
|
||||||
let actualObj, state = IlMachineState.popEvalStack thread state
|
let actualObj, state = IlMachineState.popEvalStack thread state
|
||||||
|
|
||||||
let targetType : TypeDefn =
|
let state, targetType =
|
||||||
match metadataToken with
|
match metadataToken with
|
||||||
| MetadataToken.TypeDefinition td ->
|
| MetadataToken.TypeDefinition td ->
|
||||||
let activeAssy = state.ActiveAssembly thread
|
let activeAssy = state.ActiveAssembly thread
|
||||||
@@ -544,10 +469,46 @@ module internal UnaryMetadataIlOp =
|
|||||||
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
||||||
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
||||||
|
|
||||||
|
state,
|
||||||
TypeDefn.FromDefinition (ComparableTypeDefinitionHandle.Make td, activeAssy.Name.FullName, sigType)
|
TypeDefn.FromDefinition (ComparableTypeDefinitionHandle.Make td, activeAssy.Name.FullName, sigType)
|
||||||
| MetadataToken.TypeSpecification handle -> state.ActiveAssembly(thread).TypeSpecs.[handle].Signature
|
| MetadataToken.TypeSpecification handle ->
|
||||||
|
state, state.ActiveAssembly(thread).TypeSpecs.[handle].Signature
|
||||||
|
| MetadataToken.TypeReference handle ->
|
||||||
|
let state, assy, resol =
|
||||||
|
IlMachineState.resolveTypeFromRef
|
||||||
|
loggerFactory
|
||||||
|
activeAssy
|
||||||
|
(state.ActiveAssembly(thread).TypeRefs.[handle])
|
||||||
|
ImmutableArray.Empty
|
||||||
|
state
|
||||||
|
|
||||||
|
let baseTy =
|
||||||
|
DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies assy.Name resol.BaseType
|
||||||
|
|
||||||
|
let sigType =
|
||||||
|
match baseTy with
|
||||||
|
| ResolvedBaseType.Enum
|
||||||
|
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
||||||
|
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
||||||
|
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
||||||
|
|
||||||
|
state,
|
||||||
|
TypeDefn.FromDefinition (
|
||||||
|
ComparableTypeDefinitionHandle.Make resol.TypeDefHandle,
|
||||||
|
assy.Name.FullName,
|
||||||
|
sigType
|
||||||
|
)
|
||||||
| m -> failwith $"unexpected metadata token {m} in IsInst"
|
| m -> failwith $"unexpected metadata token {m} in IsInst"
|
||||||
|
|
||||||
|
let state, targetConcreteType =
|
||||||
|
IlMachineState.concretizeType
|
||||||
|
baseClassTypes
|
||||||
|
state
|
||||||
|
activeAssy.Name
|
||||||
|
currentMethod.DeclaringType.Generics
|
||||||
|
currentMethod.Generics
|
||||||
|
targetType
|
||||||
|
|
||||||
let returnObj =
|
let returnObj =
|
||||||
match actualObj with
|
match actualObj with
|
||||||
| EvalStackValue.ManagedPointer ManagedPointerSource.Null ->
|
| EvalStackValue.ManagedPointer ManagedPointerSource.Null ->
|
||||||
@@ -557,10 +518,10 @@ module internal UnaryMetadataIlOp =
|
|||||||
| EvalStackValue.ManagedPointer (ManagedPointerSource.Heap addr) ->
|
| EvalStackValue.ManagedPointer (ManagedPointerSource.Heap addr) ->
|
||||||
match state.ManagedHeap.NonArrayObjects.TryGetValue addr with
|
match state.ManagedHeap.NonArrayObjects.TryGetValue addr with
|
||||||
| true, v ->
|
| true, v ->
|
||||||
{ new TypeInfoEval<_> with
|
if v.ConcreteType = targetConcreteType then
|
||||||
member _.Eval typeInfo = failwith "TODO"
|
actualObj
|
||||||
}
|
else
|
||||||
|> v.Type.Apply
|
failwith $"TODO: is {v.ConcreteType} an instance of {targetType} ({targetConcreteType})"
|
||||||
| false, _ ->
|
| false, _ ->
|
||||||
|
|
||||||
match state.ManagedHeap.Arrays.TryGetValue addr with
|
match state.ManagedHeap.Arrays.TryGetValue addr with
|
||||||
@@ -580,7 +541,7 @@ module internal UnaryMetadataIlOp =
|
|||||||
| MetadataToken.FieldDefinition f ->
|
| MetadataToken.FieldDefinition f ->
|
||||||
let field =
|
let field =
|
||||||
activeAssy.Fields.[f]
|
activeAssy.Fields.[f]
|
||||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "no generics allowed in FieldDefinition")
|
|> FieldInfo.mapTypeGenerics (fun _ -> failwith "no generics allowed in FieldDefinition")
|
||||||
|
|
||||||
state, field
|
state, field
|
||||||
| MetadataToken.MemberReference mr ->
|
| MetadataToken.MemberReference mr ->
|
||||||
@@ -701,7 +662,7 @@ module internal UnaryMetadataIlOp =
|
|||||||
| true, field ->
|
| true, field ->
|
||||||
let field =
|
let field =
|
||||||
field
|
field
|
||||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "no generics allowed in FieldDefinition")
|
|> FieldInfo.mapTypeGenerics (fun _ -> failwith "no generics allowed in FieldDefinition")
|
||||||
|
|
||||||
state, field
|
state, field
|
||||||
| MetadataToken.MemberReference mr ->
|
| MetadataToken.MemberReference mr ->
|
||||||
@@ -766,7 +727,7 @@ module internal UnaryMetadataIlOp =
|
|||||||
| MetadataToken.FieldDefinition f ->
|
| MetadataToken.FieldDefinition f ->
|
||||||
let field =
|
let field =
|
||||||
activeAssy.Fields.[f]
|
activeAssy.Fields.[f]
|
||||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "no generics allowed on FieldDefinition")
|
|> FieldInfo.mapTypeGenerics (fun _ -> failwith "no generics allowed on FieldDefinition")
|
||||||
|
|
||||||
state, field
|
state, field
|
||||||
| MetadataToken.MemberReference mr ->
|
| MetadataToken.MemberReference mr ->
|
||||||
@@ -946,7 +907,7 @@ module internal UnaryMetadataIlOp =
|
|||||||
| true, field ->
|
| true, field ->
|
||||||
let field =
|
let field =
|
||||||
field
|
field
|
||||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "generics not allowed in FieldDefinition")
|
|> FieldInfo.mapTypeGenerics (fun _ -> failwith "generics not allowed in FieldDefinition")
|
||||||
|
|
||||||
state, field
|
state, field
|
||||||
| MetadataToken.MemberReference mr ->
|
| MetadataToken.MemberReference mr ->
|
||||||
@@ -1230,7 +1191,7 @@ module internal UnaryMetadataIlOp =
|
|||||||
| false, _ -> failwith "TODO: Ldsflda - throw MissingFieldException"
|
| false, _ -> failwith "TODO: Ldsflda - throw MissingFieldException"
|
||||||
| true, field ->
|
| true, field ->
|
||||||
field
|
field
|
||||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "generics not allowed on FieldDefinition")
|
|> FieldInfo.mapTypeGenerics (fun _ -> failwith "generics not allowed on FieldDefinition")
|
||||||
| t -> failwith $"Unexpectedly asked to load a non-field: {t}"
|
| t -> failwith $"Unexpectedly asked to load a non-field: {t}"
|
||||||
|
|
||||||
let state, declaringTypeHandle, typeGenerics =
|
let state, declaringTypeHandle, typeGenerics =
|
||||||
@@ -1361,13 +1322,105 @@ module internal UnaryMetadataIlOp =
|
|||||||
let ty = baseClassTypes.RuntimeMethodHandle
|
let ty = baseClassTypes.RuntimeMethodHandle
|
||||||
let field = ty.Fields |> List.exactlyOne
|
let field = ty.Fields |> List.exactlyOne
|
||||||
failwith ""
|
failwith ""
|
||||||
| MetadataToken.TypeDefinition h ->
|
|
||||||
let state, typeDefn = lookupTypeDefn baseClassTypes state activeAssy h
|
|
||||||
handleTypeToken typeDefn state
|
|
||||||
| MetadataToken.TypeSpecification h ->
|
| MetadataToken.TypeSpecification h ->
|
||||||
// Get the TypeSpec from the assembly and use its signature
|
let ty = baseClassTypes.RuntimeTypeHandle
|
||||||
let typeSpec = activeAssy.TypeSpecs.[h]
|
let field = ty.Fields |> List.exactlyOne
|
||||||
handleTypeToken typeSpec.Signature state
|
|
||||||
|
if field.Name <> "m_type" then
|
||||||
|
failwith $"unexpected field name ${field.Name} for BCL type RuntimeTypeHandle"
|
||||||
|
|
||||||
|
let typeGenerics = currentMethod.DeclaringType.Generics
|
||||||
|
let methodGenerics = currentMethod.Generics
|
||||||
|
|
||||||
|
let state, assy, typeDefn =
|
||||||
|
IlMachineState.resolveTypeFromSpecConcrete
|
||||||
|
loggerFactory
|
||||||
|
baseClassTypes
|
||||||
|
h
|
||||||
|
activeAssy
|
||||||
|
typeGenerics
|
||||||
|
methodGenerics
|
||||||
|
state
|
||||||
|
|
||||||
|
let stk =
|
||||||
|
match
|
||||||
|
DumpedAssembly.resolveBaseType
|
||||||
|
baseClassTypes
|
||||||
|
state._LoadedAssemblies
|
||||||
|
assy.Name
|
||||||
|
typeDefn.BaseType
|
||||||
|
with
|
||||||
|
| ResolvedBaseType.ValueType
|
||||||
|
| ResolvedBaseType.Enum -> SignatureTypeKind.ValueType
|
||||||
|
| ResolvedBaseType.Delegate
|
||||||
|
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
||||||
|
|
||||||
|
let typeDefn =
|
||||||
|
TypeDefn.FromDefinition (
|
||||||
|
ComparableTypeDefinitionHandle.Make typeDefn.TypeDefHandle,
|
||||||
|
assy.Name.FullName,
|
||||||
|
stk
|
||||||
|
)
|
||||||
|
|
||||||
|
let state, handle =
|
||||||
|
IlMachineState.concretizeType
|
||||||
|
baseClassTypes
|
||||||
|
state
|
||||||
|
assy.Name
|
||||||
|
typeGenerics
|
||||||
|
methodGenerics
|
||||||
|
typeDefn
|
||||||
|
|
||||||
|
let alloc, state = IlMachineState.getOrAllocateType baseClassTypes handle state
|
||||||
|
|
||||||
|
let vt =
|
||||||
|
{
|
||||||
|
Name = "m_type"
|
||||||
|
Contents = CliType.ObjectRef (Some alloc)
|
||||||
|
Offset = None
|
||||||
|
}
|
||||||
|
|> List.singleton
|
||||||
|
|> CliValueType.OfFields
|
||||||
|
|
||||||
|
IlMachineState.pushToEvalStack (CliType.ValueType vt) thread state
|
||||||
|
| MetadataToken.TypeReference h ->
|
||||||
|
let ty = baseClassTypes.RuntimeTypeHandle
|
||||||
|
let field = ty.Fields |> List.exactlyOne
|
||||||
|
|
||||||
|
if field.Name <> "m_type" then
|
||||||
|
failwith $"unexpected field name ${field.Name} for BCL type RuntimeTypeHandle"
|
||||||
|
|
||||||
|
let methodGenerics = currentMethod.Generics
|
||||||
|
|
||||||
|
let typeGenerics = currentMethod.DeclaringType.Generics
|
||||||
|
|
||||||
|
let state, typeDefn, assy =
|
||||||
|
IlMachineState.lookupTypeRef loggerFactory baseClassTypes state activeAssy typeGenerics h
|
||||||
|
|
||||||
|
let state, handle =
|
||||||
|
IlMachineState.concretizeType
|
||||||
|
baseClassTypes
|
||||||
|
state
|
||||||
|
assy.Name
|
||||||
|
typeGenerics
|
||||||
|
methodGenerics
|
||||||
|
typeDefn
|
||||||
|
|
||||||
|
let alloc, state = IlMachineState.getOrAllocateType baseClassTypes handle state
|
||||||
|
|
||||||
|
let vt =
|
||||||
|
{
|
||||||
|
Name = "m_type"
|
||||||
|
Contents = CliType.ObjectRef (Some alloc)
|
||||||
|
Offset = None
|
||||||
|
}
|
||||||
|
|> List.singleton
|
||||||
|
|> CliValueType.OfFields
|
||||||
|
|
||||||
|
IlMachineState.pushToEvalStack (CliType.ValueType vt) thread state
|
||||||
|
| MetadataToken.TypeDefinition h ->
|
||||||
|
let state, typeDefn = IlMachineState.lookupTypeDefn baseClassTypes state activeAssy h
|
||||||
|
handleTypeToken typeDefn state
|
||||||
| _ -> failwith $"Unexpected metadata token %O{metadataToken} in LdToken"
|
| _ -> failwith $"Unexpected metadata token %O{metadataToken} in LdToken"
|
||||||
|
|
||||||
state
|
state
|
||||||
@@ -1379,10 +1432,16 @@ module internal UnaryMetadataIlOp =
|
|||||||
let state, ty, assy =
|
let state, ty, assy =
|
||||||
match metadataToken with
|
match metadataToken with
|
||||||
| MetadataToken.TypeDefinition h ->
|
| MetadataToken.TypeDefinition h ->
|
||||||
let state, ty = lookupTypeDefn baseClassTypes state activeAssy h
|
let state, ty = IlMachineState.lookupTypeDefn baseClassTypes state activeAssy h
|
||||||
state, ty, activeAssy
|
state, ty, activeAssy
|
||||||
| MetadataToken.TypeReference ref ->
|
| MetadataToken.TypeReference ref ->
|
||||||
lookupTypeRef loggerFactory baseClassTypes state activeAssy currentMethod.DeclaringType.Generics ref
|
IlMachineState.lookupTypeRef
|
||||||
|
loggerFactory
|
||||||
|
baseClassTypes
|
||||||
|
state
|
||||||
|
activeAssy
|
||||||
|
currentMethod.DeclaringType.Generics
|
||||||
|
ref
|
||||||
| _ -> failwith $"unexpected token {metadataToken} in Sizeof"
|
| _ -> failwith $"unexpected token {metadataToken} in Sizeof"
|
||||||
|
|
||||||
let state, typeHandle =
|
let state, typeHandle =
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
namespace WoofWare.PawPrint
|
namespace WoofWare.PawPrint
|
||||||
|
|
||||||
|
open System.Collections.Immutable
|
||||||
open System.Reflection
|
open System.Reflection
|
||||||
|
open System.Reflection.Metadata
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||||
@@ -61,8 +63,20 @@ module internal UnaryStringTokenIlOp =
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
let addr, state =
|
let state, stringType =
|
||||||
IlMachineState.allocateManagedObject baseClassTypes.String fields state
|
TypeDefn.FromDefinition (
|
||||||
|
ComparableTypeDefinitionHandle.Make baseClassTypes.String.TypeDefHandle,
|
||||||
|
baseClassTypes.Corelib.Name.FullName,
|
||||||
|
SignatureTypeKind.Class
|
||||||
|
)
|
||||||
|
|> IlMachineState.concretizeType
|
||||||
|
baseClassTypes
|
||||||
|
state
|
||||||
|
baseClassTypes.Corelib.Name
|
||||||
|
ImmutableArray.Empty
|
||||||
|
ImmutableArray.Empty
|
||||||
|
|
||||||
|
let addr, state = IlMachineState.allocateManagedObject stringType fields state
|
||||||
|
|
||||||
addr,
|
addr,
|
||||||
{ state with
|
{ state with
|
||||||
|
Reference in New Issue
Block a user