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)))
                    }))))
                })))));
            }
        }
Exemple #2
0
        public IEnumerable <StatementSyntax> GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable <ArgumentSyntax> nativeTypeConstructorArguments)
        {
            if (CanUseCallerAllocatedBuffer(info, context))
            {
                return(GenerateCallerAllocatedBufferMarshalStatements());
            }

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

            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);

                // <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))
                }))))));
            }
        }
        public IEnumerable <StatementSyntax> 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 <StatementSyntax> 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;
            }

            // ReadOnlySpan<T> <managedSpan> = <marshaller>.GetManagedValuesSource()
            // Span<TUnmanagedElement> <nativeSpan> = <marshaller>.GetUnmanagedValuesDestination()
            // << marshal contents >>
            yield return(GenerateMarshalStatement(info, context));
        }
Exemple #5
0
 public IEnumerable <StatementSyntax> GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateMarshalStatements(info, context);
Exemple #6
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))
                    }))))));
                }
            }
        }
        public IEnumerable <StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context)
        {
            // Although custom native type marshalling doesn't support [In] or [Out] by value marshalling,
            // other marshallers that wrap this one might, so we handle the correct cases here.
            switch (context.CurrentStage)
            {
            case StubCodeContext.Stage.Setup:
                return(_nativeTypeMarshaller.GenerateSetupStatements(info, context));

            case StubCodeContext.Stage.Marshal:
                if (!info.IsManagedReturnPosition && info.RefKind != RefKind.Out)
                {
                    return(_nativeTypeMarshaller.GenerateMarshalStatements(info, context));
                }
                break;

            case StubCodeContext.Stage.Pin:
                if (!info.IsByRef || info.RefKind == RefKind.In)
                {
                    return(_nativeTypeMarshaller.GeneratePinStatements(info, context));
                }
                break;

            case StubCodeContext.Stage.PinnedMarshal:
                if (!info.IsManagedReturnPosition && info.RefKind != RefKind.Out)
                {
                    return(_nativeTypeMarshaller.GeneratePinnedMarshalStatements(info, context));
                }
                break;

            case StubCodeContext.Stage.NotifyForSuccessfulInvoke:
                if (!info.IsManagedReturnPosition && info.RefKind != RefKind.Out)
                {
                    return(_nativeTypeMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context));
                }
                break;

            case StubCodeContext.Stage.UnmarshalCapture:
                if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In))
                {
                    return(_nativeTypeMarshaller.GenerateUnmarshalCaptureStatements(info, context));
                }
                break;

            case StubCodeContext.Stage.Unmarshal:
                if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In) ||
                    (_enableByValueContentsMarshalling && !info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)))
                {
                    return(_nativeTypeMarshaller.GenerateUnmarshalStatements(info, context));
                }
                break;

            case StubCodeContext.Stage.GuaranteedUnmarshal:
                if (info.IsManagedReturnPosition ||
                    (info.IsByRef && info.RefKind != RefKind.In) ||
                    (_enableByValueContentsMarshalling && !info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)))
                {
                    return(_nativeTypeMarshaller.GenerateGuaranteedUnmarshalStatements(info, context));
                }
                break;

            case StubCodeContext.Stage.Cleanup:
                return(_nativeTypeMarshaller.GenerateCleanupStatements(info, context));

            default:
                break;
            }

            return(Array.Empty <StatementSyntax>());
        }