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 :
IReadOnlyDictionary<
MethodDefinitionHandle,
WoofWare.PawPrint.MethodInfo<FakeUnit, WoofWare.PawPrint.GenericParameter>
WoofWare.PawPrint.MethodInfo<FakeUnit, WoofWare.PawPrint.GenericParameter, TypeDefn>
>
/// <summary>

View File

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

View File

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

View File

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

View File

@@ -1,29 +1,32 @@
namespace WoofWare.PawPrint
open System
open System.Collections.Immutable
/// 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
IlOffset : int
}
/// 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
ExceptionObject : ManagedHeapAddress
/// Stack trace built during unwinding
StackTrace : ExceptionStackFrame list
StackTrace : ExceptionStackFrame<'typeGen, 'methodGen, 'methodVar> list
}
/// 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
| PropagatingException of exn : CliException
| ResumeAfterFilter of handlerPC : int * exn : CliException
| PropagatingException of exn : CliException<'typeGen, 'methodGen, 'methodVar>
| ResumeAfterFilter of handlerPC : int * exn : CliException<'typeGen, 'methodGen, 'methodVar>
/// Helper functions for exception handling
[<RequireQualifiedAccess>]
@@ -44,7 +47,7 @@ module ExceptionHandling =
let findExceptionHandler
(currentPC : int)
(exceptionTypeCrate : TypeInfoCrate)
(method : WoofWare.PawPrint.MethodInfo<TypeDefn, 'methodGeneric>)
(method : WoofWare.PawPrint.MethodInfo<'typeGen, 'methodGeneric, 'methodVar>)
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
: (WoofWare.PawPrint.ExceptionRegion * bool) option // handler, isFinally
=
@@ -92,7 +95,7 @@ module ExceptionHandling =
let findFinallyBlocksToRun
(currentPC : int)
(targetPC : int)
(method : WoofWare.PawPrint.MethodInfo<TypeDefn, 'methodGeneric>)
(method : WoofWare.PawPrint.MethodInfo<'typeGeneric, 'methodGeneric, 'methodVar>)
: ExceptionOffset list
=
match method.Instructions with
@@ -122,7 +125,7 @@ module ExceptionHandling =
/// Get the active exception regions at a given offset
let getActiveRegionsAtOffset
(offset : int)
(method : WoofWare.PawPrint.MethodInfo<TypeDefn, 'methodGeneric>)
(method : WoofWare.PawPrint.MethodInfo<'a, 'b, 'c>)
: WoofWare.PawPrint.ExceptionRegion list
=
match method.Instructions with

View File

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

View File

@@ -19,7 +19,7 @@ and MethodState =
_IlOpIndex : int
EvaluationStack : EvalStack
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
LocalMemoryPool : unit
/// 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)
ActiveExceptionRegions : ExceptionRegion list
/// 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
@@ -64,7 +64,7 @@ and MethodState =
EvaluationStack = EvalStack.Empty
}
static member setExceptionContinuation (cont : ExceptionContinuation) (state : MethodState) : MethodState =
static member setExceptionContinuation (cont : ExceptionContinuation<_, _, _>) (state : MethodState) : MethodState =
{ state with
ExceptionContinuation = Some cont
}
@@ -139,7 +139,7 @@ and MethodState =
(corelib : BaseClassTypes<DumpedAssembly>)
(loadedAssemblies : ImmutableDictionary<string, DumpedAssembly>)
(containingAssembly : DumpedAssembly)
(method : WoofWare.PawPrint.MethodInfo<TypeDefn, TypeDefn>)
(method : WoofWare.PawPrint.MethodInfo<TypeDefn, TypeDefn, TypeDefn>)
(methodGenerics : ImmutableArray<TypeDefn> option)
(args : ImmutableArray<CliType>)
(returnState : MethodReturnState option)

View File

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