Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix test issues discovered from enabling AOT for authoring scenarios #1432

Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
270f2a4
Add property/logic to generate WinRT native exports
Sergio0694 Nov 22, 2023
af87b27
Make CsWinRTAotExportsEnabled compiler visible
Sergio0694 Nov 22, 2023
3b4401e
Automatically set CsWinRTAotExportsEnabled if needed
Sergio0694 Nov 22, 2023
6354f4a
Update authoring targets for NativeAOT scenario
Sergio0694 Nov 22, 2023
ed6bb9f
Refactor items in authoring .targets for clarity
Sergio0694 Nov 23, 2023
6ae4341
Fix two typos in generated native exports
Sergio0694 Nov 23, 2023
5596f81
Return REGDB_E_CLASSNOTREG for class not registered
Sergio0694 Nov 25, 2023
282c652
Enable testing authoring scenario with NativeAOT
Sergio0694 Nov 25, 2023
19ef41f
Return CLASS_E_CLASSNOTAVAILABLE instead
Sergio0694 Nov 25, 2023
b43a60e
Update WinRT.Host.runtimeconfig.json for .NET 8
Sergio0694 Nov 25, 2023
26979d9
Update .NET 8 SDK to 8.0.100 stable
Sergio0694 Nov 25, 2023
987db7c
Update AuthoringConsumptionTest.vcxproj
Sergio0694 Nov 25, 2023
dc3f311
Skip native host copy target for NAOT
Sergio0694 Nov 25, 2023
d887b4a
Fix AuthoringTest .NET TFM in AuthoringWinUITest projects
Sergio0694 Nov 27, 2023
38098bf
Update unit test for class not registered
Sergio0694 Nov 28, 2023
a6c49f0
Update CsWinRTExeTFM for .NET 7 and .NET 8
Sergio0694 Nov 30, 2023
c4180b2
Handle .NET 8 in generator
Sergio0694 Dec 1, 2023
d0225f7
Fix version causing debug build failures
manodasanW Dec 2, 2023
c2ac695
Add target to publish AuthoringTest from consuming test
Sergio0694 Dec 2, 2023
92451c8
Publish AuthoringTest with NAOT in build.cmd
Sergio0694 Dec 3, 2023
67dc5c2
Fix publishing for AOT (some tests still failing).
manodasanW Dec 20, 2023
f561450
Merge pull request #1422 from microsoft/staging/AOT
manodasanW Dec 23, 2023
55aa7da
Fix gaps found from AuthoringTest being built for AOT
manodasanW Dec 26, 2023
2d1709b
Add property/logic to generate WinRT native exports
Sergio0694 Nov 22, 2023
1ce610b
Make CsWinRTAotExportsEnabled compiler visible
Sergio0694 Nov 22, 2023
bce52e6
Automatically set CsWinRTAotExportsEnabled if needed
Sergio0694 Nov 22, 2023
6b20fef
Update authoring targets for NativeAOT scenario
Sergio0694 Nov 22, 2023
14a1d82
Refactor items in authoring .targets for clarity
Sergio0694 Nov 23, 2023
ea1a82e
Fix two typos in generated native exports
Sergio0694 Nov 23, 2023
22456bd
Return REGDB_E_CLASSNOTREG for class not registered
Sergio0694 Nov 25, 2023
98b79a7
Enable testing authoring scenario with NativeAOT
Sergio0694 Nov 25, 2023
0afd56e
Return CLASS_E_CLASSNOTAVAILABLE instead
Sergio0694 Nov 25, 2023
b381692
Update WinRT.Host.runtimeconfig.json for .NET 8
Sergio0694 Nov 25, 2023
e2d9173
Update .NET 8 SDK to 8.0.100 stable
Sergio0694 Nov 25, 2023
f7faec2
Update AuthoringConsumptionTest.vcxproj
Sergio0694 Nov 25, 2023
4498c02
Skip native host copy target for NAOT
Sergio0694 Nov 25, 2023
6703c83
Fix AuthoringTest .NET TFM in AuthoringWinUITest projects
Sergio0694 Nov 27, 2023
dce62a0
Update unit test for class not registered
Sergio0694 Nov 28, 2023
8843654
Update CsWinRTExeTFM for .NET 7 and .NET 8
Sergio0694 Nov 30, 2023
c407c76
Handle .NET 8 in generator
Sergio0694 Dec 1, 2023
2db4e9d
Fix version causing debug build failures
manodasanW Dec 2, 2023
62a2fdd
Add target to publish AuthoringTest from consuming test
Sergio0694 Dec 2, 2023
f6c2c0a
Publish AuthoringTest with NAOT in build.cmd
Sergio0694 Dec 3, 2023
fa62a4c
Fix publishing for AOT (some tests still failing).
manodasanW Dec 20, 2023
535fdf2
Fix issue with IID optimizer for certain scenarios and fix missing vt…
manodasanW Jan 8, 2024
2410694
Merge branch 'user/sergiopedri/naot-winrt-exports' into manodasanw/na…
manodasanW Jan 8, 2024
d57f6a6
Fix bug where generics in class names caused issues
manodasanW Jan 8, 2024
f2a0c6b
Merge branch 'user/sergiopedri/naot-winrt-exports' into manodasanw/na…
manodasanW Jan 9, 2024
2453f07
Address PR feedback
manodasanW Jan 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 77 additions & 25 deletions src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs

Large diffs are not rendered by default.

30 changes: 24 additions & 6 deletions src/Authoring/WinRT.SourceGenerator/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ private static bool IsFundamentalType(ISymbol type)
}

public static bool IsWinRTType(ISymbol type)
{
return IsWinRTType(type, null);
}

public static bool IsWinRTType(ISymbol type, Func<ISymbol, bool> isAuthoringWinRTType)
{
bool isProjectedType = type.GetAttributes().
Any(attribute => string.CompareOrdinal(attribute.AttributeClass.Name, "WindowsRuntimeTypeAttribute") == 0) ||
Expand All @@ -206,8 +211,11 @@ public static bool IsWinRTType(ISymbol type)
// Ensure all generic parameters are WinRT types.
if (isProjectedType && type is INamedTypeSymbol namedType && namedType.IsGenericType && !namedType.IsDefinition)
{
isProjectedType = namedType.TypeArguments.All(IsWinRTType);
isProjectedType = namedType.TypeArguments.All(t =>
IsWinRTType(t, isAuthoringWinRTType) ||
(isAuthoringWinRTType != null && isAuthoringWinRTType(t)));
}

return isProjectedType;
}

Expand All @@ -218,13 +226,23 @@ public static bool IsInternalInterfaceFromReferences(INamedTypeSymbol iface, IAs
(iface.IsGenericType && iface.TypeArguments.Any(typeArgument => IsInternalInterfaceFromReferences(typeArgument as INamedTypeSymbol, currentAssembly)));
}

// Checks whether the symbol references any generic that hasn't been instantiated.
// For instance, List<T> where T is a generic.
public static bool HasNonInstantiatedGeneric(ITypeSymbol symbol)
// Checks whether the symbol references any generic that hasn't been instantiated
// and is used by a WinRT interface. For instance, List<T> where T is a generic.
// If the generic isn't used by any WinRT interface, this returns false as for
// instance, we can still generate the vtable attribute for it.
public static bool HasNonInstantiatedWinRTGeneric(ITypeSymbol symbol)
{
return symbol is INamedTypeSymbol namedType &&
(namedType.TypeKind == TypeKind.TypeParameter ||
namedType.TypeArguments.Any(argument => argument.TypeKind == TypeKind.TypeParameter));
(IsArgumentTypeParameter(namedType) ||
(namedType.TypeArguments.Any(IsArgumentTypeParameter) &&
namedType.AllInterfaces.Any(iface => iface.TypeArguments.Any(IsArgumentTypeParameter) &&
// Checks if without the non-instantiated generic, whether it would be a WinRT type.
IsWinRTType(iface.OriginalDefinition, null))));

static bool IsArgumentTypeParameter(ITypeSymbol argument)
{
return argument.TypeKind == TypeKind.TypeParameter;
}
}

public static bool HasPrivateclass(ITypeSymbol symbol)
Expand Down
28 changes: 24 additions & 4 deletions src/Authoring/WinRT.SourceGenerator/WinRTTypeWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2663,8 +2663,13 @@ public void FinalizeGeneration()

public void GenerateWinRTExposedClassAttributes(GeneratorExecutionContext context)
{
static bool IsWinRTType(ISymbol symbol)
bool IsWinRTType(ISymbol symbol)
{
if (!SymbolEqualityComparer.Default.Equals(symbol.ContainingAssembly, context.Compilation.Assembly))
{
return GeneratorHelper.IsWinRTType(symbol, IsWinRTType);
}

if (symbol is INamedTypeSymbol namedType)
{
if (namedType.TypeKind == TypeKind.Interface)
Expand All @@ -2687,6 +2692,8 @@ static bool IsWinRTType(ISymbol symbol)
}

List<VtableAttribute> vtableAttributesToAdd = new();
HashSet<VtableAttribute> vtableAttributesToAddOnLookupTable = new();

foreach (var typeDeclaration in typeDefinitionMapping.Values)
{
if (typeDeclaration.IsComponentType &&
Expand All @@ -2695,15 +2702,28 @@ typeDeclaration.Node is INamedTypeSymbol symbol &&
!symbol.IsStatic)
{
vtableAttributesToAdd.Add(WinRTAotSourceGenerator.GetVtableAttributeToAdd(symbol, IsWinRTType, context.Compilation.Assembly, true, typeDeclaration.DefaultInterface));
WinRTAotSourceGenerator.AddVtableAdapterTypeForKnownInterface(symbol, context.Compilation, IsWinRTType, vtableAttributesToAddOnLookupTable);
}
}

if (vtableAttributesToAdd.Any())
if (vtableAttributesToAdd.Any() || vtableAttributesToAddOnLookupTable.Any())
{
WinRTAotSourceGenerator.GenerateVtableAttributes(context.AddSource, vtableAttributesToAdd.ToImmutableArray());
WinRTAotSourceGenerator.GenerateCCWForGenericInstantiation(
context.AddSource,
vtableAttributesToAdd.SelectMany(static (vtableAttribute, _) => vtableAttribute.GenericInterfaces).ToImmutableArray());
vtableAttributesToAdd.SelectMany(static (vtableAttribute, _) => vtableAttribute.GenericInterfaces).
Union(vtableAttributesToAddOnLookupTable.SelectMany(static (vtableAttribute, _) => vtableAttribute.GenericInterfaces)).
Distinct().
ToImmutableArray());
}

if (vtableAttributesToAdd.Any())
{
WinRTAotSourceGenerator.GenerateVtableAttributes(context.AddSource, vtableAttributesToAdd.ToImmutableArray(), false);
}

if (vtableAttributesToAddOnLookupTable.Any())
{
WinRTAotSourceGenerator.GenerateVtableLookupTable(context.AddSource, (vtableAttributesToAddOnLookupTable.ToImmutableArray(), (true, true)), true);
}
}

Expand Down
92 changes: 76 additions & 16 deletions src/Perf/IIDOptimizer/SignatureEmitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,8 @@ private void GenerateGuidFactoryFromComplexSignature(TypeDefinition implementati
il.Emit(OpCodes.Stloc, destination);

// SHA1.HashData(fullSignatureBuffer, destination);
var sha1Type = CecilExtensions.FindTypeReference(module, "System.Security.Cryptography", "SHA1", "System.Security.Cryptography.Algorithms", false);
var sha1Type = module.ImportReference(
new TypeReference("System.Security.Cryptography", "SHA1", module, new AssemblyNameReference("System.Security.Cryptography.Algorithms", default), false).Resolve());
var hashDataMethod = module.ImportReference(
new MethodReference("HashData", module.ImportReference(module.TypeSystem.Int32), sha1Type)
{
Expand All @@ -427,30 +428,89 @@ private void GenerateGuidFactoryFromComplexSignature(TypeDefinition implementati
}
});

var spanToReadOnlySpan = module.ImportReference(
new MethodReference("op_Implicit",
new GenericInstanceType(module.ImportReference(readOnlySpanOfByte.Resolve()))
// HashData is not defined in .NET Standard
if (hashDataMethod.Resolve() is null)
{
var spanToArrayMethod = module.ImportReference(
new MethodReference("ToArray", new ArrayType(span.Resolve().GenericParameters[0]), spanOfByte)
{
HasThis = true,
});

// byte[] arrayToHash = data.ToArray();
var arrayToHash = new VariableDefinition(new ArrayType(module.TypeSystem.Byte));
staticCtor.Body.Variables.Add(arrayToHash);
il.Emit(OpCodes.Ldloca, fullSignatureBuffer);
il.Emit(OpCodes.Call, spanToArrayMethod);
il.Emit(OpCodes.Stloc, arrayToHash);

// using (SHA1 sha = new SHA1CryptoServiceProvider())
// destination = sha.ComputeHash(data);
var sha1CryptoServiceProvider = module.ImportReference(
new TypeReference("System.Security.Cryptography", "SHA1CryptoServiceProvider", module, new AssemblyNameReference("netstandard", default), false).Resolve());
var sha = new VariableDefinition(sha1CryptoServiceProvider);
staticCtor.Body.Variables.Add(sha);
var sha1CryptoServiceProviderCtor = module.ImportReference(
new MethodReference(".ctor", module.TypeSystem.Void, sha1CryptoServiceProvider)
{
GenericArguments = { span.Resolve().GenericParameters[0] }
HasThis = true
},
spanOfByte)
{
HasThis = false,
Parameters =
sha1CryptoServiceProvider);
il.Emit(OpCodes.Newobj, sha1CryptoServiceProviderCtor);
il.Emit(OpCodes.Stloc, sha);

var computeHashMethod = module.ImportReference(
new MethodReference("ComputeHash", new ArrayType(module.TypeSystem.Byte), sha1CryptoServiceProvider)
{
HasThis = true,
Parameters =
{
new ParameterDefinition(new ArrayType(module.TypeSystem.Byte))
}
});
il.Emit(OpCodes.Ldloc, sha);
il.Emit(OpCodes.Ldloc, arrayToHash);
il.Emit(OpCodes.Callvirt, computeHashMethod);
il.Emit(OpCodes.Newobj, spanOfByteArrayCtor);
il.Emit(OpCodes.Stloc, destination);

var disposable = module.ImportReference(
new TypeReference("System", "IDisposable", module, new AssemblyNameReference("netstandard", default), false).Resolve());
var disposeMethod = module.ImportReference(
new MethodReference("Dispose", module.TypeSystem.Void, disposable)
{
HasThis = true,
});
il.Emit(OpCodes.Ldloc, sha);
il.Emit(OpCodes.Callvirt, disposeMethod);
}
else
{
var spanToReadOnlySpan = module.ImportReference(
new MethodReference("op_Implicit",
new GenericInstanceType(module.ImportReference(readOnlySpanOfByte.Resolve()))
{
GenericArguments = { span.Resolve().GenericParameters[0] }
},
spanOfByte)
{
HasThis = false,
Parameters =
{
new ParameterDefinition(
new GenericInstanceType(span)
{
GenericArguments = { span.Resolve().GenericParameters[0] }
})
}
});
}
});

il.Emit(OpCodes.Ldloc, fullSignatureBuffer);
il.Emit(OpCodes.Call, spanToReadOnlySpan);
il.Emit(OpCodes.Ldloc, destination);
il.Emit(OpCodes.Call, hashDataMethod);
il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ldloc, fullSignatureBuffer);
il.Emit(OpCodes.Call, spanToReadOnlySpan);
il.Emit(OpCodes.Ldloc, destination);
il.Emit(OpCodes.Call, hashDataMethod);
il.Emit(OpCodes.Pop);
}

// Fix endianness, bytes
var memoryExtensions = CecilExtensions.FindTypeReference(module, "System", "MemoryExtensions", "System.Memory", false);
Expand Down
7 changes: 5 additions & 2 deletions src/Perf/IIDOptimizer/SignatureGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,11 @@ public SignaturePart GetSignatureParts(TypeReference type)
var typeDef = type.Resolve();

var helperType = new TypeReference($"ABI.{typeDef.Namespace}", typeDef.Name, typeDef.Module, assembly.MainModule);

if (helperType.Resolve() is not null)
if (helperType.Resolve() is not null ||
// Handle custom mapped built-in structs such as System.Numerics.Vector3 which have their ABI type defined in WinRT.Runtime.
// This is handled separately due to the need for the is public check which isn't needed if in same module as in the initial case.
((helperType = typeDef.GetCswinrtAbiTypeDefinition(winRTRuntimeAssembly)) is not null &&
((TypeDefinition)helperType).Attributes.HasFlag(TypeAttributes.Public)))
{
if (type.IsGenericInstance)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Tests/AuthoringTest/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ public void Dispose()
}
}

internal sealed class NonProjectedDisposableClass : IDisposable
internal sealed partial class NonProjectedDisposableClass : IDisposable
{
public bool IsDisposed { get; set; }

Expand Down
Loading