diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs index 65920dc750d820..fc0baa4b2d0dda 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs @@ -512,10 +512,8 @@ void GenerateStatementsForInvoke(List statementsToUpdate, Invoc ParameterList( SeparatedList( _paramMarshallers.Select(marshaler => marshaler.Generator.AsParameter(marshaler.TypeInfo)))), - _retMarshaller.Generator.AsNativeType(_retMarshaller.TypeInfo), - _retMarshaller.Generator is IAttributedReturnTypeMarshallingGenerator attributedReturn - ? attributedReturn.GenerateAttributesForReturnType(_retMarshaller.TypeInfo) - : null + _retMarshaller.Generator.AsReturnType(_retMarshaller.TypeInfo), + _retMarshaller.Generator.GenerateAttributesForReturnType(_retMarshaller.TypeInfo) ); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs index 450ba62c1aaa1c..df914b3b3cfc18 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs @@ -27,14 +27,13 @@ public bool IsSupported(TargetFramework target, Version version) return target is TargetFramework.Net && version.Major >= 7; } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { if (IsPinningPathSupported(info, context)) { - string identifier = context.GetIdentifiers(info).native; - return Argument(CastExpression(AsNativeType(info), IdentifierName(identifier))); + return ValueBoundaryBehavior.NativeIdentifier; } - return _manualMarshallingGenerator.AsArgument(info, context); + return _manualMarshallingGenerator.GetValueBoundaryBehavior(info, context); } public TypeSyntax AsNativeType(TypePositionInfo info) @@ -42,9 +41,9 @@ public TypeSyntax AsNativeType(TypePositionInfo info) return _manualMarshallingGenerator.AsNativeType(info); } - public ParameterSyntax AsParameter(TypePositionInfo info) + public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { - return _manualMarshallingGenerator.AsParameter(info); + return _manualMarshallingGenerator.GetNativeSignatureBehavior(info); } public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs index b137316d21aedb..bc2de37e5b5486 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs @@ -20,29 +20,22 @@ public TypeSyntax AsNativeType(TypePositionInfo info) return info.ManagedType.Syntax; } - public ParameterSyntax AsParameter(TypePositionInfo info) + public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { - TypeSyntax type = info.IsByRef - ? PointerType(AsNativeType(info)) - : AsNativeType(info); - return Parameter(Identifier(info.InstanceIdentifier)) - .WithType(type); + return info.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { if (!info.IsByRef) { - return Argument(IdentifierName(info.InstanceIdentifier)); + return ValueBoundaryBehavior.ManagedIdentifier; } else if (context.SingleFrameSpansNativeContext && !info.IsManagedReturnPosition) { - return Argument(IdentifierName(context.GetIdentifiers(info).native)); + return ValueBoundaryBehavior.NativeIdentifier; } - return Argument( - PrefixUnaryExpression( - SyntaxKind.AddressOfExpression, - IdentifierName(context.GetIdentifiers(info).native))); + return ValueBoundaryBehavior.AddressOfNativeIdentifier; } public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs index 247d19ff1cf2c0..7ad4c7c58b887f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs @@ -35,27 +35,19 @@ public TypeSyntax AsNativeType(TypePositionInfo info) return _nativeType; } - public ParameterSyntax AsParameter(TypePositionInfo info) + public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { - TypeSyntax type = info.IsByRef - ? PointerType(AsNativeType(info)) - : AsNativeType(info); - return Parameter(Identifier(info.InstanceIdentifier)) - .WithType(type); + return info.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { - string identifier = context.GetIdentifiers(info).native; if (info.IsByRef) { - return Argument( - PrefixUnaryExpression( - SyntaxKind.AddressOfExpression, - IdentifierName(identifier))); + return ValueBoundaryBehavior.AddressOfNativeIdentifier; } - return Argument(IdentifierName(identifier)); + return ValueBoundaryBehavior.NativeIdentifier; } public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs index 293b97959d63b1..0421c1d6da557a 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs @@ -22,31 +22,18 @@ public Utf16CharMarshaller() public bool IsSupported(TargetFramework target, Version version) => true; - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { - (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); if (!info.IsByRef) { - // (ushort) - return Argument( - CastExpression( - AsNativeType(info), - IdentifierName(managedIdentifier))); + return ValueBoundaryBehavior.ManagedIdentifier; } else if (IsPinningPathSupported(info, context)) { - // (ushort*) - return Argument( - CastExpression( - PointerType(AsNativeType(info)), - IdentifierName(PinnedIdentifier(info.InstanceIdentifier)))); + return ValueBoundaryBehavior.NativeIdentifier; } - // & - return Argument( - PrefixUnaryExpression( - SyntaxKind.AddressOfExpression, - IdentifierName(nativeIdentifier))); + return ValueBoundaryBehavior.AddressOfNativeIdentifier; } public TypeSyntax AsNativeType(TypePositionInfo info) @@ -55,13 +42,9 @@ public TypeSyntax AsNativeType(TypePositionInfo info) return s_nativeType; } - public ParameterSyntax AsParameter(TypePositionInfo info) + public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { - TypeSyntax type = info.IsByRef - ? PointerType(AsNativeType(info)) - : AsNativeType(info); - return Parameter(Identifier(info.InstanceIdentifier)) - .WithType(type); + return info.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; } public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) @@ -85,7 +68,15 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont )) ) ), - EmptyStatement() + // ushort* = (ushort*); + LocalDeclarationStatement( + VariableDeclaration(PointerType(AsNativeType(info)), + SingletonSeparatedList( + VariableDeclarator(nativeIdentifier) + .WithInitializer(EqualsValueClause( + CastExpression( + PointerType(AsNativeType(info)), + IdentifierName(PinnedIdentifier(info.InstanceIdentifier)))))))) ); } yield break; diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs index fb097a53a12f50..970e8da3d22166 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs @@ -238,10 +238,10 @@ public virtual bool IsSupported(TargetFramework target, Version version) public abstract TypeSyntax AsNativeType(TypePositionInfo info); /// - public abstract ParameterSyntax AsParameter(TypePositionInfo info); + public abstract SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info); /// - public abstract ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context); + public abstract ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context); /// public abstract IEnumerable Generate(TypePositionInfo info, StubCodeContext context); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshallingGenerator.cs index 4a27fa3cb4eb56..c770312495087c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshallingGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshallingGenerator.cs @@ -28,9 +28,9 @@ public bool IsSupported(TargetFramework target, Version version) return target is TargetFramework.Net && version.Major >= 6; } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { - return _nativeTypeMarshaller.AsArgument(info, context); + return info.IsByRef ? ValueBoundaryBehavior.AddressOfNativeIdentifier : ValueBoundaryBehavior.NativeIdentifier; } public TypeSyntax AsNativeType(TypePositionInfo info) @@ -38,13 +38,9 @@ public TypeSyntax AsNativeType(TypePositionInfo info) return _nativeTypeMarshaller.AsNativeType(info); } - public ParameterSyntax AsParameter(TypePositionInfo info) + public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { - TypeSyntax type = info.IsByRef - ? PointerType(AsNativeType(info)) - : AsNativeType(info); - return Parameter(Identifier(info.InstanceIdentifier)) - .WithType(type); + return info.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; } public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs index 4db41933d591a5..ff9873c93b3b9e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs @@ -19,27 +19,14 @@ public TypeSyntax AsNativeType(TypePositionInfo info) return MarshallerHelpers.SystemIntPtrType; } - public ParameterSyntax AsParameter(TypePositionInfo info) + public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { - TypeSyntax type = info.IsByRef - ? PointerType(AsNativeType(info)) - : AsNativeType(info); - return Parameter(Identifier(info.InstanceIdentifier)) - .WithType(type); + return info.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { - string identifier = context.GetIdentifiers(info).native; - if (info.IsByRef) - { - return Argument( - PrefixUnaryExpression( - SyntaxKind.AddressOfExpression, - IdentifierName(identifier))); - } - - return Argument(IdentifierName(identifier)); + return info.IsByRef ? ValueBoundaryBehavior.AddressOfNativeIdentifier : ValueBoundaryBehavior.NativeIdentifier; } public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs index 92533d720031e9..561673d501318c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs @@ -11,7 +11,7 @@ namespace Microsoft.Interop { - public sealed class Forwarder : IMarshallingGenerator, IAttributedReturnTypeMarshallingGenerator + public sealed class Forwarder : IMarshallingGenerator { public bool IsSupported(TargetFramework target, Version version) => true; @@ -20,129 +20,14 @@ public TypeSyntax AsNativeType(TypePositionInfo info) return info.ManagedType.Syntax; } - private bool TryRehydrateMarshalAsAttribute(TypePositionInfo info, out AttributeSyntax marshalAsAttribute) + public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { - marshalAsAttribute = null!; - // If the parameter has [MarshalAs] marshalling, we resurface that - // in the forwarding target since the built-in system understands it. - // ICustomMarshaller marshalling requires additional information that we throw away earlier since it's unsupported, - // so explicitly do not resurface a [MarshalAs(UnmanagdType.CustomMarshaler)] attribute. - if (info.MarshallingAttributeInfo is MarshalAsInfo { UnmanagedType: not UnmanagedType.CustomMarshaler } marshalAs) - { - marshalAsAttribute = Attribute(ParseName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute)) - .WithArgumentList(AttributeArgumentList(SingletonSeparatedList(AttributeArgument( - CastExpression(ParseTypeName(TypeNames.System_Runtime_InteropServices_UnmanagedType), - LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((int)marshalAs.UnmanagedType))))))); - return true; - } - - if (info.ManagedType is SzArrayType) - { - CountInfo countInfo; - MarshallingInfo elementMarshallingInfo; - if (info.MarshallingAttributeInfo is NativeContiguousCollectionMarshallingInfo collectionMarshalling - && collectionMarshalling.UseDefaultMarshalling - && collectionMarshalling.ElementCountInfo is NoCountInfo or SizeAndParamIndexInfo - && collectionMarshalling.ElementMarshallingInfo is NoMarshallingInfo or MarshalAsInfo { UnmanagedType: not UnmanagedType.CustomMarshaler } - ) - { - countInfo = collectionMarshalling.ElementCountInfo; - elementMarshallingInfo = collectionMarshalling.ElementMarshallingInfo; - } - else if (info.MarshallingAttributeInfo is MissingSupportCollectionMarshallingInfo missingSupport) - { - countInfo = missingSupport.CountInfo; - elementMarshallingInfo = missingSupport.ElementMarshallingInfo; - } - else - { - // This condition can be hit in two ways: - // 1. User uses the MarshalUsing attribute to provide count info or element marshalling information. - // Since the MarshalUsing attribute doesn't exist on downlevel platforms where we don't support arrays, - // this case is unlikely to come in supported scenarios, but could come up with a custom CoreLib implementation - // 2. User provides a MarsalAs attribute with the ArraySubType field set to UnmanagedType.CustomMarshaler - // As mentioned above, we don't support ICustomMarshaler in the generator so we fail to forward the attribute instead of partially fowarding it. - return false; - } - - List marshalAsArguments = new List - { - AttributeArgument( - CastExpression(ParseTypeName(TypeNames.System_Runtime_InteropServices_UnmanagedType), - LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((int)UnmanagedType.LPArray)))) - }; - - if (countInfo is SizeAndParamIndexInfo sizeParamIndex) - { - if (sizeParamIndex.ConstSize != SizeAndParamIndexInfo.UnspecifiedConstSize) - { - marshalAsArguments.Add( - AttributeArgument(NameEquals("SizeConst"), null, - LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal(sizeParamIndex.ConstSize))) - ); - } - if (sizeParamIndex.ParamAtIndex is { ManagedIndex: int paramIndex }) - { - marshalAsArguments.Add( - AttributeArgument(NameEquals("SizeParamIndex"), null, - LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal(paramIndex))) - ); - } - } - - if (elementMarshallingInfo is MarshalAsInfo elementMarshalAs) - { - marshalAsArguments.Add( - AttributeArgument(NameEquals("ArraySubType"), null, - CastExpression(ParseTypeName(TypeNames.System_Runtime_InteropServices_UnmanagedType), - LiteralExpression(SyntaxKind.NumericLiteralExpression, - Literal((int)elementMarshalAs.UnmanagedType)))) - ); - } - marshalAsAttribute = Attribute(ParseName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute)) - .WithArgumentList(AttributeArgumentList(SeparatedList(marshalAsArguments))); - return true; - } - - return false; - } - - public ParameterSyntax AsParameter(TypePositionInfo info) - { - ParameterSyntax param = Parameter(Identifier(info.InstanceIdentifier)) - .WithModifiers(TokenList(Token(info.RefKindSyntax))) - .WithType(info.ManagedType.Syntax); - - List rehydratedAttributes = new(); - if (TryRehydrateMarshalAsAttribute(info, out AttributeSyntax marshalAsAttribute)) - { - rehydratedAttributes.Add(marshalAsAttribute); - } - if (info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.In)) - { - rehydratedAttributes.Add(Attribute(IdentifierName(TypeNames.System_Runtime_InteropServices_InAttribute))); - } - if (info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) - { - rehydratedAttributes.Add(Attribute(IdentifierName(TypeNames.System_Runtime_InteropServices_OutAttribute))); - } - - if (rehydratedAttributes.Count > 0) - { - param = param.AddAttributeLists(AttributeList(SeparatedList(rehydratedAttributes))); - } - - return param; + return SignatureBehavior.ManagedTypeAndAttributes; } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { - return Argument(IdentifierName(info.InstanceIdentifier)) - .WithRefKindKeyword(Token(info.RefKindSyntax)); + return ValueBoundaryBehavior.ManagedIdentifier; } public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) @@ -153,14 +38,5 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => false; public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => true; - - public AttributeListSyntax? GenerateAttributesForReturnType(TypePositionInfo info) - { - if (!TryRehydrateMarshalAsAttribute(info, out AttributeSyntax marshalAsAttribute)) - { - return null; - } - return AttributeList(SingletonSeparatedList(marshalAsAttribute)); - } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomNativeTypeMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomNativeTypeMarshallingStrategy.cs index f1b4cc171aa9fd..2160d9f1be3bdc 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomNativeTypeMarshallingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomNativeTypeMarshallingStrategy.cs @@ -18,8 +18,6 @@ internal interface ICustomNativeTypeMarshallingStrategy { TypeSyntax AsNativeType(TypePositionInfo info); - ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context); - IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context); IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments); @@ -47,20 +45,6 @@ public SimpleCustomNativeTypeMarshalling(TypeSyntax nativeTypeSyntax) _nativeTypeSyntax = nativeTypeSyntax; } - 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 TypeSyntax AsNativeType(TypePositionInfo info) { return _nativeTypeSyntax; @@ -159,20 +143,6 @@ public CustomNativeTypeWithValuePropertyMarshalling(ICustomNativeTypeMarshalling _valuePropertyType = valuePropertyType; } - 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 TypeSyntax AsNativeType(TypePositionInfo info) { return _valuePropertyType; @@ -287,11 +257,6 @@ public StackallocOptimizationMarshalling(ICustomNativeTypeMarshallingStrategy in _innerMarshaller = innerMarshaller; } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) - { - return _innerMarshaller.AsArgument(info, context); - } - public TypeSyntax AsNativeType(TypePositionInfo info) { return _innerMarshaller.AsNativeType(info); @@ -396,11 +361,6 @@ public FreeNativeCleanupStrategy(ICustomNativeTypeMarshallingStrategy innerMarsh _innerMarshaller = innerMarshaller; } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) - { - return _innerMarshaller.AsArgument(info, context); - } - public TypeSyntax AsNativeType(TypePositionInfo info) { return _innerMarshaller.AsNativeType(info); @@ -471,11 +431,6 @@ private bool CanPinMarshaller(TypePositionInfo info, StubCodeContext context) return context.SingleFrameSpansNativeContext && !info.IsManagedReturnPosition && !info.IsByRef || info.RefKind == RefKind.In; } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) - { - return _innerMarshaller.AsArgument(info, context); - } - public TypeSyntax AsNativeType(TypePositionInfo info) { return _valuePropertyType; @@ -608,11 +563,6 @@ public NumElementsExpressionMarshalling(ICustomNativeTypeMarshallingStrategy inn _sizeOfElementExpression = sizeOfElementExpression; } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) - { - return _innerMarshaller.AsArgument(info, context); - } - public TypeSyntax AsNativeType(TypePositionInfo info) { return _innerMarshaller.AsNativeType(info); @@ -721,11 +671,6 @@ public ContiguousBlittableElementCollectionMarshalling(ICustomNativeTypeMarshall _elementType = elementType; } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) - { - return _innerMarshaller.AsArgument(info, context); - } - public TypeSyntax AsNativeType(TypePositionInfo info) { return _innerMarshaller.AsNativeType(info); @@ -946,11 +891,6 @@ private StatementSyntax GenerateContentsMarshallingStatement(TypePositionInfo in return EmptyStatement(); } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) - { - return _innerMarshaller.AsArgument(info, context); - } - public TypeSyntax AsNativeType(TypePositionInfo info) { return _innerMarshaller.AsNativeType(info); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalAsMarshallingGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalAsMarshallingGeneratorFactory.cs index e754c5469c3ca5..4355feac8a1934 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalAsMarshallingGeneratorFactory.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalAsMarshallingGeneratorFactory.cs @@ -13,7 +13,7 @@ public sealed class MarshalAsMarshallingGeneratorFactory : IMarshallingGenerator private static readonly VariantBoolMarshaller s_variantBool = new(); private static readonly Utf16CharMarshaller s_utf16Char = new(); - private static readonly Utf16StringMarshaller s_utf16String = new(); + private static readonly IMarshallingGenerator s_utf16String = new PinnableManagedValueMarshaller(new Utf16StringMarshaller()); private static readonly Utf8StringMarshaller s_utf8String = new(); private static readonly AnsiStringMarshaller s_ansiString = new AnsiStringMarshaller(s_utf8String); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs index bad094d4ed3578..65ef66ce0438b3 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs @@ -20,6 +20,44 @@ public enum TargetFramework Net } + /// + /// An enumeration describing how a should be represented in its corresponding native signature element (parameter, field, or return value). + /// + public enum SignatureBehavior + { + /// + /// The native type should match the managed type, including rehydrating marshalling attributes and by-ref syntax (pure forwarding). + /// + ManagedTypeAndAttributes, + /// + /// The native signature should be the type returned by passed by value. + /// + NativeType, + /// + /// The native signature should be a pointer to the type returned by passed by value. + /// + PointerToNativeType + } + + /// + /// An enumeration describing how a should be represented in its corresponding native signature element (parameter, field, or return value). + /// + public enum ValueBoundaryBehavior + { + /// + /// The managed value should be passed as-is, including any managed by-ref syntax used in the managed declaration. + /// + ManagedIdentifier, + /// + /// The native identifier provided by should be passed by value. + /// + NativeIdentifier, + /// + /// The address of the native identifier provided by should be passed by value. + /// + AddressOfNativeIdentifier + } + /// /// Interface for generation of marshalling code for P/Invoke stubs /// @@ -41,19 +79,19 @@ public interface IMarshallingGenerator TypeSyntax AsNativeType(TypePositionInfo info); /// - /// Get the as a parameter of the P/Invoke declaration + /// Get shape that represents the provided in the native signature /// /// Object to marshal /// Parameter syntax for - ParameterSyntax AsParameter(TypePositionInfo info); + SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info); /// - /// Get the as an argument to be passed to the P/Invoke + /// Get shape of how the value represented by should be passed at the managed/native boundary in the provided /// /// Object to marshal /// Code generation context /// Argument syntax for - ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context); + ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context); /// /// Generate code for marshalling @@ -91,19 +129,6 @@ public interface IMarshallingGenerator bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context); } - /// - /// Interface for generating attributes for native return types. - /// - public interface IAttributedReturnTypeMarshallingGenerator : IMarshallingGenerator - { - /// - /// Gets any attributes that should be applied to the return type for this . - /// - /// Object to marshal - /// Attributes for the return type for this , or null if no attributes should be added. - AttributeListSyntax? GenerateAttributesForReturnType(TypePositionInfo info); - } - /// /// Exception used to indicate marshalling isn't supported. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs new file mode 100644 index 00000000000000..6cd7da3f430570 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs @@ -0,0 +1,210 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public static class MarshallingGeneratorExtensions + { + /// + /// Gets the return type for the unmanaged signature that represents the provided . + /// + /// The marshalling generator for this + /// Object to marshal + public static TypeSyntax AsReturnType(this IMarshallingGenerator generator, TypePositionInfo info) + { + return generator.GetNativeSignatureBehavior(info) switch + { + SignatureBehavior.ManagedTypeAndAttributes => info.ManagedType.Syntax, + SignatureBehavior.NativeType => generator.AsNativeType(info), + SignatureBehavior.PointerToNativeType => PointerType(generator.AsNativeType(info)), + _ => throw new InvalidOperationException() + }; + } + /// + /// Gets any attributes that should be applied to the return type for this . + /// + /// The marshalling generator for this + /// Object to marshal + /// Attributes for the return type for this , or null if no attributes should be added. + public static AttributeListSyntax? GenerateAttributesForReturnType(this IMarshallingGenerator generator, TypePositionInfo info) + { + if (generator.GetNativeSignatureBehavior(info) != SignatureBehavior.ManagedTypeAndAttributes) + { + return null; + } + + if (!TryRehydrateMarshalAsAttribute(info, out AttributeSyntax marshalAsAttribute)) + { + return null; + } + return AttributeList(SingletonSeparatedList(marshalAsAttribute)); + } + + /// + /// Gets a parameter for the unmanaged signature that represents the provided . + /// + /// The marshalling generator for this + /// Object to marshal + public static ParameterSyntax AsParameter(this IMarshallingGenerator generator, TypePositionInfo info) + { + SignatureBehavior behavior = generator.GetNativeSignatureBehavior(info); + if (behavior == SignatureBehavior.ManagedTypeAndAttributes) + { + return GenerateForwardingParameter(info); + } + return Parameter(Identifier(info.InstanceIdentifier)) + .WithType(behavior switch + { + SignatureBehavior.NativeType => generator.AsNativeType(info), + SignatureBehavior.PointerToNativeType => PointerType(generator.AsNativeType(info)), + _ => throw new InvalidOperationException() + }); + } + + private static ParameterSyntax GenerateForwardingParameter(TypePositionInfo info) + { + ParameterSyntax param = Parameter(Identifier(info.InstanceIdentifier)) + .WithModifiers(TokenList(Token(info.RefKindSyntax))) + .WithType(info.ManagedType.Syntax); + + List rehydratedAttributes = new(); + if (TryRehydrateMarshalAsAttribute(info, out AttributeSyntax marshalAsAttribute)) + { + rehydratedAttributes.Add(marshalAsAttribute); + } + if (info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.In)) + { + rehydratedAttributes.Add(Attribute(IdentifierName(TypeNames.System_Runtime_InteropServices_InAttribute))); + } + if (info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) + { + rehydratedAttributes.Add(Attribute(IdentifierName(TypeNames.System_Runtime_InteropServices_OutAttribute))); + } + + if (rehydratedAttributes.Count > 0) + { + param = param.AddAttributeLists(AttributeList(SeparatedList(rehydratedAttributes))); + } + + return param; + } + + + private static bool TryRehydrateMarshalAsAttribute(TypePositionInfo info, out AttributeSyntax marshalAsAttribute) + { + marshalAsAttribute = null!; + // If the parameter has [MarshalAs] marshalling, we resurface that + // in the forwarding target since the built-in system understands it. + // ICustomMarshaller marshalling requires additional information that we throw away earlier since it's unsupported, + // so explicitly do not resurface a [MarshalAs(UnmanagdType.CustomMarshaler)] attribute. + if (info.MarshallingAttributeInfo is MarshalAsInfo { UnmanagedType: not UnmanagedType.CustomMarshaler } marshalAs) + { + marshalAsAttribute = Attribute(ParseName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute)) + .WithArgumentList(AttributeArgumentList(SingletonSeparatedList(AttributeArgument( + CastExpression(ParseTypeName(TypeNames.System_Runtime_InteropServices_UnmanagedType), + LiteralExpression(SyntaxKind.NumericLiteralExpression, + Literal((int)marshalAs.UnmanagedType))))))); + return true; + } + + if (info.ManagedType is SzArrayType) + { + CountInfo countInfo; + MarshallingInfo elementMarshallingInfo; + if (info.MarshallingAttributeInfo is NativeContiguousCollectionMarshallingInfo collectionMarshalling + && collectionMarshalling.UseDefaultMarshalling + && collectionMarshalling.ElementCountInfo is NoCountInfo or SizeAndParamIndexInfo + && collectionMarshalling.ElementMarshallingInfo is NoMarshallingInfo or MarshalAsInfo { UnmanagedType: not UnmanagedType.CustomMarshaler } + ) + { + countInfo = collectionMarshalling.ElementCountInfo; + elementMarshallingInfo = collectionMarshalling.ElementMarshallingInfo; + } + else if (info.MarshallingAttributeInfo is MissingSupportCollectionMarshallingInfo missingSupport) + { + countInfo = missingSupport.CountInfo; + elementMarshallingInfo = missingSupport.ElementMarshallingInfo; + } + else + { + // This condition can be hit in two ways: + // 1. User uses the MarshalUsing attribute to provide count info or element marshalling information. + // Since the MarshalUsing attribute doesn't exist on downlevel platforms where we don't support arrays, + // this case is unlikely to come in supported scenarios, but could come up with a custom CoreLib implementation + // 2. User provides a MarsalAs attribute with the ArraySubType field set to UnmanagedType.CustomMarshaler + // As mentioned above, we don't support ICustomMarshaler in the generator so we fail to forward the attribute instead of partially fowarding it. + return false; + } + + List marshalAsArguments = new List + { + AttributeArgument( + CastExpression(ParseTypeName(TypeNames.System_Runtime_InteropServices_UnmanagedType), + LiteralExpression(SyntaxKind.NumericLiteralExpression, + Literal((int)UnmanagedType.LPArray)))) + }; + + if (countInfo is SizeAndParamIndexInfo sizeParamIndex) + { + if (sizeParamIndex.ConstSize != SizeAndParamIndexInfo.UnspecifiedConstSize) + { + marshalAsArguments.Add( + AttributeArgument(NameEquals("SizeConst"), null, + LiteralExpression(SyntaxKind.NumericLiteralExpression, + Literal(sizeParamIndex.ConstSize))) + ); + } + if (sizeParamIndex.ParamAtIndex is { ManagedIndex: int paramIndex }) + { + marshalAsArguments.Add( + AttributeArgument(NameEquals("SizeParamIndex"), null, + LiteralExpression(SyntaxKind.NumericLiteralExpression, + Literal(paramIndex))) + ); + } + } + + if (elementMarshallingInfo is MarshalAsInfo elementMarshalAs) + { + marshalAsArguments.Add( + AttributeArgument(NameEquals("ArraySubType"), null, + CastExpression(ParseTypeName(TypeNames.System_Runtime_InteropServices_UnmanagedType), + LiteralExpression(SyntaxKind.NumericLiteralExpression, + Literal((int)elementMarshalAs.UnmanagedType)))) + ); + } + marshalAsAttribute = Attribute(ParseName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute)) + .WithArgumentList(AttributeArgumentList(SeparatedList(marshalAsArguments))); + return true; + } + + return false; + } + + /// + /// Gets an argument expression for the unmanaged signature that can be used to pass a value of the provided in the specified . + /// + /// The marshalling generator for this + /// Object to marshal + /// Marshalling context + public static ArgumentSyntax AsArgument(this IMarshallingGenerator generator, TypePositionInfo info, StubCodeContext context) + { + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + return generator.GetValueBoundaryBehavior(info, context) switch + { + ValueBoundaryBehavior.ManagedIdentifier when !info.IsByRef => Argument(IdentifierName(managedIdentifier)), + ValueBoundaryBehavior.ManagedIdentifier when info.IsByRef => Argument(IdentifierName(managedIdentifier)).WithRefKindKeyword(Token(info.RefKindSyntax)), + ValueBoundaryBehavior.NativeIdentifier => Argument(IdentifierName(nativeIdentifier)), + ValueBoundaryBehavior.AddressOfNativeIdentifier => Argument(PrefixUnaryExpression(SyntaxKind.AddressOfExpression, IdentifierName(nativeIdentifier))), + _ => throw new InvalidOperationException() + }; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/PinnableManagedValueMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/PinnableManagedValueMarshaller.cs index e5890d04e95671..191713bbf019f4 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/PinnableManagedValueMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/PinnableManagedValueMarshaller.cs @@ -11,34 +11,33 @@ namespace Microsoft.Interop { public sealed class PinnableManagedValueMarshaller : IMarshallingGenerator { - private readonly IMarshallingGenerator _manualMarshallingGenerator; + private readonly IMarshallingGenerator _innerMarshallingGenerator; - public PinnableManagedValueMarshaller(IMarshallingGenerator manualMarshallingGenerator) + public PinnableManagedValueMarshaller(IMarshallingGenerator innerMarshallingGenerator) { - _manualMarshallingGenerator = manualMarshallingGenerator; + _innerMarshallingGenerator = innerMarshallingGenerator; } public bool IsSupported(TargetFramework target, Version version) - => _manualMarshallingGenerator.IsSupported(target, version); + => _innerMarshallingGenerator.IsSupported(target, version); - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { if (IsPinningPathSupported(info, context)) { - string identifier = context.GetIdentifiers(info).native; - return Argument(CastExpression(AsNativeType(info), IdentifierName(identifier))); + return ValueBoundaryBehavior.NativeIdentifier; } - return _manualMarshallingGenerator.AsArgument(info, context); + return _innerMarshallingGenerator.GetValueBoundaryBehavior(info, context); } public TypeSyntax AsNativeType(TypePositionInfo info) { - return _manualMarshallingGenerator.AsNativeType(info); + return _innerMarshallingGenerator.AsNativeType(info); } - public ParameterSyntax AsParameter(TypePositionInfo info) + public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { - return _manualMarshallingGenerator.AsParameter(info); + return _innerMarshallingGenerator.GetNativeSignatureBehavior(info); } public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) @@ -47,12 +46,12 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont { return GeneratePinningPath(info, context); } - return _manualMarshallingGenerator.Generate(info, context); + return _innerMarshallingGenerator.Generate(info, context); } public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) { - return _manualMarshallingGenerator.SupportsByValueMarshalKind(marshalKind, context); + return _innerMarshallingGenerator.SupportsByValueMarshalKind(marshalKind, context); } public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) @@ -61,7 +60,7 @@ public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) { return false; } - return _manualMarshallingGenerator.UsesNativeIdentifier(info, context); + return _innerMarshallingGenerator.UsesNativeIdentifier(info, context); } private static bool IsPinningPathSupported(TypePositionInfo info, StubCodeContext context) { @@ -73,17 +72,26 @@ private IEnumerable GeneratePinningPath(TypePositionInfo info, if (context.CurrentStage == StubCodeContext.Stage.Pin) { (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + string pinnedIdentifier = context.GetAdditionalIdentifier(info, "pinned"); yield return FixedStatement( VariableDeclaration( PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))), SingletonSeparatedList( - VariableDeclarator(Identifier(nativeIdentifier)) + VariableDeclarator(Identifier(pinnedIdentifier)) .WithInitializer(EqualsValueClause( IdentifierName(managedIdentifier) )) ) ), - EmptyStatement() + // = (); + LocalDeclarationStatement( + VariableDeclaration(AsNativeType(info), + SingletonSeparatedList( + VariableDeclarator(nativeIdentifier) + .WithInitializer(EqualsValueClause( + CastExpression( + AsNativeType(info), + IdentifierName(pinnedIdentifier))))))) ); } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs index 59dc0b6001bd21..363fc3846637af 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs @@ -23,27 +23,14 @@ public TypeSyntax AsNativeType(TypePositionInfo info) return MarshallerHelpers.SystemIntPtrType; } - public ParameterSyntax AsParameter(TypePositionInfo info) + public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { - TypeSyntax type = info.IsByRef - ? PointerType(AsNativeType(info)) - : AsNativeType(info); - return Parameter(Identifier(info.InstanceIdentifier)) - .WithType(type); + return info.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; } - public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { - string identifier = context.GetIdentifiers(info).native; - if (info.IsByRef) - { - return Argument( - PrefixUnaryExpression( - SyntaxKind.AddressOfExpression, - IdentifierName(identifier))); - } - - return Argument(IdentifierName(identifier)); + return info.IsByRef ? ValueBoundaryBehavior.AddressOfNativeIdentifier : ValueBoundaryBehavior.NativeIdentifier; } public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs index 40c09b0ed1890d..d279cb5d486e96 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs @@ -23,38 +23,20 @@ public AnsiStringMarshaller(Utf8StringMarshaller utf8StringMarshaller) _utf8StringMarshaller = utf8StringMarshaller; } - public override ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + public override SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { - string identifier = context.GetIdentifiers(info).native; - if (info.IsByRef) - { - // & - return Argument( - PrefixUnaryExpression( - SyntaxKind.AddressOfExpression, - IdentifierName(identifier))); - } - - // - return Argument(IdentifierName(identifier)); + return info.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; } - public override TypeSyntax AsNativeType(TypePositionInfo info) + public override ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { - // byte* - return s_nativeType; + return info.IsByRef ? ValueBoundaryBehavior.AddressOfNativeIdentifier : ValueBoundaryBehavior.NativeIdentifier; } - public override ParameterSyntax AsParameter(TypePositionInfo info) + public override TypeSyntax AsNativeType(TypePositionInfo info) { - // byte** - // or // byte* - TypeSyntax type = info.IsByRef - ? PointerType(AsNativeType(info)) - : AsNativeType(info); - return Parameter(Identifier(info.InstanceIdentifier)) - .WithType(type); + return s_nativeType; } public override IEnumerable Generate(TypePositionInfo info, StubCodeContext context) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs index 979d806d4c0fcd..956098935e6bd2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs @@ -20,69 +20,25 @@ public sealed class Utf16StringMarshaller : ConditionalStackallocMarshallingGene private static readonly TypeSyntax s_nativeType = PointerType(PredefinedType(Token(SyntaxKind.UShortKeyword))); - private static string PinnedIdentifier(string nativeIdentifier) => $"{nativeIdentifier}__pinned"; - - public override ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + public override SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { - string identifier = context.GetIdentifiers(info).native; - if (info.IsByRef) - { - // & - return Argument( - PrefixUnaryExpression( - SyntaxKind.AddressOfExpression, - IdentifierName(identifier))); - } - else if (context.SingleFrameSpansNativeContext) - { - // (ushort*) - return Argument( - CastExpression( - AsNativeType(info), - IdentifierName(PinnedIdentifier(identifier)))); - } - - // - return Argument(IdentifierName(identifier)); + return info.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; } - public override TypeSyntax AsNativeType(TypePositionInfo info) + public override ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { - // ushort* - return s_nativeType; + return info.IsByRef ? ValueBoundaryBehavior.AddressOfNativeIdentifier : ValueBoundaryBehavior.NativeIdentifier; } - public override ParameterSyntax AsParameter(TypePositionInfo info) + public override TypeSyntax AsNativeType(TypePositionInfo info) { - // ushort** - // or // ushort* - TypeSyntax type = info.IsByRef - ? PointerType(AsNativeType(info)) - : AsNativeType(info); - return Parameter(Identifier(info.InstanceIdentifier)) - .WithType(type); + return s_nativeType; } public override IEnumerable Generate(TypePositionInfo info, StubCodeContext context) { (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); - if (context.SingleFrameSpansNativeContext && !info.IsByRef && !info.IsManagedReturnPosition) - { - if (context.CurrentStage == StubCodeContext.Stage.Pin) - { - // fixed (char* = ) - yield return FixedStatement( - VariableDeclaration( - PointerType(PredefinedType(Token(SyntaxKind.CharKeyword))), - SingletonSeparatedList( - VariableDeclarator(Identifier(PinnedIdentifier(nativeIdentifier))) - .WithInitializer(EqualsValueClause(IdentifierName(managedIdentifier))))), - EmptyStatement()); - } - - yield break; - } switch (context.CurrentStage) { @@ -135,7 +91,7 @@ public override IEnumerable Generate(TypePositionInfo info, Stu } public override bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) - => info.IsManagedReturnPosition || info.IsByRef || !context.SingleFrameSpansNativeContext; + => true; public override bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => false; @@ -216,7 +172,7 @@ protected override StatementSyntax GenerateStackallocOnlyValueMarshalling( PointerType(PredefinedType(Token(SyntaxKind.CharKeyword))), IdentifierName(stackAllocPtrIdentifier))), BracketedArgumentList( - SingletonSeparatedList( + SingletonSeparatedList( Argument( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs index 8414b271b0ef6f..1774811838fb64 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs @@ -29,31 +29,18 @@ public sealed class Utf8StringMarshaller : ConditionalStackallocMarshallingGener private static readonly TypeSyntax s_nativeType = PointerType(PredefinedType(Token(SyntaxKind.ByteKeyword))); private static readonly TypeSyntax s_utf8EncodingType = ParseTypeName("System.Text.Encoding.UTF8"); - public override ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + public override SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) { - string identifier = context.GetIdentifiers(info).native; - if (info.IsByRef) - { - return Argument( - PrefixUnaryExpression( - SyntaxKind.AddressOfExpression, - IdentifierName(identifier))); - } - - return Argument(IdentifierName(identifier)); + return info.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; } - public override TypeSyntax AsNativeType(TypePositionInfo info) => s_nativeType; - - public override ParameterSyntax AsParameter(TypePositionInfo info) + public override ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) { - TypeSyntax type = info.IsByRef - ? PointerType(AsNativeType(info)) - : AsNativeType(info); - return Parameter(Identifier(info.InstanceIdentifier)) - .WithType(type); + return info.IsByRef ? ValueBoundaryBehavior.AddressOfNativeIdentifier : ValueBoundaryBehavior.NativeIdentifier; } + public override TypeSyntax AsNativeType(TypePositionInfo info) => s_nativeType; + public override IEnumerable Generate(TypePositionInfo info, StubCodeContext context) { (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info);