public IEnumerable <StatementSyntax> GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context)
        {
            if (MarshallerHelpers.CanUseCallerAllocatedBuffer(info, context))
            {
                return(GenerateCallerAllocatedBufferMarshalStatements());
            }

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

            IEnumerable <StatementSyntax> GenerateCallerAllocatedBufferMarshalStatements()
            {
                // TODO: Update once we can consume the scoped keword. We should be able to simplify this once we get that API.
                string stackPtrIdentifier = context.GetAdditionalIdentifier(info, "stackptr");

                // <bufferElementType>* <managedIdentifier>__stackptr = stackalloc <bufferElementType>[<_bufferSize>];
                yield return(LocalDeclarationStatement(
                                 VariableDeclaration(
                                     PointerType(_bufferElementType),
                                     SingletonSeparatedList(
                                         VariableDeclarator(stackPtrIdentifier)
                                         .WithInitializer(EqualsValueClause(
                                                              StackAllocArrayCreationExpression(
                                                                  ArrayType(
                                                                      _bufferElementType,
                                                                      SingletonList(ArrayRankSpecifier(SingletonSeparatedList <ExpressionSyntax>(
                                                                                                           MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                                                                  _marshallerType,
                                                                                                                                  IdentifierName(ShapeMemberNames.BufferSize))
                                                                                                           )))))))))));


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

                // <marshaller>.FromManaged(<managedIdentifier>, new Span<bufferElementType>(<stackPtrIdentifier>, <marshallerType>.BufferSize));
                yield return(ExpressionStatement(
                                 InvocationExpression(
                                     MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                            IdentifierName(context.GetAdditionalIdentifier(info, StatefulValueMarshalling.MarshallerIdentifier)),
                                                            IdentifierName(ShapeMemberNames.Value.Stateful.FromManaged)),
                                     ArgumentList(SeparatedList(
                                                      new[]
                {
                    Argument(IdentifierName(managedIdentifier)),
                    Argument(
                        ObjectCreationExpression(
                            GenericName(Identifier(TypeNames.System_Span),
                                        TypeArgumentList(SingletonSeparatedList(
                                                             _bufferElementType))))
                        .WithArgumentList(
                            ArgumentList(SeparatedList(new ArgumentSyntax[]
                    {
                        Argument(IdentifierName(stackPtrIdentifier)),
                        Argument(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                        _marshallerType,
                                                        IdentifierName(ShapeMemberNames.BufferSize)))
                    }))))
                })))));
            }
        }
Example #2
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 #3
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))
                    }))))));
                }
            }
        }