Example #1
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 #2
0
        protected StatementSyntax GenerateContentsMarshallingStatement(
            TypePositionInfo info,
            StubCodeContext context,
            ExpressionSyntax lengthExpression,
            params StubCodeContext.Stage[] stagesToGeneratePerElement)
        {
            string managedSpanIdentifier  = MarshallerHelpers.GetManagedSpanIdentifier(info, context);
            string nativeSpanIdentifier   = MarshallerHelpers.GetNativeSpanIdentifier(info, context);
            var    elementSetupSubContext = new LinearCollectionElementMarshallingCodeContext(
                StubCodeContext.Stage.Setup,
                managedSpanIdentifier,
                nativeSpanIdentifier,
                context);

            TypePositionInfo localElementInfo = _elementInfo with
            {
                InstanceIdentifier = info.InstanceIdentifier,
                RefKind            = info.IsByRef ? info.RefKind : info.ByValueContentsMarshalKind.GetRefKindForByValueContentsKind(),
                ManagedIndex       = info.ManagedIndex,
                NativeIndex        = info.NativeIndex
            };

            List <StatementSyntax> elementStatements = new();

            foreach (StubCodeContext.Stage stage in stagesToGeneratePerElement)
            {
                var elementSubContext = elementSetupSubContext with {
                    CurrentStage = stage
                };
                elementStatements.AddRange(_elementMarshaller.Generate(localElementInfo, elementSubContext));
            }

            if (elementStatements.Any())
            {
                StatementSyntax marshallingStatement = Block(
                    List(_elementMarshaller.Generate(localElementInfo, elementSetupSubContext)
                         .Concat(elementStatements)));

                if (_elementMarshaller.AsNativeType(_elementInfo) is PointerTypeSyntax elementNativeType)
                {
                    PointerNativeTypeAssignmentRewriter rewriter = new(elementSetupSubContext.GetIdentifiers(localElementInfo).native, elementNativeType);
                    marshallingStatement = (StatementSyntax)rewriter.Visit(marshallingStatement);
                }

                // Iterate through the elements of the native collection to marshal them
                return(MarshallerHelpers.GetForLoop(lengthExpression, elementSetupSubContext.IndexerIdentifier)
                       .WithStatement(marshallingStatement));
            }

            return(EmptyStatement());
        }
Example #3
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)));
        }