mirror of
https://github.com/Smaug123/WoofWare.PawPrint
synced 2025-10-16 19:08:40 +00:00
Compare commits
9 Commits
1b1b00b4dd
...
55677a507b
Author | SHA1 | Date | |
---|---|---|---|
|
55677a507b | ||
|
3930cc5fbb | ||
|
735449d4df | ||
|
6c73f14a4e | ||
|
4de0dbd816 | ||
|
5bd0f779c5 | ||
|
4e8c852b56 | ||
|
91aff34d1e | ||
|
f9e186ba8f |
@@ -423,8 +423,8 @@ module Assembly =
|
|||||||
let rec resolveTypeRef
|
let rec resolveTypeRef
|
||||||
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
|
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
|
||||||
(referencedInAssembly : DumpedAssembly)
|
(referencedInAssembly : DumpedAssembly)
|
||||||
(target : TypeRef)
|
|
||||||
(genericArgs : ImmutableArray<TypeDefn>)
|
(genericArgs : ImmutableArray<TypeDefn>)
|
||||||
|
(target : TypeRef)
|
||||||
: TypeResolutionResult
|
: TypeResolutionResult
|
||||||
=
|
=
|
||||||
match target.ResolutionScope with
|
match target.ResolutionScope with
|
||||||
@@ -495,7 +495,7 @@ module Assembly =
|
|||||||
| None ->
|
| None ->
|
||||||
|
|
||||||
match assy.TypeRef ns name with
|
match assy.TypeRef ns name with
|
||||||
| Some typeRef -> resolveTypeRef assemblies assy typeRef genericArgs
|
| Some typeRef -> resolveTypeRef assemblies assy genericArgs typeRef
|
||||||
| None ->
|
| None ->
|
||||||
|
|
||||||
match assy.ExportedType (Some ns) name with
|
match assy.ExportedType (Some ns) name with
|
||||||
@@ -532,7 +532,7 @@ module DumpedAssembly =
|
|||||||
| Some (BaseTypeInfo.TypeRef r) ->
|
| Some (BaseTypeInfo.TypeRef r) ->
|
||||||
let assy = loadedAssemblies.[source.FullName]
|
let assy = loadedAssemblies.[source.FullName]
|
||||||
// TODO: generics
|
// TODO: generics
|
||||||
match Assembly.resolveTypeRef loadedAssemblies assy assy.TypeRefs.[r] ImmutableArray.Empty with
|
match Assembly.resolveTypeRef loadedAssemblies assy ImmutableArray.Empty assy.TypeRefs.[r] with
|
||||||
| TypeResolutionResult.FirstLoadAssy _ ->
|
| TypeResolutionResult.FirstLoadAssy _ ->
|
||||||
failwith
|
failwith
|
||||||
"seems pretty unlikely that we could have constructed this object without loading its base type"
|
"seems pretty unlikely that we could have constructed this object without loading its base type"
|
||||||
@@ -560,3 +560,35 @@ module DumpedAssembly =
|
|||||||
| None -> ResolvedBaseType.Object
|
| None -> ResolvedBaseType.Object
|
||||||
|
|
||||||
go source baseTypeInfo
|
go source baseTypeInfo
|
||||||
|
|
||||||
|
let typeInfoToTypeDefn
|
||||||
|
(bct : BaseClassTypes<DumpedAssembly>)
|
||||||
|
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
|
||||||
|
(ti : TypeInfo<TypeDefn, TypeDefn>)
|
||||||
|
=
|
||||||
|
ti
|
||||||
|
|> TypeInfo.toTypeDefn
|
||||||
|
bct
|
||||||
|
(fun n -> assemblies.[n.FullName])
|
||||||
|
_.Name
|
||||||
|
(fun x y -> x.TypeDefs.[y])
|
||||||
|
(fun x y ->
|
||||||
|
let r = x.TypeRefs.[y] |> Assembly.resolveTypeRef assemblies x ImmutableArray.Empty
|
||||||
|
|
||||||
|
match r with
|
||||||
|
| TypeResolutionResult.FirstLoadAssy assemblyReference -> failwith "todo"
|
||||||
|
| TypeResolutionResult.Resolved (dumpedAssembly, typeInfo) ->
|
||||||
|
let result =
|
||||||
|
typeInfo |> TypeInfo.mapGeneric (fun typeDef -> failwith "TODO: generics")
|
||||||
|
|
||||||
|
dumpedAssembly, result
|
||||||
|
)
|
||||||
|
|
||||||
|
let typeInfoToTypeDefn'
|
||||||
|
(bct : BaseClassTypes<DumpedAssembly>)
|
||||||
|
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
|
||||||
|
(ti : TypeInfo<GenericParamFromMetadata, TypeDefn>)
|
||||||
|
=
|
||||||
|
ti
|
||||||
|
|> TypeInfo.mapGeneric (fun (par, _) -> TypeDefn.GenericTypeParameter par.SequenceNumber)
|
||||||
|
|> typeInfoToTypeDefn bct assemblies
|
||||||
|
@@ -420,7 +420,7 @@ module TypeConcretization =
|
|||||||
|
|
||||||
// First try to resolve without loading new assemblies
|
// First try to resolve without loading new assemblies
|
||||||
let resolutionResult =
|
let resolutionResult =
|
||||||
Assembly.resolveTypeRef ctx.LoadedAssemblies currentAssy typeRef ImmutableArray.Empty
|
Assembly.resolveTypeRef ctx.LoadedAssemblies currentAssy ImmutableArray.Empty typeRef
|
||||||
|
|
||||||
match resolutionResult with
|
match resolutionResult with
|
||||||
| TypeResolutionResult.Resolved (targetAssy, typeInfo) -> (targetAssy, typeInfo), ctx
|
| TypeResolutionResult.Resolved (targetAssy, typeInfo) -> (targetAssy, typeInfo), ctx
|
||||||
@@ -437,7 +437,7 @@ module TypeConcretization =
|
|||||||
|
|
||||||
// Now try to resolve again with the loaded assembly
|
// Now try to resolve again with the loaded assembly
|
||||||
let resolutionResult2 =
|
let resolutionResult2 =
|
||||||
Assembly.resolveTypeRef newCtx.LoadedAssemblies currentAssy typeRef ImmutableArray.Empty
|
Assembly.resolveTypeRef newCtx.LoadedAssemblies currentAssy ImmutableArray.Empty typeRef
|
||||||
|
|
||||||
match resolutionResult2 with
|
match resolutionResult2 with
|
||||||
| TypeResolutionResult.Resolved (targetAssy, typeInfo) -> (targetAssy, typeInfo), newCtx
|
| TypeResolutionResult.Resolved (targetAssy, typeInfo) -> (targetAssy, typeInfo), newCtx
|
||||||
@@ -608,14 +608,14 @@ module TypeConcretization =
|
|||||||
|
|
||||||
/// Concretize a type in a specific generic context
|
/// Concretize a type in a specific generic context
|
||||||
let rec concretizeType
|
let rec concretizeType
|
||||||
(ctx : ConcretizationContext<'corelib>)
|
(ctx : ConcretizationContext<DumpedAssembly>)
|
||||||
(loadAssembly :
|
(loadAssembly :
|
||||||
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
||||||
(assembly : AssemblyName)
|
(assembly : AssemblyName)
|
||||||
(typeGenerics : ImmutableArray<ConcreteTypeHandle>)
|
(typeGenerics : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(methodGenerics : ImmutableArray<ConcreteTypeHandle>)
|
(methodGenerics : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(typeDefn : TypeDefn)
|
(typeDefn : TypeDefn)
|
||||||
: ConcreteTypeHandle * ConcretizationContext<'corelib>
|
: ConcreteTypeHandle * ConcretizationContext<DumpedAssembly>
|
||||||
=
|
=
|
||||||
|
|
||||||
let key = (assembly, typeDefn)
|
let key = (assembly, typeDefn)
|
||||||
@@ -705,7 +705,7 @@ module TypeConcretization =
|
|||||||
| _ -> failwithf "TODO: Concretization of %A not implemented" typeDefn
|
| _ -> failwithf "TODO: Concretization of %A not implemented" typeDefn
|
||||||
|
|
||||||
and private concretizeGenericInstantiation
|
and private concretizeGenericInstantiation
|
||||||
(ctx : ConcretizationContext<'corelib>)
|
(ctx : ConcretizationContext<DumpedAssembly>)
|
||||||
(loadAssembly :
|
(loadAssembly :
|
||||||
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
||||||
(assembly : AssemblyName)
|
(assembly : AssemblyName)
|
||||||
@@ -713,7 +713,7 @@ module TypeConcretization =
|
|||||||
(methodGenerics : ImmutableArray<ConcreteTypeHandle>)
|
(methodGenerics : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(genericDef : TypeDefn)
|
(genericDef : TypeDefn)
|
||||||
(args : ImmutableArray<TypeDefn>)
|
(args : ImmutableArray<TypeDefn>)
|
||||||
: ConcreteTypeHandle * ConcretizationContext<'corelib>
|
: ConcreteTypeHandle * ConcretizationContext<DumpedAssembly>
|
||||||
=
|
=
|
||||||
// First, concretize all type arguments
|
// First, concretize all type arguments
|
||||||
let argHandles, ctxAfterArgs =
|
let argHandles, ctxAfterArgs =
|
||||||
@@ -864,14 +864,14 @@ module Concretization =
|
|||||||
|
|
||||||
/// Helper to concretize an array of types
|
/// Helper to concretize an array of types
|
||||||
let private concretizeTypeArray
|
let private concretizeTypeArray
|
||||||
(ctx : TypeConcretization.ConcretizationContext<'corelib>)
|
(ctx : TypeConcretization.ConcretizationContext<DumpedAssembly>)
|
||||||
(loadAssembly :
|
(loadAssembly :
|
||||||
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
||||||
(assembly : AssemblyName)
|
(assembly : AssemblyName)
|
||||||
(typeArgs : ImmutableArray<ConcreteTypeHandle>)
|
(typeArgs : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(methodArgs : ImmutableArray<ConcreteTypeHandle>)
|
(methodArgs : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(types : ImmutableArray<TypeDefn>)
|
(types : ImmutableArray<TypeDefn>)
|
||||||
: ImmutableArray<ConcreteTypeHandle> * TypeConcretization.ConcretizationContext<'corelib>
|
: ImmutableArray<ConcreteTypeHandle> * TypeConcretization.ConcretizationContext<DumpedAssembly>
|
||||||
=
|
=
|
||||||
|
|
||||||
let handles = ImmutableArray.CreateBuilder types.Length
|
let handles = ImmutableArray.CreateBuilder types.Length
|
||||||
@@ -888,14 +888,14 @@ module Concretization =
|
|||||||
|
|
||||||
/// Helper to concretize a method signature
|
/// Helper to concretize a method signature
|
||||||
let private concretizeMethodSignature
|
let private concretizeMethodSignature
|
||||||
(ctx : TypeConcretization.ConcretizationContext<'corelib>)
|
(ctx : TypeConcretization.ConcretizationContext<DumpedAssembly>)
|
||||||
(loadAssembly :
|
(loadAssembly :
|
||||||
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
|
||||||
(assembly : AssemblyName)
|
(assembly : AssemblyName)
|
||||||
(typeArgs : ImmutableArray<ConcreteTypeHandle>)
|
(typeArgs : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(methodArgs : ImmutableArray<ConcreteTypeHandle>)
|
(methodArgs : ImmutableArray<ConcreteTypeHandle>)
|
||||||
(signature : TypeMethodSignature<TypeDefn>)
|
(signature : TypeMethodSignature<TypeDefn>)
|
||||||
: TypeMethodSignature<ConcreteTypeHandle> * TypeConcretization.ConcretizationContext<'corelib>
|
: TypeMethodSignature<ConcreteTypeHandle> * TypeConcretization.ConcretizationContext<DumpedAssembly>
|
||||||
=
|
=
|
||||||
|
|
||||||
// Concretize return type
|
// Concretize return type
|
||||||
@@ -1157,8 +1157,7 @@ module Concretization =
|
|||||||
// Recursively convert generic arguments
|
// Recursively convert generic arguments
|
||||||
let genericArgs =
|
let genericArgs =
|
||||||
concreteType.Generics
|
concreteType.Generics
|
||||||
|> Seq.map (fun h -> concreteHandleToTypeDefn baseClassTypes h concreteTypes assemblies)
|
|> ImmutableArray.map (fun h -> concreteHandleToTypeDefn baseClassTypes h concreteTypes assemblies)
|
||||||
|> ImmutableArray.CreateRange
|
|
||||||
|
|
||||||
let baseDef =
|
let baseDef =
|
||||||
TypeDefn.FromDefinition (concreteType.Definition, concreteType.Assembly.FullName, signatureTypeKind)
|
TypeDefn.FromDefinition (concreteType.Definition, concreteType.Assembly.FullName, signatureTypeKind)
|
||||||
|
@@ -348,10 +348,10 @@ module TypeInfo =
|
|||||||
|
|
||||||
let rec resolveBaseType<'corelib, 'generic, 'field>
|
let rec resolveBaseType<'corelib, 'generic, 'field>
|
||||||
(baseClassTypes : BaseClassTypes<'corelib>)
|
(baseClassTypes : BaseClassTypes<'corelib>)
|
||||||
|
(sourceAssy : 'corelib)
|
||||||
(getName : 'corelib -> AssemblyName)
|
(getName : 'corelib -> AssemblyName)
|
||||||
(getTypeDef : 'corelib -> TypeDefinitionHandle -> TypeInfo<'generic, 'field>)
|
(getTypeDef : 'corelib -> TypeDefinitionHandle -> TypeInfo<'generic, 'field>)
|
||||||
(getTypeRef : 'corelib -> TypeReferenceHandle -> TypeInfo<'generic, 'field>)
|
(getTypeRef : 'corelib -> TypeReferenceHandle -> 'corelib * TypeInfo<'generic, 'field>)
|
||||||
(sourceAssembly : AssemblyName)
|
|
||||||
(value : BaseTypeInfo option)
|
(value : BaseTypeInfo option)
|
||||||
: ResolvedBaseType
|
: ResolvedBaseType
|
||||||
=
|
=
|
||||||
@@ -361,40 +361,48 @@ module TypeInfo =
|
|||||||
|
|
||||||
match value with
|
match value with
|
||||||
| BaseTypeInfo.TypeDef typeDefinitionHandle ->
|
| BaseTypeInfo.TypeDef typeDefinitionHandle ->
|
||||||
match isBaseType baseClassTypes getName sourceAssembly typeDefinitionHandle with
|
match isBaseType baseClassTypes getName (getName sourceAssy) typeDefinitionHandle with
|
||||||
| Some x -> x
|
| Some x -> x
|
||||||
| None ->
|
| None ->
|
||||||
let baseType = getTypeDef baseClassTypes.Corelib typeDefinitionHandle
|
let baseType = getTypeDef baseClassTypes.Corelib typeDefinitionHandle
|
||||||
resolveBaseType baseClassTypes getName getTypeDef getTypeRef sourceAssembly baseType.BaseType
|
resolveBaseType baseClassTypes sourceAssy getName getTypeDef getTypeRef baseType.BaseType
|
||||||
| BaseTypeInfo.TypeRef typeReferenceHandle ->
|
| BaseTypeInfo.TypeRef typeReferenceHandle ->
|
||||||
let typeRef = getTypeRef baseClassTypes.Corelib typeReferenceHandle
|
let targetAssy, typeRef = getTypeRef sourceAssy typeReferenceHandle
|
||||||
failwith $"{typeRef}"
|
|
||||||
|
match isBaseType baseClassTypes getName (getName targetAssy) typeRef.TypeDefHandle with
|
||||||
|
| Some x -> x
|
||||||
|
| None ->
|
||||||
|
let baseType = getTypeDef baseClassTypes.Corelib typeRef.TypeDefHandle
|
||||||
|
resolveBaseType baseClassTypes sourceAssy getName getTypeDef getTypeRef baseType.BaseType
|
||||||
| BaseTypeInfo.TypeSpec typeSpecificationHandle -> failwith "todo"
|
| BaseTypeInfo.TypeSpec typeSpecificationHandle -> failwith "todo"
|
||||||
| BaseTypeInfo.ForeignAssemblyType (assemblyName, typeDefinitionHandle) ->
|
| BaseTypeInfo.ForeignAssemblyType (assemblyName, typeDefinitionHandle) ->
|
||||||
resolveBaseType
|
resolveBaseType
|
||||||
baseClassTypes
|
baseClassTypes
|
||||||
|
sourceAssy
|
||||||
getName
|
getName
|
||||||
getTypeDef
|
getTypeDef
|
||||||
getTypeRef
|
getTypeRef
|
||||||
assemblyName
|
|
||||||
(Some (BaseTypeInfo.TypeDef typeDefinitionHandle))
|
(Some (BaseTypeInfo.TypeDef typeDefinitionHandle))
|
||||||
|
|
||||||
let toTypeDefn
|
let toTypeDefn
|
||||||
(baseClassTypes : BaseClassTypes<'corelib>)
|
(baseClassTypes : BaseClassTypes<'corelib>)
|
||||||
|
(assemblies : AssemblyName -> 'corelib)
|
||||||
(getName : 'corelib -> AssemblyName)
|
(getName : 'corelib -> AssemblyName)
|
||||||
(getTypeDef : 'corelib -> TypeDefinitionHandle -> TypeInfo<'generic, 'field>)
|
(getTypeDef : 'corelib -> TypeDefinitionHandle -> TypeInfo<'generic, 'field>)
|
||||||
(getTypeRef : 'corelib -> TypeReferenceHandle -> TypeInfo<'generic, 'field>)
|
(getTypeRef : 'corelib -> TypeReferenceHandle -> 'corelib * TypeInfo<'generic, 'field>)
|
||||||
(ty : TypeInfo<TypeDefn, TypeDefn>)
|
(ty : TypeInfo<TypeDefn, TypeDefn>)
|
||||||
: TypeDefn
|
: TypeDefn
|
||||||
=
|
=
|
||||||
let stk =
|
let stk =
|
||||||
match resolveBaseType baseClassTypes getName getTypeDef getTypeRef ty.Assembly ty.BaseType with
|
match resolveBaseType baseClassTypes (assemblies ty.Assembly) getName getTypeDef getTypeRef ty.BaseType with
|
||||||
| ResolvedBaseType.Enum
|
| ResolvedBaseType.Enum
|
||||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
||||||
| ResolvedBaseType.Object
|
| ResolvedBaseType.Object
|
||||||
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
||||||
|
|
||||||
let defn =
|
let defn =
|
||||||
|
// The only allowed construction of FromDefinition!
|
||||||
|
// All other constructions should use DumpedAssembly.typeInfoToTypeDefn.
|
||||||
TypeDefn.FromDefinition (ComparableTypeDefinitionHandle.Make ty.TypeDefHandle, ty.Assembly.FullName, stk)
|
TypeDefn.FromDefinition (ComparableTypeDefinitionHandle.Make ty.TypeDefHandle, ty.Assembly.FullName, stk)
|
||||||
|
|
||||||
if ty.Generics.IsEmpty then
|
if ty.Generics.IsEmpty then
|
||||||
|
@@ -48,7 +48,7 @@ module TestPureCases =
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
FileName = "ResizeArray.cs"
|
FileName = "ResizeArray.cs"
|
||||||
ExpectedReturnCode = 109
|
ExpectedReturnCode = 114
|
||||||
NativeImpls = MockEnv.make ()
|
NativeImpls = MockEnv.make ()
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@@ -61,6 +61,16 @@ module TestPureCases =
|
|||||||
ExpectedReturnCode = 0
|
ExpectedReturnCode = 0
|
||||||
NativeImpls = MockEnv.make ()
|
NativeImpls = MockEnv.make ()
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
FileName = "AdvancedStructLayout.cs"
|
||||||
|
ExpectedReturnCode = 0
|
||||||
|
NativeImpls = MockEnv.make ()
|
||||||
|
}
|
||||||
|
{
|
||||||
|
FileName = "OverlappingStructs.cs"
|
||||||
|
ExpectedReturnCode = 0
|
||||||
|
NativeImpls = MockEnv.make ()
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
let cases : EndToEndTestCase list =
|
let cases : EndToEndTestCase list =
|
||||||
@@ -183,11 +193,12 @@ module TestPureCases =
|
|||||||
use peImage = new MemoryStream (image)
|
use peImage = new MemoryStream (image)
|
||||||
|
|
||||||
try
|
try
|
||||||
|
let realResult = RealRuntime.executeWithRealRuntime [||] image
|
||||||
|
realResult.ExitCode |> shouldEqual case.ExpectedReturnCode
|
||||||
|
|
||||||
let terminalState, terminatingThread =
|
let terminalState, terminatingThread =
|
||||||
Program.run loggerFactory (Some case.FileName) peImage dotnetRuntimes case.NativeImpls []
|
Program.run loggerFactory (Some case.FileName) peImage dotnetRuntimes case.NativeImpls []
|
||||||
|
|
||||||
let realResult = RealRuntime.executeWithRealRuntime [||] image
|
|
||||||
|
|
||||||
let exitCode =
|
let exitCode =
|
||||||
match terminalState.ThreadState.[terminatingThread].MethodState.EvaluationStack.Values with
|
match terminalState.ThreadState.[terminatingThread].MethodState.EvaluationStack.Values with
|
||||||
| [] -> failwith "expected program to return a value, but it returned void"
|
| [] -> failwith "expected program to return a value, but it returned void"
|
||||||
@@ -198,7 +209,6 @@ module TestPureCases =
|
|||||||
|
|
||||||
exitCode |> shouldEqual realResult.ExitCode
|
exitCode |> shouldEqual realResult.ExitCode
|
||||||
|
|
||||||
exitCode |> shouldEqual case.ExpectedReturnCode
|
|
||||||
with _ ->
|
with _ ->
|
||||||
for message in messages () do
|
for message in messages () do
|
||||||
System.Console.Error.WriteLine $"{message}"
|
System.Console.Error.WriteLine $"{message}"
|
||||||
|
@@ -8,7 +8,7 @@ namespace HelloWorldApp
|
|||||||
{
|
{
|
||||||
int[] array = new[] { 1, 2, 3 };
|
int[] array = new[] { 1, 2, 3 };
|
||||||
|
|
||||||
if (array.Sum() != 60)
|
if (array.Sum() != 6)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@@ -124,9 +124,12 @@ public class TestInitobj
|
|||||||
{
|
{
|
||||||
ObjectRef = new object(),
|
ObjectRef = new object(),
|
||||||
StringRef = "Hello",
|
StringRef = "Hello",
|
||||||
ArrayRef = new int[] { 1, 2, 3 },
|
ArrayRef = new int[3],
|
||||||
ValueField = 42
|
ValueField = 42
|
||||||
};
|
};
|
||||||
|
c.ArrayRef[0] = 1;
|
||||||
|
c.ArrayRef[1] = 2;
|
||||||
|
c.ArrayRef[2] = 3;
|
||||||
|
|
||||||
// Verify initial values
|
// Verify initial values
|
||||||
if (c.ObjectRef == null) return 30;
|
if (c.ObjectRef == null) return 30;
|
||||||
|
@@ -191,7 +191,7 @@ public class StructLayoutTests
|
|||||||
|
|
||||||
static int TestStructPassing()
|
static int TestStructPassing()
|
||||||
{
|
{
|
||||||
var s = new SequentialStruct { A = 500, B = 50, C = 5000 };
|
var s = new SequentialStruct { A = 500, B = 50, C = 5005 };
|
||||||
int result = ProcessSequential(s);
|
int result = ProcessSequential(s);
|
||||||
if (result != 555) return 50; // 500 + 50 + 5 (C % 1000)
|
if (result != 555) return 50; // 500 + 50 + 5 (C % 1000)
|
||||||
|
|
||||||
|
@@ -273,3 +273,4 @@ public class TestUnsafeAs
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -139,6 +139,18 @@ module CliRuntimePointerSource =
|
|||||||
let a = ofManagedPointerSource a
|
let a = ofManagedPointerSource a
|
||||||
CliRuntimePointerSource.Field (a, ind)
|
CliRuntimePointerSource.Field (a, ind)
|
||||||
|
|
||||||
|
let rec toManagedPointerSource (ptrSource : CliRuntimePointerSource) : ManagedPointerSource =
|
||||||
|
match ptrSource with
|
||||||
|
| CliRuntimePointerSource.LocalVariable (sourceThread, methodFrame, whichVar) ->
|
||||||
|
ManagedPointerSource.LocalVariable (sourceThread, methodFrame, whichVar)
|
||||||
|
| CliRuntimePointerSource.Argument (sourceThread, methodFrame, whichVar) ->
|
||||||
|
ManagedPointerSource.Argument (sourceThread, methodFrame, whichVar)
|
||||||
|
| CliRuntimePointerSource.Heap managedHeapAddress -> ManagedPointerSource.Heap managedHeapAddress
|
||||||
|
| CliRuntimePointerSource.Null -> ManagedPointerSource.Null
|
||||||
|
| CliRuntimePointerSource.ArrayIndex (arr, ind) -> ManagedPointerSource.ArrayIndex (arr, ind)
|
||||||
|
| CliRuntimePointerSource.Field (a, ind) ->
|
||||||
|
let a = toManagedPointerSource a
|
||||||
|
ManagedPointerSource.Field (a, ind)
|
||||||
|
|
||||||
type CliRuntimePointer =
|
type CliRuntimePointer =
|
||||||
| Unmanaged of int64
|
| Unmanaged of int64
|
||||||
|
@@ -320,7 +320,7 @@ module EvalStackValue =
|
|||||||
| CliRuntimePointerSource.Heap addr -> EvalStackValue.ObjectRef addr
|
| CliRuntimePointerSource.Heap addr -> EvalStackValue.ObjectRef addr
|
||||||
| CliRuntimePointerSource.Null -> EvalStackValue.ManagedPointer ManagedPointerSource.Null
|
| CliRuntimePointerSource.Null -> EvalStackValue.ManagedPointer ManagedPointerSource.Null
|
||||||
| CliRuntimePointerSource.Field (source, fieldName) ->
|
| CliRuntimePointerSource.Field (source, fieldName) ->
|
||||||
ManagedPointerSource.Field (failwith "TODO", fieldName)
|
ManagedPointerSource.Field (CliRuntimePointerSource.toManagedPointerSource source, fieldName)
|
||||||
|> EvalStackValue.ManagedPointer
|
|> EvalStackValue.ManagedPointer
|
||||||
| CliType.ValueType fields ->
|
| CliType.ValueType fields ->
|
||||||
// TODO: this is a bit dubious; we're being a bit sloppy with possibly-overlapping fields here
|
// TODO: this is a bit dubious; we're being a bit sloppy with possibly-overlapping fields here
|
||||||
|
@@ -284,7 +284,7 @@ module IlMachineState =
|
|||||||
(state : IlMachineState)
|
(state : IlMachineState)
|
||||||
: IlMachineState * DumpedAssembly * WoofWare.PawPrint.TypeInfo<TypeDefn, TypeDefn>
|
: IlMachineState * DumpedAssembly * WoofWare.PawPrint.TypeInfo<TypeDefn, TypeDefn>
|
||||||
=
|
=
|
||||||
match Assembly.resolveTypeRef state._LoadedAssemblies referencedInAssembly target typeGenericArgs with
|
match Assembly.resolveTypeRef state._LoadedAssemblies referencedInAssembly typeGenericArgs target with
|
||||||
| TypeResolutionResult.Resolved (assy, typeDef) -> state, assy, typeDef
|
| TypeResolutionResult.Resolved (assy, typeDef) -> state, assy, typeDef
|
||||||
| TypeResolutionResult.FirstLoadAssy loadFirst ->
|
| TypeResolutionResult.FirstLoadAssy loadFirst ->
|
||||||
let state, _, _ =
|
let state, _, _ =
|
||||||
@@ -335,36 +335,8 @@ module IlMachineState =
|
|||||||
assy
|
assy
|
||||||
state
|
state
|
||||||
|
|
||||||
// If the resolved argument has generics, create a GenericInstantiation
|
|
||||||
// Otherwise, create a FromDefinition
|
|
||||||
let preservedArg =
|
let preservedArg =
|
||||||
let baseType =
|
DumpedAssembly.typeInfoToTypeDefn baseClassTypes state._LoadedAssemblies resolvedArg
|
||||||
resolvedArg.BaseType
|
|
||||||
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies assy.Name
|
|
||||||
|
|
||||||
let signatureTypeKind =
|
|
||||||
match baseType with
|
|
||||||
| ResolvedBaseType.Enum
|
|
||||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
|
||||||
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
|
||||||
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
|
||||||
|
|
||||||
if resolvedArg.Generics.IsEmpty then
|
|
||||||
TypeDefn.FromDefinition (
|
|
||||||
ComparableTypeDefinitionHandle.Make resolvedArg.TypeDefHandle,
|
|
||||||
assy.Name.FullName,
|
|
||||||
signatureTypeKind
|
|
||||||
)
|
|
||||||
else
|
|
||||||
// Preserve the generic instantiation
|
|
||||||
let genericDef =
|
|
||||||
TypeDefn.FromDefinition (
|
|
||||||
ComparableTypeDefinitionHandle.Make resolvedArg.TypeDefHandle,
|
|
||||||
assy.Name.FullName,
|
|
||||||
signatureTypeKind
|
|
||||||
)
|
|
||||||
|
|
||||||
TypeDefn.GenericInstantiation (genericDef, resolvedArg.Generics)
|
|
||||||
|
|
||||||
args'.Add preservedArg
|
args'.Add preservedArg
|
||||||
|
|
||||||
@@ -448,25 +420,23 @@ module IlMachineState =
|
|||||||
// Convert ConcreteTypeHandle to TypeDefn
|
// Convert ConcreteTypeHandle to TypeDefn
|
||||||
let typeGenericArgsAsDefn =
|
let typeGenericArgsAsDefn =
|
||||||
typeGenericArgs
|
typeGenericArgs
|
||||||
|> Seq.map (fun handle ->
|
|> ImmutableArray.map (fun handle ->
|
||||||
Concretization.concreteHandleToTypeDefn
|
Concretization.concreteHandleToTypeDefn
|
||||||
baseClassTypes
|
baseClassTypes
|
||||||
handle
|
handle
|
||||||
state.ConcreteTypes
|
state.ConcreteTypes
|
||||||
state._LoadedAssemblies
|
state._LoadedAssemblies
|
||||||
)
|
)
|
||||||
|> ImmutableArray.CreateRange
|
|
||||||
|
|
||||||
let methodGenericArgsAsDefn =
|
let methodGenericArgsAsDefn =
|
||||||
methodGenericArgs
|
methodGenericArgs
|
||||||
|> Seq.map (fun handle ->
|
|> ImmutableArray.map (fun handle ->
|
||||||
Concretization.concreteHandleToTypeDefn
|
Concretization.concreteHandleToTypeDefn
|
||||||
baseClassTypes
|
baseClassTypes
|
||||||
handle
|
handle
|
||||||
state.ConcreteTypes
|
state.ConcreteTypes
|
||||||
state._LoadedAssemblies
|
state._LoadedAssemblies
|
||||||
)
|
)
|
||||||
|> ImmutableArray.CreateRange
|
|
||||||
|
|
||||||
resolveTypeFromDefn loggerFactory baseClassTypes sign typeGenericArgsAsDefn methodGenericArgsAsDefn assy state
|
resolveTypeFromDefn loggerFactory baseClassTypes sign typeGenericArgsAsDefn methodGenericArgsAsDefn assy state
|
||||||
|
|
||||||
@@ -546,13 +516,13 @@ module IlMachineState =
|
|||||||
/// Concretize a ConcreteType<TypeDefn> to get a ConcreteTypeHandle for static field access
|
/// Concretize a ConcreteType<TypeDefn> to get a ConcreteTypeHandle for static field access
|
||||||
let concretizeFieldDeclaringType
|
let concretizeFieldDeclaringType
|
||||||
(loggerFactory : ILoggerFactory)
|
(loggerFactory : ILoggerFactory)
|
||||||
(baseClassTypes : BaseClassTypes<'corelib>)
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
(declaringType : ConcreteType<TypeDefn>)
|
(declaringType : ConcreteType<TypeDefn>)
|
||||||
(state : IlMachineState)
|
(state : IlMachineState)
|
||||||
: ConcreteTypeHandle * IlMachineState
|
: ConcreteTypeHandle * IlMachineState
|
||||||
=
|
=
|
||||||
// Create a concretization context from the current state
|
// Create a concretization context from the current state
|
||||||
let ctx : TypeConcretization.ConcretizationContext<'corelib> =
|
let ctx : TypeConcretization.ConcretizationContext<_> =
|
||||||
{
|
{
|
||||||
InProgress = ImmutableDictionary.Empty
|
InProgress = ImmutableDictionary.Empty
|
||||||
ConcreteTypes = state.ConcreteTypes
|
ConcreteTypes = state.ConcreteTypes
|
||||||
@@ -1484,6 +1454,48 @@ module IlMachineState =
|
|||||||
let getSyncBlock (addr : ManagedHeapAddress) (state : IlMachineState) : SyncBlock =
|
let getSyncBlock (addr : ManagedHeapAddress) (state : IlMachineState) : SyncBlock =
|
||||||
state.ManagedHeap |> ManagedHeap.getSyncBlock addr
|
state.ManagedHeap |> ManagedHeap.getSyncBlock addr
|
||||||
|
|
||||||
|
let getFieldValue (obj : ManagedPointerSource) (fieldName : string) (state : IlMachineState) : CliType =
|
||||||
|
match obj with
|
||||||
|
| ManagedPointerSource.LocalVariable (sourceThread, methodFrame, whichVar) ->
|
||||||
|
getLocalVariable sourceThread methodFrame whichVar state
|
||||||
|
|> CliType.getField fieldName
|
||||||
|
| ManagedPointerSource.Argument (sourceThread, methodFrame, whichVar) -> failwith "todo"
|
||||||
|
| ManagedPointerSource.Heap addr ->
|
||||||
|
ManagedHeap.get addr state.ManagedHeap
|
||||||
|
|> AllocatedNonArrayObject.DereferenceField fieldName
|
||||||
|
| ManagedPointerSource.ArrayIndex (arr, index) -> getArrayValue arr index state |> CliType.getField fieldName
|
||||||
|
| ManagedPointerSource.Field (src, fieldName) -> failwith "todo"
|
||||||
|
| ManagedPointerSource.Null -> failwith "TODO: throw NRE"
|
||||||
|
|
||||||
|
let setFieldValue
|
||||||
|
(obj : ManagedPointerSource)
|
||||||
|
(v : CliType)
|
||||||
|
(fieldName : string)
|
||||||
|
(state : IlMachineState)
|
||||||
|
: IlMachineState
|
||||||
|
=
|
||||||
|
match obj with
|
||||||
|
| ManagedPointerSource.LocalVariable (sourceThread, methodFrame, whichVar) ->
|
||||||
|
let v =
|
||||||
|
getLocalVariable sourceThread methodFrame whichVar state
|
||||||
|
|> CliType.withFieldSet fieldName v
|
||||||
|
|
||||||
|
state |> setLocalVariable sourceThread methodFrame whichVar v
|
||||||
|
| ManagedPointerSource.Argument (sourceThread, methodFrame, whichVar) -> failwith "todo"
|
||||||
|
| ManagedPointerSource.Heap addr ->
|
||||||
|
let newValue =
|
||||||
|
ManagedHeap.get addr state.ManagedHeap
|
||||||
|
|> AllocatedNonArrayObject.SetField fieldName v
|
||||||
|
|
||||||
|
{ state with
|
||||||
|
ManagedHeap = ManagedHeap.set addr newValue state.ManagedHeap
|
||||||
|
}
|
||||||
|
| ManagedPointerSource.ArrayIndex (arr, index) ->
|
||||||
|
let v = getArrayValue arr index state |> CliType.withFieldSet fieldName v
|
||||||
|
state |> setArrayValue arr v index
|
||||||
|
| ManagedPointerSource.Field (managedPointerSource, fieldName) -> failwith "todo"
|
||||||
|
| ManagedPointerSource.Null -> failwith "TODO: throw NRE"
|
||||||
|
|
||||||
let executeDelegateConstructor (instruction : MethodState) (state : IlMachineState) : IlMachineState =
|
let executeDelegateConstructor (instruction : MethodState) (state : IlMachineState) : IlMachineState =
|
||||||
// We've been called with arguments already popped from the stack into local arguments.
|
// We've been called with arguments already popped from the stack into local arguments.
|
||||||
let constructing = instruction.Arguments.[0]
|
let constructing = instruction.Arguments.[0]
|
||||||
@@ -1666,42 +1678,7 @@ module IlMachineState =
|
|||||||
: IlMachineState * TypeDefn
|
: IlMachineState * TypeDefn
|
||||||
=
|
=
|
||||||
let defn = activeAssy.TypeDefs.[typeDef]
|
let defn = activeAssy.TypeDefs.[typeDef]
|
||||||
|
state, DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies defn
|
||||||
let baseType =
|
|
||||||
defn.BaseType
|
|
||||||
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies defn.Assembly
|
|
||||||
|
|
||||||
let signatureTypeKind =
|
|
||||||
match baseType with
|
|
||||||
| ResolvedBaseType.Enum
|
|
||||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
|
||||||
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
|
||||||
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
|
||||||
|
|
||||||
let result =
|
|
||||||
if defn.Generics.IsEmpty then
|
|
||||||
TypeDefn.FromDefinition (
|
|
||||||
ComparableTypeDefinitionHandle.Make defn.TypeDefHandle,
|
|
||||||
defn.Assembly.FullName,
|
|
||||||
signatureTypeKind
|
|
||||||
)
|
|
||||||
else
|
|
||||||
// Preserve the generic instantiation by converting GenericParameters to TypeDefn.GenericTypeParameter
|
|
||||||
let genericDef =
|
|
||||||
TypeDefn.FromDefinition (
|
|
||||||
ComparableTypeDefinitionHandle.Make defn.TypeDefHandle,
|
|
||||||
defn.Assembly.FullName,
|
|
||||||
signatureTypeKind
|
|
||||||
)
|
|
||||||
|
|
||||||
let genericArgs =
|
|
||||||
defn.Generics
|
|
||||||
|> Seq.mapi (fun i _ -> TypeDefn.GenericTypeParameter i)
|
|
||||||
|> ImmutableArray.CreateRange
|
|
||||||
|
|
||||||
TypeDefn.GenericInstantiation (genericDef, genericArgs)
|
|
||||||
|
|
||||||
state, result
|
|
||||||
|
|
||||||
let lookupTypeRef
|
let lookupTypeRef
|
||||||
(loggerFactory : ILoggerFactory)
|
(loggerFactory : ILoggerFactory)
|
||||||
@@ -1729,25 +1706,4 @@ module IlMachineState =
|
|||||||
let state, assy, resolved =
|
let state, assy, resolved =
|
||||||
resolveTypeFromRef loggerFactory activeAssy ref typeGenerics state
|
resolveTypeFromRef loggerFactory activeAssy ref typeGenerics state
|
||||||
|
|
||||||
let baseType =
|
state, DumpedAssembly.typeInfoToTypeDefn baseClassTypes state._LoadedAssemblies resolved, assy
|
||||||
resolved.BaseType
|
|
||||||
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies assy.Name
|
|
||||||
|
|
||||||
let signatureTypeKind =
|
|
||||||
match baseType with
|
|
||||||
| ResolvedBaseType.Enum
|
|
||||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
|
||||||
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
|
||||||
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
|
||||||
|
|
||||||
let result =
|
|
||||||
TypeDefn.FromDefinition (
|
|
||||||
ComparableTypeDefinitionHandle.Make resolved.TypeDefHandle,
|
|
||||||
assy.Name.FullName,
|
|
||||||
signatureTypeKind
|
|
||||||
)
|
|
||||||
|
|
||||||
if resolved.Generics.IsEmpty then
|
|
||||||
state, result, assy
|
|
||||||
else
|
|
||||||
failwith "TODO: add generics"
|
|
||||||
|
@@ -17,11 +17,7 @@ module IlMachineStateExecution =
|
|||||||
=
|
=
|
||||||
match esv with
|
match esv with
|
||||||
| EvalStackValue.Int32 _ ->
|
| EvalStackValue.Int32 _ ->
|
||||||
TypeDefn.FromDefinition (
|
DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies baseClassTypes.Int32
|
||||||
ComparableTypeDefinitionHandle.Make baseClassTypes.Int32.TypeDefHandle,
|
|
||||||
baseClassTypes.Corelib.Name.FullName,
|
|
||||||
SignatureTypeKind.ValueType
|
|
||||||
)
|
|
||||||
|> IlMachineState.concretizeType
|
|> IlMachineState.concretizeType
|
||||||
baseClassTypes
|
baseClassTypes
|
||||||
state
|
state
|
||||||
@@ -29,11 +25,7 @@ module IlMachineStateExecution =
|
|||||||
ImmutableArray.Empty
|
ImmutableArray.Empty
|
||||||
ImmutableArray.Empty
|
ImmutableArray.Empty
|
||||||
| EvalStackValue.Int64 _ ->
|
| EvalStackValue.Int64 _ ->
|
||||||
TypeDefn.FromDefinition (
|
DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies baseClassTypes.Int64
|
||||||
ComparableTypeDefinitionHandle.Make baseClassTypes.Int64.TypeDefHandle,
|
|
||||||
baseClassTypes.Corelib.Name.FullName,
|
|
||||||
SignatureTypeKind.ValueType
|
|
||||||
)
|
|
||||||
|> IlMachineState.concretizeType
|
|> IlMachineState.concretizeType
|
||||||
baseClassTypes
|
baseClassTypes
|
||||||
state
|
state
|
||||||
@@ -42,11 +34,7 @@ module IlMachineStateExecution =
|
|||||||
ImmutableArray.Empty
|
ImmutableArray.Empty
|
||||||
| EvalStackValue.NativeInt nativeIntSource -> failwith "todo"
|
| EvalStackValue.NativeInt nativeIntSource -> failwith "todo"
|
||||||
| EvalStackValue.Float _ ->
|
| EvalStackValue.Float _ ->
|
||||||
TypeDefn.FromDefinition (
|
DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies baseClassTypes.Double
|
||||||
ComparableTypeDefinitionHandle.Make baseClassTypes.Double.TypeDefHandle,
|
|
||||||
baseClassTypes.Corelib.Name.FullName,
|
|
||||||
SignatureTypeKind.ValueType
|
|
||||||
)
|
|
||||||
|> IlMachineState.concretizeType
|
|> IlMachineState.concretizeType
|
||||||
baseClassTypes
|
baseClassTypes
|
||||||
state
|
state
|
||||||
@@ -579,30 +567,8 @@ module IlMachineStateExecution =
|
|||||||
typeDef.Name
|
typeDef.Name
|
||||||
)
|
)
|
||||||
|
|
||||||
// TypeDef won't have any generics; it would be a TypeSpec if it did
|
|
||||||
// Create a TypeDefn from the TypeDef handle
|
|
||||||
let baseTypeDefn =
|
let baseTypeDefn =
|
||||||
let baseTypeDef = sourceAssembly.TypeDefs.[typeDefinitionHandle]
|
DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies typeDef
|
||||||
|
|
||||||
let baseType =
|
|
||||||
baseTypeDef.BaseType
|
|
||||||
|> DumpedAssembly.resolveBaseType
|
|
||||||
baseClassTypes
|
|
||||||
state._LoadedAssemblies
|
|
||||||
sourceAssembly.Name
|
|
||||||
|
|
||||||
let signatureTypeKind =
|
|
||||||
match baseType with
|
|
||||||
| ResolvedBaseType.Enum
|
|
||||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
|
||||||
| ResolvedBaseType.Object
|
|
||||||
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
|
||||||
|
|
||||||
TypeDefn.FromDefinition (
|
|
||||||
ComparableTypeDefinitionHandle.Make typeDefinitionHandle,
|
|
||||||
sourceAssembly.Name.FullName,
|
|
||||||
signatureTypeKind
|
|
||||||
)
|
|
||||||
|
|
||||||
// Concretize the base type
|
// Concretize the base type
|
||||||
let state, baseTypeHandle =
|
let state, baseTypeHandle =
|
||||||
@@ -640,22 +606,8 @@ module IlMachineStateExecution =
|
|||||||
|
|
||||||
// Create a TypeDefn from the resolved TypeRef
|
// Create a TypeDefn from the resolved TypeRef
|
||||||
let baseTypeDefn =
|
let baseTypeDefn =
|
||||||
let baseType =
|
targetType
|
||||||
targetType.BaseType
|
|> DumpedAssembly.typeInfoToTypeDefn baseClassTypes state._LoadedAssemblies
|
||||||
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies assy.Name
|
|
||||||
|
|
||||||
let signatureTypeKind =
|
|
||||||
match baseType with
|
|
||||||
| ResolvedBaseType.Enum
|
|
||||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
|
||||||
| ResolvedBaseType.Object
|
|
||||||
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
|
||||||
|
|
||||||
TypeDefn.FromDefinition (
|
|
||||||
ComparableTypeDefinitionHandle.Make targetType.TypeDefHandle,
|
|
||||||
assy.Name.FullName,
|
|
||||||
signatureTypeKind
|
|
||||||
)
|
|
||||||
|
|
||||||
// Concretize the base type
|
// Concretize the base type
|
||||||
let state, baseTypeHandle =
|
let state, baseTypeHandle =
|
||||||
|
@@ -76,6 +76,7 @@ module Intrinsics =
|
|||||||
| [ field ] -> go field.ContentsEval
|
| [ field ] -> go field.ContentsEval
|
||||||
| _ -> failwith $"TODO: %O{vt}"
|
| _ -> failwith $"TODO: %O{vt}"
|
||||||
| EvalStackValue.ManagedPointer ManagedPointerSource.Null -> failwith "TODO: throw NRE"
|
| EvalStackValue.ManagedPointer ManagedPointerSource.Null -> failwith "TODO: throw NRE"
|
||||||
|
| EvalStackValue.ObjectRef addr
|
||||||
| EvalStackValue.ManagedPointer (ManagedPointerSource.Heap addr) -> Some addr
|
| EvalStackValue.ManagedPointer (ManagedPointerSource.Heap addr) -> Some addr
|
||||||
| s -> failwith $"TODO: called with unrecognised arg %O{s}"
|
| s -> failwith $"TODO: called with unrecognised arg %O{s}"
|
||||||
|
|
||||||
@@ -228,7 +229,10 @@ module Intrinsics =
|
|||||||
let arg1 = ManagedHeap.get arg1 state.ManagedHeap
|
let arg1 = ManagedHeap.get arg1 state.ManagedHeap
|
||||||
let arg2 = ManagedHeap.get arg2 state.ManagedHeap
|
let arg2 = ManagedHeap.get arg2 state.ManagedHeap
|
||||||
|
|
||||||
if AllocatedNonArrayObject.DereferenceField "_firstChar" arg1 <> AllocatedNonArrayObject.DereferenceField "_firstChar" arg2 then
|
if
|
||||||
|
AllocatedNonArrayObject.DereferenceField "_firstChar" arg1
|
||||||
|
<> AllocatedNonArrayObject.DereferenceField "_firstChar" arg2
|
||||||
|
then
|
||||||
state
|
state
|
||||||
|> IlMachineState.pushToEvalStack (CliType.ofBool false) currentThread
|
|> IlMachineState.pushToEvalStack (CliType.ofBool false) currentThread
|
||||||
|> IlMachineState.advanceProgramCounter currentThread
|
|> IlMachineState.advanceProgramCounter currentThread
|
||||||
|
@@ -17,6 +17,29 @@ type AllocatedNonArrayObject =
|
|||||||
// TODO: this is wrong, it doesn't account for overlapping fields
|
// TODO: this is wrong, it doesn't account for overlapping fields
|
||||||
f.Fields |> List.find (fun f -> f.Name = name) |> _.Contents
|
f.Fields |> List.find (fun f -> f.Name = name) |> _.Contents
|
||||||
|
|
||||||
|
static member SetField (name : string) (v : CliType) (f : AllocatedNonArrayObject) : AllocatedNonArrayObject =
|
||||||
|
// TODO: this is wrong, it doesn't account for overlapping fields
|
||||||
|
let contents =
|
||||||
|
{
|
||||||
|
Name = name
|
||||||
|
Contents = v
|
||||||
|
Offset = None
|
||||||
|
}
|
||||||
|
|
||||||
|
{ f with
|
||||||
|
Fields =
|
||||||
|
f.Fields
|
||||||
|
|> List.replaceWhere (fun f ->
|
||||||
|
if f.Name = name then
|
||||||
|
Some
|
||||||
|
{ contents with
|
||||||
|
Offset = f.Offset
|
||||||
|
}
|
||||||
|
else
|
||||||
|
None
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
type AllocatedArray =
|
type AllocatedArray =
|
||||||
{
|
{
|
||||||
Length : int
|
Length : int
|
||||||
@@ -125,6 +148,12 @@ module ManagedHeap =
|
|||||||
// TODO: arrays too
|
// TODO: arrays too
|
||||||
heap.NonArrayObjects.[alloc]
|
heap.NonArrayObjects.[alloc]
|
||||||
|
|
||||||
|
let set (alloc : ManagedHeapAddress) (v : AllocatedNonArrayObject) (heap : ManagedHeap) : ManagedHeap =
|
||||||
|
// TODO: arrays too
|
||||||
|
{ heap with
|
||||||
|
NonArrayObjects = heap.NonArrayObjects |> Map.add alloc v
|
||||||
|
}
|
||||||
|
|
||||||
let setArrayValue (alloc : ManagedHeapAddress) (offset : int) (v : CliType) (heap : ManagedHeap) : ManagedHeap =
|
let setArrayValue (alloc : ManagedHeapAddress) (offset : int) (v : CliType) (heap : ManagedHeap) : ManagedHeap =
|
||||||
let newArrs =
|
let newArrs =
|
||||||
heap.Arrays
|
heap.Arrays
|
||||||
|
@@ -112,7 +112,7 @@ module NullaryIlOp =
|
|||||||
}
|
}
|
||||||
| ManagedPointerSource.Heap managedHeapAddress -> failwith "todo"
|
| ManagedPointerSource.Heap managedHeapAddress -> failwith "todo"
|
||||||
| ManagedPointerSource.ArrayIndex _ -> failwith "todo"
|
| ManagedPointerSource.ArrayIndex _ -> failwith "todo"
|
||||||
| Field (managedPointerSource, fieldName) -> failwith "todo"
|
| ManagedPointerSource.Field (managedPointerSource, fieldName) -> failwith "todo"
|
||||||
| EvalStackValue.ObjectRef managedHeapAddress -> failwith "todo"
|
| EvalStackValue.ObjectRef managedHeapAddress -> failwith "todo"
|
||||||
|
|
||||||
let internal ldElem
|
let internal ldElem
|
||||||
|
@@ -16,11 +16,7 @@ module Program =
|
|||||||
: ManagedHeapAddress * IlMachineState
|
: ManagedHeapAddress * IlMachineState
|
||||||
=
|
=
|
||||||
let state, stringType =
|
let state, stringType =
|
||||||
TypeDefn.FromDefinition (
|
DumpedAssembly.typeInfoToTypeDefn' corelib state._LoadedAssemblies corelib.String
|
||||||
ComparableTypeDefinitionHandle.Make corelib.String.TypeDefHandle,
|
|
||||||
corelib.Corelib.Name.FullName,
|
|
||||||
SignatureTypeKind.Class
|
|
||||||
)
|
|
||||||
|> IlMachineState.concretizeType
|
|> IlMachineState.concretizeType
|
||||||
corelib
|
corelib
|
||||||
state
|
state
|
||||||
@@ -126,7 +122,7 @@ module Program =
|
|||||||
let rec go state =
|
let rec go state =
|
||||||
// Resolve the type reference to find which assembly it's in
|
// Resolve the type reference to find which assembly it's in
|
||||||
match
|
match
|
||||||
Assembly.resolveTypeRef state._LoadedAssemblies currentAssembly typeRef ImmutableArray.Empty
|
Assembly.resolveTypeRef state._LoadedAssemblies currentAssembly ImmutableArray.Empty typeRef
|
||||||
with
|
with
|
||||||
| TypeResolutionResult.FirstLoadAssy assyRef ->
|
| TypeResolutionResult.FirstLoadAssy assyRef ->
|
||||||
// Need to load this assembly first
|
// Need to load this assembly first
|
||||||
|
@@ -107,8 +107,8 @@ module internal UnaryConstIlOp =
|
|||||||
| EvalStackValue.NativeInt i -> not (NativeIntSource.isZero i)
|
| EvalStackValue.NativeInt i -> not (NativeIntSource.isZero i)
|
||||||
| EvalStackValue.Float f -> failwith "TODO: Brfalse_s float semantics undocumented"
|
| EvalStackValue.Float f -> failwith "TODO: Brfalse_s float semantics undocumented"
|
||||||
| EvalStackValue.ManagedPointer ManagedPointerSource.Null -> false
|
| EvalStackValue.ManagedPointer ManagedPointerSource.Null -> false
|
||||||
|
| EvalStackValue.ObjectRef _
|
||||||
| EvalStackValue.ManagedPointer _ -> true
|
| EvalStackValue.ManagedPointer _ -> true
|
||||||
| EvalStackValue.ObjectRef _ -> failwith "TODO: Brfalse_s ObjectRef comparison unimplemented"
|
|
||||||
| EvalStackValue.UserDefinedValueType _ ->
|
| EvalStackValue.UserDefinedValueType _ ->
|
||||||
failwith "TODO: Brfalse_s UserDefinedValueType comparison unimplemented"
|
failwith "TODO: Brfalse_s UserDefinedValueType comparison unimplemented"
|
||||||
|
|
||||||
@@ -129,8 +129,8 @@ module internal UnaryConstIlOp =
|
|||||||
| EvalStackValue.NativeInt i -> not (NativeIntSource.isZero i)
|
| EvalStackValue.NativeInt i -> not (NativeIntSource.isZero i)
|
||||||
| EvalStackValue.Float f -> failwith "TODO: Brtrue_s float semantics undocumented"
|
| EvalStackValue.Float f -> failwith "TODO: Brtrue_s float semantics undocumented"
|
||||||
| EvalStackValue.ManagedPointer ManagedPointerSource.Null -> false
|
| EvalStackValue.ManagedPointer ManagedPointerSource.Null -> false
|
||||||
| EvalStackValue.ManagedPointer _
|
| EvalStackValue.ObjectRef _
|
||||||
| EvalStackValue.ObjectRef _ -> true
|
| EvalStackValue.ManagedPointer _ -> true
|
||||||
| EvalStackValue.UserDefinedValueType _ ->
|
| EvalStackValue.UserDefinedValueType _ ->
|
||||||
failwith "TODO: Brtrue_s UserDefinedValueType comparison unimplemented"
|
failwith "TODO: Brtrue_s UserDefinedValueType comparison unimplemented"
|
||||||
|
|
||||||
@@ -422,7 +422,7 @@ module internal UnaryConstIlOp =
|
|||||||
| EvalStackValue.Float v1, _ -> failwith $"invalid comparison, {v1} with {value2}"
|
| EvalStackValue.Float v1, _ -> failwith $"invalid comparison, {v1} with {value2}"
|
||||||
| EvalStackValue.NativeInt v1, EvalStackValue.NativeInt v2 -> v1 <> v2
|
| EvalStackValue.NativeInt v1, EvalStackValue.NativeInt v2 -> v1 <> v2
|
||||||
| EvalStackValue.ManagedPointer ptr1, EvalStackValue.ManagedPointer ptr2 -> ptr1 <> ptr2
|
| EvalStackValue.ManagedPointer ptr1, EvalStackValue.ManagedPointer ptr2 -> ptr1 <> ptr2
|
||||||
| EvalStackValue.ObjectRef p1, EvalStackValue.ObjectRef p2 -> p1 <> p2
|
| EvalStackValue.ObjectRef ptr1, EvalStackValue.ObjectRef ptr2 -> ptr1 <> ptr2
|
||||||
| _, _ -> failwith $"TODO {value1} {value2} (see table III.4)"
|
| _, _ -> failwith $"TODO {value1} {value2} (see table III.4)"
|
||||||
|
|
||||||
state
|
state
|
||||||
|
@@ -455,22 +455,10 @@ module internal UnaryMetadataIlOp =
|
|||||||
let activeAssy = state.ActiveAssembly thread
|
let activeAssy = state.ActiveAssembly thread
|
||||||
let ty = activeAssy.TypeDefs.[td]
|
let ty = activeAssy.TypeDefs.[td]
|
||||||
|
|
||||||
let baseTy =
|
let result =
|
||||||
DumpedAssembly.resolveBaseType
|
DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies ty
|
||||||
baseClassTypes
|
|
||||||
state._LoadedAssemblies
|
|
||||||
activeAssy.Name
|
|
||||||
ty.BaseType
|
|
||||||
|
|
||||||
let sigType =
|
state, result
|
||||||
match baseTy with
|
|
||||||
| ResolvedBaseType.Enum
|
|
||||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
|
||||||
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
|
||||||
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
|
||||||
|
|
||||||
state,
|
|
||||||
TypeDefn.FromDefinition (ComparableTypeDefinitionHandle.Make td, activeAssy.Name.FullName, sigType)
|
|
||||||
| MetadataToken.TypeSpecification handle ->
|
| MetadataToken.TypeSpecification handle ->
|
||||||
state, state.ActiveAssembly(thread).TypeSpecs.[handle].Signature
|
state, state.ActiveAssembly(thread).TypeSpecs.[handle].Signature
|
||||||
| MetadataToken.TypeReference handle ->
|
| MetadataToken.TypeReference handle ->
|
||||||
@@ -482,22 +470,7 @@ module internal UnaryMetadataIlOp =
|
|||||||
ImmutableArray.Empty
|
ImmutableArray.Empty
|
||||||
state
|
state
|
||||||
|
|
||||||
let baseTy =
|
state, DumpedAssembly.typeInfoToTypeDefn baseClassTypes state._LoadedAssemblies resol
|
||||||
DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies assy.Name resol.BaseType
|
|
||||||
|
|
||||||
let sigType =
|
|
||||||
match baseTy with
|
|
||||||
| ResolvedBaseType.Enum
|
|
||||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
|
||||||
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
|
||||||
| ResolvedBaseType.Delegate -> SignatureTypeKind.Class
|
|
||||||
|
|
||||||
state,
|
|
||||||
TypeDefn.FromDefinition (
|
|
||||||
ComparableTypeDefinitionHandle.Make resol.TypeDefHandle,
|
|
||||||
assy.Name.FullName,
|
|
||||||
sigType
|
|
||||||
)
|
|
||||||
| m -> failwith $"unexpected metadata token {m} in IsInst"
|
| m -> failwith $"unexpected metadata token {m} in IsInst"
|
||||||
|
|
||||||
let state, targetConcreteType =
|
let state, targetConcreteType =
|
||||||
@@ -515,6 +488,7 @@ module internal UnaryMetadataIlOp =
|
|||||||
// null IsInstance check always succeeds and results in a null reference
|
// null IsInstance check always succeeds and results in a null reference
|
||||||
EvalStackValue.ManagedPointer ManagedPointerSource.Null
|
EvalStackValue.ManagedPointer ManagedPointerSource.Null
|
||||||
| EvalStackValue.ManagedPointer (ManagedPointerSource.LocalVariable _) -> failwith "TODO"
|
| EvalStackValue.ManagedPointer (ManagedPointerSource.LocalVariable _) -> failwith "TODO"
|
||||||
|
| EvalStackValue.ObjectRef addr
|
||||||
| EvalStackValue.ManagedPointer (ManagedPointerSource.Heap addr) ->
|
| EvalStackValue.ManagedPointer (ManagedPointerSource.Heap addr) ->
|
||||||
match state.ManagedHeap.NonArrayObjects.TryGetValue addr with
|
match state.ManagedHeap.NonArrayObjects.TryGetValue addr with
|
||||||
| true, v ->
|
| true, v ->
|
||||||
@@ -822,8 +796,11 @@ module internal UnaryMetadataIlOp =
|
|||||||
IlMachineState.pushToEvalStack currentValue thread state
|
IlMachineState.pushToEvalStack currentValue thread state
|
||||||
| EvalStackValue.ManagedPointer ManagedPointerSource.Null ->
|
| EvalStackValue.ManagedPointer ManagedPointerSource.Null ->
|
||||||
failwith "TODO: raise NullReferenceException"
|
failwith "TODO: raise NullReferenceException"
|
||||||
| EvalStackValue.ManagedPointer (ManagedPointerSource.Field _) ->
|
| EvalStackValue.ManagedPointer (ManagedPointerSource.Field (src, fieldName)) ->
|
||||||
failwith "TODO: get a field on a field ptr"
|
let currentValue =
|
||||||
|
IlMachineState.getFieldValue src fieldName state |> CliType.getField field.Name
|
||||||
|
|
||||||
|
IlMachineState.pushToEvalStack currentValue thread state
|
||||||
| EvalStackValue.UserDefinedValueType vt ->
|
| EvalStackValue.UserDefinedValueType vt ->
|
||||||
let result = vt |> EvalStackValueUserType.DereferenceField field.Name
|
let result = vt |> EvalStackValueUserType.DereferenceField field.Name
|
||||||
|
|
||||||
@@ -834,70 +811,51 @@ module internal UnaryMetadataIlOp =
|
|||||||
|> Tuple.withRight WhatWeDid.Executed
|
|> Tuple.withRight WhatWeDid.Executed
|
||||||
|
|
||||||
| Ldflda ->
|
| Ldflda ->
|
||||||
|
let ptr, state = IlMachineState.popEvalStack thread state
|
||||||
|
|
||||||
|
let ptr =
|
||||||
|
match ptr with
|
||||||
|
| Int32 _
|
||||||
|
| Int64 _
|
||||||
|
| Float _ -> failwith "expected pointer type"
|
||||||
|
| NativeInt nativeIntSource -> failwith "todo"
|
||||||
|
| ManagedPointer src -> src
|
||||||
|
| ObjectRef addr -> ManagedPointerSource.Heap addr
|
||||||
|
| UserDefinedValueType evalStackValueUserType -> failwith "todo"
|
||||||
|
|
||||||
let state, field =
|
let state, field =
|
||||||
match metadataToken with
|
match metadataToken with
|
||||||
| MetadataToken.FieldDefinition f ->
|
| MetadataToken.FieldDefinition f ->
|
||||||
let field = activeAssy.Fields.[f]
|
let field =
|
||||||
// Map the field to have TypeDefn type parameters
|
activeAssy.Fields.[f]
|
||||||
let mappedField =
|
|> FieldInfo.mapTypeGenerics (fun _ -> failwith "no generics allowed on FieldDefinition")
|
||||||
field |> FieldInfo.mapTypeGenerics (fun i _ -> TypeDefn.GenericTypeParameter i)
|
|
||||||
|
|
||||||
state, mappedField
|
state, field
|
||||||
| MetadataToken.MemberReference m ->
|
| MetadataToken.MemberReference mr ->
|
||||||
let state, _, resolved, _ =
|
let state, assyName, field, _ =
|
||||||
|
// TODO: generics
|
||||||
IlMachineState.resolveMember
|
IlMachineState.resolveMember
|
||||||
loggerFactory
|
loggerFactory
|
||||||
baseClassTypes
|
baseClassTypes
|
||||||
thread
|
thread
|
||||||
activeAssy
|
activeAssy
|
||||||
ImmutableArray.Empty
|
ImmutableArray.Empty
|
||||||
m
|
mr
|
||||||
state
|
state
|
||||||
|
|
||||||
match resolved with
|
match field with
|
||||||
|
| Choice1Of2 _method -> failwith "member reference was unexpectedly a method"
|
||||||
| Choice2Of2 field -> state, field
|
| Choice2Of2 field -> state, field
|
||||||
| Choice1Of2 _ -> failwith "Expected field in Ldflda but got method"
|
| t -> failwith $"Unexpectedly asked to load from a non-field: {t}"
|
||||||
| _ -> failwith $"Unexpected in Ldflda: {metadataToken}"
|
|
||||||
|
|
||||||
let source, state = IlMachineState.popEvalStack thread state
|
let result =
|
||||||
|
ManagedPointerSource.Field (ptr, field.Name) |> EvalStackValue.ManagedPointer
|
||||||
// Ldflda needs to return a pointer to the field within the object/struct
|
|
||||||
let toPush =
|
|
||||||
match source with
|
|
||||||
| EvalStackValue.ObjectRef heapAddr ->
|
|
||||||
// For object references, we need to create a pointer to the field
|
|
||||||
// TODO: The current ManagedPointerSource doesn't have a case for field pointers
|
|
||||||
// We're using Heap pointer for now, but this doesn't capture the field offset
|
|
||||||
// This will need to be enhanced to support field-specific pointers
|
|
||||||
ManagedPointerSource.Heap heapAddr |> EvalStackValue.ManagedPointer
|
|
||||||
| EvalStackValue.ManagedPointer ptr ->
|
|
||||||
// If we already have a managed pointer, we need to handle field access
|
|
||||||
// through that pointer. For now, return the same pointer type
|
|
||||||
// TODO: This needs to track the field offset within the pointed-to object
|
|
||||||
match ptr with
|
|
||||||
| ManagedPointerSource.Null -> failwith "TODO: NullReferenceException in Ldflda"
|
|
||||||
| _ -> ptr |> EvalStackValue.ManagedPointer
|
|
||||||
| EvalStackValue.NativeInt (NativeIntSource.ManagedPointer ptr) ->
|
|
||||||
// Unmanaged pointer input produces unmanaged pointer output
|
|
||||||
// TODO: This also needs field offset tracking
|
|
||||||
match ptr with
|
|
||||||
| ManagedPointerSource.Null -> failwith "TODO: NullReferenceException in Ldflda"
|
|
||||||
| _ -> ptr |> NativeIntSource.ManagedPointer |> EvalStackValue.NativeInt
|
|
||||||
| EvalStackValue.NativeInt (NativeIntSource.Verbatim _) ->
|
|
||||||
// Native int that's not from a managed pointer
|
|
||||||
// This represents an unmanaged pointer scenario
|
|
||||||
failwith "TODO: Ldflda with unmanaged pointer - not allowed in verifiable code"
|
|
||||||
| EvalStackValue.UserDefinedValueType vt ->
|
|
||||||
// For value types on the stack, we need to store them somewhere
|
|
||||||
// and return a pointer to the field
|
|
||||||
// This is complex because we need to materialize the value type
|
|
||||||
failwith "TODO: Ldflda on value type - need to allocate temporary storage and create field pointer"
|
|
||||||
| _ -> failwith $"unexpected Ldflda source: {source}"
|
|
||||||
|
|
||||||
state
|
state
|
||||||
|> IlMachineState.pushToEvalStack' toPush thread
|
|> IlMachineState.pushToEvalStack' result thread
|
||||||
|> IlMachineState.advanceProgramCounter thread
|
|> IlMachineState.advanceProgramCounter thread
|
||||||
|> Tuple.withRight WhatWeDid.Executed
|
|> Tuple.withRight WhatWeDid.Executed
|
||||||
|
|
||||||
| Ldsfld ->
|
| Ldsfld ->
|
||||||
let state, field =
|
let state, field =
|
||||||
match metadataToken with
|
match metadataToken with
|
||||||
@@ -1026,12 +984,7 @@ module internal UnaryMetadataIlOp =
|
|||||||
| _ -> failwith $"expected heap allocation for array, got {arr}"
|
| _ -> failwith $"expected heap allocation for array, got {arr}"
|
||||||
|
|
||||||
let elementType =
|
let elementType =
|
||||||
TypeInfo.toTypeDefn
|
DumpedAssembly.typeInfoToTypeDefn baseClassTypes state._LoadedAssemblies elementType
|
||||||
baseClassTypes
|
|
||||||
_.Name
|
|
||||||
(fun x y -> x.TypeDefs.[y])
|
|
||||||
(fun x y -> x.TypeRefs.[y] |> failwithf "%+A")
|
|
||||||
elementType
|
|
||||||
|
|
||||||
let state, zeroOfType =
|
let state, zeroOfType =
|
||||||
IlMachineState.cliTypeZeroOf
|
IlMachineState.cliTypeZeroOf
|
||||||
@@ -1100,12 +1053,18 @@ module internal UnaryMetadataIlOp =
|
|||||||
IlMachineState.pushToEvalStack toPush thread state
|
IlMachineState.pushToEvalStack toPush thread state
|
||||||
|> IlMachineState.advanceProgramCounter thread
|
|> IlMachineState.advanceProgramCounter thread
|
||||||
|> Tuple.withRight WhatWeDid.Executed
|
|> Tuple.withRight WhatWeDid.Executed
|
||||||
|
|
||||||
| Initobj ->
|
| Initobj ->
|
||||||
let addr, state = IlMachineState.popEvalStack thread state
|
let popped, state = IlMachineState.popEvalStack thread state
|
||||||
let declaringTypeGenerics = currentMethod.DeclaringType.Generics
|
let declaringTypeGenerics = currentMethod.DeclaringType.Generics
|
||||||
|
|
||||||
let state, assy, ty =
|
let state, assy, targetType =
|
||||||
match metadataToken with
|
match metadataToken with
|
||||||
|
| MetadataToken.TypeDefinition defn ->
|
||||||
|
state,
|
||||||
|
activeAssy,
|
||||||
|
activeAssy.TypeDefs.[defn]
|
||||||
|
|> TypeInfo.mapGeneric (fun (p, _) -> TypeDefn.GenericTypeParameter p.SequenceNumber)
|
||||||
| MetadataToken.TypeSpecification spec ->
|
| MetadataToken.TypeSpecification spec ->
|
||||||
let state, assy, ty =
|
let state, assy, ty =
|
||||||
IlMachineState.resolveTypeFromSpecConcrete
|
IlMachineState.resolveTypeFromSpecConcrete
|
||||||
@@ -1118,68 +1077,47 @@ module internal UnaryMetadataIlOp =
|
|||||||
state
|
state
|
||||||
|
|
||||||
state, assy, ty
|
state, assy, ty
|
||||||
| MetadataToken.TypeDefinition defn ->
|
| x -> failwith $"TODO: Ldelem element type resolution unimplemented for {x}"
|
||||||
let state, assy, ty =
|
|
||||||
IlMachineState.resolveTypeFromDefnConcrete
|
|
||||||
loggerFactory
|
|
||||||
baseClassTypes
|
|
||||||
defn
|
|
||||||
activeAssy
|
|
||||||
declaringTypeGenerics
|
|
||||||
currentMethod.Generics
|
|
||||||
state
|
|
||||||
|
|
||||||
state, assy, ty
|
let targetType =
|
||||||
| x -> failwith $"unexpected in Initobj: %O{x}"
|
targetType
|
||||||
|
|> DumpedAssembly.typeInfoToTypeDefn baseClassTypes state._LoadedAssemblies
|
||||||
|
|
||||||
|
let state, zeroOfType =
|
||||||
|
IlMachineState.cliTypeZeroOf
|
||||||
|
loggerFactory
|
||||||
|
baseClassTypes
|
||||||
|
assy
|
||||||
|
targetType
|
||||||
|
declaringTypeGenerics
|
||||||
|
ImmutableArray.Empty
|
||||||
|
state
|
||||||
|
|
||||||
let state =
|
let state =
|
||||||
match addr with
|
match popped with
|
||||||
|
| EvalStackValue.Int32 _
|
||||||
|
| EvalStackValue.Int64 _
|
||||||
|
| EvalStackValue.NativeInt _
|
||||||
|
| EvalStackValue.Float _ -> failwith "unexpectedly not an address"
|
||||||
|
| EvalStackValue.ManagedPointer (ManagedPointerSource.Heap addr)
|
||||||
|
| EvalStackValue.ObjectRef addr -> failwith "todo"
|
||||||
| EvalStackValue.ManagedPointer src ->
|
| EvalStackValue.ManagedPointer src ->
|
||||||
match src with
|
match src with
|
||||||
| ManagedPointerSource.Null -> failwith "TODO: probably NRE here"
|
|
||||||
| ManagedPointerSource.Heap _ -> failwith "TODO: heap"
|
|
||||||
| ManagedPointerSource.LocalVariable (thread, frame, var) ->
|
| ManagedPointerSource.LocalVariable (thread, frame, var) ->
|
||||||
// Create zero-initialized fields based on the type info
|
state |> IlMachineState.setLocalVariable thread frame var zeroOfType
|
||||||
let state, zeroFields =
|
| ManagedPointerSource.Argument (sourceThread, methodFrame, whichVar) -> failwith "todo"
|
||||||
((state, []), ty.Fields)
|
| ManagedPointerSource.ArrayIndex (arr, index) ->
|
||||||
||> List.fold (fun (state, acc) field ->
|
state |> IlMachineState.setArrayValue arr zeroOfType index
|
||||||
// Concretize the field type
|
| ManagedPointerSource.Field (managedPointerSource, fieldName) ->
|
||||||
let state, fieldHandle =
|
state |> IlMachineState.setFieldValue managedPointerSource zeroOfType fieldName
|
||||||
IlMachineState.concretizeType
|
| ManagedPointerSource.Null -> failwith "runtime error: unexpectedly Initobj'ing null"
|
||||||
baseClassTypes
|
| ManagedPointerSource.Heap _ -> failwith "logic error"
|
||||||
state
|
| EvalStackValue.UserDefinedValueType evalStackValueUserType -> failwith "todo"
|
||||||
assy.Name
|
|
||||||
declaringTypeGenerics
|
|
||||||
currentMethod.Generics
|
|
||||||
field.Signature
|
|
||||||
|
|
||||||
// Get zero value for the field type
|
|
||||||
let zero, state =
|
|
||||||
IlMachineState.cliTypeZeroOfHandle state baseClassTypes fieldHandle
|
|
||||||
|
|
||||||
let field =
|
|
||||||
{
|
|
||||||
Name = field.Name
|
|
||||||
Contents = zero
|
|
||||||
Offset = field.Offset
|
|
||||||
}
|
|
||||||
|
|
||||||
state, field :: acc
|
|
||||||
)
|
|
||||||
|> fun (state, fields) -> state, List.rev fields
|
|
||||||
|
|
||||||
// Create the value type with zero-initialized fields
|
|
||||||
let newValue = zeroFields |> CliValueType.OfFields |> CliType.ValueType
|
|
||||||
|
|
||||||
state |> IlMachineState.setLocalVariable thread frame var newValue
|
|
||||||
| ManagedPointerSource.Argument (thread, frame, arg) -> failwith "TODO: Argument"
|
|
||||||
| ManagedPointerSource.ArrayIndex (arr, index) -> failwith "todo: array index"
|
|
||||||
| Field (managedPointerSource, fieldName) -> failwith "todo"
|
|
||||||
| addr -> failwith $"Bad address in Initobj: {addr}"
|
|
||||||
|
|
||||||
state
|
state
|
||||||
|> IlMachineState.advanceProgramCounter thread
|
|> IlMachineState.advanceProgramCounter thread
|
||||||
|> Tuple.withRight WhatWeDid.Executed
|
|> Tuple.withRight WhatWeDid.Executed
|
||||||
|
|
||||||
| Ldsflda ->
|
| Ldsflda ->
|
||||||
|
|
||||||
// TODO: check whether we should throw FieldAccessException
|
// TODO: check whether we should throw FieldAccessException
|
||||||
@@ -1342,25 +1280,8 @@ module internal UnaryMetadataIlOp =
|
|||||||
methodGenerics
|
methodGenerics
|
||||||
state
|
state
|
||||||
|
|
||||||
let stk =
|
|
||||||
match
|
|
||||||
DumpedAssembly.resolveBaseType
|
|
||||||
baseClassTypes
|
|
||||||
state._LoadedAssemblies
|
|
||||||
assy.Name
|
|
||||||
typeDefn.BaseType
|
|
||||||
with
|
|
||||||
| ResolvedBaseType.ValueType
|
|
||||||
| ResolvedBaseType.Enum -> SignatureTypeKind.ValueType
|
|
||||||
| ResolvedBaseType.Delegate
|
|
||||||
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
|
||||||
|
|
||||||
let typeDefn =
|
let typeDefn =
|
||||||
TypeDefn.FromDefinition (
|
DumpedAssembly.typeInfoToTypeDefn baseClassTypes state._LoadedAssemblies typeDefn
|
||||||
ComparableTypeDefinitionHandle.Make typeDefn.TypeDefHandle,
|
|
||||||
assy.Name.FullName,
|
|
||||||
stk
|
|
||||||
)
|
|
||||||
|
|
||||||
let state, handle =
|
let state, handle =
|
||||||
IlMachineState.concretizeType
|
IlMachineState.concretizeType
|
||||||
@@ -1419,7 +1340,9 @@ module internal UnaryMetadataIlOp =
|
|||||||
|
|
||||||
IlMachineState.pushToEvalStack (CliType.ValueType vt) thread state
|
IlMachineState.pushToEvalStack (CliType.ValueType vt) thread state
|
||||||
| MetadataToken.TypeDefinition h ->
|
| MetadataToken.TypeDefinition h ->
|
||||||
let state, typeDefn = IlMachineState.lookupTypeDefn baseClassTypes state activeAssy h
|
let state, typeDefn =
|
||||||
|
IlMachineState.lookupTypeDefn baseClassTypes state activeAssy h
|
||||||
|
|
||||||
handleTypeToken typeDefn state
|
handleTypeToken typeDefn state
|
||||||
| _ -> failwith $"Unexpected metadata token %O{metadataToken} in LdToken"
|
| _ -> failwith $"Unexpected metadata token %O{metadataToken} in LdToken"
|
||||||
|
|
||||||
|
@@ -64,11 +64,7 @@ module internal UnaryStringTokenIlOp =
|
|||||||
]
|
]
|
||||||
|
|
||||||
let state, stringType =
|
let state, stringType =
|
||||||
TypeDefn.FromDefinition (
|
DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies baseClassTypes.String
|
||||||
ComparableTypeDefinitionHandle.Make baseClassTypes.String.TypeDefHandle,
|
|
||||||
baseClassTypes.Corelib.Name.FullName,
|
|
||||||
SignatureTypeKind.Class
|
|
||||||
)
|
|
||||||
|> IlMachineState.concretizeType
|
|> IlMachineState.concretizeType
|
||||||
baseClassTypes
|
baseClassTypes
|
||||||
state
|
state
|
||||||
|
Reference in New Issue
Block a user