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> Generate(TypePositionInfo info, StubCodeContext context) { if (!info.IsByRef || info.IsManagedReturnPosition) { yield break; } (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); if (context.SingleFrameSpansNativeContext) { if (context.CurrentStage == StubCodeContext.Stage.Pin) { yield return(FixedStatement( VariableDeclaration( PointerType(AsNativeType(info)), SingletonSeparatedList( VariableDeclarator(Identifier(nativeIdentifier)) .WithInitializer(EqualsValueClause( PrefixUnaryExpression(SyntaxKind.AddressOfExpression, IdentifierName(managedIdentifier)) )) ) ), EmptyStatement() )); } yield break; } switch (context.CurrentStage) { case StubCodeContext.Stage.Setup: break; case StubCodeContext.Stage.Marshal: if (info.RefKind == RefKind.Ref) { yield return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(nativeIdentifier), IdentifierName(managedIdentifier)))); } break; case StubCodeContext.Stage.Unmarshal: yield return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(managedIdentifier), IdentifierName(nativeIdentifier)))); break; default: break; } }
static ExpressionSyntax GetIndexedNumElementsExpression(StubCodeContext context, TypePositionInfo numElementsInfo, out int numIndirectionLevels) { Stack <string> indexerStack = new(); StubCodeContext?currentContext = context; StubCodeContext lastContext = null !; while (currentContext is not null) { if (currentContext is LinearCollectionElementMarshallingCodeContext collectionContext) { indexerStack.Push(collectionContext.IndexerIdentifier); } lastContext = currentContext; currentContext = currentContext.ParentContext; } numIndirectionLevels = indexerStack.Count; ExpressionSyntax indexedNumElements = IdentifierName(lastContext.GetIdentifiers(numElementsInfo).managed); while (indexerStack.Count > 0) { NameSyntax indexer = IdentifierName(indexerStack.Pop()); indexedNumElements = ElementAccessExpression(indexedNumElements) .AddArgumentListArguments(Argument(indexer)); } return(indexedNumElements); }
public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) { (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); if (!info.IsByRef) { // (ushort)<managedIdentifier> return(Argument( CastExpression( AsNativeType(info), IdentifierName(managedIdentifier)))); } else if (IsPinningPathSupported(info, context)) { // (ushort*)<pinned> return(Argument( CastExpression( PointerType(AsNativeType(info)), IdentifierName(PinnedIdentifier(info.InstanceIdentifier))))); } // &<nativeIdentifier> return(Argument( PrefixUnaryExpression( SyntaxKind.AddressOfExpression, IdentifierName(nativeIdentifier)))); }
public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) { if (info.MarshallingAttributeInfo is NativeMarshallingAttributeInfo marshalInfo) { return(CreateCustomNativeTypeMarshaller(info, context, marshalInfo)); } if (info.MarshallingAttributeInfo is UnmanagedBlittableMarshallingInfo blittableInfo) { if (Options.RuntimeMarshallingDisabled || blittableInfo.IsStrictlyBlittable) { return(s_blittable); } throw new MarshallingNotSupportedException(info, context) { NotSupportedDetails = SR.RuntimeMarshallingMustBeDisabled, DiagnosticProperties = AddDisableRuntimeMarshallingAttributeProperties }; } if (info.MarshallingAttributeInfo is MissingSupportMarshallingInfo) { return(s_forwarder); } return(_innerMarshallingGenerator.Create(info, context)); }
public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) { return(info.MarshallingAttributeInfo switch { NativeMarshallingAttributeInfo marshalInfo when Options.RuntimeMarshallingDisabled => CreateCustomNativeTypeMarshaller(info, context, marshalInfo), NativeMarshallingAttributeInfo { NativeValueType : SpecialTypeInfo specialType } marshalInfo when specialType.SpecialType.IsAlwaysBlittable() => CreateCustomNativeTypeMarshaller(info, context, marshalInfo), NativeMarshallingAttributeInfo { NativeValueType : PointerTypeInfo } marshalInfo => CreateCustomNativeTypeMarshaller(info, context, marshalInfo), UnmanagedBlittableMarshallingInfo when Options.RuntimeMarshallingDisabled => s_blittable, UnmanagedBlittableMarshallingInfo or NativeMarshallingAttributeInfo when !Options.RuntimeMarshallingDisabled => throw new MarshallingNotSupportedException(info, context) { NotSupportedDetails = SR.RuntimeMarshallingMustBeDisabled, DiagnosticProperties = AddDisableRuntimeMarshallingAttributeProperties }, GeneratedNativeMarshallingAttributeInfo => s_forwarder, MissingSupportMarshallingInfo => s_forwarder, _ => _innerMarshallingGenerator.Create(info, context) });
protected bool UsesConditionalStackAlloc(TypePositionInfo info, StubCodeContext context) { return(context.SingleFrameSpansNativeContext && (!info.IsByRef || info.RefKind == RefKind.In) && !info.IsManagedReturnPosition && context.AdditionalTemporaryStateLivesAcrossStages); }
protected override StatementSyntax GenerateStackallocOnlyValueMarshalling( TypePositionInfo info, StubCodeContext context, SyntaxToken byteLengthIdentifier, SyntaxToken stackAllocPtrIdentifier) { string managedIdentifier = context.GetIdentifiers(info).managed; return(Block( // ((ReadOnlySpan<char>)<managed>).CopyTo(new Span<char>(<stackAllocPtr>, <managed>.Length)); ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, ParenthesizedExpression( CastExpression( GenericName(Identifier("System.ReadOnlySpan"), TypeArgumentList(SingletonSeparatedList <TypeSyntax>( PredefinedType(Token(SyntaxKind.CharKeyword))))), IdentifierName(managedIdentifier))), IdentifierName("CopyTo")), ArgumentList( SeparatedList(new[] { Argument( ObjectCreationExpression( GenericName(Identifier(TypeNames.System_Span), TypeArgumentList(SingletonSeparatedList <TypeSyntax>( PredefinedType(Token(SyntaxKind.CharKeyword))))), ArgumentList( SeparatedList(new[] { Argument(IdentifierName(stackAllocPtrIdentifier)), Argument( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(managedIdentifier), IdentifierName("Length"))) })), initializer: null)) })))), // ((char*)<stackAllocPtr>)[<managed>.Length] = '\0'; ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, ElementAccessExpression( ParenthesizedExpression( CastExpression( PointerType(PredefinedType(Token(SyntaxKind.CharKeyword))), IdentifierName(stackAllocPtrIdentifier))), BracketedArgumentList( SingletonSeparatedList( Argument( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(managedIdentifier), IdentifierName("Length")))))), LiteralExpression( SyntaxKind.CharacterLiteralExpression, Literal('\0')))))); }
public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { if (IsPinningPathSupported(info, context)) { return(ValueBoundaryBehavior.NativeIdentifier); } return(_manualMarshallingGenerator.GetValueBoundaryBehavior(info, context)); }
public IEnumerable <StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context) { if (IsPinningPathSupported(info, context)) { return(GeneratePinningPath(info, context)); } return(_manualMarshallingGenerator.Generate(info, context)); }
public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) { if (IsPinningPathSupported(info, context)) { return(false); } return(_manualMarshallingGenerator.UsesNativeIdentifier(info, context)); }
/// <summary> /// Generate code to check if the managed value is not null. /// </summary> /// <param name="info">Object to marshal</param> /// <param name="context">Code generation context</param> /// <returns>An expression that checks if the managed value is not null.</returns> protected virtual ExpressionSyntax GenerateNullCheckExpression( TypePositionInfo info, StubCodeContext context) { return(BinaryExpression( SyntaxKind.NotEqualsExpression, IdentifierName(context.GetIdentifiers(info).managed), LiteralExpression(SyntaxKind.NullLiteralExpression))); }
public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) { return(info.MarshallingAttributeInfo switch { NativeMarshallingAttributeInfo marshalInfo => CreateCustomNativeTypeMarshaller(info, context, marshalInfo), BlittableTypeAttributeInfo => s_blittable, GeneratedNativeMarshallingAttributeInfo => s_forwarder, _ => _innerMarshallingGenerator.Create(info, context) });
public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) { if (IsPinningPathSupported(info, context)) { string identifier = context.GetIdentifiers(info).native; return(Argument(CastExpression(AsNativeType(info), IdentifierName(identifier)))); } return(_manualMarshallingGenerator.AsArgument(info, context)); }
public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { if (info.IsByRef) { return(ValueBoundaryBehavior.AddressOfNativeIdentifier); } return(ValueBoundaryBehavior.NativeIdentifier); }
public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) { if (info.IsNativeReturnPosition && !info.IsManagedReturnPosition) { // Use marshaller for native HRESULT return / exception throwing System.Diagnostics.Debug.Assert(info.ManagedType.Equals(SpecialTypeInfo.Int32)); return(s_hResultException); } return(_inner.Create(info, context)); }
protected override ExpressionSyntax GenerateAllocationExpression( TypePositionInfo info, StubCodeContext context, SyntaxToken byteLengthIdentifier, out bool allocationRequiresByteLength) { allocationRequiresByteLength = false; return(CastExpression( AsNativeType(info), StringMarshaller.AllocationExpression(CharEncoding.Utf16, context.GetIdentifiers(info).managed))); }
public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { if (!info.IsByRef) { return(ValueBoundaryBehavior.ManagedIdentifier); } else if (context.SingleFrameSpansNativeContext && !info.IsManagedReturnPosition) { return(ValueBoundaryBehavior.NativeIdentifier); } return(ValueBoundaryBehavior.AddressOfNativeIdentifier); }
public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { if (!info.IsByRef) { return(ValueBoundaryBehavior.ManagedIdentifier); } else if (IsPinningPathSupported(info, context)) { return(ValueBoundaryBehavior.NativeIdentifier); } return(ValueBoundaryBehavior.AddressOfNativeIdentifier); }
public IMarshallingGenerator Create( TypePositionInfo info, StubCodeContext context) { if (info.MarshallingAttributeInfo is NoMarshallingInfo && CustomTypeToErrorMessageMap.TryGetValue(info.ManagedType, out string errorMessage)) { throw new MarshallingNotSupportedException(info, context) { NotSupportedDetails = errorMessage }; } return(_inner.Create(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()); }
public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) { string identifier = context.GetIdentifiers(info).native; if (info.IsByRef) { return(Argument( PrefixUnaryExpression( SyntaxKind.AddressOfExpression, IdentifierName(identifier)))); } return(Argument(IdentifierName(identifier))); }
public StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCodeContext context) { ExpressionSyntax source = CastToManagedIfNecessary(GetUnmanagedValuesSource(info, context)); // <source>.CopyTo(<GetManagedValuesDestination>); return(ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, source, IdentifierName("CopyTo"))) .AddArgumentListArguments( Argument(GetManagedValuesDestination(info, context))))); }
public IEnumerable <StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context) { (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); switch (context.CurrentStage) { case StubCodeContext.Stage.Setup: break; case StubCodeContext.Stage.Marshal: // <nativeIdentifier> = (<nativeType>)(<managedIdentifier> ? _trueValue : _falseValue); if (info.RefKind != RefKind.Out) { yield return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(nativeIdentifier), CastExpression( AsNativeType(info), ParenthesizedExpression( ConditionalExpression(IdentifierName(managedIdentifier), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(_trueValue)), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(_falseValue)))))))); } break; case StubCodeContext.Stage.Unmarshal: if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) { // <managedIdentifier> = <nativeIdentifier> == _trueValue; // or // <managedIdentifier> = <nativeIdentifier> != _falseValue; (SyntaxKind binaryOp, int comparand) = _compareToTrue ? (SyntaxKind.EqualsExpression, _trueValue) : (SyntaxKind.NotEqualsExpression, _falseValue); yield return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(managedIdentifier), BinaryExpression( binaryOp, IdentifierName(nativeIdentifier), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(comparand)))))); } break; default: break; } }
public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) { if (!info.IsByRef) { return(Argument(IdentifierName(info.InstanceIdentifier))); } else if (context.SingleFrameSpansNativeContext && !info.IsManagedReturnPosition) { return(Argument(IdentifierName(context.GetIdentifiers(info).native))); } return(Argument( PrefixUnaryExpression( SyntaxKind.AddressOfExpression, IdentifierName(context.GetIdentifiers(info).native)))); }
public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { if (IsPinningPathSupported(info, context)) { if (AsNativeType(info) is PointerTypeSyntax pointerType && pointerType.ElementType is PredefinedTypeSyntax predefinedType && predefinedType.Keyword.IsKind(SyntaxKind.VoidKeyword)) { return(ValueBoundaryBehavior.NativeIdentifier); } // Cast to native type if it is not void* return(ValueBoundaryBehavior.CastNativeIdentifier); } return(_manualMarshallingGenerator.GetValueBoundaryBehavior(info, context)); }
public override ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) { ExpressionSyntax windowsExpr = _windowsMarshaller.AsArgument(info, context).Expression; ExpressionSyntax nonWindowsExpr = _nonWindowsMarshaller.AsArgument(info, context).Expression; // If the Windows and non-Windows syntax are equivalent, just return one of them. if (windowsExpr.IsEquivalentTo(nonWindowsExpr)) { return(Argument(windowsExpr)); } // OperatingSystem.IsWindows() ? << Windows code >> : << non-Windows code >> return(Argument( ConditionalExpression( IsWindows, windowsExpr, nonWindowsExpr))); }
protected override StatementSyntax GenerateStackallocOnlyValueMarshalling( TypePositionInfo info, StubCodeContext context, SyntaxToken byteLengthIdentifier, SyntaxToken stackAllocPtrIdentifier) { return(Block( // <byteLen> = Encoding.UTF8.GetBytes(<managed>, new Span<byte>(<stackAllocPtr>, <byteLen>)); ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(byteLengthIdentifier), InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, s_utf8EncodingType, IdentifierName("GetBytes")), ArgumentList( SeparatedList(new ArgumentSyntax[] { Argument(IdentifierName(context.GetIdentifiers(info).managed)), Argument( ObjectCreationExpression( GenericName(Identifier(TypeNames.System_Span), TypeArgumentList(SingletonSeparatedList <TypeSyntax>( PredefinedType(Token(SyntaxKind.ByteKeyword))))), ArgumentList( SeparatedList(new ArgumentSyntax[] { Argument(IdentifierName(stackAllocPtrIdentifier)), Argument(IdentifierName(byteLengthIdentifier)) })), initializer: null)) }))))), // <stackAllocPtr>[<byteLen>] = 0; ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, ElementAccessExpression( IdentifierName(stackAllocPtrIdentifier), BracketedArgumentList( SingletonSeparatedList <ArgumentSyntax>( Argument(IdentifierName(byteLengthIdentifier))))), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)))))); }
public IEnumerable <StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context) { if (context.CurrentStage != StubCodeContext.Stage.Unmarshal) { yield break; } // Marshal.ThrowExceptionForHR(<managed>) string identifier = context.GetIdentifiers(info).managed; yield return(ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, MarshallerHelpers.InteropServicesMarshalType, IdentifierName(nameof(System.Runtime.InteropServices.Marshal.ThrowExceptionForHR))), ArgumentList(SingletonSeparatedList( Argument(IdentifierName(identifier))))))); }
protected bool TryGenerateSetupSyntax(TypePositionInfo info, StubCodeContext context, out StatementSyntax statement) { statement = EmptyStatement(); if (!UsesConditionalStackAlloc(info, context)) { return(false); } string allocationMarkerIdentifier = GetAllocationMarkerIdentifier(info, context); // bool <allocationMarker> = false; statement = LocalDeclarationStatement( VariableDeclaration( PredefinedType(Token(SyntaxKind.BoolKeyword)), SingletonSeparatedList( VariableDeclarator(allocationMarkerIdentifier) .WithInitializer(EqualsValueClause(LiteralExpression(SyntaxKind.FalseLiteralExpression)))))); return(true); }