From 5b8bebb4bb18a11839030efd564889ca789b301e Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 19 May 2023 10:44:51 -0700 Subject: [PATCH 1/3] Refactor our linear collection marshalling implementation Refactor the elements marshalling logic to split out space allocation and source/destination span construction from the elements marshalling logic. Pull out the element marshalling logic to a common base class and separate it out from the actual marshalling strategies. This refactoring is required to provide customization points to correctly fix #85795. I've validated that this change is a zero-diff change on all of the generated code for the LibraryImportGenerator integration tests. --- ...ributedMarshallingModelGeneratorFactory.cs | 43 ++- .../Marshalling/ElementsMarshalling.cs | 104 ++++--- .../StatefulMarshallingStrategy.cs | 204 +++---------- .../StatelessMarshallingStrategy.cs | 287 +++++------------- 4 files changed, 195 insertions(+), 443 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs index b06fcd8cf33474..03b90462ea3013 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs @@ -311,25 +311,19 @@ private IMarshallingGenerator CreateNativeCollectionMarshaller( marshallingStrategy = new StatefulCallerAllocatedBufferMarshalling(marshallingStrategy, marshallerTypeSyntax, bufferElementTypeSyntax); } - if (elementIsBlittable) - { - marshallingStrategy = new StatefulLinearCollectionBlittableElementsMarshalling(marshallingStrategy, marshallerData.Shape, marshallerData.CollectionElementType.Syntax, unmanagedElementType, numElementsExpression); - } - else - { - marshallingStrategy = new StatefulLinearCollectionNonBlittableElementsMarshalling(marshallingStrategy, marshallerData.Shape, unmanagedElementType, elementMarshaller, elementInfo, numElementsExpression); - } + IElementsMarshallingCollectionSource collectionSource = new StatefulLinearCollectionSource(); + IElementsMarshalling elementsMarshalling = CreateElementsMarshalling(marshallerData, elementInfo, elementMarshaller, unmanagedElementType, collectionSource); + + marshallingStrategy = new StatefulLinearCollectionMarshalling(marshallingStrategy, marshallerData.Shape, numElementsExpression, elementsMarshalling); } else { - if (elementIsBlittable) - { - marshallingStrategy = new StatelessLinearCollectionBlittableElementsMarshalling(marshallerTypeSyntax, nativeType, marshallerData.Shape, marshallerData.CollectionElementType.Syntax, unmanagedElementType, numElementsExpression); - } - else - { - marshallingStrategy = new StatelessLinearCollectionNonBlittableElementsMarshalling(marshallerTypeSyntax, nativeType, marshallerData.Shape, unmanagedElementType, elementMarshaller, elementInfo, numElementsExpression); - } + marshallingStrategy = new StatelessLinearCollectionSpaceAllocator(marshallerTypeSyntax, nativeType, marshallerData.Shape, numElementsExpression); + + IElementsMarshallingCollectionSource collectionSource = new StatelessLinearCollectionSource(marshallerTypeSyntax); + IElementsMarshalling elementsMarshalling = CreateElementsMarshalling(marshallerData, elementInfo, elementMarshaller, unmanagedElementType, collectionSource); + + marshallingStrategy = new StatelessLinearCollectionMarshalling(marshallingStrategy, elementsMarshalling, nativeType, marshallerData.Shape); if (marshallerData.Shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) { @@ -357,6 +351,23 @@ private IMarshallingGenerator CreateNativeCollectionMarshaller( return marshallingGenerator; } + private static IElementsMarshalling CreateElementsMarshalling(CustomTypeMarshallerData marshallerData, TypePositionInfo elementInfo, IMarshallingGenerator elementMarshaller, TypeSyntax unmanagedElementType, IElementsMarshallingCollectionSource collectionSource) + { + IElementsMarshalling elementsMarshalling; + + bool elementIsBlittable = elementMarshaller is BlittableMarshaller; + if (elementIsBlittable) + { + elementsMarshalling = new BlittableElementsMarshalling(marshallerData.CollectionElementType.Syntax, unmanagedElementType, collectionSource); + } + else + { + elementsMarshalling = new NonBlittableElementsMarshalling(unmanagedElementType, elementMarshaller, elementInfo, collectionSource); + } + + return elementsMarshalling; + } + private static bool ElementTypeIsSometimesNonBlittable(TypePositionInfo elementInfo) { if (elementInfo.MarshallingAttributeInfo is NoMarshallingInfo diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs index 253e51b983076d..ae87646a2908b4 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs @@ -11,26 +11,41 @@ namespace Microsoft.Interop { + internal interface IElementsMarshallingCollectionSource + { + StatementSyntax GetManagedValuesNumElementsAssignment(TypePositionInfo info, StubCodeContext context); + InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo info, StubCodeContext context); + InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, StubCodeContext context); + InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context); + InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context); + } + + internal interface IElementsMarshalling + { + StatementSyntax GenerateByValueOutMarshalStatement(TypePositionInfo info, StubCodeContext context); + StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCodeContext context); + StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo info, StubCodeContext context); + StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCodeContext context); + StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, StubCodeContext context); + } + /// /// Support for marshalling blittable elements /// - internal abstract class BlittableElementsMarshalling + internal sealed class BlittableElementsMarshalling : IElementsMarshalling { private readonly TypeSyntax _managedElementType; private readonly TypeSyntax _unmanagedElementType; + private readonly IElementsMarshallingCollectionSource _collectionSource; - public BlittableElementsMarshalling(TypeSyntax managedElementType, TypeSyntax unmanagedElementType) + public BlittableElementsMarshalling(TypeSyntax managedElementType, TypeSyntax unmanagedElementType, IElementsMarshallingCollectionSource collectionSource) { _managedElementType = managedElementType; _unmanagedElementType = unmanagedElementType; + _collectionSource = collectionSource; } - protected abstract InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo info, StubCodeContext context); - protected abstract InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, StubCodeContext context); - protected abstract InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context); - protected abstract InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context); - - protected StatementSyntax GenerateByValueOutMarshalStatement(TypePositionInfo info, StubCodeContext context) + public StatementSyntax GenerateByValueOutMarshalStatement(TypePositionInfo info, StubCodeContext context) { // If the parameter is marshalled by-value [Out], then we don't marshal the contents of the collection. // We do clear the span, so that if the invoke target doesn't fill it, we aren't left with undefined content. @@ -39,28 +54,28 @@ protected StatementSyntax GenerateByValueOutMarshalStatement(TypePositionInfo in InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - GetUnmanagedValuesDestination(info, context), + _collectionSource.GetUnmanagedValuesDestination(info, context), IdentifierName("Clear")))); } - protected StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCodeContext context) + public StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCodeContext context) { - ExpressionSyntax destination = CastToManagedIfNecessary(GetUnmanagedValuesDestination(info, context)); + ExpressionSyntax destination = CastToManagedIfNecessary(_collectionSource.GetUnmanagedValuesDestination(info, context)); // .CopyTo(); return ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - GetManagedValuesSource(info, context), + _collectionSource.GetManagedValuesSource(info, context), IdentifierName("CopyTo"))) .AddArgumentListArguments( Argument(destination))); } - protected StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo info, StubCodeContext context) + public StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo info, StubCodeContext context) { - ExpressionSyntax source = CastToManagedIfNecessary(GetUnmanagedValuesDestination(info, context)); + ExpressionSyntax source = CastToManagedIfNecessary(_collectionSource.GetUnmanagedValuesDestination(info, context)); // MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(), .Length) ExpressionSyntax destination = InvocationExpression( @@ -77,12 +92,12 @@ protected StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo ParseName(TypeNames.System_Runtime_InteropServices_MemoryMarshal), IdentifierName("GetReference")), ArgumentList(SingletonSeparatedList( - Argument(GetManagedValuesSource(info, context)))))) + Argument(_collectionSource.GetManagedValuesSource(info, context)))))) .WithRefKindKeyword( Token(SyntaxKind.RefKeyword)), Argument( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - GetManagedValuesSource(info, context), + _collectionSource.GetManagedValuesSource(info, context), IdentifierName("Length"))) }))); @@ -99,7 +114,7 @@ protected StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo public StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCodeContext context) { - ExpressionSyntax source = CastToManagedIfNecessary(GetUnmanagedValuesSource(info, context)); + ExpressionSyntax source = CastToManagedIfNecessary(_collectionSource.GetUnmanagedValuesSource(info, context)); // .CopyTo(); return ExpressionStatement( @@ -109,7 +124,7 @@ public StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCod source, IdentifierName("CopyTo"))) .AddArgumentListArguments( - Argument(GetManagedValuesDestination(info, context)))); + Argument(_collectionSource.GetManagedValuesDestination(info, context)))); } private ExpressionSyntax CastToManagedIfNecessary(ExpressionSyntax expression) @@ -134,33 +149,33 @@ private ExpressionSyntax CastToManagedIfNecessary(ExpressionSyntax expression) ArgumentList(SingletonSeparatedList( Argument(expression)))); } + + public StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, StubCodeContext context) => EmptyStatement(); } /// /// Support for marshalling non-blittable elements /// - internal abstract class NonBlittableElementsMarshalling + internal sealed class NonBlittableElementsMarshalling : IElementsMarshalling { private readonly TypeSyntax _unmanagedElementType; private readonly IMarshallingGenerator _elementMarshaller; private readonly TypePositionInfo _elementInfo; + private readonly IElementsMarshallingCollectionSource _collectionSource; public NonBlittableElementsMarshalling( TypeSyntax unmanagedElementType, IMarshallingGenerator elementMarshaller, - TypePositionInfo elementInfo) + TypePositionInfo elementInfo, + IElementsMarshallingCollectionSource collectionSource) { _unmanagedElementType = unmanagedElementType; _elementMarshaller = elementMarshaller; _elementInfo = elementInfo; + _collectionSource = collectionSource; } - protected abstract InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo info, StubCodeContext context); - protected abstract InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, StubCodeContext context); - protected abstract InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context); - protected abstract InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context); - - protected StatementSyntax GenerateByValueOutMarshalStatement(TypePositionInfo info, StubCodeContext context) + public StatementSyntax GenerateByValueOutMarshalStatement(TypePositionInfo info, StubCodeContext context) { // If the parameter is marshalled by-value [Out], then we don't marshal the contents of the collection. // We do clear the span, so that if the invoke target doesn't fill it, we aren't left with undefined content. @@ -169,11 +184,11 @@ protected StatementSyntax GenerateByValueOutMarshalStatement(TypePositionInfo in InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - GetUnmanagedValuesDestination(info, context), + _collectionSource.GetUnmanagedValuesDestination(info, context), IdentifierName("Clear")))); } - protected StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCodeContext context) + public StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCodeContext context) { string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context); string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); @@ -189,7 +204,7 @@ protected StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCo SingletonSeparatedList( VariableDeclarator(Identifier(managedSpanIdentifier)) .WithInitializer(EqualsValueClause( - GetManagedValuesSource(info, context)))))), + _collectionSource.GetManagedValuesSource(info, context)))))), LocalDeclarationStatement(VariableDeclaration( GenericName( Identifier(TypeNames.System_Span), @@ -198,7 +213,7 @@ protected StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCo VariableDeclarator( Identifier(nativeSpanIdentifier)) .WithInitializer(EqualsValueClause( - GetUnmanagedValuesDestination(info, context)))))), + _collectionSource.GetUnmanagedValuesDestination(info, context)))))), GenerateContentsMarshallingStatement( info, context, @@ -226,7 +241,7 @@ public StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCod VariableDeclarator( Identifier(nativeSpanIdentifier)) .WithInitializer(EqualsValueClause( - GetUnmanagedValuesSource(info, context)))))), + _collectionSource.GetUnmanagedValuesSource(info, context)))))), LocalDeclarationStatement(VariableDeclaration( GenericName( Identifier(TypeNames.System_Span), @@ -235,7 +250,7 @@ public StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCod VariableDeclarator( Identifier(managedSpanIdentifier)) .WithInitializer(EqualsValueClause( - GetManagedValuesDestination(info, context)))))), + _collectionSource.GetManagedValuesDestination(info, context)))))), GenerateContentsMarshallingStatement( info, context, @@ -244,7 +259,7 @@ public StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCod StubCodeContext.Stage.Unmarshal)); } - protected StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo info, StubCodeContext context) + public StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo info, StubCodeContext context) { // Use ManagedSource and NativeDestination spans for by-value marshalling since we're just marshalling back the contents, // not the array itself. @@ -253,6 +268,8 @@ protected StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context); + var setNumElements = _collectionSource.GetManagedValuesNumElementsAssignment(info, context); + // Span = MemoryMarshal.CreateSpan(ref Unsafe.AsRef(in .GetPinnableReference(), )); LocalDeclarationStatementSyntax managedValuesDeclaration = LocalDeclarationStatement(VariableDeclaration( GenericName( @@ -281,7 +298,7 @@ protected StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - GetManagedValuesSource(info, context), + _collectionSource.GetManagedValuesSource(info, context), IdentifierName("GetPinnableReference")), ArgumentList())) .WithRefKindKeyword( @@ -302,20 +319,21 @@ protected StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo VariableDeclarator( Identifier(nativeSpanIdentifier)) .WithInitializer(EqualsValueClause( - GetUnmanagedValuesDestination(info, context)))))); + _collectionSource.GetUnmanagedValuesDestination(info, context)))))); return Block( + setNumElements, managedValuesDeclaration, unmanagedValuesDeclaration, GenerateContentsMarshallingStatement( - info, - context, - IdentifierName(numElementsIdentifier), - StubCodeContext.Stage.UnmarshalCapture, - StubCodeContext.Stage.Unmarshal)); + info, + context, + IdentifierName(numElementsIdentifier), + StubCodeContext.Stage.UnmarshalCapture, + StubCodeContext.Stage.Unmarshal)); } - protected StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, StubCodeContext context) + public StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, StubCodeContext context) { string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); StatementSyntax contentsCleanupStatements = GenerateContentsMarshallingStatement(info, context, @@ -338,11 +356,11 @@ protected StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, VariableDeclarator( Identifier(nativeSpanIdentifier)) .WithInitializer(EqualsValueClause( - GetUnmanagedValuesDestination(info, context)))))), + _collectionSource.GetUnmanagedValuesDestination(info, context)))))), contentsCleanupStatements); } - protected StatementSyntax GenerateContentsMarshallingStatement( + private StatementSyntax GenerateContentsMarshallingStatement( TypePositionInfo info, StubCodeContext context, ExpressionSyntax lengthExpression, diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs index 8aa9ce5f340b73..735def6110bc59 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs @@ -288,85 +288,9 @@ public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); } - /// - /// Marshaller that enables support for marshalling blittable elements of a collection via a native type that implements the LinearCollection marshalling spec. - /// - internal sealed class StatefulLinearCollectionBlittableElementsMarshalling : BlittableElementsMarshalling, ICustomTypeMarshallingStrategy + internal sealed class StatefulLinearCollectionSource : IElementsMarshallingCollectionSource { - private readonly ICustomTypeMarshallingStrategy _innerMarshaller; - private readonly MarshallerShape _shape; - private readonly ExpressionSyntax _numElementsExpression; - - public StatefulLinearCollectionBlittableElementsMarshalling( - ICustomTypeMarshallingStrategy innerMarshaller, MarshallerShape shape, TypeSyntax managedElementType, TypeSyntax unmanagedElementType, ExpressionSyntax numElementsExpression) - : base (managedElementType, unmanagedElementType) - { - _innerMarshaller = innerMarshaller; - _shape = shape; - _numElementsExpression = numElementsExpression; - } - - public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _innerMarshaller.AsNativeType(info); - public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateCleanupStatements(info, context); - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context); - - public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) - { - if (!_shape.HasFlag(MarshallerShape.ToUnmanaged) && !_shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) - yield break; - - foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context)) - { - yield return statement; - } - - if (!info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out) - { - yield return GenerateByValueOutMarshalStatement(info, context); - yield break; - } - - yield return GenerateMarshalStatement(info, context); - } - - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinnedMarshalStatements(info, context); - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinStatements(info, context); - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateSetupStatements(info, context); - public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context); - - public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) - { - if (!_shape.HasFlag(MarshallerShape.ToManaged)) - yield break; - - if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) - { - yield return GenerateByValueOutUnmarshalStatement(info, context); - } - else - { - // int = - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - yield return LocalDeclarationStatement( - VariableDeclaration( - PredefinedType(Token(SyntaxKind.IntKeyword)), - SingletonSeparatedList( - VariableDeclarator(numElementsIdentifier) - .WithInitializer(EqualsValueClause(_numElementsExpression))))); - - yield return GenerateUnmarshalStatement(info, context); - } - - foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, context)) - { - yield return statement; - } - } - - public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.UsesNativeIdentifier(info, context); - - protected override InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo info, StubCodeContext context) { string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); @@ -375,11 +299,11 @@ protected override InvocationExpressionSyntax GetUnmanagedValuesDestination(Type MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(marshaller), - IdentifierName(ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesDestination)), + IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetUnmanagedValuesDestination)), ArgumentList()); } - protected override InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, StubCodeContext context) { string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); @@ -392,7 +316,7 @@ protected override InvocationExpressionSyntax GetManagedValuesSource(TypePositio ArgumentList()); } - protected override InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context) { string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); @@ -407,7 +331,7 @@ protected override InvocationExpressionSyntax GetUnmanagedValuesSource(TypePosit Argument(IdentifierName(numElementsIdentifier))))); } - protected override InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context) { string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); @@ -417,39 +341,54 @@ protected override InvocationExpressionSyntax GetManagedValuesDestination(TypePo MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(marshaller), - IdentifierName(ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesDestination)), + IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetManagedValuesDestination)), ArgumentList(SingletonSeparatedList( Argument(IdentifierName(numElementsIdentifier))))); } + + public StatementSyntax GetManagedValuesNumElementsAssignment(TypePositionInfo info, StubCodeContext context) + { + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + // int = .Length; + return LocalDeclarationStatement( + VariableDeclaration( + PredefinedType(Token(SyntaxKind.IntKeyword)), + SingletonSeparatedList( + VariableDeclarator(numElementsIdentifier) + .WithInitializer(EqualsValueClause( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + GetManagedValuesSource(info, context), + IdentifierName("Length"))))))); + } } /// - /// Marshaller that enables support for marshalling non-blittable elements of a collection via a native type that implements the LinearCollection marshalling spec. + /// Marshaller that enables support for marshalling elements of a collection via a native type that implements the LinearCollection marshalling spec. /// - internal sealed class StatefulLinearCollectionNonBlittableElementsMarshalling : NonBlittableElementsMarshalling, ICustomTypeMarshallingStrategy + internal sealed class StatefulLinearCollectionMarshalling : ICustomTypeMarshallingStrategy { private readonly ICustomTypeMarshallingStrategy _innerMarshaller; private readonly MarshallerShape _shape; private readonly ExpressionSyntax _numElementsExpression; + private readonly IElementsMarshalling _elementsMarshalling; - public StatefulLinearCollectionNonBlittableElementsMarshalling( + public StatefulLinearCollectionMarshalling( ICustomTypeMarshallingStrategy innerMarshaller, MarshallerShape shape, - TypeSyntax unmanagedElementType, - IMarshallingGenerator elementMarshaller, - TypePositionInfo elementInfo, - ExpressionSyntax numElementsExpression) - : base (unmanagedElementType, elementMarshaller, elementInfo) + ExpressionSyntax numElementsExpression, + IElementsMarshalling elementsMarshalling) { _innerMarshaller = innerMarshaller; _shape = shape; _numElementsExpression = numElementsExpression; + _elementsMarshalling = elementsMarshalling; } public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _innerMarshaller.AsNativeType(info); public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context) { - StatementSyntax elementCleanup = GenerateElementCleanupStatement(info, context); + StatementSyntax elementCleanup = _elementsMarshalling.GenerateElementCleanupStatement(info, context); if (!elementCleanup.IsKind(SyntaxKind.EmptyStatement)) { @@ -482,14 +421,11 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i if (!info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out) { - yield return GenerateByValueOutMarshalStatement(info, context); + yield return _elementsMarshalling.GenerateByValueOutMarshalStatement(info, context); yield break; } - // ReadOnlySpan = .GetManagedValuesSource() - // Span = .GetUnmanagedValuesDestination() - // << marshal contents >> - yield return GenerateMarshalStatement(info, context); + yield return _elementsMarshalling.GenerateMarshalStatement(info, context); } public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); @@ -503,18 +439,7 @@ public IEnumerable GenerateUnmarshalStatements(TypePositionInfo if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) { - // int = .Length; - yield return LocalDeclarationStatement( - VariableDeclaration( - PredefinedType(Token(SyntaxKind.IntKeyword)), - SingletonSeparatedList( - VariableDeclarator(numElementsIdentifier) - .WithInitializer(EqualsValueClause( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - GetManagedValuesSource(info, context), - IdentifierName("Length"))))))); - yield return GenerateByValueOutUnmarshalStatement(info, context); + yield return _elementsMarshalling.GenerateByValueOutUnmarshalStatement(info, context); } if (!_shape.HasFlag(MarshallerShape.ToManaged)) @@ -531,10 +456,7 @@ public IEnumerable GenerateUnmarshalStatements(TypePositionInfo VariableDeclarator(numElementsIdentifier) .WithInitializer(EqualsValueClause(_numElementsExpression))))); - // ReadOnlySpan = .GetUnmanagedValuesSource(, ) - // Span = .GetManagedValuesDestination() - // << unmarshal contents >> - yield return GenerateUnmarshalStatement(info, context); + yield return _elementsMarshalling.GenerateUnmarshalStatement(info, context); } foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, context)) @@ -546,61 +468,5 @@ public IEnumerable GenerateUnmarshalStatements(TypePositionInfo public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context); public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; - - protected override InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo info, StubCodeContext context) - { - string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); - - // .GetUnmanagedValuesDestination() - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(marshaller), - IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetUnmanagedValuesDestination)), - ArgumentList()); - } - - protected override InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, StubCodeContext context) - { - string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); - - // .GetManagedValuesSource() - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(marshaller), - IdentifierName(ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesSource)), - ArgumentList()); - } - - protected override InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context) - { - string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - - // .GetUnmanagedValuesSource() - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(marshaller), - IdentifierName(ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesSource)), - ArgumentList(SingletonSeparatedList( - Argument(IdentifierName(numElementsIdentifier))))); - } - - protected override InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context) - { - string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - - // .GetManagedValuesDestination() - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(marshaller), - IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetManagedValuesDestination)), - ArgumentList(SingletonSeparatedList( - Argument(IdentifierName(numElementsIdentifier))))); - } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs index e17f1c02647375..666e6434af9d93 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs @@ -296,17 +296,16 @@ public IEnumerable GenerateCleanupStatements(TypePositionInfo i } /// - /// Marshaller that enables support for marshalling blittable elements of a collection via a native type that implements the LinearCollection marshalling spec. + /// Marshaller type that enables allocating space for marshalling a linear collection using a marshaller that implements the LinearCollection marshalling spec. /// - internal sealed class StatelessLinearCollectionBlittableElementsMarshalling : BlittableElementsMarshalling, ICustomTypeMarshallingStrategy + internal sealed class StatelessLinearCollectionSpaceAllocator : ICustomTypeMarshallingStrategy { private readonly TypeSyntax _marshallerTypeSyntax; private readonly ManagedTypeInfo _unmanagedType; private readonly MarshallerShape _shape; private readonly ExpressionSyntax _numElementsExpression; - public StatelessLinearCollectionBlittableElementsMarshalling(TypeSyntax marshallerTypeSyntax, ManagedTypeInfo unmanagedType, MarshallerShape shape, TypeSyntax managedElementType, TypeSyntax unmanagedElementType, ExpressionSyntax numElementsExpression) - : base(managedElementType, unmanagedElementType) + public StatelessLinearCollectionSpaceAllocator(TypeSyntax marshallerTypeSyntax, ManagedTypeInfo unmanagedType, MarshallerShape shape, ExpressionSyntax numElementsExpression) { _marshallerTypeSyntax = marshallerTypeSyntax; _unmanagedType = unmanagedType; @@ -346,8 +345,8 @@ public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePo IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForManagedElementsFinally)), ArgumentList(SeparatedList(new ArgumentSyntax[] { - Argument(IdentifierName(nativeIdentifier)), - Argument(IdentifierName(numElementsIdentifier)) + Argument(IdentifierName(nativeIdentifier)), + Argument(IdentifierName(numElementsIdentifier)) }))))); } @@ -374,20 +373,11 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForUnmanagedElements)), ArgumentList(SeparatedList(new ArgumentSyntax[] { - Argument(IdentifierName(managedIdentifier)), - Argument(IdentifierName(numElementsIdentifier)) - .WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)) + Argument(IdentifierName(managedIdentifier)), + Argument(IdentifierName(numElementsIdentifier)) + .WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)) }))))); } - - if (!info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out) - { - yield return GenerateByValueOutMarshalStatement(info, context); - } - else - { - yield return GenerateMarshalStatement(info, context); - } } public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); @@ -416,7 +406,6 @@ public IEnumerable GenerateUnmarshalStatements(TypePositionInfo { if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) { - yield return GenerateByValueOutUnmarshalStatement(info, context); yield break; } @@ -443,16 +432,24 @@ public IEnumerable GenerateUnmarshalStatements(TypePositionInfo IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForManagedElements)), ArgumentList(SeparatedList(new ArgumentSyntax[] { - Argument(IdentifierName(nativeIdentifier)), - Argument(IdentifierName(numElementsIdentifier)) + Argument(IdentifierName(nativeIdentifier)), + Argument(IdentifierName(numElementsIdentifier)) }))))); - - yield return GenerateUnmarshalStatement(info, context); } public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; + } - protected override InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo info, StubCodeContext context) + internal sealed class StatelessLinearCollectionSource : IElementsMarshallingCollectionSource + { + private readonly TypeSyntax _marshallerTypeSyntax; + + public StatelessLinearCollectionSource(TypeSyntax marshallerTypeSyntax) + { + _marshallerTypeSyntax = marshallerTypeSyntax; + } + + public InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo info, StubCodeContext context) { string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); string nativeIdentifier = context.GetIdentifiers(info).native; @@ -470,7 +467,7 @@ protected override InvocationExpressionSyntax GetUnmanagedValuesDestination(Type }))); } - protected override InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, StubCodeContext context) { // .GetManagedValuesSource() string managedIdentifier = context.GetIdentifiers(info).managed; @@ -483,7 +480,7 @@ protected override InvocationExpressionSyntax GetManagedValuesSource(TypePositio Argument(IdentifierName(managedIdentifier))))); } - protected override InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context) { string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); string nativeIdentifier = context.GetIdentifiers(info).native; @@ -501,7 +498,7 @@ protected override InvocationExpressionSyntax GetUnmanagedValuesSource(TypePosit }))); } - protected override InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context) { string managedIdentifier = context.GetIdentifiers(info).managed; @@ -513,154 +510,96 @@ protected override InvocationExpressionSyntax GetManagedValuesDestination(TypePo IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetManagedValuesDestination)), ArgumentList(SingletonSeparatedList(Argument(IdentifierName(managedIdentifier))))); } + + public StatementSyntax GetManagedValuesNumElementsAssignment(TypePositionInfo info, StubCodeContext context) + { + var numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + // = .Length; + return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(numElementsIdentifier), + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + GetManagedValuesSource(info, context), + IdentifierName("Length")))); + } } /// - /// Marshaller that enables support for marshalling non-blittable elements of a collection via a native type that implements the LinearCollection marshalling spec. + /// Marshaller that enables support for marshalling elements of a collection via a marshaller type that implements the contiguous collection marshalling shape. /// - internal sealed class StatelessLinearCollectionNonBlittableElementsMarshalling : NonBlittableElementsMarshalling, ICustomTypeMarshallingStrategy + internal sealed class StatelessLinearCollectionMarshalling : ICustomTypeMarshallingStrategy { - private readonly TypeSyntax _marshallerTypeSyntax; + private readonly ICustomTypeMarshallingStrategy _spaceMarshallingStrategy; + private readonly IElementsMarshalling _elementsMarshalling; private readonly ManagedTypeInfo _unmanagedType; private readonly MarshallerShape _shape; - private readonly ExpressionSyntax _numElementsExpression; - public StatelessLinearCollectionNonBlittableElementsMarshalling( - TypeSyntax marshallerTypeSyntax, + public StatelessLinearCollectionMarshalling( + ICustomTypeMarshallingStrategy spaceMarshallingStrategy, + IElementsMarshalling elementsMarshalling, ManagedTypeInfo unmanagedType, - MarshallerShape shape, - TypeSyntax unmanagedElementType, - IMarshallingGenerator elementMarshaller, - TypePositionInfo elementInfo, - ExpressionSyntax numElementsExpression) - : base(unmanagedElementType, elementMarshaller, elementInfo) + MarshallerShape shape) { - _marshallerTypeSyntax = marshallerTypeSyntax; + _spaceMarshallingStrategy = spaceMarshallingStrategy; + _elementsMarshalling = elementsMarshalling; _unmanagedType = unmanagedType; _shape = shape; - _numElementsExpression = numElementsExpression; } public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _unmanagedType; public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context) { - StatementSyntax elementCleanup = GenerateElementCleanupStatement(info, context); + StatementSyntax elementCleanup = _elementsMarshalling.GenerateElementCleanupStatement(info, context); if (!elementCleanup.IsKind(SyntaxKind.EmptyStatement)) { yield return elementCleanup; } - } - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) - { - if (!_shape.HasFlag(MarshallerShape.GuaranteedUnmarshal)) - yield break; - - (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - - yield return ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - IdentifierName(numElementsIdentifier), - _numElementsExpression)); - - // = .AllocateContainerForManagedElementsFinally(, ); - yield return ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - IdentifierName(managedIdentifier), - InvocationExpression( - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, - IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForManagedElementsFinally)), - ArgumentList(SeparatedList(new ArgumentSyntax[] - { - Argument(IdentifierName(nativeIdentifier)), - Argument(IdentifierName(numElementsIdentifier)) - }))))); + foreach (var statement in _spaceMarshallingStrategy.GenerateCleanupStatements(info, context)) + { + yield return statement; + } } + public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _spaceMarshallingStrategy.GenerateGuaranteedUnmarshalStatements(info, context); + public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) { - if (!_shape.HasFlag(MarshallerShape.ToUnmanaged) && !_shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) - yield break; - - if (_shape.HasFlag(MarshallerShape.ToUnmanaged) - && !(_shape.HasFlag(MarshallerShape.CallerAllocatedBuffer) && MarshallerHelpers.CanUseCallerAllocatedBuffer(info, context))) + foreach (var statement in _spaceMarshallingStrategy.GenerateMarshalStatements(info, context)) { - (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - - // = .AllocateContainerForUnmanagedElements(, out ); - yield return ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - IdentifierName(nativeIdentifier), - InvocationExpression( - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, - IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForUnmanagedElements)), - ArgumentList(SeparatedList(new ArgumentSyntax[] - { - Argument(IdentifierName(managedIdentifier)), - Argument(IdentifierName(numElementsIdentifier)) - .WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)) - }))))); + yield return statement; } + if (!_shape.HasFlag(MarshallerShape.ToUnmanaged) && !_shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) + yield break; if (!info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out) { - yield return GenerateByValueOutMarshalStatement(info, context); + yield return _elementsMarshalling.GenerateByValueOutMarshalStatement(info, context); } else { - yield return GenerateMarshalStatement(info, context); + yield return _elementsMarshalling.GenerateMarshalStatement(info, context); } } - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); + public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _spaceMarshallingStrategy.GenerateNotifyForSuccessfulInvokeStatements(info, context); + public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _spaceMarshallingStrategy.GeneratePinnedMarshalStatements(info, context); + public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _spaceMarshallingStrategy.GeneratePinStatements(info, context); - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) - { - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - yield return LocalDeclarationStatement( - VariableDeclaration( - PredefinedType(Token(SyntaxKind.IntKeyword)), - SingletonSeparatedList( - VariableDeclarator(numElementsIdentifier)))); - // Use the numElements local to ensure the compiler doesn't give errors for using an uninitialized variable. - // The value will never be used unless it has been initialized, so this is safe. - yield return MarshallerHelpers.SkipInitOrDefaultInit( - new TypePositionInfo(SpecialTypeInfo.Int32, NoMarshallingInfo.Instance) - { - InstanceIdentifier = numElementsIdentifier - }, context); - } + public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) => _spaceMarshallingStrategy.GenerateSetupStatements(info, context); public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) { - (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) { - // = GenerateUnmarshalStatements(TypePositionInfo } else { - // = ; - yield return ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - IdentifierName(numElementsIdentifier), - _numElementsExpression)); - - // = .AllocateContainerForManagedElements(, ); - yield return ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - IdentifierName(managedIdentifier), - InvocationExpression( - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, - IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForManagedElements)), - ArgumentList(SeparatedList(new ArgumentSyntax[] - { - Argument(IdentifierName(nativeIdentifier)), - Argument(IdentifierName(numElementsIdentifier)) - }))))); + foreach (var statement in _spaceMarshallingStrategy.GenerateUnmarshalStatements(info, context)) + { + yield return statement; + } - // ReadOnlySpan = .GetUnmanagedValuesSource(, ) - // Span = .GetManagedValuesDestination() - // << unmarshal contents >> - yield return GenerateUnmarshalStatement(info, context); + yield return _elementsMarshalling.GenerateUnmarshalStatement(info, context); } } public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; - - protected override InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo info, StubCodeContext context) - { - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - string nativeIdentifier = context.GetIdentifiers(info).native; - - // .GetUnmanagedValuesDestination(, ) - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, - IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetUnmanagedValuesDestination)), - ArgumentList(SeparatedList(new ArgumentSyntax[] - { - Argument(IdentifierName(nativeIdentifier)), - Argument(IdentifierName(numElementsIdentifier)), - }))); - } - - protected override InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, StubCodeContext context) - { - // .GetManagedValuesSource() - string managedIdentifier = context.GetIdentifiers(info).managed; - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, - IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetManagedValuesSource)), - ArgumentList(SingletonSeparatedList( - Argument(IdentifierName(managedIdentifier))))); - } - - protected override InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context) - { - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - string nativeIdentifier = context.GetIdentifiers(info).native; - - // .GetUnmanagedValuesSource(, ) - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, - IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetUnmanagedValuesSource)), - ArgumentList(SeparatedList(new ArgumentSyntax[] - { - Argument(IdentifierName(nativeIdentifier)), - Argument(IdentifierName(numElementsIdentifier)) - }))); - } - - protected override InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context) - { - string managedIdentifier = context.GetIdentifiers(info).managed; - - // .GetManagedValuesDestination() - return InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, - IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetManagedValuesDestination)), - ArgumentList(SingletonSeparatedList(Argument(IdentifierName(managedIdentifier))))); - } } } From 747ccb036316ad7fca6177301246fc0491a91680 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 19 May 2023 11:34:46 -0700 Subject: [PATCH 2/3] Update src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs --- .../Marshalling/StatefulMarshallingStrategy.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs index 735def6110bc59..0e7038db58cd9e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs @@ -299,7 +299,7 @@ public InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(marshaller), - IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetUnmanagedValuesDestination)), + IdentifierName(ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesDestination)), ArgumentList()); } From 05bc732bff4628a538fbcdf847f085851056fae8 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 19 May 2023 13:51:22 -0700 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Jackson Schuster <36744439+jtschuster@users.noreply.github.com> --- .../Marshalling/ElementsMarshalling.cs | 10 +++++----- .../Marshalling/StatefulMarshallingStrategy.cs | 2 +- .../Marshalling/StatelessMarshallingStrategy.cs | 14 +++++++------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs index ae87646a2908b4..02d0b6bf70a54c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs @@ -326,11 +326,11 @@ public StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo inf managedValuesDeclaration, unmanagedValuesDeclaration, GenerateContentsMarshallingStatement( - info, - context, - IdentifierName(numElementsIdentifier), - StubCodeContext.Stage.UnmarshalCapture, - StubCodeContext.Stage.Unmarshal)); + info, + context, + IdentifierName(numElementsIdentifier), + StubCodeContext.Stage.UnmarshalCapture, + StubCodeContext.Stage.Unmarshal)); } public StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, StubCodeContext context) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs index 0e7038db58cd9e..8c8aa0db66ccb7 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs @@ -341,7 +341,7 @@ public InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo i MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(marshaller), - IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetManagedValuesDestination)), + IdentifierName(ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesDestination)), ArgumentList(SingletonSeparatedList( Argument(IdentifierName(numElementsIdentifier))))); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs index 666e6434af9d93..94ea82a31b6d0a 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs @@ -345,8 +345,8 @@ public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePo IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForManagedElementsFinally)), ArgumentList(SeparatedList(new ArgumentSyntax[] { - Argument(IdentifierName(nativeIdentifier)), - Argument(IdentifierName(numElementsIdentifier)) + Argument(IdentifierName(nativeIdentifier)), + Argument(IdentifierName(numElementsIdentifier)) }))))); } @@ -373,9 +373,9 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForUnmanagedElements)), ArgumentList(SeparatedList(new ArgumentSyntax[] { - Argument(IdentifierName(managedIdentifier)), - Argument(IdentifierName(numElementsIdentifier)) - .WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)) + Argument(IdentifierName(managedIdentifier)), + Argument(IdentifierName(numElementsIdentifier)) + .WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword)) }))))); } } @@ -432,8 +432,8 @@ public IEnumerable GenerateUnmarshalStatements(TypePositionInfo IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForManagedElements)), ArgumentList(SeparatedList(new ArgumentSyntax[] { - Argument(IdentifierName(nativeIdentifier)), - Argument(IdentifierName(numElementsIdentifier)) + Argument(IdentifierName(nativeIdentifier)), + Argument(IdentifierName(numElementsIdentifier)) }))))); }