mirror of
https://github.com/Smaug123/WoofWare.PawPrint
synced 2025-10-05 14:18:40 +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)
|
||||
: ResolvedBaseType
|
||||
=
|
||||
let rec go (baseType : BaseTypeInfo option) =
|
||||
let rec go (source : AssemblyName) (baseType : BaseTypeInfo option) =
|
||||
match baseType with
|
||||
| Some (BaseTypeInfo.TypeRef r) ->
|
||||
let assy = loadedAssemblies.[source.FullName]
|
||||
@@ -539,7 +539,7 @@ module DumpedAssembly =
|
||||
| TypeResolutionResult.Resolved (assy, typeInfo) ->
|
||||
match TypeInfo.isBaseType bct _.Name assy.Name typeInfo.TypeDefHandle with
|
||||
| Some v -> v
|
||||
| None -> go typeInfo.BaseType
|
||||
| None -> go assy.Name typeInfo.BaseType
|
||||
| Some (BaseTypeInfo.ForeignAssemblyType (assy, ty)) ->
|
||||
let assy = loadedAssemblies.[assy.FullName]
|
||||
|
||||
@@ -547,7 +547,7 @@ module DumpedAssembly =
|
||||
| Some v -> v
|
||||
| None ->
|
||||
let ty = assy.TypeDefs.[ty]
|
||||
go ty.BaseType
|
||||
go assy.Name ty.BaseType
|
||||
| Some (BaseTypeInfo.TypeSpec _) -> failwith "TODO"
|
||||
| Some (BaseTypeInfo.TypeDef h) ->
|
||||
let assy = loadedAssemblies.[source.FullName]
|
||||
@@ -556,7 +556,7 @@ module DumpedAssembly =
|
||||
| Some v -> v
|
||||
| None ->
|
||||
let ty = assy.TypeDefs.[h]
|
||||
go ty.BaseType
|
||||
go assy.Name ty.BaseType
|
||||
| None -> ResolvedBaseType.Object
|
||||
|
||||
go baseTypeInfo
|
||||
go source baseTypeInfo
|
||||
|
@@ -142,6 +142,17 @@ type MethodInstructions =
|
||||
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>
|
||||
/// Represents detailed information about a method in a .NET assembly.
|
||||
/// This is a strongly-typed representation of MethodDefinition from System.Reflection.Metadata.
|
||||
|
@@ -40,6 +40,29 @@ module Program =
|
||||
|
||||
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
|
||||
/// caused execution to end.
|
||||
let run
|
||||
@@ -83,7 +106,7 @@ module Program =
|
||||
dumped
|
||||
// pretend there are no instructions, so we avoid preparing anything
|
||||
{ mainMethod with
|
||||
Instructions = None
|
||||
Instructions = Some MethodInstructions.OnlyRet
|
||||
}
|
||||
None
|
||||
(ImmutableArray.CreateRange [ CliType.ObjectRef None ])
|
||||
@@ -153,7 +176,14 @@ module Program =
|
||||
| TypeDefn.PrimitiveType PrimitiveType.Int32 -> ()
|
||||
| _ -> 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 =
|
||||
match
|
||||
MethodState.Empty
|
||||
@@ -171,27 +201,22 @@ module Program =
|
||||
let threadState =
|
||||
{ state.ThreadState.[mainThread] with
|
||||
MethodStates = ImmutableArray.Create methodState
|
||||
ActiveMethodState = 0
|
||||
}
|
||||
|
||||
let state =
|
||||
let state, init =
|
||||
{ state with
|
||||
ThreadState = state.ThreadState |> Map.add mainThread threadState
|
||||
}
|
||||
|> IlMachineState.ensureTypeInitialised
|
||||
loggerFactory
|
||||
baseClassTypes
|
||||
mainThread
|
||||
methodState.ExecutingMethod.DeclaringType
|
||||
|
||||
let rec go (state : IlMachineState) =
|
||||
match AbstractMachine.executeOneStep loggerFactory impls baseClassTypes state mainThread with
|
||||
| ExecutionResult.Terminated (state, terminatingThread) -> state, terminatingThread
|
||||
| ExecutionResult.Stepped (state', whatWeDid) ->
|
||||
match init with
|
||||
| WhatWeDid.SuspendedForClassInit -> failwith "TODO: suspended for class init"
|
||||
| WhatWeDid.BlockedOnClassInit _ -> failwith "logic error: surely this thread can't be blocked on class init"
|
||||
| WhatWeDid.Executed -> ()
|
||||
|
||||
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."
|
||||
|
||||
go state'
|
||||
|
||||
go state
|
||||
pumpToReturn loggerFactory logger baseClassTypes impls mainThread state
|
||||
|
Reference in New Issue
Block a user