public IEnumerable <StatementSyntax> GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) { if (!_shape.HasFlag(MarshallerShape.GuaranteedUnmarshal)) { yield break; } (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); yield return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(numElementsIdentifier), _numElementsExpression))); // <managedIdentifier> = <marshallerType>.AllocateContainerForManagedElementsFinally(<nativeIdentifier>, <numElements>); yield return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(managedIdentifier), InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, _marshallerTypeSyntax, IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForManagedElementsFinally)), ArgumentList(SeparatedList(new ArgumentSyntax[] { Argument(IdentifierName(nativeIdentifier)), Argument(IdentifierName(numElementsIdentifier)) })))))); }
public IEnumerable <StatementSyntax> GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) { if (!_shape.HasFlag(MarshallerShape.ToManaged)) { yield break; } if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) { yield return(GenerateByValueOutUnmarshalStatement(info, context)); } else { // int <numElements> = <numElementExpression> string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); yield return(LocalDeclarationStatement( VariableDeclaration( PredefinedType(Token(SyntaxKind.IntKeyword)), SingletonSeparatedList( VariableDeclarator(numElementsIdentifier) .WithInitializer(EqualsValueClause(_numElementsExpression)))))); yield return(GenerateUnmarshalStatement(info, context)); } foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, context)) { yield return(statement); } }
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))); }
public IEnumerable <StatementSyntax> GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) { yield return(MarshallerHelpers.Declare( _marshallerTypeSyntax, context.GetAdditionalIdentifier(info, MarshallerIdentifier), ImplicitObjectCreationExpression(ArgumentList(), initializer: null))); }
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> GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) { yield return(LocalDeclarationStatement( VariableDeclaration( PredefinedType(Token(SyntaxKind.IntKeyword)), SingletonSeparatedList( VariableDeclarator(MarshallerHelpers.GetNumElementsIdentifier(info, context)))))); }
static IEnumerable <int> GetInfoDependencies(TypePositionInfo info) { // A parameter without a managed index cannot have any dependencies. if (info.ManagedIndex == TypePositionInfo.UnsetIndex) { return(Array.Empty <int>()); } return(MarshallerHelpers.GetDependentElementsOfMarshallingInfo(info.MarshallingAttributeInfo) .Select(static info => GetInfoIndex(info)).ToImmutableArray());
public IEnumerable <StatementSyntax> GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) { (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) { // <numElements> = <GetManagedValuesSource.Length; yield return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(numElementsIdentifier), MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GetManagedValuesSource(info, context), IdentifierName("Length"))))); yield return(GenerateByValueOutUnmarshalStatement(info, context)); } if (!_shape.HasFlag(MarshallerShape.ToManaged)) { yield break; } else { // <numElements> = <numElementsExpression>; yield return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(numElementsIdentifier), _numElementsExpression))); // <managedIdentifier> = <marshallerType>.AllocateContainerForManagedElements(<nativeIdentifier>, <numElements>); yield return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(managedIdentifier), InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, _marshallerTypeSyntax, IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForManagedElements)), ArgumentList(SeparatedList(new ArgumentSyntax[] { Argument(IdentifierName(nativeIdentifier)), Argument(IdentifierName(numElementsIdentifier)) })))))); // ReadOnlySpan<TUnmanagedElement> <nativeSpan> = <marshallerType>.GetUnmanagedValuesSource(<nativeIdentifier>, <numElements>) // Span<T> <managedSpan> = <marshallerType>.GetManagedValuesDestination(<managedIdentifier>) // << unmarshal contents >> yield return(GenerateUnmarshalStatement(info, context)); } }
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 override InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context) { string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); // <marshaller>.GetManagedValuesDestination(<numElements>) return(InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(marshaller), IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetManagedValuesDestination)), ArgumentList(SingletonSeparatedList( Argument(IdentifierName(numElementsIdentifier)))))); }
public IEnumerable <StatementSyntax> GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) { string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) { // int <numElements> = <GetManagedValuesSource>.Length; yield return(LocalDeclarationStatement( VariableDeclaration( PredefinedType(Token(SyntaxKind.IntKeyword)), SingletonSeparatedList( VariableDeclarator(numElementsIdentifier) .WithInitializer(EqualsValueClause( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GetManagedValuesSource(info, context), IdentifierName("Length")))))))); yield return(GenerateByValueOutUnmarshalStatement(info, context)); } if (!_shape.HasFlag(MarshallerShape.ToManaged)) { yield break; } else { // int <numElements> = <numElementsExpression>; yield return(LocalDeclarationStatement( VariableDeclaration( PredefinedType(Token(SyntaxKind.IntKeyword)), SingletonSeparatedList( VariableDeclarator(numElementsIdentifier) .WithInitializer(EqualsValueClause(_numElementsExpression)))))); // ReadOnlySpan<TUnmanagedElement> <nativeSpan> = <marshaller>.GetUnmanagedValuesSource(<nativeIdentifier>, <numElements>) // Span<T> <managedSpan> = <marshaller>.GetManagedValuesDestination(<managedIdentifier>) // << unmarshal contents >> yield return(GenerateUnmarshalStatement(info, context)); } foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, context)) { yield return(statement); } }
public IEnumerable <StatementSyntax> GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) { // <marshaller> = new(); LocalDeclarationStatementSyntax declaration = MarshallerHelpers.Declare( _marshallerType.Syntax, context.GetAdditionalIdentifier(info, MarshallerIdentifier), ImplicitObjectCreationExpression(ArgumentList(), initializer: null)); // For byref-like marshaller types, we'll mark them as scoped. // Byref-like types can capture references, so by default the compiler has to worry that // they could enable those references to escape the current stack frame. // In particular, this can interact poorly with the caller-allocated-buffer marshalling // support and make the simple `marshaller.FromManaged(managed, stackalloc X[i])` expression // illegal. Mark the marshaller type as scoped so the compiler knows that it won't escape. if (_marshallerType is ValueTypeInfo { IsByRefLike : true })
protected override InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context) { string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); string nativeIdentifier = context.GetIdentifiers(info).native; // <marshallerType>.GetUnmanagedValuesSource(<nativeIdentifier>, <numElements>) return(InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, _marshallerTypeSyntax, IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetUnmanagedValuesSource)), ArgumentList(SeparatedList(new ArgumentSyntax[] { Argument(IdentifierName(nativeIdentifier)), Argument(IdentifierName(numElementsIdentifier)) })))); }
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)); } }
/// <summary> /// Generate the method body of the p/invoke stub. /// </summary> /// <param name="dllImportName">Name of the target DllImport function to invoke</param> /// <returns>Method body of the p/invoke stub</returns> /// <remarks> /// The generated code assumes it will be in an unsafe context. /// </remarks> public BlockSyntax GeneratePInvokeBody(string dllImportName) { GeneratedStatements statements = GeneratedStatements.Create(_marshallers, _context, IdentifierName(dllImportName)); bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.Cleanup.IsEmpty; VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForManagedToNative(_marshallers, _context, shouldInitializeVariables); var setupStatements = new List <StatementSyntax>(); if (_setLastError) { // Declare variable for last error setupStatements.Add(MarshallerHelpers.Declare( PredefinedType(Token(SyntaxKind.IntKeyword)), LastErrorIdentifier, initializeToDefault: false)); } if (!statements.GuaranteedUnmarshal.IsEmpty) { setupStatements.Add(MarshallerHelpers.Declare(PredefinedType(Token(SyntaxKind.BoolKeyword)), InvokeSucceededIdentifier, initializeToDefault: true)); } setupStatements.AddRange(declarations.Initializations); setupStatements.AddRange(declarations.Variables); setupStatements.AddRange(statements.Setup); var tryStatements = new List <StatementSyntax>(); tryStatements.AddRange(statements.Marshal); BlockSyntax fixedBlock = Block(statements.PinnedMarshal); if (_setLastError) { StatementSyntax clearLastError = MarshallerHelpers.CreateClearLastSystemErrorStatement(SuccessErrorCode); StatementSyntax getLastError = MarshallerHelpers.CreateGetLastSystemErrorStatement(LastErrorIdentifier); fixedBlock = fixedBlock.AddStatements(clearLastError, statements.InvokeStatement, getLastError); } else { fixedBlock = fixedBlock.AddStatements(statements.InvokeStatement); } tryStatements.Add(statements.Pin.NestFixedStatements(fixedBlock)); // <invokeSucceeded> = true; if (!statements.GuaranteedUnmarshal.IsEmpty) { tryStatements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(InvokeSucceededIdentifier), LiteralExpression(SyntaxKind.TrueLiteralExpression)))); } tryStatements.AddRange(statements.NotifyForSuccessfulInvoke); tryStatements.AddRange(statements.Unmarshal); List <StatementSyntax> allStatements = setupStatements; List <StatementSyntax> finallyStatements = new List <StatementSyntax>(); if (!statements.GuaranteedUnmarshal.IsEmpty) { finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal))); } finallyStatements.AddRange(statements.Cleanup); if (finallyStatements.Count > 0) { // Add try-finally block if there are any statements in the finally block allStatements.Add( TryStatement(Block(tryStatements), default, FinallyClause(Block(finallyStatements))));
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)) })))))); } } }
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))); }