Skip to content

Commit

Permalink
Address issues discovered after fixing AOT warnings (#1511)
Browse files Browse the repository at this point in the history
* Fix build breaks from AOT warning fixes

* Improvements to GUID helper type lookup to avoid needing instantiated generic type

* Move around where helper type is initialized to handle more scenarios

* Remove commented code
  • Loading branch information
manodasanW authored and Sergio0694 committed Mar 12, 2024
1 parent 3db682d commit 6446fba
Show file tree
Hide file tree
Showing 15 changed files with 188 additions and 176 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PreprocessorDefinitions>X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>X64;NDEBUG;AOT;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
Expand Down
3 changes: 3 additions & 0 deletions src/Tests/AuthoringConsumptionTest/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ TEST(AuthoringTest, Arrays)
EXPECT_EQ(arr2[idx], idx + 1);
}

// Array marshaling on AOT needs dynamic code.
#ifndef AOT
std::array<BasicStruct, 2> basicStructArr;
basicStructArr[0] = basicClass.GetBasicStruct();
basicStructArr[1].X = 4;
Expand All @@ -272,6 +274,7 @@ TEST(AuthoringTest, Arrays)
EXPECT_EQ(result[1].X, basicStructArr[1].X);
EXPECT_EQ(result[1].Y, basicStructArr[1].Y);
EXPECT_EQ(result[1].Value, basicStructArr[1].Value);
#endif
}

TEST(AuthoringTest, CustomTypes)
Expand Down
9 changes: 9 additions & 0 deletions src/WinRT.Runtime/ComWrappersSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,15 @@ internal static ObjectReference<T> GetObjectReferenceForInterface<T>(IntPtr exte

public static void RegisterAuthoringMetadataTypeLookup(Func<Type, Type> authoringMetadataTypeLookup) => TypeExtensions.RegisterAuthoringMetadataTypeLookup(authoringMetadataTypeLookup);

public static void RegisterHelperType(
Type type,
#if NET
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods |
DynamicallyAccessedMemberTypes.PublicNestedTypes |
DynamicallyAccessedMemberTypes.PublicFields)]
#endif
Type helperType) => TypeExtensions.HelperTypeCache.TryAdd(type, helperType);

internal static List<ComInterfaceEntry> GetInterfaceTableEntries(Type type)
{
var entries = new List<ComInterfaceEntry>();
Expand Down
133 changes: 67 additions & 66 deletions src/WinRT.Runtime/GuidGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static Guid GetGUID(Type type)
return type.GetGuidType().GUID;
}

public static Guid GetIID(
public static Guid GetIID(
#if NET
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
#endif
Expand All @@ -35,21 +35,40 @@ public static Guid GetIID(
return (Guid)type.GetField("PIID").GetValue(null);
}

public static string GetSignature(
public static string GetSignature(
#if NET
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
#endif
Type type)
{
{
if (type == typeof(object))
{
return "cinterface(IInspectable)";
}

}

if (type == typeof(string))
{
return "string";
}
}

if (type.IsGenericType)
{
static string[] SelectSignaturesForTypes(Type[] types)
{
string[] signatures = new string[types.Length];

for (int i = 0; i < types.Length; i++)
{
signatures[i] = GetSignature(types[i]);
}

return signatures;
}

var args = SelectSignaturesForTypes(type.GetGenericArguments());
var genericHelperType = type.GetGenericTypeDefinition().FindHelperType() ?? type;
return "pinterface({" + genericHelperType.GUID + "};" + string.Join(";", args) + ")";
}

var helperType = type.FindHelperType();
if (helperType != null)
Expand Down Expand Up @@ -88,70 +107,52 @@ public static string GetSignature(
if (!type.IsPrimitive)
{
var winrtTypeAttribute = type.GetCustomAttribute<WindowsRuntimeTypeAttribute>();
if (winrtTypeAttribute != null && !string.IsNullOrEmpty(winrtTypeAttribute.GuidSignature))
{
return winrtTypeAttribute.GuidSignature;
if (winrtTypeAttribute != null && !string.IsNullOrEmpty(winrtTypeAttribute.GuidSignature))
{
return winrtTypeAttribute.GuidSignature;
}
else if (winrtTypeAttribute == null &&
(winrtTypeAttribute = type.GetAuthoringMetadataType()?.GetCustomAttribute<WindowsRuntimeTypeAttribute>()) != null &&
!string.IsNullOrEmpty(winrtTypeAttribute.GuidSignature))
{
return winrtTypeAttribute.GuidSignature;
else if (winrtTypeAttribute == null &&
(winrtTypeAttribute = type.GetAuthoringMetadataType()?.GetCustomAttribute<WindowsRuntimeTypeAttribute>()) != null &&
!string.IsNullOrEmpty(winrtTypeAttribute.GuidSignature))
{
return winrtTypeAttribute.GuidSignature;
}
else
{
static string[] SelectSignaturesForFields(FieldInfo[] fields)
{
string[] signatures = new string[fields.Length];

for (int i = 0; i < fields.Length; i++)
{
signatures[i] = GetSignature(fields[i].FieldType);
}

return signatures;
}

var args = SelectSignaturesForFields(type.GetFields(BindingFlags.Instance | BindingFlags.Public));
return "struct(" + type.FullName + ";" + String.Join(";", args) + ")";
else
{
static string[] SelectSignaturesForFields(FieldInfo[] fields)
{
string[] signatures = new string[fields.Length];

for (int i = 0; i < fields.Length; i++)
{
signatures[i] = GetSignature(fields[i].FieldType);
}

return signatures;
}

var args = SelectSignaturesForFields(type.GetFields(BindingFlags.Instance | BindingFlags.Public));
return "struct(" + type.FullName + ";" + String.Join(";", args) + ")";
}
}
throw new InvalidOperationException("unsupported value type");
}
}
}

// For authoring interfaces, we can use the metadata type or the helper type to get the guid.
// For built-in system interfaces that are custom type mapped, we use the helper type to get the guid.
// For others, either the type itself or the helper type has the same guid and can be used.
type = type.IsInterface ? (helperType ?? type) : type;

if (type.IsGenericType)
{
static string[] SelectSignaturesForTypes(Type[] types)
{
string[] signatures = new string[types.Length];

for (int i = 0; i < types.Length; i++)
{
signatures[i] = GetSignature(types[i]);
}

return signatures;
}
// For authoring interfaces, we can use the metadata type or the helper type to get the guid.
// For built-in system interfaces that are custom type mapped, we use the helper type to get the guid.
// For others, either the type itself or the helper type has the same guid and can be used.
type = type.IsInterface ? (helperType ?? type) : type;

var args = SelectSignaturesForTypes(type.GetGenericArguments());
return "pinterface({" + GetGUID(type) + "};" + String.Join(";", args) + ")";
}

if (type.IsDelegate())
{
return "delegate({" + GetGUID(type) + "})";
}

if (type.IsClass && Projections.TryGetDefaultInterfaceTypeForRuntimeClassType(type, out Type iface))
{
return "rc(" + type.FullName + ";" + GetSignature(iface) + ")";
}

if (type.IsClass && Projections.TryGetDefaultInterfaceTypeForRuntimeClassType(type, out Type iface))
{
return "rc(" + type.FullName + ";" + GetSignature(iface) + ")";
}

return "{" + type.GUID.ToString() + "}";
Expand Down Expand Up @@ -195,14 +196,14 @@ public static Guid CreateIID(Type type)
{
return new Guid(sig);
}
else
{
return CreateIIDForGenericType(sig);
else
{
return CreateIIDForGenericType(sig);
}
}

internal static Guid CreateIIDForGenericType(string signature)
{
internal static Guid CreateIIDForGenericType(string signature)
{
#if !NET
var data = System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Concat(wrt_pinterface_namespace.ToByteArray(), Encoding.UTF8.GetBytes(signature)));

Expand All @@ -217,10 +218,10 @@ internal static Guid CreateIIDForGenericType(string signature)
Span<byte> dataSpan = data;
wrt_pinterface_namespace.TryWriteBytes(dataSpan);
var numBytes = UTF8Encoding.UTF8.GetBytes(signature, dataSpan[16..]);
data = data[..(16 + numBytes)];

return encode_guid(SHA1.HashData(data));
#endif
data = data[..(16 + numBytes)];

return encode_guid(SHA1.HashData(data));
#endif
}
}
}
3 changes: 2 additions & 1 deletion src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,5 @@ CannotRemoveAttribute : Attribute 'System.ObsoleteAttribute' exists on 'ABI.WinR
CannotRemoveAttribute : Attribute 'System.ComponentModel.EditorBrowsableAttribute' exists on 'WinRT.IObjectReference.AsType<T>()' in the implementation but not the reference.
CannotRemoveAttribute : Attribute 'System.ObsoleteAttribute' exists on 'WinRT.IObjectReference.AsType<T>()' in the implementation but not the reference.
CannotRemoveAttribute : Attribute 'System.ObsoleteAttribute' exists on 'System.Type WinRT.Marshaler<T>.RefAbiType' in the implementation but not the reference.
Total Issues: 211
MembersMustExist : Member 'public void WinRT.ComWrappersSupport.RegisterHelperType(System.Type, System.Type)' does not exist in the reference but it does exist in the implementation.
Total Issues: 212
2 changes: 1 addition & 1 deletion src/WinRT.Runtime/Projections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ public static Type FindCustomHelperTypeMapping(Type publicType, bool filterToRun
return null;
}

if (publicType.IsGenericType)
if (publicType.IsGenericType && !publicType.IsGenericTypeDefinition)
{
if (CustomTypeToHelperTypeMappings.TryGetValue(publicType, out Type specializedAbiType))
{
Expand Down
5 changes: 3 additions & 2 deletions src/WinRT.Runtime/Projections/EventHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ static class EventHandler<T>

static unsafe EventHandler()
{
ComWrappersSupport.RegisterHelperType(typeof(global::System.EventHandler<T>), typeof(global::ABI.System.EventHandler<T>));
ComWrappersSupport.RegisterDelegateFactory(typeof(global::System.EventHandler<T>), CreateRcw);

#if NET
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
Expand Down Expand Up @@ -152,8 +155,6 @@ static unsafe EventHandler()
((IntPtr*)AbiToProjectionVftablePtr)[3] = Marshal.GetFunctionPointerForDelegate(AbiInvokeDelegate);
#pragma warning restore IL3050
}

ComWrappersSupport.RegisterDelegateFactory(typeof(global::System.EventHandler<T>), CreateRcw);
}

public static global::System.Delegate AbiInvokeDelegate { get; }
Expand Down
28 changes: 14 additions & 14 deletions src/WinRT.Runtime/Projections/IDictionary.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ static class IDictionaryMethods<K, V>
{
unsafe static IDictionaryMethods()
{
ComWrappersSupport.RegisterHelperType(typeof(global::System.Collections.Generic.IDictionary<K, V>), typeof(global::ABI.System.Collections.Generic.IDictionary<K, V>));

// Early return to ensure things are trimmed correctly on NAOT.
// See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md.
if (!RuntimeFeature.IsDynamicCodeCompiled)
Expand Down Expand Up @@ -855,6 +857,9 @@ public static unsafe bool InitCcw(
return false;
}

// Register generic helper types referenced in CCW.
ComWrappersSupport.RegisterHelperType(typeof(global::System.Collections.Generic.IReadOnlyDictionary<K, V>), typeof(global::ABI.System.Collections.Generic.IReadOnlyDictionary<K, V>));

return true;
}

Expand All @@ -876,20 +881,15 @@ internal static unsafe void InitFallbackCCWVtable()
new IDictionary_Delegates.Clear_6(Do_Abi_Clear_6)
};

var abiToProjectionVftablePtr = (IntPtr)NativeMemory.AllocZeroed((nuint)(sizeof(IInspectable.Vftbl) + sizeof(IntPtr) * 7));
*(IInspectable.Vftbl*)abiToProjectionVftablePtr = IInspectable.Vftbl.AbiToProjectionVftable;
((IntPtr*)abiToProjectionVftablePtr)[6] = Marshal.GetFunctionPointerForDelegate(DelegateCache[0]);
((IntPtr*)abiToProjectionVftablePtr)[7] = Marshal.GetFunctionPointerForDelegate(DelegateCache[1]);
((IntPtr*)abiToProjectionVftablePtr)[8] = Marshal.GetFunctionPointerForDelegate(DelegateCache[2]);
((IntPtr*)abiToProjectionVftablePtr)[9] = Marshal.GetFunctionPointerForDelegate(DelegateCache[3]);
((IntPtr*)abiToProjectionVftablePtr)[10] = Marshal.GetFunctionPointerForDelegate(DelegateCache[4]);
((IntPtr*)abiToProjectionVftablePtr)[11] = Marshal.GetFunctionPointerForDelegate(DelegateCache[5]);
((IntPtr*)abiToProjectionVftablePtr)[12] = Marshal.GetFunctionPointerForDelegate(DelegateCache[6]);

if (!IDictionaryMethods<K, V>.TryInitCCWVtable(abiToProjectionVftablePtr))
{
NativeMemory.Free((void*)abiToProjectionVftablePtr);
}
InitCcw(
(delegate* unmanaged[Stdcall]<IntPtr, KAbi, VAbi*, int>) Marshal.GetFunctionPointerForDelegate(DelegateCache[0]),
(delegate* unmanaged[Stdcall]<IntPtr, uint*, int>) Marshal.GetFunctionPointerForDelegate(DelegateCache[1]),
(delegate* unmanaged[Stdcall]<IntPtr, KAbi, byte*, int>) Marshal.GetFunctionPointerForDelegate(DelegateCache[2]),
(delegate* unmanaged[Stdcall]<IntPtr, IntPtr*, int>) Marshal.GetFunctionPointerForDelegate(DelegateCache[3]),
(delegate* unmanaged[Stdcall]<IntPtr, KAbi, VAbi, byte*, int>) Marshal.GetFunctionPointerForDelegate(DelegateCache[4]),
(delegate* unmanaged[Stdcall]<IntPtr, KAbi, int>) Marshal.GetFunctionPointerForDelegate(DelegateCache[5]),
(delegate* unmanaged[Stdcall]<IntPtr, int>) Marshal.GetFunctionPointerForDelegate(DelegateCache[6])
);
}

private static unsafe int Do_Abi_Lookup_0(void* thisPtr, KAbi key, VAbi* __return_value__)
Expand Down
Loading

0 comments on commit 6446fba

Please sign in to comment.