Implement Ldtoken for fields (#94)

This commit is contained in:
Patrick Stevens
2025-07-05 22:21:58 +01:00
committed by GitHub
parent 56d1cf63d6
commit 3af1f2cc97
23 changed files with 830 additions and 345 deletions

View File

@@ -182,3 +182,47 @@ When encountering errors:
4. Add logging to see generic contexts: `failwithf "Failed to concretize: %A" typeDefn`
5. Check if you're in a generic method calling another generic method
6. Verify TypeRefs are being resolved in the correct assembly
## Common Type System Patterns
### Creating TypeDefn from Type Metadata
When you need to create a `TypeDefn` from type metadata (e.g., from a `TypeInfo`), there's a common pattern that involves:
1. Resolving the base type to determine `SignatureTypeKind`
2. Creating the base `TypeDefn.FromDefinition`
3. For generic types, creating a `GenericInstantiation` with type parameters
This pattern is implemented in `UnaryMetadataIlOp.lookupTypeDefn`. Example usage:
```fsharp
let state, typeDefn =
UnaryMetadataIlOp.lookupTypeDefn
baseClassTypes
state
activeAssembly
typeDefHandle
```
### Field Signature Comparison in Generic Contexts
When comparing field signatures in generic contexts (e.g., when resolving member references), signatures must be concretized before comparison. This ensures generic type parameters are properly substituted:
```fsharp
// Concretize both signatures before comparing
let state, concreteFieldSig = concretizeType ... fieldSig
let state, fieldSigConcrete = concretizeType ... fi.Signature
if fieldSigConcrete = concreteFieldSig then ...
```
### Static vs Instance Fields
When constructing objects with `Newobj`:
- Only instance fields should be included in the object
- Static fields belong to the type, not instances
- Filter using: `field.Attributes.HasFlag FieldAttributes.Static`
Example:
```fsharp
let instanceFields =
ctorType.Fields
|> List.filter (fun field -> not (field.Attributes.HasFlag FieldAttributes.Static))
```

View File

@@ -0,0 +1,37 @@
namespace WoofWare.PawPrint
open System
open System.Reflection.Metadata
[<CustomEquality>]
[<CustomComparison>]
type ComparableFieldDefinitionHandle =
private
{
_Inner : FieldDefinitionHandle
}
override this.Equals other =
match other with
| :? ComparableFieldDefinitionHandle as other -> this._Inner.GetHashCode () = other._Inner.GetHashCode ()
| _ -> false
override this.GetHashCode () : int = this._Inner.GetHashCode ()
interface IComparable<ComparableFieldDefinitionHandle> with
member this.CompareTo (other : ComparableFieldDefinitionHandle) : int =
this._Inner.GetHashCode().CompareTo (other._Inner.GetHashCode ())
interface IComparable with
member this.CompareTo (other : obj) : int =
match other with
| :? ComparableFieldDefinitionHandle as other ->
(this :> IComparable<ComparableFieldDefinitionHandle>).CompareTo other
| _ -> failwith "invalid comparison"
static member Make (h : FieldDefinitionHandle) =
{
_Inner = h
}
member this.Get = this._Inner

View File

@@ -11,7 +11,7 @@ type ComparableTypeDefinitionHandle =
_Inner : TypeDefinitionHandle
}
override this.Equals (other) =
override this.Equals other =
match other with
| :? ComparableTypeDefinitionHandle as other -> this._Inner.GetHashCode () = other._Inner.GetHashCode ()
| _ -> false

View File

@@ -36,6 +36,8 @@ type FieldInfo<'typeGeneric, 'fieldGeneric when 'typeGeneric : comparison and 't
Attributes : FieldAttributes
}
member this.HasFieldRVA = this.Attributes.HasFlag FieldAttributes.HasFieldRVA
override this.ToString () : string =
$"%s{this.DeclaringType.Assembly.Name}.{this.DeclaringType.Name}.%s{this.Name}"
@@ -52,7 +54,7 @@ module FieldInfo =
let fieldSig = def.DecodeSignature (TypeDefn.typeProvider assembly, ())
let declaringType = def.GetDeclaringType ()
let typeGenerics = mr.GetTypeDefinition(declaringType).GetGenericParameters().Count
let decType = mr.GetTypeDefinition (declaringType)
let decType = mr.GetTypeDefinition declaringType
let declaringTypeNamespace = mr.GetString decType.Namespace
let declaringTypeName = mr.GetString decType.Name

View File

@@ -1,5 +1,6 @@
namespace WoofWare.PawPrint
open System
open System.Collections.Immutable
open System.Reflection
open System.Reflection.Metadata
@@ -81,10 +82,72 @@ module AllConcreteTypes =
toRet, newState
// Active patterns for matching concrete types
[<AutoOpen>]
module ConcreteActivePatterns =
/// Active pattern to match primitive types from concrete type handles
let (|ConcretePrimitive|_|) (concreteTypes : AllConcreteTypes) (handle : ConcreteTypeHandle) =
match handle with
| ConcreteTypeHandle.Concrete id ->
match concreteTypes.Mapping |> Map.tryFind id with
| Some ct when ct.Namespace = "System" && ct.Generics.IsEmpty ->
match ct.Name with
| "Int32" -> Some PrimitiveType.Int32
| "Int64" -> Some PrimitiveType.Int64
| "Int16" -> Some PrimitiveType.Int16
| "UInt32" -> Some PrimitiveType.UInt32
| "UInt64" -> Some PrimitiveType.UInt64
| "UInt16" -> Some PrimitiveType.UInt16
| "Byte" -> Some PrimitiveType.Byte
| "SByte" -> Some PrimitiveType.SByte
| "Single" -> Some PrimitiveType.Single
| "Double" -> Some PrimitiveType.Double
| "String" -> Some PrimitiveType.String
| "Boolean" -> Some PrimitiveType.Boolean
| "Char" -> Some PrimitiveType.Char
| "Object" -> Some PrimitiveType.Object
| "IntPtr" -> Some PrimitiveType.IntPtr
| "UIntPtr" -> Some PrimitiveType.UIntPtr
| "TypedReference" -> Some PrimitiveType.TypedReference
| _ -> None
| _ -> None
| _ -> None
/// Active pattern to match void type
let (|ConcreteVoid|_|) (concreteTypes : AllConcreteTypes) (handle : ConcreteTypeHandle) =
match handle with
| ConcreteTypeHandle.Concrete id ->
match concreteTypes.Mapping |> Map.tryFind id with
| Some ct when ct.Namespace = "System" && ct.Name = "Void" && ct.Generics.IsEmpty -> Some ()
| _ -> None
| _ -> None
/// Active pattern to match any concrete type by assembly/namespace/name and generics
let (|ConcreteType|_|) (concreteTypes : AllConcreteTypes) (handle : ConcreteTypeHandle) =
match handle with
| ConcreteTypeHandle.Concrete id ->
match concreteTypes.Mapping |> Map.tryFind id with
| Some ct -> Some (ct.Assembly.Name, ct.Namespace, ct.Name, ct.Generics)
| None -> None
| _ -> None
/// Active pattern to match byref types
let (|ConcreteByref|_|) (handle : ConcreteTypeHandle) =
match handle with
| ConcreteTypeHandle.Byref inner -> Some inner
| _ -> None
/// Active pattern to match pointer types
let (|ConcretePointer|_|) (handle : ConcreteTypeHandle) =
match handle with
| ConcreteTypeHandle.Pointer inner -> Some inner
| _ -> None
[<RequireQualifiedAccess>]
module TypeConcretization =
type ConcretizationContext =
type ConcretizationContext<'corelib> =
{
/// Types currently being processed (to detect cycles)
InProgress : ImmutableDictionary<AssemblyName * TypeDefn, ConcreteTypeHandle>
@@ -92,7 +155,7 @@ module TypeConcretization =
ConcreteTypes : AllConcreteTypes
/// For resolving type references
LoadedAssemblies : ImmutableDictionary<string, DumpedAssembly>
BaseTypes : BaseClassTypes<DumpedAssembly>
BaseTypes : BaseClassTypes<'corelib>
}
// Helper function to find existing types by assembly, namespace, name, and generics
@@ -128,13 +191,13 @@ module TypeConcretization =
// Helper function to create and add a ConcreteType to the context
let private createAndAddConcreteType
(ctx : ConcretizationContext)
(ctx : ConcretizationContext<'corelib>)
(assembly : AssemblyName)
(definition : ComparableTypeDefinitionHandle)
(ns : string)
(name : string)
(generics : ConcreteTypeHandle ImmutableArray)
: ConcreteTypeHandle * ConcretizationContext
: ConcreteTypeHandle * ConcretizationContext<'corelib>
=
let concreteType =
{
@@ -158,10 +221,10 @@ module TypeConcretization =
let private loadAssemblyAndResolveTypeRef
(loadAssembly :
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(ctx : ConcretizationContext)
(ctx : ConcretizationContext<'corelib>)
(currentAssembly : AssemblyName)
(typeRef : TypeRef)
: (DumpedAssembly * WoofWare.PawPrint.TypeInfo<_, _>) * ConcretizationContext
: (DumpedAssembly * WoofWare.PawPrint.TypeInfo<_, _>) * ConcretizationContext<'corelib>
=
let currentAssy =
match ctx.LoadedAssemblies.TryGetValue currentAssembly.FullName with
@@ -196,9 +259,9 @@ module TypeConcretization =
| _ -> failwith "Unexpected resolution scope"
let private concretizePrimitive
(ctx : ConcretizationContext)
(ctx : ConcretizationContext<'corelib>)
(prim : PrimitiveType)
: ConcreteTypeHandle * ConcretizationContext
: ConcreteTypeHandle * ConcretizationContext<'corelib>
=
// Get the TypeInfo for this primitive from BaseClassTypes
@@ -238,10 +301,10 @@ module TypeConcretization =
ImmutableArray.Empty // Primitives have no generic parameters
let private concretizeArray
(ctx : ConcretizationContext)
(ctx : ConcretizationContext<'corelib>)
(elementHandle : ConcreteTypeHandle)
(shape : 'a)
: ConcreteTypeHandle * ConcretizationContext
: ConcreteTypeHandle * ConcretizationContext<'corelib>
=
// Arrays are System.Array<T> where T is the element type
@@ -268,9 +331,9 @@ module TypeConcretization =
(ImmutableArray.Create elementHandle) // Array<T> has one generic parameter
let private concretizeOneDimArray
(ctx : ConcretizationContext)
(ctx : ConcretizationContext<'corelib>)
(elementHandle : ConcreteTypeHandle)
: ConcreteTypeHandle * ConcretizationContext
: ConcreteTypeHandle * ConcretizationContext<'corelib>
=
// One-dimensional arrays with lower bound 0 are also System.Array<T>
@@ -298,10 +361,10 @@ module TypeConcretization =
(ImmutableArray.Create elementHandle) // Array<T> has one generic parameter
let concretizeTypeDefinition
(ctx : ConcretizationContext)
(ctx : ConcretizationContext<'corelib>)
(assemblyName : AssemblyName)
(typeDefHandle : ComparableTypeDefinitionHandle)
: ConcreteTypeHandle * ConcretizationContext
: ConcreteTypeHandle * ConcretizationContext<'corelib>
=
// Look up the type definition in the assembly
@@ -336,10 +399,10 @@ module TypeConcretization =
let private concretizeTypeReference
(loadAssembly :
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(ctx : ConcretizationContext)
(ctx : ConcretizationContext<'corelib>)
(currentAssembly : AssemblyName)
(typeRef : TypeRef)
: ConcreteTypeHandle * ConcretizationContext
: ConcreteTypeHandle * ConcretizationContext<'corelib>
=
// Use the helper to load assembly and resolve the type reference
let (targetAssy, typeInfo), ctx =
@@ -358,14 +421,14 @@ module TypeConcretization =
/// Concretize a type in a specific generic context
let rec concretizeType
(ctx : ConcretizationContext)
(ctx : ConcretizationContext<'corelib>)
(loadAssembly :
AssemblyName -> AssemblyReferenceHandle -> (ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly))
(assembly : AssemblyName)
(typeGenerics : ConcreteTypeHandle ImmutableArray)
(methodGenerics : ConcreteTypeHandle ImmutableArray)
(typeDefn : TypeDefn)
: ConcreteTypeHandle * ConcretizationContext
: ConcreteTypeHandle * ConcretizationContext<'corelib>
=
let key = (assembly, typeDefn)
@@ -394,13 +457,13 @@ module TypeConcretization =
if index < typeGenerics.Length then
typeGenerics.[index], ctx
else
failwithf "Generic type parameter %d out of range" index
raise (IndexOutOfRangeException $"Generic type parameter %i{index}")
| TypeDefn.GenericMethodParameter index ->
if index < methodGenerics.Length then
methodGenerics.[index], ctx
else
failwithf "Generic method parameter %d out of range" index
raise (IndexOutOfRangeException $"Generic method parameter %i{index}")
| TypeDefn.GenericInstantiation (genericDef, args) ->
concretizeGenericInstantiation ctx loadAssembly assembly typeGenerics methodGenerics genericDef args
@@ -455,15 +518,15 @@ module TypeConcretization =
| _ -> failwithf "TODO: Concretization of %A not implemented" typeDefn
and private concretizeGenericInstantiation
(ctx : ConcretizationContext)
(ctx : ConcretizationContext<'corelib>)
(loadAssembly :
AssemblyName -> AssemblyReferenceHandle -> (ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly))
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(assembly : AssemblyName)
(typeGenerics : ConcreteTypeHandle ImmutableArray)
(methodGenerics : ConcreteTypeHandle ImmutableArray)
(genericDef : TypeDefn)
(args : ImmutableArray<TypeDefn>)
: ConcreteTypeHandle * ConcretizationContext
: ConcreteTypeHandle * ConcretizationContext<'corelib>
=
// First, concretize all type arguments
let argHandles, ctxAfterArgs =
@@ -614,17 +677,17 @@ module Concretization =
/// Helper to concretize an array of types
let private concretizeTypeArray
(ctx : TypeConcretization.ConcretizationContext)
(ctx : TypeConcretization.ConcretizationContext<'corelib>)
(loadAssembly :
AssemblyName -> AssemblyReferenceHandle -> (ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly))
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(assembly : AssemblyName)
(typeArgs : ConcreteTypeHandle ImmutableArray)
(methodArgs : ConcreteTypeHandle ImmutableArray)
(types : ImmutableArray<TypeDefn>)
: ImmutableArray<ConcreteTypeHandle> * TypeConcretization.ConcretizationContext
: ImmutableArray<ConcreteTypeHandle> * TypeConcretization.ConcretizationContext<'corelib>
=
let handles = ImmutableArray.CreateBuilder (types.Length)
let handles = ImmutableArray.CreateBuilder types.Length
let mutable ctx = ctx
for i = 0 to types.Length - 1 do
@@ -638,14 +701,14 @@ module Concretization =
/// Helper to concretize a method signature
let private concretizeMethodSignature
(ctx : TypeConcretization.ConcretizationContext)
(ctx : TypeConcretization.ConcretizationContext<'corelib>)
(loadAssembly :
AssemblyName -> AssemblyReferenceHandle -> (ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly))
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(assembly : AssemblyName)
(typeArgs : ConcreteTypeHandle ImmutableArray)
(methodArgs : ConcreteTypeHandle ImmutableArray)
(signature : TypeMethodSignature<TypeDefn>)
: TypeMethodSignature<ConcreteTypeHandle> * TypeConcretization.ConcretizationContext
: TypeMethodSignature<ConcreteTypeHandle> * TypeConcretization.ConcretizationContext<'corelib>
=
// Concretize return type

View File

@@ -150,6 +150,8 @@ type BaseClassTypes<'corelib> =
RuntimeMethodHandle : TypeInfo<WoofWare.PawPrint.GenericParameter, TypeDefn>
RuntimeFieldHandle : TypeInfo<WoofWare.PawPrint.GenericParameter, TypeDefn>
RuntimeTypeHandle : TypeInfo<WoofWare.PawPrint.GenericParameter, TypeDefn>
RuntimeFieldInfoStub : TypeInfo<WoofWare.PawPrint.GenericParameter, TypeDefn>
RuntimeFieldHandleInternal : TypeInfo<WoofWare.PawPrint.GenericParameter, TypeDefn>
RuntimeType : TypeInfo<WoofWare.PawPrint.GenericParameter, TypeDefn>
Void : TypeInfo<WoofWare.PawPrint.GenericParameter, TypeDefn>
TypedReference : TypeInfo<WoofWare.PawPrint.GenericParameter, TypeDefn>
@@ -323,7 +325,7 @@ module TypeInfo =
(Some (BaseTypeInfo.TypeDef typeDefinitionHandle))
let toTypeDefn
(corelib : BaseClassTypes<'corelib>)
(baseClassTypes : BaseClassTypes<'corelib>)
(getName : 'corelib -> AssemblyName)
(getTypeDef : 'corelib -> TypeDefinitionHandle -> TypeInfo<'generic, 'field>)
(getTypeRef : 'corelib -> TypeReferenceHandle -> TypeInfo<'generic, 'field>)
@@ -331,7 +333,7 @@ module TypeInfo =
: TypeDefn
=
let stk =
match resolveBaseType corelib getName getTypeDef getTypeRef ty.Assembly ty.BaseType with
match resolveBaseType baseClassTypes getName getTypeDef getTypeRef ty.Assembly ty.BaseType with
| ResolvedBaseType.Enum
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
| ResolvedBaseType.Object

View File

@@ -14,6 +14,7 @@
<Compile Include="AssemblyReference.fs" />
<Compile Include="EventDefn.fs" />
<Compile Include="ComparableTypeDefinitionHandle.fs" />
<Compile Include="ComparableFieldDefinitionHandle.fs" />
<Compile Include="ComparableSignatureHeader.fs" />
<Compile Include="TypeDefn.fs" />
<Compile Include="ConcreteType.fs" />

View File

@@ -19,6 +19,12 @@ module TestPureCases =
NativeImpls = MockEnv.make ()
LocalVariablesOfMain = None
}
{
FileName = "InitializeArray.cs"
ExpectedReturnCode = 0
NativeImpls = MockEnv.make ()
LocalVariablesOfMain = None
}
{
FileName = "GenericEdgeCases.cs"
ExpectedReturnCode = 0
@@ -73,6 +79,12 @@ module TestPureCases =
NativeImpls = MockEnv.make ()
LocalVariablesOfMain = None
}
{
FileName = "LdtokenField.cs"
ExpectedReturnCode = 0
NativeImpls = MockEnv.make ()
LocalVariablesOfMain = None
}
]
let cases : TestCase list =

View File

@@ -21,6 +21,8 @@
<EmbeddedResource Include="sourcesPure\BasicLock.cs" />
<EmbeddedResource Include="sourcesPure\Floats.cs" />
<EmbeddedResource Include="sourcesPure\NoOp.cs" />
<EmbeddedResource Include="sourcesPure\InitializeArray.cs" />
<EmbeddedResource Include="sourcesPure\LdtokenField.cs" />
<EmbeddedResource Include="sourcesPure\StaticVariables.cs" />
<EmbeddedResource Include="sourcesPure\Ldelema.cs" />
<EmbeddedResource Include="sourcesPure\ExceptionWithNoOpCatch.cs" />

View File

@@ -0,0 +1,19 @@
using System.Linq;
namespace HelloWorldApp
{
class Program
{
static int Main(string[] args)
{
int[] array = new[] { 1, 2, 3 };
if (array.Sum() != 60)
{
return 1;
}
return 0;
}
}
}

View File

@@ -39,7 +39,7 @@ unsafe class LdindTest
failures += TestTruncation();
// Test with managed pointers (ref)
// failures += TestManagedPointers();
failures += TestManagedPointers();
// Test Ldind.i (native int)
failures += TestLdindI();
@@ -325,7 +325,10 @@ unsafe class LdindTest
}
// Test with array element
int[] array = { 10, 20, 30 };
int[] array = new int[3];
array[0] = 10;
array[1] = 20;
array[2] = 30;
ref int element = ref array[1];
if (element != 20)
{

View File

@@ -0,0 +1,128 @@
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace LdtokenFieldTest
{
class Program
{
// Various field types to test ldtoken with
public static int StaticIntField = 42;
public string InstanceStringField = "test";
private readonly double PrivateReadonlyField = 3.14;
internal decimal InternalField;
protected bool ProtectedField;
public static readonly DateTime StaticReadonlyField = DateTime.MinValue;
// Generic type fields
public GenericClass<int>.NestedClass<string> GenericField;
static int Main(string[] args)
{
int testsFailed = 0;
// Test 1: Static field via FieldInfo
FieldInfo staticField = typeof(Program).GetField(nameof(StaticIntField));
if (staticField == null || staticField.FieldType != typeof(int))
{
testsFailed++;
}
// Test 2: Instance field via FieldInfo
FieldInfo instanceField = typeof(Program).GetField(nameof(InstanceStringField));
if (instanceField == null || instanceField.FieldType != typeof(string))
{
testsFailed++;
}
// Test 3: Private field via FieldInfo with binding flags
FieldInfo privateField = typeof(Program).GetField("PrivateReadonlyField",
BindingFlags.NonPublic | BindingFlags.Instance);
if (privateField == null || privateField.FieldType != typeof(double))
{
testsFailed++;
}
// Test 4: Using RuntimeFieldHandle directly
RuntimeFieldHandle handle = staticField.FieldHandle;
FieldInfo fieldFromHandle = FieldInfo.GetFieldFromHandle(handle);
if (!ReferenceEquals(fieldFromHandle, staticField))
{
testsFailed++;
}
// Test 5: Field from generic type
Type genericType = typeof(GenericClass<>);
FieldInfo genericFieldInfo = genericType.GetField("GenericField");
if (genericFieldInfo == null)
{
testsFailed++;
}
// Test 6: Field from nested type
Type nestedType = typeof(OuterClass.InnerClass);
FieldInfo nestedField = nestedType.GetField("NestedField");
if (nestedField == null || nestedField.FieldType != typeof(int))
{
testsFailed++;
}
// Test 7: Field handle with generic context
Type constructedGeneric = typeof(GenericClass<int>);
FieldInfo constructedField = constructedGeneric.GetField("GenericField");
RuntimeFieldHandle genericHandle = constructedField.FieldHandle;
FieldInfo reconstructed = FieldInfo.GetFieldFromHandle(genericHandle, constructedGeneric.TypeHandle);
if (reconstructed.DeclaringType != constructedGeneric)
{
testsFailed++;
}
// Test 8: Struct field
Type structType = typeof(TestStruct);
FieldInfo structField = structType.GetField("StructField");
if (structField == null || structField.FieldType != typeof(long))
{
testsFailed++;
}
// Test 9: Volatile field
FieldInfo volatileField = typeof(VolatileFieldClass).GetField("VolatileField");
if (volatileField == null || !volatileField.GetRequiredCustomModifiers().Any(t => t == typeof(IsVolatile)))
{
testsFailed++;
}
return testsFailed;
}
}
// Supporting types for testing
public class GenericClass<T>
{
public T GenericField;
public class NestedClass<U>
{
public U NestedGenericField;
}
}
public class OuterClass
{
public class InnerClass
{
public int NestedField = 100;
}
}
public struct TestStruct
{
public long StructField;
}
public class VolatileFieldClass
{
public volatile int VolatileField;
}
}

View File

@@ -125,42 +125,55 @@ module AbstractMachine =
targetType.Namespace,
targetType.Name,
instruction.ExecutingMethod.Name,
instruction.ExecutingMethod.RawSignature.ParameterTypes,
instruction.ExecutingMethod.RawSignature.ReturnType
instruction.ExecutingMethod.Signature.ParameterTypes,
instruction.ExecutingMethod.Signature.ReturnType
with
| "System.Private.CoreLib",
"System",
"Environment",
"GetProcessorCount",
[],
TypeDefn.PrimitiveType PrimitiveType.Int32 ->
ConcretePrimitive state.ConcreteTypes PrimitiveType.Int32 ->
let env = ISystem_Environment_Env.get impls
env.GetProcessorCount thread state
| "System.Private.CoreLib",
"System",
"Environment",
"_Exit",
[ TypeDefn.PrimitiveType PrimitiveType.Int32 ],
TypeDefn.Void ->
[ ConcretePrimitive state.ConcreteTypes PrimitiveType.Int32 ],
ConcreteVoid state.ConcreteTypes ->
let env = ISystem_Environment_Env.get impls
env._Exit thread state
| "System.Private.CoreLib",
"System.Threading",
"Monitor",
"ReliableEnter",
[ TypeDefn.PrimitiveType PrimitiveType.Object
TypeDefn.Byref (TypeDefn.PrimitiveType PrimitiveType.Boolean) ],
TypeDefn.Void ->
[ ConcretePrimitive state.ConcreteTypes PrimitiveType.Object
ConcreteByref (ConcretePrimitive state.ConcreteTypes PrimitiveType.Boolean) ],
ConcreteVoid state.ConcreteTypes ->
let env = ISystem_Threading_Monitor_Env.get impls
env.ReliableEnter thread state
| "System.Private.CoreLib",
"System.Threading",
"Monitor",
"Exit",
[ TypeDefn.PrimitiveType PrimitiveType.Object ],
TypeDefn.Void ->
[ ConcretePrimitive state.ConcreteTypes PrimitiveType.Object ],
ConcreteVoid state.ConcreteTypes ->
let env = ISystem_Threading_Monitor_Env.get impls
env.Exit thread state
| "System.Private.CoreLib",
"System",
"Type",
"GetField",
[ ConcretePrimitive state.ConcreteTypes PrimitiveType.String ; ty ],
ret ->
let ty = AllConcreteTypes.lookup ty state.ConcreteTypes |> Option.get
let ret = AllConcreteTypes.lookup ret state.ConcreteTypes |> Option.get
match ty.Namespace, ty.Name, ty.Generics.IsEmpty, ret.Namespace, ret.Name, ret.Generics.IsEmpty with
| "System.Reflection", "BindingFlags", true, "System.Reflection", "FieldInfo", true ->
failwith "TODO: GetField"
| _ -> failwith "unexpected signature for Type.GetField"
| assy, ns, typeName, methName, param, retType ->
failwith
$"TODO: tried to IL-interpret a method in {assy} {ns}.{typeName} named {methName} with no implementation; {param} -> {retType}"

View File

@@ -396,7 +396,7 @@ module CliType =
let loadAssembly
(assyName : AssemblyName)
(ref : AssemblyReferenceHandle)
: (ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
: ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly
=
match assemblies.TryGetValue assyName.FullName with
| true, currentAssy ->

View File

@@ -134,6 +134,21 @@ module Corelib =
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "UIntPtr" then Some v else None)
|> Seq.exactlyOne
let runtimeFieldInfoStubType =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) -> if v.Name = "RuntimeFieldInfoStub" then Some v else None)
|> Seq.exactlyOne
let runtimeFieldHandleInternalType =
corelib.TypeDefs
|> Seq.choose (fun (KeyValue (_, v)) ->
if v.Name = "RuntimeFieldHandleInternal" then
Some v
else
None
)
|> Seq.exactlyOne
{
Corelib = corelib
String = stringType
@@ -157,6 +172,8 @@ module Corelib =
RuntimeTypeHandle = runtimeTypeHandleType
RuntimeMethodHandle = runtimeMethodHandleType
RuntimeFieldHandle = runtimeFieldHandleType
RuntimeFieldInfoStub = runtimeFieldInfoStubType
RuntimeFieldHandleInternal = runtimeFieldHandleInternalType
RuntimeType = runtimeTypeType
Void = voidType
TypedReference = typedReferenceType

View File

@@ -0,0 +1,111 @@
namespace WoofWare.PawPrint
open System.Reflection
open System.Reflection.Metadata
type FieldHandle =
private
{
AssemblyFullName : string
DeclaringType : ConcreteTypeHandle
FieldHandle : ComparableFieldDefinitionHandle
}
type FieldHandleRegistry =
private
{
FieldHandleToId : Map<FieldHandle, int64>
FieldHandleToField : Map<ManagedHeapAddress, FieldHandle>
FieldToHandle : Map<FieldHandle, ManagedHeapAddress>
NextHandle : int64
}
[<RequireQualifiedAccess>]
module FieldHandleRegistry =
let empty () =
{
FieldHandleToField = Map.empty
FieldToHandle = Map.empty
FieldHandleToId = Map.empty
NextHandle = 1L
}
/// Returns a (struct) System.RuntimeFieldHandle, with its contents (reference type) freshly allocated if necessary.
let getOrAllocate
(baseClassTypes : BaseClassTypes<'corelib>)
(allocState : 'allocState)
(allocate : (string * CliType) list -> 'allocState -> ManagedHeapAddress * 'allocState)
(declaringAssy : AssemblyName)
(declaringType : ConcreteTypeHandle)
(handle : FieldDefinitionHandle)
(reg : FieldHandleRegistry)
: CliType * FieldHandleRegistry * 'allocState
=
let runtimeFieldHandle (runtimeFieldInfoStub : ManagedHeapAddress) =
// RuntimeFieldHandle is a struct; it contains one field, an IRuntimeFieldInfo
// https://github.com/dotnet/runtime/blob/1d1bf92fcf43aa6981804dc53c5174445069c9e4/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs#L1048
// In practice we expect to use RuntimeFieldInfoStub for that IRuntimeFieldInfo:
// https://github.com/dotnet/runtime/blob/1d1bf92fcf43aa6981804dc53c5174445069c9e4/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs#L1157
let runtimeFieldHandleType = baseClassTypes.RuntimeFieldHandle
let field = runtimeFieldHandleType.Fields |> List.exactlyOne
if field.Name <> "m_ptr" then
failwith $"unexpected field name %s{field.Name} for BCL type RuntimeFieldHandle"
{
Fields = [ "m_ptr", CliType.ofManagedObject runtimeFieldInfoStub ]
}
|> CliType.ValueType
let handle =
{
AssemblyFullName = declaringAssy.FullName
FieldHandle = ComparableFieldDefinitionHandle.Make handle
DeclaringType = declaringType
}
match Map.tryFind handle reg.FieldToHandle with
| Some v -> runtimeFieldHandle v, reg, allocState
| None ->
let newHandle = reg.NextHandle
let runtimeFieldHandleInternal =
let field = baseClassTypes.RuntimeFieldHandleInternal.Fields |> List.exactlyOne
if field.Name <> "m_handle" then
failwith $"unexpected field name %s{field.Name} for BCL type RuntimeFieldHandleInternal"
match field.Signature with
| TypeDefn.PrimitiveType PrimitiveType.IntPtr -> ()
| s -> failwith $"bad sig: {s}"
{
Fields = [ "m_handle", CliType.RuntimePointer (CliRuntimePointer.Unmanaged newHandle) ]
}
|> CliType.ValueType
let runtimeFieldInfoStub =
[
// If we ever implement a GC, something should change here
"m_keepalive", CliType.ObjectRef None
"m_c", CliType.ObjectRef None
"m_d", CliType.ObjectRef None
"m_b", CliType.Numeric (CliNumericType.Int32 0)
"m_e", CliType.ObjectRef None
// RuntimeFieldHandleInternal: https://github.com/dotnet/runtime/blob/1d1bf92fcf43aa6981804dc53c5174445069c9e4/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs#L1048
"m_fieldHandle", runtimeFieldHandleInternal
]
let alloc, state = allocate runtimeFieldInfoStub allocState
let reg =
{
FieldHandleToField = reg.FieldHandleToField |> Map.add alloc handle
FieldToHandle = reg.FieldToHandle |> Map.add handle alloc
FieldHandleToId = reg.FieldHandleToId |> Map.add handle newHandle
NextHandle = reg.NextHandle + 1L
}
runtimeFieldHandle alloc, reg, state

View File

@@ -1,5 +1,6 @@
namespace WoofWare.PawPrint
open System
open System.Collections.Immutable
open System.IO
open System.Reflection
@@ -26,6 +27,7 @@ type IlMachineState =
_Statics : ImmutableDictionary<ConcreteTypeHandle, ImmutableDictionary<string, CliType>>
DotnetRuntimeDirs : string ImmutableArray
TypeHandles : TypeHandleRegistry
FieldHandles : FieldHandleRegistry
}
member this.WithTypeBeginInit (thread : ThreadId) (ty : ConcreteTypeHandle) =
@@ -147,6 +149,47 @@ type StateLoadResult =
module IlMachineState =
type private Dummy = class end
let concretizeType
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(state : IlMachineState)
(declaringAssembly : AssemblyName)
(typeGenerics : ImmutableArray<ConcreteTypeHandle>)
(methodGenerics : ImmutableArray<ConcreteTypeHandle>)
(ty : TypeDefn)
: IlMachineState * ConcreteTypeHandle
=
let ctx =
{
TypeConcretization.ConcretizationContext.InProgress = ImmutableDictionary.Empty
TypeConcretization.ConcretizationContext.ConcreteTypes = state.ConcreteTypes
TypeConcretization.ConcretizationContext.LoadedAssemblies = state._LoadedAssemblies
TypeConcretization.ConcretizationContext.BaseTypes = baseClassTypes
}
let handle, ctx =
TypeConcretization.concretizeType
ctx
(fun assyName ref ->
let currentAssy = state.LoadedAssembly assyName |> Option.get
let targetAssy =
currentAssy.AssemblyReferences.[ref].Name |> state.LoadedAssembly |> Option.get
state._LoadedAssemblies, targetAssy
)
declaringAssembly
typeGenerics
methodGenerics
ty
let state =
{ state with
_LoadedAssemblies = ctx.LoadedAssemblies
ConcreteTypes = ctx.ConcreteTypes
}
state, handle
/// <summary>
/// Create a new IlMachineState which has loaded the given assembly.
/// This involves reading assemblies from the disk and doing a complete parse of them, so it might be quite slow!
@@ -267,7 +310,7 @@ module IlMachineState =
let rec resolveTypeFromDefn
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(ty : TypeDefn)
(typeGenericArgs : ImmutableArray<TypeDefn>)
(methodGenericArgs : ImmutableArray<TypeDefn>)
@@ -283,14 +326,21 @@ module IlMachineState =
(state, args)
||> Seq.fold (fun state arg ->
let state, assy, resolvedArg =
resolveTypeFromDefn loggerFactory corelib arg typeGenericArgs methodGenericArgs assy state
resolveTypeFromDefn
loggerFactory
baseClassTypes
arg
typeGenericArgs
methodGenericArgs
assy
state
// If the resolved argument has generics, create a GenericInstantiation
// Otherwise, create a FromDefinition
let preservedArg =
let baseType =
resolvedArg.BaseType
|> DumpedAssembly.resolveBaseType corelib state._LoadedAssemblies assy.Name
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies assy.Name
let signatureTypeKind =
match baseType with
@@ -322,7 +372,7 @@ module IlMachineState =
)
let args' = args'.ToImmutable ()
resolveTypeFromDefn loggerFactory corelib generic args' methodGenericArgs assy state
resolveTypeFromDefn loggerFactory baseClassTypes generic args' methodGenericArgs assy state
| TypeDefn.FromDefinition (defn, assy, _typeKind) ->
let assy = state._LoadedAssemblies.[assy]
@@ -339,39 +389,39 @@ module IlMachineState =
| 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.Boolean -> baseClassTypes.Boolean
| PrimitiveType.Char -> baseClassTypes.Char
| PrimitiveType.SByte -> baseClassTypes.SByte
| PrimitiveType.Byte -> baseClassTypes.Byte
| PrimitiveType.Int16 -> baseClassTypes.Int16
| PrimitiveType.UInt16 -> baseClassTypes.UInt16
| PrimitiveType.Int32 -> baseClassTypes.Int32
| PrimitiveType.UInt32 -> baseClassTypes.UInt32
| PrimitiveType.Int64 -> baseClassTypes.Int64
| PrimitiveType.UInt64 -> baseClassTypes.UInt64
| PrimitiveType.Single -> baseClassTypes.Single
| PrimitiveType.Double -> baseClassTypes.Double
| PrimitiveType.String -> baseClassTypes.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
state, baseClassTypes.Corelib, ty
| TypeDefn.GenericTypeParameter param ->
let arg = typeGenericArgs.[param]
// TODO: this assembly is probably wrong?
resolveTypeFromDefn loggerFactory corelib arg typeGenericArgs methodGenericArgs assy state
resolveTypeFromDefn loggerFactory baseClassTypes arg typeGenericArgs methodGenericArgs assy state
| TypeDefn.GenericMethodParameter param ->
let arg = methodGenericArgs.[param]
// TODO: this assembly is probably wrong?
resolveTypeFromDefn loggerFactory corelib arg typeGenericArgs methodGenericArgs assy state
resolveTypeFromDefn loggerFactory baseClassTypes arg typeGenericArgs methodGenericArgs assy state
| s -> failwith $"TODO: resolveTypeFromDefn unimplemented for {s}"
let resolveTypeFromSpec
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(ty : TypeSpecificationHandle)
(assy : DumpedAssembly)
(typeGenericArgs : TypeDefn ImmutableArray)
@@ -380,12 +430,12 @@ module IlMachineState =
: IlMachineState * DumpedAssembly * WoofWare.PawPrint.TypeInfo<TypeDefn, TypeDefn>
=
let sign = assy.TypeSpecs.[ty].Signature
resolveTypeFromDefn loggerFactory corelib sign typeGenericArgs methodGenericArgs assy state
resolveTypeFromDefn loggerFactory baseClassTypes sign typeGenericArgs methodGenericArgs assy state
/// Resolve a TypeSpecification using concrete type handles from execution context
let resolveTypeFromSpecConcrete
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(ty : TypeSpecificationHandle)
(assy : DumpedAssembly)
(typeGenericArgs : ConcreteTypeHandle ImmutableArray)
@@ -399,28 +449,36 @@ module IlMachineState =
let typeGenericArgsAsDefn =
typeGenericArgs
|> Seq.map (fun handle ->
Concretization.concreteHandleToTypeDefn corelib handle state.ConcreteTypes state._LoadedAssemblies
Concretization.concreteHandleToTypeDefn
baseClassTypes
handle
state.ConcreteTypes
state._LoadedAssemblies
)
|> ImmutableArray.CreateRange
let methodGenericArgsAsDefn =
methodGenericArgs
|> Seq.map (fun handle ->
Concretization.concreteHandleToTypeDefn corelib handle state.ConcreteTypes state._LoadedAssemblies
Concretization.concreteHandleToTypeDefn
baseClassTypes
handle
state.ConcreteTypes
state._LoadedAssemblies
)
|> ImmutableArray.CreateRange
resolveTypeFromDefn loggerFactory corelib sign typeGenericArgsAsDefn methodGenericArgsAsDefn assy state
resolveTypeFromDefn loggerFactory baseClassTypes sign typeGenericArgsAsDefn methodGenericArgsAsDefn assy state
/// Get zero value for a type that's already been concretized
let cliTypeZeroOfHandle
(state : IlMachineState)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(handle : ConcreteTypeHandle)
: CliType * IlMachineState
=
let zero, updatedConcreteTypes =
CliType.zeroOf state.ConcreteTypes state._LoadedAssemblies corelib handle
CliType.zeroOf state.ConcreteTypes state._LoadedAssemblies baseClassTypes handle
let newState =
{ state with
@@ -440,25 +498,25 @@ module IlMachineState =
/// Concretize a ConcreteType<TypeDefn> to get a ConcreteTypeHandle for static field access
let concretizeFieldDeclaringType
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<'corelib>)
(declaringType : ConcreteType<TypeDefn>)
(state : IlMachineState)
: ConcreteTypeHandle * IlMachineState
=
// Create a concretization context from the current state
let ctx : TypeConcretization.ConcretizationContext =
let ctx : TypeConcretization.ConcretizationContext<'corelib> =
{
InProgress = ImmutableDictionary.Empty
ConcreteTypes = state.ConcreteTypes
LoadedAssemblies = state._LoadedAssemblies
BaseTypes = corelib
BaseTypes = baseClassTypes
}
// Helper function to get assembly from reference
let loadAssembly
(currentAssembly : AssemblyName)
(assyRef : AssemblyReferenceHandle)
: (ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
: ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly
=
let assyToLoad =
match state.LoadedAssembly currentAssembly with
@@ -537,7 +595,7 @@ module IlMachineState =
/// Get zero value for a TypeDefn, concretizing it first
let cliTypeZeroOf
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(assy : DumpedAssembly)
(ty : TypeDefn)
(typeGenerics : ConcreteTypeHandle ImmutableArray)
@@ -554,39 +612,11 @@ module IlMachineState =
else
state.WithLoadedAssembly assy.Name assy
let ctx =
{
TypeConcretization.ConcretizationContext.InProgress = ImmutableDictionary.Empty
TypeConcretization.ConcretizationContext.ConcreteTypes = state.ConcreteTypes
TypeConcretization.ConcretizationContext.LoadedAssemblies = state._LoadedAssemblies
TypeConcretization.ConcretizationContext.BaseTypes = corelib
}
let handle, newCtx =
TypeConcretization.concretizeType
ctx
(fun assyName ref ->
// Helper to get assembly from reference
let currentAssy = state.LoadedAssembly (assyName) |> Option.get
let targetAssy =
currentAssy.AssemblyReferences.[ref].Name |> state.LoadedAssembly |> Option.get
state._LoadedAssemblies, targetAssy
)
assy.Name
typeGenerics
methodGenerics
ty
let state =
{ state with
ConcreteTypes = newCtx.ConcreteTypes
_LoadedAssemblies = newCtx.LoadedAssemblies
}
let state, handle =
concretizeType baseClassTypes state assy.Name typeGenerics methodGenerics ty
// Now get the zero value
let zero, state = cliTypeZeroOfHandle state corelib handle
let zero, state = cliTypeZeroOfHandle state baseClassTypes handle
state, zero
let pushToEvalStack' (o : EvalStackValue) (thread : ThreadId) (state : IlMachineState) =
@@ -656,7 +686,7 @@ module IlMachineState =
/// There might be no stack frame to return to, so you might get None.
let returnStackFrame
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(currentThread : ThreadId)
(state : IlMachineState)
: IlMachineState option
@@ -696,7 +726,7 @@ module IlMachineState =
let resolvedBaseType =
DumpedAssembly.resolveBaseType
corelib
baseClassTypes
state._LoadedAssemblies
constructed.Type.Assembly
constructed.Type.BaseType
@@ -728,7 +758,7 @@ module IlMachineState =
// | TypeDefn.Void -> state
| retType ->
// TODO: generics
let zero, state = cliTypeZeroOfHandle state corelib retType
let zero, state = cliTypeZeroOfHandle state baseClassTypes retType
let toPush = EvalStackValue.toCliTypeCoerced zero retVal
@@ -741,7 +771,7 @@ module IlMachineState =
let concretizeMethodWithTypeGenerics
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(typeGenerics : ImmutableArray<ConcreteTypeHandle>)
(methodToCall : WoofWare.PawPrint.MethodInfo<TypeDefn, WoofWare.PawPrint.GenericParameter, TypeDefn>)
(methodGenerics : TypeDefn ImmutableArray option)
@@ -762,45 +792,17 @@ module IlMachineState =
let mutable state = state
for i = 0 to generics.Length - 1 do
let ctx =
{
TypeConcretization.ConcretizationContext.InProgress = ImmutableDictionary.Empty
TypeConcretization.ConcretizationContext.ConcreteTypes = state.ConcreteTypes
TypeConcretization.ConcretizationContext.LoadedAssemblies = state._LoadedAssemblies
TypeConcretization.ConcretizationContext.BaseTypes = corelib
}
// When concretizing method generic arguments, we need to handle the case where
// the generic argument itself doesn't reference method parameters
try
let handle, newCtx =
TypeConcretization.concretizeType
ctx
(fun assyName ref ->
let currentAssy = state.LoadedAssembly assyName |> Option.get
let targetAssy =
currentAssy.AssemblyReferences.[ref].Name |> state.LoadedAssembly |> Option.get
state._LoadedAssemblies, targetAssy
)
callingAssembly
typeGenerics
currentExecutingMethodGenerics
generics.[i]
state <-
{ state with
ConcreteTypes = newCtx.ConcreteTypes
}
handles.Add handle
with ex ->
failwithf
"Failed to concretize method generic argument %d: %A. Exception: %s"
i
let state2, handle =
concretizeType
baseClassTypes
state
callingAssembly
typeGenerics
currentExecutingMethodGenerics
generics.[i]
ex.Message
state <- state2
handles.Add handle
state, handles.ToImmutable ()
@@ -825,7 +827,7 @@ module IlMachineState =
failwithf "Current assembly %s not loaded when trying to resolve reference" assyName.FullName
)
state._LoadedAssemblies
corelib
baseClassTypes
methodToCall
typeGenerics
concretizedMethodGenerics
@@ -846,7 +848,7 @@ module IlMachineState =
let concretizeMethodForExecution
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(thread : ThreadId)
(methodToCall : WoofWare.PawPrint.MethodInfo<TypeDefn, WoofWare.PawPrint.GenericParameter, TypeDefn>)
(methodGenerics : TypeDefn ImmutableArray option)
@@ -871,7 +873,7 @@ module IlMachineState =
TypeConcretization.ConcretizationContext.InProgress = ImmutableDictionary.Empty
TypeConcretization.ConcretizationContext.ConcreteTypes = state.ConcreteTypes
TypeConcretization.ConcretizationContext.LoadedAssemblies = state._LoadedAssemblies
TypeConcretization.ConcretizationContext.BaseTypes = corelib
TypeConcretization.ConcretizationContext.BaseTypes = baseClassTypes
}
let handle, newCtx =
@@ -910,7 +912,7 @@ module IlMachineState =
concretizeMethodWithTypeGenerics
loggerFactory
corelib
baseClassTypes
typeGenerics
methodToCall
methodGenerics
@@ -921,7 +923,7 @@ module IlMachineState =
// Add to IlMachineState module
let concretizeFieldForExecution
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(thread : ThreadId)
(field : WoofWare.PawPrint.FieldInfo<TypeDefn, TypeDefn>)
(state : IlMachineState)
@@ -940,7 +942,7 @@ module IlMachineState =
TypeConcretization.ConcretizationContext.InProgress = ImmutableDictionary.Empty
TypeConcretization.ConcretizationContext.ConcreteTypes = state.ConcreteTypes
TypeConcretization.ConcretizationContext.LoadedAssemblies = state._LoadedAssemblies
TypeConcretization.ConcretizationContext.BaseTypes = corelib
TypeConcretization.ConcretizationContext.BaseTypes = baseClassTypes
}
// Create a TypeDefn for the field's declaring type
@@ -952,7 +954,7 @@ module IlMachineState =
let baseType =
typeDef.BaseType
|> DumpedAssembly.resolveBaseType corelib state._LoadedAssemblies assy.Name
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies assy.Name
let signatureTypeKind =
match baseType with
@@ -973,7 +975,7 @@ module IlMachineState =
let baseTypeResolved =
typeDef.BaseType
|> DumpedAssembly.resolveBaseType corelib state._LoadedAssemblies assy.Name
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies assy.Name
let signatureTypeKind =
match baseTypeResolved with
@@ -1049,6 +1051,7 @@ module IlMachineState =
TypeInitTable = ImmutableDictionary.Empty
DotnetRuntimeDirs = dotnetRuntimeDirs
TypeHandles = TypeHandleRegistry.empty ()
FieldHandles = FieldHandleRegistry.empty ()
}
state.WithLoadedAssembly assyName entryAssembly
@@ -1188,7 +1191,7 @@ module IlMachineState =
let resolveMember
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(currentThread : ThreadId)
(assy : DumpedAssembly)
(m : MemberReferenceHandle)
@@ -1211,7 +1214,11 @@ module IlMachineState =
let typeGenerics =
executing.DeclaringType.Generics
|> Seq.map (fun handle ->
Concretization.concreteHandleToTypeDefn corelib handle state.ConcreteTypes state._LoadedAssemblies
Concretization.concreteHandleToTypeDefn
baseClassTypes
handle
state.ConcreteTypes
state._LoadedAssemblies
)
|> ImmutableArray.CreateRange
@@ -1222,13 +1229,13 @@ module IlMachineState =
let state, assy, targetType =
resolveType loggerFactory parent ImmutableArray.Empty assy state
state, assy, targetType, ImmutableArray<TypeDefn>.Empty // No type args from TypeReference
state, assy, targetType, ImmutableArray.Empty // No type args from TypeReference
| MetadataToken.TypeSpecification parent ->
let methodGenerics =
executing.Generics
|> Seq.map (fun handle ->
Concretization.concreteHandleToTypeDefn
corelib
baseClassTypes
handle
state.ConcreteTypes
state._LoadedAssemblies
@@ -1236,7 +1243,7 @@ module IlMachineState =
|> ImmutableArray.CreateRange
let state, assy, targetType =
resolveTypeFromSpec loggerFactory corelib parent assy typeGenerics methodGenerics state
resolveTypeFromSpec loggerFactory baseClassTypes parent assy typeGenerics methodGenerics state
// Extract type arguments from the resolved type
let extractedTypeArgs = targetType.Generics
@@ -1244,12 +1251,58 @@ module IlMachineState =
state, assy, targetType, extractedTypeArgs
| parent -> failwith $"Unexpected: {parent}"
let state, concreteExtractedTypeArgs =
((state, ImmutableArray.CreateBuilder ()), extractedTypeArgs)
||> Seq.fold (fun (state, acc) ty ->
// TODO: generics?
let state, t =
concretizeType
baseClassTypes
state
targetType.Assembly
ImmutableArray.Empty
ImmutableArray.Empty
ty
acc.Add t
state, acc
)
|> Tuple.rmap (fun x -> x.ToImmutable ())
match mem.Signature with
| MemberSignature.Field fieldSig ->
let availableFields =
targetType.Fields
|> List.filter (fun fi -> fi.Name = memberName)
|> List.filter (fun fi -> fi.Signature = fieldSig)
// Concretize the field signature from the member reference
let state, concreteFieldSig =
concretizeType
baseClassTypes
state
(state.ActiveAssembly(currentThread).Name)
concreteExtractedTypeArgs
ImmutableArray.Empty
fieldSig
// Find matching fields by comparing concretized signatures
let state, availableFields =
((state, []), targetType.Fields)
||> List.fold (fun (state, acc) fi ->
if fi.Name <> memberName then
state, acc
else
// Concretize the field's signature for comparison
let state, fieldSigConcrete =
concretizeType
baseClassTypes
state
assy.Name
concreteExtractedTypeArgs
ImmutableArray.Empty
fi.Signature
if fieldSigConcrete = concreteFieldSig then
state, fi :: acc
else
state, acc
)
let field =
match availableFields with
@@ -1265,16 +1318,50 @@ module IlMachineState =
| MemberSignature.Method memberSig ->
let availableMethods =
targetType.Methods
|> List.filter (fun mi -> mi.Name = memberName)
// TODO: this needs to resolve the TypeMethodSignature to e.g. remove references to generic parameters
|> List.filter (fun mi -> mi.Signature = memberSig)
targetType.Methods |> List.filter (fun mi -> mi.Name = memberName)
let state, memberSig =
memberSig
|> TypeMethodSignature.map
state
(fun state ty ->
concretizeType
baseClassTypes
state
(state.ActiveAssembly(currentThread).Name)
concreteExtractedTypeArgs
ImmutableArray.Empty
ty
)
let state, availableMethods =
((state, []), availableMethods)
||> List.fold (fun (state, acc) meth ->
let state, methSig =
meth.Signature
|> TypeMethodSignature.map
state
(fun state ty ->
concretizeType
baseClassTypes
state
assy.Name
concreteExtractedTypeArgs
ImmutableArray.Empty
ty
)
if methSig = memberSig then
state, meth :: acc
else
state, acc
)
let method =
match availableMethods with
| [] ->
failwith
$"Could not find member {memberName} with the right signature on {targetType.Namespace}.{targetType.Name}"
$"Could not find member {memberName} with the right signature {memberSig} on {targetType.Namespace}.{targetType.Name}"
| [ x ] -> x |> MethodInfo.mapTypeGenerics (fun i _ -> targetType.Generics.[i])
| _ ->
failwith
@@ -1379,6 +1466,47 @@ module IlMachineState =
result, state
/// Returns a System.RuntimeFieldHandle.
let getOrAllocateField<'corelib>
(loggerFactory : ILoggerFactory)
(baseClassTypes : BaseClassTypes<'corelib>)
(declaringAssy : AssemblyName)
(fieldHandle : FieldDefinitionHandle)
(state : IlMachineState)
: CliType * IlMachineState
=
let field = state.LoadedAssembly(declaringAssy).Value.Fields.[fieldHandle]
// For LdToken, we don't have generic context, so we create a non-generic type
// TODO: This might need to be revisited if we need to support generic field handles
let declaringTypeWithGenerics : ConcreteType<TypeDefn> =
ConcreteType.make
field.DeclaringType.Assembly
field.DeclaringType.Namespace
field.DeclaringType.Name
field.DeclaringType.Definition.Get
ImmutableArray.Empty // No generic arguments in this context
let declaringType, state =
concretizeFieldDeclaringType loggerFactory baseClassTypes declaringTypeWithGenerics state
let result, reg, state =
FieldHandleRegistry.getOrAllocate
baseClassTypes
state
(fun fields state -> allocateManagedObject baseClassTypes.RuntimeType fields state)
declaringAssy
declaringType
fieldHandle
state.FieldHandles
let state =
{ state with
FieldHandles = reg
}
result, state
let setStatic
(ty : ConcreteTypeHandle)
(field : string)

View File

@@ -7,7 +7,7 @@ open Microsoft.Extensions.Logging
module IlMachineStateExecution =
let callMethod
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(wasInitialising : ConcreteTypeHandle option)
(wasConstructing : ManagedHeapAddress option)
(wasClassConstructor : bool)
@@ -34,7 +34,7 @@ module IlMachineStateExecution =
match
if isIntrinsic then
Intrinsics.call corelib methodToCall thread state
Intrinsics.call baseClassTypes methodToCall thread state
else
None
with
@@ -45,7 +45,7 @@ module IlMachineStateExecution =
let state, argZeroObjects =
((state, []), methodToCall.Signature.ParameterTypes)
||> List.fold (fun (state, zeros) tyHandle ->
let zero, state = IlMachineState.cliTypeZeroOfHandle state corelib tyHandle
let zero, state = IlMachineState.cliTypeZeroOfHandle state baseClassTypes tyHandle
state, zero :: zeros
)
@@ -129,7 +129,7 @@ module IlMachineStateExecution =
match
MethodState.Empty
state.ConcreteTypes
corelib
baseClassTypes
state._LoadedAssemblies
(state.ActiveAssembly thread)
methodToCall
@@ -174,7 +174,7 @@ module IlMachineStateExecution =
let rec loadClass
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(ty : ConcreteTypeHandle)
(currentThread : ThreadId)
(state : IlMachineState)
@@ -251,7 +251,10 @@ module IlMachineStateExecution =
let baseType =
baseTypeDef.BaseType
|> DumpedAssembly.resolveBaseType corelib state._LoadedAssemblies sourceAssembly.Name
|> DumpedAssembly.resolveBaseType
baseClassTypes
state._LoadedAssemblies
sourceAssembly.Name
let signatureTypeKind =
match baseType with
@@ -267,30 +270,18 @@ module IlMachineStateExecution =
)
// Concretize the base type
let ctx =
{
TypeConcretization.ConcretizationContext.InProgress = ImmutableDictionary.Empty
TypeConcretization.ConcretizationContext.ConcreteTypes = state.ConcreteTypes
TypeConcretization.ConcretizationContext.LoadedAssemblies = state._LoadedAssemblies
TypeConcretization.ConcretizationContext.BaseTypes = corelib
}
let baseTypeHandle, newCtx =
TypeConcretization.concretizeType
ctx
(fun _ _ -> failwith "getAssembly not needed for base type concretization")
let state, baseTypeHandle =
IlMachineState.concretizeType
baseClassTypes
state
sourceAssembly.Name
concreteType.Generics // Use the current type's generics
ImmutableArray.Empty // No method generics
concreteType.Generics
// TODO: surely we have generics in scope here?
ImmutableArray.Empty
baseTypeDefn
let state =
{ state with
ConcreteTypes = newCtx.ConcreteTypes
}
// Recursively load the base class
match loadClass loggerFactory corelib baseTypeHandle currentThread state with
match loadClass loggerFactory baseClassTypes baseTypeHandle currentThread state with
| FirstLoadThis state -> Error state
| NothingToDo state -> Ok state
| BaseTypeInfo.TypeRef typeReferenceHandle ->
@@ -316,7 +307,7 @@ module IlMachineStateExecution =
let baseTypeDefn =
let baseType =
targetType.BaseType
|> DumpedAssembly.resolveBaseType corelib state._LoadedAssemblies assy.Name
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies assy.Name
let signatureTypeKind =
match baseType with
@@ -332,30 +323,18 @@ module IlMachineStateExecution =
)
// Concretize the base type
let ctx =
{
TypeConcretization.ConcretizationContext.InProgress = ImmutableDictionary.Empty
TypeConcretization.ConcretizationContext.ConcreteTypes = state.ConcreteTypes
TypeConcretization.ConcretizationContext.LoadedAssemblies = state._LoadedAssemblies
TypeConcretization.ConcretizationContext.BaseTypes = corelib
}
let baseTypeHandle, newCtx =
TypeConcretization.concretizeType
ctx
(fun _ _ -> failwith "getAssembly not needed for base type concretization")
assy.Name
concreteType.Generics // Use the current type's generics
ImmutableArray.Empty // No method generics
let state, baseTypeHandle =
IlMachineState.concretizeType
baseClassTypes
state
sourceAssembly.Name
concreteType.Generics
// TODO: surely we have generics in scope here?
ImmutableArray.Empty
baseTypeDefn
let state =
{ state with
ConcreteTypes = newCtx.ConcreteTypes
}
// Recursively load the base class
match loadClass loggerFactory corelib baseTypeHandle currentThread state with
match loadClass loggerFactory baseClassTypes baseTypeHandle currentThread state with
| FirstLoadThis state -> Error state
| NothingToDo state -> Ok state
| BaseTypeInfo.TypeSpec typeSpecificationHandle ->
@@ -395,40 +374,14 @@ module IlMachineStateExecution =
|> TypeMethodSignature.map
state
(fun state typeDefn ->
// Concretize each TypeDefn in the signature
let ctx =
{
TypeConcretization.ConcretizationContext.InProgress = ImmutableDictionary.Empty
TypeConcretization.ConcretizationContext.ConcreteTypes = state.ConcreteTypes
TypeConcretization.ConcretizationContext.LoadedAssemblies = state._LoadedAssemblies
TypeConcretization.ConcretizationContext.BaseTypes = corelib
}
let handle, ctx =
TypeConcretization.concretizeType
ctx
(fun assyName ref ->
let currentAssy = state.LoadedAssembly assyName |> Option.get
let targetAssy =
currentAssy.AssemblyReferences.[ref].Name
|> state.LoadedAssembly
|> Option.get
state._LoadedAssemblies, targetAssy
)
concreteType.Assembly
concreteType.Generics
ImmutableArray.Empty // no method generics for cctor
typeDefn
let state =
{ state with
_LoadedAssemblies = ctx.LoadedAssemblies
ConcreteTypes = ctx.ConcreteTypes
}
state, handle
IlMachineState.concretizeType
baseClassTypes
state
concreteType.Assembly
concreteType.Generics
// no method generics for cctor
ImmutableArray.Empty
typeDefn
)
// Convert method instructions (local variables)
@@ -444,41 +397,15 @@ module IlMachineStateExecution =
let state, convertedVars =
((state, []), localVars)
||> Seq.fold (fun (state, acc) typeDefn ->
let ctx =
{
TypeConcretization.ConcretizationContext.InProgress =
ImmutableDictionary.Empty
TypeConcretization.ConcretizationContext.ConcreteTypes =
state.ConcreteTypes
TypeConcretization.ConcretizationContext.LoadedAssemblies =
state._LoadedAssemblies
TypeConcretization.ConcretizationContext.BaseTypes = corelib
}
let handle, ctx =
TypeConcretization.concretizeType
ctx
(fun assyName ref ->
let currentAssy = state.LoadedAssembly assyName |> Option.get
let targetAssy =
currentAssy.AssemblyReferences.[ref].Name
|> state.LoadedAssembly
|> Option.get
state._LoadedAssemblies, targetAssy
)
let state, handle =
IlMachineState.concretizeType
baseClassTypes
state
concreteType.Assembly
concreteType.Generics
ImmutableArray.Empty // no method generics for cctor
typeDefn
let state =
{ state with
_LoadedAssemblies = ctx.LoadedAssemblies
ConcreteTypes = ctx.ConcreteTypes
}
state, handle :: acc
)
|> Tuple.rmap ImmutableArray.CreateRange
@@ -492,7 +419,7 @@ module IlMachineStateExecution =
callMethod
loggerFactory
corelib
baseClassTypes
(Some ty)
None
true
@@ -516,7 +443,7 @@ module IlMachineStateExecution =
let ensureTypeInitialised
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(thread : ThreadId)
(ty : ConcreteTypeHandle)
(state : IlMachineState)
@@ -524,7 +451,7 @@ module IlMachineStateExecution =
=
match TypeInitTable.tryGet ty state.TypeInitTable with
| None ->
match loadClass loggerFactory corelib ty thread state with
match loadClass loggerFactory baseClassTypes ty thread state with
| NothingToDo state -> state, WhatWeDid.Executed
| FirstLoadThis state -> state, WhatWeDid.SuspendedForClassInit
| Some TypeInitState.Initialized -> state, WhatWeDid.Executed
@@ -541,7 +468,7 @@ module IlMachineStateExecution =
/// another call to its function pointer.)
let callMethodInActiveAssembly
(loggerFactory : ILoggerFactory)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(thread : ThreadId)
(advanceProgramCounterOfCaller : bool)
(methodGenerics : TypeDefn ImmutableArray option)
@@ -556,7 +483,7 @@ module IlMachineStateExecution =
let state, concretizedMethod, declaringTypeHandle =
IlMachineState.concretizeMethodForExecution
loggerFactory
corelib
baseClassTypes
thread
methodToCall
methodGenerics
@@ -564,13 +491,13 @@ module IlMachineStateExecution =
state
let state, typeInit =
ensureTypeInitialised loggerFactory corelib thread declaringTypeHandle state
ensureTypeInitialised loggerFactory baseClassTypes thread declaringTypeHandle state
match typeInit with
| WhatWeDid.Executed ->
callMethod
loggerFactory
corelib
baseClassTypes
None
weAreConstructingObj
false

View File

@@ -234,5 +234,8 @@ module Intrinsics =
else
failwith "TODO: unexpected params to String.op_Implicit"
| _ -> failwith "TODO: unexpected params to String.op_Implicit"
| "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
failwith "TODO: array initialization"
| a, b, c -> failwith $"TODO: implement JIT intrinsic {a}.{b}.{c}"
|> Option.map (fun s -> s.WithThreadSwitchedToAssembly callerAssy currentThread |> fst)

View File

@@ -137,7 +137,7 @@ and MethodState =
/// If `method` is static, `args` must be of length numParams.
static member Empty
(concreteTypes : AllConcreteTypes)
(corelib : BaseClassTypes<DumpedAssembly>)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(loadedAssemblies : ImmutableDictionary<string, DumpedAssembly>)
(containingAssembly : DumpedAssembly)
(method : WoofWare.PawPrint.MethodInfo<ConcreteTypeHandle, ConcreteTypeHandle, ConcreteTypeHandle>)
@@ -172,7 +172,7 @@ and MethodState =
// Note: This assumes all types have already been concretized
// If this fails with "ConcreteTypeHandle not found", it means
// we need to ensure types are concretized before creating the MethodState
let zero, _ = CliType.zeroOf concreteTypes loadedAssemblies corelib var
let zero, _ = CliType.zeroOf concreteTypes loadedAssemblies baseClassTypes var
result.Add zero
result.ToImmutable ()

View File

@@ -46,7 +46,9 @@ module NullaryIlOp =
| ManagedPointerSource.LocalVariable (sourceThread, methodFrame, whichVar) ->
state.ThreadState.[sourceThread].MethodStates.[methodFrame].LocalVariables.[int<uint16> whichVar]
| ManagedPointerSource.Heap managedHeapAddress -> failwith "TODO: Heap pointer dereferencing not implemented"
| ManagedPointerSource.ArrayIndex _ -> failwith "TODO: array index pointer dereferencing not implemented"
| ManagedPointerSource.ArrayIndex (arr, index) ->
let arr = state.ManagedHeap.Arrays.[arr]
arr.Elements.[index]
// Unified Ldind implementation
let private executeLdind

View File

@@ -337,7 +337,12 @@ module internal UnaryMetadataIlOp =
let typeGenerics = concretizedCtor.DeclaringType.Generics
let state, fieldZeros =
((state, []), ctorType.Fields)
// Only include instance fields when constructing objects
let instanceFields =
ctorType.Fields
|> List.filter (fun field -> not (field.Attributes.HasFlag FieldAttributes.Static))
((state, []), instanceFields)
||> List.fold (fun (state, zeros) field ->
// TODO: generics
let state, zero =
@@ -1071,15 +1076,11 @@ module internal UnaryMetadataIlOp =
let state =
match metadataToken with
| MetadataToken.FieldDefinition h ->
let ty = baseClassTypes.RuntimeFieldHandle
// this is a struct; it contains one field, an IRuntimeFieldInfo
// https://github.com/dotnet/runtime/blob/1d1bf92fcf43aa6981804dc53c5174445069c9e4/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs#L1097
let field = ty.Fields |> List.exactlyOne
// TODO: how do we know what concrete type this is a field on?
let runtimeFieldHandle, state =
IlMachineState.getOrAllocateField loggerFactory baseClassTypes activeAssy.Name h state
if field.Name <> "m_ptr" then
failwith $"unexpected field name ${field.Name} for BCL type RuntimeFieldHandle"
failwith ""
IlMachineState.pushToEvalStack runtimeFieldHandle thread state
| MetadataToken.MethodDef h ->
let ty = baseClassTypes.RuntimeMethodHandle
let field = ty.Fields |> List.exactlyOne
@@ -1095,34 +1096,17 @@ module internal UnaryMetadataIlOp =
let typeGenerics = currentMethod.DeclaringType.Generics
if not (methodGenerics.IsEmpty && typeGenerics.IsEmpty) then
failwith "TODO: generics"
let state, typeDefn = lookupTypeDefn baseClassTypes state activeAssy h
let ctx =
{
TypeConcretization.ConcretizationContext.InProgress = ImmutableDictionary.Empty
TypeConcretization.ConcretizationContext.ConcreteTypes = state.ConcreteTypes
TypeConcretization.ConcretizationContext.LoadedAssemblies = state._LoadedAssemblies
TypeConcretization.ConcretizationContext.BaseTypes = baseClassTypes
}
let handle, newCtx =
TypeConcretization.concretizeType
ctx
(fun _ _ -> failwith "getAssembly not needed for type def concretization")
let state, handle =
IlMachineState.concretizeType
baseClassTypes
state
activeAssy.Name
typeGenerics
methodGenerics
typeDefn
let state =
{ state with
_LoadedAssemblies = newCtx.LoadedAssemblies
ConcreteTypes = newCtx.ConcreteTypes
}
let alloc, state = IlMachineState.getOrAllocateType baseClassTypes handle state
let vt =
@@ -1148,29 +1132,15 @@ module internal UnaryMetadataIlOp =
lookupTypeRef loggerFactory baseClassTypes state activeAssy currentMethod.DeclaringType.Generics ref
| _ -> failwith $"unexpected token {metadataToken} in Sizeof"
let ctx =
{
TypeConcretization.ConcretizationContext.InProgress = ImmutableDictionary.Empty
TypeConcretization.ConcretizationContext.ConcreteTypes = state.ConcreteTypes
TypeConcretization.ConcretizationContext.LoadedAssemblies = state._LoadedAssemblies
TypeConcretization.ConcretizationContext.BaseTypes = baseClassTypes
}
let typeHandle, newCtx =
TypeConcretization.concretizeType
ctx
(fun _ _ -> failwith "getAssembly not needed for base type concretization")
let state, typeHandle =
IlMachineState.concretizeType
baseClassTypes
state
assy.Name
currentMethod.DeclaringType.Generics
currentMethod.Generics
ty
let state =
{ state with
_LoadedAssemblies = newCtx.LoadedAssemblies
ConcreteTypes = newCtx.ConcreteTypes
}
let zero, state = IlMachineState.cliTypeZeroOfHandle state baseClassTypes typeHandle
let size = CliType.sizeOf zero

View File

@@ -12,6 +12,7 @@
<Compile Include="AbstractMachineDomain.fs" />
<Compile Include="BasicCliType.fs" />
<Compile Include="TypeHandleRegistry.fs" />
<Compile Include="FieldHandleRegistry.fs" />
<Compile Include="ManagedHeap.fs" />
<Compile Include="TypeInitialisation.fs" />
<Compile Include="Exceptions.fs" />