35 Commits

Author SHA1 Message Date
Smaug123
a9b2598525 Progress 2025-08-24 23:47:05 +01:00
Smaug123
e05abbb724 Rejig assembly load 2025-08-24 23:20:14 +01:00
Smaug123
55677a507b Revert 2025-08-24 20:43:06 +01:00
Smaug123
3930cc5fbb More 2025-08-24 20:40:52 +01:00
Smaug123
735449d4df Revert 2025-08-24 20:40:32 +01:00
Smaug123
6c73f14a4e Merge branch 'main' into generic-edge-cases 2025-08-24 20:39:27 +01:00
Smaug123
5bd0f779c5 Merge branch 'main' into generic-edge-cases 2025-08-24 20:27:48 +01:00
Smaug123
4e8c852b56 Merge branch 'main' into generic-edge-cases 2025-08-24 20:27:39 +01:00
Smaug123
1b1b00b4dd Merge branch 'main' into generic-edge-cases 2025-08-24 10:54:23 +01:00
Smaug123
6e98652691 Revert 2025-08-24 10:07:21 +01:00
Smaug123
ec5f6ed752 Merge branch 'main' into generic-edge-cases 2025-08-24 10:06:32 +01:00
Smaug123
99e46b3756 more 2025-08-24 09:08:52 +01:00
Smaug123
35128afab4 Merge commit '9afc7efea128e46f9cd1a00adcce8e7e50aa7418' into generic-edge-cases 2025-08-24 09:06:52 +01:00
Smaug123
57b0e545c9 Merge commit '2190f148e13ed6aab310c2e867f178c7a551ec1e' into generic-edge-cases 2025-08-23 22:53:34 +01:00
Smaug123
f1db433711 Merge commit 'e2e3d5c3bf7c07fcbf89c0c69d04273aa20b0d2f' into generic-edge-cases 2025-08-23 22:53:30 +01:00
Smaug123
64339bf4ee Merge commit '92f22cff42e73c533f0d9c28e37991046a8008d7' into generic-edge-cases 2025-08-23 22:52:32 +01:00
Smaug123
2e8e6f3919 Merge commit '3bdfeaf8a1cb802ce4dce2cd12d6abd639edc75e' into generic-edge-cases 2025-08-23 22:51:41 +01:00
Smaug123
02ae05893b Merge commit '174e415c70843d905a6d40790cbdfdcf0f21cbdb' into generic-edge-cases 2025-08-23 22:51:31 +01:00
Smaug123
4b7e2ac1e6 Merge commit 'cfd67166162b7c28a6e044e5904cac53da2a194d' into generic-edge-cases 2025-08-23 22:50:11 +01:00
Smaug123
027a49c51a Merge commit 'd711d6fff5c59378a601a6366e01354cd2a43d88' into generic-edge-cases 2025-08-23 22:48:56 +01:00
Smaug123
f020d560a6 WIP 2025-08-18 23:08:15 +01:00
Smaug123
2e8245d341 WIP 2025-08-15 14:11:48 +01:00
Smaug123
fca9a6dc47 WIP 2025-08-14 08:31:32 +01:00
Smaug123
cc14fb0edd Start initobj 2025-08-12 08:39:25 +01:00
Smaug123
1dbd4b008b resolveTypeFromDefnConcrete 2025-08-12 08:15:38 +01:00
Smaug123
064deee8d5 WIP 2025-08-11 22:12:37 +01:00
Smaug123
407c37a5fb WIP 2025-08-11 21:21:12 +01:00
Smaug123
59fd8a23b7 WIP 2025-08-11 08:18:13 +01:00
Smaug123
bdedea098a Merge branch 'main' into generic-edge-cases 2025-08-10 23:29:28 +01:00
Smaug123
6f48c89ef3 More 2025-08-10 23:22:04 +01:00
Smaug123
07c5e931e4 Feature parity 2025-08-10 23:03:23 +01:00
Smaug123
e0e954b131 Remove another spare test 2025-08-10 22:52:45 +01:00
Smaug123
95f422efa9 Revert example 2025-08-10 22:50:44 +01:00
Smaug123
e89fac2780 Fix a couple of TODOs 2025-08-10 22:50:26 +01:00
Smaug123
9bafd0f4b0 WIP 2025-08-02 20:57:53 +01:00
11 changed files with 444 additions and 218 deletions

View File

@@ -331,6 +331,13 @@ module ConcreteActivePatterns =
| ConcreteTypeHandle.Pointer inner -> Some inner | ConcreteTypeHandle.Pointer inner -> Some inner
| _ -> None | _ -> None
type IAssemblyLoad =
abstract LoadAssembly :
loadedAssemblies : ImmutableDictionary<string, DumpedAssembly> ->
referencedIn : AssemblyName ->
handle : AssemblyReferenceHandle ->
ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
module TypeConcretization = module TypeConcretization =
@@ -406,8 +413,7 @@ module TypeConcretization =
// Helper function for assembly loading with retry pattern // Helper function for assembly loading with retry pattern
let private loadAssemblyAndResolveTypeRef let private loadAssemblyAndResolveTypeRef
(loadAssembly : (loadAssembly : IAssemblyLoad)
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(ctx : ConcretizationContext<'corelib>) (ctx : ConcretizationContext<'corelib>)
(currentAssembly : AssemblyName) (currentAssembly : AssemblyName)
(typeRef : TypeRef) (typeRef : TypeRef)
@@ -428,7 +434,8 @@ module TypeConcretization =
// Need to load the assembly // Need to load the assembly
match typeRef.ResolutionScope with match typeRef.ResolutionScope with
| TypeRefResolutionScope.Assembly assyRef -> | TypeRefResolutionScope.Assembly assyRef ->
let newAssemblies, _ = loadAssembly currentAssembly assyRef let newAssemblies, _ =
loadAssembly.LoadAssembly ctx.LoadedAssemblies currentAssembly assyRef
let newCtx = let newCtx =
{ ctx with { ctx with
@@ -584,8 +591,7 @@ module TypeConcretization =
ImmutableArray.Empty // No generic parameters ImmutableArray.Empty // No generic parameters
let private concretizeTypeReference let private concretizeTypeReference
(loadAssembly : (loadAssembly : IAssemblyLoad)
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(ctx : ConcretizationContext<'corelib>) (ctx : ConcretizationContext<'corelib>)
(currentAssembly : AssemblyName) (currentAssembly : AssemblyName)
(typeRef : TypeRef) (typeRef : TypeRef)
@@ -609,8 +615,7 @@ 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<DumpedAssembly>) (ctx : ConcretizationContext<DumpedAssembly>)
(loadAssembly : (loadAssembly : IAssemblyLoad)
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(assembly : AssemblyName) (assembly : AssemblyName)
(typeGenerics : ImmutableArray<ConcreteTypeHandle>) (typeGenerics : ImmutableArray<ConcreteTypeHandle>)
(methodGenerics : ImmutableArray<ConcreteTypeHandle>) (methodGenerics : ImmutableArray<ConcreteTypeHandle>)
@@ -706,8 +711,7 @@ module TypeConcretization =
and private concretizeGenericInstantiation and private concretizeGenericInstantiation
(ctx : ConcretizationContext<DumpedAssembly>) (ctx : ConcretizationContext<DumpedAssembly>)
(loadAssembly : (loadAssembly : IAssemblyLoad)
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(assembly : AssemblyName) (assembly : AssemblyName)
(typeGenerics : ImmutableArray<ConcreteTypeHandle>) (typeGenerics : ImmutableArray<ConcreteTypeHandle>)
(methodGenerics : ImmutableArray<ConcreteTypeHandle>) (methodGenerics : ImmutableArray<ConcreteTypeHandle>)
@@ -786,7 +790,8 @@ module TypeConcretization =
| false, _ -> | false, _ ->
// Need to load the assembly // Need to load the assembly
let newAssemblies, loadedAssy = loadAssembly assembly assyRef let newAssemblies, loadedAssy =
loadAssembly.LoadAssembly ctx.LoadedAssemblies assembly assyRef
let ctxWithNewAssy = let ctxWithNewAssy =
{ ctxAfterArgs with { ctxAfterArgs with
@@ -865,8 +870,7 @@ 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<DumpedAssembly>) (ctx : TypeConcretization.ConcretizationContext<DumpedAssembly>)
(loadAssembly : (loadAssembly : IAssemblyLoad)
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(assembly : AssemblyName) (assembly : AssemblyName)
(typeArgs : ImmutableArray<ConcreteTypeHandle>) (typeArgs : ImmutableArray<ConcreteTypeHandle>)
(methodArgs : ImmutableArray<ConcreteTypeHandle>) (methodArgs : ImmutableArray<ConcreteTypeHandle>)
@@ -889,8 +893,7 @@ module Concretization =
/// Helper to concretize a method signature /// Helper to concretize a method signature
let private concretizeMethodSignature let private concretizeMethodSignature
(ctx : TypeConcretization.ConcretizationContext<DumpedAssembly>) (ctx : TypeConcretization.ConcretizationContext<DumpedAssembly>)
(loadAssembly : (loadAssembly : IAssemblyLoad)
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(assembly : AssemblyName) (assembly : AssemblyName)
(typeArgs : ImmutableArray<ConcreteTypeHandle>) (typeArgs : ImmutableArray<ConcreteTypeHandle>)
(methodArgs : ImmutableArray<ConcreteTypeHandle>) (methodArgs : ImmutableArray<ConcreteTypeHandle>)
@@ -926,8 +929,7 @@ module Concretization =
/// Helper to ensure base type assembly is loaded /// Helper to ensure base type assembly is loaded
let rec private ensureBaseTypeAssembliesLoaded let rec private ensureBaseTypeAssembliesLoaded
(loadAssembly : (loadAssembly : IAssemblyLoad)
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(assemblies : ImmutableDictionary<string, DumpedAssembly>) (assemblies : ImmutableDictionary<string, DumpedAssembly>)
(assyName : AssemblyName) (assyName : AssemblyName)
(baseTypeInfo : BaseTypeInfo option) (baseTypeInfo : BaseTypeInfo option)
@@ -947,7 +949,7 @@ module Concretization =
| true, _ -> assemblies | true, _ -> assemblies
| false, _ -> | false, _ ->
// Need to load the assembly - pass the assembly that contains the reference // Need to load the assembly - pass the assembly that contains the reference
let newAssemblies, _ = loadAssembly assy.Name assyRef let newAssemblies, _ = loadAssembly.LoadAssembly assemblies assy.Name assyRef
newAssemblies newAssemblies
| _ -> assemblies | _ -> assemblies
| Some (BaseTypeInfo.TypeDef _) | Some (BaseTypeInfo.TypeDef _)
@@ -957,8 +959,7 @@ module Concretization =
/// Concretize a method's signature and body /// Concretize a method's signature and body
let concretizeMethod let concretizeMethod
(ctx : AllConcreteTypes) (ctx : AllConcreteTypes)
(loadAssembly : (loadAssembly : IAssemblyLoad)
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(assemblies : ImmutableDictionary<string, DumpedAssembly>) (assemblies : ImmutableDictionary<string, DumpedAssembly>)
(baseTypes : BaseClassTypes<DumpedAssembly>) (baseTypes : BaseClassTypes<DumpedAssembly>)
(method : WoofWare.PawPrint.MethodInfo<'ty, GenericParamFromMetadata, TypeDefn>) (method : WoofWare.PawPrint.MethodInfo<'ty, GenericParamFromMetadata, TypeDefn>)

View File

@@ -22,12 +22,17 @@ module TestPureCases =
NativeImpls = MockEnv.make () NativeImpls = MockEnv.make ()
} }
{ {
FileName = "InitializeArray.cs" FileName = "OverlappingStructs.cs"
ExpectedReturnCode = 0 ExpectedReturnCode = 0
NativeImpls = MockEnv.make () NativeImpls = MockEnv.make ()
} }
{ {
FileName = "GenericEdgeCases.cs" FileName = "AdvancedStructLayout.cs"
ExpectedReturnCode = 0
NativeImpls = MockEnv.make ()
}
{
FileName = "InitializeArray.cs"
ExpectedReturnCode = 0 ExpectedReturnCode = 0
NativeImpls = MockEnv.make () NativeImpls = MockEnv.make ()
} }
@@ -56,21 +61,6 @@ 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 ()
}
{
FileName = "UnsafeAs.cs"
ExpectedReturnCode = 0
NativeImpls = MockEnv.make ()
}
] ]
let cases : EndToEndTestCase list = let cases : EndToEndTestCase list =
@@ -80,6 +70,21 @@ module TestPureCases =
ExpectedReturnCode = 1 ExpectedReturnCode = 1
NativeImpls = MockEnv.make () NativeImpls = MockEnv.make ()
} }
{
FileName = "UnsafeAs.cs"
ExpectedReturnCode = 0
NativeImpls = MockEnv.make ()
}
{
FileName = "Initobj.cs"
ExpectedReturnCode = 0
NativeImpls = MockEnv.make ()
}
{
FileName = "GenericEdgeCases.cs"
ExpectedReturnCode = 0
NativeImpls = MockEnv.make ()
}
{ {
FileName = "TestShl.cs" FileName = "TestShl.cs"
ExpectedReturnCode = 0 ExpectedReturnCode = 0
@@ -165,11 +170,6 @@ module TestPureCases =
ExpectedReturnCode = 0 ExpectedReturnCode = 0
NativeImpls = MockEnv.make () NativeImpls = MockEnv.make ()
} }
{
FileName = "Initobj.cs"
ExpectedReturnCode = 0
NativeImpls = MockEnv.make ()
}
] ]
let runTest (case : EndToEndTestCase) : unit = let runTest (case : EndToEndTestCase) : unit =

View File

@@ -222,5 +222,5 @@ module AbstractMachine =
|> ExecutionResult.Stepped |> ExecutionResult.Stepped
| IlOp.Switch immutableArray -> failwith "TODO: Switch unimplemented" | IlOp.Switch immutableArray -> failwith "TODO: Switch unimplemented"
| IlOp.UnaryStringToken (unaryStringTokenIlOp, stringHandle) -> | IlOp.UnaryStringToken (unaryStringTokenIlOp, stringHandle) ->
UnaryStringTokenIlOp.execute baseClassTypes unaryStringTokenIlOp stringHandle state thread UnaryStringTokenIlOp.execute loggerFactory baseClassTypes unaryStringTokenIlOp stringHandle state thread
|> ExecutionResult.Stepped |> ExecutionResult.Stepped

View File

@@ -460,20 +460,22 @@ module CliType =
// The field type might reference generic parameters of the declaring type // The field type might reference generic parameters of the declaring type
let methodGenerics = ImmutableArray.Empty // Fields don't have method generics let methodGenerics = ImmutableArray.Empty // Fields don't have method generics
let loadAssembly let loadAssembly =
(assyName : AssemblyName) { new IAssemblyLoad with
(ref : AssemblyReferenceHandle) member _.LoadAssembly loaded assyName ref =
: ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly match loaded.TryGetValue assyName.FullName with
=
match assemblies.TryGetValue assyName.FullName with
| true, currentAssy -> | true, currentAssy ->
let targetAssyRef = currentAssy.AssemblyReferences.[ref] let targetAssyRef = currentAssy.AssemblyReferences.[ref]
match assemblies.TryGetValue targetAssyRef.Name.FullName with match loaded.TryGetValue targetAssyRef.Name.FullName with
| true, targetAssy -> assemblies, targetAssy | true, targetAssy -> loaded, targetAssy
| false, _ -> | false, _ ->
failwithf "Assembly %s not loaded when trying to resolve reference" targetAssyRef.Name.FullName failwithf
| false, _ -> failwithf "Current assembly %s not loaded when trying to resolve reference" assyName.FullName "Assembly %s not loaded when trying to resolve reference"
targetAssyRef.Name.FullName
| false, _ ->
failwithf "Current assembly %s not loaded when trying to resolve reference" assyName.FullName
}
let handle, newCtx = let handle, newCtx =
TypeConcretization.concretizeType TypeConcretization.concretizeType

View File

@@ -149,7 +149,73 @@ type StateLoadResult =
module IlMachineState = module IlMachineState =
type private Dummy = class end type private Dummy = class end
let private loadAssembly'
(loggerFactory : ILoggerFactory)
(dotnetRuntimeDirs : string seq)
(referencedInAssembly : DumpedAssembly)
(r : AssemblyReferenceHandle)
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
=
let assemblyRef = referencedInAssembly.AssemblyReferences.[r]
let assemblyName = assemblyRef.Name
match assemblies.TryGetValue assemblyName.FullName with
| true, v -> v, assemblyName
| false, _ ->
let logger = loggerFactory.CreateLogger typeof<Dummy>.DeclaringType
let assy =
dotnetRuntimeDirs
|> Seq.choose (fun dir ->
let file = Path.Combine (dir, assemblyName.Name + ".dll")
try
use f = File.OpenRead file
logger.LogInformation ("Loading assembly from file {AssemblyFileLoadPath}", file)
Assembly.read loggerFactory (Some file) f |> Some
with :? FileNotFoundException ->
None
)
|> Seq.toList
match assy |> List.tryHead with
| None -> failwith $"Could not find a readable DLL in any runtime dir with name %s{assemblyName.Name}.dll"
| Some assy -> assy, assemblyName
/// <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!
///
/// This function doesn't do anything if the referenced assembly has already been loaded.
/// </summary>
/// <param name="loggerFactory">LoggerFactory into which to emit logs.</param>
/// <param name="referencedInAssembly">The assembly which contains an AssemblyReference which causes us to want to load a new assembly.</param>
/// <param name="r">The AssemblyReferenceHandle pointing at an assembly we want to load. *Important*: this is an AssemblyReferenceHandle from <c>referencedInAssembly</c>; in general, AssemblyReferenceHandles are only well-defined if you know what assembly they were defined in.</param>
/// <param name="state">The immutable state to augment with the new assembly.</param>
let loadAssembly
(loggerFactory : ILoggerFactory)
(referencedInAssembly : DumpedAssembly)
(r : AssemblyReferenceHandle)
(state : IlMachineState)
: IlMachineState * DumpedAssembly * AssemblyName
=
let dumped, assy =
loadAssembly' loggerFactory state.DotnetRuntimeDirs referencedInAssembly r state._LoadedAssemblies
state.WithLoadedAssembly assy dumped, dumped, assy
let private loader (loggerFactory : ILoggerFactory) (state : IlMachineState) : IAssemblyLoad =
{ new IAssemblyLoad with
member _.LoadAssembly loaded assyName ref =
let targetAssy, name =
loadAssembly' loggerFactory state.DotnetRuntimeDirs loaded.[assyName.FullName] ref loaded
let newAssys = loaded.SetItem (name.FullName, targetAssy)
newAssys, targetAssy
}
let concretizeType let concretizeType
(loggerFactory : ILoggerFactory)
(baseClassTypes : BaseClassTypes<DumpedAssembly>) (baseClassTypes : BaseClassTypes<DumpedAssembly>)
(state : IlMachineState) (state : IlMachineState)
(declaringAssembly : AssemblyName) (declaringAssembly : AssemblyName)
@@ -169,14 +235,7 @@ module IlMachineState =
let handle, ctx = let handle, ctx =
TypeConcretization.concretizeType TypeConcretization.concretizeType
ctx ctx
(fun assyName ref -> (loader loggerFactory state)
let currentAssy = state.LoadedAssembly assyName |> Option.get
let targetAssy =
currentAssy.AssemblyReferences.[ref].Name |> state.LoadedAssembly |> Option.get
state._LoadedAssemblies, targetAssy
)
declaringAssembly declaringAssembly
typeGenerics typeGenerics
methodGenerics methodGenerics
@@ -190,51 +249,6 @@ module IlMachineState =
state, handle 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!
///
/// This function doesn't do anything if the referenced assembly has already been loaded.
/// </summary>
/// <param name="loggerFactory">LoggerFactory into which to emit logs.</param>
/// <param name="referencedInAssembly">The assembly which contains an AssemblyReference which causes us to want to load a new assembly.</param>
/// <param name="r">The AssemblyReferenceHandle pointing at an assembly we want to load. *Important*: this is an AssemblyReferenceHandle from <c>referencedInAssembly</c>; in general, AssemblyReferenceHandles are only well-defined if you know what assembly they were defined in.</param>
/// <param name="state">The immutable state to augment with the new assembly.</param>
let loadAssembly
(loggerFactory : ILoggerFactory)
(referencedInAssembly : DumpedAssembly)
(r : AssemblyReferenceHandle)
(state : IlMachineState)
: IlMachineState * DumpedAssembly * AssemblyName
=
let assemblyRef = referencedInAssembly.AssemblyReferences.[r]
let assemblyName = assemblyRef.Name
match state.LoadedAssembly assemblyName with
| Some v -> state, v, assemblyName
| None ->
let logger = loggerFactory.CreateLogger typeof<Dummy>.DeclaringType
let assy =
state.DotnetRuntimeDirs
|> Seq.choose (fun dir ->
let file = Path.Combine (dir, assemblyName.Name + ".dll")
try
use f = File.OpenRead file
logger.LogInformation ("Loading assembly from file {AssemblyFileLoadPath}", file)
Assembly.read loggerFactory (Some file) f |> Some
with :? FileNotFoundException ->
None
)
|> Seq.toList
match assy |> List.tryHead with
| None -> failwith $"Could not find a readable DLL in any runtime dir with name %s{assemblyName.Name}.dll"
| Some assy ->
state.WithLoadedAssembly assemblyName assy, assy, assemblyName
let rec internal resolveTypeFromName let rec internal resolveTypeFromName
(loggerFactory : ILoggerFactory) (loggerFactory : ILoggerFactory)
(ns : string option) (ns : string option)
@@ -440,6 +454,54 @@ module IlMachineState =
resolveTypeFromDefn loggerFactory baseClassTypes sign typeGenericArgsAsDefn methodGenericArgsAsDefn assy state resolveTypeFromDefn loggerFactory baseClassTypes sign typeGenericArgsAsDefn methodGenericArgsAsDefn assy state
/// Resolve a TypeDefinition using concrete type handles from execution context
let resolveTypeFromDefnConcrete
(loggerFactory : ILoggerFactory)
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
(ty : TypeDefinitionHandle)
(assy : DumpedAssembly)
(typeGenericArgs : ConcreteTypeHandle ImmutableArray)
(methodGenericArgs : ConcreteTypeHandle ImmutableArray)
(state : IlMachineState)
: IlMachineState * DumpedAssembly * WoofWare.PawPrint.TypeInfo<TypeDefn, TypeDefn>
=
let typeDef = assy.TypeDefs.[ty]
// Convert ConcreteTypeHandle to TypeDefn for the generics
let typeGenericArgsAsDefn =
typeGenericArgs
|> Seq.map (fun handle ->
Concretization.concreteHandleToTypeDefn
baseClassTypes
handle
state.ConcreteTypes
state._LoadedAssemblies
)
|> ImmutableArray.CreateRange
let methodGenericArgsAsDefn =
methodGenericArgs
|> Seq.map (fun handle ->
Concretization.concreteHandleToTypeDefn
baseClassTypes
handle
state.ConcreteTypes
state._LoadedAssemblies
)
|> ImmutableArray.CreateRange
// Map the type definition's generics using the provided type generic arguments
let resolvedTypeDef =
typeDef
|> TypeInfo.mapGeneric (fun (param, _) ->
if param.SequenceNumber < typeGenericArgsAsDefn.Length then
typeGenericArgsAsDefn.[param.SequenceNumber]
else
failwithf "Generic type parameter %d out of range" param.SequenceNumber
)
state, assy, resolvedTypeDef
/// Get zero value for a type that's already been concretized /// Get zero value for a type that's already been concretized
let cliTypeZeroOfHandle let cliTypeZeroOfHandle
(state : IlMachineState) (state : IlMachineState)
@@ -482,26 +544,6 @@ module IlMachineState =
BaseTypes = baseClassTypes BaseTypes = baseClassTypes
} }
// Helper function to get assembly from reference
let loadAssembly
(currentAssembly : AssemblyName)
(assyRef : AssemblyReferenceHandle)
: ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly
=
let assyToLoad =
match state.LoadedAssembly currentAssembly with
| Some assy -> assy
| None -> failwithf "Assembly %s not loaded" currentAssembly.FullName
let referencedAssy = assyToLoad.AssemblyReferences.[assyRef]
match state.LoadedAssembly referencedAssy.Name with
| Some assy -> state._LoadedAssemblies, assy
| None ->
// Need to load the assembly
let newState, loadedAssy, _ = loadAssembly loggerFactory assyToLoad assyRef state
newState._LoadedAssemblies, loadedAssy
// Concretize each generic argument first // Concretize each generic argument first
let mutable currentCtx = ctx let mutable currentCtx = ctx
let genericHandles = ImmutableArray.CreateBuilder declaringType.Generics.Length let genericHandles = ImmutableArray.CreateBuilder declaringType.Generics.Length
@@ -510,7 +552,7 @@ module IlMachineState =
let handle, newCtx = let handle, newCtx =
TypeConcretization.concretizeType TypeConcretization.concretizeType
currentCtx currentCtx
loadAssembly (loader loggerFactory state)
declaringType.Assembly declaringType.Assembly
ImmutableArray.Empty // No type generics in this context ImmutableArray.Empty // No type generics in this context
ImmutableArray.Empty // No method generics in this context ImmutableArray.Empty // No method generics in this context
@@ -522,12 +564,13 @@ module IlMachineState =
// Now we need to concretize the type definition itself // Now we need to concretize the type definition itself
// If it's a non-generic type, we can use concretizeTypeDefinition directly // If it's a non-generic type, we can use concretizeTypeDefinition directly
if declaringType.Generics.IsEmpty then if declaringType.Generics.IsEmpty then
let handle, newCtx = let handle, currentCtx =
TypeConcretization.concretizeTypeDefinition currentCtx declaringType.Assembly declaringType.Definition TypeConcretization.concretizeTypeDefinition currentCtx declaringType.Assembly declaringType.Definition
let newState = let newState =
{ state with { state with
ConcreteTypes = newCtx.ConcreteTypes ConcreteTypes = currentCtx.ConcreteTypes
_LoadedAssemblies = currentCtx.LoadedAssemblies
} }
handle, newState handle, newState
@@ -583,7 +626,7 @@ module IlMachineState =
state.WithLoadedAssembly assy.Name assy state.WithLoadedAssembly assy.Name assy
let state, handle = let state, handle =
concretizeType baseClassTypes state assy.Name typeGenerics methodGenerics ty concretizeType loggerFactory baseClassTypes state assy.Name typeGenerics methodGenerics ty
// Now get the zero value // Now get the zero value
let zero, state = cliTypeZeroOfHandle state baseClassTypes handle let zero, state = cliTypeZeroOfHandle state baseClassTypes handle
@@ -759,22 +802,7 @@ module IlMachineState =
let concretizedMethod, newConcreteTypes, newAssemblies = let concretizedMethod, newConcreteTypes, newAssemblies =
Concretization.concretizeMethod Concretization.concretizeMethod
state.ConcreteTypes state.ConcreteTypes
(fun assyName ref -> (loader loggerFactory state)
match state.LoadedAssembly assyName with
| Some currentAssy ->
let targetAssyRef = currentAssy.AssemblyReferences.[ref]
match state.LoadedAssembly targetAssyRef.Name with
| Some _ ->
// Assembly already loaded, return existing state
state._LoadedAssemblies, state._LoadedAssemblies.[targetAssyRef.Name.FullName]
| None ->
// Need to load the assembly
let newState, loadedAssy, _ = loadAssembly loggerFactory currentAssy ref state
newState._LoadedAssemblies, loadedAssy
| None ->
failwithf "Current assembly %s not loaded when trying to resolve reference" assyName.FullName
)
state._LoadedAssemblies state._LoadedAssemblies
baseClassTypes baseClassTypes
methodToCall methodToCall
@@ -820,6 +848,7 @@ module IlMachineState =
for i = 0 to generics.Length - 1 do for i = 0 to generics.Length - 1 do
let state2, handle = let state2, handle =
concretizeType concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
callingAssembly callingAssembly
@@ -875,14 +904,7 @@ module IlMachineState =
let handle, newCtx = let handle, newCtx =
TypeConcretization.concretizeType TypeConcretization.concretizeType
ctx ctx
(fun assyName ref -> (loader loggerFactory state)
let currentAssy = state.LoadedAssembly assyName |> Option.get
let targetAssy =
currentAssy.AssemblyReferences.[ref].Name |> state.LoadedAssembly |> Option.get
state._LoadedAssemblies, targetAssy
)
(state.ActiveAssembly thread).Name (state.ActiveAssembly thread).Name
ImmutableArray.Empty // No type generics for the concretization context ImmutableArray.Empty // No type generics for the concretization context
ImmutableArray.Empty // No method generics for the concretization context ImmutableArray.Empty // No method generics for the concretization context
@@ -893,6 +915,7 @@ module IlMachineState =
state <- state <-
{ state with { state with
ConcreteTypes = newCtx.ConcreteTypes ConcreteTypes = newCtx.ConcreteTypes
_LoadedAssemblies = newCtx.LoadedAssemblies
} }
handles.ToImmutable (), state handles.ToImmutable (), state
@@ -997,14 +1020,7 @@ module IlMachineState =
let declaringHandle, newCtx = let declaringHandle, newCtx =
TypeConcretization.concretizeType TypeConcretization.concretizeType
ctx ctx
(fun assyName ref -> (loader loggerFactory state)
let currentAssy = state.LoadedAssembly assyName |> Option.get
let targetAssy =
currentAssy.AssemblyReferences.[ref].Name |> state.LoadedAssembly |> Option.get
state._LoadedAssemblies, targetAssy
)
field.DeclaringType.Assembly field.DeclaringType.Assembly
contextTypeGenerics contextTypeGenerics
contextMethodGenerics contextMethodGenerics
@@ -1190,6 +1206,7 @@ module IlMachineState =
(baseClassTypes : BaseClassTypes<DumpedAssembly>) (baseClassTypes : BaseClassTypes<DumpedAssembly>)
(currentThread : ThreadId) (currentThread : ThreadId)
(assy : DumpedAssembly) (assy : DumpedAssembly)
(genericMethodTypeArgs : ImmutableArray<ConcreteTypeHandle>)
(m : MemberReferenceHandle) (m : MemberReferenceHandle)
(state : IlMachineState) (state : IlMachineState)
: IlMachineState * : IlMachineState *
@@ -1253,6 +1270,7 @@ module IlMachineState =
// TODO: generics? // TODO: generics?
let state, t = let state, t =
concretizeType concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
targetType.Assembly targetType.Assembly
@@ -1270,6 +1288,7 @@ module IlMachineState =
// Concretize the field signature from the member reference // Concretize the field signature from the member reference
let state, concreteFieldSig = let state, concreteFieldSig =
concretizeType concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
(state.ActiveAssembly(currentThread).Name) (state.ActiveAssembly(currentThread).Name)
@@ -1287,6 +1306,7 @@ module IlMachineState =
// Concretize the field's signature for comparison // Concretize the field's signature for comparison
let state, fieldSigConcrete = let state, fieldSigConcrete =
concretizeType concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
assy.Name assy.Name
@@ -1324,11 +1344,12 @@ module IlMachineState =
state state
(fun state ty -> (fun state ty ->
concretizeType concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
(state.ActiveAssembly(currentThread).Name) (state.ActiveAssembly(currentThread).Name)
concreteExtractedTypeArgs concreteExtractedTypeArgs
ImmutableArray.Empty genericMethodTypeArgs
ty ty
) )
@@ -1341,11 +1362,12 @@ module IlMachineState =
state state
(fun state ty -> (fun state ty ->
concretizeType concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
assy.Name assy.Name
concreteExtractedTypeArgs concreteExtractedTypeArgs
ImmutableArray.Empty genericMethodTypeArgs
ty ty
) )
@@ -1507,6 +1529,7 @@ module IlMachineState =
/// Returns the type handle and an allocated System.RuntimeType. /// Returns the type handle and an allocated System.RuntimeType.
let getOrAllocateType let getOrAllocateType
(loggerFactory : ILoggerFactory)
(baseClassTypes : BaseClassTypes<DumpedAssembly>) (baseClassTypes : BaseClassTypes<DumpedAssembly>)
(defn : ConcreteTypeHandle) (defn : ConcreteTypeHandle)
(state : IlMachineState) (state : IlMachineState)
@@ -1518,7 +1541,13 @@ module IlMachineState =
baseClassTypes.Corelib.Name.FullName, baseClassTypes.Corelib.Name.FullName,
SignatureTypeKind.Class SignatureTypeKind.Class
) )
|> concretizeType baseClassTypes state baseClassTypes.Corelib.Name ImmutableArray.Empty ImmutableArray.Empty |> concretizeType
loggerFactory
baseClassTypes
state
baseClassTypes.Corelib.Name
ImmutableArray.Empty
ImmutableArray.Empty
let result, reg, state = let result, reg, state =
TypeHandleRegistry.getOrAllocate TypeHandleRegistry.getOrAllocate
@@ -1562,7 +1591,13 @@ module IlMachineState =
baseClassTypes.Corelib.Name.FullName, baseClassTypes.Corelib.Name.FullName,
SignatureTypeKind.Class SignatureTypeKind.Class
) )
|> concretizeType baseClassTypes state baseClassTypes.Corelib.Name ImmutableArray.Empty ImmutableArray.Empty |> concretizeType
loggerFactory
baseClassTypes
state
baseClassTypes.Corelib.Name
ImmutableArray.Empty
ImmutableArray.Empty
let result, reg, state = let result, reg, state =
FieldHandleRegistry.getOrAllocate FieldHandleRegistry.getOrAllocate

View File

@@ -10,6 +10,7 @@ open Microsoft.Extensions.Logging
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
module IlMachineStateExecution = module IlMachineStateExecution =
let getTypeOfObj let getTypeOfObj
(loggerFactory : ILoggerFactory)
(baseClassTypes : BaseClassTypes<DumpedAssembly>) (baseClassTypes : BaseClassTypes<DumpedAssembly>)
(state : IlMachineState) (state : IlMachineState)
(esv : EvalStackValue) (esv : EvalStackValue)
@@ -19,6 +20,7 @@ module IlMachineStateExecution =
| EvalStackValue.Int32 _ -> | EvalStackValue.Int32 _ ->
DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies baseClassTypes.Int32 DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies baseClassTypes.Int32
|> IlMachineState.concretizeType |> IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
baseClassTypes.Corelib.Name baseClassTypes.Corelib.Name
@@ -27,6 +29,7 @@ module IlMachineStateExecution =
| EvalStackValue.Int64 _ -> | EvalStackValue.Int64 _ ->
DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies baseClassTypes.Int64 DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies baseClassTypes.Int64
|> IlMachineState.concretizeType |> IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
baseClassTypes.Corelib.Name baseClassTypes.Corelib.Name
@@ -36,6 +39,7 @@ module IlMachineStateExecution =
| EvalStackValue.Float _ -> | EvalStackValue.Float _ ->
DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies baseClassTypes.Double DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies baseClassTypes.Double
|> IlMachineState.concretizeType |> IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
baseClassTypes.Corelib.Name baseClassTypes.Corelib.Name
@@ -156,7 +160,8 @@ module IlMachineStateExecution =
| None -> failwith "unexpectedly no `this` on the eval stack of instance method" | None -> failwith "unexpectedly no `this` on the eval stack of instance method"
| Some this -> this | Some this -> this
let state, callingObjTyHandle = getTypeOfObj baseClassTypes state callingObj let state, callingObjTyHandle =
getTypeOfObj loggerFactory baseClassTypes state callingObj
let callingObjTy = let callingObjTy =
let ty = let ty =
@@ -200,6 +205,7 @@ module IlMachineStateExecution =
let state, retType = let state, retType =
meth.Signature.ReturnType meth.Signature.ReturnType
|> IlMachineState.concretizeType |> IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
meth.DeclaringType.Assembly meth.DeclaringType.Assembly
@@ -211,6 +217,7 @@ module IlMachineStateExecution =
||> Seq.mapFold (fun state ty -> ||> Seq.mapFold (fun state ty ->
ty ty
|> IlMachineState.concretizeType |> IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
meth.DeclaringType.Assembly meth.DeclaringType.Assembly
@@ -573,6 +580,7 @@ module IlMachineStateExecution =
// Concretize the base type // Concretize the base type
let state, baseTypeHandle = let state, baseTypeHandle =
IlMachineState.concretizeType IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
sourceAssembly.Name sourceAssembly.Name
@@ -612,6 +620,7 @@ module IlMachineStateExecution =
// Concretize the base type // Concretize the base type
let state, baseTypeHandle = let state, baseTypeHandle =
IlMachineState.concretizeType IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
sourceAssembly.Name sourceAssembly.Name
@@ -663,6 +672,7 @@ module IlMachineStateExecution =
state state
(fun state typeDefn -> (fun state typeDefn ->
IlMachineState.concretizeType IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
concreteType.Assembly concreteType.Assembly
@@ -687,6 +697,7 @@ module IlMachineStateExecution =
||> Seq.fold (fun (state, acc) typeDefn -> ||> Seq.fold (fun (state, acc) typeDefn ->
let state, handle = let state, handle =
IlMachineState.concretizeType IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
concreteType.Assembly concreteType.Assembly

View File

@@ -14,6 +14,10 @@ module Intrinsics =
"System.Private.CoreLib", "ArgumentNullException", "ThrowIfNull" "System.Private.CoreLib", "ArgumentNullException", "ThrowIfNull"
// https://github.com/dotnet/runtime/blob/ec11903827fc28847d775ba17e0cd1ff56cfbc2e/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs#L82 // https://github.com/dotnet/runtime/blob/ec11903827fc28847d775ba17e0cd1ff56cfbc2e/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs#L82
"System.Private.CoreLib", "Type", "GetTypeFromHandle" "System.Private.CoreLib", "Type", "GetTypeFromHandle"
// https://github.com/dotnet/runtime/blob/108fa7856efcfd39bc991c2d849eabbf7ba5989c/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs#L161
"System.Private.CoreLib", "ReadOnlySpan`1", "get_Length"
// https://github.com/dotnet/runtime/blob/9e5e6aa7bc36aeb2a154709a9d1192030c30a2ef/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs#L153
"System.Private.CoreLib", "RuntimeHelpers", "CreateSpan"
] ]
|> Set.ofList |> Set.ofList
@@ -299,15 +303,47 @@ module Intrinsics =
| [], ConcreteBool state.ConcreteTypes -> () | [], ConcreteBool state.ConcreteTypes -> ()
| _ -> failwith "bad signature for System.Private.CoreLib.RuntimeHelpers.IsReferenceOrContainsReference" | _ -> failwith "bad signature for System.Private.CoreLib.RuntimeHelpers.IsReferenceOrContainsReference"
let generic = let arg = Seq.exactlyOne methodToCall.Generics
AllConcreteTypes.lookup (Seq.exactlyOne methodToCall.Generics) state.ConcreteTypes
let result =
// Some types appear circular, because they're hardcoded in the runtime. We have to special-case them.
match arg with
| ConcreteChar state.ConcreteTypes -> false
| _ ->
let generic = AllConcreteTypes.lookup arg state.ConcreteTypes
let generic = let generic =
match generic with match generic with
| None -> failwith "somehow have not already concretised type in IsReferenceOrContainsReferences" | None -> failwith "somehow have not already concretised type in IsReferenceOrContainsReferences"
| Some generic -> generic | Some generic -> generic
failwith $"TODO: do the thing on %O{generic}" let td =
state.LoadedAssembly (generic.Assembly)
|> Option.get
|> fun a -> a.TypeDefs.[generic.Definition.Get]
let baseType =
td.BaseType
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies generic.Assembly
match baseType with
| ResolvedBaseType.Enum -> false
| ResolvedBaseType.ValueType ->
let nonStaticFields =
td.Fields
|> List.choose (fun field -> if field.IsStatic then None else Some field.Signature)
failwith $"TODO: search the fields on {td.Namespace}.{td.Name}: {nonStaticFields}"
| ResolvedBaseType.Object
| ResolvedBaseType.Delegate -> true
let state =
state
|> IlMachineState.pushToEvalStack (CliType.ofBool result) currentThread
|> IlMachineState.advanceProgramCounter currentThread
Some state
| "System.Private.CoreLib", "RuntimeHelpers", "InitializeArray" -> | "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 // https://github.com/dotnet/runtime/blob/9e5e6aa7bc36aeb2a154709a9d1192030c30a2ef/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs#L18
match methodToCall.Signature.ParameterTypes, methodToCall.Signature.ReturnType with match methodToCall.Signature.ParameterTypes, methodToCall.Signature.ReturnType with
@@ -319,6 +355,57 @@ module Intrinsics =
failwith "TODO: if arg1 contains null handle, throw ArgumentException" failwith "TODO: if arg1 contains null handle, throw ArgumentException"
failwith "TODO: array initialization" failwith "TODO: array initialization"
| "System.Private.CoreLib", "Unsafe", "As" ->
// https://github.com/dotnet/runtime/blob/721fdf6dcb032da1f883d30884e222e35e3d3c99/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs#L64
let inputType, retType =
match methodToCall.Signature.ParameterTypes, methodToCall.Signature.ReturnType with
| [ input ], ret -> input, ret
| _ -> failwith "bad signature Unsafe.As"
let from, to_ =
match Seq.toList methodToCall.Generics with
| [ from ; to_ ] -> from, to_
| _ -> failwith "bad generics"
if ConcreteTypeHandle.Byref to_ <> retType then
failwith "bad return type"
if ConcreteTypeHandle.Byref from <> inputType then
failwith "bad input type"
let from =
match AllConcreteTypes.lookup from state.ConcreteTypes with
| None -> failwith "somehow have not concretised input type"
| Some t -> t
let to_ =
match AllConcreteTypes.lookup to_ state.ConcreteTypes with
| None -> failwith "somehow have not concretised ret type"
| Some t -> t
failwith "TODO: transmute fields etc"
let state = state |> IlMachineState.advanceProgramCounter currentThread
Some state
| "System.Private.CoreLib", "Unsafe", "SizeOf" ->
// https://github.com/dotnet/runtime/blob/721fdf6dcb032da1f883d30884e222e35e3d3c99/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs#L51
match methodToCall.Signature.ParameterTypes, methodToCall.Signature.ReturnType with
| [], ConcreteInt32 state.ConcreteTypes -> ()
| _ -> failwith "bad signature Unsafe.SizeOf"
let ty =
match Seq.toList methodToCall.Generics with
| [ ty ] -> ty
| _ -> failwith "bad generics"
let zero, state = IlMachineState.cliTypeZeroOfHandle state baseClassTypes ty
let size = CliType.sizeOf zero
state
|> IlMachineState.pushToEvalStack (CliType.Numeric (CliNumericType.Int32 size)) currentThread
|> IlMachineState.advanceProgramCounter currentThread
|> Some
| "System.Private.CoreLib", "RuntimeHelpers", "CreateSpan" -> | "System.Private.CoreLib", "RuntimeHelpers", "CreateSpan" ->
// https://github.com/dotnet/runtime/blob/9e5e6aa7bc36aeb2a154709a9d1192030c30a2ef/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs#L153 // https://github.com/dotnet/runtime/blob/9e5e6aa7bc36aeb2a154709a9d1192030c30a2ef/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs#L153
None None

View File

@@ -52,7 +52,7 @@ module NullaryIlOp =
| EvalStackValue.NativeInt nativeIntSource -> | EvalStackValue.NativeInt nativeIntSource ->
failwith $"TODO: Native int pointer dereferencing not implemented for {targetType}" failwith $"TODO: Native int pointer dereferencing not implemented for {targetType}"
| EvalStackValue.ObjectRef managedHeapAddress -> | EvalStackValue.ObjectRef managedHeapAddress ->
failwith "TODO: Object reference dereferencing not implemented" IlMachineState.dereferencePointer state (ManagedPointerSource.Heap managedHeapAddress)
| other -> failwith $"Unexpected eval stack value for Ldind operation: {other}" | other -> failwith $"Unexpected eval stack value for Ldind operation: {other}"
let loadedValue = loadedValue |> EvalStackValue.ofCliType let loadedValue = loadedValue |> EvalStackValue.ofCliType

View File

@@ -10,6 +10,7 @@ open Microsoft.Extensions.Logging
module Program = module Program =
/// Returns the pointer to the resulting array on the heap. /// Returns the pointer to the resulting array on the heap.
let allocateArgs let allocateArgs
(loggerFactory : ILoggerFactory)
(args : string list) (args : string list)
(corelib : BaseClassTypes<DumpedAssembly>) (corelib : BaseClassTypes<DumpedAssembly>)
(state : IlMachineState) (state : IlMachineState)
@@ -18,6 +19,7 @@ module Program =
let state, stringType = let state, stringType =
DumpedAssembly.typeInfoToTypeDefn' corelib state._LoadedAssemblies corelib.String DumpedAssembly.typeInfoToTypeDefn' corelib state._LoadedAssemblies corelib.String
|> IlMachineState.concretizeType |> IlMachineState.concretizeType
loggerFactory
corelib corelib
state state
corelib.Corelib.Name corelib.Corelib.Name
@@ -285,7 +287,7 @@ module Program =
let arrayAllocation, state = let arrayAllocation, state =
match mainMethodFromMetadata.Signature.ParameterTypes |> Seq.toList with match mainMethodFromMetadata.Signature.ParameterTypes |> Seq.toList with
| [ TypeDefn.OneDimensionalArrayLowerBoundZero (TypeDefn.PrimitiveType PrimitiveType.String) ] -> | [ TypeDefn.OneDimensionalArrayLowerBoundZero (TypeDefn.PrimitiveType PrimitiveType.String) ] ->
allocateArgs argv baseClassTypes state allocateArgs loggerFactory argv baseClassTypes state
| _ -> failwith "Main method must take an array of strings; other signatures not yet implemented" | _ -> failwith "Main method must take an array of strings; other signatures not yet implemented"
match mainMethodFromMetadata.Signature.ReturnType with match mainMethodFromMetadata.Signature.ReturnType with

View File

@@ -28,6 +28,24 @@ module internal UnaryMetadataIlOp =
| MetadataToken.MethodSpecification h -> | MetadataToken.MethodSpecification h ->
let spec = activeAssy.MethodSpecs.[h] let spec = activeAssy.MethodSpecs.[h]
let state, methodGenerics =
((state, []), spec.Signature)
||> Seq.fold (fun (state, acc) typeDefn ->
let state, concreteType =
IlMachineState.concretizeType
loggerFactory
baseClassTypes
state
(state.ActiveAssembly thread).Name
currentMethod.DeclaringType.Generics
currentMethod.Generics
typeDefn
state, concreteType :: acc
)
let methodGenerics = List.rev methodGenerics |> ImmutableArray.CreateRange
match spec.Method with match spec.Method with
| MetadataToken.MethodDef token -> | MetadataToken.MethodDef token ->
let method = let method =
@@ -44,6 +62,7 @@ module internal UnaryMetadataIlOp =
baseClassTypes baseClassTypes
thread thread
(state.ActiveAssembly thread) (state.ActiveAssembly thread)
methodGenerics
ref ref
state state
@@ -58,6 +77,7 @@ module internal UnaryMetadataIlOp =
baseClassTypes baseClassTypes
thread thread
(state.ActiveAssembly thread) (state.ActiveAssembly thread)
currentMethod.DeclaringType.Generics
h h
state state
@@ -114,6 +134,24 @@ module internal UnaryMetadataIlOp =
| MetadataToken.MethodSpecification h -> | MetadataToken.MethodSpecification h ->
let spec = activeAssy.MethodSpecs.[h] let spec = activeAssy.MethodSpecs.[h]
let state, methodGenerics =
((state, []), spec.Signature)
||> Seq.fold (fun (state, acc) typeDefn ->
let state, concreteType =
IlMachineState.concretizeType
loggerFactory
baseClassTypes
state
(state.ActiveAssembly thread).Name
currentMethod.DeclaringType.Generics
ImmutableArray.Empty
typeDefn
state, concreteType :: acc
)
let methodGenerics = List.rev methodGenerics |> ImmutableArray.CreateRange
match spec.Method with match spec.Method with
| MetadataToken.MethodDef token -> | MetadataToken.MethodDef token ->
let method = let method =
@@ -128,6 +166,7 @@ module internal UnaryMetadataIlOp =
baseClassTypes baseClassTypes
thread thread
(state.ActiveAssembly thread) (state.ActiveAssembly thread)
methodGenerics
ref ref
state state
@@ -142,6 +181,7 @@ module internal UnaryMetadataIlOp =
baseClassTypes baseClassTypes
thread thread
(state.ActiveAssembly thread) (state.ActiveAssembly thread)
ImmutableArray.Empty
h h
state state
@@ -203,6 +243,7 @@ module internal UnaryMetadataIlOp =
baseClassTypes baseClassTypes
thread thread
(state.ActiveAssembly thread) (state.ActiveAssembly thread)
ImmutableArray.Empty
mr mr
state state
@@ -436,6 +477,7 @@ module internal UnaryMetadataIlOp =
let state, targetConcreteType = let state, targetConcreteType =
IlMachineState.concretizeType IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
activeAssy.Name activeAssy.Name
@@ -481,7 +523,14 @@ module internal UnaryMetadataIlOp =
state, field state, field
| MetadataToken.MemberReference mr -> | MetadataToken.MemberReference mr ->
let state, _, field, _ = let state, _, field, _ =
IlMachineState.resolveMember loggerFactory baseClassTypes thread activeAssy mr state IlMachineState.resolveMember
loggerFactory
baseClassTypes
thread
activeAssy
ImmutableArray.Empty
mr
state
match field with match field with
| Choice1Of2 _method -> failwith "member reference was unexpectedly a method" | Choice1Of2 _method -> failwith "member reference was unexpectedly a method"
@@ -498,6 +547,7 @@ module internal UnaryMetadataIlOp =
) )
let valueToStore, state = IlMachineState.popEvalStack thread state let valueToStore, state = IlMachineState.popEvalStack thread state
let currentObj, state = IlMachineState.popEvalStack thread state
let state, declaringTypeHandle, typeGenerics = let state, declaringTypeHandle, typeGenerics =
IlMachineState.concretizeFieldForExecution loggerFactory baseClassTypes thread field state IlMachineState.concretizeFieldForExecution loggerFactory baseClassTypes thread field state
@@ -514,8 +564,6 @@ module internal UnaryMetadataIlOp =
let valueToStore = EvalStackValue.toCliTypeCoerced zero valueToStore let valueToStore = EvalStackValue.toCliTypeCoerced zero valueToStore
let currentObj, state = IlMachineState.popEvalStack thread state
if field.Attributes.HasFlag FieldAttributes.Static then if field.Attributes.HasFlag FieldAttributes.Static then
let state = let state =
IlMachineState.setStatic declaringTypeHandle field.Name valueToStore state IlMachineState.setStatic declaringTypeHandle field.Name valueToStore state
@@ -601,6 +649,7 @@ module internal UnaryMetadataIlOp =
baseClassTypes baseClassTypes
thread thread
(state.ActiveAssembly thread) (state.ActiveAssembly thread)
ImmutableArray.Empty
mr mr
state state
@@ -660,7 +709,14 @@ module internal UnaryMetadataIlOp =
state, field state, field
| MetadataToken.MemberReference mr -> | MetadataToken.MemberReference mr ->
let state, assyName, field, _ = let state, assyName, field, _ =
IlMachineState.resolveMember loggerFactory baseClassTypes thread activeAssy mr state IlMachineState.resolveMember
loggerFactory
baseClassTypes
thread
activeAssy
ImmutableArray.Empty
mr
state
match field with match field with
| Choice1Of2 _method -> failwith "member reference was unexpectedly a method" | Choice1Of2 _method -> failwith "member reference was unexpectedly a method"
@@ -750,6 +806,7 @@ module internal UnaryMetadataIlOp =
IlMachineState.pushToEvalStack currentValue thread state 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
IlMachineState.pushToEvalStack' result thread state IlMachineState.pushToEvalStack' result thread state
state state
@@ -779,7 +836,15 @@ module internal UnaryMetadataIlOp =
state, field state, field
| MetadataToken.MemberReference mr -> | MetadataToken.MemberReference mr ->
let state, assyName, field, _ = let state, assyName, field, _ =
IlMachineState.resolveMember loggerFactory baseClassTypes thread activeAssy mr state // TODO: generics
IlMachineState.resolveMember
loggerFactory
baseClassTypes
thread
activeAssy
ImmutableArray.Empty
mr
state
match field with match field with
| Choice1Of2 _method -> failwith "member reference was unexpectedly a method" | Choice1Of2 _method -> failwith "member reference was unexpectedly a method"
@@ -793,6 +858,7 @@ module internal UnaryMetadataIlOp =
|> IlMachineState.pushToEvalStack' result 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
@@ -807,7 +873,14 @@ module internal UnaryMetadataIlOp =
state, field state, field
| MetadataToken.MemberReference mr -> | MetadataToken.MemberReference mr ->
let state, _, field, _ = let state, _, field, _ =
IlMachineState.resolveMember loggerFactory baseClassTypes thread activeAssy mr state IlMachineState.resolveMember
loggerFactory
baseClassTypes
thread
activeAssy
ImmutableArray.Empty
mr
state
match field with match field with
| Choice1Of2 _method -> failwith "member reference was unexpectedly a method" | Choice1Of2 _method -> failwith "member reference was unexpectedly a method"
@@ -983,6 +1056,7 @@ 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 popped, state = IlMachineState.popEvalStack thread state let popped, state = IlMachineState.popEvalStack thread state
let declaringTypeGenerics = currentMethod.DeclaringType.Generics let declaringTypeGenerics = currentMethod.DeclaringType.Generics
@@ -1046,6 +1120,7 @@ module internal UnaryMetadataIlOp =
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
@@ -1142,6 +1217,42 @@ module internal UnaryMetadataIlOp =
| Stobj -> failwith "TODO: Stobj unimplemented" | Stobj -> failwith "TODO: Stobj unimplemented"
| Constrained -> failwith "TODO: Constrained unimplemented" | Constrained -> failwith "TODO: Constrained unimplemented"
| Ldtoken -> | Ldtoken ->
// Helper function to handle type tokens and create RuntimeTypeHandle
let handleTypeToken (typeDefn : TypeDefn) (state : IlMachineState) : IlMachineState =
let ty = baseClassTypes.RuntimeTypeHandle
let field = ty.Fields |> List.exactlyOne
if field.Name <> "m_type" then
failwith $"unexpected field name ${field.Name} for BCL type RuntimeTypeHandle"
let methodGenerics = currentMethod.Generics
let typeGenerics = currentMethod.DeclaringType.Generics
let state, handle =
IlMachineState.concretizeType
loggerFactory
baseClassTypes
state
activeAssy.Name
typeGenerics
methodGenerics
typeDefn
let alloc, state =
IlMachineState.getOrAllocateType loggerFactory baseClassTypes handle state
let vt =
// https://github.com/dotnet/runtime/blob/2b21c73fa2c32fa0195e4a411a435dda185efd08/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs#L92
{
Name = "m_type"
Contents = CliType.ObjectRef (Some alloc)
Offset = None
}
|> List.singleton
|> CliValueType.OfFields
IlMachineState.pushToEvalStack (CliType.ValueType vt) thread state
let state = let state =
match metadataToken with match metadataToken with
| MetadataToken.FieldDefinition h -> | MetadataToken.FieldDefinition h ->
@@ -1179,6 +1290,7 @@ module internal UnaryMetadataIlOp =
let state, handle = let state, handle =
IlMachineState.concretizeType IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
assy.Name assy.Name
@@ -1186,7 +1298,8 @@ module internal UnaryMetadataIlOp =
methodGenerics methodGenerics
typeDefn typeDefn
let alloc, state = IlMachineState.getOrAllocateType baseClassTypes handle state let alloc, state =
IlMachineState.getOrAllocateType loggerFactory baseClassTypes handle state
let vt = let vt =
{ {
@@ -1214,6 +1327,7 @@ module internal UnaryMetadataIlOp =
let state, handle = let state, handle =
IlMachineState.concretizeType IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
assy.Name assy.Name
@@ -1221,7 +1335,8 @@ module internal UnaryMetadataIlOp =
methodGenerics methodGenerics
typeDefn typeDefn
let alloc, state = IlMachineState.getOrAllocateType baseClassTypes handle state let alloc, state =
IlMachineState.getOrAllocateType loggerFactory baseClassTypes handle state
let vt = let vt =
{ {
@@ -1234,40 +1349,10 @@ module internal UnaryMetadataIlOp =
IlMachineState.pushToEvalStack (CliType.ValueType vt) thread state IlMachineState.pushToEvalStack (CliType.ValueType vt) thread state
| MetadataToken.TypeDefinition h -> | MetadataToken.TypeDefinition h ->
let ty = baseClassTypes.RuntimeTypeHandle
let field = ty.Fields |> List.exactlyOne
if field.Name <> "m_type" then
failwith $"unexpected field name ${field.Name} for BCL type RuntimeTypeHandle"
let methodGenerics = currentMethod.Generics
let typeGenerics = currentMethod.DeclaringType.Generics
let state, typeDefn = let state, typeDefn =
IlMachineState.lookupTypeDefn baseClassTypes state activeAssy h IlMachineState.lookupTypeDefn baseClassTypes state activeAssy h
let state, handle = handleTypeToken typeDefn state
IlMachineState.concretizeType
baseClassTypes
state
activeAssy.Name
typeGenerics
methodGenerics
typeDefn
let alloc, state = IlMachineState.getOrAllocateType baseClassTypes handle state
let vt =
{
Name = "m_type"
Contents = CliType.ObjectRef (Some alloc)
Offset = None
}
|> List.singleton
|> CliValueType.OfFields
IlMachineState.pushToEvalStack (CliType.ValueType vt) thread state
| _ -> failwith $"Unexpected metadata token %O{metadataToken} in LdToken" | _ -> failwith $"Unexpected metadata token %O{metadataToken} in LdToken"
state state
@@ -1293,6 +1378,7 @@ module internal UnaryMetadataIlOp =
let state, typeHandle = let state, typeHandle =
IlMachineState.concretizeType IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
assy.Name assy.Name

View File

@@ -2,12 +2,13 @@ namespace WoofWare.PawPrint
open System.Collections.Immutable open System.Collections.Immutable
open System.Reflection open System.Reflection
open System.Reflection.Metadata open Microsoft.Extensions.Logging
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] [<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module internal UnaryStringTokenIlOp = module internal UnaryStringTokenIlOp =
let execute let execute
(loggerFactory : ILoggerFactory)
(baseClassTypes : BaseClassTypes<DumpedAssembly>) (baseClassTypes : BaseClassTypes<DumpedAssembly>)
(op : UnaryStringTokenIlOp) (op : UnaryStringTokenIlOp)
(sh : StringToken) (sh : StringToken)
@@ -66,6 +67,7 @@ module internal UnaryStringTokenIlOp =
let state, stringType = let state, stringType =
DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies baseClassTypes.String DumpedAssembly.typeInfoToTypeDefn' baseClassTypes state._LoadedAssemblies baseClassTypes.String
|> IlMachineState.concretizeType |> IlMachineState.concretizeType
loggerFactory
baseClassTypes baseClassTypes
state state
baseClassTypes.Corelib.Name baseClassTypes.Corelib.Name