mirror of
https://github.com/Smaug123/WoofWare.PawPrint
synced 2025-10-07 06:58:39 +00:00
Finish initialising class of the main method before execution (#59)
This commit is contained in:
@@ -527,7 +527,7 @@ module DumpedAssembly =
|
|||||||
(baseTypeInfo : BaseTypeInfo option)
|
(baseTypeInfo : BaseTypeInfo option)
|
||||||
: ResolvedBaseType
|
: ResolvedBaseType
|
||||||
=
|
=
|
||||||
let rec go (baseType : BaseTypeInfo option) =
|
let rec go (source : AssemblyName) (baseType : BaseTypeInfo option) =
|
||||||
match baseType with
|
match baseType with
|
||||||
| Some (BaseTypeInfo.TypeRef r) ->
|
| Some (BaseTypeInfo.TypeRef r) ->
|
||||||
let assy = loadedAssemblies.[source.FullName]
|
let assy = loadedAssemblies.[source.FullName]
|
||||||
@@ -539,7 +539,7 @@ module DumpedAssembly =
|
|||||||
| TypeResolutionResult.Resolved (assy, typeInfo) ->
|
| TypeResolutionResult.Resolved (assy, typeInfo) ->
|
||||||
match TypeInfo.isBaseType bct _.Name assy.Name typeInfo.TypeDefHandle with
|
match TypeInfo.isBaseType bct _.Name assy.Name typeInfo.TypeDefHandle with
|
||||||
| Some v -> v
|
| Some v -> v
|
||||||
| None -> go typeInfo.BaseType
|
| None -> go assy.Name typeInfo.BaseType
|
||||||
| Some (BaseTypeInfo.ForeignAssemblyType (assy, ty)) ->
|
| Some (BaseTypeInfo.ForeignAssemblyType (assy, ty)) ->
|
||||||
let assy = loadedAssemblies.[assy.FullName]
|
let assy = loadedAssemblies.[assy.FullName]
|
||||||
|
|
||||||
@@ -547,7 +547,7 @@ module DumpedAssembly =
|
|||||||
| Some v -> v
|
| Some v -> v
|
||||||
| None ->
|
| None ->
|
||||||
let ty = assy.TypeDefs.[ty]
|
let ty = assy.TypeDefs.[ty]
|
||||||
go ty.BaseType
|
go assy.Name ty.BaseType
|
||||||
| Some (BaseTypeInfo.TypeSpec _) -> failwith "TODO"
|
| Some (BaseTypeInfo.TypeSpec _) -> failwith "TODO"
|
||||||
| Some (BaseTypeInfo.TypeDef h) ->
|
| Some (BaseTypeInfo.TypeDef h) ->
|
||||||
let assy = loadedAssemblies.[source.FullName]
|
let assy = loadedAssemblies.[source.FullName]
|
||||||
@@ -556,7 +556,7 @@ module DumpedAssembly =
|
|||||||
| Some v -> v
|
| Some v -> v
|
||||||
| None ->
|
| None ->
|
||||||
let ty = assy.TypeDefs.[h]
|
let ty = assy.TypeDefs.[h]
|
||||||
go ty.BaseType
|
go assy.Name ty.BaseType
|
||||||
| None -> ResolvedBaseType.Object
|
| None -> ResolvedBaseType.Object
|
||||||
|
|
||||||
go baseTypeInfo
|
go source baseTypeInfo
|
||||||
|
@@ -142,6 +142,17 @@ type MethodInstructions =
|
|||||||
ExceptionRegions : ImmutableArray<ExceptionRegion>
|
ExceptionRegions : ImmutableArray<ExceptionRegion>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static member OnlyRet : MethodInstructions =
|
||||||
|
let op = IlOp.Nullary NullaryIlOp.Ret
|
||||||
|
|
||||||
|
{
|
||||||
|
Instructions = [ op, 0 ]
|
||||||
|
Locations = Map.empty |> Map.add 0 op
|
||||||
|
LocalsInit = false
|
||||||
|
LocalVars = None
|
||||||
|
ExceptionRegions = ImmutableArray.Empty
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents detailed information about a method in a .NET assembly.
|
/// Represents detailed information about a method in a .NET assembly.
|
||||||
/// This is a strongly-typed representation of MethodDefinition from System.Reflection.Metadata.
|
/// This is a strongly-typed representation of MethodDefinition from System.Reflection.Metadata.
|
||||||
|
@@ -40,6 +40,29 @@ module Program =
|
|||||||
|
|
||||||
arrayAllocation, state
|
arrayAllocation, state
|
||||||
|
|
||||||
|
let rec pumpToReturn
|
||||||
|
(loggerFactory : ILoggerFactory)
|
||||||
|
(logger : ILogger)
|
||||||
|
(baseClassTypes : BaseClassTypes<DumpedAssembly>)
|
||||||
|
impls
|
||||||
|
(mainThread : ThreadId)
|
||||||
|
(state : IlMachineState)
|
||||||
|
: IlMachineState * ThreadId
|
||||||
|
=
|
||||||
|
match AbstractMachine.executeOneStep loggerFactory impls baseClassTypes state mainThread with
|
||||||
|
| ExecutionResult.Terminated (state, terminatingThread) -> state, terminatingThread
|
||||||
|
| ExecutionResult.Stepped (state', whatWeDid) ->
|
||||||
|
|
||||||
|
match whatWeDid with
|
||||||
|
| WhatWeDid.Executed ->
|
||||||
|
logger.LogInformation $"Executed one step; active assembly: {state'.ActiveAssembly(mainThread).Name.Name}"
|
||||||
|
| WhatWeDid.SuspendedForClassInit ->
|
||||||
|
logger.LogInformation "Suspended execution of current method for class initialisation."
|
||||||
|
| WhatWeDid.BlockedOnClassInit threadBlockingUs ->
|
||||||
|
logger.LogInformation "Unable to execute because class has not yet initialised."
|
||||||
|
|
||||||
|
pumpToReturn loggerFactory logger baseClassTypes impls mainThread state'
|
||||||
|
|
||||||
/// Returns the abstract machine's state at the end of execution, together with the thread which
|
/// Returns the abstract machine's state at the end of execution, together with the thread which
|
||||||
/// caused execution to end.
|
/// caused execution to end.
|
||||||
let run
|
let run
|
||||||
@@ -83,7 +106,7 @@ module Program =
|
|||||||
dumped
|
dumped
|
||||||
// pretend there are no instructions, so we avoid preparing anything
|
// pretend there are no instructions, so we avoid preparing anything
|
||||||
{ mainMethod with
|
{ mainMethod with
|
||||||
Instructions = None
|
Instructions = Some MethodInstructions.OnlyRet
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
(ImmutableArray.CreateRange [ CliType.ObjectRef None ])
|
(ImmutableArray.CreateRange [ CliType.ObjectRef None ])
|
||||||
@@ -153,7 +176,14 @@ module Program =
|
|||||||
| TypeDefn.PrimitiveType PrimitiveType.Int32 -> ()
|
| TypeDefn.PrimitiveType PrimitiveType.Int32 -> ()
|
||||||
| _ -> failwith "Main method must return int32; other types not currently supported"
|
| _ -> failwith "Main method must return int32; other types not currently supported"
|
||||||
|
|
||||||
// Now that BCL initialisation has taken place, overwrite the main thread completely.
|
// We might be in the middle of class construction. Pump the static constructors to completion.
|
||||||
|
// We haven't yet entered the main method!
|
||||||
|
|
||||||
|
let state, _ =
|
||||||
|
pumpToReturn loggerFactory logger baseClassTypes impls mainThread state
|
||||||
|
|
||||||
|
// Now that BCL initialisation has taken place and the user-code classes are constructed,
|
||||||
|
// overwrite the main thread completely.
|
||||||
let methodState =
|
let methodState =
|
||||||
match
|
match
|
||||||
MethodState.Empty
|
MethodState.Empty
|
||||||
@@ -171,27 +201,22 @@ module Program =
|
|||||||
let threadState =
|
let threadState =
|
||||||
{ state.ThreadState.[mainThread] with
|
{ state.ThreadState.[mainThread] with
|
||||||
MethodStates = ImmutableArray.Create methodState
|
MethodStates = ImmutableArray.Create methodState
|
||||||
|
ActiveMethodState = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
let state =
|
let state, init =
|
||||||
{ state with
|
{ state with
|
||||||
ThreadState = state.ThreadState |> Map.add mainThread threadState
|
ThreadState = state.ThreadState |> Map.add mainThread threadState
|
||||||
}
|
}
|
||||||
|
|> IlMachineState.ensureTypeInitialised
|
||||||
|
loggerFactory
|
||||||
|
baseClassTypes
|
||||||
|
mainThread
|
||||||
|
methodState.ExecutingMethod.DeclaringType
|
||||||
|
|
||||||
let rec go (state : IlMachineState) =
|
match init with
|
||||||
match AbstractMachine.executeOneStep loggerFactory impls baseClassTypes state mainThread with
|
| WhatWeDid.SuspendedForClassInit -> failwith "TODO: suspended for class init"
|
||||||
| ExecutionResult.Terminated (state, terminatingThread) -> state, terminatingThread
|
| WhatWeDid.BlockedOnClassInit _ -> failwith "logic error: surely this thread can't be blocked on class init"
|
||||||
| ExecutionResult.Stepped (state', whatWeDid) ->
|
| WhatWeDid.Executed -> ()
|
||||||
|
|
||||||
match whatWeDid with
|
pumpToReturn loggerFactory logger baseClassTypes impls mainThread state
|
||||||
| WhatWeDid.Executed ->
|
|
||||||
logger.LogInformation
|
|
||||||
$"Executed one step; active assembly: {state'.ActiveAssembly(mainThread).Name.Name}"
|
|
||||||
| WhatWeDid.SuspendedForClassInit ->
|
|
||||||
logger.LogInformation "Suspended execution of current method for class initialisation."
|
|
||||||
| WhatWeDid.BlockedOnClassInit threadBlockingUs ->
|
|
||||||
logger.LogInformation "Unable to execute because class has not yet initialised."
|
|
||||||
|
|
||||||
go state'
|
|
||||||
|
|
||||||
go state
|
|
||||||
|
Reference in New Issue
Block a user