Add another generic for MethodInfo (#85)

This commit is contained in:
Patrick Stevens
2025-07-02 18:49:24 +01:00
committed by GitHub
parent c79f775ce4
commit 0fc4335760
8 changed files with 80 additions and 38 deletions

View File

@@ -67,7 +67,7 @@ type DumpedAssembly =
Methods : Methods :
IReadOnlyDictionary< IReadOnlyDictionary<
MethodDefinitionHandle, MethodDefinitionHandle,
WoofWare.PawPrint.MethodInfo<FakeUnit, WoofWare.PawPrint.GenericParameter> WoofWare.PawPrint.MethodInfo<FakeUnit, WoofWare.PawPrint.GenericParameter, TypeDefn>
> >
/// <summary> /// <summary>

View File

@@ -117,7 +117,7 @@ type ExceptionRegion =
| ExceptionRegionKind.Fault -> ExceptionRegion.Fault offset | ExceptionRegionKind.Fault -> ExceptionRegion.Fault offset
| _ -> raise (ArgumentOutOfRangeException ()) | _ -> raise (ArgumentOutOfRangeException ())
type MethodInstructions = type MethodInstructions<'methodVars> =
{ {
/// <summary> /// <summary>
/// The IL instructions that compose the method body, along with their offset positions. /// The IL instructions that compose the method body, along with their offset positions.
@@ -137,12 +137,14 @@ type MethodInstructions =
/// </summary> /// </summary>
LocalsInit : bool LocalsInit : bool
LocalVars : ImmutableArray<TypeDefn> option LocalVars : ImmutableArray<'methodVars> option
ExceptionRegions : ImmutableArray<ExceptionRegion> ExceptionRegions : ImmutableArray<ExceptionRegion>
} }
static member OnlyRet : MethodInstructions = [<RequireQualifiedAccess>]
module MethodInstructions =
let onlyRet () : MethodInstructions<'methodVars> =
let op = IlOp.Nullary NullaryIlOp.Ret let op = IlOp.Nullary NullaryIlOp.Ret
{ {
@@ -153,11 +155,20 @@ type MethodInstructions =
ExceptionRegions = ImmutableArray.Empty ExceptionRegions = ImmutableArray.Empty
} }
let setLocalVars<'a, 'b> (v : ImmutableArray<'b> option) (s : MethodInstructions<'a>) : MethodInstructions<'b> =
{
Instructions = s.Instructions
Locations = s.Locations
LocalsInit = s.LocalsInit
LocalVars = v
ExceptionRegions = s.ExceptionRegions
}
/// <summary> /// <summary>
/// Represents detailed information about a method in a .NET assembly. /// Represents detailed information about a method in a .NET assembly.
/// This is a strongly-typed representation of MethodDefinition from System.Reflection.Metadata. /// This is a strongly-typed representation of MethodDefinition from System.Reflection.Metadata.
/// </summary> /// </summary>
type MethodInfo<'typeGenerics, 'methodGenerics type MethodInfo<'typeGenerics, 'methodGenerics, 'methodVars
when 'typeGenerics :> IComparable<'typeGenerics> and 'typeGenerics : comparison> = when 'typeGenerics :> IComparable<'typeGenerics> and 'typeGenerics : comparison> =
{ {
/// <summary> /// <summary>
@@ -178,7 +189,7 @@ type MethodInfo<'typeGenerics, 'methodGenerics
/// ///
/// There may be no instructions for this method, e.g. if it's an `InternalCall`. /// There may be no instructions for this method, e.g. if it's an `InternalCall`.
/// </summary> /// </summary>
Instructions : MethodInstructions option Instructions : MethodInstructions<'methodVars> option
/// <summary> /// <summary>
/// The parameters of this method. /// The parameters of this method.
@@ -193,7 +204,12 @@ type MethodInfo<'typeGenerics, 'methodGenerics
/// <summary> /// <summary>
/// The signature of the method, including return type and parameter types. /// The signature of the method, including return type and parameter types.
/// </summary> /// </summary>
Signature : TypeMethodSignature<TypeDefn> Signature : TypeMethodSignature<'methodVars>
/// <summary>
/// The signature as it was read from assembly metadata.
/// </summary>
RawSignature : TypeMethodSignature<TypeDefn>
/// <summary> /// <summary>
/// Custom attributes defined on the method. I've never yet seen one of these in practice. /// Custom attributes defined on the method. I've never yet seen one of these in practice.
@@ -230,8 +246,8 @@ type MethodInfo<'typeGenerics, 'methodGenerics
module MethodInfo = module MethodInfo =
let isJITIntrinsic let isJITIntrinsic
(getMemberRefParentType : MemberReferenceHandle -> TypeRef) (getMemberRefParentType : MemberReferenceHandle -> TypeRef)
(methodDefs : IReadOnlyDictionary<MethodDefinitionHandle, MethodInfo<'a, 'b>>) (methodDefs : IReadOnlyDictionary<MethodDefinitionHandle, MethodInfo<'a, 'b, 'c>>)
(this : MethodInfo<'d, 'e>) (this : MethodInfo<'d, 'e, 'f>)
: bool : bool
= =
this.CustomAttributes this.CustomAttributes
@@ -251,11 +267,11 @@ module MethodInfo =
| con -> failwith $"TODO: {con}" | con -> failwith $"TODO: {con}"
) )
let mapTypeGenerics<'a, 'b, 'methodGen let mapTypeGenerics<'a, 'b, 'methodGen, 'vars
when 'a :> IComparable<'a> and 'a : comparison and 'b : comparison and 'b :> IComparable<'b>> when 'a :> IComparable<'a> and 'a : comparison and 'b : comparison and 'b :> IComparable<'b>>
(f : int -> 'a -> 'b) (f : int -> 'a -> 'b)
(m : MethodInfo<'a, 'methodGen>) (m : MethodInfo<'a, 'methodGen, 'vars>)
: MethodInfo<'b, 'methodGen> : MethodInfo<'b, 'methodGen, 'vars>
= =
{ {
DeclaringType = m.DeclaringType |> ConcreteType.mapGeneric f DeclaringType = m.DeclaringType |> ConcreteType.mapGeneric f
@@ -265,16 +281,17 @@ module MethodInfo =
Parameters = m.Parameters Parameters = m.Parameters
Generics = m.Generics Generics = m.Generics
Signature = m.Signature Signature = m.Signature
RawSignature = m.RawSignature
CustomAttributes = m.CustomAttributes CustomAttributes = m.CustomAttributes
MethodAttributes = m.MethodAttributes MethodAttributes = m.MethodAttributes
ImplAttributes = m.ImplAttributes ImplAttributes = m.ImplAttributes
IsStatic = m.IsStatic IsStatic = m.IsStatic
} }
let mapMethodGenerics<'a, 'b, 'typeGen when 'typeGen :> IComparable<'typeGen> and 'typeGen : comparison> let mapMethodGenerics<'a, 'b, 'vars, 'typeGen when 'typeGen :> IComparable<'typeGen> and 'typeGen : comparison>
(f : int -> 'a -> 'b) (f : int -> 'a -> 'b)
(m : MethodInfo<'typeGen, 'a>) (m : MethodInfo<'typeGen, 'a, 'vars>)
: MethodInfo<'typeGen, 'b> : MethodInfo<'typeGen, 'b, 'vars>
= =
{ {
DeclaringType = m.DeclaringType DeclaringType = m.DeclaringType
@@ -284,12 +301,33 @@ module MethodInfo =
Parameters = m.Parameters Parameters = m.Parameters
Generics = m.Generics |> Seq.mapi f |> ImmutableArray.CreateRange Generics = m.Generics |> Seq.mapi f |> ImmutableArray.CreateRange
Signature = m.Signature Signature = m.Signature
RawSignature = m.RawSignature
CustomAttributes = m.CustomAttributes CustomAttributes = m.CustomAttributes
MethodAttributes = m.MethodAttributes MethodAttributes = m.MethodAttributes
ImplAttributes = m.ImplAttributes ImplAttributes = m.ImplAttributes
IsStatic = m.IsStatic IsStatic = m.IsStatic
} }
let setMethodVars
(vars2 : MethodInstructions<'vars2> option)
(signature : TypeMethodSignature<'vars2>)
(m : MethodInfo<'typeGen, 'methodGen, 'vars1>)
: MethodInfo<'typeGen, 'methodGen, 'vars2>
=
{
DeclaringType = m.DeclaringType
Handle = m.Handle
Name = m.Name
Instructions = vars2
Parameters = m.Parameters
Generics = m.Generics
Signature = signature
RawSignature = m.RawSignature
CustomAttributes = m.CustomAttributes
MethodAttributes = m.MethodAttributes
ImplAttributes = m.ImplAttributes
IsStatic = m.IsStatic
}
type private Dummy = class end type private Dummy = class end
@@ -638,7 +676,7 @@ module MethodInfo =
(peReader : PEReader) (peReader : PEReader)
(metadataReader : MetadataReader) (metadataReader : MetadataReader)
(methodHandle : MethodDefinitionHandle) (methodHandle : MethodDefinitionHandle)
: MethodInfo<FakeUnit, GenericParameter> option : MethodInfo<FakeUnit, GenericParameter, TypeDefn> option
= =
let logger = loggerFactory.CreateLogger "MethodInfo" let logger = loggerFactory.CreateLogger "MethodInfo"
let assemblyName = metadataReader.GetAssemblyDefinition().GetAssemblyName () let assemblyName = metadataReader.GetAssemblyDefinition().GetAssemblyName ()
@@ -715,6 +753,7 @@ module MethodInfo =
Parameters = methodParams Parameters = methodParams
Generics = methodGenericParams Generics = methodGenericParams
Signature = typeSig Signature = typeSig
RawSignature = typeSig
MethodAttributes = methodDef.Attributes MethodAttributes = methodDef.Attributes
CustomAttributes = attrs CustomAttributes = attrs
IsStatic = not methodSig.Header.IsInstance IsStatic = not methodSig.Header.IsInstance
@@ -724,7 +763,7 @@ module MethodInfo =
let rec resolveBaseType let rec resolveBaseType
(methodGenerics : TypeDefn ImmutableArray option) (methodGenerics : TypeDefn ImmutableArray option)
(executingMethod : MethodInfo<TypeDefn, 'methodGen>) (executingMethod : MethodInfo<TypeDefn, 'methodGen, 'vars>)
(td : TypeDefn) (td : TypeDefn)
: ResolvedBaseType : ResolvedBaseType
= =

View File

@@ -34,7 +34,7 @@ type TypeInfo<'generic, 'fieldGeneric> =
/// <summary> /// <summary>
/// All methods defined within this type. /// All methods defined within this type.
/// </summary> /// </summary>
Methods : WoofWare.PawPrint.MethodInfo<FakeUnit, WoofWare.PawPrint.GenericParameter> list Methods : WoofWare.PawPrint.MethodInfo<FakeUnit, WoofWare.PawPrint.GenericParameter, TypeDefn> list
/// <summary> /// <summary>
/// Method implementation mappings for this type, often used for interface implementations /// Method implementation mappings for this type, often used for interface implementations

View File

@@ -63,7 +63,7 @@ type UnsignedNativeIntSource =
type NativeIntSource = type NativeIntSource =
| Verbatim of int64 | Verbatim of int64
| ManagedPointer of ManagedPointerSource | ManagedPointer of ManagedPointerSource
| FunctionPointer of MethodInfo<FakeUnit, WoofWare.PawPrint.GenericParameter> | FunctionPointer of MethodInfo<FakeUnit, WoofWare.PawPrint.GenericParameter, TypeDefn>
| TypeHandlePtr of int64<typeHandle> | TypeHandlePtr of int64<typeHandle>
override this.ToString () : string = override this.ToString () : string =

View File

@@ -1,29 +1,32 @@
namespace WoofWare.PawPrint namespace WoofWare.PawPrint
open System
open System.Collections.Immutable open System.Collections.Immutable
/// Represents a location in the code where an exception occurred /// Represents a location in the code where an exception occurred
type ExceptionStackFrame = type ExceptionStackFrame<'typeGen, 'methodGen, 'methodVar
when 'typeGen : comparison and 'typeGen :> IComparable<'typeGen>> =
{ {
Method : WoofWare.PawPrint.MethodInfo<TypeDefn, TypeDefn> Method : WoofWare.PawPrint.MethodInfo<'typeGen, 'methodGen, 'methodVar>
/// The number of bytes into the IL of the method we were in /// The number of bytes into the IL of the method we were in
IlOffset : int IlOffset : int
} }
/// Represents a CLI exception being propagated /// Represents a CLI exception being propagated
type CliException = type CliException<'typeGen, 'methodGen, 'methodVar when 'typeGen : comparison and 'typeGen :> IComparable<'typeGen>> =
{ {
/// The exception object allocated on the heap /// The exception object allocated on the heap
ExceptionObject : ManagedHeapAddress ExceptionObject : ManagedHeapAddress
/// Stack trace built during unwinding /// Stack trace built during unwinding
StackTrace : ExceptionStackFrame list StackTrace : ExceptionStackFrame<'typeGen, 'methodGen, 'methodVar> list
} }
/// Represents what to do after executing a finally/filter block /// Represents what to do after executing a finally/filter block
type ExceptionContinuation = type ExceptionContinuation<'typeGen, 'methodGen, 'methodVar
when 'typeGen : comparison and 'typeGen :> IComparable<'typeGen>> =
| ResumeAfterFinally of targetPC : int | ResumeAfterFinally of targetPC : int
| PropagatingException of exn : CliException | PropagatingException of exn : CliException<'typeGen, 'methodGen, 'methodVar>
| ResumeAfterFilter of handlerPC : int * exn : CliException | ResumeAfterFilter of handlerPC : int * exn : CliException<'typeGen, 'methodGen, 'methodVar>
/// Helper functions for exception handling /// Helper functions for exception handling
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@@ -44,7 +47,7 @@ module ExceptionHandling =
let findExceptionHandler let findExceptionHandler
(currentPC : int) (currentPC : int)
(exceptionTypeCrate : TypeInfoCrate) (exceptionTypeCrate : TypeInfoCrate)
(method : WoofWare.PawPrint.MethodInfo<TypeDefn, 'methodGeneric>) (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
= =
@@ -92,7 +95,7 @@ module ExceptionHandling =
let findFinallyBlocksToRun let findFinallyBlocksToRun
(currentPC : int) (currentPC : int)
(targetPC : int) (targetPC : int)
(method : WoofWare.PawPrint.MethodInfo<TypeDefn, 'methodGeneric>) (method : WoofWare.PawPrint.MethodInfo<'typeGeneric, 'methodGeneric, 'methodVar>)
: ExceptionOffset list : ExceptionOffset list
= =
match method.Instructions with match method.Instructions with
@@ -122,7 +125,7 @@ module ExceptionHandling =
/// Get the active exception regions at a given offset /// Get the active exception regions at a given offset
let getActiveRegionsAtOffset let getActiveRegionsAtOffset
(offset : int) (offset : int)
(method : WoofWare.PawPrint.MethodInfo<TypeDefn, 'methodGeneric>) (method : WoofWare.PawPrint.MethodInfo<'a, 'b, 'c>)
: WoofWare.PawPrint.ExceptionRegion list : WoofWare.PawPrint.ExceptionRegion list
= =
match method.Instructions with match method.Instructions with

View File

@@ -549,7 +549,7 @@ module IlMachineState =
let callIntrinsic let callIntrinsic
(baseClassTypes : BaseClassTypes<_>) (baseClassTypes : BaseClassTypes<_>)
(methodToCall : WoofWare.PawPrint.MethodInfo<TypeDefn, WoofWare.PawPrint.GenericParameter>) (methodToCall : WoofWare.PawPrint.MethodInfo<TypeDefn, WoofWare.PawPrint.GenericParameter, TypeDefn>)
(currentThread : ThreadId) (currentThread : ThreadId)
(state : IlMachineState) (state : IlMachineState)
: IlMachineState option : IlMachineState option
@@ -741,7 +741,7 @@ module IlMachineState =
(wasClassConstructor : bool) (wasClassConstructor : bool)
(advanceProgramCounterOfCaller : bool) (advanceProgramCounterOfCaller : bool)
(methodGenerics : ImmutableArray<TypeDefn> option) (methodGenerics : ImmutableArray<TypeDefn> option)
(methodToCall : WoofWare.PawPrint.MethodInfo<TypeDefn, WoofWare.PawPrint.GenericParameter>) (methodToCall : WoofWare.PawPrint.MethodInfo<TypeDefn, WoofWare.PawPrint.GenericParameter, TypeDefn>)
(thread : ThreadId) (thread : ThreadId)
(threadState : ThreadState) (threadState : ThreadState)
(state : IlMachineState) (state : IlMachineState)
@@ -1093,7 +1093,7 @@ module IlMachineState =
(thread : ThreadId) (thread : ThreadId)
(advanceProgramCounterOfCaller : bool) (advanceProgramCounterOfCaller : bool)
(methodGenerics : TypeDefn ImmutableArray option) (methodGenerics : TypeDefn ImmutableArray option)
(methodToCall : WoofWare.PawPrint.MethodInfo<TypeDefn, WoofWare.PawPrint.GenericParameter>) (methodToCall : WoofWare.PawPrint.MethodInfo<TypeDefn, WoofWare.PawPrint.GenericParameter, TypeDefn>)
(weAreConstructingObj : ManagedHeapAddress option) (weAreConstructingObj : ManagedHeapAddress option)
(state : IlMachineState) (state : IlMachineState)
: IlMachineState * WhatWeDid : IlMachineState * WhatWeDid
@@ -1289,7 +1289,7 @@ module IlMachineState =
: IlMachineState * : IlMachineState *
AssemblyName * AssemblyName *
Choice< Choice<
WoofWare.PawPrint.MethodInfo<TypeDefn, WoofWare.PawPrint.GenericParameter>, WoofWare.PawPrint.MethodInfo<TypeDefn, WoofWare.PawPrint.GenericParameter, TypeDefn>,
WoofWare.PawPrint.FieldInfo<TypeDefn, TypeDefn> WoofWare.PawPrint.FieldInfo<TypeDefn, TypeDefn>
> >
= =

View File

@@ -19,7 +19,7 @@ and MethodState =
_IlOpIndex : int _IlOpIndex : int
EvaluationStack : EvalStack EvaluationStack : EvalStack
Arguments : CliType ImmutableArray Arguments : CliType ImmutableArray
ExecutingMethod : WoofWare.PawPrint.MethodInfo<TypeDefn, TypeDefn> ExecutingMethod : WoofWare.PawPrint.MethodInfo<TypeDefn, TypeDefn, TypeDefn>
/// We don't implement the local memory pool right now /// We don't implement the local memory pool right now
LocalMemoryPool : unit LocalMemoryPool : unit
/// On return, we restore this state. This should be Some almost always; an exception is the entry point. /// On return, we restore this state. This should be Some almost always; an exception is the entry point.
@@ -28,7 +28,7 @@ and MethodState =
/// Track which exception regions are currently active (innermost first) /// Track which exception regions are currently active (innermost first)
ActiveExceptionRegions : ExceptionRegion list ActiveExceptionRegions : ExceptionRegion list
/// When executing a finally/fault/filter, we need to know where to return /// When executing a finally/fault/filter, we need to know where to return
ExceptionContinuation : ExceptionContinuation option ExceptionContinuation : ExceptionContinuation<TypeDefn, TypeDefn, TypeDefn> option
} }
member this.IlOpIndex = this._IlOpIndex member this.IlOpIndex = this._IlOpIndex
@@ -64,7 +64,7 @@ and MethodState =
EvaluationStack = EvalStack.Empty EvaluationStack = EvalStack.Empty
} }
static member setExceptionContinuation (cont : ExceptionContinuation) (state : MethodState) : MethodState = static member setExceptionContinuation (cont : ExceptionContinuation<_, _, _>) (state : MethodState) : MethodState =
{ state with { state with
ExceptionContinuation = Some cont ExceptionContinuation = Some cont
} }
@@ -139,7 +139,7 @@ and MethodState =
(corelib : BaseClassTypes<DumpedAssembly>) (corelib : BaseClassTypes<DumpedAssembly>)
(loadedAssemblies : ImmutableDictionary<string, DumpedAssembly>) (loadedAssemblies : ImmutableDictionary<string, DumpedAssembly>)
(containingAssembly : DumpedAssembly) (containingAssembly : DumpedAssembly)
(method : WoofWare.PawPrint.MethodInfo<TypeDefn, TypeDefn>) (method : WoofWare.PawPrint.MethodInfo<TypeDefn, TypeDefn, TypeDefn>)
(methodGenerics : ImmutableArray<TypeDefn> option) (methodGenerics : ImmutableArray<TypeDefn> option)
(args : ImmutableArray<CliType>) (args : ImmutableArray<CliType>)
(returnState : MethodReturnState option) (returnState : MethodReturnState option)

View File

@@ -106,7 +106,7 @@ module Program =
dumped dumped
// pretend there are no instructions, so we avoid preparing anything // pretend there are no instructions, so we avoid preparing anything
{ mainMethod with { mainMethod with
Instructions = Some MethodInstructions.OnlyRet Instructions = Some (MethodInstructions.onlyRet ())
} }
None None
(ImmutableArray.CreateRange [ CliType.ObjectRef None ]) (ImmutableArray.CreateRange [ CliType.ObjectRef None ])