mirror of
https://github.com/Smaug123/WoofWare.PawPrint
synced 2025-10-07 23:18:41 +00:00
Fix argument ordering bug (#58)
This commit is contained in:
@@ -244,6 +244,7 @@ type DumpedAssembly =
|
||||
interface IDisposable with
|
||||
member this.Dispose () = this.PeReader.Dispose ()
|
||||
|
||||
|
||||
type TypeResolutionResult =
|
||||
| FirstLoadAssy of WoofWare.PawPrint.AssemblyReference
|
||||
| Resolved of DumpedAssembly * TypeInfo<TypeDefn>
|
||||
@@ -516,3 +517,46 @@ module Assembly =
|
||||
match assemblies.TryGetValue assy.Name.FullName with
|
||||
| false, _ -> TypeResolutionResult.FirstLoadAssy assy
|
||||
| true, toAssy -> resolveTypeFromName toAssy assemblies ty.Namespace ty.Name genericArgs
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module DumpedAssembly =
|
||||
let resolveBaseType
|
||||
(bct : BaseClassTypes<DumpedAssembly>)
|
||||
(loadedAssemblies : ImmutableDictionary<string, DumpedAssembly>)
|
||||
(source : AssemblyName)
|
||||
(baseTypeInfo : BaseTypeInfo option)
|
||||
: ResolvedBaseType
|
||||
=
|
||||
let rec go (baseType : BaseTypeInfo option) =
|
||||
match baseType with
|
||||
| Some (BaseTypeInfo.TypeRef r) ->
|
||||
let assy = loadedAssemblies.[source.FullName]
|
||||
// TODO: generics
|
||||
match Assembly.resolveTypeRef loadedAssemblies assy assy.TypeRefs.[r] None with
|
||||
| TypeResolutionResult.FirstLoadAssy _ ->
|
||||
failwith
|
||||
"seems pretty unlikely that we could have constructed this object without loading its base type"
|
||||
| TypeResolutionResult.Resolved (assy, typeInfo) ->
|
||||
match TypeInfo.isBaseType bct _.Name assy.Name typeInfo.TypeDefHandle with
|
||||
| Some v -> v
|
||||
| None -> go typeInfo.BaseType
|
||||
| Some (BaseTypeInfo.ForeignAssemblyType (assy, ty)) ->
|
||||
let assy = loadedAssemblies.[assy.FullName]
|
||||
|
||||
match TypeInfo.isBaseType bct _.Name assy.Name ty with
|
||||
| Some v -> v
|
||||
| None ->
|
||||
let ty = assy.TypeDefs.[ty]
|
||||
go ty.BaseType
|
||||
| Some (BaseTypeInfo.TypeSpec _) -> failwith "TODO"
|
||||
| Some (BaseTypeInfo.TypeDef h) ->
|
||||
let assy = loadedAssemblies.[source.FullName]
|
||||
|
||||
match TypeInfo.isBaseType bct _.Name assy.Name h with
|
||||
| Some v -> v
|
||||
| None ->
|
||||
let ty = assy.TypeDefs.[h]
|
||||
go ty.BaseType
|
||||
| None -> ResolvedBaseType.Object
|
||||
|
||||
go baseTypeInfo
|
||||
|
@@ -132,6 +132,7 @@ type NullaryIlOp =
|
||||
| Ldind_i
|
||||
| Ldind_i1
|
||||
| Ldind_i2
|
||||
/// Loads a value of type int32 as an int32 onto the evaluation stack indirectly from the specified address.
|
||||
| Ldind_i4
|
||||
| Ldind_i8
|
||||
| Ldind_u1
|
||||
|
@@ -90,6 +90,8 @@ type TypeInfoEval<'ret> =
|
||||
type TypeInfoCrate =
|
||||
abstract Apply<'ret> : TypeInfoEval<'ret> -> 'ret
|
||||
abstract ToString : unit -> string
|
||||
abstract BaseType : BaseTypeInfo option
|
||||
abstract Assembly : AssemblyName
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module TypeInfoCrate =
|
||||
@@ -102,6 +104,10 @@ module TypeInfoCrate =
|
||||
member _.Eval this = string<TypeInfo<_>> this
|
||||
}
|
||||
|> this.Apply
|
||||
|
||||
member this.BaseType = t.BaseType
|
||||
|
||||
member this.Assembly = t.Assembly
|
||||
}
|
||||
|
||||
type BaseClassTypes<'corelib> =
|
||||
@@ -242,10 +248,32 @@ module TypeInfo =
|
||||
Events = events
|
||||
}
|
||||
|
||||
let isBaseType<'corelib>
|
||||
(baseClassTypes : BaseClassTypes<'corelib>)
|
||||
(getName : 'corelib -> AssemblyName)
|
||||
(typeAssy : AssemblyName)
|
||||
(typeDefinitionHandle : TypeDefinitionHandle)
|
||||
: ResolvedBaseType option
|
||||
=
|
||||
if typeAssy = getName baseClassTypes.Corelib then
|
||||
if typeDefinitionHandle = baseClassTypes.Enum.TypeDefHandle then
|
||||
Some ResolvedBaseType.Enum
|
||||
elif typeDefinitionHandle = baseClassTypes.ValueType.TypeDefHandle then
|
||||
Some ResolvedBaseType.ValueType
|
||||
elif typeDefinitionHandle = baseClassTypes.DelegateType.TypeDefHandle then
|
||||
Some ResolvedBaseType.Delegate
|
||||
elif typeDefinitionHandle = baseClassTypes.Object.TypeDefHandle then
|
||||
Some ResolvedBaseType.Object
|
||||
else
|
||||
None
|
||||
else
|
||||
None
|
||||
|
||||
let rec resolveBaseType<'corelib, 'generic>
|
||||
(baseClassTypes : BaseClassTypes<'corelib>)
|
||||
(getName : 'corelib -> AssemblyName)
|
||||
(getType : 'corelib -> TypeDefinitionHandle -> TypeInfo<'generic>)
|
||||
(getTypeDef : 'corelib -> TypeDefinitionHandle -> TypeInfo<'generic>)
|
||||
(getTypeRef : 'corelib -> TypeReferenceHandle -> TypeInfo<'generic>)
|
||||
(sourceAssembly : AssemblyName)
|
||||
(value : BaseTypeInfo option)
|
||||
: ResolvedBaseType
|
||||
@@ -256,37 +284,34 @@ module TypeInfo =
|
||||
|
||||
match value with
|
||||
| BaseTypeInfo.TypeDef typeDefinitionHandle ->
|
||||
if sourceAssembly = getName baseClassTypes.Corelib then
|
||||
if typeDefinitionHandle = baseClassTypes.Enum.TypeDefHandle then
|
||||
ResolvedBaseType.Enum
|
||||
elif typeDefinitionHandle = baseClassTypes.ValueType.TypeDefHandle then
|
||||
ResolvedBaseType.ValueType
|
||||
elif typeDefinitionHandle = baseClassTypes.DelegateType.TypeDefHandle then
|
||||
ResolvedBaseType.Delegate
|
||||
else
|
||||
let baseType = getType baseClassTypes.Corelib typeDefinitionHandle
|
||||
resolveBaseType baseClassTypes getName getType sourceAssembly baseType.BaseType
|
||||
else
|
||||
failwith "unexpected base type not in corelib"
|
||||
| BaseTypeInfo.TypeRef typeReferenceHandle -> failwith "todo"
|
||||
match isBaseType baseClassTypes getName sourceAssembly typeDefinitionHandle with
|
||||
| Some x -> x
|
||||
| None ->
|
||||
let baseType = getTypeDef baseClassTypes.Corelib typeDefinitionHandle
|
||||
resolveBaseType baseClassTypes getName getTypeDef getTypeRef sourceAssembly baseType.BaseType
|
||||
| BaseTypeInfo.TypeRef typeReferenceHandle ->
|
||||
let typeRef = getTypeRef baseClassTypes.Corelib typeReferenceHandle
|
||||
failwith $"{typeRef}"
|
||||
| BaseTypeInfo.TypeSpec typeSpecificationHandle -> failwith "todo"
|
||||
| BaseTypeInfo.ForeignAssemblyType (assemblyName, typeDefinitionHandle) ->
|
||||
resolveBaseType
|
||||
baseClassTypes
|
||||
getName
|
||||
getType
|
||||
getTypeDef
|
||||
getTypeRef
|
||||
assemblyName
|
||||
(Some (BaseTypeInfo.TypeDef typeDefinitionHandle))
|
||||
|
||||
let toTypeDefn
|
||||
(corelib : BaseClassTypes<'corelib>)
|
||||
(getName : 'corelib -> AssemblyName)
|
||||
(getType : 'corelib -> TypeDefinitionHandle -> TypeInfo<'generic>)
|
||||
(getTypeDef : 'corelib -> TypeDefinitionHandle -> TypeInfo<'generic>)
|
||||
(getTypeRef : 'corelib -> TypeReferenceHandle -> TypeInfo<'generic>)
|
||||
(ty : TypeInfo<'generic>)
|
||||
: TypeDefn
|
||||
=
|
||||
let stk =
|
||||
match resolveBaseType corelib getName getType ty.Assembly ty.BaseType with
|
||||
match resolveBaseType corelib getName getTypeDef getTypeRef ty.Assembly ty.BaseType with
|
||||
| ResolvedBaseType.Enum
|
||||
| ResolvedBaseType.ValueType -> SignatureTypeKind.ValueType
|
||||
| ResolvedBaseType.Object -> SignatureTypeKind.Class
|
||||
|
@@ -10,6 +10,7 @@ open WoofWare.PawPrint.ExternImplementations
|
||||
open WoofWare.PawPrint.Test
|
||||
|
||||
[<TestFixture>]
|
||||
[<Parallelizable(ParallelScope.All)>]
|
||||
module TestCases =
|
||||
let assy = typeof<RunResult>.Assembly
|
||||
|
||||
@@ -72,6 +73,20 @@ module TestCases =
|
||||
NativeImpls = MockEnv.make ()
|
||||
LocalVariablesOfMain = [ CliType.Numeric (CliNumericType.Int32 1) ]
|
||||
}
|
||||
{
|
||||
FileName = "ArgumentOrdering.cs"
|
||||
ExpectedReturnCode = 42
|
||||
NativeImpls = MockEnv.make ()
|
||||
LocalVariablesOfMain =
|
||||
[
|
||||
// localVar
|
||||
CliType.Numeric (CliNumericType.Int32 42)
|
||||
// t
|
||||
CliType.ValueType [ CliType.Numeric (CliNumericType.Int32 42) ]
|
||||
// return value
|
||||
CliType.Numeric (CliNumericType.Int32 42)
|
||||
]
|
||||
}
|
||||
{
|
||||
FileName = "BasicLock.cs"
|
||||
ExpectedReturnCode = 1
|
||||
|
@@ -27,6 +27,7 @@
|
||||
<EmbeddedResource Include="sources\InstaQuit.cs" />
|
||||
<EmbeddedResource Include="sources\Threads.cs" />
|
||||
<EmbeddedResource Include="sources\ResizeArray.cs" />
|
||||
<EmbeddedResource Include="sources\ArgumentOrdering.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
19
WoofWare.PawPrint.Test/sources/ArgumentOrdering.cs
Normal file
19
WoofWare.PawPrint.Test/sources/ArgumentOrdering.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
public class Program
|
||||
{
|
||||
public struct TestStruct
|
||||
{
|
||||
public int Value;
|
||||
|
||||
public TestStruct(ref int x)
|
||||
{
|
||||
Value = x;
|
||||
}
|
||||
}
|
||||
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
int localVar = 42;
|
||||
TestStruct t = new TestStruct(ref localVar);
|
||||
return t.Value;
|
||||
}
|
||||
}
|
@@ -30,10 +30,9 @@ module AbstractMachine =
|
||||
targetAssy.TypeDefs.[instruction.ExecutingMethod.DeclaringType.Definition.Get]
|
||||
|
||||
let baseType =
|
||||
TypeInfo.resolveBaseType
|
||||
DumpedAssembly.resolveBaseType
|
||||
baseClassTypes
|
||||
_.Name
|
||||
(fun x y -> x.TypeDefs.[y])
|
||||
state._LoadedAssemblies
|
||||
targetAssy.Name
|
||||
targetType.BaseType
|
||||
|
||||
|
@@ -63,7 +63,7 @@ type EvalStackValue =
|
||||
|
||||
override this.ToString () =
|
||||
match this with
|
||||
| EvalStackValue.Int32 i -> $"Int32(%i{i}"
|
||||
| EvalStackValue.Int32 i -> $"Int32(%i{i})"
|
||||
| EvalStackValue.Int64 i -> $"Int64(%i{i})"
|
||||
| EvalStackValue.NativeInt src -> $"NativeInt(%O{src})"
|
||||
| EvalStackValue.Float f -> $"Float(%f{f})"
|
||||
@@ -141,6 +141,7 @@ module EvalStackValue =
|
||||
| CliNumericType.Int32 _ ->
|
||||
match popped with
|
||||
| EvalStackValue.Int32 i -> CliType.Numeric (CliNumericType.Int32 i)
|
||||
| EvalStackValue.UserDefinedValueType [ popped ] -> toCliTypeCoerced target popped
|
||||
| i -> failwith $"TODO: %O{i}"
|
||||
| CliNumericType.ProvenanceTrackedNativeInt64 _
|
||||
| CliNumericType.Int64 _ ->
|
||||
@@ -223,8 +224,14 @@ module EvalStackValue =
|
||||
| CliType.ValueType fields ->
|
||||
match popped with
|
||||
| EvalStackValue.UserDefinedValueType popped ->
|
||||
if fields.Length <> popped.Length then
|
||||
failwith "mismatch"
|
||||
|
||||
List.map2 toCliTypeCoerced fields popped |> CliType.ValueType
|
||||
| popped -> failwith $"todo: %O{popped}"
|
||||
| popped ->
|
||||
match fields with
|
||||
| [ target ] -> toCliTypeCoerced target popped
|
||||
| _ -> failwith "TODO"
|
||||
|
||||
let rec ofCliType (v : CliType) : EvalStackValue =
|
||||
match v with
|
||||
|
@@ -295,7 +295,7 @@ module IlMachineState =
|
||||
|
||||
let baseType =
|
||||
arg.BaseType
|
||||
|> TypeInfo.resolveBaseType corelib _.Name (fun x y -> x.TypeDefs.[y]) assy.Name
|
||||
|> DumpedAssembly.resolveBaseType corelib state._LoadedAssemblies assy.Name
|
||||
|
||||
let signatureTypeKind =
|
||||
match baseType with
|
||||
@@ -571,7 +571,9 @@ module IlMachineState =
|
||||
state, newFrame, oldFrame
|
||||
else
|
||||
let args = ImmutableArray.CreateBuilder (methodToCall.Parameters.Length + 1)
|
||||
let mutable afterPop = activeMethodState
|
||||
|
||||
let thisPointer, afterPop = activeMethodState |> MethodState.popFromStack
|
||||
let mutable afterPop = afterPop
|
||||
|
||||
for i = 1 to methodToCall.Parameters.Length do
|
||||
let poppedArg, afterPop' = afterPop |> MethodState.popFromStack
|
||||
@@ -581,11 +583,12 @@ module IlMachineState =
|
||||
afterPop <- afterPop'
|
||||
args.Add poppedArg
|
||||
|
||||
let poppedArg, afterPop = afterPop |> MethodState.popFromStack
|
||||
// it only matters that the RuntimePointer is a RuntimePointer, so that the coercion has a target of the
|
||||
// right shape
|
||||
args.Add (
|
||||
EvalStackValue.toCliTypeCoerced (CliType.RuntimePointer (CliRuntimePointer.Unmanaged ())) poppedArg
|
||||
EvalStackValue.toCliTypeCoerced
|
||||
(CliType.RuntimePointer (CliRuntimePointer.Unmanaged ()))
|
||||
thisPointer
|
||||
)
|
||||
|
||||
args.Reverse ()
|
||||
@@ -1160,7 +1163,24 @@ module IlMachineState =
|
||||
match returnState.WasConstructingObj with
|
||||
| Some constructing ->
|
||||
// Assumption: a constructor can't also return a value.
|
||||
state |> pushToEvalStack (CliType.OfManagedObject constructing) currentThread
|
||||
// If we were constructing a reference type, we push a reference to it.
|
||||
// Otherwise, extract the now-complete object from the heap and push it to the stack directly.
|
||||
let constructed = state.ManagedHeap.NonArrayObjects.[constructing]
|
||||
|
||||
let resolvedBaseType =
|
||||
DumpedAssembly.resolveBaseType
|
||||
corelib
|
||||
state._LoadedAssemblies
|
||||
constructed.Type.Assembly
|
||||
constructed.Type.BaseType
|
||||
|
||||
match resolvedBaseType with
|
||||
| ResolvedBaseType.Object -> state |> pushToEvalStack (CliType.OfManagedObject constructing) currentThread
|
||||
| ResolvedBaseType.ValueType ->
|
||||
state
|
||||
|> pushToEvalStack (CliType.ValueType (Seq.toList constructed.Fields.Values)) currentThread
|
||||
| ResolvedBaseType.Enum -> failwith "TODO"
|
||||
| ResolvedBaseType.Delegate -> failwith "TODO"
|
||||
| None ->
|
||||
match threadStateAtEndOfMethod.MethodState.EvaluationStack.Values with
|
||||
| [] ->
|
||||
|
@@ -659,12 +659,61 @@ module NullaryIlOp =
|
||||
| Ldind_i -> failwith "TODO: Ldind_i unimplemented"
|
||||
| Ldind_i1 -> failwith "TODO: Ldind_i1 unimplemented"
|
||||
| Ldind_i2 -> failwith "TODO: Ldind_i2 unimplemented"
|
||||
| Ldind_i4 -> failwith "TODO: Ldind_i4 unimplemented"
|
||||
| Ldind_i4 ->
|
||||
let popped, state = IlMachineState.popEvalStack currentThread state
|
||||
|
||||
let value =
|
||||
let load (c : CliType) =
|
||||
match c with
|
||||
| CliType.Bool _ -> failwith "bool"
|
||||
| CliType.Numeric numeric ->
|
||||
match numeric with
|
||||
| CliNumericType.Int32 i -> i
|
||||
| _ -> failwith $"TODO: {numeric}"
|
||||
| CliType.Char _ -> failwith "tried to load a Char as a i4"
|
||||
| CliType.ObjectRef _ -> failwith "tried to load an ObjectRef as a i4"
|
||||
| CliType.RuntimePointer _ -> failwith "tried to load a RuntimePointer as a i4"
|
||||
| CliType.ValueType cliTypes -> failwith "todo"
|
||||
|
||||
match popped with
|
||||
| EvalStackValue.ManagedPointer src ->
|
||||
match src with
|
||||
| ManagedPointerSource.Null -> failwith "unexpected null pointer in Ldind_i4"
|
||||
| ManagedPointerSource.Argument (sourceThread, methodFrame, whichVar) ->
|
||||
let methodState =
|
||||
state.ThreadState.[sourceThread].MethodStates.[methodFrame].Arguments.[int<uint16> whichVar]
|
||||
|
||||
load methodState
|
||||
| ManagedPointerSource.LocalVariable (sourceThread, methodFrame, whichVar) ->
|
||||
let methodState =
|
||||
state.ThreadState.[sourceThread].MethodStates.[methodFrame].LocalVariables
|
||||
.[int<uint16> whichVar]
|
||||
|
||||
load methodState
|
||||
| ManagedPointerSource.Heap managedHeapAddress -> failwith "todo"
|
||||
| s -> failwith $"TODO(Ldind_i4): {s}"
|
||||
|
||||
let state =
|
||||
state
|
||||
|> IlMachineState.pushToEvalStack (CliType.Numeric (CliNumericType.Int32 value)) currentThread
|
||||
|> IlMachineState.advanceProgramCounter currentThread
|
||||
|
||||
(state, WhatWeDid.Executed) |> ExecutionResult.Stepped
|
||||
|
||||
| Ldind_i8 -> failwith "TODO: Ldind_i8 unimplemented"
|
||||
| Ldind_u1 ->
|
||||
let popped, state = IlMachineState.popEvalStack currentThread state
|
||||
|
||||
let value =
|
||||
let load (c : CliType) =
|
||||
match c with
|
||||
| CliType.Bool b -> b
|
||||
| CliType.Numeric numeric -> failwith $"tried to load a Numeric as a u8: {numeric}"
|
||||
| CliType.Char _ -> failwith "tried to load a Char as a u8"
|
||||
| CliType.ObjectRef _ -> failwith "tried to load an ObjectRef as a u8"
|
||||
| CliType.RuntimePointer _ -> failwith "tried to load a RuntimePointer as a u8"
|
||||
| CliType.ValueType cliTypes -> failwith "todo"
|
||||
|
||||
match popped with
|
||||
| EvalStackValue.NativeInt nativeIntSource -> failwith $"TODO: in Ldind_u1, {nativeIntSource}"
|
||||
| EvalStackValue.ManagedPointer src ->
|
||||
@@ -674,25 +723,14 @@ module NullaryIlOp =
|
||||
let methodState =
|
||||
state.ThreadState.[sourceThread].MethodStates.[methodFrame].Arguments.[int<uint16> whichVar]
|
||||
|
||||
match methodState with
|
||||
| CliType.Bool b -> b
|
||||
| CliType.Numeric numeric -> failwith $"tried to load a Numeric as a u8: {numeric}"
|
||||
| CliType.Char _ -> failwith "tried to load a Char as a u8"
|
||||
| CliType.ObjectRef _ -> failwith "tried to load an ObjectRef as a u8"
|
||||
| CliType.RuntimePointer _ -> failwith "tried to load a RuntimePointer as a u8"
|
||||
| CliType.ValueType cliTypes -> failwith "todo"
|
||||
load methodState
|
||||
|
||||
| ManagedPointerSource.LocalVariable (sourceThread, methodFrame, whichVar) ->
|
||||
let methodState =
|
||||
state.ThreadState.[sourceThread].MethodStates.[methodFrame].LocalVariables
|
||||
.[int<uint16> whichVar]
|
||||
|
||||
match methodState with
|
||||
| CliType.Bool b -> b
|
||||
| CliType.Numeric numeric -> failwith $"tried to load a Numeric as a u8: {numeric}"
|
||||
| CliType.Char _ -> failwith "tried to load a Char as a u8"
|
||||
| CliType.ObjectRef _ -> failwith "tried to load an ObjectRef as a u8"
|
||||
| CliType.RuntimePointer _ -> failwith "tried to load a RuntimePointer as a u8"
|
||||
| CliType.ValueType cliTypes -> failwith "todo"
|
||||
load methodState
|
||||
| ManagedPointerSource.Heap managedHeapAddress -> failwith "todo"
|
||||
| EvalStackValue.ObjectRef managedHeapAddress -> failwith "todo"
|
||||
| popped -> failwith $"unexpected Ldind_u1 input: {popped}"
|
||||
|
@@ -206,6 +206,11 @@ module internal UnaryMetadataIlOp =
|
||||
|
||||
let fields = List.rev fieldZeros
|
||||
|
||||
// Note: this is a bit unorthodox for value types, which *aren't* heap-allocated.
|
||||
// We'll perform their construction on the heap, though, to keep the interface
|
||||
// of Newobj uniform.
|
||||
// On completion of the constructor, we'll copy the value back off the heap,
|
||||
// and put it on the eval stack directly.
|
||||
let allocatedAddr, state =
|
||||
IlMachineState.allocateManagedObject ctorType fields state
|
||||
|
||||
@@ -255,7 +260,7 @@ module internal UnaryMetadataIlOp =
|
||||
|
||||
let baseType =
|
||||
defn.BaseType
|
||||
|> TypeInfo.resolveBaseType baseClassTypes _.Name (fun x y -> x.TypeDefs.[y]) defn.Assembly
|
||||
|> DumpedAssembly.resolveBaseType baseClassTypes state._LoadedAssemblies defn.Assembly
|
||||
|
||||
let signatureTypeKind =
|
||||
match baseType with
|
||||
@@ -312,10 +317,9 @@ module internal UnaryMetadataIlOp =
|
||||
let ty = activeAssy.TypeDefs.[td]
|
||||
|
||||
let baseTy =
|
||||
TypeInfo.resolveBaseType
|
||||
DumpedAssembly.resolveBaseType
|
||||
baseClassTypes
|
||||
_.Name
|
||||
(fun x y -> x.TypeDefs.[y])
|
||||
state._LoadedAssemblies
|
||||
activeAssy.Name
|
||||
ty.BaseType
|
||||
|
||||
@@ -602,7 +606,7 @@ module internal UnaryMetadataIlOp =
|
||||
| true, v -> IlMachineState.pushToEvalStack v.Fields.[field.Name] thread state
|
||||
| ManagedPointerSource.Null -> failwith "TODO: raise NullReferenceException"
|
||||
| EvalStackValue.ObjectRef managedHeapAddress -> failwith $"todo: {managedHeapAddress}"
|
||||
| EvalStackValue.UserDefinedValueType _ -> failwith "todo"
|
||||
| EvalStackValue.UserDefinedValueType _ as udvt -> IlMachineState.pushToEvalStack' udvt thread state
|
||||
|
||||
state
|
||||
|> IlMachineState.advanceProgramCounter thread
|
||||
@@ -745,6 +749,7 @@ module internal UnaryMetadataIlOp =
|
||||
baseClassTypes
|
||||
_.Name
|
||||
(fun x y -> x.TypeDefs.[y])
|
||||
(fun x y -> x.TypeRefs.[y] |> failwithf "%+A")
|
||||
(elementType
|
||||
|> TypeInfo.mapGeneric (fun i _ ->
|
||||
{
|
||||
|
Reference in New Issue
Block a user