mirror of
https://github.com/Smaug123/WoofWare.PawPrint
synced 2025-10-10 08:18:39 +00:00
Store ConcreteType in FieldInfo (#36)
This commit is contained in:
@@ -71,7 +71,7 @@ type DumpedAssembly =
|
||||
/// <summary>
|
||||
/// Dictionary of all field definitions in this assembly, keyed by their handle.
|
||||
/// </summary>
|
||||
Fields : IReadOnlyDictionary<FieldDefinitionHandle, WoofWare.PawPrint.FieldInfo>
|
||||
Fields : IReadOnlyDictionary<FieldDefinitionHandle, WoofWare.PawPrint.FieldInfo<FakeUnit>>
|
||||
|
||||
/// <summary>
|
||||
/// The entry point method of the assembly, if one exists.
|
||||
@@ -268,7 +268,7 @@ module Assembly =
|
||||
let builder = ImmutableDictionary.CreateBuilder ()
|
||||
|
||||
for ref in metadataReader.AssemblyReferences do
|
||||
builder.Add (ref, AssemblyReference.make ref (metadataReader.GetAssemblyReference ref))
|
||||
builder.Add (ref, AssemblyReference.make (ref, assy.Name) (metadataReader.GetAssemblyReference ref))
|
||||
|
||||
builder.ToImmutable ()
|
||||
|
||||
@@ -355,7 +355,7 @@ module Assembly =
|
||||
for field in metadataReader.FieldDefinitions do
|
||||
let fieldDefn =
|
||||
metadataReader.GetFieldDefinition field
|
||||
|> FieldInfo.make metadataReader.GetString field
|
||||
|> FieldInfo.make metadataReader assy.Name field
|
||||
|
||||
result.Add (field, fieldDefn)
|
||||
|
||||
|
@@ -6,7 +6,8 @@ open System.Reflection.Metadata
|
||||
|
||||
type AssemblyReference =
|
||||
{
|
||||
Handle : AssemblyReferenceHandle
|
||||
/// A handle relative to the specified assembly.
|
||||
Handle : AssemblyReferenceHandle * AssemblyName
|
||||
Culture : StringToken
|
||||
Flags : AssemblyFlags
|
||||
Name : AssemblyName
|
||||
@@ -16,7 +17,7 @@ type AssemblyReference =
|
||||
[<RequireQualifiedAccess>]
|
||||
module AssemblyReference =
|
||||
let make
|
||||
(handle : AssemblyReferenceHandle)
|
||||
(handle : AssemblyReferenceHandle * AssemblyName)
|
||||
(ref : System.Reflection.Metadata.AssemblyReference)
|
||||
: AssemblyReference
|
||||
=
|
||||
|
@@ -1,12 +1,14 @@
|
||||
namespace WoofWare.PawPrint
|
||||
|
||||
open System
|
||||
open System.Reflection
|
||||
open System.Reflection.Metadata
|
||||
|
||||
/// <summary>
|
||||
/// Represents detailed information about a field in a .NET assembly.
|
||||
/// This is a strongly-typed representation of FieldDefinition from System.Reflection.Metadata.
|
||||
/// </summary>
|
||||
type FieldInfo =
|
||||
type FieldInfo<'typeGeneric when 'typeGeneric : comparison and 'typeGeneric :> IComparable<'typeGeneric>> =
|
||||
{
|
||||
/// <summary>
|
||||
/// The metadata token handle that uniquely identifies this field in the assembly.
|
||||
@@ -19,7 +21,7 @@ type FieldInfo =
|
||||
/// <summary>
|
||||
/// The type that declares this field.
|
||||
/// </summary>
|
||||
DeclaringType : TypeDefinitionHandle
|
||||
DeclaringType : ConcreteType<'typeGeneric>
|
||||
|
||||
/// <summary>
|
||||
/// The type of the field.
|
||||
@@ -30,20 +32,42 @@ type FieldInfo =
|
||||
/// The attributes applied to this field, including visibility, static/instance,
|
||||
/// literal, and other characteristics.
|
||||
/// </summary>
|
||||
Attributes : System.Reflection.FieldAttributes
|
||||
Attributes : FieldAttributes
|
||||
}
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module FieldInfo =
|
||||
let make (getString : StringHandle -> string) (handle : FieldDefinitionHandle) (def : FieldDefinition) : FieldInfo =
|
||||
let name = getString def.Name
|
||||
let make
|
||||
(mr : MetadataReader)
|
||||
(assembly : AssemblyName)
|
||||
(handle : FieldDefinitionHandle)
|
||||
(def : FieldDefinition)
|
||||
: FieldInfo<FakeUnit>
|
||||
=
|
||||
let name = mr.GetString def.Name
|
||||
let fieldSig = def.DecodeSignature (TypeDefn.typeProvider, ())
|
||||
let declaringType = def.GetDeclaringType ()
|
||||
let typeGenerics = mr.GetTypeDefinition(declaringType).GetGenericParameters().Count
|
||||
|
||||
{
|
||||
Name = name
|
||||
Signature = fieldSig
|
||||
DeclaringType = declaringType
|
||||
DeclaringType = ConcreteType.make' assembly declaringType typeGenerics
|
||||
Handle = handle
|
||||
Attributes = def.Attributes
|
||||
}
|
||||
|
||||
let mapTypeGenerics<'a, 'b
|
||||
when 'a :> IComparable<'a> and 'a : comparison and 'b :> IComparable<'b> and 'b : comparison>
|
||||
(f : int -> 'a -> 'b)
|
||||
(input : FieldInfo<'a>)
|
||||
: FieldInfo<'b>
|
||||
=
|
||||
{
|
||||
Handle = input.Handle
|
||||
Name = input.Name
|
||||
DeclaringType = input.DeclaringType |> ConcreteType.mapGeneric f
|
||||
Signature = input.Signature
|
||||
Attributes = input.Attributes
|
||||
|
||||
}
|
||||
|
@@ -23,20 +23,34 @@ type IlMachineState =
|
||||
/// Tracks initialization state of types across assemblies
|
||||
TypeInitTable : TypeInitTable
|
||||
/// For each type, specialised to each set of generic args, a map of string field name to static value contained therein.
|
||||
Statics : ImmutableDictionary<RuntimeConcreteType, ImmutableDictionary<string, CliType>>
|
||||
_Statics : ImmutableDictionary<ConcreteType<FakeUnit>, ImmutableDictionary<string, CliType>>
|
||||
DotnetRuntimeDirs : string ImmutableArray
|
||||
}
|
||||
|
||||
member this.SetStatic (ty : RuntimeConcreteType) (field : string) (value : CliType) : IlMachineState =
|
||||
// Static variables are shared among all instantiations of a generic type.
|
||||
let ty = ty |> ConcreteType.mapGeneric (fun _ _ -> FakeUnit.FakeUnit)
|
||||
|
||||
let statics =
|
||||
match this.Statics.TryGetValue ty with
|
||||
| false, _ -> this.Statics.Add (ty, ImmutableDictionary.Create().Add (field, value))
|
||||
| true, v -> this.Statics.SetItem (ty, v.SetItem (field, value))
|
||||
match this._Statics.TryGetValue ty with
|
||||
| false, _ -> this._Statics.Add (ty, ImmutableDictionary.Create().Add (field, value))
|
||||
| true, v -> this._Statics.SetItem (ty, v.SetItem (field, value))
|
||||
|
||||
{ this with
|
||||
Statics = statics
|
||||
_Statics = statics
|
||||
}
|
||||
|
||||
member this.GetStatic (ty : RuntimeConcreteType) (field : string) : CliType option =
|
||||
// Static variables are shared among all instantiations of a generic type.
|
||||
let ty = ty |> ConcreteType.mapGeneric (fun _ _ -> FakeUnit.FakeUnit)
|
||||
|
||||
match this._Statics.TryGetValue ty with
|
||||
| false, _ -> None
|
||||
| true, v ->
|
||||
match v.TryGetValue field with
|
||||
| false, _ -> None
|
||||
| true, v -> Some v
|
||||
|
||||
member this.WithTypeBeginInit (thread : ThreadId) (ty : RuntimeConcreteType) =
|
||||
this.Logger.LogDebug (
|
||||
"Beginning initialisation of type {s_Assembly}.{TypeName}, handle {TypeDefinitionHandle}",
|
||||
@@ -198,7 +212,13 @@ module IlMachineState =
|
||||
match Assembly.resolveTypeFromName assy state._LoadedAssemblies ns name with
|
||||
| TypeResolutionResult.Resolved (assy, typeDef) -> state, assy, typeDef
|
||||
| TypeResolutionResult.FirstLoadAssy loadFirst ->
|
||||
let state, _, _ = loadAssembly loggerFactory assy loadFirst.Handle state
|
||||
let state, _, _ =
|
||||
loadAssembly
|
||||
loggerFactory
|
||||
state._LoadedAssemblies.[snd(loadFirst.Handle).FullName]
|
||||
(fst loadFirst.Handle)
|
||||
state
|
||||
|
||||
resolveTypeFromName loggerFactory ns name assy state
|
||||
|
||||
and resolveTypeFromExport
|
||||
@@ -211,8 +231,14 @@ module IlMachineState =
|
||||
match Assembly.resolveTypeFromExport fromAssembly state._LoadedAssemblies ty with
|
||||
| TypeResolutionResult.Resolved (assy, typeDef) -> state, assy, typeDef
|
||||
| TypeResolutionResult.FirstLoadAssy loadFirst ->
|
||||
let state, _, _ = loadAssembly loggerFactory fromAssembly loadFirst.Handle state
|
||||
resolveTypeFromExport loggerFactory fromAssembly ty state
|
||||
let state, targetAssy, _ =
|
||||
loadAssembly
|
||||
loggerFactory
|
||||
state._LoadedAssemblies.[snd(loadFirst.Handle).FullName]
|
||||
(fst loadFirst.Handle)
|
||||
state
|
||||
|
||||
resolveTypeFromName loggerFactory ty.Namespace ty.Name targetAssy state
|
||||
|
||||
and resolveTypeFromRef
|
||||
(loggerFactory : ILoggerFactory)
|
||||
@@ -225,7 +251,11 @@ module IlMachineState =
|
||||
| TypeResolutionResult.Resolved (assy, typeDef) -> state, assy, typeDef
|
||||
| TypeResolutionResult.FirstLoadAssy loadFirst ->
|
||||
let state, _, _ =
|
||||
loadAssembly loggerFactory referencedInAssembly loadFirst.Handle state
|
||||
loadAssembly
|
||||
loggerFactory
|
||||
(state._LoadedAssemblies.[snd(loadFirst.Handle).FullName])
|
||||
(fst loadFirst.Handle)
|
||||
state
|
||||
|
||||
resolveTypeFromRef loggerFactory referencedInAssembly target state
|
||||
|
||||
@@ -295,7 +325,9 @@ module IlMachineState =
|
||||
match CliType.zeroOf state._LoadedAssemblies assy generics ty with
|
||||
| CliTypeResolutionResult.Resolved result -> state, result
|
||||
| CliTypeResolutionResult.FirstLoad ref ->
|
||||
let state, _, _ = loadAssembly loggerFactory assy ref.Handle state
|
||||
let state, _, _ =
|
||||
loadAssembly loggerFactory state._LoadedAssemblies.[snd(ref.Handle).FullName] (fst ref.Handle) state
|
||||
|
||||
cliTypeZeroOf loggerFactory assy ty generics state
|
||||
|
||||
let callMethod
|
||||
@@ -368,7 +400,7 @@ module IlMachineState =
|
||||
loadAssembly
|
||||
loggerFactory
|
||||
(state.LoadedAssembly methodToCall.DeclaringType.Assembly |> Option.get)
|
||||
toLoad.Handle
|
||||
(fst toLoad.Handle)
|
||||
state
|
||||
|
||||
state
|
||||
@@ -429,7 +461,7 @@ module IlMachineState =
|
||||
loadAssembly
|
||||
loggerFactory
|
||||
(state.LoadedAssembly methodToCall.DeclaringType.Assembly |> Option.get)
|
||||
toLoad.Handle
|
||||
(fst toLoad.Handle)
|
||||
state
|
||||
|
||||
state
|
||||
@@ -651,7 +683,7 @@ module IlMachineState =
|
||||
ThreadState = Map.empty
|
||||
InternedStrings = ImmutableDictionary.Empty
|
||||
_LoadedAssemblies = ImmutableDictionary.Empty
|
||||
Statics = ImmutableDictionary.Empty
|
||||
_Statics = ImmutableDictionary.Empty
|
||||
TypeInitTable = ImmutableDictionary.Empty
|
||||
DotnetRuntimeDirs = dotnetRuntimeDirs
|
||||
}
|
||||
@@ -857,7 +889,9 @@ module IlMachineState =
|
||||
(assy : DumpedAssembly)
|
||||
(m : MemberReferenceHandle)
|
||||
(state : IlMachineState)
|
||||
: IlMachineState * AssemblyName * Choice<WoofWare.PawPrint.MethodInfo<TypeDefn>, WoofWare.PawPrint.FieldInfo>
|
||||
: IlMachineState *
|
||||
AssemblyName *
|
||||
Choice<WoofWare.PawPrint.MethodInfo<TypeDefn>, WoofWare.PawPrint.FieldInfo<TypeDefn>>
|
||||
=
|
||||
// TODO: do we need to initialise the parent class here?
|
||||
let mem = assy.Members.[m]
|
||||
@@ -882,7 +916,7 @@ module IlMachineState =
|
||||
| [] ->
|
||||
failwith
|
||||
$"Could not find field member {memberName} with the right signature on {targetType.Namespace}.{targetType.Name}"
|
||||
| [ x ] -> x
|
||||
| [ x ] -> x |> FieldInfo.mapTypeGenerics (fun index _ -> targetType.Generics.[index])
|
||||
| _ ->
|
||||
failwith
|
||||
$"Multiple overloads matching signature for {targetType.Namespace}.{targetType.Name}'s field {memberName}!"
|
||||
|
@@ -44,7 +44,7 @@ type TypeInfo<'generic> =
|
||||
/// <summary>
|
||||
/// Fields defined in this type.
|
||||
/// </summary>
|
||||
Fields : WoofWare.PawPrint.FieldInfo list
|
||||
Fields : WoofWare.PawPrint.FieldInfo<FakeUnit> list
|
||||
|
||||
/// <summary>
|
||||
/// The base type that this type inherits from, or None for types that don't have a base type
|
||||
@@ -152,7 +152,7 @@ module TypeInfo =
|
||||
|
||||
let fields =
|
||||
typeDef.GetFields ()
|
||||
|> Seq.map (fun h -> FieldInfo.make metadataReader.GetString h (metadataReader.GetFieldDefinition h))
|
||||
|> Seq.map (fun h -> FieldInfo.make metadataReader thisAssembly h (metadataReader.GetFieldDefinition h))
|
||||
|> Seq.toList
|
||||
|
||||
let name = metadataReader.GetString typeDef.Name
|
||||
|
@@ -287,20 +287,20 @@ module internal UnaryMetadataIlOp =
|
||||
let state, declaringType, field =
|
||||
match metadataToken with
|
||||
| MetadataToken.FieldDefinition f ->
|
||||
let field = activeAssy.Fields.[f]
|
||||
// No generics on a type if we're accessing it by FieldDefinition
|
||||
let declaringType = ConcreteType.make activeAssy.Name field.DeclaringType []
|
||||
state, declaringType, field
|
||||
let field =
|
||||
activeAssy.Fields.[f]
|
||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "no generics allowed in FieldDefinition")
|
||||
|
||||
state, field.DeclaringType, field
|
||||
| t -> failwith $"Unexpectedly asked to store to a non-field: {t}"
|
||||
|
||||
do
|
||||
let logger = loggerFactory.CreateLogger "Stfld"
|
||||
let declaring = activeAssy.TypeDefs.[field.DeclaringType]
|
||||
|
||||
logger.LogInformation (
|
||||
"Storing in object field {FieldAssembly}.{FieldDeclaringType}.{FieldName} (type {FieldType})",
|
||||
declaring.Assembly.Name,
|
||||
declaring.Name,
|
||||
field.DeclaringType.Assembly.Name,
|
||||
field.Name,
|
||||
field.Name,
|
||||
field.Signature
|
||||
)
|
||||
@@ -362,41 +362,42 @@ module internal UnaryMetadataIlOp =
|
||||
| Stsfld ->
|
||||
let activeAssy = state.ActiveAssembly thread
|
||||
|
||||
let state, field, declaringType =
|
||||
let state, field =
|
||||
match metadataToken with
|
||||
| MetadataToken.FieldDefinition fieldHandle ->
|
||||
match activeAssy.Fields.TryGetValue fieldHandle with
|
||||
| false, _ -> failwith "TODO: Stsfld - throw MissingFieldException"
|
||||
| true, field -> state, field, ConcreteType.make activeAssy.Name field.DeclaringType []
|
||||
| true, field ->
|
||||
let field =
|
||||
field
|
||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "no generics allowed in FieldDefinition")
|
||||
|
||||
state, field
|
||||
| MetadataToken.MemberReference mr ->
|
||||
let state, assy, method =
|
||||
let state, _, method =
|
||||
IlMachineState.resolveMember loggerFactory (state.ActiveAssembly thread) mr state
|
||||
|
||||
match method with
|
||||
| Choice1Of2 methodInfo ->
|
||||
failwith $"unexpectedly asked to store to a non-field method: {methodInfo.Name}"
|
||||
| Choice2Of2 fieldInfo ->
|
||||
state,
|
||||
fieldInfo,
|
||||
ConcreteType.make
|
||||
assy
|
||||
fieldInfo.DeclaringType
|
||||
(failwith "TODO: refactor FieldInfo to store a Runtime type")
|
||||
| Choice2Of2 fieldInfo -> state, fieldInfo
|
||||
| t -> failwith $"Unexpectedly asked to store to a non-field: {t}"
|
||||
|
||||
do
|
||||
let logger = loggerFactory.CreateLogger "Stsfld"
|
||||
let declaring = state.ActiveAssembly(thread).TypeDefs.[field.DeclaringType]
|
||||
|
||||
let declaring =
|
||||
state.ActiveAssembly(thread).TypeDefs.[field.DeclaringType.Definition.Get]
|
||||
|
||||
logger.LogInformation (
|
||||
"Storing in static field {FieldAssembly}.{FieldDeclaringType}.{FieldName} (type {FieldType})",
|
||||
declaring.Assembly.Name,
|
||||
field.DeclaringType.Assembly.Name,
|
||||
declaring.Name,
|
||||
field.Name,
|
||||
field.Signature
|
||||
)
|
||||
|
||||
match IlMachineState.loadClass loggerFactory declaringType thread state with
|
||||
match IlMachineState.loadClass loggerFactory field.DeclaringType thread state with
|
||||
| FirstLoadThis state -> state, WhatWeDid.SuspendedForClassInit
|
||||
| NothingToDo state ->
|
||||
|
||||
@@ -407,13 +408,13 @@ module internal UnaryMetadataIlOp =
|
||||
loggerFactory
|
||||
activeAssy
|
||||
field.Signature
|
||||
(ImmutableArray.CreateRange declaringType.Generics)
|
||||
(ImmutableArray.CreateRange field.DeclaringType.Generics)
|
||||
state
|
||||
|
||||
let toStore = EvalStackValue.toCliTypeCoerced zero popped
|
||||
|
||||
let state =
|
||||
state.SetStatic declaringType field.Name toStore
|
||||
state.SetStatic field.DeclaringType field.Name toStore
|
||||
|> IlMachineState.advanceProgramCounter thread
|
||||
|
||||
state, WhatWeDid.Executed
|
||||
@@ -421,36 +422,30 @@ module internal UnaryMetadataIlOp =
|
||||
| Ldfld ->
|
||||
let activeAssembly = state.ActiveAssembly thread
|
||||
|
||||
let state, declaringType, field =
|
||||
let state, field =
|
||||
match metadataToken with
|
||||
| MetadataToken.FieldDefinition f ->
|
||||
let declaringType =
|
||||
ConcreteType.make activeAssembly.Name activeAssembly.Fields.[f].DeclaringType []
|
||||
let field =
|
||||
activeAssembly.Fields.[f]
|
||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "no generics allowed on FieldDefinition")
|
||||
|
||||
state, declaringType, activeAssembly.Fields.[f]
|
||||
state, field
|
||||
| MetadataToken.MemberReference mr ->
|
||||
let state, assyName, field =
|
||||
IlMachineState.resolveMember loggerFactory activeAssembly mr state
|
||||
|
||||
match field with
|
||||
| Choice1Of2 _method -> failwith "member reference was unexpectedly a method"
|
||||
| Choice2Of2 field ->
|
||||
let parentTy = state.LoadedAssembly(assyName).Value.TypeDefs.[field.DeclaringType]
|
||||
|
||||
if parentTy.Generics.Length > 0 then
|
||||
failwith "oh no: generics"
|
||||
|
||||
let declaringType = ConcreteType.make assyName field.DeclaringType []
|
||||
state, declaringType, field
|
||||
| Choice2Of2 field -> state, field
|
||||
| t -> failwith $"Unexpectedly asked to load from a non-field: {t}"
|
||||
|
||||
do
|
||||
let logger = loggerFactory.CreateLogger "Ldfld"
|
||||
let declaring = activeAssembly.TypeDefs.[field.DeclaringType]
|
||||
let declaring = activeAssembly.TypeDefs.[field.DeclaringType.Definition.Get]
|
||||
|
||||
logger.LogInformation (
|
||||
"Loading object field {FieldAssembly}.{FieldDeclaringType}.{FieldName} (type {FieldType})",
|
||||
declaring.Assembly.Name,
|
||||
field.DeclaringType.Assembly.Name,
|
||||
declaring.Name,
|
||||
field.Name,
|
||||
field.Signature
|
||||
@@ -459,7 +454,21 @@ module internal UnaryMetadataIlOp =
|
||||
let currentObj, state = IlMachineState.popEvalStack thread state
|
||||
|
||||
if field.Attributes.HasFlag FieldAttributes.Static then
|
||||
let staticField = state.Statics.[declaringType].[field.Name]
|
||||
let state, staticField =
|
||||
match state.GetStatic field.DeclaringType field.Name with
|
||||
| Some v -> state, v
|
||||
| None ->
|
||||
let state, zero =
|
||||
IlMachineState.cliTypeZeroOf
|
||||
loggerFactory
|
||||
(state.LoadedAssembly(field.DeclaringType.Assembly).Value)
|
||||
field.Signature
|
||||
(ImmutableArray.CreateRange field.DeclaringType.Generics)
|
||||
state
|
||||
|
||||
let state = state.SetStatic field.DeclaringType field.Name zero
|
||||
state, zero
|
||||
|
||||
let state = state |> IlMachineState.pushToEvalStack staticField thread
|
||||
state, WhatWeDid.Executed
|
||||
else
|
||||
@@ -496,67 +505,59 @@ module internal UnaryMetadataIlOp =
|
||||
|
||||
let activeAssy = state.ActiveAssembly thread
|
||||
|
||||
let field, declaringType =
|
||||
let field =
|
||||
match metadataToken with
|
||||
| MetadataToken.FieldDefinition fieldHandle ->
|
||||
match activeAssy.Fields.TryGetValue fieldHandle with
|
||||
| false, _ -> failwith "TODO: Ldsfld - throw MissingFieldException"
|
||||
| true, field ->
|
||||
// FieldDefinition won't come on a generic type
|
||||
field, ConcreteType.make activeAssy.Name field.DeclaringType []
|
||||
field
|
||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "generics not allowed in FieldDefinition")
|
||||
| t -> failwith $"Unexpectedly asked to load from a non-field: {t}"
|
||||
|
||||
do
|
||||
let declaring =
|
||||
state.LoadedAssembly (declaringType.Assembly)
|
||||
state.LoadedAssembly field.DeclaringType.Assembly
|
||||
|> Option.get
|
||||
|> fun a -> a.TypeDefs.[declaringType.Definition.Get]
|
||||
|> fun a -> a.TypeDefs.[field.DeclaringType.Definition.Get]
|
||||
|
||||
logger.LogInformation (
|
||||
"Loading from static field {FieldAssembly}.{FieldDeclaringType}.{FieldName} (type {FieldType})",
|
||||
declaring.Assembly.Name,
|
||||
field.DeclaringType.Assembly.Name,
|
||||
declaring.Name,
|
||||
field.Name,
|
||||
field.Signature
|
||||
)
|
||||
|
||||
match IlMachineState.loadClass loggerFactory declaringType thread state with
|
||||
match IlMachineState.loadClass loggerFactory field.DeclaringType thread state with
|
||||
| FirstLoadThis state -> state, WhatWeDid.SuspendedForClassInit
|
||||
| NothingToDo state ->
|
||||
|
||||
let fieldValue, state =
|
||||
match state.Statics.TryGetValue declaringType with
|
||||
| false, _ ->
|
||||
match state.GetStatic field.DeclaringType field.Name with
|
||||
| None ->
|
||||
let state, newVal =
|
||||
IlMachineState.cliTypeZeroOf
|
||||
loggerFactory
|
||||
activeAssy
|
||||
field.Signature
|
||||
(declaringType.Generics |> ImmutableArray.CreateRange)
|
||||
(field.DeclaringType.Generics |> ImmutableArray.CreateRange)
|
||||
state
|
||||
|
||||
newVal, state.SetStatic declaringType field.Name newVal
|
||||
| true, v ->
|
||||
match v.TryGetValue field.Name with
|
||||
| true, v -> v, state
|
||||
| false, _ ->
|
||||
let state, newVal =
|
||||
IlMachineState.cliTypeZeroOf
|
||||
loggerFactory
|
||||
activeAssy
|
||||
field.Signature
|
||||
(declaringType.Generics |> ImmutableArray.CreateRange)
|
||||
state
|
||||
|
||||
newVal, state.SetStatic declaringType field.Name newVal
|
||||
newVal, state.SetStatic field.DeclaringType field.Name newVal
|
||||
| Some v -> v, state
|
||||
|
||||
do
|
||||
let logger = loggerFactory.CreateLogger "Ldsfld"
|
||||
let declaring = state.ActiveAssembly(thread).TypeDefs.[field.DeclaringType]
|
||||
|
||||
let declaring =
|
||||
state
|
||||
.LoadedAssembly(field.DeclaringType.Assembly)
|
||||
.Value.TypeDefs.[field.DeclaringType.Definition.Get]
|
||||
|
||||
logger.LogInformation (
|
||||
"Loaded from static field {FieldAssembly}.{FieldDeclaringType}.{FieldName} (type {FieldType}), value {LoadedValue}",
|
||||
declaring.Assembly.Name,
|
||||
field.DeclaringType.Assembly.Name,
|
||||
declaring.Name,
|
||||
field.Name,
|
||||
field.Signature,
|
||||
@@ -578,47 +579,42 @@ module internal UnaryMetadataIlOp =
|
||||
|
||||
// TODO: check whether we should throw FieldAccessException
|
||||
|
||||
let field, declaringType =
|
||||
let field =
|
||||
match metadataToken with
|
||||
| MetadataToken.FieldDefinition fieldHandle ->
|
||||
match activeAssy.Fields.TryGetValue fieldHandle with
|
||||
| false, _ -> failwith "TODO: Ldsflda - throw MissingFieldException"
|
||||
| true, field ->
|
||||
// FieldDefinition is not found on generic type
|
||||
field, ConcreteType.make activeAssy.Name field.DeclaringType []
|
||||
field
|
||||
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "generics not allowed on FieldDefinition")
|
||||
| t -> failwith $"Unexpectedly asked to load a non-field: {t}"
|
||||
|
||||
match IlMachineState.loadClass loggerFactory declaringType thread state with
|
||||
match IlMachineState.loadClass loggerFactory field.DeclaringType thread state with
|
||||
| FirstLoadThis state -> state, WhatWeDid.SuspendedForClassInit
|
||||
| NothingToDo state ->
|
||||
|
||||
if TypeDefn.isManaged field.Signature then
|
||||
let allocateStatic () =
|
||||
match state.GetStatic field.DeclaringType field.Name with
|
||||
| Some v ->
|
||||
IlMachineState.pushToEvalStack v thread state
|
||||
|> IlMachineState.advanceProgramCounter thread
|
||||
|> Tuple.withRight WhatWeDid.Executed
|
||||
| None ->
|
||||
// Field is not yet initialised
|
||||
let state, zero =
|
||||
IlMachineState.cliTypeZeroOf
|
||||
loggerFactory
|
||||
activeAssy
|
||||
field.Signature
|
||||
(declaringType.Generics |> ImmutableArray.CreateRange)
|
||||
(field.DeclaringType.Generics |> ImmutableArray.CreateRange)
|
||||
state
|
||||
|
||||
state.SetStatic declaringType field.Name zero
|
||||
state.SetStatic field.DeclaringType field.Name zero
|
||||
|> IlMachineState.pushToEvalStack (CliType.ObjectRef None) thread
|
||||
|> Tuple.withRight WhatWeDid.Executed
|
||||
|
||||
match state.Statics.TryGetValue declaringType with
|
||||
| true, v ->
|
||||
match v.TryGetValue field.Name with
|
||||
| true, v ->
|
||||
IlMachineState.pushToEvalStack v thread state
|
||||
|> IlMachineState.advanceProgramCounter thread
|
||||
|> Tuple.withRight WhatWeDid.Executed
|
||||
| false, _ ->
|
||||
// Field has not yet been initialised.
|
||||
allocateStatic ()
|
||||
| false, _ -> allocateStatic ()
|
||||
else
|
||||
failwith "TODO: Ldsflda - push unmanaged pointer"
|
||||
|
||||
| Ldftn -> failwith "TODO: Ldftn unimplemented"
|
||||
| Stobj -> failwith "TODO: Stobj unimplemented"
|
||||
| Constrained -> failwith "TODO: Constrained unimplemented"
|
||||
|
@@ -18,8 +18,8 @@
|
||||
<Compile Include="ComparableTypeDefinitionHandle.fs" />
|
||||
<Compile Include="ComparableSignatureHeader.fs" />
|
||||
<Compile Include="TypeDefn.fs" />
|
||||
<Compile Include="FieldInfo.fs" />
|
||||
<Compile Include="ConcreteType.fs" />
|
||||
<Compile Include="FieldInfo.fs" />
|
||||
<Compile Include="MethodInfo.fs" />
|
||||
<Compile Include="TypeInfo.fs" />
|
||||
<Compile Include="MethodSpec.fs" />
|
||||
|
Reference in New Issue
Block a user