Better generics handling (#38)

This commit is contained in:
Patrick Stevens
2025-06-02 22:06:53 +01:00
committed by GitHub
parent 3ac37776df
commit fbae38acee
14 changed files with 288 additions and 55 deletions

View File

@@ -56,6 +56,12 @@ module TestCases =
NativeImpls = NativeImpls.PassThru ()
LocalVariablesOfMain = []
}
{
FileName = "ResizeArray.cs"
ExpectedReturnCode = 109
NativeImpls = MockEnv.make ()
LocalVariablesOfMain = [ CliType.Numeric (CliNumericType.Int32 10) ]
}
]
let cases : TestCase list =

View File

@@ -311,7 +311,7 @@ module Assembly =
(fun i ->
let i = i + 1
let handle = MetadataTokens.MethodSpecificationHandle i
KeyValuePair (handle, MethodSpec.make (metadataReader.GetMethodSpecification handle))
KeyValuePair (handle, MethodSpec.make assy.Name (metadataReader.GetMethodSpecification handle))
)
|> ImmutableDictionary.CreateRange
@@ -320,7 +320,7 @@ module Assembly =
for i = 1 to metadataReader.GetTableRowCount TableIndex.TypeSpec do
let handle = MetadataTokens.TypeSpecificationHandle i
result.Add (handle, metadataReader.GetTypeSpecification handle |> TypeSpec.make handle)
result.Add (handle, metadataReader.GetTypeSpecification handle |> TypeSpec.make assy.Name handle)
result.ToImmutable ()
@@ -334,6 +334,7 @@ module Assembly =
metadataReader.GetBlobReader
metadataReader.GetString
MetadataToken.ofEntityHandle
assy.Name
(metadataReader.GetMemberReference c)
)

View File

@@ -141,7 +141,7 @@ module CliType =
| TypeResolutionResult.FirstLoadAssy assy -> CliTypeResolutionResult.FirstLoad assy
| SignatureTypeKind.Class -> CliType.ObjectRef None |> CliTypeResolutionResult.Resolved
| _ -> raise (ArgumentOutOfRangeException ())
| TypeDefn.FromDefinition (typeDefinitionHandle, signatureTypeKind) ->
| TypeDefn.FromDefinition (typeDefinitionHandle, _, signatureTypeKind) ->
match signatureTypeKind with
| SignatureTypeKind.Unknown -> failwith "todo"
| SignatureTypeKind.ValueType ->

View File

@@ -59,7 +59,12 @@ type RuntimeConcreteType = ConcreteType<TypeDefn>
[<RequireQualifiedAccess>]
module ConcreteType =
let make (assemblyName : AssemblyName) (defn : TypeDefinitionHandle) (generics : TypeDefn list) =
let make
(assemblyName : AssemblyName)
(defn : TypeDefinitionHandle)
(generics : TypeDefn list)
: RuntimeConcreteType
=
{
_AssemblyName = assemblyName
_Definition = ComparableTypeDefinitionHandle.Make defn

View File

@@ -29,9 +29,81 @@ module Corelib =
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "ValueType" then Some v else None)
|> Seq.exactlyOne
let boolean =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Boolean" then Some v else None)
|> Seq.exactlyOne
let char =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Char" then Some v else None)
|> Seq.exactlyOne
let byte =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Byte" then Some v else None)
|> Seq.exactlyOne
let sbyte =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "SByte" then Some v else None)
|> Seq.exactlyOne
let int16 =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Int16" then Some v else None)
|> Seq.exactlyOne
let int32 =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Int32" then Some v else None)
|> Seq.exactlyOne
let int64 =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Int64" then Some v else None)
|> Seq.exactlyOne
let uint16 =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "UInt16" then Some v else None)
|> Seq.exactlyOne
let uint32 =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "UInt32" then Some v else None)
|> Seq.exactlyOne
let uint64 =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "UInt64" then Some v else None)
|> Seq.exactlyOne
let single =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Single" then Some v else None)
|> Seq.exactlyOne
let double =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "Double" then Some v else None)
|> Seq.exactlyOne
{
Corelib = corelib
String = stringType
Boolean = boolean
Char = char
SByte = sbyte
Byte = byte
Int16 = int16
UInt16 = uint16
Int32 = int32
UInt32 = uint32
Int64 = int64
UInt64 = uint64
Single = single
Double = double
Array = arrayType
Enum = enumType
ValueType = valueType

View File

@@ -45,14 +45,15 @@ module FieldInfo =
: FieldInfo<FakeUnit>
=
let name = mr.GetString def.Name
let fieldSig = def.DecodeSignature (TypeDefn.typeProvider, ())
let fieldSig = def.DecodeSignature (TypeDefn.typeProvider assembly, ())
let declaringType = def.GetDeclaringType ()
let typeGenerics = mr.GetTypeDefinition(declaringType).GetGenericParameters().Count
let declaringType = ConcreteType.make' assembly declaringType typeGenerics
{
Name = name
Signature = fieldSig
DeclaringType = ConcreteType.make' assembly declaringType typeGenerics
DeclaringType = declaringType
Handle = handle
Attributes = def.Attributes
}
@@ -63,10 +64,12 @@ module FieldInfo =
(input : FieldInfo<'a>)
: FieldInfo<'b>
=
let declaringType = input.DeclaringType |> ConcreteType.mapGeneric f
{
Handle = input.Handle
Name = input.Name
DeclaringType = input.DeclaringType |> ConcreteType.mapGeneric f
DeclaringType = declaringType
Signature = input.Signature
Attributes = input.Attributes

View File

@@ -276,6 +276,7 @@ module IlMachineState =
let rec resolveTypeFromDefn
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(ty : TypeDefn)
(genericArgs : ImmutableArray<TypeDefn> option)
(assy : DumpedAssembly)
@@ -284,8 +285,45 @@ module IlMachineState =
=
match ty with
| TypeDefn.GenericInstantiation (generic, args) ->
resolveTypeFromDefn loggerFactory generic (Some args) assy state
| TypeDefn.FromDefinition (defn, _typeKind) ->
let args' = ImmutableArray.CreateBuilder ()
let state =
(state, args)
||> Seq.fold (fun state arg ->
let state, assy, arg =
resolveTypeFromDefn loggerFactory corelib arg genericArgs assy state
let baseType =
arg.BaseType
|> TypeInfo.resolveBaseType
(fun (x : DumpedAssembly) -> x.Name)
(fun x y -> x.TypeDefs.[y])
corelib
assy.Name
let signatureTypeKind =
match baseType with
| ResolvedBaseType.Enum
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
| ResolvedBaseType.Object -> SignatureTypeKind.Class
| ResolvedBaseType.Delegate -> failwith "TODO: delegate"
args'.Add (
TypeDefn.FromDefinition (
ComparableTypeDefinitionHandle.Make arg.TypeDefHandle,
assy.Name.FullName,
signatureTypeKind
)
)
state
)
let args' = args'.ToImmutable ()
resolveTypeFromDefn loggerFactory corelib generic (Some args') assy state
| TypeDefn.FromDefinition (defn, assy, _typeKind) ->
let assy = state._LoadedAssemblies.[assy]
let defn =
assy.TypeDefs.[defn.Get]
|> TypeInfo.mapGeneric (fun param ->
@@ -298,17 +336,48 @@ module IlMachineState =
| TypeDefn.FromReference (ref, _typeKind) ->
let state, assy, ty = resolveTypeFromRef loggerFactory assy ref genericArgs state
state, assy, ty
| TypeDefn.PrimitiveType prim ->
let ty =
match prim with
| PrimitiveType.Boolean -> corelib.Boolean
| PrimitiveType.Char -> corelib.Char
| PrimitiveType.SByte -> corelib.SByte
| PrimitiveType.Byte -> corelib.Byte
| PrimitiveType.Int16 -> corelib.Int16
| PrimitiveType.UInt16 -> corelib.UInt16
| PrimitiveType.Int32 -> corelib.Int32
| PrimitiveType.UInt32 -> corelib.UInt32
| PrimitiveType.Int64 -> corelib.Int64
| PrimitiveType.UInt64 -> corelib.UInt64
| PrimitiveType.Single -> corelib.Single
| PrimitiveType.Double -> corelib.Double
| PrimitiveType.String -> corelib.String
| PrimitiveType.TypedReference -> failwith "todo"
| PrimitiveType.IntPtr -> failwith "todo"
| PrimitiveType.UIntPtr -> failwith "todo"
| PrimitiveType.Object -> failwith "todo"
|> TypeInfo.mapGeneric (fun _ -> failwith "none of these types are generic")
state, corelib.Corelib, ty
| TypeDefn.GenericTypeParameter param ->
match genericArgs with
| None -> failwith "tried to resolve generic parameter without generic args"
| Some genericArgs ->
let arg = genericArgs.[param]
// TODO: this assembly is probably wrong?
resolveTypeFromDefn loggerFactory corelib arg (Some genericArgs) assy state
| s -> failwith $"TODO: resolveTypeFromDefn unimplemented for {s}"
let resolveTypeFromSpec
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(ty : TypeSpecificationHandle)
(assy : DumpedAssembly)
(typeGenericArgs : TypeDefn ImmutableArray option)
(state : IlMachineState)
: IlMachineState * DumpedAssembly * WoofWare.PawPrint.TypeInfo<TypeDefn>
=
// Any necessary generics will be baked into the TypeDefn e.g. as a `GenericInstantiation`.
resolveTypeFromDefn loggerFactory assy.TypeSpecs.[ty].Signature None assy state
resolveTypeFromDefn loggerFactory corelib assy.TypeSpecs.[ty].Signature typeGenericArgs assy state
let rec cliTypeZeroOf
(loggerFactory : ILoggerFactory)
@@ -888,6 +957,8 @@ module IlMachineState =
let resolveMember
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(currentThread : ThreadId)
(assy : DumpedAssembly)
(m : MemberReferenceHandle)
(state : IlMachineState)
@@ -903,7 +974,13 @@ module IlMachineState =
let state, assy, targetType =
match mem.Parent with
| MetadataToken.TypeReference parent -> resolveType loggerFactory parent None assy state
| MetadataToken.TypeSpecification parent -> resolveTypeFromSpec loggerFactory parent assy state
| MetadataToken.TypeSpecification parent ->
let typeGenerics =
match state.ThreadState.[currentThread].MethodState.ExecutingMethod.DeclaringType.Generics with
| [] -> None
| l -> Some (ImmutableArray.CreateRange l)
resolveTypeFromSpec loggerFactory corelib parent assy typeGenerics state
| parent -> failwith $"Unexpected: {parent}"
match mem.Signature with

View File

@@ -1,6 +1,7 @@
namespace WoofWare.PawPrint
open System
open System.Reflection
open System.Reflection.Metadata
type MemberSignature =
@@ -35,6 +36,7 @@ module MemberReference =
(blobReader : BlobHandle -> BlobReader)
(getString : StringHandle -> string)
(makeParent : EntityHandle -> 'parent)
(assemblyName : AssemblyName)
(mr : System.Reflection.Metadata.MemberReference)
: MemberReference<'parent>
=
@@ -45,8 +47,8 @@ module MemberReference =
let signature =
match header.Kind with
| SignatureKind.Method -> mr.DecodeMethodSignature (TypeDefn.typeProvider, ()) |> Choice1Of2
| SignatureKind.Field -> mr.DecodeFieldSignature (TypeDefn.typeProvider, ()) |> Choice2Of2
| SignatureKind.Method -> mr.DecodeMethodSignature (TypeDefn.typeProvider assemblyName, ()) |> Choice1Of2
| SignatureKind.Field -> mr.DecodeFieldSignature (TypeDefn.typeProvider assemblyName, ()) |> Choice2Of2
| SignatureKind.LocalVariables -> failwith "TODO: LocalVariables"
| SignatureKind.Property -> failwith "TODO: Property"
| SignatureKind.MethodSpecification -> failwith "TODO: MethodSpec"

View File

@@ -263,6 +263,7 @@ module MethodInfo =
let private readMethodBody
(peReader : PEReader)
(metadataReader : MetadataReader)
(assembly : AssemblyName)
(methodDef : MethodDefinition)
: MethodBody option
=
@@ -277,7 +278,7 @@ module MethodInfo =
else
let s = methodBody.LocalSignature |> metadataReader.GetStandaloneSignature
s.DecodeLocalSignature (TypeDefn.typeProvider, ()) |> Some
s.DecodeLocalSignature (TypeDefn.typeProvider assembly, ()) |> Some
let ilBytes = methodBody.GetILBytes ()
use bytes = fixed ilBytes
@@ -584,7 +585,7 @@ module MethodInfo =
let assemblyName = metadataReader.GetAssemblyDefinition().GetAssemblyName ()
let methodDef = metadataReader.GetMethodDefinition methodHandle
let methodName = metadataReader.GetString methodDef.Name
let methodSig = methodDef.DecodeSignature (TypeDefn.typeProvider, ())
let methodSig = methodDef.DecodeSignature (TypeDefn.typeProvider assemblyName, ())
let implAttrs = methodDef.ImplAttributes
let methodBody =
@@ -596,7 +597,7 @@ module MethodInfo =
elif methodDef.Attributes.HasFlag MethodAttributes.PinvokeImpl then
None
else
match readMethodBody peReader metadataReader methodDef with
match readMethodBody peReader metadataReader assemblyName methodDef with
| None ->
logger.LogTrace $"no method body in {assemblyName.Name} {methodName}"
None
@@ -682,7 +683,7 @@ module MethodInfo =
| TypeDefn.OneDimensionalArrayLowerBoundZero elements -> failwith "todo"
| TypeDefn.Modified (original, afterMod, modificationRequired) -> failwith "todo"
| TypeDefn.FromReference (typeRef, signatureTypeKind) -> failwith "todo"
| TypeDefn.FromDefinition (comparableTypeDefinitionHandle, signatureTypeKind) -> failwith "todo"
| TypeDefn.FromDefinition (comparableTypeDefinitionHandle, _, signatureTypeKind) -> failwith "todo"
| TypeDefn.GenericInstantiation (generic, args) -> failwith "todo"
| TypeDefn.FunctionPointer typeMethodSignature -> failwith "todo"
| TypeDefn.GenericTypeParameter index ->

View File

@@ -1,6 +1,7 @@
namespace WoofWare.PawPrint
open System.Collections.Immutable
open System.Reflection
open System.Reflection.Metadata
/// <summary>
@@ -19,8 +20,8 @@ type MethodSpec =
[<RequireQualifiedAccess>]
module MethodSpec =
let make (p : MethodSpecification) : MethodSpec =
let signature = p.DecodeSignature (TypeDefn.typeProvider, ())
let make (assemblyName : AssemblyName) (p : MethodSpecification) : MethodSpec =
let signature = p.DecodeSignature (TypeDefn.typeProvider assemblyName, ())
{
// Horrible abuse to get this as an int

View File

@@ -1,6 +1,7 @@
namespace WoofWare.PawPrint
open System.Collections.Immutable
open System.Reflection
open System.Reflection.Metadata
open System.Reflection.Metadata.Ecma335
open Microsoft.FSharp.Core
@@ -106,7 +107,7 @@ type TypeDefn =
| OneDimensionalArrayLowerBoundZero of elements : TypeDefn
| Modified of original : TypeDefn * afterMod : TypeDefn * modificationRequired : bool
| FromReference of TypeRef * SignatureTypeKind
| FromDefinition of ComparableTypeDefinitionHandle * SignatureTypeKind
| FromDefinition of ComparableTypeDefinitionHandle * assemblyFullName : string * SignatureTypeKind
| GenericInstantiation of generic : TypeDefn * args : ImmutableArray<TypeDefn>
| FunctionPointer of TypeMethodSignature<TypeDefn>
| GenericTypeParameter of index : int
@@ -126,7 +127,7 @@ module TypeDefn =
| TypeDefn.OneDimensionalArrayLowerBoundZero elements -> failwith "todo"
| TypeDefn.Modified (original, afterMod, modificationRequired) -> failwith "todo"
| TypeDefn.FromReference _ -> true
| TypeDefn.FromDefinition (_, signatureTypeKind) ->
| TypeDefn.FromDefinition (_, _, signatureTypeKind) ->
match signatureTypeKind with
| SignatureTypeKind.Unknown -> failwith "todo"
| SignatureTypeKind.ValueType -> false
@@ -174,7 +175,7 @@ module TypeDefn =
| SignatureTypeCode.Pinned -> failwith "todo"
| x -> failwith $"Unrecognised type code: {x}"
let typeProvider : ISignatureTypeProvider<TypeDefn, unit> =
let typeProvider (a : AssemblyName) : ISignatureTypeProvider<TypeDefn, unit> =
{ new ISignatureTypeProvider<TypeDefn, unit> with
member this.GetArrayType (elementType : TypeDefn, shape : ArrayShape) : TypeDefn =
TypeDefn.Array (elementType, ())
@@ -202,7 +203,7 @@ module TypeDefn =
let handle' : EntityHandle = TypeDefinitionHandle.op_Implicit handle
let typeKind = reader.ResolveSignatureTypeKind (handle', rawTypeKind)
TypeDefn.FromDefinition (ComparableTypeDefinitionHandle.Make handle, typeKind)
TypeDefn.FromDefinition (ComparableTypeDefinitionHandle.Make handle, a.FullName, typeKind)
member this.GetTypeFromReference
(reader : MetadataReader, handle : TypeReferenceHandle, rawTypeKind : byte)

View File

@@ -97,6 +97,18 @@ type BaseClassTypes<'corelib> =
{
Corelib : 'corelib
String : TypeInfo<WoofWare.PawPrint.GenericParameter>
Boolean : TypeInfo<WoofWare.PawPrint.GenericParameter>
Char : TypeInfo<WoofWare.PawPrint.GenericParameter>
SByte : TypeInfo<WoofWare.PawPrint.GenericParameter>
Byte : TypeInfo<WoofWare.PawPrint.GenericParameter>
Int16 : TypeInfo<WoofWare.PawPrint.GenericParameter>
UInt16 : TypeInfo<WoofWare.PawPrint.GenericParameter>
Int32 : TypeInfo<WoofWare.PawPrint.GenericParameter>
UInt32 : TypeInfo<WoofWare.PawPrint.GenericParameter>
Int64 : TypeInfo<WoofWare.PawPrint.GenericParameter>
UInt64 : TypeInfo<WoofWare.PawPrint.GenericParameter>
Single : TypeInfo<WoofWare.PawPrint.GenericParameter>
Double : TypeInfo<WoofWare.PawPrint.GenericParameter>
Array : TypeInfo<WoofWare.PawPrint.GenericParameter>
Enum : TypeInfo<WoofWare.PawPrint.GenericParameter>
ValueType : TypeInfo<WoofWare.PawPrint.GenericParameter>

View File

@@ -1,5 +1,6 @@
namespace WoofWare.PawPrint
open System.Reflection
open System.Reflection.Metadata
/// <summary>
@@ -23,8 +24,8 @@ type TypeSpec =
[<RequireQualifiedAccess>]
module TypeSpec =
let make (handle : TypeSpecificationHandle) (r : TypeSpecification) : TypeSpec =
let spec = r.DecodeSignature (TypeDefn.typeProvider, ())
let make (assembly : AssemblyName) (handle : TypeSpecificationHandle) (r : TypeSpecification) : TypeSpec =
let spec = r.DecodeSignature (TypeDefn.typeProvider assembly, ())
{
Handle = handle

View File

@@ -2,6 +2,7 @@ namespace WoofWare.PawPrint
open System.Collections.Immutable
open System.Reflection
open System.Reflection.Metadata
open Microsoft.Extensions.Logging
[<RequireQualifiedAccess>]
@@ -33,7 +34,13 @@ module internal UnaryMetadataIlOp =
state, method, Some spec.Signature
| MetadataToken.MemberReference ref ->
let state, _, method =
IlMachineState.resolveMember loggerFactory (state.ActiveAssembly thread) ref state
IlMachineState.resolveMember
loggerFactory
baseClassTypes
thread
(state.ActiveAssembly thread)
ref
state
match method with
| Choice2Of2 _field -> failwith "tried to Call a field"
@@ -41,7 +48,13 @@ module internal UnaryMetadataIlOp =
| k -> failwith $"Unrecognised kind: %O{k}"
| MetadataToken.MemberReference h ->
let state, _, method =
IlMachineState.resolveMember loggerFactory (state.ActiveAssembly thread) h state
IlMachineState.resolveMember
loggerFactory
baseClassTypes
thread
(state.ActiveAssembly thread)
h
state
match method with
| Choice2Of2 _field -> failwith "tried to Call a field"
@@ -140,7 +153,13 @@ module internal UnaryMetadataIlOp =
state, activeAssy.Name, MethodInfo.mapTypeGenerics (fun _ -> failwith "non-generic method") method
| MemberReference mr ->
let state, name, method =
IlMachineState.resolveMember loggerFactory (state.ActiveAssembly thread) mr state
IlMachineState.resolveMember
loggerFactory
baseClassTypes
thread
(state.ActiveAssembly thread)
mr
state
match method with
| Choice1Of2 mr -> state, name, mr
@@ -217,38 +236,47 @@ module internal UnaryMetadataIlOp =
| EvalStackValue.Int32 v -> v
| popped -> failwith $"unexpectedly popped value %O{popped} to serve as array len"
let baseType =
let elementType, assy =
match metadataToken with
| MetadataToken.TypeDefinition defn ->
let assy = state.LoadedAssembly currentState.ActiveAssembly |> Option.get
let elementType = assy.TypeDefs.[defn]
let defn = assy.TypeDefs.[defn]
let baseType =
elementType.BaseType
defn.BaseType
|> TypeInfo.resolveBaseType
(fun (x : DumpedAssembly) -> x.Name)
(fun x y -> x.TypeDefs.[y])
baseClassTypes
elementType.Assembly
defn.Assembly
baseType
let signatureTypeKind =
match baseType with
| ResolvedBaseType.Enum
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
| ResolvedBaseType.Object -> SignatureTypeKind.Class
| ResolvedBaseType.Delegate -> failwith "TODO: delegate"
TypeDefn.FromDefinition (
ComparableTypeDefinitionHandle.Make defn.TypeDefHandle,
defn.Assembly.Name,
signatureTypeKind
),
assy
| MetadataToken.TypeSpecification spec ->
let assy = state.LoadedAssembly currentState.ActiveAssembly |> Option.get
let elementType = assy.TypeSpecs.[spec].Signature
MethodInfo.resolveBaseType newMethodState.Generics newMethodState.ExecutingMethod elementType
assy.TypeSpecs.[spec].Signature, assy
| x -> failwith $"TODO: Newarr element type resolution unimplemented for {x}"
let zeroOfType =
match baseType with
| ResolvedBaseType.Object ->
// initialise with null references
fun () -> CliType.ObjectRef None
| ResolvedBaseType.Enum -> failwith "TODO: Newarr Enum array initialization unimplemented"
| ResolvedBaseType.ValueType -> failwith "TODO: Newarr ValueType array initialization unimplemented"
| ResolvedBaseType.Delegate -> failwith "TODO: Newarr Delegate array initialization unimplemented"
let typeGenerics =
match newMethodState.ExecutingMethod.DeclaringType.Generics with
| [] -> None
| l -> Some (ImmutableArray.CreateRange l)
let alloc, state = IlMachineState.allocateArray zeroOfType len state
let state, zeroOfType =
IlMachineState.cliTypeZeroOf loggerFactory assy elementType typeGenerics newMethodState.Generics state
let alloc, state = IlMachineState.allocateArray (fun () -> zeroOfType) len state
let state =
{ state with
@@ -284,14 +312,21 @@ module internal UnaryMetadataIlOp =
| Stfld ->
let activeAssy = state.ActiveAssembly thread
let state, declaringType, field =
let state, field =
match metadataToken with
| MetadataToken.FieldDefinition f ->
let field =
activeAssy.Fields.[f]
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "no generics allowed in FieldDefinition")
state, field.DeclaringType, field
state, field
| MetadataToken.MemberReference mr ->
let state, _, field =
IlMachineState.resolveMember loggerFactory baseClassTypes thread activeAssy mr state
match field with
| Choice1Of2 _method -> failwith "member reference was unexpectedly a method"
| Choice2Of2 field -> state, field
| t -> failwith $"Unexpectedly asked to store to a non-field: {t}"
do
@@ -308,7 +343,7 @@ module internal UnaryMetadataIlOp =
let valueToStore, state = IlMachineState.popEvalStack thread state
let typeGenerics =
match declaringType.Generics with
match field.DeclaringType.Generics with
| [] -> None
| l -> Some (ImmutableArray.CreateRange l)
@@ -326,7 +361,7 @@ module internal UnaryMetadataIlOp =
let currentObj, state = IlMachineState.popEvalStack thread state
if field.Attributes.HasFlag FieldAttributes.Static then
let state = state.SetStatic declaringType field.Name valueToStore
let state = state.SetStatic field.DeclaringType field.Name valueToStore
state, WhatWeDid.Executed
else
@@ -381,7 +416,13 @@ module internal UnaryMetadataIlOp =
state, field
| MetadataToken.MemberReference mr ->
let state, _, method =
IlMachineState.resolveMember loggerFactory (state.ActiveAssembly thread) mr state
IlMachineState.resolveMember
loggerFactory
baseClassTypes
thread
(state.ActiveAssembly thread)
mr
state
match method with
| Choice1Of2 methodInfo ->
@@ -444,7 +485,7 @@ module internal UnaryMetadataIlOp =
state, field
| MetadataToken.MemberReference mr ->
let state, assyName, field =
IlMachineState.resolveMember loggerFactory activeAssembly mr state
IlMachineState.resolveMember loggerFactory baseClassTypes thread activeAssembly mr state
match field with
| Choice1Of2 _method -> failwith "member reference was unexpectedly a method"
@@ -523,14 +564,24 @@ module internal UnaryMetadataIlOp =
let activeAssy = state.ActiveAssembly thread
let field =
let state, field =
match metadataToken with
| MetadataToken.FieldDefinition fieldHandle ->
match activeAssy.Fields.TryGetValue fieldHandle with
| false, _ -> failwith "TODO: Ldsfld - throw MissingFieldException"
| true, field ->
field
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "generics not allowed in FieldDefinition")
let field =
field
|> FieldInfo.mapTypeGenerics (fun _ _ -> failwith "generics not allowed in FieldDefinition")
state, field
| MetadataToken.MemberReference mr ->
let state, _, field =
IlMachineState.resolveMember loggerFactory baseClassTypes thread activeAssy mr state
match field with
| Choice1Of2 _method -> failwith "member reference was unexpectedly a method"
| Choice2Of2 field -> state, field
| t -> failwith $"Unexpectedly asked to load from a non-field: {t}"
do