Merge commit '174e415c70843d905a6d40790cbdfdcf0f21cbdb' into generic-edge-cases

This commit is contained in:
Smaug123
2025-08-23 22:51:31 +01:00
4 changed files with 102 additions and 7 deletions

View File

@@ -52,6 +52,14 @@ module Parameter =
result.ToImmutable ()
type GenericVariance =
| Covariant
| Contravariant
type GenericConstraint =
| Reference
| NonNullableValue
/// <summary>
/// Represents a generic type or method parameter definition.
/// Corresponds to GenericParameter in System.Reflection.Metadata.
@@ -66,6 +74,10 @@ type GenericParameter =
/// For example, in Dictionary&lt;TKey, TValue&rt;, TKey has index 0 and TValue has index 1.
/// </summary>
SequenceNumber : int
Variance : GenericVariance option
Constraint : GenericConstraint option
RequiresParameterlessConstructor : bool
}
[<RequireQualifiedAccess>]
@@ -79,9 +91,31 @@ module GenericParameter =
|> Seq.map (fun param ->
let param = metadata.GetGenericParameter param
let requiresParamlessCons =
param.Attributes.HasFlag GenericParameterAttributes.DefaultConstructorConstraint
let constr =
if param.Attributes.HasFlag GenericParameterAttributes.NotNullableValueTypeConstraint then
Some GenericConstraint.NonNullableValue
elif param.Attributes.HasFlag GenericParameterAttributes.ReferenceTypeConstraint then
Some GenericConstraint.Reference
else
None
let variance =
if param.Attributes.HasFlag GenericParameterAttributes.Contravariant then
Some GenericVariance.Contravariant
elif param.Attributes.HasFlag GenericParameterAttributes.Covariant then
Some GenericVariance.Covariant
else
None
{
Name = metadata.GetString param.Name
SequenceNumber = param.Index
Variance = variance
Constraint = constr
RequiresParameterlessConstructor = requiresParamlessCons
}
)
|> ImmutableArray.CreateRange

View File

@@ -119,7 +119,13 @@ module ConcreteActivePatterns =
match handle with
| ConcreteTypeHandle.Concrete id ->
match concreteTypes.Mapping |> Map.tryFind id with
| Some ct when ct.Namespace = "System" && ct.Name = "Void" && ct.Generics.IsEmpty -> Some ()
| Some ct when
ct.Assembly.Name = "System.Private.CoreLib"
&& ct.Namespace = "System"
&& ct.Name = "Void"
&& ct.Generics.IsEmpty
->
Some ()
| _ -> None
| _ -> None
@@ -149,6 +155,34 @@ module ConcreteActivePatterns =
| None -> None
| _ -> None
let (|ConcreteRuntimeFieldHandle|_|) (concreteTypes : AllConcreteTypes) (handle : ConcreteTypeHandle) =
match handle with
| ConcreteTypeHandle.Concrete id ->
match concreteTypes.Mapping |> Map.tryFind id with
| Some ct when
ct.Assembly.Name = "System.Private.CoreLib"
&& ct.Namespace = "System"
&& ct.Name = "RuntimeFieldHandle"
&& ct.Generics.IsEmpty
->
Some ()
| _ -> None
| _ -> None
let (|ConcreteNonGenericArray|_|) (concreteTypes : AllConcreteTypes) (handle : ConcreteTypeHandle) =
match handle with
| ConcreteTypeHandle.Concrete id ->
match concreteTypes.Mapping |> Map.tryFind id with
| Some ct when
ct.Assembly.Name = "System.Private.CoreLib"
&& ct.Namespace = "System"
&& ct.Name = "Array"
&& ct.Generics.IsEmpty
->
Some ()
| _ -> None
| _ -> None
let (|ConcreteBool|_|) (concreteTypes : AllConcreteTypes) (handle : ConcreteTypeHandle) : unit option =
match handle with
| ConcreteTypeHandle.Concrete id ->
@@ -542,7 +576,7 @@ module TypeConcretization =
let rec concretizeType
(ctx : ConcretizationContext<'corelib>)
(loadAssembly :
AssemblyName -> AssemblyReferenceHandle -> (ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly))
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(assembly : AssemblyName)
(typeGenerics : ConcreteTypeHandle ImmutableArray)
(methodGenerics : ConcreteTypeHandle ImmutableArray)
@@ -890,7 +924,7 @@ module Concretization =
let concretizeMethod
(ctx : AllConcreteTypes)
(loadAssembly :
AssemblyName -> AssemblyReferenceHandle -> (ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly))
AssemblyName -> AssemblyReferenceHandle -> ImmutableDictionary<string, DumpedAssembly> * DumpedAssembly)
(assemblies : ImmutableDictionary<string, DumpedAssembly>)
(baseTypes : BaseClassTypes<DumpedAssembly>)
(method : WoofWare.PawPrint.MethodInfo<TypeDefn, WoofWare.PawPrint.GenericParameter, TypeDefn>)

View File

@@ -403,9 +403,9 @@ module IlMachineState =
| PrimitiveType.Double -> baseClassTypes.Double
| PrimitiveType.String -> baseClassTypes.String
| PrimitiveType.TypedReference -> failwith "todo"
| PrimitiveType.IntPtr -> failwith "todo"
| PrimitiveType.UIntPtr -> failwith "todo"
| PrimitiveType.Object -> failwith "todo"
| PrimitiveType.IntPtr -> baseClassTypes.IntPtr
| PrimitiveType.UIntPtr -> baseClassTypes.UIntPtr
| PrimitiveType.Object -> baseClassTypes.Object
|> TypeInfo.mapGeneric (fun _ -> failwith "none of these types are generic")
state, baseClassTypes.Corelib, ty

View File

@@ -403,7 +403,34 @@ module internal UnaryConstIlOp =
else
id
|> Tuple.withRight WhatWeDid.Executed
| Bne_un_s b -> failwith "TODO: Bne_un_s unimplemented"
| Bne_un_s b ->
// Table III.4
let value2, state = IlMachineState.popEvalStack currentThread state
let value1, state = IlMachineState.popEvalStack currentThread state
let isNotEqual =
match value1, value2 with
| EvalStackValue.Int32 v1, EvalStackValue.Int32 v2 -> v1 <> v2
| EvalStackValue.Int32 v1, EvalStackValue.NativeInt v2 -> failwith "TODO"
| EvalStackValue.Int32 v1, _ -> failwith $"invalid comparison, {v1} with {value2}"
| _, EvalStackValue.Int32 v2 -> failwith $"invalid comparison, {value1} with {v2}"
| EvalStackValue.Int64 v1, EvalStackValue.Int64 v2 -> v1 <> v2
| EvalStackValue.Int64 v1, _ -> failwith $"invalid comparison, {v1} with {value2}"
| _, EvalStackValue.Int64 v2 -> failwith $"invalid comparison, {value1} with {v2}"
| EvalStackValue.Float v1, EvalStackValue.Float v2 -> v1 <> v2
| _, EvalStackValue.Float v2 -> failwith $"invalid comparison, {value1} with {v2}"
| EvalStackValue.Float v1, _ -> failwith $"invalid comparison, {v1} with {value2}"
| EvalStackValue.NativeInt v1, EvalStackValue.NativeInt v2 -> v1 <> v2
| EvalStackValue.ManagedPointer ptr1, EvalStackValue.ManagedPointer ptr2 -> ptr1 <> ptr2
| _, _ -> failwith $"TODO {value1} {value2} (see table III.4)"
state
|> IlMachineState.advanceProgramCounter currentThread
|> if isNotEqual then
IlMachineState.jumpProgramCounter currentThread (int b)
else
id
|> Tuple.withRight WhatWeDid.Executed
| Bge_un_s b ->
let value2, state = IlMachineState.popEvalStack currentThread state
let value1, state = IlMachineState.popEvalStack currentThread state