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))) })))) }))))); } }
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)); }
public IEnumerable <StatementSyntax> GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateMarshalStatements(info, context);
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>()); }