diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs index 0b1b74009..fd76cf46c 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs @@ -66,10 +66,130 @@ public static void IIDs( out get_ReferenceIidMethod); } + /// + /// Creates a new type definition for the vtable for an IDelegate interface. + /// + /// The for the type. + /// The instance to use. + /// The instance to use. + /// The emit state for this invocation. + /// The interop module being built. + /// The resulting vtable type. + public static void Vftbl( + GenericInstanceTypeSignature delegateType, + InteropDefinitions interopDefinitions, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module, + out TypeDefinition vftblType) + { + MemberReference delegateInvokeMethod = interopReferences.DelegateInvoke(delegateType, module); + + // Prepare the sender and arguments types (same as for the 'Impl' type below) + TypeSignature senderType = ((MethodSignature)delegateInvokeMethod.Signature!).ParameterTypes[0]; + TypeSignature argsType = ((MethodSignature)delegateInvokeMethod.Signature!).ParameterTypes[1]; + + bool isSenderReferenceType = senderType.HasReferenceAbiType(interopReferences); + bool isArgsReferenceType = argsType.HasReferenceAbiType(interopReferences); + + // We can share the vtable type for 'void*' when both sender and args types are reference types + if (isSenderReferenceType && isArgsReferenceType) + { + vftblType = interopDefinitions.DelegateVftbl; + + return; + } + + // If both the sender and the args types are not reference types, we can't possibly share + // the vtable type. So in this case, we just always construct a specialized new type. + if (!isSenderReferenceType && !isArgsReferenceType) + { + vftblType = WellKnownTypeDefinitionFactory.DelegateVftbl( + ns: InteropUtf8NameFactory.TypeNamespace(delegateType), + name: InteropUtf8NameFactory.TypeName(delegateType, "Vftbl"), + senderType: senderType.GetAbiType(interopReferences), + argsType: argsType.GetAbiType(interopReferences), + interopReferences: interopReferences, + module: module); + + module.TopLevelTypes.Add(vftblType); + + return; + } + + // Helper to create vtable types that can be shared between multiple delegate types + static void GetOrCreateVftbl( + TypeSignature senderType, + TypeSignature argsType, + TypeSignature displaySenderType, + TypeSignature displayArgsType, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module, + out TypeDefinition vftblType) + { + // If we already have a vtable type for this pair, reuse that + if (emitState.TryGetDelegateVftblType(senderType, argsType, out vftblType!)) + { + return; + } + + // Create a dummy signature just to generate the mangled name for the vtable type + TypeSignature sharedEventHandlerType = interopReferences.EventHandler2.MakeGenericReferenceType( + displaySenderType, + displayArgsType); + + // Construct a new specialized vtable type + TypeDefinition newVftblType = WellKnownTypeDefinitionFactory.DelegateVftbl( + ns: InteropUtf8NameFactory.TypeNamespace(sharedEventHandlerType), + name: InteropUtf8NameFactory.TypeName(sharedEventHandlerType, "Vftbl"), + senderType: senderType, + argsType: argsType, + interopReferences: interopReferences, + module: module); + + // Go through the lookup so that we can reuse the vtable later + vftblType = emitState.GetOrAddDelegateVftblType(senderType, argsType, newVftblType); + + // If we won the race and this is the vtable type that was just created, we can add it to the module + if (vftblType == newVftblType) + { + module.TopLevelTypes.Add(newVftblType); + } + } + + // Get or create a shared vtable where the reference type is replaced with just 'void*' + if (isSenderReferenceType) + { + GetOrCreateVftbl( + senderType: interopReferences.CorLibTypeFactory.Void.MakePointerType(), + argsType: argsType.GetAbiType(interopReferences), + displaySenderType: interopReferences.CorLibTypeFactory.Object, + displayArgsType: argsType, + interopReferences: interopReferences, + emitState: emitState, + module: module, + out vftblType); + } + else + { + GetOrCreateVftbl( + senderType: senderType.GetAbiType(interopReferences), + argsType: interopReferences.CorLibTypeFactory.Void.MakePointerType(), + displaySenderType: senderType, + displayArgsType: interopReferences.CorLibTypeFactory.Object, + interopReferences: interopReferences, + emitState: emitState, + module: module, + out vftblType); + } + } + /// /// Creates a new type definition for the implementation of the vtable for an 'IDelegate' interface. /// /// The for the type. + /// The type returned by . /// The instance to use. /// The instance to use. /// The emit state for this invocation. @@ -77,6 +197,7 @@ public static void IIDs( /// The resulting implementation type. public static void ImplType( GenericInstanceTypeSignature delegateType, + TypeDefinition vftblType, InteropDefinitions interopDefinitions, InteropReferences interopReferences, InteropGeneratorEmitState emitState, @@ -172,7 +293,7 @@ public static void ImplType( interfaceType: ComInterfaceType.InterfaceIsIUnknown, ns: InteropUtf8NameFactory.TypeNamespace(delegateType), name: InteropUtf8NameFactory.TypeName(delegateType, "Impl"), - vftblType: interopDefinitions.DelegateVftbl, + vftblType: vftblType, interopDefinitions: interopDefinitions, interopReferences: interopReferences, module: module, @@ -401,12 +522,14 @@ public static void ComWrappersCallbackType( /// The for the type. /// The instance to use. /// The instance to use. + /// The emit state for this invocation. /// The interop module being built. /// The resulting callback type. public static void NativeDelegateType( GenericInstanceTypeSignature delegateType, InteropDefinitions interopDefinitions, InteropReferences interopReferences, + InteropGeneratorEmitState emitState, ModuleDefinition module, out TypeDefinition nativeDelegateType) { @@ -436,14 +559,15 @@ public static void NativeDelegateType( parameterTypes: [ interopReferences.WindowsRuntimeObjectReference.ToReferenceTypeSignature().Import(module), senderType.Import(module), - argsType.Import(module)])) - { CilMethodBody = new CilMethodBody() }; + argsType.Import(module)])); nativeDelegateType.Methods.Add(invokeMethod); - // Get the method body for the 'Invoke' method - CilMethodBody invokeBody = invokeMethod.CilMethodBody; - CilInstructionCollection invokeInstructions = invokeBody.Instructions; + // Prepare the 'Invoke' signature + MethodSignature invokeSignature = WellKnownTypeSignatureFactory.InvokeImpl( + senderType: senderType.GetAbiType(interopReferences), + argsType: argsType.GetAbiType(interopReferences), + interopReferences: interopReferences); // Import 'WindowsRuntimeObjectReferenceValue', compute it just once TypeSignature windowsRuntimeObjectReferenceValueType = interopReferences.WindowsRuntimeObjectReferenceValue @@ -452,93 +576,94 @@ public static void NativeDelegateType( // Declare the local variables: // [0]: 'WindowsRuntimeObjectReferenceValue' (for 'thisValue') - // [1]: 'WindowsRuntimeObjectReferenceValue' (for 'senderValue') - // [2]: 'WindowsRuntimeObjectReferenceValue' (for 'eValue') - // [3]: 'void*' (for 'thisPtr') - invokeBody.LocalVariables.Add(new CilLocalVariable(windowsRuntimeObjectReferenceValueType)); - invokeBody.LocalVariables.Add(new CilLocalVariable(windowsRuntimeObjectReferenceValueType)); - invokeBody.LocalVariables.Add(new CilLocalVariable(windowsRuntimeObjectReferenceValueType)); - invokeBody.LocalVariables.Add(new CilLocalVariable(module.CorLibTypeFactory.Void.MakePointerType())); + // [1]: 'void*' (for 'thisPtr') + CilLocalVariable loc_0_thisValue = new(windowsRuntimeObjectReferenceValueType); + CilLocalVariable loc_1_thisPtr = new(module.CorLibTypeFactory.Void.MakePointerType()); + // Jump labels + CilInstruction nop_try_this = new(Nop); + CilInstruction nop_try_sender = new(Nop); + CilInstruction nop_try_args = new(Nop); + CilInstruction nop_ld_sender = new(Nop); + CilInstruction nop_ld_args = new(Nop); + CilInstruction nop_finally_sender = new(Nop); + CilInstruction nop_finally_args = new(Nop); + CilInstruction ldloca_0_finally_0 = new(Ldloca_S, loc_0_thisValue); CilInstruction ret = new(Ret); - // Load the local [0] - _ = invokeInstructions.Add(Ldarg_0); - _ = invokeInstructions.Add(Callvirt, interopReferences.WindowsRuntimeObjectReferenceAsValue.Import(module)); - _ = invokeInstructions.Add(Stloc_0); - - // '.try' for local [0] - CilInstruction try_0 = invokeInstructions.Add(Ldarg_1); - _ = invokeInstructions.Add(Call, interopReferences.WindowsRuntimeObjectMarshallerConvertToUnmanaged.Import(module)); - _ = invokeInstructions.Add(Stloc_1); - - // '.try' for local [1] - CilInstruction try_1 = invokeInstructions.Add(Ldarg_2); - _ = invokeInstructions.Add(Call, interopReferences.WindowsRuntimeObjectMarshallerConvertToUnmanaged.Import(module)); - _ = invokeInstructions.Add(Stloc_2); - - // 'Invoke' call for the native delegate (and 'try' for local [2]) - CilInstruction try_2 = invokeInstructions.Add(Ldloca_S, invokeBody.LocalVariables[0]); - _ = invokeInstructions.Add(Call, interopReferences.WindowsRuntimeObjectReferenceValueGetThisPtrUnsafe.Import(module)); - _ = invokeInstructions.Add(Stloc_3); - _ = invokeInstructions.Add(Ldloc_3); - _ = invokeInstructions.Add(Ldloca_S, invokeBody.LocalVariables[1]); - _ = invokeInstructions.Add(Call, interopReferences.WindowsRuntimeObjectReferenceValueGetThisPtrUnsafe.Import(module)); - _ = invokeInstructions.Add(Ldloca_S, invokeBody.LocalVariables[2]); - _ = invokeInstructions.Add(Call, interopReferences.WindowsRuntimeObjectReferenceValueGetThisPtrUnsafe.Import(module)); - _ = invokeInstructions.Add(Ldloc_3); - _ = invokeInstructions.Add(Ldind_I); - _ = invokeInstructions.Add(Ldfld, interopDefinitions.DelegateVftbl.Fields[3]); - _ = invokeInstructions.Add(Calli, WellKnownTypeSignatureFactory.InvokeImpl(interopReferences).Import(module).MakeStandAloneSignature()); - _ = invokeInstructions.Add(Call, interopReferences.RestrictedErrorInfoThrowExceptionForHR.Import(module)); - _ = invokeInstructions.Add(Leave_S, ret.CreateLabel()); - - // 'finally' for local [2] - CilInstruction finally_2 = invokeInstructions.Add(Ldloca_S, invokeBody.LocalVariables[2]); - _ = invokeInstructions.Add(Call, interopReferences.WindowsRuntimeObjectReferenceValueDispose.Import(module)); - _ = invokeInstructions.Add(Endfinally); - - // 'finally' for local [1] - CilInstruction finally_1 = invokeInstructions.Add(Ldloca_S, invokeBody.LocalVariables[1]); - _ = invokeInstructions.Add(Call, interopReferences.WindowsRuntimeObjectReferenceValueDispose.Import(module)); - _ = invokeInstructions.Add(Endfinally); - - // 'finally' for local [0] - CilInstruction finally_0 = invokeInstructions.Add(Ldloca_S, invokeBody.LocalVariables[0]); - _ = invokeInstructions.Add(Call, interopReferences.WindowsRuntimeObjectReferenceValueDispose.Import(module)); - _ = invokeInstructions.Add(Endfinally); - - invokeInstructions.Add(ret); - - // Setup 'try/finally' for local [0] - invokeBody.ExceptionHandlers.Add(new CilExceptionHandler - { - HandlerType = CilExceptionHandlerType.Finally, - TryStart = try_0.CreateLabel(), - TryEnd = finally_0.CreateLabel(), - HandlerStart = finally_0.CreateLabel(), - HandlerEnd = ret.CreateLabel() - }); - - // Setup 'try/finally' for local [1] - invokeBody.ExceptionHandlers.Add(new CilExceptionHandler - { - HandlerType = CilExceptionHandlerType.Finally, - TryStart = try_1.CreateLabel(), - TryEnd = finally_1.CreateLabel(), - HandlerStart = finally_1.CreateLabel(), - HandlerEnd = finally_0.CreateLabel() - }); - - // Setup 'try/finally' for local [2] - invokeBody.ExceptionHandlers.Add(new CilExceptionHandler + // Create a method body for the 'Invoke' method + invokeMethod.CilMethodBody = new CilMethodBody() { - HandlerType = CilExceptionHandlerType.Finally, - TryStart = try_2.CreateLabel(), - TryEnd = finally_2.CreateLabel(), - HandlerStart = finally_2.CreateLabel(), - HandlerEnd = finally_1.CreateLabel() - }); + LocalVariables = { loc_0_thisValue, loc_1_thisPtr }, + Instructions = + { + // Load the local [0] + { Ldarg_0 }, + { Callvirt, interopReferences.WindowsRuntimeObjectReferenceAsValue.Import(module) }, + { Stloc_0 }, + { nop_try_this }, + + // Arguments loading inside outer 'try/catch' block + { nop_try_sender }, + { nop_try_args }, + + // 'Invoke' call for the native delegate (and 'try' for local [2]) + { Ldloca_S, loc_0_thisValue }, + { Call, interopReferences.WindowsRuntimeObjectReferenceValueGetThisPtrUnsafe.Import(module) }, + { Stloc_1 }, + { Ldloc_1 }, + { nop_ld_sender }, + { nop_ld_args }, + { Ldloc_1 }, + { Ldind_I }, + { Ldfld, interopDefinitions.DelegateVftbl.Fields[3] }, + { Calli, invokeSignature.Import(module).MakeStandAloneSignature() }, + { Call, interopReferences.RestrictedErrorInfoThrowExceptionForHR.Import(module) }, + { Leave_S, ret.CreateLabel() }, + + // Optional 'finally' blocks for the marshalled parameters. These are intentionally + // in reverse order, as the inner-most parameter should be released first. + { nop_finally_args }, + { nop_finally_sender }, + + // 'finally' for local [0] + { ldloca_0_finally_0 }, + { Call, interopReferences.WindowsRuntimeObjectReferenceValueDispose.Import(module) }, + { Endfinally }, + + // return; + { ret } + }, + ExceptionHandlers = + { + // Setup 'try/finally' for local [0] + new CilExceptionHandler + { + HandlerType = CilExceptionHandlerType.Finally, + TryStart = nop_try_this.CreateLabel(), + TryEnd = ldloca_0_finally_0.CreateLabel(), + HandlerStart = ldloca_0_finally_0.CreateLabel(), + HandlerEnd = ret.CreateLabel() + } + } + }; + + // Track rewriting the two parameters for this method + emitState.TrackNativeParameterMethodRewrite( + paraneterType: senderType, + method: invokeMethod, + tryMarker: nop_try_sender, + loadMarker: nop_ld_sender, + finallyMarker: nop_finally_sender, + parameterIndex: 1); + + emitState.TrackNativeParameterMethodRewrite( + paraneterType: argsType, + method: invokeMethod, + tryMarker: nop_try_args, + loadMarker: nop_ld_args, + finallyMarker: nop_finally_args, + parameterIndex: 2); } /// diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IDictionary2.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IDictionary2.cs index 36b170243..b62708d51 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IDictionary2.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IDictionary2.cs @@ -89,8 +89,8 @@ public static void Vftbl( TypeSignature keyType = dictionaryType.TypeArguments[0]; TypeSignature valueType = dictionaryType.TypeArguments[1]; - bool isKeyReferenceType = !keyType.IsValueType || keyType.IsConstructedKeyValuePairType(interopReferences); - bool isValueReferenceType = !valueType.IsValueType || valueType.IsConstructedKeyValuePairType(interopReferences); + bool isKeyReferenceType = keyType.HasReferenceAbiType(interopReferences); + bool isValueReferenceType = valueType.HasReferenceAbiType(interopReferences); // We can share the vtable type for 'void*' when both key and value types are reference types if (isKeyReferenceType && isValueReferenceType) @@ -135,14 +135,14 @@ static void GetOrCreateVftbl( } // Create a dummy signature just to generate the mangled name for the vtable type - TypeSignature sharedReadOnlyDictionaryType = interopReferences.IDictionary2.MakeGenericReferenceType( + TypeSignature sharedDictionaryType = interopReferences.IDictionary2.MakeGenericReferenceType( displayKeyType, displayValueType); // Construct a new specialized vtable type TypeDefinition newVftblType = WellKnownTypeDefinitionFactory.IDictionary2Vftbl( - ns: InteropUtf8NameFactory.TypeNamespace(sharedReadOnlyDictionaryType), - name: InteropUtf8NameFactory.TypeName(sharedReadOnlyDictionaryType, "Vftbl"), + ns: InteropUtf8NameFactory.TypeNamespace(sharedDictionaryType), + name: InteropUtf8NameFactory.TypeName(sharedDictionaryType, "Vftbl"), keyType: keyType, valueType: valueType, interopReferences: interopReferences, diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IList1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IList1.cs index f4a5e8999..70df2b95b 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IList1.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IList1.cs @@ -86,9 +86,8 @@ public static void Vftbl( { TypeSignature elementType = listType.TypeArguments[0]; - // All reference types can share the same vtable type (as it just uses 'void*' for the ABI type). - // We can also share vtables for 'KeyValuePair<,>' types, as their ABI type is an interface. - if (!elementType.IsValueType || elementType.IsConstructedKeyValuePairType(interopReferences)) + // For types which use 'void*' as their ABI types, we can share the same vtable type definition + if (elementType.HasReferenceAbiType(interopReferences)) { vftblType = interopDefinitions.IList1Vftbl; diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyDictionary2.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyDictionary2.cs index 179251ee8..5a212b348 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyDictionary2.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyDictionary2.cs @@ -43,7 +43,7 @@ public static void Vftbl( // All reference types can share the same vtable type (as it just uses 'void*' for the ABI type). // The 'IMapView' interface doesn't use 'V' as a by-value parameter anywhere in the vtable, // so we can aggressively share vtable types for all cases where 'K' is a reference type. - if (!keyType.IsValueType || keyType.IsConstructedKeyValuePairType(interopReferences)) + if (keyType.HasReferenceAbiType(interopReferences)) { vftblType = interopDefinitions.IReadOnlyDictionary2Vftbl; diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs index 7e78946a9..af61f50d6 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs @@ -39,7 +39,7 @@ public static void Vftbl( TypeSignature elementType = readOnlyListType.TypeArguments[0]; // Same logic as with 'IList1.Vftbl' (i.e. share for all reference types) - if (!elementType.IsValueType || elementType.IsConstructedKeyValuePairType(interopReferences)) + if (elementType.HasReferenceAbiType(interopReferences)) { vftblType = interopDefinitions.IReadOnlyList1Vftbl; diff --git a/src/WinRT.Interop.Generator/Extensions/CilInstructionCollectionExtensions.cs b/src/WinRT.Interop.Generator/Extensions/CilInstructionCollectionExtensions.cs index d0e67048f..100916eae 100644 --- a/src/WinRT.Interop.Generator/Extensions/CilInstructionCollectionExtensions.cs +++ b/src/WinRT.Interop.Generator/Extensions/CilInstructionCollectionExtensions.cs @@ -16,32 +16,34 @@ internal static class CilInstructionCollectionExtensions extension(CilInstructionCollection instructions) { /// - /// Replaces a target instruction with a collection of new instructions. + /// Removes a set of CIL instructions from the collection. /// - /// The instruction to replace. - /// The new instructions to emit. - public void ReplaceRange(CilInstruction target, params IEnumerable values) + /// The instructions to remove. + public void ReferenceRemoveRange(params IEnumerable items) { - int index; - - // Find the index of the target instruction in the collection. - // We can't use 'IndexOf', as we only want to match by reference. - for (index = 0; index < instructions.Count; index++) + foreach (CilInstruction item in items) { - if (instructions[index] == target) - { - break; - } + _ = instructions.ReferenceRemove(item); } + } + + /// + /// Replaces a target instruction with a collection of new instructions. + /// + /// The instruction to replace. + /// The new instructions to emit. + public void ReferenceReplaceRange(CilInstruction target, params IEnumerable items) + { + int index = instructions.ReferenceIndexOf(target); // Ensure we did find the target instruction - if (index >= instructions.Count) + if (index == -1) { throw new ArgumentException("The target instruction was not found in the collection.", nameof(target)); } instructions.RemoveAt(index); - instructions.InsertRange(index, values); + instructions.InsertRange(index, items); } } } \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/Extensions/IListExtensions.cs b/src/WinRT.Interop.Generator/Extensions/IListExtensions.cs new file mode 100644 index 000000000..bcb1cf9d2 --- /dev/null +++ b/src/WinRT.Interop.Generator/Extensions/IListExtensions.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; + +namespace WindowsRuntime.InteropGenerator; + +/// +/// Extensions for the type. +/// +internal static class IListExtensions +{ + extension(IList list) + where T : class + { + /// + /// + /// This method only ever compares values by reference equality. + /// + public bool ReferenceContains(T value) + { + return list.Count != 0 && list.ReferenceIndexOf(value) >= 0; + } + + /// + /// + /// This method only ever compares values by reference equality. + /// + public bool ReferenceRemove(T value) + { + int index = list.ReferenceIndexOf(value); + + if (index >= 0) + { + list.RemoveAt(index); + + return true; + } + + return false; + } + + /// + /// + /// This method only ever compares values by reference equality. + /// + public int ReferenceIndexOf(T value) + { + for (int i = 0; i < list.Count; i++) + { + if (ReferenceEquals(list[i], value)) + { + return i; + } + } + + return -1; + } + } +} \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs b/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs index 791bc3859..1ade639d2 100644 --- a/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs +++ b/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs @@ -92,6 +92,15 @@ public bool IsTypeOfObject() return type is CorLibTypeSignature { ElementType: ElementType.Object }; } + /// + /// Checks whether an is a pointer type. + /// + /// Whether the type is a pointer type. + public bool IsTypeOfVoidPointer() + { + return type is PointerTypeSignature { BaseType: CorLibTypeSignature { ElementType: ElementType.Void } }; + } + /// /// Checks whether an represents a fundamental Windows Runtime type. /// @@ -477,11 +486,46 @@ public bool IsTrackerSupportRequired(InteropReferences interopReferences) return false; } + /// + /// Gets whether a given type has an ABI type that is a reference type. + /// + /// The instance to use. + /// Whether the input type has an ABI type that is a reference type. + public bool HasReferenceAbiType(InteropReferences interopReferences) + { + // All constructed generics will use 'void*' for the ABI type + if (type is GenericInstanceTypeSignature) + { + return true; + } + + // All other value types will never have a reference type as the ABI type + if (type.IsValueType) + { + return false; + } + + // 'Type' is a class, but is custom-mapped to the 'TypeName' struct type + if (SignatureComparer.IgnoreVersion.Equals(type, interopReferences.Type)) + { + return false; + } + + // 'Exception' is also a class, but is custom-mapped to the 'HResult' struct type + if (SignatureComparer.IgnoreVersion.Equals(type, interopReferences.Exception)) + { + return false; + } + + // For all other cases (e.g. interfaces, classes, delegates, etc.), the ABI type is always a pointer + return true; + } + /// /// Gets the ABI type for a given type. /// /// The instance to use. - /// The ABi type for the input type. + /// The ABI type for the input type. public TypeSignature GetAbiType(InteropReferences interopReferences) { // All constructed generics will use 'void*' for the ABI type. This applies to both reference diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ManagedParameter.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ManagedParameter.cs index bae3eec7e..e4e1003d0 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ManagedParameter.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ManagedParameter.cs @@ -47,13 +47,12 @@ public static void RewriteMethod( } // If we didn't find the marker, it means the target method is either invalid - if (!body.Instructions.Contains(marker)) + if (!body.Instructions.ReferenceContains(marker)) { throw WellKnownInteropExceptions.MethodRewriteMarkerInstructionNotFoundError(marker, method); } - // If we didn't find the marker, it means the target method is either invalid, or the - // supplied marker was incorrect (or the caller forgot to add it to the method body). + // Validate that the target parameter index is in range if ((uint)parameterIndex >= method.Parameters.Count) { throw WellKnownInteropExceptions.MethodRewriteParameterIndexNotValidError(parameterIndex, method); @@ -72,12 +71,12 @@ public static void RewriteMethod( // If the return type is blittable, we can just load it directly it directly (simplest case) if (parameterType.IsBlittable(interopReferences)) { - body.Instructions.ReplaceRange(marker, CilInstruction.CreateLdarg(parameterIndex)); + body.Instructions.ReferenceReplaceRange(marker, CilInstruction.CreateLdarg(parameterIndex)); } else if (parameterType.IsConstructedKeyValuePairType(interopReferences)) { // If the type is some constructed 'KeyValuePair<,>' type, we use the generated marshaller - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ CilInstruction.CreateLdarg(parameterIndex), new CilInstruction(Call, emitState.LookupTypeDefinition(parameterType, "Marshaller").GetMethod("ConvertToManaged"))]); } @@ -96,7 +95,7 @@ public static void RewriteMethod( parameterTypes: [module.CorLibTypeFactory.Void.MakePointerType()])); // Emit code similar to 'KeyValuePair<,>' above, to marshal the resulting 'Nullable' value - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ CilInstruction.CreateLdarg(parameterIndex), new CilInstruction(Call, marshallerMethod.Import(module))]); } @@ -114,7 +113,7 @@ public static void RewriteMethod( parameterTypes: [parameterType.GetAbiType(interopReferences)])); // We can directly call the marshaller and return it, no 'try/finally' complexity is needed - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ CilInstruction.CreateLdarg(parameterIndex), new CilInstruction(Call, marshallerMethod.Import(module))]); } @@ -122,14 +121,14 @@ public static void RewriteMethod( else if (parameterType.IsTypeOfString()) { // When marshalling 'string' values, we must use 'HStringMarshaller' (the ABI type is not actually a COM object) - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ CilInstruction.CreateLdarg(parameterIndex), new CilInstruction(Call, interopReferences.HStringMarshallerConvertToManaged.Import(module))]); } else if (parameterType is GenericInstanceTypeSignature) { // This case (constructed interfaces or delegates) is effectively identical to marshalling 'KeyValuePair<,>' values - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ CilInstruction.CreateLdarg(parameterIndex), new CilInstruction(Call, emitState.LookupTypeDefinition(parameterType, "Marshaller").GetMethod("ConvertToManaged"))]); } @@ -146,7 +145,7 @@ public static void RewriteMethod( parameterTypes: [module.CorLibTypeFactory.Void.MakePointerType()])); // Marshal the value and release the original interface pointer - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ CilInstruction.CreateLdarg(parameterIndex), new CilInstruction(Call, marshallerMethod.Import(module))]); } diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.NativeParameter.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.NativeParameter.cs new file mode 100644 index 000000000..71acbfd64 --- /dev/null +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.NativeParameter.cs @@ -0,0 +1,414 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using AsmResolver.DotNet; +using AsmResolver.DotNet.Code.Cil; +using AsmResolver.DotNet.Collections; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Cil; +using WindowsRuntime.InteropGenerator.Errors; +using WindowsRuntime.InteropGenerator.Generation; +using WindowsRuntime.InteropGenerator.References; +using static AsmResolver.PE.DotNet.Cil.CilOpCodes; + +#pragma warning disable CS1573 + +namespace WindowsRuntime.InteropGenerator.Factories; + +/// +internal partial class InteropMethodRewriteFactory +{ + /// + /// Contains the logic for marshalling native parameters (i.e. parameters that are passed to native methods). + /// + public static class NativeParameter + { + /// + /// Performs two-pass code generation on a target method to marshal a managed parameter. + /// + /// The parameter type that needs to be marshalled. + /// The target method to perform two-pass code generation on. + /// The target IL instruction to replace with the right set of specialized instructions, for the optional block. + /// The target IL instruction to replace with the right set of specialized instructions to load the marshalled value. + /// The target IL instruction to replace with the right set of specialized instructions, for the optional block. + /// The index of the parameter to marshal. + /// The instance to use. + /// The emit state for this invocation. + /// The interop module being built. + public static void RewriteMethod( + TypeSignature parameterType, + MethodDefinition method, + CilInstruction tryMarker, + CilInstruction loadMarker, + CilInstruction finallyMarker, + int parameterIndex, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module) + { + // Validate that we do have some IL body for the input method (this should always be the case) + if (method.CilMethodBody is not CilMethodBody body) + { + throw WellKnownInteropExceptions.MethodRewriteMissingBodyError(method); + } + + // If we didn't find any of markers, it means the target method is either invalid + foreach (CilInstruction marker in (ReadOnlySpan)[tryMarker, loadMarker, finallyMarker]) + { + if (!body.Instructions.ReferenceContains(marker)) + { + throw WellKnownInteropExceptions.MethodRewriteMarkerInstructionNotFoundError(marker, method); + } + } + + // Validate that the target parameter index is in range + if ((uint)parameterIndex >= method.Parameters.Count) + { + throw WellKnownInteropExceptions.MethodRewriteParameterIndexNotValidError(parameterIndex, method); + } + + Parameter source = method.Parameters[parameterIndex]; + + // Validate that the type matches + if (!SignatureComparer.IgnoreVersion.Equals(source.ParameterType, parameterType)) + { + throw WellKnownInteropExceptions.MethodRewriteSourceParameterTypeMismatchError(source.ParameterType, parameterType, method); + } + + if (parameterType.IsValueType) + { + // If the return type is blittable, we can just load it directly it directly (simplest case) + if (parameterType.IsBlittable(interopReferences)) + { + body.Instructions.ReferenceRemoveRange(tryMarker, finallyMarker); + body.Instructions.ReferenceReplaceRange(loadMarker, CilInstruction.CreateLdarg(parameterIndex)); + } + else if (parameterType.IsConstructedKeyValuePairType(interopReferences)) + { + RewriteBody( + parameterType: parameterType, + body: body, + tryMarker: tryMarker, + loadMarker: loadMarker, + finallyMarker: finallyMarker, + parameterIndex: parameterIndex, + marshallerMethod: emitState.LookupTypeDefinition(parameterType, "Marshaller").GetMethod("ConvertToUnmanaged"), + disposeMethod: null, + interopReferences: interopReferences, + module: module); + } + else if (parameterType.IsConstructedNullableValueType(interopReferences)) + { + TypeSignature underlyingType = ((GenericInstanceTypeSignature)parameterType).TypeArguments[0]; + + // For 'Nullable' return types, we need the marshaller for the instantiated 'T' type (same as for return values) + ITypeDefOrRef marshallerType = GetValueTypeMarshallerType(underlyingType, interopReferences, emitState); + + // Get the right reference to the unboxing marshalling method to call + IMethodDefOrRef marshallerMethod = marshallerType.GetMethodDefOrRef( + name: "BoxToUnmanaged"u8, + signature: MethodSignature.CreateStatic( + returnType: interopReferences.WindowsRuntimeObjectReferenceValue.ToValueTypeSignature(), + parameterTypes: [parameterType])); + + RewriteBody( + parameterType: parameterType, + body: body, + tryMarker: tryMarker, + loadMarker: loadMarker, + finallyMarker: finallyMarker, + parameterIndex: parameterIndex, + marshallerMethod: marshallerMethod, + disposeMethod: null, + interopReferences: interopReferences, + module: module); + } + else + { + // The last case handles all other value types, which need explicit disposal for their ABI values + ITypeDefOrRef marshallerType = GetValueTypeMarshallerType(parameterType, interopReferences, emitState); + + // Get the reference to 'ConvertToUnmanaged' to produce the resulting value to pass as argument + IMethodDefOrRef marshallerMethod = marshallerType.GetMethodDefOrRef( + name: "ConvertToUnmanaged"u8, + signature: MethodSignature.CreateStatic( + returnType: parameterType.GetAbiType(interopReferences), + parameterTypes: [parameterType])); + + // Get the reference to 'Dispose' method to call on the ABI value + IMethodDefOrRef disposeMethod = marshallerType.GetMethodDefOrRef( + name: "Dispose"u8, + signature: MethodSignature.CreateStatic( + returnType: interopReferences.CorLibTypeFactory.Void, + parameterTypes: [parameterType.GetAbiType(interopReferences)])); + + RewriteBody( + parameterType: parameterType, + body: body, + tryMarker: tryMarker, + loadMarker: loadMarker, + finallyMarker: finallyMarker, + parameterIndex: parameterIndex, + marshallerMethod: marshallerMethod, + disposeMethod: disposeMethod, + interopReferences: interopReferences, + module: module); + } + } + else if (parameterType.IsTypeOfString()) + { + RewriteBodyForTypeOfString( + body: body, + tryMarker: tryMarker, + loadMarker: loadMarker, + finallyMarker: finallyMarker, + parameterIndex: parameterIndex, + interopReferences: interopReferences, + module: module); + } + else if (parameterType.IsTypeOfType(interopReferences)) + { + RewriteBodyForTypeOfType( + body: body, + tryMarker: tryMarker, + loadMarker: loadMarker, + finallyMarker: finallyMarker, + parameterIndex: parameterIndex, + interopReferences: interopReferences, + module: module); + } + else if (parameterType.IsTypeOfException(interopReferences)) + { + // The ABI type of 'Exception' is unmanaged, so we can marshal the value directly + body.Instructions.ReferenceRemoveRange(tryMarker, finallyMarker); + body.Instructions.ReferenceReplaceRange(loadMarker, [ + CilInstruction.CreateLdarg(parameterIndex), + new CilInstruction(Call, interopReferences.ExceptionMarshallerConvertToUnmanaged.Import(module))]); + } + else + { + // Get the marshaller for all other types (doesn't matter if constructed generics or not) + ITypeDefOrRef marshallerType = GetReferenceTypeMarshallerType(parameterType, interopReferences, emitState); + + // Get the reference to 'ConvertToUnmanaged' to produce the resulting value to pass as argument + IMethodDefOrRef marshallerMethod = marshallerType.GetMethodDefOrRef( + name: "ConvertToUnmanaged"u8, + signature: MethodSignature.CreateStatic( + returnType: interopReferences.WindowsRuntimeObjectReferenceValue.ToValueTypeSignature(), + parameterTypes: [parameterType])); + + RewriteBody( + parameterType: parameterType, + body: body, + tryMarker: tryMarker, + loadMarker: loadMarker, + finallyMarker: finallyMarker, + parameterIndex: parameterIndex, + marshallerMethod: marshallerMethod, + disposeMethod: null, + interopReferences: interopReferences, + module: module); + } + } + + /// + /// The target body to perform two-pass code generation on. + /// The method to invoke to marshal the managed value. + /// The method to invoke to dispose the original ABI value, if a value type. + private static void RewriteBody( + TypeSignature parameterType, + CilMethodBody body, + CilInstruction tryMarker, + CilInstruction loadMarker, + CilInstruction finallyMarker, + int parameterIndex, + IMethodDefOrRef marshallerMethod, + IMethodDefOrRef? disposeMethod, + InteropReferences interopReferences, + ModuleDefinition module) + { + TypeSignature parameterAbiType = parameterType.GetAbiType(interopReferences); + + // Prepare the new local for the ABI value (or 'WindowsRuntimeObjectReferenceValue'). + // This is only for parameter types that need some kind of disposal after the call. + CilLocalVariable loc_parameter = parameterAbiType.IsTypeOfVoidPointer() + ? new CilLocalVariable(interopReferences.WindowsRuntimeObjectReferenceValue.Import(module).ToValueTypeSignature()) + : new CilLocalVariable(parameterAbiType.Import(module)); + + body.LocalVariables.Add(loc_parameter); + + // Prepare the jump labels + CilInstruction nop_tryStart = new(Nop); + CilInstruction ldloc_or_a_finallyStart; + CilInstruction nop_finallyEnd = new(Nop); + + // Marshal the value before the call + body.Instructions.ReferenceReplaceRange(tryMarker, [ + CilInstruction.CreateLdarg(parameterIndex), + new CilInstruction(Call, marshallerMethod.Import(module)), + CilInstruction.CreateStloc(loc_parameter, body), + nop_tryStart]); + + // Get the ABI value to pass to the native method. If we have a 'WindowsRuntimeObjectReferenceValue', + // we'll get the pointer from it. Otherwise, we just load the ABI value and pass it directly to native. + if (parameterAbiType.IsTypeOfVoidPointer()) + { + body.Instructions.ReferenceReplaceRange(loadMarker, [ + new CilInstruction(Ldloca_S, loc_parameter), + new CilInstruction(Call, interopReferences.WindowsRuntimeObjectReferenceValueGetThisPtrUnsafe.Import(module))]); + } + else + { + body.Instructions.ReferenceReplaceRange(loadMarker, CilInstruction.CreateLdloc(loc_parameter, body)); + } + + // Release the ABI value, or the 'WindowsRuntimeObjectReferenceValue' value, after the call. + // Once again we need specialized logic for when we're using 'WindowsRuntimeObjectReferenceValue'. + // That is, for that object we'll need to call the instance 'Dispose' on it directly. For all + // other cases, we'll instead load the local and pass it to the 'Dispose' method on the marshaller. + if (parameterAbiType.IsTypeOfVoidPointer()) + { + ldloc_or_a_finallyStart = new CilInstruction(Ldloca_S, loc_parameter); + + body.Instructions.ReferenceReplaceRange(finallyMarker, [ + ldloc_or_a_finallyStart, + new CilInstruction(Call, interopReferences.WindowsRuntimeObjectReferenceValueDispose.Import(module)), + new CilInstruction(Endfinally), + nop_finallyEnd]); + } + else + { + ldloc_or_a_finallyStart = CilInstruction.CreateLdloc(loc_parameter, body); + + body.Instructions.ReferenceReplaceRange(finallyMarker, [ + ldloc_or_a_finallyStart, + new CilInstruction(Call, disposeMethod!.Import(module)), + new CilInstruction(Endfinally), + nop_finallyEnd]); + } + + // Setup the protected region to call the 'Dispose' method in a 'finally' block + body.ExceptionHandlers.Add(new CilExceptionHandler + { + HandlerType = CilExceptionHandlerType.Finally, + TryStart = nop_tryStart.CreateLabel(), + TryEnd = ldloc_or_a_finallyStart.CreateLabel(), + HandlerStart = ldloc_or_a_finallyStart.CreateLabel(), + HandlerEnd = nop_finallyEnd.CreateLabel() + }); + } + + /// + /// The target body to perform two-pass code generation on. + private static void RewriteBodyForTypeOfString( + CilMethodBody body, + CilInstruction tryMarker, + CilInstruction loadMarker, + CilInstruction finallyMarker, + int parameterIndex, + InteropReferences interopReferences, + ModuleDefinition module) + { + // Declare the local variables: + // [0]: 'ref char' (for the pinned 'string') + // [1]: 'HStringReference' (for 'hstringReference') + // [2]: 'int?' (for 'length') + CilLocalVariable loc_0_pinnedString = new(interopReferences.CorLibTypeFactory.Char.MakeByReferenceType().MakePinnedType()); + CilLocalVariable loc_1_hstringReference = new(interopReferences.HStringReference.Import(module).ToValueTypeSignature()); + CilLocalVariable loc_2_length = new(interopReferences.Nullable1.MakeGenericValueType(interopReferences.CorLibTypeFactory.Int32).Import(module)); + + body.LocalVariables.Add(loc_0_pinnedString); + body.LocalVariables.Add(loc_1_hstringReference); + body.LocalVariables.Add(loc_2_length); + + // Prepare the jump labels + CilInstruction ldarg_pinning = CilInstruction.CreateLdarg(parameterIndex); + CilInstruction ldarg_lengthNullCheck = CilInstruction.CreateLdarg(parameterIndex); + CilInstruction ldarg_getLength = CilInstruction.CreateLdarg(parameterIndex); + CilInstruction ldloca_s_getHStringReference = new(Ldloca_S, loc_1_hstringReference); + + // Pin the input 'string' value, get the (possibly 'null') length, and create the 'HStringReference' value + body.Instructions.ReferenceReplaceRange(tryMarker, [ + + // fixed (char* p = value) { } + CilInstruction.CreateLdarg(parameterIndex), + new CilInstruction(Brtrue_S, ldarg_pinning.CreateLabel()), + new CilInstruction(Ldc_I4_0), + new CilInstruction(Conv_U), + new CilInstruction(Br_S, ldarg_lengthNullCheck.CreateLabel()), + ldarg_pinning, + new CilInstruction(Call, interopReferences.StringGetPinnableReference.Import(module)), + CilInstruction.CreateStloc(loc_0_pinnedString, body), + CilInstruction.CreateLdloc(loc_0_pinnedString, body), + new CilInstruction(Conv_U), + + // int? length = value?.Length; + ldarg_lengthNullCheck, + new CilInstruction(Brtrue_S, ldarg_getLength.CreateLabel()), + new CilInstruction(Ldloca_S, loc_2_length), + new CilInstruction(Initobj, interopReferences.NullableInt32.Import(module).ToTypeDefOrRef()), + CilInstruction.CreateLdloc(loc_2_length, body), + new CilInstruction(Br_S, ldloca_s_getHStringReference.CreateLabel()), + ldarg_getLength, + new CilInstruction(Call, interopReferences.Stringget_Length.Import(module)), + new CilInstruction(Newobj, interopReferences.Nullable1_ctor(interopReferences.CorLibTypeFactory.Int32).Import(module)), + + // HStringMarshaller.ConvertToUnmanagedUnsafe(p, length, out HStringReference hstringReference); + ldloca_s_getHStringReference, + new CilInstruction(Call, interopReferences.HStringMarshallerConvertToUnmanagedUnsafe.Import(module))]); + + // Get the 'HString' value from the reference and pass it as a parameter + body.Instructions.ReferenceReplaceRange(loadMarker, [ + new CilInstruction(Ldloca_S, loc_1_hstringReference), + new CilInstruction(Call, interopReferences.HStringReferenceget_HString.Import(module))]); + + // Unpin the local (just assign 'null' to it) + body.Instructions.ReferenceReplaceRange(finallyMarker, [ + new CilInstruction(Ldc_I4_0), + new CilInstruction(Conv_U), + CilInstruction.CreateStloc(loc_0_pinnedString, body)]); + } + + /// + /// The target body to perform two-pass code generation on. + private static void RewriteBodyForTypeOfType( + CilMethodBody body, + CilInstruction tryMarker, + CilInstruction loadMarker, + CilInstruction finallyMarker, + int parameterIndex, + InteropReferences interopReferences, + ModuleDefinition module) + { + // Declare the local variables: + // [0]: 'TypeReference' (for 'typeReference') + // [1]: 'ref byte' (for the pinned type reference) + CilLocalVariable loc_0_typeReference = new(interopReferences.TypeReference.Import(module).ToValueTypeSignature()); + CilLocalVariable loc_1_pinnedTypeReference = new(interopReferences.CorLibTypeFactory.Byte.MakeByReferenceType().MakePinnedType()); + + body.LocalVariables.Add(loc_0_typeReference); + body.LocalVariables.Add(loc_1_pinnedTypeReference); + + // Get the 'TypeReference' value and pin it + body.Instructions.ReferenceReplaceRange(tryMarker, [ + CilInstruction.CreateLdarg(parameterIndex), + new CilInstruction(Ldloca_S, loc_0_typeReference), + new CilInstruction(Call, interopReferences.TypeMarshallerConvertToUnmanagedUnsafe.Import(module)), + new CilInstruction(Ldloca_S, loc_0_typeReference), + new CilInstruction(Call, interopReferences.TypeReferenceGetPinnableReference.Import(module)), + CilInstruction.CreateStloc(loc_1_pinnedTypeReference, body)]); + + // Get the ABI 'Type' value and pass it as a parameter + body.Instructions.ReferenceReplaceRange(loadMarker, [ + new CilInstruction(Ldloca_S, loc_0_typeReference), + new CilInstruction(Call, interopReferences.TypeReferenceConvertToUnmanagedUnsafe.Import(module))]); + + // Unpin the local (just assign 'null' to it) + body.Instructions.ReferenceReplaceRange(finallyMarker, [ + new CilInstruction(Ldc_I4_0), + new CilInstruction(Conv_U), + CilInstruction.CreateStloc(loc_1_pinnedTypeReference, body)]); + } + } +} \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.RetVal.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.RetVal.cs index a33b21bd9..6188ebdc9 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.RetVal.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.RetVal.cs @@ -60,7 +60,7 @@ public static void RewriteMethod( // If we didn't find the marker, it means the target method is either invalid, or the // supplied marker was incorrect (or the caller forgot to add it to the method body). - if (!body.Instructions.Contains(marker)) + if (!body.Instructions.ReferenceContains(marker)) { throw WellKnownInteropExceptions.MethodRewriteMarkerInstructionNotFoundError(marker, method); } @@ -89,7 +89,7 @@ public static void RewriteMethod( _ => new CilInstruction(Stobj, retValType.Import(module).ToTypeDefOrRef()), }; - body.Instructions.ReplaceRange(marker, [storeInstruction]); + body.Instructions.ReferenceReplaceRange(marker, [storeInstruction]); } else if (retValType.IsConstructedKeyValuePairType(interopReferences)) { @@ -137,7 +137,7 @@ public static void RewriteMethod( parameterTypes: [retValType.GetAbiType(interopReferences)])); // Delegate to the marshaller to convert the managed value type on the evaluation stack - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ new CilInstruction(Call, marshallerMethod.Import(module)), new CilInstruction(Stobj, retValType.GetAbiType(interopReferences).Import(module).ToTypeDefOrRef())]); } @@ -145,21 +145,21 @@ public static void RewriteMethod( else if (retValType.IsTypeOfString()) { // When marshalling 'string' values, we must use 'HStringMarshaller' - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ new CilInstruction(Call, interopReferences.HStringMarshallerConvertToUnmanaged.Import(module)), new CilInstruction(Stind_I)]); } else if (retValType.IsTypeOfType(interopReferences)) { // 'Type' values also need their own specialized marshaller - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ new CilInstruction(Call, interopReferences.TypeMarshallerConvertToUnmanaged.Import(module)), new CilInstruction(Stobj, interopReferences.AbiType.Import(module).ToTypeDefOrRef())]); } else if (retValType.IsTypeOfException(interopReferences)) { // 'Exception' is also special, and needs its own specialized marshaller - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ new CilInstruction(Call, interopReferences.ExceptionMarshallerConvertToUnmanaged.Import(module)), new CilInstruction(Stobj, interopReferences.AbiException.Import(module).ToTypeDefOrRef())]); } @@ -213,7 +213,7 @@ private static void RewriteBody( body.LocalVariables.Add(loc_returnValue); // Marshal the value and detach its native pointer before assigning it to the target location - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ new CilInstruction(Call, marshallerMethod.Import(module)), CilInstruction.CreateStloc(loc_returnValue, body), new CilInstruction(Ldloca_S, loc_returnValue), diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ReturnValue.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ReturnValue.cs index 674e05df2..d0e1e6785 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ReturnValue.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ReturnValue.cs @@ -49,13 +49,13 @@ public static void RewriteMethod( // If we didn't find the marker, it means the target method is either invalid, or the // supplied marker was incorrect (or the caller forgot to add it to the method body). - if (!body.Instructions.Contains(marker)) + if (!body.Instructions.ReferenceContains(marker)) { throw WellKnownInteropExceptions.MethodRewriteMarkerInstructionNotFoundError(marker, method); } // Also validate that the target local variable is also actually part of the method - if (!body.LocalVariables.Contains(source)) + if (!body.LocalVariables.ReferenceContains(source)) { throw WellKnownInteropExceptions.MethodRewriteSourceLocalNotFoundError(source, method); } @@ -71,7 +71,7 @@ public static void RewriteMethod( // If the return type is blittable, we can always return it directly (simplest case) if (returnType.IsBlittable(interopReferences)) { - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ CilInstruction.CreateLdloc(source, body), new CilInstruction(Ret)]); } @@ -161,7 +161,7 @@ public static void RewriteMethod( parameterTypes: [returnType.GetAbiType(interopReferences)])); // We can directly call the marshaller and return it, no 'try/finally' complexity is needed - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ CilInstruction.CreateLdloc(source, body), new CilInstruction(Call, marshallerMethod.Import(module)), new CilInstruction(Ret)]); @@ -194,7 +194,7 @@ public static void RewriteMethod( else if (returnType.IsTypeOfException(interopReferences)) { // 'Exception' is also special, though it's simple: the ABI type is an unmanaged value type - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ CilInstruction.CreateLdloc(source, body), new CilInstruction(Call, interopReferences.ExceptionMarshallerConvertToManaged.Import(module)), new CilInstruction(Ret)]); @@ -263,7 +263,7 @@ private static void RewriteBody( CilInstruction ldloc_finallyEnd = CilInstruction.CreateLdloc(loc_returnValue, body); // Marshal the value and release the original interface pointer, or dispose the ABI value - body.Instructions.ReplaceRange(marker, [ + body.Instructions.ReferenceReplaceRange(marker, [ ldloc_tryStart, new CilInstruction(Call, marshallerMethod.Import(module)), CilInstruction.CreateStloc(loc_returnValue, body), diff --git a/src/WinRT.Interop.Generator/Factories/WellKnownTypeDefinitionFactory.cs b/src/WinRT.Interop.Generator/Factories/WellKnownTypeDefinitionFactory.cs index 0a007c5da..004602fed 100644 --- a/src/WinRT.Interop.Generator/Factories/WellKnownTypeDefinitionFactory.cs +++ b/src/WinRT.Interop.Generator/Factories/WellKnownTypeDefinitionFactory.cs @@ -96,13 +96,43 @@ public static TypeDefinition IInspectableVftbl(InteropReferences interopReferenc /// The instance to use. /// The module that will contain the type being created. /// The resulting instance. - /// This method always assumes the type will take two objects as input parameters. + /// + /// Unlike , + /// this overload just uses * as sender and args types, so it can be shared across reference types (for both types). + /// public static TypeDefinition DelegateVftbl(InteropReferences interopReferences, ModuleDefinition module) { - // We're declaring an 'internal struct' type - TypeDefinition vftblType = new( + return DelegateVftbl( ns: null, name: ""u8, + senderType: interopReferences.CorLibTypeFactory.Void.MakePointerType(), + argsType: interopReferences.CorLibTypeFactory.Void.MakePointerType(), + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a new type definition for the vtable of a type. + /// + /// The namespace for the type. + /// The type name. + /// The sender type for the vtable type. + /// The args type for the vtable type. + /// The instance to use. + /// The module that will contain the type being created. + /// The resulting instance. + public static TypeDefinition DelegateVftbl( + Utf8String? ns, + Utf8String name, + TypeSignature senderType, + TypeSignature argsType, + InteropReferences interopReferences, + ModuleDefinition module) + { + // We're declaring an 'internal struct' type + TypeDefinition vftblType = new( + ns: ns, + name: name, attributes: TypeAttributes.SequentialLayout | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, baseType: interopReferences.ValueType.Import(module)); @@ -112,14 +142,17 @@ public static TypeDefinition DelegateVftbl(InteropReferences interopReferences, MethodSignature releaseType = WellKnownTypeSignatureFactory.ReleaseImpl(interopReferences); // Also get the 'Invoke' signature - MethodSignature invokeType = WellKnownTypeSignatureFactory.InvokeImpl(interopReferences); + MethodSignature invokeType = WellKnownTypeSignatureFactory.InvokeImpl( + senderType: senderType, + argsType: argsType, + interopReferences: interopReferences); // The vtable layout for 'IDelegate' looks like this: // // public delegate* unmanaged[MemberFunction] QueryInterface; // public delegate* unmanaged[MemberFunction] AddRef; // public delegate* unmanaged[MemberFunction] Release; - // public delegate* unmanaged[MemberFunction] Invoke; + // public delegate* unmanaged[MemberFunction], , HRESULT> Invoke; vftblType.Fields.Add(new FieldDefinition("QueryInterface"u8, FieldAttributes.Public, queryInterfaceType.Import(module).MakeFunctionPointerType())); vftblType.Fields.Add(new FieldDefinition("AddRef"u8, FieldAttributes.Public, addRefType.Import(module).MakeFunctionPointerType())); vftblType.Fields.Add(new FieldDefinition("Release"u8, FieldAttributes.Public, releaseType.Import(module).MakeFunctionPointerType())); diff --git a/src/WinRT.Interop.Generator/Factories/WellKnownTypeSignatureFactory.cs b/src/WinRT.Interop.Generator/Factories/WellKnownTypeSignatureFactory.cs index 18b55f6cf..d3b3acf21 100644 --- a/src/WinRT.Interop.Generator/Factories/WellKnownTypeSignatureFactory.cs +++ b/src/WinRT.Interop.Generator/Factories/WellKnownTypeSignatureFactory.cs @@ -243,13 +243,18 @@ public static MethodSignature get_UntypedRetVal(InteropReferences interopReferen } /// - /// Creates a type signature for the Invoke vtable entry for a delegate, taking objects for both parameters. + /// Creates a type signature for the Invoke vtable entry for a delegate. /// + /// The sender type for the vtable type. + /// The args type for the vtable type. /// The instance to use. /// The resulting instance. - public static MethodSignature InvokeImpl(InteropReferences interopReferences) + public static MethodSignature InvokeImpl( + TypeSignature senderType, + TypeSignature argsType, + InteropReferences interopReferences) { - // Signature for 'delegate* unmanaged[MemberFunction]' + // Signature for 'delegate* unmanaged[MemberFunction], , HRESULT>' return new( attributes: CallingConventionAttributes.Unmanaged, returnType: new CustomModifierTypeSignature( @@ -258,8 +263,8 @@ public static MethodSignature InvokeImpl(InteropReferences interopReferences) baseType: interopReferences.CorLibTypeFactory.Int32), parameterTypes: [ interopReferences.CorLibTypeFactory.Void.MakePointerType(), - interopReferences.CorLibTypeFactory.Void.MakePointerType(), - interopReferences.CorLibTypeFactory.Void.MakePointerType()]); + senderType, + argsType]); } /// diff --git a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs index e99445de9..f7c17fd92 100644 --- a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs +++ b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs @@ -272,10 +272,19 @@ private static void DefineGenericDelegateTypes( get_IidMethod: out MethodDefinition get_IidMethod, get_ReferenceIidMethod: out MethodDefinition get_ReferenceIidMethod); + InteropTypeDefinitionBuilder.Delegate.Vftbl( + delegateType: typeSignature, + interopDefinitions: interopDefinitions, + interopReferences: interopReferences, + emitState: emitState, + module: module, + vftblType: out TypeDefinition vftblType); + InteropTypeDefinitionBuilder.Delegate.NativeDelegateType( delegateType: typeSignature, interopDefinitions: interopDefinitions, interopReferences: interopReferences, + emitState: emitState, module: module, nativeDelegateType: out TypeDefinition nativeDelegateType); @@ -299,6 +308,7 @@ private static void DefineGenericDelegateTypes( InteropTypeDefinitionBuilder.Delegate.ImplType( delegateType: typeSignature, + vftblType: vftblType, interopDefinitions: interopDefinitions, interopReferences: interopReferences, emitState: emitState, @@ -2039,6 +2049,20 @@ private static void RewriteMethodDefinitions( emitState: emitState, module: module); break; + + // Rewrite native parameters + case MethodRewriteInfo.NativeParameter nativeParameterInfo: + InteropMethodRewriteFactory.NativeParameter.RewriteMethod( + parameterType: nativeParameterInfo.Type, + method: nativeParameterInfo.Method, + tryMarker: nativeParameterInfo.TryMarker, + loadMarker: nativeParameterInfo.Marker, + finallyMarker: nativeParameterInfo.FinallyMarker, + parameterIndex: nativeParameterInfo.ParameterIndex, + interopReferences: interopReferences, + emitState: emitState, + module: module); + break; default: throw new UnreachableException(); } } diff --git a/src/WinRT.Interop.Generator/Generation/InteropGeneratorEmitState.cs b/src/WinRT.Interop.Generator/Generation/InteropGeneratorEmitState.cs index 52a4f2a8c..96e09161c 100644 --- a/src/WinRT.Interop.Generator/Generation/InteropGeneratorEmitState.cs +++ b/src/WinRT.Interop.Generator/Generation/InteropGeneratorEmitState.cs @@ -40,6 +40,11 @@ internal sealed class InteropGeneratorEmitState /// private readonly ConcurrentDictionary<(TypeSignature Key, TypeSignature Value), TypeDefinition> _mapVftblTypes = new(SignatureComparer.IgnoreVersion.MakeValueTupleComparer()); + /// + /// A map to allow reusing vtable types for applicable IDelegate interfaces. + /// + private readonly ConcurrentDictionary<(TypeSignature Sender, TypeSignature Args), TypeDefinition> _delegateVftblTypes = new(SignatureComparer.IgnoreVersion.MakeValueTupleComparer()); + /// /// Indicates whether the current state is readonly. /// @@ -128,7 +133,7 @@ public void TrackRetValValueMethodRewrite( } /// - /// Tracks a method rewrite that involves loading a parameter in the specified method. + /// Tracks a method rewrite that involves loading a managed parameter in the specified method. /// /// /// @@ -151,6 +156,36 @@ public void TrackManagedParameterMethodRewrite( }); } + /// + /// Tracks a method rewrite that involves loading a native parameter in the specified method. + /// + /// + /// + /// + /// + /// + /// + public void TrackNativeParameterMethodRewrite( + TypeSignature paraneterType, + MethodDefinition method, + CilInstruction tryMarker, + CilInstruction loadMarker, + CilInstruction finallyMarker, + int parameterIndex) + { + ThrowIfReadOnly(); + + _methodRewriteInfos.Add(new MethodRewriteInfo.NativeParameter + { + Type = paraneterType, + Method = method, + TryMarker = tryMarker, + Marker = loadMarker, + FinallyMarker = finallyMarker, + ParameterIndex = parameterIndex + }); + } + /// /// Enumerates all instances with info on two-pass code generation steps to perform. /// @@ -210,6 +245,32 @@ public TypeDefinition GetOrAddIMap2VftblType(TypeSignature keyType, TypeSignatur return _mapVftblTypes.GetOrAdd((keyType, valueType), vftblType); } + /// + /// Tries to get a previously registered vtable type for an IDelegate interface. + /// + /// The sender type. + /// The args type. + /// The resulting vtable type, if present. + /// Whether was successfully retrieved. + public bool TryGetDelegateVftblType(TypeSignature senderType, TypeSignature argsType, [NotNullWhen(true)] out TypeDefinition? vftblType) + { + return _delegateVftblTypes.TryGetValue((senderType, argsType), out vftblType); + } + + /// + /// Gets or adds a vtable type for an IDelegate interface. + /// + /// The key type. + /// The value type. + /// The created vtable type for . + /// The vtable type that should be used. + public TypeDefinition GetOrAddDelegateVftblType(TypeSignature senderType, TypeSignature argsType, TypeDefinition vftblType) + { + ThrowIfReadOnly(); + + return _delegateVftblTypes.GetOrAdd((senderType, argsType), vftblType); + } + /// /// Marks the current state as readonly. /// diff --git a/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.ManagedParameter.cs b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.ManagedParameter.cs index 5e18a8788..010c753bf 100644 --- a/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.ManagedParameter.cs +++ b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.ManagedParameter.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using WindowsRuntime.InteropGenerator.Helpers; + namespace WindowsRuntime.InteropGenerator.Models; /// @@ -9,7 +11,7 @@ internal partial class MethodRewriteInfo /// /// Contains info for a target method for two-pass IL generation, for a managed parameter. /// - /// + /// public sealed class ManagedParameter : MethodRewriteInfo { /// @@ -23,27 +25,41 @@ public override int CompareTo(MethodRewriteInfo? other) return 1; } - if (ReferenceEquals(this, other)) - { - return 0; - } - // If the input object is of a different type, just sort alphabetically based on the type name if (other is not ManagedParameter info) { return typeof(ManagedParameter).FullName!.CompareTo(other.GetType().FullName!); } - int result = CompareByMethodRewriteInfo(other); + int result = MemberDefinitionComparer.Instance.Compare(Method, other.Method); + + // First, sort by target method + if (result != 0) + { + return result; + } + + // Next, sort by parameter index + result = ParameterIndex.CompareTo(info.ParameterIndex); + + if (result != 0) + { + return result; + } + + // Next, compare by order of instructions within the target method + int leftIndex = Method.CilMethodBody?.Instructions.ReferenceIndexOf(Marker) ?? -1; + int rightIndex = other.Method.CilMethodBody?.Instructions.ReferenceIndexOf(other.Marker) ?? -1; + + result = leftIndex.CompareTo(rightIndex); - // If the two items are already not equal, we can stop here if (result != 0) { return result; } - // Lastly, compare by parameter index - return ParameterIndex.CompareTo(info.ParameterIndex); + // Lastly, compare by target type (this shouldn't be reached for valid objects) + return TypeDescriptorComparer.Instance.Compare(Type, other.Type); } } } diff --git a/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.NativeParameter.cs b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.NativeParameter.cs new file mode 100644 index 000000000..65884e8f9 --- /dev/null +++ b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.NativeParameter.cs @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using AsmResolver.PE.DotNet.Cil; +using WindowsRuntime.InteropGenerator.Helpers; + +namespace WindowsRuntime.InteropGenerator.Models; + +/// +internal partial class MethodRewriteInfo +{ + /// + /// Contains info for a target method for two-pass IL generation, for a native parameter. + /// + /// + public sealed class NativeParameter : MethodRewriteInfo + { + /// + public required CilInstruction TryMarker { get; init; } + + /// + public required CilInstruction FinallyMarker { get; init; } + + /// + public required int ParameterIndex { get; init; } + + /// + public override int CompareTo(MethodRewriteInfo? other) + { + if (other is null) + { + return 1; + } + + // If the input object is of a different type, just sort alphabetically based on the type name + if (other is not NativeParameter info) + { + return typeof(NativeParameter).FullName!.CompareTo(other.GetType().FullName!); + } + + int result = MemberDefinitionComparer.Instance.Compare(Method, other.Method); + + // First, sort by target method + if (result != 0) + { + return result; + } + + // Next, sort by parameter index + result = ParameterIndex.CompareTo(info.ParameterIndex); + + if (result != 0) + { + return result; + } + + ReadOnlySpan markers = [TryMarker, Marker, FinallyMarker]; + ReadOnlySpan otherMarkers = [info.TryMarker, info.Marker, info.FinallyMarker]; + + // Next, compare by order of instructions within the target method + for (int i = 0; i < markers.Length; i++) + { + int leftIndex = Method.CilMethodBody?.Instructions.ReferenceIndexOf(markers[i]) ?? -1; + int rightIndex = other.Method.CilMethodBody?.Instructions.ReferenceIndexOf(otherMarkers[i]) ?? -1; + + result = leftIndex.CompareTo(rightIndex); + + if (result != 0) + { + return result; + } + } + + // Lastly, compare by target type (this shouldn't be reached for valid objects) + return TypeDescriptorComparer.Instance.Compare(Type, other.Type); + } + } +} diff --git a/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.RetVal.cs b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.RetVal.cs index d86d21e98..821989703 100644 --- a/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.RetVal.cs +++ b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.RetVal.cs @@ -15,20 +15,10 @@ public sealed class RetVal : MethodRewriteInfo /// public override int CompareTo(MethodRewriteInfo? other) { - if (other is null) - { - return 1; - } - - if (ReferenceEquals(this, other)) - { - return 0; - } - - // Same logic as in 'ReturnValue', or just compare the base state - return other is not RetVal - ? typeof(RetVal).FullName!.CompareTo(other.GetType().FullName!) - : CompareByMethodRewriteInfo(other); + // 'RetVal' objects have no additional state, so just compare with the base state + return ReferenceEquals(this, other) + ? 0 + : CompareByMethodRewriteInfo(other); } } } diff --git a/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.ReturnValue.cs b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.ReturnValue.cs index 6fdf333ca..452e75d26 100644 --- a/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.ReturnValue.cs +++ b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.ReturnValue.cs @@ -20,36 +20,23 @@ public sealed class ReturnValue : MethodRewriteInfo /// public override int CompareTo(MethodRewriteInfo? other) { - if (other is null) - { - return 1; - } - if (ReferenceEquals(this, other)) { return 0; } - // If the input object is of a different type, just sort alphabetically based on the type name - if (other is not ReturnValue info) - { - return typeof(ReturnValue).FullName!.CompareTo(other.GetType().FullName!); - } - - int result = CompareByMethodRewriteInfo(other); + int result = CompareByMethodRewriteInfo(other); - // If the two items are already not equal, we can stop here + // First, compare with the base state if (result != 0) { return result; } int leftIndex = Method.CilMethodBody?.LocalVariables.IndexOf(Source) ?? -1; - int rightIndex = other.Method.CilMethodBody?.LocalVariables.IndexOf(info.Source) ?? -1; + int rightIndex = other!.Method.CilMethodBody?.LocalVariables.IndexOf(((ReturnValue)other).Source) ?? -1; - // Lastly, compare by order of instructions within the target method. - // There's no concern about stable sorting with respect to objects - // where the instructions are missing, as 'cswinrtgen' will fail. + // Lastly, compare by the order of the source variable return leftIndex.CompareTo(rightIndex); } } diff --git a/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.cs b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.cs index 0790df9fe..06d2afec5 100644 --- a/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.cs +++ b/src/WinRT.Interop.Generator/Models/MethodRewriteInfo/MethodRewriteInfo.cs @@ -31,32 +31,45 @@ internal abstract partial class MethodRewriteInfo : IComparable /// Compares the current instance just based on the state from . /// + /// The type currently in use. /// The input instance. /// The comparison result. - protected int CompareByMethodRewriteInfo(MethodRewriteInfo other) + protected int CompareByMethodRewriteInfo(MethodRewriteInfo? other) + where T : MethodRewriteInfo { - int result = TypeDescriptorComparer.Instance.Compare(Type, other.Type); + if (other is null) + { + return 1; + } - // Match by marshalling type first - if (result != 0) + // If the input object is of a different type, just sort alphabetically based on the type name + if (other is not T) { - return result; + return typeof(T).FullName!.CompareTo(other.GetType().FullName!); } - result = MemberDefinitionComparer.Instance.Compare(Method, other.Method); + int result = MemberDefinitionComparer.Instance.Compare(Method, other.Method); - // Match by target method next + // First, sort by target method if (result != 0) { return result; } - int leftIndex = Method.CilMethodBody?.Instructions.IndexOf(Marker) ?? -1; - int rightIndex = other.Method.CilMethodBody?.Instructions.IndexOf(other.Marker) ?? -1; - - // Lastly, compare by order of instructions within the target method. + // Next, compare by order of instructions within the target method. // There's no concern about stable sorting with respect to objects // where the instructions are missing, as 'cswinrtgen' will fail. - return leftIndex.CompareTo(rightIndex); + int leftIndex = Method.CilMethodBody?.Instructions.ReferenceIndexOf(Marker) ?? -1; + int rightIndex = other.Method.CilMethodBody?.Instructions.ReferenceIndexOf(other.Marker) ?? -1; + + result = leftIndex.CompareTo(rightIndex); + + if (result != 0) + { + return result; + } + + // Lastly, compare by target type (this shouldn't be reached for valid objects) + return TypeDescriptorComparer.Instance.Compare(Type, other.Type); } } diff --git a/src/WinRT.Interop.Generator/References/InteropReferences.cs b/src/WinRT.Interop.Generator/References/InteropReferences.cs index 348103964..797a43b9c 100644 --- a/src/WinRT.Interop.Generator/References/InteropReferences.cs +++ b/src/WinRT.Interop.Generator/References/InteropReferences.cs @@ -89,27 +89,27 @@ public InteropReferences( publicKeyOrToken: WellKnownPublicKeyTokens.SystemMemory); /// - /// Gets the for . + /// Gets the for . /// public TypeReference Attribute => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "Attribute"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference AttributeTargets => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "AttributeTargets"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference AttributeUsageAttribute => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "AttributeUsageAttribute"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference TypeMapAttribute1 => field ??= SystemRuntimeInteropServices.CreateTypeReference("System.Runtime.InteropServices"u8, "TypeMapAttribute`1"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference GuidAttribute => field ??= SystemRuntimeInteropServices.CreateTypeReference("System.Runtime.InteropServices"u8, "GuidAttribute"u8); @@ -119,7 +119,7 @@ public InteropReferences( public GenericInstanceTypeSignature TypeMapAttributeWindowsRuntimeComWrappersTypeMapGroup => field ??= TypeMapAttribute1.MakeGenericReferenceType(WindowsRuntimeComWrappersTypeMapGroup.ToReferenceTypeSignature()); /// - /// Gets the for . + /// Gets the for . /// public TypeReference TypeMapAssociationAttribute1 => field ??= SystemRuntimeInteropServices.CreateTypeReference("System.Runtime.InteropServices"u8, "TypeMapAssociationAttribute`1"u8); @@ -129,895 +129,925 @@ public InteropReferences( public GenericInstanceTypeSignature TypeMapAssociationAttributeDynamicInterfaceCastableImplementationTypeMapGroup => field ??= TypeMapAttribute1.MakeGenericReferenceType(DynamicInterfaceCastableImplementationTypeMapGroup.ToReferenceTypeSignature()); /// - /// Gets the for . + /// Gets the for . /// public TypeReference Array => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "Array"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference Nullable1 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "Nullable`1"u8); /// - /// Gets the for . + /// Gets the for of . + /// + public GenericInstanceTypeSignature NullableInt32 => field ??= Nullable1.MakeGenericValueType(_corLibTypeFactory.Int32); + + /// + /// Gets the for . /// public TypeReference Type => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "Type"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference RuntimeTypeHandle => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "RuntimeTypeHandle"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference Delegate => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "Delegate"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference ValueType => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "ValueType"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference FlagsAttribute => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "FlagsAttribute"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference Span1 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "Span`1"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference ReadOnlySpan1 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "ReadOnlySpan`1"u8); /// - /// Gets the for of . + /// Gets the for of . /// public GenericInstanceTypeSignature ReadOnlySpanByte => field ??= ReadOnlySpan1.MakeGenericValueType(_corLibTypeFactory.Byte); /// - /// Gets the for of . + /// Gets the for of . /// public GenericInstanceTypeSignature ReadOnlySpanChar => field ??= ReadOnlySpan1.MakeGenericValueType(_corLibTypeFactory.Char); /// - /// Gets the for of . + /// Gets the for of . /// public GenericInstanceTypeSignature ReadOnlySpanUInt16 => field ??= ReadOnlySpan1.MakeGenericValueType(_corLibTypeFactory.UInt16); /// - /// Gets the for of . + /// Gets the for of . /// public GenericInstanceTypeSignature ReadOnlySpanInt32 => field ??= ReadOnlySpan1.MakeGenericValueType(_corLibTypeFactory.Int32); /// - /// Gets the for . + /// Gets the for . /// public TypeReference Func3 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "Func`3"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference Exception => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "Exception"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference NotSupportedException => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "NotSupportedException"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference Guid => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "Guid"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference EventHandler => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "EventHandler"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference EventHandler1 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "EventHandler`1"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference EventHandler2 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "EventHandler`2"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IDisposable => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "IDisposable"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference TimeSpan => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "TimeSpan"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference DateTimeOffset => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "DateTimeOffset"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IServiceProvider => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System"u8, "IServiceProvider"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference ICommand => field ??= SystemObjectModel.CreateTypeReference("System.Windows.Input"u8, "ICommand"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference INotifyCollectionChanged => field ??= SystemObjectModel.CreateTypeReference("System.Collections.Specialized"u8, "INotifyCollectionChanged"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference INotifyDataErrorInfo => field ??= SystemObjectModel.CreateTypeReference("System.ComponentModel"u8, "INotifyDataErrorInfo"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference INotifyPropertyChanged => field ??= SystemObjectModel.CreateTypeReference("System.ComponentModel"u8, "INotifyPropertyChanged"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IEnumerator => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections"u8, "IEnumerator"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IEnumerator1 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections.Generic"u8, "IEnumerator`1"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IEnumerable => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections"u8, "IEnumerable"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IEnumerable1 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections.Generic"u8, "IEnumerable`1"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference ICollection1 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections.Generic"u8, "ICollection`1"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IReadOnlyCollection1 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections.Generic"u8, "IReadOnlyCollection`1"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IList => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections"u8, "IList"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IList1 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections.Generic"u8, "IList`1"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IReadOnlyList1 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections.Generic"u8, "IReadOnlyList`1"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IDictionary2 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections.Generic"u8, "IDictionary`2"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IReadOnlyDictionary2 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections.Generic"u8, "IReadOnlyDictionary`2"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference KeyValuePair => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections.Generic"u8, "KeyValuePair"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference KeyValuePair2 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections.Generic"u8, "KeyValuePair`2"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference NotifyCollectionChangedEventHandler => field ??= SystemObjectModel.CreateTypeReference("System.Collections.Specialized"u8, "NotifyCollectionChangedEventHandler"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference NotifyCollectionChangedEventArgs => field ??= SystemObjectModel.CreateTypeReference("System.Collections.Specialized"u8, "NotifyCollectionChangedEventArgs"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference PropertyChangedEventHandler => field ??= SystemObjectModel.CreateTypeReference("System.ComponentModel"u8, "PropertyChangedEventHandler"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference PropertyChangedEventArgs => field ??= SystemObjectModel.CreateTypeReference("System.ComponentModel"u8, "PropertyChangedEventArgs"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference MemoryExtensions => field ??= SystemMemory.CreateTypeReference("System"u8, "MemoryExtensions"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference Interlocked => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Threading"u8, "Interlocked"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference MemoryMarshal => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Runtime.InteropServices"u8, "MemoryMarshal"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference ComWrappers => field ??= SystemRuntimeInteropServices.CreateTypeReference("System.Runtime.InteropServices"u8, "ComWrappers"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference ComInterfaceDispatch => field ??= ComWrappers.CreateTypeReference("ComInterfaceDispatch"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference ComInterfaceEntry => field ??= ComWrappers.CreateTypeReference("ComInterfaceEntry"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference CreateComInterfaceFlags => field ??= SystemRuntimeInteropServices.CreateTypeReference("System.Runtime.InteropServices"u8, "CreateComInterfaceFlags"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference CreatedWrapperFlags => field ??= SystemRuntimeInteropServices.CreateTypeReference("System.Runtime.InteropServices"u8, "CreatedWrapperFlags"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference InAttribute => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Runtime.InteropServices"u8, "InAttribute"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference DynamicInterfaceCastableImplementationAttribute => field ??= SystemRuntimeInteropServices.CreateTypeReference("System.Runtime.InteropServices"u8, "DynamicInterfaceCastableImplementationAttribute"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IUnknownDerivedAttribute2 => field ??= SystemRuntimeInteropServices.CreateTypeReference("System.Runtime.InteropServices.Marshalling"u8, "IUnknownDerivedAttribute`2"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IIUnknownInterfaceType => field ??= SystemRuntimeInteropServices.CreateTypeReference("System.Runtime.InteropServices.Marshalling"u8, "IIUnknownInterfaceType"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IsVolatile => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Runtime.CompilerServices"u8, "IsVolatile"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference IsReadOnlyAttribute => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Runtime.CompilerServices"u8, "IsReadOnlyAttribute"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference FixedAddressValueTypeAttribute => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Runtime.CompilerServices"u8, "FixedAddressValueTypeAttribute"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference ScopedRefAttribute => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Runtime.CompilerServices"u8, "ScopedRefAttribute"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference CallConvMemberFunction => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Runtime.CompilerServices"u8, "CallConvMemberFunction"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference ConditionalWeakTable2 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Runtime.CompilerServices"u8, "ConditionalWeakTable`2"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference UnmanagedCallersOnlyAttribute => field ??= SystemRuntimeInteropServices.CreateTypeReference("System.Runtime.InteropServices"u8, "UnmanagedCallersOnlyAttribute"u8); /// - /// Gets the for ABI.System.Type. + /// Gets the for ABI.System.Type. /// public TypeReference AbiType => field ??= _windowsRuntimeModule.CreateTypeReference("ABI.System"u8, "Type"u8); /// - /// Gets the for ABI.System.Exception. + /// Gets the for ABI.System.Exception. /// public TypeReference AbiException => field ??= _windowsRuntimeModule.CreateTypeReference("ABI.System"u8, "Exception"u8); /// - /// Gets the for ABI.System.TimeSpan. + /// Gets the for ABI.System.TimeSpan. /// public TypeReference AbiTimeSpan => field ??= _windowsRuntimeModule.CreateTypeReference("ABI.System"u8, "TimeSpan"u8); /// - /// Gets the for ABI.System.DateTimeOffset. + /// Gets the for ABI.System.DateTimeOffset. /// public TypeReference AbiDateTimeOffset => field ??= _windowsRuntimeModule.CreateTypeReference("ABI.System"u8, "DateTimeOffset"u8); /// - /// Gets the for ABI.System.TypeMarshaller. + /// Gets the for ABI.System.TypeMarshaller. /// public TypeReference TypeMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("ABI.System"u8, "TypeMarshaller"u8); /// - /// Gets the for ABI.System.TypeMarshaller. + /// Gets the for ABI.System.TypeMarshaller. /// public TypeReference ExceptionMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("ABI.System"u8, "ExceptionMarshaller"u8); /// - /// Gets the for ABI.System.TimeSpanMarshaller. + /// Gets the for ABI.System.TimeSpanMarshaller. /// public TypeReference TimeSpanMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("ABI.System"u8, "TimeSpanMarshaller"u8); /// - /// Gets the for ABI.System.DateTimeOffsetMarshaller. + /// Gets the for ABI.System.DateTimeOffsetMarshaller. /// public TypeReference DateTimeOffsetMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("ABI.System"u8, "DateTimeOffsetMarshaller"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeClassNameAttribute. + /// Gets the for WindowsRuntime.WindowsRuntimeClassNameAttribute. /// public TypeReference WindowsRuntimeClassNameAttribute => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeClassNameAttribute"u8); /// - /// Gets the for . + /// Gets the for . /// public TypeReference WindowsRuntimeDefaultInterfaceAttribute => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeDefaultInterfaceAttribute"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeMetadataAttribute. + /// Gets the for WindowsRuntime.WindowsRuntimeMetadataAttribute. /// public TypeReference WindowsRuntimeMetadataAttribute => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeMetadataAttribute"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeManagedOnlyTypeAttribute. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeManagedOnlyTypeAttribute. /// public TypeReference WindowsRuntimeManagedOnlyTypeAttribute => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "WindowsRuntimeManagedOnlyTypeAttribute"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeComWrappersTypeMapGroup. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeComWrappersTypeMapGroup. /// public TypeReference WindowsRuntimeComWrappersTypeMapGroup => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "WindowsRuntimeComWrappersTypeMapGroup"u8); /// - /// Gets the for WindowsRuntime.InteropServices.DynamicInterfaceCastableImplementationTypeMapGroup. + /// Gets the for WindowsRuntime.InteropServices.DynamicInterfaceCastableImplementationTypeMapGroup. /// public TypeReference DynamicInterfaceCastableImplementationTypeMapGroup => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "DynamicInterfaceCastableImplementationTypeMapGroup"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WellKnownInterfaceIIDs. + /// Gets the for WindowsRuntime.InteropServices.WellKnownInterfaceIIDs. /// public TypeReference WellKnownInterfaceIIDs => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "WellKnownInterfaceIIDs"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IUnknownImpl. + /// Gets the for WindowsRuntime.InteropServices.IUnknownImpl. /// public TypeReference IUnknownImpl => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IUnknownImpl"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IInspectableImpl. + /// Gets the for WindowsRuntime.InteropServices.IInspectableImpl. /// public TypeReference IInspectableImpl => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IInspectableImpl"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IPropertyValueImpl. + /// Gets the for WindowsRuntime.InteropServices.IPropertyValueImpl. /// public TypeReference IPropertyValueImpl => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IPropertyValueImpl"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IStringableImpl. + /// Gets the for WindowsRuntime.InteropServices.IStringableImpl. /// public TypeReference IStringableImpl => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IStringableImpl"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IMarshalImpl. + /// Gets the for WindowsRuntime.InteropServices.IMarshalImpl. /// public TypeReference IMarshalImpl => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IMarshalImpl"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IWeakReferenceSourceImpl. + /// Gets the for WindowsRuntime.InteropServices.IWeakReferenceSourceImpl. /// public TypeReference IWeakReferenceSourceImpl => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IWeakReferenceSourceImpl"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IAgileObjectImpl. + /// Gets the for WindowsRuntime.InteropServices.IAgileObjectImpl. /// public TypeReference IAgileObjectImpl => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IAgileObjectImpl"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IAsyncActionWithProgressMethods. + /// Gets the for WindowsRuntime.InteropServices.IAsyncActionWithProgressMethods. /// public TypeReference IAsyncActionWithProgressMethods => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IAsyncActionWithProgressMethods"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IAsyncActionWithProgressMethodsImpl<TProgress>. + /// Gets the for WindowsRuntime.InteropServices.IAsyncActionWithProgressMethodsImpl<TProgress>. /// public TypeReference IAsyncActionWithProgressMethodsImpl1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IAsyncActionWithProgressMethodsImpl`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IAsyncOperationMethodsImpl<TResult>. + /// Gets the for WindowsRuntime.InteropServices.IAsyncOperationMethodsImpl<TResult>. /// public TypeReference IAsyncOperationMethodsImpl1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IAsyncOperationMethodsImpl`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IAsyncOperationWithProgressMethodsImpl<TResult, TProgress>. + /// Gets the for WindowsRuntime.InteropServices.IAsyncOperationWithProgressMethodsImpl<TResult, TProgress>. /// public TypeReference IAsyncOperationWithProgressMethodsImpl2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IAsyncOperationWithProgressMethodsImpl`2"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IIterableMethodsImpl<T>. + /// Gets the for WindowsRuntime.InteropServices.IIterableMethodsImpl<T>. /// public TypeReference IIterableMethodsImpl1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IIterableMethodsImpl`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IIteratorMethods. + /// Gets the for WindowsRuntime.InteropServices.IIteratorMethods. /// public TypeReference IIteratorMethods => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IIteratorMethods"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IIteratorMethodsImpl<T>. + /// Gets the for WindowsRuntime.InteropServices.IIteratorMethodsImpl<T>. /// public TypeReference IIteratorMethodsImpl1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IIteratorMethodsImpl`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IEnumeratorAdapter<T>. + /// Gets the for WindowsRuntime.InteropServices.IEnumeratorAdapter<T>. /// public TypeReference IEnumeratorAdapter1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IEnumeratorAdapter`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IVectorMethodsImpl<T>. + /// Gets the for WindowsRuntime.InteropServices.IVectorMethodsImpl<T>. /// public TypeReference IVectorMethodsImpl1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IVectorMethodsImpl`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IVectorMethodsImpl<T>. + /// Gets the for WindowsRuntime.InteropServices.IVectorMethodsImpl<T>. /// public TypeReference IVectorMethods1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IVectorMethodsImpl`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IVectorViewMethodsImpl<T>. + /// Gets the for WindowsRuntime.InteropServices.IVectorViewMethodsImpl<T>. /// public TypeReference IVectorViewMethods1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IVectorViewMethodsImpl`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IMapMethodsImpl<K, V>. + /// Gets the for WindowsRuntime.InteropServices.IMapMethodsImpl<K, V>. /// public TypeReference IMapMethodsImpl2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IMapMethodsImpl`2"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IMapViewMethodsImpl<K, V>. + /// Gets the for WindowsRuntime.InteropServices.IMapViewMethodsImpl<K, V>. /// public TypeReference IMapViewMethodsImpl2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IMapViewMethodsImpl`2"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IObservableVectorMethodsImpl<T>. + /// Gets the for WindowsRuntime.InteropServices.IObservableVectorMethodsImpl<T>. /// public TypeReference IObservableVectorMethodsImpl1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IObservableVectorMethodsImpl`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IObservableMapMethodsImpl<TKey, TValue>. + /// Gets the for WindowsRuntime.InteropServices.IObservableMapMethodsImpl<TKey, TValue>. /// public TypeReference IObservableMapMethodsImpl2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IObservableMapMethodsImpl`2"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IMapChangedEventArgsImpl<K>. + /// Gets the for WindowsRuntime.InteropServices.IMapChangedEventArgsImpl<K>. /// public TypeReference IMapChangedEventArgsImpl1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IMapChangedEventArgsImpl`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IListMethods. + /// Gets the for WindowsRuntime.InteropServices.IListMethods. /// public TypeReference IListMethods => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IListMethods"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListMethods. + /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListMethods. /// public TypeReference IReadOnlyListMethods => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IReadOnlyListMethods"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IListMethods<T>. + /// Gets the for WindowsRuntime.InteropServices.IListMethods<T>. /// public TypeReference IListMethods1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IListMethods`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListMethods<T>. + /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListMethods<T>. /// public TypeReference IReadOnlyListMethods1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IReadOnlyListMethods`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IDictionaryMethods. + /// Gets the for WindowsRuntime.InteropServices.IDictionaryMethods. /// public TypeReference IDictionaryMethods => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IDictionaryMethods"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IDictionaryMethods<TKey, TValue>. + /// Gets the for WindowsRuntime.InteropServices.IDictionaryMethods<TKey, TValue>. /// public TypeReference IDictionaryMethods2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IDictionaryMethods`2"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IReadOnlyDictionaryMethods. + /// Gets the for WindowsRuntime.InteropServices.IReadOnlyDictionaryMethods. /// public TypeReference IReadOnlyDictionaryMethods => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IReadOnlyDictionaryMethods"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IReadOnlyDictionaryMethods<TKey, TValue>. + /// Gets the for WindowsRuntime.InteropServices.IReadOnlyDictionaryMethods<TKey, TValue>. /// public TypeReference IReadOnlyDictionaryMethods2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IReadOnlyDictionaryMethods`2"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IMapChangedEventArgsMethods. + /// Gets the for WindowsRuntime.InteropServices.IMapChangedEventArgsMethods. /// public TypeReference IMapChangedEventArgsMethods => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IMapChangedEventArgsMethods"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeObject. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeObject. /// public TypeReference WindowsRuntimeObject => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeObject"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeAsyncActionWithProgress<T, ...>. + /// Gets the for WindowsRuntime.WindowsRuntimeAsyncActionWithProgress<T, ...>. /// public TypeReference WindowsRuntimeAsyncActionWithProgress2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeAsyncActionWithProgress`2"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeAsyncOperation<T, ...>. + /// Gets the for WindowsRuntime.WindowsRuntimeAsyncOperation<T, ...>. /// public TypeReference WindowsRuntimeAsyncOperation2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeAsyncOperation`2"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeAsyncOperationWithProgress<T, ...>. + /// Gets the for WindowsRuntime.WindowsRuntimeAsyncOperationWithProgress<T, ...>. /// public TypeReference WindowsRuntimeAsyncOperationWithProgress3 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeAsyncOperationWithProgress`3"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeEnumerator<T, ...>. + /// Gets the for WindowsRuntime.WindowsRuntimeEnumerator<T, ...>. /// public TypeReference WindowsRuntimeEnumerator2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeEnumerator`2"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeEnumerable<T, ...>. + /// Gets the for WindowsRuntime.WindowsRuntimeEnumerable<T, ...>. /// public TypeReference WindowsRuntimeEnumerable2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeEnumerable`2"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeList<T, ...>. + /// Gets the for WindowsRuntime.WindowsRuntimeList<T, ...>. /// public TypeReference WindowsRuntimeList4 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeList`4"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeReadOnlyList<T, ...>. + /// Gets the for WindowsRuntime.WindowsRuntimeReadOnlyList<T, ...>. /// public TypeReference WindowsRuntimeReadOnlyList4 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeReadOnlyList`4"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeDictionary<TKey, TValue, ...>. + /// Gets the for WindowsRuntime.WindowsRuntimeDictionary<TKey, TValue, ...>. /// public TypeReference WindowsRuntimeDictionary5 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeDictionary`5"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeReadOnlyDictionary<TKey, TValue, ...>. + /// Gets the for WindowsRuntime.WindowsRuntimeReadOnlyDictionary<TKey, TValue, ...>. /// public TypeReference WindowsRuntimeReadOnlyDictionary5 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeReadOnlyDictionary`5"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeObservableVector<T, ...>. + /// Gets the for WindowsRuntime.WindowsRuntimeObservableVector<T, ...>. /// public TypeReference WindowsRuntimeObservableVector6 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeObservableVector`6"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeObservableMap<TKey, TValue, ...>. + /// Gets the for WindowsRuntime.WindowsRuntimeObservableMap<TKey, TValue, ...>. /// public TypeReference WindowsRuntimeObservableMap7 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeObservableMap`7"u8); /// - /// Gets the for WindowsRuntime.WindowsRuntimeMapChangedEventArgs<TKey, ...>. + /// Gets the for WindowsRuntime.WindowsRuntimeMapChangedEventArgs<TKey, ...>. /// public TypeReference WindowsRuntimeMapChangedEventArgs2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeMapChangedEventArgs`2"u8); /// - /// Gets the for WindowsRuntime.DictionaryKeyCollection2<TKey, TValue>. + /// Gets the for WindowsRuntime.DictionaryKeyCollection2<TKey, TValue>. /// public TypeReference DictionaryKeyCollection2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "DictionaryKeyCollection`2"u8); /// - /// Gets the for WindowsRuntime.DictionaryValueCollection2<TKey, TValue>. + /// Gets the for WindowsRuntime.DictionaryValueCollection2<TKey, TValue>. /// public TypeReference DictionaryValueCollection2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "DictionaryValueCollection`2"u8); /// - /// Gets the for WindowsRuntime.ReadOnlyDictionaryKeyCollection2<TKey, TValue>. + /// Gets the for WindowsRuntime.ReadOnlyDictionaryKeyCollection2<TKey, TValue>. /// public TypeReference ReadOnlyDictionaryKeyCollection2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "ReadOnlyDictionaryKeyCollection`2"u8); /// - /// Gets the for WindowsRuntime.ReadOnlyDictionaryValueCollection2<TKey, TValue>. + /// Gets the for WindowsRuntime.ReadOnlyDictionaryValueCollection2<TKey, TValue>. /// public TypeReference ReadOnlyDictionaryValueCollection2 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "ReadOnlyDictionaryValueCollection`2"u8); /// - /// Gets the for WindowsRuntime.InteropServices.BindableIReadOnlyListAdapter. + /// Gets the for WindowsRuntime.InteropServices.BindableIReadOnlyListAdapter. /// public TypeReference BindableIReadOnlyListAdapter => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "BindableIReadOnlyListAdapter"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IWindowsRuntimeInterface. + /// Gets the for WindowsRuntime.InteropServices.IWindowsRuntimeInterface. /// public TypeReference IWindowsRuntimeInterface => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IWindowsRuntimeInterface"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IWindowsRuntimeObjectComWrappersCallback. + /// Gets the for WindowsRuntime.InteropServices.IWindowsRuntimeObjectComWrappersCallback. /// public TypeReference IWindowsRuntimeObjectComWrappersCallback => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IWindowsRuntimeObjectComWrappersCallback"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IWindowsRuntimeUnsealedObjectComWrappersCallback. + /// Gets the for WindowsRuntime.InteropServices.IWindowsRuntimeUnsealedObjectComWrappersCallback. /// public TypeReference IWindowsRuntimeUnsealedObjectComWrappersCallback => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IWindowsRuntimeUnsealedObjectComWrappersCallback"u8); /// - /// Gets the for WindowsRuntime.InteropServices.IWindowsRuntimeArrayComWrappersCallback. + /// Gets the for WindowsRuntime.InteropServices.IWindowsRuntimeArrayComWrappersCallback. /// public TypeReference IWindowsRuntimeArrayComWrappersCallback => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IWindowsRuntimeArrayComWrappersCallback"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeComWrappersMarshallerAttribute. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeComWrappersMarshallerAttribute. /// public TypeReference WindowsRuntimeComWrappersMarshallerAttribute => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "WindowsRuntimeComWrappersMarshallerAttribute"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeObjectReference. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeObjectReference. /// public TypeReference WindowsRuntimeObjectReference => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "WindowsRuntimeObjectReference"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeObjectReferenceValue. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeObjectReferenceValue. /// public TypeReference WindowsRuntimeObjectReferenceValue => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "WindowsRuntimeObjectReferenceValue"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeComWrappersMarshal. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeComWrappersMarshal. /// public TypeReference WindowsRuntimeComWrappersMarshal => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "WindowsRuntimeComWrappersMarshal"u8); /// - /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeUnknownMarshaller. + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeUnknownMarshaller. /// public TypeReference WindowsRuntimeUnknownMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeUnknownMarshaller"u8); /// - /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeObjectMarshaller. + /// Gets the for WindowsRuntime.InteropServices.Marshalling.WindowsRuntimeObjectMarshaller. /// public TypeReference WindowsRuntimeObjectMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeObjectMarshaller"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeUnsealedObjectMarshaller. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeUnsealedObjectMarshaller. /// public TypeReference WindowsRuntimeUnsealedObjectMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeUnsealedObjectMarshaller"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeInterfaceMarshaller<T>. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeInterfaceMarshaller<T>. /// public TypeReference WindowsRuntimeInterfaceMarshaller1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeInterfaceMarshaller`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeDelegateMarshaller. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeDelegateMarshaller. /// public TypeReference WindowsRuntimeDelegateMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeDelegateMarshaller"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeArrayMarshaller. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeArrayMarshaller. /// public TypeReference WindowsRuntimeArrayMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeArrayMarshaller"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeValueTypeMarshaller. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeValueTypeMarshaller. /// public TypeReference WindowsRuntimeValueTypeMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "WindowsRuntimeValueTypeMarshaller"u8); /// - /// Gets the for WindowsRuntime.InteropServices.HStringMarshaller. + /// Gets the for WindowsRuntime.InteropServices.Marshalling.TypeReference. + /// + public TypeReference TypeReference => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "TypeReference"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.Marshalling.HStringReference. + /// + public TypeReference HStringReference => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "HStringReference"u8); + + /// + /// Gets the for WindowsRuntime.InteropServices.HStringMarshaller. /// public TypeReference HStringMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "HStringMarshaller"u8); /// - /// Gets the for WindowsRuntime.InteropServices.RestrictedErrorInfo. + /// Gets the for WindowsRuntime.InteropServices.RestrictedErrorInfo. /// public TypeReference RestrictedErrorInfo => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "RestrictedErrorInfo"u8); /// - /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeArrayHelpers. + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeArrayHelpers. /// public TypeReference WindowsRuntimeArrayHelpers => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "WindowsRuntimeArrayHelpers"u8); /// - /// Gets the for WindowsRuntime.InteropServices.Marshalling.RestrictedErrorInfoExceptionMarshaller. + /// Gets the for WindowsRuntime.InteropServices.Marshalling.RestrictedErrorInfoExceptionMarshaller. /// public TypeReference RestrictedErrorInfoExceptionMarshaller => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices.Marshalling"u8, "RestrictedErrorInfoExceptionMarshaller"u8); /// - /// Gets the for WindowsRuntime.InteropServices.EventRegistrationToken. + /// Gets the for WindowsRuntime.InteropServices.EventRegistrationToken. /// public TypeReference EventRegistrationToken => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "EventRegistrationToken"u8); /// - /// Gets the for WindowsRuntime.InteropServices.EventRegistrationTokenTable<T>. + /// Gets the for WindowsRuntime.InteropServices.EventRegistrationTokenTable<T>. /// public TypeReference EventRegistrationTokenTable1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "EventRegistrationTokenTable`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.EventSource<T>. + /// Gets the for WindowsRuntime.InteropServices.EventSource<T>. /// public TypeReference EventSource1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "EventSource`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.EventHandlerEventSource<TEventArgs>. + /// Gets the for WindowsRuntime.InteropServices.EventHandlerEventSource<TEventArgs>. /// public TypeReference EventHandler1EventSource => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "EventHandlerEventSource`1"u8); /// - /// Gets the for WindowsRuntime.InteropServices.EventHandlerEventSource<TSender, TEventArgs>. + /// Gets the for WindowsRuntime.InteropServices.EventHandlerEventSource<TSender, TEventArgs>. /// public TypeReference EventHandler2EventSource => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "EventHandlerEventSource`2"u8); /// - /// Gets the for Windows.Foundation.Collections.IObservableVector<T>. + /// Gets the for Windows.Foundation.Collections.IObservableVector<T>. /// public TypeReference IObservableVector1 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation.Collections"u8, "IObservableVector`1"u8); /// - /// Gets the for Windows.Foundation.Collections.IObservableMap<K, V>. + /// Gets the for Windows.Foundation.Collections.IObservableMap<K, V>. /// public TypeReference IObservableMap2 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation.Collections"u8, "IObservableMap`2"u8); /// - /// Gets the for Windows.Foundation.Collections.IMapChangedEventArgs<K>. + /// Gets the for Windows.Foundation.Collections.IMapChangedEventArgs<K>. /// public TypeReference IMapChangedEventArgs1 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation.Collections"u8, "IMapChangedEventArgs`1"u8); /// - /// Gets the for Windows.Foundation.Collections.IVectorChangedEventArgs<T>. + /// Gets the for Windows.Foundation.Collections.IVectorChangedEventArgs<T>. /// public TypeReference IVectorChangedEventArgs => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation.Collections"u8, "IVectorChangedEventArgs"u8); /// - /// Gets the for Windows.Foundation.Collections.CollectionChange. + /// Gets the for Windows.Foundation.Collections.CollectionChange. /// public TypeReference CollectionChange => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation.Collections"u8, "CollectionChange"u8); /// - /// Gets the for Windows.Foundation.Collections.VectorChangedEventHandler<T>. + /// Gets the for Windows.Foundation.Collections.VectorChangedEventHandler<T>. /// public TypeReference VectorChangedEventHandler1 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation.Collections"u8, "VectorChangedEventHandler`1"u8); /// - /// Gets the for the event source type for . + /// Gets the for the event source type for . /// public TypeReference VectorChangedEventHandler1EventSource => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "VectorChangedEventHandlerEventSource`1"u8); /// - /// Gets the for Windows.Foundation.Collections.MapChangedEventHandler<K, V>. + /// Gets the for Windows.Foundation.Collections.MapChangedEventHandler<K, V>. /// public TypeReference MapChangedEventHandler2 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation.Collections"u8, "MapChangedEventHandler`2"u8); /// - /// Gets the for the event source type for . + /// Gets the for the event source type for . /// public TypeReference MapChangedEventHandler2EventSource => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "MapChangedEventHandlerEventSource`2"u8); /// - /// Gets the for Windows.Foundation.TrustLevel. + /// Gets the for Windows.Foundation.TrustLevel. /// public TypeReference TrustLevel => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "TrustLevel"u8); /// - /// Gets the for Windows.Foundation.Point. + /// Gets the for Windows.Foundation.Point. /// public TypeReference Point => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "Point"u8); /// - /// Gets the for Windows.Foundation.Rect. + /// Gets the for Windows.Foundation.Rect. /// public TypeReference Rect => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "Rect"u8); /// - /// Gets the for Windows.Foundation.Size. + /// Gets the for Windows.Foundation.Size. /// public TypeReference Size => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "Size"u8); /// - /// Gets the for Windows.Foundation.AsyncStatus. + /// Gets the for Windows.Foundation.AsyncStatus. /// public TypeReference AsyncStatus => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "AsyncStatus"u8); /// - /// Gets the for Windows.Foundation.IAsyncInfo. + /// Gets the for Windows.Foundation.IAsyncInfo. /// public TypeReference IAsyncInfo => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "IAsyncInfo"u8); /// - /// Gets the for Windows.Foundation.IAsyncAction. + /// Gets the for Windows.Foundation.IAsyncAction. /// public TypeReference IAsyncAction => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "IAsyncAction"u8); /// - /// Gets the for Windows.Foundation.AsyncActionCompletedHandler. + /// Gets the for Windows.Foundation.AsyncActionCompletedHandler. /// public TypeReference AsyncActionCompletedHandler => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "AsyncActionCompletedHandler"u8); /// - /// Gets the for Windows.Foundation.IAsyncActionWithProgress<TProgress>. + /// Gets the for Windows.Foundation.IAsyncActionWithProgress<TProgress>. /// public TypeReference IAsyncActionWithProgress1 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "IAsyncActionWithProgress`1"u8); /// - /// Gets the for Windows.Foundation.AsyncActionProgressHandler<TProgress>. + /// Gets the for Windows.Foundation.AsyncActionProgressHandler<TProgress>. /// public TypeReference AsyncActionProgressHandler1 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "AsyncActionProgressHandler`1"u8); /// - /// Gets the for Windows.Foundation.AsyncActionWithProgressCompletedHandler<TProgress>. + /// Gets the for Windows.Foundation.AsyncActionWithProgressCompletedHandler<TProgress>. /// public TypeReference AsyncActionWithProgressCompletedHandler1 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "AsyncActionWithProgressCompletedHandler`1"u8); /// - /// Gets the for Windows.Foundation.IAsyncOperation<TResult>. + /// Gets the for Windows.Foundation.IAsyncOperation<TResult>. /// public TypeReference IAsyncOperation1 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "IAsyncOperation`1"u8); /// - /// Gets the for Windows.Foundation.AsyncOperationCompletedHandler<TResult>. + /// Gets the for Windows.Foundation.AsyncOperationCompletedHandler<TResult>. /// public TypeReference AsyncOperationCompletedHandler1 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "AsyncOperationCompletedHandler`1"u8); /// - /// Gets the for Windows.Foundation.IAsyncOperationWithProgress<TResult, TProgress>. + /// Gets the for Windows.Foundation.IAsyncOperationWithProgress<TResult, TProgress>. /// public TypeReference IAsyncOperationWithProgress2 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "IAsyncOperationWithProgress`2"u8); /// - /// Gets the for Windows.Foundation.AsyncOperationProgressHandler<TResult, TProgress>. + /// Gets the for Windows.Foundation.AsyncOperationProgressHandler<TResult, TProgress>. /// public TypeReference AsyncOperationProgressHandler2 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "AsyncOperationProgressHandler`2"u8); /// - /// Gets the for Windows.Foundation.AsyncOperationWithProgressCompletedHandler<TResult>. + /// Gets the for Windows.Foundation.AsyncOperationWithProgressCompletedHandler<TResult>. /// public TypeReference AsyncOperationWithProgressCompletedHandler2 => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "AsyncOperationWithProgressCompletedHandler`2"u8); + /// + /// Gets the for . + /// + public MemberReference Stringget_Length => field ??= _corLibTypeFactory.String + .ToTypeDefOrRef() + .CreateMemberReference("get_Length"u8, MethodSignature.CreateInstance(_corLibTypeFactory.Int32)); + + /// + /// Gets the for . + /// + public MemberReference StringGetPinnableReference => field ??= _corLibTypeFactory.String + .ToTypeDefOrRef() + .CreateMemberReference("GetPinnableReference"u8, MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Char.MakeByReferenceType().MakeModifierType(InAttribute, isRequired: true))); + /// /// Gets the for . /// @@ -1049,24 +1079,24 @@ public InteropReferences( returnType: RuntimeTypeHandle.ToValueTypeSignature())); /// - /// Gets the for . + /// Gets the for . /// public MemberReference AttributeUsageAttribute_ctor_AttributeTargets => field ??= AttributeUsageAttribute.CreateConstructorReference( corLibTypeFactory: _corLibTypeFactory, parameterTypes: [AttributeTargets.ToValueTypeSignature()]); /// - /// Gets the for , using . + /// Gets the for , using . /// public MemberReference TypeMapAttributeWindowsRuntimeComWrappersTypeMapGroup_ctor_TrimTarget => field ??= TypeMapAttribute1_ctor_TrimTarget(WindowsRuntimeComWrappersTypeMapGroup.ToReferenceTypeSignature()); /// - /// Gets the for , using . + /// Gets the for , using . /// public MemberReference TypeMapAssociationAttributeWindowsRuntimeComWrappersTypeMapGroup_ctor => field ??= TypeMapAssociationAttribute1_ctor(WindowsRuntimeComWrappersTypeMapGroup.ToReferenceTypeSignature()); /// - /// Gets the for , using . + /// Gets the for , using . /// public MemberReference TypeMapAssociationAttributeDynamicInterfaceCastableImplementationTypeMapGroup_ctor => field ??= TypeMapAssociationAttribute1_ctor(DynamicInterfaceCastableImplementationTypeMapGroup.ToReferenceTypeSignature()); @@ -1184,27 +1214,27 @@ public InteropReferences( _corLibTypeFactory.Int32])); /// - /// Gets the for . + /// Gets the for . /// public MemberReference FixedAddressValueTypeAttribute_ctor => field ??= FixedAddressValueTypeAttribute.CreateConstructorReference(_corLibTypeFactory); /// - /// Gets the for . + /// Gets the for . /// public MemberReference DynamicInterfaceCastableImplementationAttribute_ctor => field ??= DynamicInterfaceCastableImplementationAttribute.CreateConstructorReference(_corLibTypeFactory); /// - /// Gets the for . + /// Gets the for . /// public MemberReference IsReadOnlyAttribute_ctor => field ??= IsReadOnlyAttribute.CreateConstructorReference(_corLibTypeFactory); /// - /// Gets the for . + /// Gets the for . /// public MemberReference ScopedRefAttribute_ctor => field ??= ScopedRefAttribute.CreateConstructorReference(_corLibTypeFactory); /// - /// Gets the for . + /// Gets the for . /// public MemberReference UnmanagedCallersOnlyAttribute_ctor => field ??= UnmanagedCallersOnlyAttribute.CreateConstructorReference(_corLibTypeFactory); @@ -1448,14 +1478,14 @@ public InteropReferences( parameterTypes: [WindowsRuntimeObjectReference.ToReferenceTypeSignature()])); /// - /// Gets the for 's get_NativeObjectReference method. + /// Gets the for 's get_NativeObjectReference method. /// public MemberReference WindowsRuntimeObjectget_NativeObjectReference => field ??= WindowsRuntimeObject .CreateMemberReference("get_NativeObjectReference"u8, MethodSignature.CreateInstance( returnType: WindowsRuntimeObjectReference.ToReferenceTypeSignature())); /// - /// Gets the for 's GetObjectReferenceForInterface method. + /// Gets the for 's GetObjectReferenceForInterface method. /// public MemberReference WindowsRuntimeObjectGetObjectReferenceForInterface => field ??= WindowsRuntimeObject .CreateMemberReference("GetObjectReferenceForInterface"u8, MethodSignature.CreateInstance( @@ -1463,7 +1493,7 @@ public InteropReferences( parameterTypes: [RuntimeTypeHandle.ToValueTypeSignature()])); /// - /// Gets the for WindowsRuntime.InteropServices.IWindowsRuntimeInterface.get_IID(). + /// Gets the for WindowsRuntime.InteropServices.IWindowsRuntimeInterface.get_IID(). /// public MemberReference IWindowsRuntimeInterfaceget_IID => field ??= IWindowsRuntimeInterface .CreateMemberReference("get_IID"u8, MethodSignature.CreateStatic( @@ -1640,6 +1670,16 @@ public InteropReferences( returnType: AbiType.ToValueTypeSignature(), parameterTypes: [Type.ToReferenceTypeSignature()])); + /// + /// Gets the for ABI.System.TypeMarshaller.ConvertToUnmanagedUnsafe. + /// + public MemberReference TypeMarshallerConvertToUnmanagedUnsafe => field ??= TypeMarshaller + .CreateMemberReference("ConvertToUnmanagedUnsafe"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + Type.ToReferenceTypeSignature(), + TypeReference.MakeByReferenceType()])); + /// /// Gets the for ABI.System.TypeMarshaller.Dispose. /// @@ -1752,6 +1792,27 @@ public InteropReferences( CreateComInterfaceFlags.ToValueTypeSignature(), Guid.ToValueTypeSignature().MakeByReferenceType()])); + /// + /// Gets the for WindowsRuntime.InteropServices.TypeReference.GetPinnableReference. + /// + public MemberReference TypeReferenceGetPinnableReference => field ??= TypeReference + .CreateMemberReference("GetPinnableReference"u8, MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Byte.MakeByReferenceType())); + + /// + /// Gets the for WindowsRuntime.InteropServices.TypeReference.ConvertToUnmanagedUnsafe. + /// + public MemberReference TypeReferenceConvertToUnmanagedUnsafe => field ??= TypeReference + .CreateMemberReference("ConvertToUnmanagedUnsafe"u8, MethodSignature.CreateInstance( + returnType: AbiType.ToValueTypeSignature())); + + /// + /// Gets the for WindowsRuntime.InteropServices.HStringReference.get_HString. + /// + public MemberReference HStringReferenceget_HString => field ??= HStringReference + .CreateMemberReference("get_HString"u8, MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Void.MakePointerType())); + /// /// Gets the for WindowsRuntime.InteropServices.HStringMarshaller.ConvertToUnmanaged. /// @@ -1760,6 +1821,17 @@ public InteropReferences( returnType: _corLibTypeFactory.Void.MakePointerType(), parameterTypes: [ReadOnlySpanChar])); + /// + /// Gets the for WindowsRuntime.InteropServices.HStringMarshaller.ConvertToUnmanagedUnsafe. + /// + public MemberReference HStringMarshallerConvertToUnmanagedUnsafe => field ??= HStringMarshaller + .CreateMemberReference("ConvertToUnmanagedUnsafe"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Void, + parameterTypes: [ + _corLibTypeFactory.Char.MakePointerType(), + Nullable1.MakeGenericValueType(_corLibTypeFactory.Int32), + HStringReference.ToValueTypeSignature().MakeByReferenceType()])); + /// /// Gets the for WindowsRuntime.InteropServices.HStringMarshaller.ConvertToManaged. /// @@ -1860,6 +1932,22 @@ public MemberReference EventRegistrationTokenTableRemoveEventHandler(TypeSignatu new GenericParameterSignature(GenericParameterType.Type, 0).MakeByReferenceType()])); } + /// + /// Gets the for the .ctor method of a given nullable value type. + /// + /// The input value type. + public MemberReference Nullable1_ctor(TypeSignature valueType) + { + // Get the special delegate constructor taking the target and function pointer. We leverage this to create + // a delegate instance that directly wraps our 'WindowsRuntimeObjectReference' object and 'Invoke' method. + return Nullable1 + .MakeGenericValueType(valueType) + .ToTypeDefOrRef() + .CreateConstructorReference( + corLibTypeFactory: _corLibTypeFactory, + parameterTypes: [new GenericParameterSignature(GenericParameterType.Type, 0)]); + } + /// /// Gets the for 's constructor (of an SZ array type). /// @@ -1872,7 +1960,7 @@ public MemberReference ReadOnlySpan1_ctor(SzArrayTypeSignature arrayType) } /// - /// Gets the for . + /// Gets the for . /// /// The type map group to use. public MemberReference TypeMapAttribute1_ctor_TrimTarget(TypeSignature typeMapGroup) @@ -1889,7 +1977,7 @@ public MemberReference TypeMapAttribute1_ctor_TrimTarget(TypeSignature typeMapGr } /// - /// Gets the for . + /// Gets the for . /// /// The type map group to use. public MemberReference TypeMapAssociationAttribute1_ctor(TypeSignature typeMapGroup) diff --git a/src/WinRT.Interop.Generator/References/WellKnownInterfaceIIDs.cs b/src/WinRT.Interop.Generator/References/WellKnownInterfaceIIDs.cs index e95112ff3..41745f641 100644 --- a/src/WinRT.Interop.Generator/References/WellKnownInterfaceIIDs.cs +++ b/src/WinRT.Interop.Generator/References/WellKnownInterfaceIIDs.cs @@ -192,6 +192,8 @@ _ when SignatureComparer.IgnoreVersion.Equals(interfaceType, interopReferences.V => new Guid("A1E9ACD7-E4DF-5A79-AEFA-DE07934AB0FB"), _ when SignatureComparer.IgnoreVersion.Equals(interfaceType, interopReferences.AsyncActionProgressHandler1) => new Guid("C261D8D0-71BA-5F38-A239-872342253A18"), + _ when SignatureComparer.IgnoreVersion.Equals(interfaceType, interopReferences.IMapChangedEventArgs1) + => new Guid("9939F4DF-050A-4C0F-AA60-77075F9C4777"), _ when SignatureComparer.IgnoreVersion.Equals(interfaceType, interopReferences.IVectorChangedEventArgs) => new Guid("575933DF-34FE-4480-AF15-07691F3D5D9B"),