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