Example #1
0
        public IEnumerable <StatementSyntax> 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)));

            // <managedIdentifier> = <marshallerType>.AllocateContainerForManagedElementsFinally(<nativeIdentifier>, <numElements>);
            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))
            }))))));
        }
        public IEnumerable <StatementSyntax> 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 <numElements> = <numElementExpression>
                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);
            }
        }
Example #3
0
        public StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCodeContext context)
        {
            string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context);
            string nativeSpanIdentifier  = MarshallerHelpers.GetNativeSpanIdentifier(info, context);
            string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context);

            // ReadOnlySpan<TUnmanagedElement> <nativeSpan> = <GetUnmanagedValuesSource>
            // Span<T> <managedSpan> = <GetManagedValuesDestination>
            // << unmarshal contents >>
            return(Block(
                       LocalDeclarationStatement(VariableDeclaration(
                                                     GenericName(
                                                         Identifier(TypeNames.System_ReadOnlySpan),
                                                         TypeArgumentList(SingletonSeparatedList(_unmanagedElementType))),
                                                     SingletonSeparatedList(
                                                         VariableDeclarator(
                                                             Identifier(nativeSpanIdentifier))
                                                         .WithInitializer(EqualsValueClause(
                                                                              GetUnmanagedValuesSource(info, context)))))),
                       LocalDeclarationStatement(VariableDeclaration(
                                                     GenericName(
                                                         Identifier(TypeNames.System_Span),
                                                         TypeArgumentList(SingletonSeparatedList(_elementInfo.ManagedType.Syntax))),
                                                     SingletonSeparatedList(
                                                         VariableDeclarator(
                                                             Identifier(managedSpanIdentifier))
                                                         .WithInitializer(EqualsValueClause(
                                                                              GetManagedValuesDestination(info, context)))))),
                       GenerateContentsMarshallingStatement(
                           info,
                           context,
                           IdentifierName(numElementsIdentifier),
                           StubCodeContext.Stage.UnmarshalCapture,
                           StubCodeContext.Stage.Unmarshal)));
        }
Example #4
0
 public IEnumerable <StatementSyntax> GenerateSetupStatements(TypePositionInfo info, StubCodeContext context)
 {
     yield return(LocalDeclarationStatement(
                      VariableDeclaration(
                          PredefinedType(Token(SyntaxKind.IntKeyword)),
                          SingletonSeparatedList(
                              VariableDeclarator(MarshallerHelpers.GetNumElementsIdentifier(info, context))))));
 }
Example #5
0
        public IEnumerable <StatementSyntax> 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))
            {
                // <numElements> = <GetManagedValuesSource.Length;
                yield return(ExpressionStatement(
                                 AssignmentExpression(
                                     SyntaxKind.SimpleAssignmentExpression,
                                     IdentifierName(numElementsIdentifier),
                                     MemberAccessExpression(
                                         SyntaxKind.SimpleMemberAccessExpression,
                                         GetManagedValuesSource(info, context),
                                         IdentifierName("Length")))));

                yield return(GenerateByValueOutUnmarshalStatement(info, context));
            }

            if (!_shape.HasFlag(MarshallerShape.ToManaged))
            {
                yield break;
            }
            else
            {
                // <numElements> = <numElementsExpression>;
                yield return(ExpressionStatement(
                                 AssignmentExpression(
                                     SyntaxKind.SimpleAssignmentExpression,
                                     IdentifierName(numElementsIdentifier),
                                     _numElementsExpression)));

                // <managedIdentifier> = <marshallerType>.AllocateContainerForManagedElements(<nativeIdentifier>, <numElements>);
                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))
                }))))));

                // ReadOnlySpan<TUnmanagedElement> <nativeSpan> = <marshallerType>.GetUnmanagedValuesSource(<nativeIdentifier>, <numElements>)
                // Span<T> <managedSpan> = <marshallerType>.GetManagedValuesDestination(<managedIdentifier>)
                // << unmarshal contents >>
                yield return(GenerateUnmarshalStatement(info, context));
            }
        }
        protected override InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context)
        {
            string marshaller            = StatefulValueMarshalling.GetMarshallerIdentifier(info, context);
            string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context);

            // <marshaller>.GetManagedValuesDestination(<numElements>)
            return(InvocationExpression(
                       MemberAccessExpression(
                           SyntaxKind.SimpleMemberAccessExpression,
                           IdentifierName(marshaller),
                           IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetManagedValuesDestination)),
                       ArgumentList(SingletonSeparatedList(
                                        Argument(IdentifierName(numElementsIdentifier))))));
        }
        public IEnumerable <StatementSyntax> GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context)
        {
            string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context);

            if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))
            {
                // int <numElements> = <GetManagedValuesSource>.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));
            }

            if (!_shape.HasFlag(MarshallerShape.ToManaged))
            {
                yield break;
            }
            else
            {
                // int <numElements> = <numElementsExpression>;
                yield return(LocalDeclarationStatement(
                                 VariableDeclaration(
                                     PredefinedType(Token(SyntaxKind.IntKeyword)),
                                     SingletonSeparatedList(
                                         VariableDeclarator(numElementsIdentifier)
                                         .WithInitializer(EqualsValueClause(_numElementsExpression))))));

                // ReadOnlySpan<TUnmanagedElement> <nativeSpan> = <marshaller>.GetUnmanagedValuesSource(<nativeIdentifier>, <numElements>)
                // Span<T> <managedSpan> = <marshaller>.GetManagedValuesDestination(<managedIdentifier>)
                // << unmarshal contents >>
                yield return(GenerateUnmarshalStatement(info, context));
            }

            foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, context))
            {
                yield return(statement);
            }
        }
Example #8
0
        protected override InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context)
        {
            string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context);
            string nativeIdentifier      = context.GetIdentifiers(info).native;

            // <marshallerType>.GetUnmanagedValuesSource(<nativeIdentifier>, <numElements>)
            return(InvocationExpression(
                       MemberAccessExpression(
                           SyntaxKind.SimpleMemberAccessExpression,
                           _marshallerTypeSyntax,
                           IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetUnmanagedValuesSource)),
                       ArgumentList(SeparatedList(new ArgumentSyntax[]
            {
                Argument(IdentifierName(nativeIdentifier)),
                Argument(IdentifierName(numElementsIdentifier))
            }))));
        }
Example #9
0
        public IEnumerable <StatementSyntax> 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)))
            {
                (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info);
                string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context);

                // <nativeIdentifier> = <marshallerType>.AllocateContainerForUnmanagedElements(<managedIdentifier>, out <numElements>);
                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))
                }))))));
            }

            if (!info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out)
            {
                yield return(GenerateByValueOutMarshalStatement(info, context));
            }
            else
            {
                yield return(GenerateMarshalStatement(info, context));
            }
        }
Example #10
0
        protected 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.
            // This code is ugly since we're now enforcing readonly safety with ReadOnlySpan for all other scenarios,
            // but this is an uncommon case so we don't want to design the API around enabling just it.
            string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context);
            string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context);

            // Span<TElement> <managedSpan> = MemoryMarshal.CreateSpan(ref Unsafe.AsRef(in <GetManagedValuesSource>.GetPinnableReference(), <numElements>));
            LocalDeclarationStatementSyntax managedValuesDeclaration = LocalDeclarationStatement(VariableDeclaration(
                                                                                                     GenericName(
                                                                                                         Identifier(TypeNames.System_Span),
                                                                                                         TypeArgumentList(
                                                                                                             SingletonSeparatedList(_elementInfo.ManagedType.Syntax))
                                                                                                         ),
                                                                                                     SingletonSeparatedList(VariableDeclarator(managedSpanIdentifier).WithInitializer(EqualsValueClause(
                                                                                                                                                                                          InvocationExpression(
                                                                                                                                                                                              MemberAccessExpression(
                                                                                                                                                                                                  SyntaxKind.SimpleMemberAccessExpression,
                                                                                                                                                                                                  ParseName(TypeNames.System_Runtime_InteropServices_MemoryMarshal),
                                                                                                                                                                                                  IdentifierName("CreateSpan")))
                                                                                                                                                                                          .WithArgumentList(
                                                                                                                                                                                              ArgumentList(
                                                                                                                                                                                                  SeparatedList(
                                                                                                                                                                                                      new[]
            {
                Argument(
                    InvocationExpression(
                        MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                               ParseName(TypeNames.System_Runtime_CompilerServices_Unsafe),
                                               IdentifierName("AsRef")),
                        ArgumentList(SingletonSeparatedList(
                                         Argument(
                                             InvocationExpression(
                                                 MemberAccessExpression(
                                                     SyntaxKind.SimpleMemberAccessExpression,
                                                     GetManagedValuesSource(info, context),
                                                     IdentifierName("GetPinnableReference")),
                                                 ArgumentList()))
                                         .WithRefKindKeyword(
                                             Token(SyntaxKind.InKeyword))))))
                .WithRefKindKeyword(
                    Token(SyntaxKind.RefKeyword)),
                Argument(
                    IdentifierName(numElementsIdentifier))
            }))))))));

            // Span<TUnmanagedElement> <nativeSpan> = <GetUnmanagedValuesDestination>
            string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context);
            LocalDeclarationStatementSyntax unmanagedValuesDeclaration = LocalDeclarationStatement(VariableDeclaration(
                                                                                                       GenericName(
                                                                                                           Identifier(TypeNames.System_Span),
                                                                                                           TypeArgumentList(SingletonSeparatedList(_unmanagedElementType))),
                                                                                                       SingletonSeparatedList(
                                                                                                           VariableDeclarator(
                                                                                                               Identifier(nativeSpanIdentifier))
                                                                                                           .WithInitializer(EqualsValueClause(
                                                                                                                                GetUnmanagedValuesDestination(info, context))))));

            return(Block(
                       managedValuesDeclaration,
                       unmanagedValuesDeclaration,
                       GenerateContentsMarshallingStatement(
                           info,
                           context,
                           IdentifierName(numElementsIdentifier),
                           StubCodeContext.Stage.UnmarshalCapture,
                           StubCodeContext.Stage.Unmarshal)));
        }
Example #11
0
        public IEnumerable <StatementSyntax> GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context)
        {
            if (MarshallerHelpers.CanUseCallerAllocatedBuffer(info, context))
            {
                return(GenerateCallerAllocatedBufferMarshalStatements());
            }

            return(_innerMarshaller.GenerateMarshalStatements(info, context));

            IEnumerable <StatementSyntax> GenerateCallerAllocatedBufferMarshalStatements()
            {
                string bufferIdentifier = context.GetAdditionalIdentifier(info, "buffer");

                // Span<bufferElementType> <bufferIdentifier> = stackalloc <bufferElementType>[<marshallerType>.BufferSize];
                yield return(LocalDeclarationStatement(
                                 VariableDeclaration(
                                     GenericName(
                                         Identifier(TypeNames.System_Span),
                                         TypeArgumentList(
                                             SingletonSeparatedList(_bufferElementType))),
                                     SingletonSeparatedList(
                                         VariableDeclarator(bufferIdentifier)
                                         .WithInitializer(EqualsValueClause(
                                                              StackAllocArrayCreationExpression(
                                                                  ArrayType(
                                                                      _bufferElementType,
                                                                      SingletonList(ArrayRankSpecifier(SingletonSeparatedList <ExpressionSyntax>(
                                                                                                           MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                                                                  _marshallerType,
                                                                                                                                  IdentifierName(ShapeMemberNames.BufferSize))
                                                                                                           )))))))))));

                (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info);

                if (_isLinearCollectionMarshalling)
                {
                    string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context);

                    // <nativeIdentifier> = <marshallerType>.AllocateContainerForUnmanagedElements(<managedIdentifier>, <bufferIdentifier>, out <numElements>);
                    yield return(ExpressionStatement(
                                     AssignmentExpression(
                                         SyntaxKind.SimpleAssignmentExpression,
                                         IdentifierName(nativeIdentifier),
                                         InvocationExpression(
                                             MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                    _marshallerType,
                                                                    IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForUnmanagedElements)),
                                             ArgumentList(SeparatedList(new ArgumentSyntax[]
                    {
                        Argument(IdentifierName(managedIdentifier)),
                        Argument(IdentifierName(bufferIdentifier)),
                        Argument(IdentifierName(numElementsIdentifier))
                        .WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword))
                    }))))));

                    // Linear collections have additional marshalling required using the inner marshaller
                    foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context))
                    {
                        yield return(statement);
                    }
                }
                else
                {
                    // <nativeIdentifier> = <marshallerType>.ConvertToUnmanaged(<managedIdentifier>, <nativeIdentifier>__buffer);
                    yield return(ExpressionStatement(
                                     AssignmentExpression(
                                         SyntaxKind.SimpleAssignmentExpression,
                                         IdentifierName(nativeIdentifier),
                                         InvocationExpression(
                                             MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                    _marshallerType,
                                                                    IdentifierName(ShapeMemberNames.Value.Stateless.ConvertToUnmanaged)),
                                             ArgumentList(SeparatedList(new ArgumentSyntax[]
                    {
                        Argument(IdentifierName(managedIdentifier)),
                        Argument(IdentifierName(bufferIdentifier))
                    }))))));
                }
            }
        }