Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ internal FieldOnTypeBuilderInstantiation(FieldInfo field, TypeBuilderInstantiati
#region Public Abstract\Virtual Members
public override Type[] GetRequiredCustomModifiers() { return _field.GetRequiredCustomModifiers(); }
public override Type[] GetOptionalCustomModifiers() { return _field.GetOptionalCustomModifiers(); }
public override Type GetModifiedFieldType() => _field.GetModifiedFieldType();
public override void SetValueDirect(TypedReference obj, object value)
{
throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public override MethodInfo MakeGenericMethod(params Type[] typeArgs)

#region Public Abstract\Virtual Members
public override Type ReturnType => _method.ReturnType;
public override ParameterInfo ReturnParameter => throw new NotSupportedException();
public override ParameterInfo ReturnParameter => _method.ReturnParameter;
public override ICustomAttributeProvider ReturnTypeCustomAttributes => throw new NotSupportedException();
public override MethodInfo GetBaseDefinition() { throw new NotSupportedException(); }
#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ public override void SetValue(object? obj, object? val, BindingFlags invokeAttr,

public override Type[] GetOptionalCustomModifiers() => _optionalCustomModifiers ?? Type.EmptyTypes;

public override Type GetModifiedFieldType() => FieldType;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works for function pointers, but is it acceptable? It doesn't behave how a user might expect (although it didn't work at all until now, so there's that).


#endregion

#region ICustomAttributeProvider Implementation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ internal void AppendMetadata(MethodBodyStreamEncoder methodBodyEncoder, BlobBuil
}

// Now write all generic parameters in order
genericParams.Sort((x, y) => {
genericParams.Sort((x, y) =>
{
int primary = CodedIndex.TypeOrMethodDef(x._parentHandle).CompareTo(CodedIndex.TypeOrMethodDef(y._parentHandle));
if (primary != 0)
return primary;
Expand Down Expand Up @@ -690,6 +691,8 @@ internal void WriteCustomAttributes(List<CustomAttributeWrapper>? customAttribut

private EntityHandle GetTypeReferenceOrSpecificationHandle(Type type)
{
type = type.UnderlyingSystemType;

if (!_typeReferences.TryGetValue(type, out var typeHandle))
{
if (type.HasElementType || type.IsGenericParameter ||
Expand Down Expand Up @@ -740,7 +743,7 @@ private EntityHandle GetMemberReferenceHandle(MemberInfo memberInfo)
declaringType = declaringType.MakeGenericType(declaringType.GetGenericArguments());
}

Type fieldType = ((FieldInfo)GetOriginalMemberIfConstructedType(field)).FieldType;
Type fieldType = ((FieldInfo)GetOriginalMemberIfConstructedType(field)).GetModifiedFieldType();
memberHandle = AddMemberReference(field.Name, GetTypeHandle(declaringType),
MetadataSignatureHelper.GetFieldSignature(fieldType, field.GetRequiredCustomModifiers(), field.GetOptionalCustomModifiers(), this));

Expand Down Expand Up @@ -791,7 +794,7 @@ private EntityHandle GetMethodReference(MethodInfo methodInfo, Type[] optionalPa
}

private BlobBuilder GetMethodSignature(MethodInfo method, Type[]? optionalParameterTypes) =>
MetadataSignatureHelper.GetMethodSignature(this, ParameterTypes(method.GetParameters()), method.ReturnType,
MetadataSignatureHelper.GetMethodSignature(this, ParameterTypes(method.GetParameters()), method.ReturnParameter.GetModifiedParameterType(),
GetSignatureConvention(method.CallingConvention), method.GetGenericArguments().Length, !method.IsStatic, optionalParameterTypes);

private BlobBuilder GetMethodArrayMethodSignature(ArrayMethod method) => MetadataSignatureHelper.GetMethodSignature(
Expand Down Expand Up @@ -829,7 +832,7 @@ private MemberInfo GetOriginalMemberIfConstructedType(MemberInfo memberInfo)
return memberInfo;
}

private static Type[] ParameterTypes(ParameterInfo[] parameterInfos)
internal static Type[] ParameterTypes(ParameterInfo[] parameterInfos)
{
if (parameterInfos.Length == 0)
{
Expand All @@ -840,7 +843,7 @@ private static Type[] ParameterTypes(ParameterInfo[] parameterInfos)

for (int i = 0; i < parameterInfos.Length; i++)
{
parameterTypes[i] = parameterInfos[i].ParameterType;
parameterTypes[i] = parameterInfos[i].GetModifiedParameterType();
}

return parameterTypes;
Expand All @@ -861,7 +864,7 @@ private AssemblyReferenceHandle GetAssemblyReference(Assembly assembly)
}
else
{
publicKeyOrToken = aName.GetPublicKeyToken();
publicKeyOrToken = aName.GetPublicKeyToken();
}
handle = AddAssemblyReference(aName.Name, aName.Version, aName.CultureName, publicKeyOrToken, assemblyFlags);
_assemblyReferences.Add(assembly, handle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan
internal sealed class ParameterInfoWrapper : ParameterInfo
{
private readonly ParameterBuilderImpl _pb;
private readonly Type _type
;
private readonly Type _type;
public ParameterInfoWrapper(ParameterBuilderImpl pb, Type type)
{
_pb = pb;
Expand All @@ -87,5 +86,7 @@ public ParameterInfoWrapper(ParameterBuilderImpl pb, Type type)
public override bool HasDefaultValue => _pb._defaultValue != DBNull.Value;

public override object? DefaultValue => HasDefaultValue ? _pb._defaultValue : null;

public override Type GetModifiedParameterType() => ParameterType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ internal static BlobBuilder GetConstructorSignature(ParameterInfo[]? parameters,

retType.Void();

WriteParametersSignature(module, Array.ConvertAll(parameters, p => p.ParameterType), parameterEncoder);
WriteParametersSignature(module, ModuleBuilderImpl.ParameterTypes(parameters), parameterEncoder);

return constructorSignature;
}
Expand Down Expand Up @@ -122,6 +122,8 @@ private static void WriteReturnTypeCustomModifiers(CustomModifiersEncoder encode

private static void WriteCustomModifiers(CustomModifiersEncoder encoder, Type[] customModifiers, bool isOptional, ModuleBuilderImpl module)
{
// GetOptionalCustomModifiers and GetRequiredCustomModifiers return modifiers in reverse order
Array.Reverse(customModifiers);
foreach (Type modifier in customModifiers)
{
encoder.AddModifier(module.GetTypeHandle(modifier), isOptional);
Expand Down Expand Up @@ -201,27 +203,27 @@ private static void WriteSignatureForType(SignatureTypeEncoder signature, Type t
module.GetTypeHandle(type.GetGenericTypeDefinition()), genericArguments.Length, type.IsValueType);
foreach (Type gType in genericArguments)
{
if (gType.IsGenericMethodParameter)
if (gType.UnderlyingSystemType.IsGenericMethodParameter)
{
encoder.AddArgument().GenericMethodTypeParameter(gType.GenericParameterPosition);
encoder.AddArgument().GenericMethodTypeParameter(gType.UnderlyingSystemType.GenericParameterPosition);
}
else if (gType.IsGenericParameter)
else if (gType.UnderlyingSystemType.IsGenericParameter)
{
encoder.AddArgument().GenericTypeParameter(gType.GenericParameterPosition);
encoder.AddArgument().GenericTypeParameter(gType.UnderlyingSystemType.GenericParameterPosition);
}
else
{
WriteSignatureForType(encoder.AddArgument(), gType, module);
}
}
}
else if (type.IsGenericMethodParameter)
else if (type.UnderlyingSystemType.IsGenericMethodParameter)
{
signature.GenericMethodTypeParameter(type.GenericParameterPosition);
signature.GenericMethodTypeParameter(type.UnderlyingSystemType.GenericParameterPosition);
}
else if (type.IsGenericParameter)
else if (type.UnderlyingSystemType.IsGenericParameter)
{
signature.GenericTypeParameter(type.GenericParameterPosition);
signature.GenericTypeParameter(type.UnderlyingSystemType.GenericParameterPosition);
}
else if (type.IsFunctionPointer)
{
Expand Down Expand Up @@ -295,6 +297,7 @@ private static void WriteSignatureForFunctionPointerType(SignatureTypeEncoder si

private static void WriteSimpleSignature(SignatureTypeEncoder signature, Type type, ModuleBuilderImpl module)
{
type = type.UnderlyingSystemType;
CoreTypeId? typeId = module.GetTypeIdFromCoreTypes(type);

switch (typeId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -633,8 +633,8 @@ public void ReturnTypeAndParameterRequiredOptionalCustomModifiers()
Type[] par0RequiredMods = allModMethod.GetParameters()[0].GetRequiredCustomModifiers();
Type[] par0OptionalMods = allModMethod.GetParameters()[0].GetOptionalCustomModifiers();
Assert.Equal(2, returnReqMods.Length);
Assert.Equal(mlc.CoreAssembly.GetType(typeof(short).FullName), returnReqMods[0]);
Assert.Equal(mlc.CoreAssembly.GetType(typeof(int).FullName), returnReqMods[1]);
Assert.Equal(mlc.CoreAssembly.GetType(typeof(int).FullName), returnReqMods[0]);
Assert.Equal(mlc.CoreAssembly.GetType(typeof(short).FullName), returnReqMods[1]);
Assert.Equal(1, returnOptMods.Length);
Assert.Equal(mlc.CoreAssembly.GetType(typeof(Version).FullName), returnOptMods[0]);
Assert.Equal(cmodsReq1.Length, par0RequiredMods.Length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@ public void SaveFunctionPointerFields()
}

[Fact]
public void ConsumeFunctionPointerFields()
public void ConsumeFunctionPointerMembers()
{
// public unsafe class Container
// {
Expand Down Expand Up @@ -915,16 +915,29 @@ public void ConsumeFunctionPointerFields()
MethodBuilder mainMethod = programType.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static);
mainMethod.SetReturnType(typeof(int));
ILGenerator il = mainMethod.GetILGenerator();
il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerFields).GetField("field1"));
il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field1"));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field2"));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field3"));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field4"));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field5"));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method1"));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method2"));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method3"));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method4"));
il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method5"));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ldsfld, typeof(GenericClassWithFunctionPointerMembers<int>).GetField("Field"));
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Call, typeof(GenericClassWithFunctionPointerMembers<Guid>).GetMethod("Method").MakeGenericMethod(typeof(string)));
il.Emit(OpCodes.Pop);
// References to fields with unmanaged calling convention are broken
// [ActiveIssue("https://github.com/dotnet/runtime/issues/120909")]
// il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerFields).GetField("field2"));
// il.Emit(OpCodes.Pop);
// il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerFields).GetField("field3"));
// il.Emit(OpCodes.Pop);
// il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerFields).GetField("field4"));
// il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Call, assembly1FromDisk.GetType("Container").GetMethod("Init"));
il.Emit(OpCodes.Ldc_I4_2);
il.Emit(OpCodes.Ldc_I4_3);
Expand Down Expand Up @@ -989,11 +1002,24 @@ public class ClassWithFields : EmptyTestClass
public byte field2;
}

public unsafe class ClassWithFunctionPointerFields
public unsafe class ClassWithFunctionPointerMembers
{
public static delegate*<ClassWithFunctionPointerFields> field1;
public static delegate*<ClassWithFunctionPointerMembers> field1;
public static delegate* unmanaged<int> field2;
public static delegate* unmanaged[Cdecl]<Guid> field3;
public static delegate* unmanaged[Cdecl, SuppressGCTransition]<Vector<int>, Vector<int>> field4;
public static List<delegate* unmanaged[Stdcall, MemberFunction, SuppressGCTransition]<long>*[]> field5;

public static delegate*<int> Method1() => null;
public static delegate* unmanaged<string> Method2() => null;
public static delegate* unmanaged[Fastcall]<double> Method3() => null;
public static delegate* unmanaged[Cdecl]<delegate* unmanaged<int>, Guid> Method4() => null;
public static delegate* unmanaged[Cdecl]<int> Method5(delegate* unmanaged[Cdecl]<delegate* unmanaged<int>, Guid> funcPtr) => null;
}

public unsafe class GenericClassWithFunctionPointerMembers<T>
{
public static delegate* unmanaged[Cdecl]<T> Field;
public static delegate* unmanaged[Fastcall, MemberFunction]<T, U> Method<U>() => null;
}
}
Loading