diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
index 6e86818b1d237..eeefa8f376b13 100644
--- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
+++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
@@ -877,14 +877,12 @@
-
-
-
-
+
+
diff --git a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs
index df636135d3547..80889981a05b2 100644
--- a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs
@@ -4,6 +4,7 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
using System.Runtime.Versioning;
using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
@@ -20,6 +21,9 @@ namespace System
[DebuggerTypeProxy(typeof(SpanDebugView<>))]
[DebuggerDisplay("{ToString(),raw}")]
[NonVersionable]
+#pragma warning disable SYSLIB1056 // Specified native type is invalid
+ [NativeMarshalling(typeof(ReadOnlySpanMarshaller<,>))]
+#pragma warning restore SYSLIB1056 // Specified native type is invalid
public readonly ref struct ReadOnlySpan
{
/// A byref or a native ptr.
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomTypeMarshallerAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomTypeMarshallerAttribute.cs
deleted file mode 100644
index 1bdad6fbaedc0..0000000000000
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomTypeMarshallerAttribute.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace System.Runtime.InteropServices.Marshalling
-{
- ///
- /// Attribute used to indicate that the type can be used to convert a value of the provided to a native representation.
- ///
- ///
- /// This attribute is recognized by the runtime-provided source generators for source-generated interop scenarios.
- /// It is not used by the interop marshalling system at runtime.
- ///
- ///
- [AttributeUsage(AttributeTargets.Struct)]
- public sealed class CustomTypeMarshallerAttribute : Attribute
- {
- public CustomTypeMarshallerAttribute(Type managedType, CustomTypeMarshallerKind marshallerKind = CustomTypeMarshallerKind.Value)
- {
- ManagedType = managedType;
- MarshallerKind = marshallerKind;
- }
-
- ///
- /// The managed type for which the attributed type is a marshaller
- ///
- public Type ManagedType { get; }
-
- ///
- /// The required shape of the attributed type
- ///
- public CustomTypeMarshallerKind MarshallerKind { get; }
-
- ///
- /// When the flag is set on the size of the caller-allocated buffer in number of elements.
- ///
- public int BufferSize { get; set; }
-
- ///
- /// The marshalling directions this custom type marshaller supports.
- ///
- /// Default is
- public CustomTypeMarshallerDirection Direction { get; set; } = CustomTypeMarshallerDirection.Ref;
-
- ///
- /// The optional features for the that the marshaller supports.
- ///
- public CustomTypeMarshallerFeatures Features { get; set; }
-
- ///
- /// This type is used as a placeholder for the first generic parameter when generic parameters cannot be used
- /// to identify the managed type (i.e. when the marshaller type is generic over T and the managed type is T[])
- ///
- public struct GenericPlaceholder
- {
- }
- }
-}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomTypeMarshallerFeatures.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomTypeMarshallerFeatures.cs
deleted file mode 100644
index 7c2520bbecd07..0000000000000
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomTypeMarshallerFeatures.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-using System;
-
-#if MICROSOFT_INTEROP_SOURCEGENERATION
-namespace Microsoft.Interop
-#else
-namespace System.Runtime.InteropServices.Marshalling
-#endif
-{
- ///
- /// Optional features supported by custom type marshallers.
- ///
- [Flags]
- public enum CustomTypeMarshallerFeatures
- {
- ///
- /// No optional features supported
- ///
- None = 0,
- ///
- /// The marshaller owns unmanaged resources that must be freed
- ///
- UnmanagedResources = 0x1,
- ///
- /// The marshaller can use a caller-allocated buffer instead of allocating in some scenarios
- ///
- CallerAllocatedBuffer = 0x2,
- ///
- /// The marshaller uses the two-stage marshalling design for its instead of the one-stage design.
- ///
- TwoStageMarshalling = 0x4
- }
-}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomTypeMarshallerKind.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomTypeMarshallerKind.cs
deleted file mode 100644
index 02cba782fd6e0..0000000000000
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomTypeMarshallerKind.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#if MICROSOFT_INTEROP_SOURCEGENERATION
-namespace Microsoft.Interop
-#else
-namespace System.Runtime.InteropServices.Marshalling
-#endif
-{
- ///
- /// The shape of a custom type marshaller for usage in source-generated interop scenarios.
- ///
- ///
- public enum CustomTypeMarshallerKind
- {
- ///
- /// This custom type marshaller represents a single value.
- ///
- Value,
- ///
- /// This custom type marshaller represents a container of values that are placed sequentially in memory.
- ///
- LinearCollection
- }
-}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/MarshalUsingAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/MarshalUsingAttribute.cs
index f10c2743a6021..fefeba869b150 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/MarshalUsingAttribute.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/MarshalUsingAttribute.cs
@@ -10,7 +10,7 @@ namespace System.Runtime.InteropServices.Marshalling
/// This attribute is recognized by the runtime-provided source generators for source-generated interop scenarios.
/// It is not used by the interop marshalling system at runtime.
///
- ///
+ ///
///
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)]
public sealed class MarshalUsingAttribute : Attribute
@@ -26,7 +26,7 @@ public MarshalUsingAttribute()
///
/// Create a that provides a native marshalling type and optionally size information.
///
- /// The marshaller type used to convert the attributed type from managed to native code. This type must be attributed with
+ /// The marshaller type used to convert the attributed type from managed to native code. This type must be attributed with
public MarshalUsingAttribute(Type nativeType)
: this()
{
@@ -34,7 +34,7 @@ public MarshalUsingAttribute(Type nativeType)
}
///
- /// The marshaller type used to convert the attributed type from managed to native code. This type must be attributed with
+ /// The marshaller type used to convert the attributed type from managed to native code. This type must be attributed with
///
public Type? NativeType { get; }
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/NativeMarshallingAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/NativeMarshallingAttribute.cs
index c4883cba97a46..2c0d604b19196 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/NativeMarshallingAttribute.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/NativeMarshallingAttribute.cs
@@ -10,7 +10,7 @@ namespace System.Runtime.InteropServices.Marshalling
/// This attribute is recognized by the runtime-provided source generators for source-generated interop scenarios.
/// It is not used by the interop marshalling system at runtime.
///
- ///
+ ///
///
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Delegate)]
public sealed class NativeMarshallingAttribute : Attribute
@@ -18,14 +18,14 @@ public sealed class NativeMarshallingAttribute : Attribute
///
/// Create a that provides a native marshalling type.
///
- /// The marshaller type used to convert the attributed type from managed to native code. This type must be attributed with
+ /// The marshaller type used to convert the attributed type from managed to native code. This type must be attributed with
public NativeMarshallingAttribute(Type nativeType)
{
NativeType = nativeType;
}
///
- /// The marshaller type used to convert the attributed type from managed to native code. This type must be attributed with
+ /// The marshaller type used to convert the attributed type from managed to native code. This type must be attributed with
///
public Type NativeType { get; }
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ReadOnlySpanMarshaller.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ReadOnlySpanMarshaller.cs
new file mode 100644
index 0000000000000..148c7aa38501c
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ReadOnlySpanMarshaller.cs
@@ -0,0 +1,166 @@
+// 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.CompilerServices;
+using System.Text;
+
+namespace System.Runtime.InteropServices.Marshalling
+{
+ ///
+ /// The type supports marshalling a from managed value
+ /// to a contiguous native array of the unmanaged values of the elements.
+ ///
+ /// The managed element type of the span.
+ /// The unmanaged type for the elements of the span.
+ ///
+ /// A marshalled with this marshaller will match the semantics of .
+ /// In particular, this marshaller will pass a non-null value for a zero-length span if the span was constructed with a non-null value.
+ ///
+ [CLSCompliant(false)]
+ [CustomMarshaller(typeof(ReadOnlySpan<>), MarshalMode.ManagedToUnmanagedIn, typeof(ReadOnlySpanMarshaller<,>.ManagedToUnmanagedIn))]
+ [CustomMarshaller(typeof(ReadOnlySpan<>), MarshalMode.UnmanagedToManagedOut, typeof(ReadOnlySpanMarshaller<,>.UnmanagedToManagedOut))]
+ [ContiguousCollectionMarshaller]
+ public static unsafe class ReadOnlySpanMarshaller
+ where TUnmanagedElement : unmanaged
+ {
+ ///
+ /// The marshaller type that supports marshalling from managed into unmanaged in a call from unmanaged code to managed code.
+ ///
+ public static unsafe class UnmanagedToManagedOut
+ {
+ ///
+ /// Allocate the space to store the unmanaged elements.
+ ///
+ /// The managed span.
+ /// The number of elements in the span.
+ /// A pointer to the block of memory for the unmanaged elements.
+ public static TUnmanagedElement* AllocateContainerForUnmanagedElements(ReadOnlySpan managed, out int numElements)
+ {
+ // Emulate the pinning behavior:
+ // If the span is over a null reference, then pass a null pointer.
+ if (Unsafe.IsNullRef(ref MemoryMarshal.GetReference(managed)))
+ {
+ numElements = 0;
+ return null;
+ }
+
+ numElements = managed.Length;
+
+ // Always allocate at least one byte when the array is zero-length.
+ int spaceToAllocate = Math.Max(checked(sizeof(TUnmanagedElement) * numElements), 1);
+ return (TUnmanagedElement*)Marshal.AllocCoTaskMem(spaceToAllocate);
+ }
+
+ ///
+ /// Get a span of the managed collection elements.
+ ///
+ /// The managed collection.
+ /// A span of the managed collection elements.
+ public static ReadOnlySpan GetManagedValuesSource(ReadOnlySpan managed)
+ => managed;
+
+ ///
+ /// Get a span of the space where the unmanaged collection elements should be stored.
+ ///
+ /// The pointer to the block of memory for the unmanaged elements.
+ /// The number of elements that will be copied into the memory block.
+ /// A span over the unmanaged memory that can contain the specified number of elements.
+ public static Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements)
+ => new Span(unmanaged, numElements);
+ }
+
+ ///
+ /// The marshaller type that supports marshalling from managed into unmanaged in a call from managed code to unmanaged code.
+ ///
+ public ref struct ManagedToUnmanagedIn
+ {
+ ///
+ /// The size of the caller-allocated buffer to allocate.
+ ///
+ // We'll keep the buffer size at a maximum of 200 bytes to avoid overflowing the stack.
+ public static int BufferSize { get; } = 0x200 / sizeof(TUnmanagedElement);
+
+ private ReadOnlySpan _managedArray;
+ private TUnmanagedElement* _allocatedMemory;
+ private Span _span;
+
+ ///
+ /// Initializes the marshaller.
+ ///
+ /// Span to be marshalled.
+ /// Buffer that may be used for marshalling.
+ ///
+ /// The must not be movable - that is, it should not be
+ /// on the managed heap or it should be pinned.
+ ///
+ public void FromManaged(ReadOnlySpan managed, Span buffer)
+ {
+ _allocatedMemory = null;
+ // Emulate the pinning behavior:
+ // If the span is over a null reference, then pass a null pointer.
+ if (Unsafe.IsNullRef(ref MemoryMarshal.GetReference(managed)))
+ {
+ _managedArray = null;
+ _span = default;
+ return;
+ }
+
+ _managedArray = managed;
+
+ // Always allocate at least one byte when the span is zero-length.
+ if (managed.Length <= buffer.Length)
+ {
+ _span = buffer[0..managed.Length];
+ }
+ else
+ {
+ int bufferSize = checked(managed.Length * sizeof(TUnmanagedElement));
+ _allocatedMemory = (TUnmanagedElement*)NativeMemory.Alloc((nuint)bufferSize);
+ _span = new Span(_allocatedMemory, managed.Length);
+ }
+ }
+
+ ///
+ /// Gets a span that points to the memory where the managed values of the array are stored.
+ ///
+ /// Span over managed values of the array.
+ public ReadOnlySpan GetManagedValuesSource() => _managedArray;
+
+ ///
+ /// Returns a span that points to the memory where the unmanaged values of the array should be stored.
+ ///
+ /// Span where unmanaged values of the array should be stored.
+ public Span GetUnmanagedValuesDestination() => _span;
+
+ ///
+ /// Returns a reference to the marshalled array.
+ ///
+ public ref TUnmanagedElement GetPinnableReference() => ref MemoryMarshal.GetReference(_span);
+
+ ///
+ /// Returns the unmanaged value representing the array.
+ ///
+ public TUnmanagedElement* ToUnmanaged() => (TUnmanagedElement*)Unsafe.AsPointer(ref GetPinnableReference());
+
+ ///
+ /// Frees resources.
+ ///
+ public void Free()
+ {
+ NativeMemory.Free(_allocatedMemory);
+ }
+
+ ///
+ /// Pin the managed span to a pointer to pass directly to unmanaged code.
+ ///
+ /// The managed span.
+ /// A reference that can be pinned and directly passed to unmanaged code.
+ public static ref T GetPinnableReference(ReadOnlySpan managed)
+ {
+ return ref MemoryMarshal.GetReference(managed);
+ }
+ }
+ }
+}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/SpanMarshaller.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/SpanMarshaller.cs
new file mode 100644
index 0000000000000..bccaef9203e6d
--- /dev/null
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/SpanMarshaller.cs
@@ -0,0 +1,189 @@
+// 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.CompilerServices;
+using System.Text;
+
+namespace System.Runtime.InteropServices.Marshalling
+{
+ ///
+ /// The type supports marshalling a from managed value
+ /// to a contiguous native array of the unmanaged values of the elements.
+ ///
+ /// The managed element type of the span.
+ /// The unmanaged type for the elements of the span.
+ ///
+ /// A marshalled with this marshaller will match the semantics of .
+ /// In particular, this marshaller will pass a non-null value for a zero-length span if the span was constructed with a non-null value.
+ ///
+ [CLSCompliant(false)]
+ [CustomMarshaller(typeof(Span<>), MarshalMode.Default, typeof(SpanMarshaller<,>))]
+ [CustomMarshaller(typeof(Span<>), MarshalMode.ManagedToUnmanagedIn, typeof(SpanMarshaller<,>.ManagedToUnmanagedIn))]
+ [ContiguousCollectionMarshaller]
+ public static unsafe class SpanMarshaller
+ where TUnmanagedElement : unmanaged
+ {
+ ///
+ /// Allocate the space to store the unmanaged elements.
+ ///
+ /// The managed span.
+ /// The number of elements in the span.
+ /// A pointer to the block of memory for the unmanaged elements.
+ public static TUnmanagedElement* AllocateContainerForUnmanagedElements(Span managed, out int numElements)
+ {
+ // Emulate the pinning behavior:
+ // If the span is over a null reference, then pass a null pointer.
+ if (Unsafe.IsNullRef(ref MemoryMarshal.GetReference(managed)))
+ {
+ numElements = 0;
+ return null;
+ }
+
+ numElements = managed.Length;
+
+ // Always allocate at least one byte when the array is zero-length.
+ int spaceToAllocate = Math.Max(checked(sizeof(TUnmanagedElement) * numElements), 1);
+ return (TUnmanagedElement*)Marshal.AllocCoTaskMem(spaceToAllocate);
+ }
+
+ ///
+ /// Get a span of the managed collection elements.
+ ///
+ /// The managed collection.
+ /// A span of the managed collection elements.
+ public static ReadOnlySpan GetManagedValuesSource(Span managed)
+ => managed;
+
+ ///
+ /// Get a span of the space where the unmanaged collection elements should be stored.
+ ///
+ /// The pointer to the block of memory for the unmanaged elements.
+ /// The number of elements that will be copied into the memory block.
+ /// A span over the unmanaged memory that can contain the specified number of elements.
+ public static Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements)
+ => new Span(unmanaged, numElements);
+
+ ///
+ /// Allocate the space to store the managed elements.
+ ///
+ /// The unmanaged value.
+ /// The number of elements in the unmanaged collection.
+ /// A span over enough memory to contain elements.
+ public static Span AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements)
+ {
+ if (unmanaged is null)
+ return null;
+
+ return new T[numElements];
+ }
+
+ ///
+ /// Get a span of the space where the managed collection elements should be stored.
+ ///
+ /// A span over the space to store the managed elements
+ /// A span over the managed memory that can contain the specified number of elements.
+ public static Span GetManagedValuesDestination(Span managed)
+ => managed;
+
+ ///
+ /// Get a span of the native collection elements.
+ ///
+ /// The unmanaged value.
+ /// The number of elements in the unmanaged collection.
+ /// A span over the native collection elements.
+ public static ReadOnlySpan GetUnmanagedValuesSource(TUnmanagedElement* unmanaged, int numElements)
+ => new ReadOnlySpan(unmanaged, numElements);
+
+ ///
+ /// Free the allocated unmanaged memory.
+ ///
+ /// Allocated unmanaged memory
+ public static void Free(TUnmanagedElement* unmanaged)
+ => Marshal.FreeCoTaskMem((IntPtr)unmanaged);
+
+ ///
+ /// The marshaller type that supports marshalling from managed into unmanaged in a call from managed code to unmanaged code.
+ ///
+ public ref struct ManagedToUnmanagedIn
+ {
+ // We'll keep the buffer size at a maximum of 200 bytes to avoid overflowing the stack.
+ public static int BufferSize { get; } = 0x200 / sizeof(TUnmanagedElement);
+
+ private Span _managedArray;
+ private TUnmanagedElement* _allocatedMemory;
+ private Span _span;
+
+ ///
+ /// Initializes the marshaller.
+ ///
+ /// Span to be marshalled.
+ /// Buffer that may be used for marshalling.
+ ///
+ /// The must not be movable - that is, it should not be
+ /// on the managed heap or it should be pinned.
+ ///
+ public void FromManaged(Span managed, Span buffer)
+ {
+ _allocatedMemory = null;
+ // Emulate the pinning behavior:
+ // If the span is over a null reference, then pass a null pointer.
+ if (Unsafe.IsNullRef(ref MemoryMarshal.GetReference(managed)))
+ {
+ _managedArray = null;
+ _span = default;
+ return;
+ }
+
+ _managedArray = managed;
+
+ if (managed.Length <= buffer.Length)
+ {
+ _span = buffer[0..managed.Length];
+ }
+ else
+ {
+ int bufferSize = checked(managed.Length * sizeof(TUnmanagedElement));
+ _allocatedMemory = (TUnmanagedElement*)NativeMemory.Alloc((nuint)bufferSize);
+ _span = new Span(_allocatedMemory, managed.Length);
+ }
+ }
+
+ ///
+ /// Gets a span that points to the memory where the managed values of the array are stored.
+ ///
+ /// Span over managed values of the array.
+ public ReadOnlySpan GetManagedValuesSource() => _managedArray;
+
+ ///
+ /// Returns a span that points to the memory where the unmanaged values of the array should be stored.
+ ///
+ /// Span where unmanaged values of the array should be stored.
+ public Span GetUnmanagedValuesDestination() => _span;
+
+ ///
+ /// Returns a reference to the marshalled array.
+ ///
+ public ref TUnmanagedElement GetPinnableReference() => ref MemoryMarshal.GetReference(_span);
+
+ ///
+ /// Returns the unmanaged value representing the array.
+ ///
+ public TUnmanagedElement* ToUnmanaged() => (TUnmanagedElement*)Unsafe.AsPointer(ref GetPinnableReference());
+
+ ///
+ /// Frees resources.
+ ///
+ public void Free()
+ {
+ NativeMemory.Free(_allocatedMemory);
+ }
+
+ public static ref T GetPinnableReference(Span managed)
+ {
+ return ref MemoryMarshal.GetReference(managed);
+ }
+ }
+ }
+}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Span.cs b/src/libraries/System.Private.CoreLib/src/System/Span.cs
index dc8f2500ae1e8..49816d0e107f5 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Span.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Span.cs
@@ -4,6 +4,7 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.Marshalling;
using System.Runtime.Versioning;
using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
@@ -19,6 +20,9 @@ namespace System
[DebuggerTypeProxy(typeof(SpanDebugView<>))]
[DebuggerDisplay("{ToString(),raw}")]
[NonVersionable]
+#pragma warning disable SYSLIB1056 // Specified native type is invalid
+ [NativeMarshalling(typeof(SpanMarshaller<,>))]
+#pragma warning restore SYSLIB1056 // Specified native type is invalid
public readonly ref struct Span
{
/// A byref or a native ptr.
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSStubCodeContext.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSStubCodeContext.cs
index 1d0b0727ad1b8..abd0e3da24e97 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSStubCodeContext.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSStubCodeContext.cs
@@ -25,7 +25,7 @@ internal sealed record JSImportCodeContext : JSStubCodeContext
public JSImportCodeContext(JSImportData attributeData, StubCodeContext inner)
{
_inner = inner;
- Direction = CustomTypeMarshallerDirection.In;
+ Direction = CustomTypeMarshallingDirection.In;
AttributeData = attributeData;
}
@@ -37,7 +37,7 @@ internal sealed record JSExportCodeContext : JSStubCodeContext
public JSExportCodeContext(JSExportData attributeData, StubCodeContext inner)
{
_inner = inner;
- Direction = CustomTypeMarshallerDirection.Out;
+ Direction = CustomTypeMarshallingDirection.Out;
AttributeData = attributeData;
}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs
index 03652eea4a8da..fed51dde6d6f6 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs
@@ -53,12 +53,12 @@ public override IEnumerable Generate(TypePositionInfo info, Stu
.Select(a => ParseTypeName(a.FullTypeName))
.ToArray();
- if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallerDirection.In && info.IsManagedReturnPosition)
+ if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.In && info.IsManagedReturnPosition)
{
yield return ToManagedMethod(target, source, jsty);
}
- if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == CustomTypeMarshallerDirection.Out && info.IsManagedReturnPosition)
+ if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == CustomTypeMarshallingDirection.Out && info.IsManagedReturnPosition)
{
yield return ToJSMethod(target, source, jsty);
}
@@ -68,12 +68,12 @@ public override IEnumerable Generate(TypePositionInfo info, Stu
yield return x;
}
- if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == CustomTypeMarshallerDirection.In && !info.IsManagedReturnPosition)
+ if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == CustomTypeMarshallingDirection.In && !info.IsManagedReturnPosition)
{
yield return ToJSMethod(target, source, jsty);
}
- if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallerDirection.Out && !info.IsManagedReturnPosition)
+ if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.Out && !info.IsManagedReturnPosition)
{
yield return ToManagedMethod(target, source, jsty);
}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs
index b25b95710d5b1..e3920e46765fb 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs
@@ -32,12 +32,12 @@ public override IEnumerable Generate(TypePositionInfo info, Stu
? Argument(IdentifierName(context.GetIdentifiers(info).native))
: _inner.AsArgument(info, context);
- if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallerDirection.In && info.IsManagedReturnPosition)
+ if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.In && info.IsManagedReturnPosition)
{
yield return ToManagedMethod(target, source);
}
- if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == CustomTypeMarshallerDirection.Out && info.IsManagedReturnPosition)
+ if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == CustomTypeMarshallingDirection.Out && info.IsManagedReturnPosition)
{
yield return ToJSMethod(target, source);
}
@@ -47,12 +47,12 @@ public override IEnumerable Generate(TypePositionInfo info, Stu
yield return x;
}
- if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == CustomTypeMarshallerDirection.In && !info.IsManagedReturnPosition)
+ if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == CustomTypeMarshallingDirection.In && !info.IsManagedReturnPosition)
{
yield return ToJSMethod(target, source);
}
- if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallerDirection.Out && !info.IsManagedReturnPosition)
+ if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.Out && !info.IsManagedReturnPosition)
{
yield return ToManagedMethod(target, source);
}
diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs
index 3bfa38c12ea22..86162f0e62c94 100644
--- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs
@@ -45,14 +45,14 @@ public override IEnumerable Generate(TypePositionInfo info, Stu
? Argument(IdentifierName(context.GetIdentifiers(info).native))
: _inner.AsArgument(info, context);
- if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallerDirection.In && info.IsManagedReturnPosition)
+ if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.In && info.IsManagedReturnPosition)
{
yield return jsty.ResultTypeInfo.FullTypeName == "void"
? ToManagedMethodVoid(target, source)
: ToManagedMethod(target, source, jsty.ResultTypeInfo.Syntax);
}
- if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == CustomTypeMarshallerDirection.Out && info.IsManagedReturnPosition)
+ if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == CustomTypeMarshallingDirection.Out && info.IsManagedReturnPosition)
{
yield return jsty.ResultTypeInfo.FullTypeName == "void"
? ToJSMethodVoid(target, source)
@@ -64,14 +64,14 @@ public override IEnumerable Generate(TypePositionInfo info, Stu
yield return x;
}
- if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == CustomTypeMarshallerDirection.In && !info.IsManagedReturnPosition)
+ if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == CustomTypeMarshallingDirection.In && !info.IsManagedReturnPosition)
{
yield return jsty.ResultTypeInfo.FullTypeName == "void"
? ToJSMethodVoid(target, source)
: ToJSMethod(target, source, jsty.ResultTypeInfo.Syntax);
}
- if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallerDirection.Out && !info.IsManagedReturnPosition)
+ if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.Out && !info.IsManagedReturnPosition)
{
yield return jsty.ResultTypeInfo.FullTypeName == "void"
? ToManagedMethodVoid(target, source)
diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomTypeMarshallerAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomTypeMarshallerAnalyzer.cs
index 8e380eeba243d..35180ee242f9e 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomTypeMarshallerAnalyzer.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomTypeMarshallerAnalyzer.cs
@@ -18,18 +18,10 @@ public class CustomTypeMarshallerAnalyzer : DiagnosticAnalyzer
{
private const string Category = "Usage";
- public const string MissingFeaturesKey = nameof(MissingFeaturesKey);
-
public static class MissingMemberNames
{
public const string Key = nameof(MissingMemberNames);
public const char Delimiter = ' ';
-
- public const string ValueManagedToNativeConstructor = nameof(ValueManagedToNativeConstructor);
- public const string ValueCallerAllocatedBufferConstructor = nameof(ValueCallerAllocatedBufferConstructor);
- public const string CollectionManagedToNativeConstructor = nameof(CollectionManagedToNativeConstructor);
- public const string CollectionCallerAllocatedBufferConstructor = nameof(CollectionCallerAllocatedBufferConstructor);
- public const string CollectionNativeElementSizeConstructor = nameof(CollectionNativeElementSizeConstructor);
}
public static readonly DiagnosticDescriptor MarshallerTypeMustSpecifyManagedTypeRule =
@@ -42,36 +34,6 @@ public static class MissingMemberNames
isEnabledByDefault: true,
description: GetResourceString(nameof(SR.MarshallerTypeMustSpecifyManagedTypeDescription)));
- public static readonly DiagnosticDescriptor CustomTypeMarshallerAttributeMustBeValidRule =
- new DiagnosticDescriptor(
- Ids.InvalidCustomTypeMarshallerAttributeUsage,
- GetResourceString(nameof(SR.InvalidCustomTypeMarshallerAttributeUsageTitle)),
- GetResourceString(nameof(SR.CustomTypeMarshallerAttributeMustBeValidMessage)),
- Category,
- DiagnosticSeverity.Error,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.CustomTypeMarshallerAttributeMustBeValidDescription)));
-
- public static readonly DiagnosticDescriptor MarshallerKindMustBeValidRule =
- new DiagnosticDescriptor(
- Ids.InvalidCustomTypeMarshallerAttributeUsage,
- GetResourceString(nameof(SR.InvalidCustomTypeMarshallerAttributeUsageTitle)),
- GetResourceString(nameof(SR.MarshallerKindMustBeValidMessage)),
- Category,
- DiagnosticSeverity.Error,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.MarshallerKindMustBeValidDescription)));
-
- public static readonly DiagnosticDescriptor MarshallerDirectionMustBeValidRule =
- new DiagnosticDescriptor(
- Ids.InvalidCustomTypeMarshallerAttributeUsage,
- GetResourceString(nameof(SR.InvalidCustomTypeMarshallerAttributeUsageTitle)),
- GetResourceString(nameof(SR.MarshallerDirectionMustBeValidMessage)),
- Category,
- DiagnosticSeverity.Error,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.MarshallerDirectionMustBeValidDescription)));
-
public static readonly DiagnosticDescriptor NativeTypeMustHaveCustomTypeMarshallerAttributeRule =
new DiagnosticDescriptor(
Ids.InvalidNativeType,
@@ -112,16 +74,6 @@ public static class MissingMemberNames
isEnabledByDefault: true,
description: GetResourceString(nameof(SR.NativeTypeMustBePointerSizedDescription)));
- public static readonly DiagnosticDescriptor CustomMarshallerTypeMustSupportDirectionRule =
- new DiagnosticDescriptor(
- Ids.InvalidCustomTypeMarshallerAttributeUsage,
- GetResourceString(nameof(SR.InvalidCustomTypeMarshallerAttributeUsageTitle)),
- GetResourceString(nameof(SR.CustomMarshallerTypeMustSupportDirectionMessage)),
- Category,
- DiagnosticSeverity.Error,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.CustomMarshallerTypeMustSupportDirectionDescription)));
-
public static readonly DiagnosticDescriptor ValueInRequiresOneParameterConstructorRule =
new DiagnosticDescriptor(
Ids.CustomMarshallerTypeMustHaveRequiredShape,
@@ -192,66 +144,6 @@ public static class MissingMemberNames
isEnabledByDefault: true,
description: GetResourceString(nameof(SR.LinearCollectionOutRequiresCollectionMethodsDescription)));
- public static readonly DiagnosticDescriptor LinearCollectionOutRequiresIntConstructorRule =
- new DiagnosticDescriptor(
- Ids.CustomMarshallerTypeMustHaveRequiredShape,
- GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)),
- GetResourceString(nameof(SR.LinearCollectionOutRequiresIntConstructorMessage)),
- Category,
- DiagnosticSeverity.Error,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.LinearCollectionOutRequiresIntConstructorDescription)));
-
- public static readonly DiagnosticDescriptor UnmanagedResourcesRequiresFreeNativeRule =
- new DiagnosticDescriptor(
- Ids.CustomMarshallerTypeMustHaveRequiredShape,
- GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)),
- GetResourceString(nameof(SR.UnmanagedResourcesRequiresFreeNativeMessage)),
- Category,
- DiagnosticSeverity.Error,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.UnmanagedResourcesRequiresFreeNativeDescription)));
-
- public static readonly DiagnosticDescriptor OutTwoStageMarshallingRequiresFromNativeValueRule =
- new DiagnosticDescriptor(
- Ids.CustomMarshallerTypeMustHaveRequiredShape,
- GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)),
- GetResourceString(nameof(SR.OutTwoStageMarshallingRequiresFromNativeValueMessage)),
- Category,
- DiagnosticSeverity.Error,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.OutTwoStageMarshallingRequiresFromNativeValueDescription)));
-
- public static readonly DiagnosticDescriptor InTwoStageMarshallingRequiresToNativeValueRule =
- new DiagnosticDescriptor(
- Ids.CustomMarshallerTypeMustHaveRequiredShape,
- GetResourceString(nameof(SR.CustomMarshallerTypeMustHaveRequiredShapeTitle)),
- GetResourceString(nameof(SR.InTwoStageMarshallingRequiresToNativeValueMessage)),
- Category,
- DiagnosticSeverity.Error,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.InTwoStageMarshallingRequiresToNativeValueDescription)));
-
- public static readonly DiagnosticDescriptor GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackRule =
- new DiagnosticDescriptor(
- Ids.MissingAllocatingMarshallingFallback,
- GetResourceString(nameof(SR.MissingAllocatingMarshallingFallbackTitle)),
- GetResourceString(nameof(SR.GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackMessage)),
- Category,
- DiagnosticSeverity.Warning,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackDescription)));
-
- public static readonly DiagnosticDescriptor CallerAllocMarshallingShouldSupportAllocatingMarshallingFallbackRule =
- new DiagnosticDescriptor(
- Ids.MissingAllocatingMarshallingFallback,
- GetResourceString(nameof(SR.MissingAllocatingMarshallingFallbackTitle)),
- GetResourceString(nameof(SR.CallerAllocMarshallingShouldSupportAllocatingMarshallingFallbackMessage)),
- Category,
- DiagnosticSeverity.Warning,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.CallerAllocMarshallingShouldSupportAllocatingMarshallingFallbackDescription)));
-
public static readonly DiagnosticDescriptor CallerAllocConstructorMustHaveBufferSizeRule =
new DiagnosticDescriptor(
Ids.CallerAllocConstructorMustHaveBufferSize,
@@ -282,56 +174,6 @@ public static class MissingMemberNames
isEnabledByDefault: true,
description: GetResourceString(nameof(SR.NativeGenericTypeMustBeClosedOrMatchArityDescription)));
- public static readonly DiagnosticDescriptor MarshallerGetPinnableReferenceRequiresTwoStageMarshallingRule =
- new DiagnosticDescriptor(
- Ids.ProvidedMethodsNotSpecifiedInFeatures,
- GetResourceString(nameof(SR.ProvidedMethodsNotSpecifiedInFeaturesTitle)),
- GetResourceString(nameof(SR.MarshallerGetPinnableReferenceRequiresTwoStageMarshallingMessage)),
- Category,
- DiagnosticSeverity.Error,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.MarshallerGetPinnableReferenceRequiresTwoStageMarshallingDescription)));
-
- public static readonly DiagnosticDescriptor FreeNativeMethodProvidedShouldSpecifyUnmanagedResourcesFeatureRule =
- new DiagnosticDescriptor(
- Ids.ProvidedMethodsNotSpecifiedInFeatures,
- GetResourceString(nameof(SR.ProvidedMethodsNotSpecifiedInFeaturesTitle)),
- GetResourceString(nameof(SR.FreeNativeMethodProvidedShouldSpecifyUnmanagedResourcesFeatureMessage)),
- Category,
- DiagnosticSeverity.Warning,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.FreeNativeMethodProvidedShouldSpecifyUnmanagedResourcesFeatureDescription)));
-
- public static readonly DiagnosticDescriptor ToNativeValueMethodProvidedShouldSpecifyTwoStageMarshallingFeatureRule =
- new DiagnosticDescriptor(
- Ids.ProvidedMethodsNotSpecifiedInFeatures,
- GetResourceString(nameof(SR.ProvidedMethodsNotSpecifiedInFeaturesTitle)),
- GetResourceString(nameof(SR.ToNativeValueMethodProvidedShouldSpecifyTwoStageMarshallingFeatureMessage)),
- Category,
- DiagnosticSeverity.Warning,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.ToNativeValueMethodProvidedShouldSpecifyTwoStageMarshallingFeatureDescription)));
-
- public static readonly DiagnosticDescriptor FromNativeValueMethodProvidedShouldSpecifyTwoStageMarshallingFeatureRule =
- new DiagnosticDescriptor(
- Ids.ProvidedMethodsNotSpecifiedInFeatures,
- GetResourceString(nameof(SR.ProvidedMethodsNotSpecifiedInFeaturesTitle)),
- GetResourceString(nameof(SR.FromNativeValueMethodProvidedShouldSpecifyTwoStageMarshallingFeatureMessage)),
- Category,
- DiagnosticSeverity.Warning,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.FromNativeValueMethodProvidedShouldSpecifyTwoStageMarshallingFeatureDescription)));
-
- public static readonly DiagnosticDescriptor CallerAllocatedBufferConstructorProvidedShouldSpecifyFeatureRule =
- new DiagnosticDescriptor(
- Ids.ProvidedMethodsNotSpecifiedInFeatures,
- GetResourceString(nameof(SR.ProvidedMethodsNotSpecifiedInFeaturesTitle)),
- GetResourceString(nameof(SR.CallerAllocatedBufferConstructorProvidedShouldSpecifyFeatureMessage)),
- Category,
- DiagnosticSeverity.Warning,
- isEnabledByDefault: true,
- description: GetResourceString(nameof(SR.CallerAllocatedBufferConstructorProvidedShouldSpecifyFeatureDescription)));
-
public static readonly DiagnosticDescriptor TwoStageMarshallingNativeTypesMustMatchRule =
new DiagnosticDescriptor(
Ids.InvalidSignaturesInMarshallerShape,
@@ -355,9 +197,6 @@ public static class MissingMemberNames
public override ImmutableArray SupportedDiagnostics =>
ImmutableArray.Create(
MarshallerTypeMustSpecifyManagedTypeRule,
- CustomTypeMarshallerAttributeMustBeValidRule,
- MarshallerKindMustBeValidRule,
- MarshallerDirectionMustBeValidRule,
NativeTypeMustHaveCustomTypeMarshallerAttributeRule,
NativeTypeMustBeBlittableRule,
GetPinnableReferenceReturnTypeBlittableRule,
@@ -367,20 +206,9 @@ public static class MissingMemberNames
OutRequiresToManagedRule,
LinearCollectionInRequiresCollectionMethodsRule,
LinearCollectionOutRequiresCollectionMethodsRule,
- LinearCollectionOutRequiresIntConstructorRule,
- CustomMarshallerTypeMustSupportDirectionRule,
- OutTwoStageMarshallingRequiresFromNativeValueRule,
- InTwoStageMarshallingRequiresToNativeValueRule,
- GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackRule,
- CallerAllocMarshallingShouldSupportAllocatingMarshallingFallbackRule,
CallerAllocConstructorMustHaveBufferSizeRule,
RefNativeValueUnsupportedRule,
NativeGenericTypeMustBeClosedOrMatchArityRule,
- MarshallerGetPinnableReferenceRequiresTwoStageMarshallingRule,
- FreeNativeMethodProvidedShouldSpecifyUnmanagedResourcesFeatureRule,
- ToNativeValueMethodProvidedShouldSpecifyTwoStageMarshallingFeatureRule,
- FromNativeValueMethodProvidedShouldSpecifyTwoStageMarshallingFeatureRule,
- CallerAllocatedBufferConstructorProvidedShouldSpecifyFeatureRule,
TwoStageMarshallingNativeTypesMustMatchRule,
LinearCollectionElementTypesMustMatchRule);
@@ -494,427 +322,20 @@ private static void AnalyzeManagedTypeMarshallingInfo(
managedType.ToDisplayString()));
}
- (bool hasCustomTypeMarshallerAttribute, ITypeSymbol? marshallerManagedType, _) = ManualTypeMarshallingHelper_V1.GetMarshallerShapeInfo(entryType);
-
- marshallerManagedType = ManualTypeMarshallingHelper.ResolveManagedType(marshallerManagedType, entryType, context.Compilation);
-
- if (!hasCustomTypeMarshallerAttribute)
- {
- if (ManualTypeMarshallingHelper.HasEntryPointMarshallerAttribute(entryType))
- {
- // TEMPORARY: Don't analyze V2 analyzers in this method for now.
- // We'll add support soon, but for now just don't emit warnings to use the V1 marshaller design
- // when using the V2 design.
- return;
- }
- context.ReportDiagnostic(
- attributeData.CreateDiagnostic(
- NativeTypeMustHaveCustomTypeMarshallerAttributeRule,
- managedType.ToDisplayString()));
- return;
- }
-
- if (marshallerManagedType is null)
- {
- context.ReportDiagnostic(
- attributeData.CreateDiagnostic(
- NativeTypeMustHaveCustomTypeMarshallerAttributeRule,
- managedType.ToDisplayString()));
- return;
- }
- if (!TypeSymbolsConstructedFromEqualTypes(managedType, marshallerManagedType))
+ if (!ManualTypeMarshallingHelper.HasEntryPointMarshallerAttribute(entryType))
{
- context.ReportDiagnostic(
- attributeData.CreateDiagnostic(
- NativeTypeMustHaveCustomTypeMarshallerAttributeRule,
- managedType.ToDisplayString()));
+ // TODO: Report that the marshaller needs to be an entry-point marshaller type.
return;
}
}
- private static bool TypeSymbolsConstructedFromEqualTypes(ITypeSymbol left, ITypeSymbol right)
- {
- return (left, right) switch
- {
- (INamedTypeSymbol namedLeft, INamedTypeSymbol namedRight) => SymbolEqualityComparer.Default.Equals(namedLeft.ConstructedFrom, namedRight.ConstructedFrom),
- _ => SymbolEqualityComparer.Default.Equals(left, right)
- };
- }
-
+#pragma warning disable CA1822 // Mark members as static
public void AnalyzeMarshallerType(SymbolAnalysisContext context)
+#pragma warning restore CA1822 // Mark members as static
{
- INamedTypeSymbol marshallerType = (INamedTypeSymbol)context.Symbol;
- (bool hasCustomTypeMarshallerAttribute, ITypeSymbol? type, CustomTypeMarshallerData_V1? marshallerDataMaybe) = ManualTypeMarshallingHelper_V1.GetMarshallerShapeInfo(marshallerType);
- type = ManualTypeMarshallingHelper.ResolveManagedType(type, marshallerType, context.Compilation);
-
- if (!hasCustomTypeMarshallerAttribute)
- {
- return;
- }
- if (type is null)
- {
- context.ReportDiagnostic(marshallerType.CreateDiagnostic(MarshallerTypeMustSpecifyManagedTypeRule, marshallerType.ToDisplayString()));
- return;
- }
-
- if (marshallerDataMaybe is not { } marshallerData)
- {
- context.ReportDiagnostic(marshallerType.CreateDiagnostic(CustomTypeMarshallerAttributeMustBeValidRule, marshallerType.ToDisplayString()));
- return;
- }
-
- if (!Enum.IsDefined(typeof(CustomTypeMarshallerKind), marshallerData.Kind))
- {
- context.ReportDiagnostic(marshallerType.CreateDiagnostic(MarshallerKindMustBeValidRule, marshallerType.ToDisplayString()));
- return;
- }
-
- if (type is INamedTypeSymbol { IsUnboundGenericType: true } generic)
- {
- if (generic.TypeArguments.Length != marshallerType.TypeArguments.Length)
- {
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- NativeGenericTypeMustBeClosedOrMatchArityRule,
- marshallerType.ToDisplayString(),
- type.ToDisplayString()));
- return;
- }
- type = generic.ConstructedFrom.Construct(marshallerType.TypeArguments, marshallerType.TypeArgumentNullableAnnotations);
- }
-
- IMethodSymbol? inConstructor = null;
- IMethodSymbol? callerAllocatedSpanConstructor = null;
- IMethodSymbol collectionOutConstructor = null;
- foreach (IMethodSymbol ctor in marshallerType.Constructors)
- {
- if (ctor.IsStatic)
- {
- continue;
- }
-
- if (inConstructor is null && ManualTypeMarshallingHelper_V1.IsManagedToNativeConstructor(ctor, type, marshallerData.Kind))
- {
- inConstructor = ctor;
- }
-
- if (callerAllocatedSpanConstructor is null && ManualTypeMarshallingHelper_V1.IsCallerAllocatedSpanConstructor(ctor, type, _spanOfT, marshallerData.Kind, out _))
- {
- callerAllocatedSpanConstructor = ctor;
- }
- if (collectionOutConstructor is null && ctor.Parameters.Length == 1 && ctor.Parameters[0].Type.SpecialType == SpecialType.System_Int32)
- {
- collectionOutConstructor = ctor;
- }
- }
-
- if (marshallerData.Direction.HasFlag(CustomTypeMarshallerDirection.In))
- {
- if (inConstructor is null)
- {
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- GetInConstructorShapeRule(marshallerData.Kind),
- ImmutableDictionary.Empty.Add(
- MissingMemberNames.Key,
- GetInConstructorMissingMemberName(marshallerData.Kind)),
- marshallerType.ToDisplayString(),
- type.ToDisplayString()));
- }
- if (marshallerData.Features.HasFlag(CustomTypeMarshallerFeatures.CallerAllocatedBuffer))
- {
- if (callerAllocatedSpanConstructor is null)
- {
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- GetCallerAllocatedBufferConstructorShapeRule(marshallerData.Kind),
- ImmutableDictionary.Empty.Add(
- MissingMemberNames.Key,
- GetCallerAllocatedBufferConstructorMissingMemberName(marshallerData.Kind)),
- marshallerType.ToDisplayString(),
- type.ToDisplayString()));
- }
- if (marshallerData.BufferSize == null)
- {
- context.ReportDiagnostic(
- (callerAllocatedSpanConstructor ?? (ISymbol)marshallerType).CreateDiagnostic(
- CallerAllocConstructorMustHaveBufferSizeRule,
- marshallerType.ToDisplayString()));
- }
- }
- else if (callerAllocatedSpanConstructor is not null)
- {
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- CallerAllocatedBufferConstructorProvidedShouldSpecifyFeatureRule,
- ImmutableDictionary.Empty.Add(
- MissingFeaturesKey,
- nameof(CustomTypeMarshallerFeatures.CallerAllocatedBuffer)),
- marshallerType.ToDisplayString()));
- }
-
- // Validate that this type can support marshalling when stackalloc is not usable.
- if (callerAllocatedSpanConstructor is not null && inConstructor is null)
- {
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- CallerAllocMarshallingShouldSupportAllocatingMarshallingFallbackRule,
- marshallerType.ToDisplayString()));
- }
- }
-
- if (marshallerData.Direction.HasFlag(CustomTypeMarshallerDirection.Out) && !ManualTypeMarshallingHelper_V1.HasToManagedMethod(marshallerType, type))
- {
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- OutRequiresToManagedRule,
- ImmutableDictionary.Empty.Add(
- MissingMemberNames.Key,
- ShapeMemberNames_V1.Value.ToManaged),
- marshallerType.ToDisplayString()));
- }
-
- if (marshallerData.Kind == CustomTypeMarshallerKind.LinearCollection)
- {
- IMethodSymbol? getManagedValuesSourceMethod = ManualTypeMarshallingHelper_V1.FindGetManagedValuesSourceMethod(marshallerType, _readOnlySpanOfT);
- IMethodSymbol? getManagedValuesDestinationMethod = ManualTypeMarshallingHelper_V1.FindGetManagedValuesDestinationMethod(marshallerType, _spanOfT);
- IMethodSymbol? getNativeValuesSourceMethod = ManualTypeMarshallingHelper_V1.FindGetNativeValuesSourceMethod(marshallerType, _readOnlySpanOfByte);
- IMethodSymbol? getNativeValuesDestinationMethod = ManualTypeMarshallingHelper_V1.FindGetNativeValuesDestinationMethod(marshallerType, _spanOfByte);
- if (marshallerData.Direction.HasFlag(CustomTypeMarshallerDirection.In) && (getManagedValuesSourceMethod is null || getNativeValuesDestinationMethod is null))
- {
- var missingMembers = (getManagedValuesSourceMethod, getNativeValuesDestinationMethod) switch
- {
- (null, not null) => ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource,
- (not null, null) => ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination,
- (null, null) => $"{ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource}{MissingMemberNames.Delimiter}{ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination}",
- (not null, not null) => string.Empty
- };
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- LinearCollectionInRequiresCollectionMethodsRule,
- ImmutableDictionary.Empty.Add(
- MissingMemberNames.Key,
- missingMembers),
- marshallerType.ToDisplayString()));
- }
-
- if (marshallerData.Direction.HasFlag(CustomTypeMarshallerDirection.Out) && (getNativeValuesSourceMethod is null || getManagedValuesDestinationMethod is null))
- {
- var missingMembers = (getNativeValuesSourceMethod, getManagedValuesDestinationMethod) switch
- {
- (not null, null) => ShapeMemberNames_V1.LinearCollection.GetNativeValuesSource,
- (null, not null) => ShapeMemberNames_V1.LinearCollection.GetManagedValuesDestination,
- (null, null) => $"{ShapeMemberNames_V1.LinearCollection.GetNativeValuesSource}{MissingMemberNames.Delimiter}{ShapeMemberNames_V1.LinearCollection.GetManagedValuesDestination}",
- (not null, not null) => string.Empty
- };
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- LinearCollectionOutRequiresCollectionMethodsRule,
- ImmutableDictionary.Empty.Add(
- MissingMemberNames.Key,
- missingMembers),
- marshallerType.ToDisplayString()));
- }
-
- if (getManagedValuesSourceMethod is not null
- && getManagedValuesDestinationMethod is not null
- && !SymbolEqualityComparer.Default.Equals(
- ((INamedTypeSymbol)getManagedValuesSourceMethod.ReturnType).TypeArguments[0],
- ((INamedTypeSymbol)getManagedValuesDestinationMethod.ReturnType).TypeArguments[0]))
- {
- context.ReportDiagnostic(getManagedValuesSourceMethod.CreateDiagnostic(LinearCollectionElementTypesMustMatchRule));
- }
- if (marshallerData.Direction.HasFlag(CustomTypeMarshallerDirection.Out) && collectionOutConstructor is null)
- {
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- LinearCollectionOutRequiresIntConstructorRule,
- ImmutableDictionary.Empty.Add(
- MissingMemberNames.Key,
- MissingMemberNames.CollectionNativeElementSizeConstructor),
- marshallerType.ToDisplayString()));
- }
- }
-
-
- // Validate that the native type has at least one marshalling direction (either managed to native or native to managed)
- if ((marshallerData.Direction & CustomTypeMarshallerDirection.Ref) == CustomTypeMarshallerDirection.None)
- {
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- CustomMarshallerTypeMustSupportDirectionRule,
- marshallerType.ToDisplayString()));
- }
-
- if (marshallerData.Features.HasFlag(CustomTypeMarshallerFeatures.UnmanagedResources) && !ManualTypeMarshallingHelper_V1.HasFreeNativeMethod(marshallerType))
- {
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- UnmanagedResourcesRequiresFreeNativeRule,
- ImmutableDictionary.Empty.Add(
- MissingMemberNames.Key,
- ShapeMemberNames_V1.Value.FreeNative),
- marshallerType.ToDisplayString(),
- type.ToDisplayString()));
- }
- else if (!marshallerData.Features.HasFlag(CustomTypeMarshallerFeatures.UnmanagedResources) && ManualTypeMarshallingHelper_V1.HasFreeNativeMethod(marshallerType))
- {
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- FreeNativeMethodProvidedShouldSpecifyUnmanagedResourcesFeatureRule,
- ImmutableDictionary.Empty.Add(
- MissingFeaturesKey,
- nameof(CustomTypeMarshallerFeatures.UnmanagedResources)),
- marshallerType.ToDisplayString()));
- }
-
- IMethodSymbol? toNativeValueMethod = ManualTypeMarshallingHelper_V1.FindToNativeValueMethod(marshallerType);
- IMethodSymbol? fromNativeValueMethod = ManualTypeMarshallingHelper_V1.FindFromNativeValueMethod(marshallerType);
- bool toNativeValueMethodIsRefReturn = toNativeValueMethod is { ReturnsByRef: true } or { ReturnsByRefReadonly: true };
- ITypeSymbol nativeType = marshallerType;
-
- if (marshallerData.Features.HasFlag(CustomTypeMarshallerFeatures.TwoStageMarshalling))
- {
- if (marshallerData.Direction.HasFlag(CustomTypeMarshallerDirection.In) && toNativeValueMethod is null)
- {
- context.ReportDiagnostic(marshallerType.CreateDiagnostic(
- InTwoStageMarshallingRequiresToNativeValueRule,
- ImmutableDictionary.Empty.Add(
- MissingMemberNames.Key,
- ShapeMemberNames_V1.Value.ToNativeValue),
- marshallerType.ToDisplayString()));
- }
- if (marshallerData.Direction.HasFlag(CustomTypeMarshallerDirection.Out) && fromNativeValueMethod is null)
- {
- context.ReportDiagnostic(marshallerType.CreateDiagnostic(
- OutTwoStageMarshallingRequiresFromNativeValueRule,
- ImmutableDictionary.Empty.Add(
- MissingMemberNames.Key,
- ShapeMemberNames_V1.Value.FromNativeValue),
- marshallerType.ToDisplayString()));
- }
-
- // ToNativeValue and FromNativeValue must be provided with the same type.
- if (toNativeValueMethod is not null
- && fromNativeValueMethod is not null
- && !SymbolEqualityComparer.Default.Equals(toNativeValueMethod.ReturnType, fromNativeValueMethod.Parameters[0].Type))
- {
- context.ReportDiagnostic(toNativeValueMethod.CreateDiagnostic(TwoStageMarshallingNativeTypesMustMatchRule));
- }
- }
- else if (fromNativeValueMethod is not null)
- {
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- FromNativeValueMethodProvidedShouldSpecifyTwoStageMarshallingFeatureRule,
- ImmutableDictionary.Empty.Add(
- MissingFeaturesKey,
- nameof(CustomTypeMarshallerFeatures.TwoStageMarshalling)),
- marshallerType.ToDisplayString()));
- }
- else if (toNativeValueMethod is not null)
- {
- context.ReportDiagnostic(
- marshallerType.CreateDiagnostic(
- ToNativeValueMethodProvidedShouldSpecifyTwoStageMarshallingFeatureRule,
- ImmutableDictionary.Empty.Add(
- MissingFeaturesKey,
- nameof(CustomTypeMarshallerFeatures.TwoStageMarshalling)),
- marshallerType.ToDisplayString()));
- }
-
- if (toNativeValueMethod is not null)
- {
- if (toNativeValueMethodIsRefReturn)
- {
- context.ReportDiagnostic(
- toNativeValueMethod.CreateDiagnostic(
- RefNativeValueUnsupportedRule,
- marshallerType.ToDisplayString()));
- }
-
- nativeType = toNativeValueMethod.ReturnType;
- }
- else if (ManualTypeMarshallingHelper.FindGetPinnableReference(marshallerType) is IMethodSymbol marshallerGetPinnableReferenceMethod)
- {
- // If we don't have a ToNativeValue method, then we disallow a GetPinnableReference on the marshaler type.
- // We do this since there is no valid use case that we can think of for a GetPinnableReference on a blittable type
- // being a requirement to calculate the value of the fields of the same blittable instance,
- // so we're pre-emptively blocking this until a use case is discovered.
- context.ReportDiagnostic(
- marshallerGetPinnableReferenceMethod.CreateDiagnostic(
- MarshallerGetPinnableReferenceRequiresTwoStageMarshallingRule,
- nativeType.ToDisplayString()));
- }
-
- if (!nativeType.IsConsideredBlittable())
- {
- context.ReportDiagnostic(
- (toNativeValueMethod ?? (ISymbol)marshallerType).CreateDiagnostic(
- NativeTypeMustBeBlittableRule,
- nativeType.ToDisplayString(),
- type.ToDisplayString()));
- }
-
- if (SymbolEqualityComparer.Default.Equals(ManualTypeMarshallingHelper.GetDefaultMarshallerEntryType(type).entryType, marshallerType)
- && ManualTypeMarshallingHelper.FindGetPinnableReference(type) is IMethodSymbol managedGetPinnableReferenceMethod)
- {
- if (!managedGetPinnableReferenceMethod.ReturnType.IsConsideredBlittable())
- {
- context.ReportDiagnostic(managedGetPinnableReferenceMethod.CreateDiagnostic(GetPinnableReferenceReturnTypeBlittableRule));
- }
- // Validate that our marshaler supports scenarios where GetPinnableReference cannot be used.
- if (!marshallerData.Direction.HasFlag(CustomTypeMarshallerDirection.In))
- {
- context.ReportDiagnostic(
- type.CreateDiagnostic(
- GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackRule,
- type.ToDisplayString()));
- }
-
- // If the managed type has a GetPinnableReference method, make sure that the Value getter is also a pointer-sized primitive.
- // This ensures that marshalling via pinning the managed value and marshalling via the default marshaller will have the same ABI.
- if (toNativeValueMethod is not null
- && !toNativeValueMethodIsRefReturn // Ref returns are already reported above as invalid, so don't issue another warning here about them
- && nativeType is not (
- IPointerTypeSymbol or
- { SpecialType: SpecialType.System_IntPtr } or
- { SpecialType: SpecialType.System_UIntPtr }))
- {
- context.ReportDiagnostic(
- toNativeValueMethod.CreateDiagnostic(
- NativeTypeMustBePointerSizedRule,
- nativeType.ToDisplayString(),
- managedGetPinnableReferenceMethod.ContainingType.ToDisplayString()));
- }
- }
+ // TODO: Implement for the V2 shapes
}
-
- private static DiagnosticDescriptor GetInConstructorShapeRule(CustomTypeMarshallerKind kind) => kind switch
- {
- CustomTypeMarshallerKind.Value => ValueInRequiresOneParameterConstructorRule,
- CustomTypeMarshallerKind.LinearCollection => LinearCollectionInRequiresTwoParameterConstructorRule,
- _ => throw new UnreachableException()
- };
- private static string GetInConstructorMissingMemberName(CustomTypeMarshallerKind kind) => kind switch
- {
- CustomTypeMarshallerKind.Value => MissingMemberNames.ValueManagedToNativeConstructor,
- CustomTypeMarshallerKind.LinearCollection => MissingMemberNames.CollectionManagedToNativeConstructor,
- _ => throw new UnreachableException()
- };
- private static DiagnosticDescriptor GetCallerAllocatedBufferConstructorShapeRule(CustomTypeMarshallerKind kind) => kind switch
- {
- CustomTypeMarshallerKind.Value => ValueInCallerAllocatedBufferRequiresSpanConstructorRule,
- CustomTypeMarshallerKind.LinearCollection => LinearCollectionInCallerAllocatedBufferRequiresSpanConstructorRule,
- _ => throw new UnreachableException()
- };
- private static string GetCallerAllocatedBufferConstructorMissingMemberName(CustomTypeMarshallerKind kind) => kind switch
- {
- CustomTypeMarshallerKind.Value => MissingMemberNames.ValueCallerAllocatedBufferConstructor,
- CustomTypeMarshallerKind.LinearCollection => MissingMemberNames.CollectionCallerAllocatedBufferConstructor,
- _ => throw new UnreachableException()
- };
}
}
}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomTypeMarshallerFixer.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomTypeMarshallerFixer.cs
index 084acbe9d0255..33fbd671c1355 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomTypeMarshallerFixer.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomTypeMarshallerFixer.cs
@@ -22,7 +22,6 @@ namespace Microsoft.Interop.Analyzers
public class CustomTypeMarshallerFixer : CodeFixProvider
{
private const string AddMissingCustomTypeMarshallerMembersKey = nameof(AddMissingCustomTypeMarshallerMembersKey);
- private const string AddMissingCustomTypeMarshallerFeaturesKey = nameof(AddMissingCustomTypeMarshallerFeaturesKey);
private sealed class CustomFixAllProvider : DocumentBasedFixAllProvider
{
@@ -41,15 +40,7 @@ protected override async Task FixAllAsync(FixAllContext fixAllContext,
{
SyntaxNode node = root.FindNode(diagnosticsBySpan.Key);
- AddMissingMembers(fixAllContext, editor, diagnosticsBySpan, node);
- }
- break;
- case AddMissingCustomTypeMarshallerFeaturesKey:
- foreach (IGrouping diagnosticsBySpan in diagnostics.GroupBy(d => d.Location.SourceSpan))
- {
- SyntaxNode node = root.FindNode(diagnosticsBySpan.Key);
-
- await AddMissingFeatures(fixAllContext, editor, diagnosticsBySpan, node).ConfigureAwait(false);
+ AddMissingMembers(editor, diagnosticsBySpan, node);
}
break;
default:
@@ -59,7 +50,7 @@ protected override async Task FixAllAsync(FixAllContext fixAllContext,
return editor.GetChangedDocument();
}
- private static void AddMissingMembers(FixAllContext fixAllContext, DocumentEditor editor, IEnumerable diagnostics, SyntaxNode node)
+ private static void AddMissingMembers(DocumentEditor editor, IEnumerable diagnostics, SyntaxNode node)
{
var (missingMemberNames, _) = GetRequiredShapeMissingMemberNames(diagnostics);
ITypeSymbol marshallerType = (ITypeSymbol)editor.SemanticModel.GetDeclaredSymbol(node);
@@ -73,24 +64,6 @@ private static void AddMissingMembers(FixAllContext fixAllContext, DocumentEdito
editor.SemanticModel.Compilation,
gen));
}
-
- private static async Task AddMissingFeatures(FixAllContext fixAllContext, DocumentEditor editor, IEnumerable diagnostics, SyntaxNode node)
- {
- var (featuresToAdd, _) = GetFeaturesToAdd(diagnostics);
- ITypeSymbol marshallerType = (ITypeSymbol)editor.SemanticModel.GetDeclaredSymbol(node);
- AttributeData customTypeMarshallerAttribute = marshallerType.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.ToDisplayString() == TypeNames.CustomTypeMarshallerAttribute);
-
- SyntaxNode attributeSyntax = await customTypeMarshallerAttribute.ApplicationSyntaxReference!.GetSyntaxAsync(fixAllContext.CancellationToken).ConfigureAwait(false);
-
- editor.ReplaceNode(
- attributeSyntax,
- (node, gen) =>
- CustomTypeMarshallerFixer.AddMissingFeatures(
- gen.GetName(node),
- customTypeMarshallerAttribute,
- featuresToAdd,
- gen));
- }
}
public override FixAllProvider? GetFixAllProvider() => new CustomFixAllProvider();
@@ -120,18 +93,6 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
AddMissingCustomTypeMarshallerMembersKey),
missingMembersDiagnostics);
}
-
- var (featuresToAdd, featuresToAddDiagnostics) = GetFeaturesToAdd(context.Diagnostics);
-
- if (featuresToAddDiagnostics.Count > 0 && featuresToAdd != CustomTypeMarshallerFeatures.None)
- {
- context.RegisterCodeFix(
- CodeAction.Create(
- SR.AddMissingFeaturesToCustomTypeMarshaller,
- ct => AddMissingFeatures(doc, node, featuresToAdd, ct),
- AddMissingCustomTypeMarshallerFeaturesKey),
- featuresToAddDiagnostics);
- }
}
private static (List missingMembers, List fixedDiagnostics) GetRequiredShapeMissingMemberNames(IEnumerable diagnostics)
@@ -152,78 +113,6 @@ private static (List missingMembers, List fixedDiagnostics)
return (missingMemberNames, requiredShapeDiagnostics);
}
- private static (CustomTypeMarshallerFeatures featuresToAdd, List fixedDiagnostics) GetFeaturesToAdd(IEnumerable diagnostics)
- {
- List featuresToAddDiagnostics = new();
- CustomTypeMarshallerFeatures featuresToAdd = CustomTypeMarshallerFeatures.None;
- foreach (var diagnostic in diagnostics)
- {
- if (diagnostic.Id == AnalyzerDiagnostics.Ids.ProvidedMethodsNotSpecifiedInFeatures)
- {
- featuresToAddDiagnostics.Add(diagnostic);
- if (diagnostic.Properties.TryGetValue(CustomTypeMarshallerAnalyzer.MissingFeaturesKey, out string missingFeatures)
- && Enum.TryParse(missingFeatures, out CustomTypeMarshallerFeatures featuresValue))
- {
- featuresToAdd |= featuresValue;
- }
- }
- }
-
- return (featuresToAdd, featuresToAddDiagnostics);
- }
- private static async Task AddMissingFeatures(Document doc, SyntaxNode node, CustomTypeMarshallerFeatures featuresToAdd, CancellationToken ct)
- {
- var editor = await DocumentEditor.CreateAsync(doc, ct).ConfigureAwait(false);
- var gen = editor.Generator;
-
- ISymbol marshallerType = editor.SemanticModel.GetDeclaredSymbol(node, ct);
-
- AttributeData customTypeMarshallerAttribute = marshallerType.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.ToDisplayString() == TypeNames.CustomTypeMarshallerAttribute);
-
- SyntaxNode attributeSyntax = await customTypeMarshallerAttribute.ApplicationSyntaxReference!.GetSyntaxAsync(ct).ConfigureAwait(false);
-
- SyntaxNode updatedDeclaration = AddMissingFeatures(gen.GetName(attributeSyntax), customTypeMarshallerAttribute, featuresToAdd, gen);
-
- editor.ReplaceNode(attributeSyntax, updatedDeclaration);
-
- return editor.GetChangedDocument();
- }
-
- private static SyntaxNode AddMissingFeatures(string attributeName, AttributeData? customTypeMarshallerAttribute, CustomTypeMarshallerFeatures featuresToAdd, SyntaxGenerator gen)
- {
- SyntaxNode newAttributeSyntax = gen.Attribute(attributeName);
-
- newAttributeSyntax = gen.AddAttributeArguments(newAttributeSyntax, customTypeMarshallerAttribute.ConstructorArguments.Select(a => gen.AttributeArgument(gen.TypedConstantExpression(a))));
-
- CustomTypeMarshallerFeatures newFeaturesValue = featuresToAdd;
- int? featuresArgLocation = null;
-
- newAttributeSyntax = gen.AddAttributeArguments(newAttributeSyntax, customTypeMarshallerAttribute.NamedArguments
- .Where((a, i) =>
- {
- if (a.Key == "Features")
- {
- // Capture the original location of the 'Features' named argument so we can update it "in place".
- featuresArgLocation = customTypeMarshallerAttribute.ConstructorArguments.Length + i;
- newFeaturesValue |= (CustomTypeMarshallerFeatures)a.Value.Value;
- return false;
- }
- return true;
- })
- .Select(a => gen.AttributeArgument(a.Key, gen.TypedConstantExpression(a.Value))));
-
- SyntaxNode featureAttributeArgument = gen.AttributeArgument("Features",
- gen.GetEnumValueAsFlagsExpression(
- customTypeMarshallerAttribute.AttributeClass.GetMembers(ManualTypeMarshallingHelper_V1.CustomMarshallerAttributeFields.Features).OfType().First().Type,
- (int)newFeaturesValue,
- includeZeroValueFlags: false));
-
- newAttributeSyntax = featuresArgLocation is null
- ? gen.AddAttributeArguments(newAttributeSyntax, new[] { featureAttributeArgument })
- : gen.InsertAttributeArguments(newAttributeSyntax, featuresArgLocation.Value, new[] { featureAttributeArgument });
-
- return newAttributeSyntax;
- }
private static async Task AddMissingMembers(Document doc, SyntaxNode node, List missingMemberNames, CancellationToken ct)
{
@@ -240,165 +129,8 @@ private static async Task AddMissingMembers(Document doc, SyntaxNode n
private static SyntaxNode AddMissingMembers(SyntaxNode node, ITypeSymbol
marshallerType, List missingMemberNames, Compilation compilation, SyntaxGenerator gen)
{
- INamedTypeSymbol @byte = compilation.GetSpecialType(SpecialType.System_Byte);
- INamedTypeSymbol @object = compilation.GetSpecialType(SpecialType.System_Object);
- INamedTypeSymbol spanOfT = compilation.GetTypeByMetadataName(TypeNames.System_Span_Metadata)!;
- INamedTypeSymbol spanOfByte = spanOfT.Construct(@byte)!;
- INamedTypeSymbol readOnlySpanOfT = compilation.GetTypeByMetadataName(TypeNames.System_ReadOnlySpan_Metadata)!;
- INamedTypeSymbol readOnlySpanOfByte = readOnlySpanOfT.Construct(@byte)!;
- INamedTypeSymbol int32 = compilation.GetSpecialType(SpecialType.System_Int32);
-
- SyntaxNode updatedDeclaration = node;
-
-
- (_, ITypeSymbol managedType, _) = ManualTypeMarshallingHelper_V1.GetMarshallerShapeInfo(marshallerType);
-
- IMethodSymbol? fromNativeValueMethod = ManualTypeMarshallingHelper_V1.FindFromNativeValueMethod(marshallerType);
- IMethodSymbol? toNativeValueMethod = ManualTypeMarshallingHelper_V1.FindToNativeValueMethod(marshallerType);
- IMethodSymbol? getManagedValuesSourceMethod = ManualTypeMarshallingHelper_V1.FindGetManagedValuesSourceMethod(marshallerType, readOnlySpanOfT);
- IMethodSymbol? getManagedValuesDestinationMethod = ManualTypeMarshallingHelper_V1.FindGetManagedValuesDestinationMethod(marshallerType, spanOfT);
-
- SyntaxNode[] throwNotImplementedStatements = new[]
- {
- gen.ThrowStatement(gen.ObjectCreationExpression(gen.DottedName("System.NotImplementedException")))
- };
-
- foreach (string missingMemberName in missingMemberNames)
- {
- switch (missingMemberName)
- {
- case CustomTypeMarshallerAnalyzer.MissingMemberNames.ValueManagedToNativeConstructor:
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.ConstructorDeclaration(
- gen.GetName(node),
- new[]
- {
- gen.ParameterDeclaration("managed", type: gen.TypeExpression(managedType))
- },
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- case CustomTypeMarshallerAnalyzer.MissingMemberNames.ValueCallerAllocatedBufferConstructor:
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.ConstructorDeclaration(
- gen.GetName(node),
- new[]
- {
- gen.ParameterDeclaration("managed", type: gen.TypeExpression(managedType)),
- gen.ParameterDeclaration("buffer", type: gen.TypeExpression(spanOfByte))
- },
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- case CustomTypeMarshallerAnalyzer.MissingMemberNames.CollectionManagedToNativeConstructor:
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.ConstructorDeclaration(
- gen.GetName(node),
- new[]
- {
- gen.ParameterDeclaration("managed", type: gen.TypeExpression(managedType)),
- gen.ParameterDeclaration("nativeElementSize", type: gen.TypeExpression(int32))
- },
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- case CustomTypeMarshallerAnalyzer.MissingMemberNames.CollectionCallerAllocatedBufferConstructor:
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.ConstructorDeclaration(
- gen.GetName(node),
- new[]
- {
- gen.ParameterDeclaration("managed", type: gen.TypeExpression(managedType)),
- gen.ParameterDeclaration("buffer", type: gen.TypeExpression(spanOfByte)),
- gen.ParameterDeclaration("nativeElementSize", type: gen.TypeExpression(int32))
- },
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- case CustomTypeMarshallerAnalyzer.MissingMemberNames.CollectionNativeElementSizeConstructor:
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.ConstructorDeclaration(
- gen.GetName(node),
- new[]
- {
- gen.ParameterDeclaration("nativeElementSize", type: gen.TypeExpression(int32))
- },
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- case ShapeMemberNames_V1.Value.ToManaged:
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
- ShapeMemberNames_V1.Value.ToManaged,
- returnType: gen.TypeExpression(managedType),
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- case ShapeMemberNames_V1.Value.FreeNative:
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(ShapeMemberNames_V1.Value.FreeNative,
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- case ShapeMemberNames_V1.Value.FromNativeValue:
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
- ShapeMemberNames_V1.Value.FromNativeValue,
- parameters: new[]
- {
- gen.ParameterDeclaration("value",
- type: gen.TypeExpression(toNativeValueMethod?.ReturnType ?? @byte))
- },
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- case ShapeMemberNames_V1.Value.ToNativeValue:
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
- ShapeMemberNames_V1.Value.ToNativeValue,
- returnType: gen.TypeExpression(fromNativeValueMethod?.Parameters[0].Type ?? @byte),
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- case ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource:
- INamedTypeSymbol? getManagedValuesDestinationReturnType = (INamedTypeSymbol?)getManagedValuesDestinationMethod?.ReturnType;
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
- ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource,
- returnType: gen.TypeExpression(
- readOnlySpanOfT.Construct(
- getManagedValuesDestinationReturnType?.TypeArguments[0] ?? @object)),
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- case ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination:
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
- ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination,
- returnType: gen.TypeExpression(spanOfByte),
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- case ShapeMemberNames_V1.LinearCollection.GetNativeValuesSource:
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
- ShapeMemberNames_V1.LinearCollection.GetNativeValuesSource,
- parameters: new[]
- {
- gen.ParameterDeclaration("numElements", type: gen.TypeExpression(int32))
- },
- returnType: gen.TypeExpression(readOnlySpanOfByte),
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- case ShapeMemberNames_V1.LinearCollection.GetManagedValuesDestination:
- INamedTypeSymbol? getManagedValuesSourceReturnType = (INamedTypeSymbol?)getManagedValuesSourceMethod?.ReturnType;
- updatedDeclaration = gen.AddMembers(updatedDeclaration, gen.MethodDeclaration(
- ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination,
- parameters: new[]
- {
- gen.ParameterDeclaration("numElements", type: gen.TypeExpression(int32))
- },
- returnType: gen.TypeExpression(
- spanOfT.Construct(
- getManagedValuesSourceReturnType?.TypeArguments[0] ?? @object)),
- accessibility: Accessibility.Public,
- statements: throwNotImplementedStatements));
- break;
- default:
- break;
- }
- }
-
- return updatedDeclaration;
+ // TODO: Implement adding the missing members for the V2 shapes
+ return node;
}
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomTypeMarshallerDirection.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/CustomTypeMarshallingDirection.cs
similarity index 80%
rename from src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomTypeMarshallerDirection.cs
rename to src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/CustomTypeMarshallingDirection.cs
index 7c1748171b47b..25dd1dd095402 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/CustomTypeMarshallerDirection.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/CustomTypeMarshallingDirection.cs
@@ -1,19 +1,16 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// 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.ComponentModel;
-#if MICROSOFT_INTEROP_SOURCEGENERATION
+
namespace Microsoft.Interop
-#else
-namespace System.Runtime.InteropServices.Marshalling
-#endif
{
///
/// A direction of marshalling data into or out of the managed environment
///
[Flags]
- public enum CustomTypeMarshallerDirection
+ public enum CustomTypeMarshallingDirection
{
///
/// No marshalling direction
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.V1.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.V1.cs
deleted file mode 100644
index 83e02fa4e3e58..0000000000000
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.V1.cs
+++ /dev/null
@@ -1,227 +0,0 @@
-// 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.Collections.Immutable;
-using System.Linq;
-using System.Runtime.InteropServices;
-using Microsoft.CodeAnalysis;
-
-namespace Microsoft.Interop
-{
- public readonly record struct CustomTypeMarshallerData_V1(CustomTypeMarshallerKind Kind, CustomTypeMarshallerDirection Direction, CustomTypeMarshallerFeatures Features, int? BufferSize);
-
- public static class ShapeMemberNames_V1
- {
- public abstract class Value
- {
- public const string ToNativeValue = nameof(ToNativeValue);
- public const string FromNativeValue = nameof(FromNativeValue);
- public const string GetPinnableReference = nameof(GetPinnableReference);
- public const string FreeNative = nameof(FreeNative);
- public const string ToManaged = nameof(ToManaged);
- }
-
- public abstract class LinearCollection : Value
- {
- public const string GetManagedValuesDestination = nameof(GetManagedValuesDestination);
- public const string GetManagedValuesSource = nameof(GetManagedValuesSource);
- public const string GetNativeValuesDestination = nameof(GetNativeValuesDestination);
- public const string GetNativeValuesSource = nameof(GetNativeValuesSource);
- }
- }
- public static class ManualTypeMarshallingHelper_V1
- {
- public static class CustomMarshallerAttributeFields
- {
- public const string BufferSize = nameof(BufferSize);
- public const string Direction = nameof(Direction);
- public const string Features = nameof(Features);
- }
-
- public static (bool hasAttribute, ITypeSymbol? managedType, CustomTypeMarshallerData_V1? kind) GetMarshallerShapeInfo(ITypeSymbol marshallerType)
- {
- var attr = marshallerType.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.ToDisplayString() == TypeNames.CustomTypeMarshallerAttribute);
- if (attr is null)
- {
- return (false, null, null);
- }
- if (attr.ConstructorArguments.Length == 0)
- {
- return (true, null, null);
- }
- CustomTypeMarshallerKind kind = CustomTypeMarshallerKind.Value;
- ITypeSymbol? managedType = attr.ConstructorArguments[0].Value as ITypeSymbol;
- if (attr.ConstructorArguments.Length > 1)
- {
- if (attr.ConstructorArguments[1].Value is not int i)
- {
- return (true, managedType, null);
- }
- kind = (CustomTypeMarshallerKind)i;
- }
- var namedArguments = attr.NamedArguments.ToImmutableDictionary();
- int? bufferSize = namedArguments.TryGetValue(CustomMarshallerAttributeFields.BufferSize, out TypedConstant bufferSizeConstant) ? bufferSizeConstant.Value as int? : null;
- CustomTypeMarshallerDirection direction = namedArguments.TryGetValue(CustomMarshallerAttributeFields.Direction, out TypedConstant directionConstant) ? (CustomTypeMarshallerDirection)directionConstant.Value : CustomTypeMarshallerDirection.Ref;
- CustomTypeMarshallerFeatures features = namedArguments.TryGetValue(CustomMarshallerAttributeFields.Features, out TypedConstant featuresConstant) ? (CustomTypeMarshallerFeatures)featuresConstant.Value : CustomTypeMarshallerFeatures.None;
- return (true, managedType, new CustomTypeMarshallerData_V1(kind, direction, features, bufferSize));
- }
-
- ///
- /// Get the supported for a marshaller type
- ///
- /// The marshaller type.
- /// The mananged type that would be marshalled.
- /// Supported
- public static CustomTypeMarshallerPinning GetMarshallerPinningFeatures(ITypeSymbol marshallerType, ITypeSymbol? managedType)
- {
- CustomTypeMarshallerPinning pinning = CustomTypeMarshallerPinning.None;
-
- if (ManualTypeMarshallingHelper.FindGetPinnableReference(marshallerType) is not null)
- {
- pinning |= CustomTypeMarshallerPinning.NativeType;
- }
-
- if (managedType is not null && ManualTypeMarshallingHelper.FindGetPinnableReference(managedType) is not null)
- {
- pinning |= CustomTypeMarshallerPinning.ManagedType;
- }
-
- return pinning;
- }
-
- public static bool HasToManagedMethod(ITypeSymbol nativeType, ITypeSymbol managedType)
- {
- return nativeType.GetMembers(ShapeMemberNames_V1.Value.ToManaged)
- .OfType()
- .Any(m => m.Parameters.IsEmpty
- && !m.ReturnsByRef
- && !m.ReturnsByRefReadonly
- && SymbolEqualityComparer.Default.Equals(m.ReturnType, managedType)
- && !m.IsStatic);
- }
-
- public static bool IsManagedToNativeConstructor(
- IMethodSymbol ctor,
- ITypeSymbol managedType,
- CustomTypeMarshallerKind variant)
- {
- if (variant == CustomTypeMarshallerKind.LinearCollection)
- {
- return ctor.Parameters.Length == 2
- && SymbolEqualityComparer.Default.Equals(managedType, ctor.Parameters[0].Type)
- && ctor.Parameters[1].Type.SpecialType == SpecialType.System_Int32;
- }
- return ctor.Parameters.Length == 1
- && SymbolEqualityComparer.Default.Equals(managedType, ctor.Parameters[0].Type);
- }
-
- public static bool IsCallerAllocatedSpanConstructor(
- IMethodSymbol ctor,
- ITypeSymbol managedType,
- ITypeSymbol spanOfT,
- CustomTypeMarshallerKind variant,
- out ITypeSymbol? spanElementType)
- {
- spanElementType = null;
- if (variant == CustomTypeMarshallerKind.LinearCollection)
- {
- return ctor.Parameters.Length == 3
- && SymbolEqualityComparer.Default.Equals(managedType, ctor.Parameters[0].Type)
- && IsSpanOfUnmanagedType(ctor.Parameters[1].Type, spanOfT, out spanElementType)
- && spanElementType.SpecialType == SpecialType.System_Byte
- && ctor.Parameters[2].Type.SpecialType == SpecialType.System_Int32;
- }
- return ctor.Parameters.Length == 2
- && SymbolEqualityComparer.Default.Equals(managedType, ctor.Parameters[0].Type)
- && IsSpanOfUnmanagedType(ctor.Parameters[1].Type, spanOfT, out spanElementType);
-
- static bool IsSpanOfUnmanagedType(ITypeSymbol typeToCheck, ITypeSymbol spanOfT, out ITypeSymbol? typeArgument)
- {
- typeArgument = null;
- if (typeToCheck is INamedTypeSymbol namedType
- && SymbolEqualityComparer.Default.Equals(spanOfT, namedType.ConstructedFrom)
- && namedType.TypeArguments.Length == 1
- && namedType.TypeArguments[0].IsUnmanagedType)
- {
- typeArgument = namedType.TypeArguments[0];
- return true;
- }
-
- return false;
- }
- }
-
- public static bool HasFreeNativeMethod(ITypeSymbol type)
- {
- return type.GetMembers(ShapeMemberNames_V1.Value.FreeNative)
- .OfType()
- .Any(m => m is { IsStatic: false, Parameters.Length: 0, ReturnType.SpecialType: SpecialType.System_Void });
- }
-
- public static IMethodSymbol? FindToNativeValueMethod(ITypeSymbol type)
- {
- return type.GetMembers(ShapeMemberNames_V1.Value.ToNativeValue)
- .OfType()
- .FirstOrDefault(m => m is { IsStatic: false, Parameters.Length: 0 });
- }
-
- public static IMethodSymbol? FindFromNativeValueMethod(ITypeSymbol type)
- {
- return type.GetMembers(ShapeMemberNames_V1.Value.FromNativeValue)
- .OfType()
- .FirstOrDefault(m => m is { IsStatic: false, Parameters.Length: 1, ReturnType.SpecialType: SpecialType.System_Void });
- }
-
- public static bool TryGetElementTypeFromLinearCollectionMarshaller(ITypeSymbol type, ITypeSymbol readOnlySpanOfT, out ITypeSymbol elementType)
- {
- if (FindGetManagedValuesSourceMethod(type, readOnlySpanOfT) is not IMethodSymbol managedValuesSourceMethod)
- {
- elementType = null!;
- return false;
- }
-
- elementType = ((INamedTypeSymbol)managedValuesSourceMethod.ReturnType).TypeArguments[0];
- return true;
- }
-
- public static IMethodSymbol? FindGetManagedValuesSourceMethod(ITypeSymbol type, ITypeSymbol readOnlySpanOfT)
- {
- return type
- .GetMembers(ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource)
- .OfType()
- .FirstOrDefault(m => m is { IsStatic: false, ReturnsByRef: false, ReturnsByRefReadonly: false, Parameters.Length: 0, ReturnType: INamedTypeSymbol { ConstructedFrom: INamedTypeSymbol returnType } }
- && SymbolEqualityComparer.Default.Equals(returnType, readOnlySpanOfT));
- }
-
- public static IMethodSymbol? FindGetManagedValuesDestinationMethod(ITypeSymbol type, ITypeSymbol spanOfT)
- {
- return type
- .GetMembers(ShapeMemberNames_V1.LinearCollection.GetManagedValuesDestination)
- .OfType()
- .FirstOrDefault(m => m is { IsStatic: false, ReturnsByRef: false, ReturnsByRefReadonly: false, Parameters.Length: 1, ReturnType: INamedTypeSymbol { ConstructedFrom: INamedTypeSymbol returnType } }
- && m.Parameters[0].Type.SpecialType == SpecialType.System_Int32
- && SymbolEqualityComparer.Default.Equals(returnType, spanOfT));
- }
-
- public static IMethodSymbol? FindGetNativeValuesDestinationMethod(ITypeSymbol type, ITypeSymbol spanOfByte)
- {
- return type
- .GetMembers(ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination)
- .OfType()
- .FirstOrDefault(m => m is { IsStatic: false, ReturnsByRef: false, ReturnsByRefReadonly: false, Parameters.Length: 0, ReturnType: INamedTypeSymbol returnType }
- && SymbolEqualityComparer.Default.Equals(returnType, spanOfByte));
- }
-
- public static IMethodSymbol? FindGetNativeValuesSourceMethod(ITypeSymbol type, ITypeSymbol readOnlySpanOfByte)
- {
- return type
- .GetMembers(ShapeMemberNames_V1.LinearCollection.GetNativeValuesSource)
- .OfType()
- .FirstOrDefault(m => m is { IsStatic: false, ReturnsByRef: false, ReturnsByRefReadonly: false, Parameters.Length: 1, ReturnType: INamedTypeSymbol returnType }
- && m.Parameters[0].Type.SpecialType == SpecialType.System_Int32
- && SymbolEqualityComparer.Default.Equals(returnType, readOnlySpanOfByte));
- }
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs
index 8827eacd59020..89a11309070ff 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs
@@ -229,8 +229,7 @@ private static bool TryGetMarshallersFromEntryType(
}
}
- if (innerType.ToDisplayString() != TypeNames.CustomTypeMarshallerAttributeGenericPlaceholder
- && innerType.ToDisplayString() != TypeNames.CustomMarshallerAttributeGenericPlaceholder)
+ if (innerType.ToDisplayString() != TypeNames.CustomMarshallerAttributeGenericPlaceholder)
{
return managedType;
}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs
index 100d756bc32e5..611a4b1cb0c65 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs
@@ -56,31 +56,6 @@ public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext conte
return CreateCustomNativeTypeMarshaller(info, context, marshalInfo);
}
- if (info.MarshallingAttributeInfo is NativeMarshallingAttributeInfo_V1 marshalInfoV1)
- {
- if (Options.RuntimeMarshallingDisabled || marshalInfoV1.IsStrictlyBlittable)
- {
- return CreateCustomNativeTypeMarshaller_V1(info, context, marshalInfoV1);
- }
-
- if (marshalInfoV1.NativeValueType is SpecialTypeInfo specialType
- && specialType.SpecialType.IsAlwaysBlittable())
- {
- return CreateCustomNativeTypeMarshaller_V1(info, context, marshalInfoV1);
- }
-
- if (marshalInfoV1.NativeValueType is PointerTypeInfo)
- {
- return CreateCustomNativeTypeMarshaller_V1(info, context, marshalInfoV1);
- }
-
- throw new MarshallingNotSupportedException(info, context)
- {
- NotSupportedDetails = SR.RuntimeMarshallingMustBeDisabled,
- DiagnosticProperties = AddDisableRuntimeMarshallingAttributeProperties
- };
- }
-
if (info.MarshallingAttributeInfo is UnmanagedBlittableMarshallingInfo blittableInfo)
{
if (Options.RuntimeMarshallingDisabled || blittableInfo.IsStrictlyBlittable)
@@ -141,11 +116,6 @@ ExpressionSyntax GetExpressionForParam(TypePositionInfo paramInfo)
type = marshallerData.CollectionElementType;
marshallingInfo = marshallerData.CollectionElementMarshallingInfo;
}
- else if (marshallingInfo is NativeLinearCollectionMarshallingInfo_V1 collectionInfoV1)
- {
- type = collectionInfoV1.ElementType;
- marshallingInfo = collectionInfoV1.ElementMarshallingInfo;
- }
else
{
throw new MarshallingNotSupportedException(info, context)
@@ -269,9 +239,7 @@ private IMarshallingGenerator CreateCustomNativeTypeMarshaller(TypePositionInfo
marshallingGenerator = new StaticPinnableManagedValueMarshaller(marshallingGenerator, marshallerData.MarshallerType.Syntax);
}
- return marshalInfo.IsPinnableManagedType
- ? new PinnableManagedValueMarshaller(marshallingGenerator)
- : marshallingGenerator;
+ return marshallingGenerator;
}
private IMarshallingGenerator CreateNativeCollectionMarshaller(
@@ -351,16 +319,13 @@ private IMarshallingGenerator CreateNativeCollectionMarshaller(
marshallingGenerator = new StaticPinnableManagedValueMarshaller(marshallingGenerator, marshallerTypeSyntax);
}
- return marshalInfo.IsPinnableManagedType && elementIsBlittable
- ? new PinnableManagedValueMarshaller(marshallingGenerator)
- : marshallingGenerator;
+ return marshallingGenerator;
}
private static bool ElementTypeIsSometimesNonBlittable(TypePositionInfo elementInfo)
{
if (elementInfo.MarshallingAttributeInfo is NoMarshallingInfo
- || elementInfo.MarshallingAttributeInfo is UnmanagedBlittableMarshallingInfo { IsStrictlyBlittable: true }
- || elementInfo.MarshallingAttributeInfo is NativeMarshallingAttributeInfo_V1 { IsStrictlyBlittable: true })
+ || elementInfo.MarshallingAttributeInfo is UnmanagedBlittableMarshallingInfo { IsStrictlyBlittable: true })
{
return false;
}
@@ -419,159 +384,6 @@ private void ValidateCustomNativeTypeMarshallingSupported(TypePositionInfo info,
}
}
- private IMarshallingGenerator CreateCustomNativeTypeMarshaller_V1(TypePositionInfo info, StubCodeContext context, NativeMarshallingAttributeInfo_V1 marshalInfo)
- {
- ValidateCustomNativeTypeMarshallingSupported_V1(info, context, marshalInfo);
-
- ICustomNativeTypeMarshallingStrategy marshallingStrategy = new SimpleCustomNativeTypeMarshalling(marshalInfo.NativeMarshallingType.Syntax);
-
- if ((marshalInfo.MarshallingFeatures & CustomTypeMarshallerFeatures.CallerAllocatedBuffer) != 0)
- {
- if (marshalInfo.BufferSize is null)
- {
- throw new MarshallingNotSupportedException(info, context);
- }
- marshallingStrategy = new StackallocOptimizationMarshalling(marshallingStrategy, marshalInfo.BufferElementType.Syntax, marshalInfo.BufferSize.Value);
- }
-
- if ((marshalInfo.MarshallingFeatures & CustomTypeMarshallerFeatures.UnmanagedResources) != 0)
- {
- marshallingStrategy = new FreeNativeCleanupStrategy(marshallingStrategy);
- }
-
- // Collections have extra configuration, so handle them here.
- if (marshalInfo is NativeLinearCollectionMarshallingInfo_V1 collectionMarshallingInfo)
- {
- return CreateNativeCollectionMarshaller_V1(info, context, collectionMarshallingInfo, marshallingStrategy);
- }
- else if (marshalInfo.NativeValueType is not null)
- {
- marshallingStrategy = new CustomNativeTypeWithToFromNativeValueMarshalling(marshallingStrategy, marshalInfo.NativeValueType.Syntax);
- if (marshalInfo.PinningFeatures.HasFlag(CustomTypeMarshallerPinning.NativeType) && marshalInfo.MarshallingFeatures.HasFlag(CustomTypeMarshallerFeatures.TwoStageMarshalling))
- {
- marshallingStrategy = new PinnableMarshallerTypeMarshalling(marshallingStrategy);
- }
- }
-
- IMarshallingGenerator marshallingGenerator = new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: false);
-
- if (marshalInfo.PinningFeatures.HasFlag(CustomTypeMarshallerPinning.ManagedType))
- {
- return new PinnableManagedValueMarshaller(marshallingGenerator);
- }
-
- return marshallingGenerator;
- }
-
- private static void ValidateCustomNativeTypeMarshallingSupported_V1(TypePositionInfo info, StubCodeContext context, NativeMarshallingAttributeInfo_V1 marshalInfo)
- {
- // The marshalling method for this type doesn't support marshalling from native to managed,
- // but our scenario requires marshalling from native to managed.
- if ((info.RefKind == RefKind.Ref || info.RefKind == RefKind.Out || info.IsManagedReturnPosition)
- && !marshalInfo.Direction.HasFlag(CustomTypeMarshallerDirection.Out))
- {
- throw new MarshallingNotSupportedException(info, context)
- {
- NotSupportedDetails = string.Format(SR.CustomTypeMarshallingNativeToManagedUnsupported, marshalInfo.NativeMarshallingType.FullTypeName)
- };
- }
-
- // The marshalling method for this type doesn't support marshalling from managed to native by value,
- // but our scenario requires marshalling from managed to native by value.
- if (!info.IsByRef
- && !info.IsManagedReturnPosition
- && context.SingleFrameSpansNativeContext
- && !(marshalInfo.PinningFeatures.HasFlag(CustomTypeMarshallerPinning.ManagedType)
- || marshalInfo.MarshallingFeatures.HasFlag(CustomTypeMarshallerFeatures.CallerAllocatedBuffer)
- || marshalInfo.Direction.HasFlag(CustomTypeMarshallerDirection.In)))
- {
- throw new MarshallingNotSupportedException(info, context)
- {
- NotSupportedDetails = string.Format(SR.CustomTypeMarshallingManagedToNativeUnsupported, marshalInfo.NativeMarshallingType.FullTypeName)
- };
- }
-
- // The marshalling method for this type doesn't support marshalling from managed to native by reference,
- // but our scenario requires marshalling from managed to native by reference.
- // "in" byref supports stack marshalling.
- if (info.RefKind == RefKind.In
- && !(context.SingleFrameSpansNativeContext && marshalInfo.MarshallingFeatures.HasFlag(CustomTypeMarshallerFeatures.CallerAllocatedBuffer))
- && !marshalInfo.Direction.HasFlag(CustomTypeMarshallerDirection.In))
- {
- throw new MarshallingNotSupportedException(info, context)
- {
- NotSupportedDetails = string.Format(SR.CustomTypeMarshallingManagedToNativeUnsupported, marshalInfo.NativeMarshallingType.FullTypeName)
- };
- }
-
- // The marshalling method for this type doesn't support marshalling from managed to native by reference,
- // but our scenario requires marshalling from managed to native by reference.
- // "ref" byref marshalling doesn't support stack marshalling
- // The "Out" direction for "ref" was checked above
- if (info.RefKind == RefKind.Ref
- && !marshalInfo.Direction.HasFlag(CustomTypeMarshallerDirection.In))
- {
- throw new MarshallingNotSupportedException(info, context)
- {
- NotSupportedDetails = string.Format(SR.CustomTypeMarshallingManagedToNativeUnsupported, marshalInfo.NativeMarshallingType.FullTypeName)
- };
- }
- }
-
- private IMarshallingGenerator CreateNativeCollectionMarshaller_V1(
- TypePositionInfo info,
- StubCodeContext context,
- NativeLinearCollectionMarshallingInfo_V1 collectionInfo,
- ICustomNativeTypeMarshallingStrategy marshallingStrategy)
- {
- var elementInfo = new TypePositionInfo(collectionInfo.ElementType, collectionInfo.ElementMarshallingInfo)
- {
- ManagedIndex = info.ManagedIndex,
- RefKind = CreateElementRefKind(info.RefKind, info.ByValueContentsMarshalKind)
- };
- IMarshallingGenerator elementMarshaller = _elementMarshallingGenerator.Create(
- elementInfo,
- new LinearCollectionElementMarshallingCodeContext(StubCodeContext.Stage.Setup, string.Empty, string.Empty, context));
-
- ExpressionSyntax numElementsExpression = LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0));
- if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In))
- {
- // In this case, we need a numElementsExpression supplied from metadata, so we'll calculate it here.
- numElementsExpression = GetNumElementsExpressionFromMarshallingInfo(info, collectionInfo.ElementCountInfo, context);
- }
-
- bool elementIsBlittable = elementMarshaller is BlittableMarshaller;
- if (elementIsBlittable)
- {
- marshallingStrategy = new LinearCollectionWithBlittableElementsMarshalling(marshallingStrategy, collectionInfo.ElementType.Syntax, numElementsExpression);
- }
- else
- {
- marshallingStrategy = new LinearCollectionWithNonBlittableElementsMarshalling(marshallingStrategy, elementMarshaller, elementInfo, numElementsExpression);
- }
-
- marshallingStrategy = new CustomNativeTypeWithToFromNativeValueMarshalling(marshallingStrategy, collectionInfo.NativeValueType.Syntax);
- if (collectionInfo.PinningFeatures.HasFlag(CustomTypeMarshallerPinning.NativeType) && collectionInfo.MarshallingFeatures.HasFlag(CustomTypeMarshallerFeatures.TwoStageMarshalling))
- {
- marshallingStrategy = new PinnableMarshallerTypeMarshalling(marshallingStrategy);
- }
-
- TypeSyntax nativeElementType = elementMarshaller.AsNativeType(elementInfo);
- marshallingStrategy = new SizeOfElementMarshalling(
- marshallingStrategy,
- SizeOfExpression(nativeElementType));
-
- IMarshallingGenerator marshallingGenerator = new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: false);
-
- // Elements in the collection must be blittable to use the pinnable marshaller.
- if (collectionInfo.PinningFeatures.HasFlag(CustomTypeMarshallerPinning.ManagedType) && elementIsBlittable)
- {
- return new PinnableManagedValueMarshaller(marshallingGenerator);
- }
-
- return marshallingGenerator;
- }
-
private static RefKind CreateElementRefKind(RefKind refKind, ByValueContentsMarshalKind byValueContentsMarshalKind)
{
if (refKind == RefKind.None)
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 aa6520c959b64..604530f800f64 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
@@ -14,10 +14,10 @@ namespace Microsoft.Interop
///
internal sealed class CustomNativeTypeMarshallingGenerator : IMarshallingGenerator
{
- private readonly ICustomTypeMarshallingStrategyBase _nativeTypeMarshaller;
+ private readonly ICustomTypeMarshallingStrategy _nativeTypeMarshaller;
private readonly bool _enableByValueContentsMarshalling;
- public CustomNativeTypeMarshallingGenerator(ICustomTypeMarshallingStrategyBase nativeTypeMarshaller, bool enableByValueContentsMarshalling)
+ public CustomNativeTypeMarshallingGenerator(ICustomTypeMarshallingStrategy nativeTypeMarshaller, bool enableByValueContentsMarshalling)
{
_nativeTypeMarshaller = nativeTypeMarshaller;
_enableByValueContentsMarshalling = enableByValueContentsMarshalling;
@@ -54,14 +54,7 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont
case StubCodeContext.Stage.Marshal:
if (!info.IsManagedReturnPosition && info.RefKind != RefKind.Out)
{
- if (_nativeTypeMarshaller is ICustomNativeTypeMarshallingStrategy strategyWithConstructorArgs)
- {
- return strategyWithConstructorArgs.GenerateMarshalStatements(info, context, strategyWithConstructorArgs.GetNativeTypeConstructorArguments(info, context));
- }
- else if (_nativeTypeMarshaller is ICustomTypeMarshallingStrategy strategyWithNoConstructorArgs)
- {
- return strategyWithNoConstructorArgs.GenerateMarshalStatements(info, context);
- }
+ return _nativeTypeMarshaller.GenerateMarshalStatements(info, context);
}
break;
case StubCodeContext.Stage.Pin:
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
deleted file mode 100644
index b7699f4855990..0000000000000
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomNativeTypeMarshallingStrategy.cs
+++ /dev/null
@@ -1,1281 +0,0 @@
-// 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.Linq;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-
-namespace Microsoft.Interop
-{
- internal interface ICustomNativeTypeMarshallingStrategy : ICustomTypeMarshallingStrategyBase
- {
- IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context);
-
- IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments);
- }
-
- ///
- /// Marshalling support for a type that has a custom native type.
- ///
- internal sealed class SimpleCustomNativeTypeMarshalling : ICustomNativeTypeMarshallingStrategy
- {
- private readonly TypeSyntax _nativeTypeSyntax;
-
- public SimpleCustomNativeTypeMarshalling(TypeSyntax nativeTypeSyntax)
- {
- _nativeTypeSyntax = nativeTypeSyntax;
- }
-
- public TypeSyntax AsNativeType(TypePositionInfo info)
- {
- return _nativeTypeSyntax;
- }
-
- public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context)
- {
- return true;
- }
-
- public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
- {
- return Array.Empty();
- }
-
- public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments)
- {
- // = new();
- yield return ExpressionStatement(
- AssignmentExpression(
- SyntaxKind.SimpleAssignmentExpression,
- IdentifierName(context.GetIdentifiers(info).native),
- ImplicitObjectCreationExpression()
- .WithArgumentList(ArgumentList(SeparatedList(nativeTypeConstructorArguments)))));
- }
-
- public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- return Array.Empty();
- }
-
- public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- // If the current element is being marshalled by-value [Out], then don't call the ToManaged method and do the assignment.
- // The assignment will end up being a no-op and will not be observed.
- if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))
- {
- yield break;
- }
-
- (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info);
- // = .ToManaged();
- yield return ExpressionStatement(
- AssignmentExpression(
- SyntaxKind.SimpleAssignmentExpression,
- IdentifierName(managedIdentifier),
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.Value.ToManaged)))));
- }
-
- public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context)
- {
- return Array.Empty();
- }
-
- public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context)
- {
- yield return Argument(IdentifierName(context.GetIdentifiers(info).managed));
- }
-
- public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context)
- {
- return Array.Empty();
- }
-
- public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context)
- {
- return Array.Empty();
- }
- }
-
- ///
- /// A context that redefines the 'native' identifier for a TypePositionInfo to be the marshaller identifier.
- ///
- internal sealed record CustomNativeTypeWithToFromNativeValueContext : StubCodeContext
- {
- public CustomNativeTypeWithToFromNativeValueContext(StubCodeContext parentContext)
- {
- ParentContext = parentContext;
- CurrentStage = parentContext.CurrentStage;
- }
-
- public override (TargetFramework framework, Version version) GetTargetFramework()
- => ParentContext!.GetTargetFramework();
-
- public override bool SingleFrameSpansNativeContext => ParentContext!.SingleFrameSpansNativeContext;
-
- public override bool AdditionalTemporaryStateLivesAcrossStages => ParentContext!.AdditionalTemporaryStateLivesAcrossStages;
-
- public override (string managed, string native) GetIdentifiers(TypePositionInfo info)
- {
- return (ParentContext!.GetIdentifiers(info).managed, MarshallerHelpers.GetMarshallerIdentifier(info, ParentContext));
- }
- }
-
- ///
- /// Marshaller that enables support of ToNativeValue/FromNativeValue methods on a native type.
- ///
- internal sealed class CustomNativeTypeWithToFromNativeValueMarshalling : ICustomNativeTypeMarshallingStrategy
- {
- private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller;
- private readonly TypeSyntax _nativeValueTypeSyntax;
-
- public CustomNativeTypeWithToFromNativeValueMarshalling(ICustomNativeTypeMarshallingStrategy innerMarshaller, TypeSyntax nativeValueTypeSyntax)
- {
- _innerMarshaller = innerMarshaller;
- _nativeValueTypeSyntax = nativeValueTypeSyntax;
- }
-
- public TypeSyntax AsNativeType(TypePositionInfo info)
- {
- return _nativeValueTypeSyntax;
- }
-
- public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context)
- {
- return true;
- }
-
- public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
- {
- var subContext = new CustomNativeTypeWithToFromNativeValueContext(context);
-
- // When temporary state does not live across stages, the marshaller state is uninitialized
- // in any stage other than Marshal and Unmarshal. So, we need to reinitialize it here in Cleanup
- // from the native value so we can safely run any cleanup functionality in the marshaller.
- if (!context.AdditionalTemporaryStateLivesAcrossStages)
- {
- yield return GenerateFromNativeValueInvocation(info, context, subContext);
- }
-
- foreach (StatementSyntax statement in _innerMarshaller.GenerateCleanupStatements(info, subContext))
- {
- yield return statement;
- }
- }
-
- public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments)
- {
- var subContext = new CustomNativeTypeWithToFromNativeValueContext(context);
- foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, subContext, nativeTypeConstructorArguments))
- {
- yield return statement;
- }
- }
-
- public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- var subContext = new CustomNativeTypeWithToFromNativeValueContext(context);
-
- foreach (StatementSyntax statement in _innerMarshaller.GeneratePinnedMarshalStatements(info, subContext))
- {
- yield return statement;
- }
-
- // = .ToNativeValue();
- yield return ExpressionStatement(
- AssignmentExpression(
- SyntaxKind.SimpleAssignmentExpression,
- IdentifierName(context.GetIdentifiers(info).native),
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(subContext.GetIdentifiers(info).native),
- IdentifierName(ShapeMemberNames_V1.Value.ToNativeValue)),
- ArgumentList())));
- }
-
- private static StatementSyntax GenerateFromNativeValueInvocation(TypePositionInfo info, StubCodeContext context, CustomNativeTypeWithToFromNativeValueContext subContext)
- {
- // .FromNativeValue();
- return ExpressionStatement(
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(subContext.GetIdentifiers(info).native),
- IdentifierName(ShapeMemberNames_V1.Value.FromNativeValue)),
- ArgumentList(SingletonSeparatedList(Argument(IdentifierName(context.GetIdentifiers(info).native))))));
- }
-
- public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context)
- {
- var subContext = new CustomNativeTypeWithToFromNativeValueContext(context);
-
- if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In))
- {
- yield return GenerateFromNativeValueInvocation(info, context, subContext);
- }
- }
-
- public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- var subContext = new CustomNativeTypeWithToFromNativeValueContext(context);
-
- foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, subContext))
- {
- yield return statement;
- }
- }
-
- public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context)
- {
- var subContext = new CustomNativeTypeWithToFromNativeValueContext(context);
- return _innerMarshaller.GetNativeTypeConstructorArguments(info, subContext);
- }
-
- public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context)
- {
- var subContext = new CustomNativeTypeWithToFromNativeValueContext(context);
- yield return LocalDeclarationStatement(
- VariableDeclaration(
- _innerMarshaller.AsNativeType(info),
- SingletonSeparatedList(
- VariableDeclarator(subContext.GetIdentifiers(info).native)
- .WithInitializer(EqualsValueClause(LiteralExpression(SyntaxKind.DefaultLiteralExpression))))));
-
- foreach (StatementSyntax statement in _innerMarshaller.GenerateSetupStatements(info, subContext))
- {
- yield return statement;
- }
- }
-
- public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context)
- {
- var subContext = new CustomNativeTypeWithToFromNativeValueContext(context);
- return _innerMarshaller.GeneratePinStatements(info, subContext);
- }
- }
-
- ///
- /// Marshaller that enables support for a stackalloc constructor variant on a native type.
- ///
- internal sealed class StackallocOptimizationMarshalling : ICustomNativeTypeMarshallingStrategy
- {
- private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller;
- private readonly TypeSyntax _bufferElementType;
- private readonly int _bufferSize;
-
- public StackallocOptimizationMarshalling(ICustomNativeTypeMarshallingStrategy innerMarshaller, TypeSyntax bufferElementType, int bufferSize)
- {
- _innerMarshaller = innerMarshaller;
- _bufferElementType = bufferElementType;
- _bufferSize = bufferSize;
- }
-
- public TypeSyntax AsNativeType(TypePositionInfo info)
- {
- return _innerMarshaller.AsNativeType(info);
- }
-
- public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateCleanupStatements(info, context);
- }
-
- public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments)
- {
- if (StackAllocOptimizationValid(info, context))
- {
- // * __stackptr = stackalloc [<_bufferSize>];
- yield return LocalDeclarationStatement(
- VariableDeclaration(
- PointerType(_bufferElementType),
- SingletonSeparatedList(
- VariableDeclarator(GetStackAllocPointerIdentifier(info, context))
- .WithInitializer(EqualsValueClause(
- StackAllocArrayCreationExpression(
- ArrayType(
- _bufferElementType,
- SingletonList(ArrayRankSpecifier(SingletonSeparatedList(
- LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(_bufferSize))
- ))))))))));
- }
-
- foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context, nativeTypeConstructorArguments))
- {
- yield return statement;
- }
- }
-
- public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GeneratePinnedMarshalStatements(info, context);
- }
-
- private static bool StackAllocOptimizationValid(TypePositionInfo info, StubCodeContext context)
- {
- return context.SingleFrameSpansNativeContext && (!info.IsByRef || info.RefKind == RefKind.In);
- }
-
- private static string GetStackAllocPointerIdentifier(TypePositionInfo info, StubCodeContext context)
- {
- return context.GetAdditionalIdentifier(info, "stackptr");
- }
-
- public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GeneratePinStatements(info, context);
- }
-
- public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateSetupStatements(info, context);
- }
-
- public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context);
- }
-
- public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateUnmarshalStatements(info, context);
- }
-
- public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context)
- {
- foreach (ArgumentSyntax arg in _innerMarshaller.GetNativeTypeConstructorArguments(info, context))
- {
- yield return arg;
- }
- if (StackAllocOptimizationValid(info, context))
- {
- yield return Argument(
- ObjectCreationExpression(
- GenericName(Identifier(TypeNames.System_Span),
- TypeArgumentList(SingletonSeparatedList(
- _bufferElementType))))
- .WithArgumentList(
- ArgumentList(SeparatedList(new ArgumentSyntax[]
- {
- Argument(IdentifierName(GetStackAllocPointerIdentifier(info, context))),
- Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(_bufferSize)))
- }))));
- }
- }
-
- public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.UsesNativeIdentifier(info, context);
- }
- }
-
- ///
- /// Marshaller that enables support for a FreeNative method on a native type.
- ///
- internal sealed class FreeNativeCleanupStrategy : ICustomNativeTypeMarshallingStrategy
- {
- private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller;
-
- public FreeNativeCleanupStrategy(ICustomNativeTypeMarshallingStrategy innerMarshaller)
- {
- _innerMarshaller = innerMarshaller;
- }
-
- public TypeSyntax AsNativeType(TypePositionInfo info)
- {
- return _innerMarshaller.AsNativeType(info);
- }
-
- public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
- {
- foreach (StatementSyntax statement in _innerMarshaller.GenerateCleanupStatements(info, context))
- {
- yield return statement;
- }
-
- // .FreeNative();
- yield return ExpressionStatement(
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(context.GetIdentifiers(info).native),
- IdentifierName(ShapeMemberNames_V1.Value.FreeNative))));
- }
-
- public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments)
- {
- return _innerMarshaller.GenerateMarshalStatements(info, context, nativeTypeConstructorArguments);
- }
-
- public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GeneratePinnedMarshalStatements(info, context);
- }
-
- public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GeneratePinStatements(info, context);
- }
-
- public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateSetupStatements(info, context);
- }
-
- public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context);
- }
-
- public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateUnmarshalStatements(info, context);
- }
-
- public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GetNativeTypeConstructorArguments(info, context);
- }
-
- public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.UsesNativeIdentifier(info, context);
- }
- }
-
- ///
- /// Marshaller that calls the GetPinnableReference method on the marshaller value and enables support for the ToNativeValue and FromNativeValue methods.
- ///
- internal sealed class PinnableMarshallerTypeMarshalling : ICustomNativeTypeMarshallingStrategy
- {
- private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller;
-
- public PinnableMarshallerTypeMarshalling(ICustomNativeTypeMarshallingStrategy innerMarshaller)
- {
- _innerMarshaller = innerMarshaller;
- }
-
- public TypeSyntax AsNativeType(TypePositionInfo info)
- {
- return _innerMarshaller.AsNativeType(info);
- }
-
- public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateCleanupStatements(info, context);
- }
-
- public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments)
- {
- return _innerMarshaller.GenerateMarshalStatements(info, context, nativeTypeConstructorArguments);
- }
-
- public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GeneratePinnedMarshalStatements(info, context);
- }
-
- public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context)
- {
- // The type of the ignored identifier isn't relevant, so we use void* for all.
- // fixed (void* = &);
- var subContext = new CustomNativeTypeWithToFromNativeValueContext(context);
- yield return FixedStatement(
- VariableDeclaration(
- PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))),
- SingletonSeparatedList(
- VariableDeclarator(Identifier(context.GetAdditionalIdentifier(info, "ignored")))
- .WithInitializer(EqualsValueClause(
- IdentifierName(subContext.GetIdentifiers(info).native))))),
- EmptyStatement());
- }
-
- public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateSetupStatements(info, context);
- }
-
- public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context);
- }
-
- public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateUnmarshalStatements(info, context);
- }
-
- public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GetNativeTypeConstructorArguments(info, context);
- }
-
- public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.UsesNativeIdentifier(info, context);
- }
- }
-
- ///
- /// Marshaller that enables support for native types with the constructor variants that take a sizeOfElement int parameter.
- ///
- internal sealed class SizeOfElementMarshalling : ICustomNativeTypeMarshallingStrategy
- {
- private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller;
- private readonly ExpressionSyntax _sizeOfElementExpression;
-
- public SizeOfElementMarshalling(ICustomNativeTypeMarshallingStrategy innerMarshaller, ExpressionSyntax sizeOfElementExpression)
- {
- _innerMarshaller = innerMarshaller;
- _sizeOfElementExpression = sizeOfElementExpression;
- }
-
- public TypeSyntax AsNativeType(TypePositionInfo info)
- {
- return _innerMarshaller.AsNativeType(info);
- }
-
- public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
- {
- // When temporary state does not live across stages, the marshaller state is uninitialized
- // in any stage other than Marshal and Unmarshal. So, we need to reinitialize it here in Cleanup
- // from the native data so we can safely run any cleanup functionality in the marshaller.
- if (!context.AdditionalTemporaryStateLivesAcrossStages)
- {
- foreach (StatementSyntax statement in GenerateUnmarshallerCollectionInitialization(info, context))
- {
- yield return statement;
- }
- }
-
- foreach (StatementSyntax statement in _innerMarshaller.GenerateCleanupStatements(info, context))
- {
- yield return statement;
- }
- }
-
- public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments)
- {
- return _innerMarshaller.GenerateMarshalStatements(info, context, nativeTypeConstructorArguments);
- }
-
- public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GeneratePinnedMarshalStatements(info, context);
- }
-
-
- public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GeneratePinStatements(info, context);
- }
-
- public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateSetupStatements(info, context);
- }
-
- public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context)
- {
- // To fulfill the generic contiguous collection marshaller design,
- // we need to emit code to initialize the collection marshaller with the size of native elements
- // and set the unmanaged collection length before we marshal back the native data.
- // This ensures that the marshaller object has enough state to successfully set up the ManagedValues
- // and NativeValueStorage spans when the actual collection value is unmarshalled from native to the marshaller.
- foreach (StatementSyntax statement in GenerateUnmarshallerCollectionInitialization(info, context))
- {
- yield return statement;
- }
- foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context))
- {
- yield return statement;
- }
- }
-
- private IEnumerable GenerateUnmarshallerCollectionInitialization(TypePositionInfo info, StubCodeContext context)
- {
- string marshalerIdentifier = MarshallerHelpers.GetMarshallerIdentifier(info, context);
- if (info.RefKind == RefKind.Out || info.IsManagedReturnPosition)
- {
- yield return ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
- IdentifierName(marshalerIdentifier),
- ImplicitObjectCreationExpression().AddArgumentListArguments(Argument(_sizeOfElementExpression))));
- }
- }
-
- public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateUnmarshalStatements(info, context);
- }
-
- public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context)
- {
- foreach (ArgumentSyntax arg in _innerMarshaller.GetNativeTypeConstructorArguments(info, context))
- {
- yield return arg;
- }
- yield return Argument(_sizeOfElementExpression);
- }
-
- public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.UsesNativeIdentifier(info, context);
- }
- }
-
- ///
- /// Marshaller that enables support for marshalling blittable elements of a collection via a native type that implements the LinearCollection marshalling spec.
- ///
- internal sealed class LinearCollectionWithBlittableElementsMarshalling : ICustomNativeTypeMarshallingStrategy
- {
- private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller;
- private readonly TypeSyntax _elementType;
- private readonly ExpressionSyntax _numElementsExpression;
-
- public LinearCollectionWithBlittableElementsMarshalling(ICustomNativeTypeMarshallingStrategy innerMarshaller, TypeSyntax elementType, ExpressionSyntax numElementsExpression)
- {
- _innerMarshaller = innerMarshaller;
- _elementType = elementType;
- _numElementsExpression = numElementsExpression;
- }
-
- public TypeSyntax AsNativeType(TypePositionInfo info)
- {
- return _innerMarshaller.AsNativeType(info);
- }
-
- public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateCleanupStatements(info, context);
- }
-
- public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments)
- {
- string nativeIdentifier = context.GetIdentifiers(info).native;
- foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context, nativeTypeConstructorArguments))
- {
- yield return statement;
- }
-
- if (!info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out)
- {
- // If the parameter is marshalled by-value [Out], then we don't marshal the contents of the collection.
- // We do clear the span, so that if the invoke target doesn't fill it, we aren't left with undefined content.
- // .GetNativeValuesDestination().Clear();
- yield return ExpressionStatement(
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination)),
- ArgumentList()),
- IdentifierName("Clear"))));
- yield break;
- }
-
- // .GetManagedValuesSource().CopyTo(MemoryMarshal.Cast>(.GetNativeValuesDestination()));
- yield return ExpressionStatement(
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource)),
- ArgumentList()),
- IdentifierName("CopyTo")))
- .AddArgumentListArguments(
- Argument(
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- ParseTypeName(TypeNames.System_Runtime_InteropServices_MemoryMarshal),
- GenericName(
- Identifier("Cast"))
- .WithTypeArgumentList(
- TypeArgumentList(
- SeparatedList(
- new[]
- {
- PredefinedType(Token(SyntaxKind.ByteKeyword)),
- _elementType
- })))))
- .AddArgumentListArguments(
- Argument(
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination)),
- ArgumentList()))))));
- }
-
- public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GeneratePinnedMarshalStatements(info, context);
- }
-
- public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GeneratePinStatements(info, context);
- }
-
- public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateSetupStatements(info, context);
- }
-
- public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context);
- }
-
- public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- string nativeIdentifier = context.GetIdentifiers(info).native;
- string numElementsIdentifier = context.GetAdditionalIdentifier(info, "numElements");
-
- ExpressionSyntax copySource;
- ExpressionSyntax copyDestination;
- if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))
- {
- // .GetNativeValuesDestination()
- copySource = InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination)));
-
- // MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(.GetManagedValuesSource()), .GetManagedValuesSource().Length)
- copyDestination = InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- ParseName(TypeNames.System_Runtime_InteropServices_MemoryMarshal),
- IdentifierName("CreateSpan")),
- ArgumentList(
- SeparatedList(new[]
- {
- Argument(
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- ParseName(TypeNames.System_Runtime_InteropServices_MemoryMarshal),
- IdentifierName("GetReference")),
- ArgumentList(SingletonSeparatedList(
- Argument(
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource))))))))
- .WithRefKindKeyword(
- Token(SyntaxKind.RefKeyword)),
- Argument(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource))),
- IdentifierName("Length")))
- })));
-
- }
- else
- {
- yield return LocalDeclarationStatement(
- VariableDeclaration(
- PredefinedType(Token(SyntaxKind.IntKeyword)),
- SingletonSeparatedList(
- VariableDeclarator(numElementsIdentifier).WithInitializer(EqualsValueClause(_numElementsExpression)))));
-
- // .GetNativeValuesSource()
- copySource = InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetNativeValuesSource)),
- ArgumentList(SingletonSeparatedList(Argument(IdentifierName(numElementsIdentifier)))));
-
- // .GetManagedValuesDestination()
- copyDestination = InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetManagedValuesDestination)),
- ArgumentList(SingletonSeparatedList(Argument(IdentifierName(numElementsIdentifier)))));
- }
-
- // MemoryMarshal.Cast>().CopyTo();
- yield return ExpressionStatement(
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- ParseTypeName(TypeNames.System_Runtime_InteropServices_MemoryMarshal),
- GenericName(
- Identifier("Cast"))
- .WithTypeArgumentList(
- TypeArgumentList(
- SeparatedList(
- new[]
- {
- PredefinedType(Token(SyntaxKind.ByteKeyword)),
- _elementType
- })))))
- .AddArgumentListArguments(
- Argument(copySource)),
- IdentifierName("CopyTo")))
- .AddArgumentListArguments(
- Argument(copyDestination)));
-
- foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, context))
- {
- yield return statement;
- }
- }
-
- public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GetNativeTypeConstructorArguments(info, context);
- }
-
- public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.UsesNativeIdentifier(info, context);
- }
- }
-
- ///
- /// Marshaller that enables support for marshalling non-blittable elements of a collection via a native type that implements the LinearCollection marshalling spec.
- ///
- internal sealed class LinearCollectionWithNonBlittableElementsMarshalling : ICustomNativeTypeMarshallingStrategy
- {
- private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller;
- private readonly IMarshallingGenerator _elementMarshaller;
- private readonly TypePositionInfo _elementInfo;
- private readonly ExpressionSyntax _numElementsExpression;
-
- public LinearCollectionWithNonBlittableElementsMarshalling(ICustomNativeTypeMarshallingStrategy innerMarshaller,
- IMarshallingGenerator elementMarshaller,
- TypePositionInfo elementInfo,
- ExpressionSyntax numElementsExpression)
- {
- _innerMarshaller = innerMarshaller;
- _elementMarshaller = elementMarshaller;
- _elementInfo = elementInfo;
- _numElementsExpression = numElementsExpression;
- }
-
- private LocalDeclarationStatementSyntax GenerateNativeValuesDestinationDeclaration(TypePositionInfo info, StubCodeContext context)
- {
- string nativeIdentifier = context.GetIdentifiers(info).native;
- string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context);
- return LocalDeclarationStatement(VariableDeclaration(
- GenericName(
- Identifier(TypeNames.System_Span),
- TypeArgumentList(
- SingletonSeparatedList(_elementMarshaller.AsNativeType(_elementInfo).GetCompatibleGenericTypeParameterSyntax()))
- ),
- SingletonSeparatedList(
- VariableDeclarator(Identifier(nativeSpanIdentifier))
- .WithInitializer(EqualsValueClause(
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- ParseTypeName(TypeNames.System_Runtime_InteropServices_MemoryMarshal),
- GenericName(
- Identifier("Cast"))
- .WithTypeArgumentList(
- TypeArgumentList(
- SeparatedList(
- new[]
- {
- PredefinedType(Token(SyntaxKind.ByteKeyword)),
- _elementMarshaller.AsNativeType(_elementInfo).GetCompatibleGenericTypeParameterSyntax()
- })))))
- .AddArgumentListArguments(
- Argument(
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination)),
- ArgumentList()))))))));
- }
-
- private LocalDeclarationStatementSyntax GenerateNativeValuesSourceDeclaration(TypePositionInfo info, StubCodeContext context, string numElementsIdentifier)
- {
- string nativeIdentifier = context.GetIdentifiers(info).native;
- string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context);
- return LocalDeclarationStatement(VariableDeclaration(
- GenericName(
- Identifier(TypeNames.System_ReadOnlySpan),
- TypeArgumentList(
- SingletonSeparatedList(_elementMarshaller.AsNativeType(_elementInfo).GetCompatibleGenericTypeParameterSyntax()))
- ),
- SingletonSeparatedList(
- VariableDeclarator(Identifier(nativeSpanIdentifier))
- .WithInitializer(EqualsValueClause(
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- ParseTypeName(TypeNames.System_Runtime_InteropServices_MemoryMarshal),
- GenericName(
- Identifier("Cast"))
- .WithTypeArgumentList(
- TypeArgumentList(
- SeparatedList(
- new[]
- {
- PredefinedType(Token(SyntaxKind.ByteKeyword)),
- _elementMarshaller.AsNativeType(_elementInfo).GetCompatibleGenericTypeParameterSyntax()
- })))))
- .AddArgumentListArguments(
- Argument(
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetNativeValuesSource)),
- ArgumentList(SingletonSeparatedList(Argument(IdentifierName(numElementsIdentifier))))))))))));
- }
-
- private LocalDeclarationStatementSyntax GeneratedManagedValuesSourceDeclaration(TypePositionInfo info, StubCodeContext context)
- {
- string nativeIdentifier = context.GetIdentifiers(info).native;
- string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context);
- return LocalDeclarationStatement(VariableDeclaration(
- GenericName(
- Identifier(TypeNames.System_ReadOnlySpan),
- TypeArgumentList(
- SingletonSeparatedList(_elementInfo.ManagedType.Syntax))
- ),
- SingletonSeparatedList(
- VariableDeclarator(Identifier(managedSpanIdentifier))
- .WithInitializer(EqualsValueClause(
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource)),
- ArgumentList()))))));
- }
-
- private LocalDeclarationStatementSyntax GeneratedManagedValuesDestinationDeclaration(TypePositionInfo info, StubCodeContext context, string numElementsIdentifier)
- {
- string nativeIdentifier = context.GetIdentifiers(info).native;
- string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context);
- return LocalDeclarationStatement(VariableDeclaration(
- GenericName(
- Identifier(TypeNames.System_Span),
- TypeArgumentList(
- SingletonSeparatedList(_elementInfo.ManagedType.Syntax))
- ),
- SingletonSeparatedList(
- VariableDeclarator(Identifier(managedSpanIdentifier))
- .WithInitializer(EqualsValueClause(
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetManagedValuesDestination)),
- ArgumentList(SingletonSeparatedList(Argument(IdentifierName(numElementsIdentifier))))))))));
- }
-
- private 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 elementStatements = new();
-
- foreach (var 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 unmarshal them
- return MarshallerHelpers.GetForLoop(lengthExpression, elementSetupSubContext.IndexerIdentifier)
- .WithStatement(marshallingStatement);
- }
- return EmptyStatement();
- }
-
- public TypeSyntax AsNativeType(TypePositionInfo info)
- {
- return _innerMarshaller.AsNativeType(info);
- }
-
- public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context)
- {
- StatementSyntax contentsCleanupStatements = GenerateContentsMarshallingStatement(info, context,
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(MarshallerHelpers.GetNativeSpanIdentifier(info, context)),
- IdentifierName("Length")),
- StubCodeContext.Stage.Cleanup);
-
- if (!contentsCleanupStatements.IsKind(SyntaxKind.EmptyStatement))
- {
- yield return Block(
- GenerateNativeValuesDestinationDeclaration(info, context),
- contentsCleanupStatements);
- }
-
- foreach (StatementSyntax statement in _innerMarshaller.GenerateCleanupStatements(info, context))
- {
- yield return statement;
- }
- }
-
- public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments)
- {
- foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context, nativeTypeConstructorArguments))
- {
- yield return statement;
- }
-
- if (!info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out)
- {
- // If the parameter is marshalled by-value [Out], then we don't marshal the contents of the collection.
- // We do clear the span, so that if the invoke target doesn't fill it, we aren't left with undefined content.
- // .GetNativeValuesDestination().Clear();
- string nativeIdentifier = context.GetIdentifiers(info).native;
- yield return ExpressionStatement(
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetNativeValuesDestination)),
- ArgumentList()),
- IdentifierName("Clear"))));
- yield break;
- }
-
- yield return Block(
- GeneratedManagedValuesSourceDeclaration(info, context),
- GenerateNativeValuesDestinationDeclaration(info, context),
- GenerateContentsMarshallingStatement(info, context,
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(MarshallerHelpers.GetManagedSpanIdentifier(info, context)),
- IdentifierName("Length")),
- StubCodeContext.Stage.Marshal,
- // Using the PinnedMarshal stage here isn't strictly valid as we don't guarantee that GetPinnableReference
- // is pinned, but for our existing marshallers this is not an issue and we'll be removing support for stateful element marshallers soon
- // (at which point we can remove this)
- // and address this problem better when we bring them back in the future.
- StubCodeContext.Stage.PinnedMarshal));
- }
-
- public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GeneratePinnedMarshalStatements(info, context);
- }
-
-
- public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GeneratePinStatements(info, context);
- }
-
- public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateSetupStatements(info, context);
- }
-
- public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context);
- }
-
- private StatementSyntax GenerateByValueUnmarshalStatement(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.
- var (_, nativeIdentifier) = context.GetIdentifiers(info);
- string numElementsIdentifier = context.GetAdditionalIdentifier(info, "numElements");
- // int = .GetManagedValuesSource().Length;
- LocalDeclarationStatementSyntax numElementsDeclaration = LocalDeclarationStatement(
- VariableDeclaration(
- PredefinedType(Token(SyntaxKind.IntKeyword)),
- SingletonSeparatedList(
- VariableDeclarator(numElementsIdentifier).WithInitializer(EqualsValueClause(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource)),
- ArgumentList()),
- IdentifierName("Length")))))));
-
- string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context);
- // Span = MemoryMarshal.CreateSpan(ref Unsafe.AsRef(ref .GetManagedValuesSource().GetPinnableReference(), ));
- 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,
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName(nativeIdentifier),
- IdentifierName(ShapeMemberNames_V1.LinearCollection.GetManagedValuesSource)),
- ArgumentList()),
- IdentifierName("GetPinnableReference")),
- ArgumentList()))
- .WithRefKindKeyword(
- Token(SyntaxKind.InKeyword))))))
- .WithRefKindKeyword(
- Token(SyntaxKind.RefKeyword)),
- Argument(
- IdentifierName(numElementsIdentifier))
- }))))))));
-
- LocalDeclarationStatementSyntax nativeValuesDeclaration = GenerateNativeValuesDestinationDeclaration(info, context);
-
- return Block(numElementsDeclaration,
- managedValuesDeclaration,
- nativeValuesDeclaration,
- GenerateContentsMarshallingStatement(info, context,
- IdentifierName(numElementsIdentifier),
- StubCodeContext.Stage.UnmarshalCapture,
- StubCodeContext.Stage.Unmarshal));
- }
-
- public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context)
- {
- string numElementsIdentifier = context.GetAdditionalIdentifier(info, "numElements");
- if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))
- {
- yield return GenerateByValueUnmarshalStatement(info, context);
- }
- else
- {
- yield return Block(LocalDeclarationStatement(
- VariableDeclaration(
- PredefinedType(Token(SyntaxKind.IntKeyword)),
- SingletonSeparatedList(
- VariableDeclarator(numElementsIdentifier).WithInitializer(EqualsValueClause(_numElementsExpression))))),
- GeneratedManagedValuesDestinationDeclaration(info, context, numElementsIdentifier),
- GenerateNativeValuesSourceDeclaration(info, context, numElementsIdentifier),
- GenerateContentsMarshallingStatement(info, context,
- IdentifierName(numElementsIdentifier),
- StubCodeContext.Stage.UnmarshalCapture,
- StubCodeContext.Stage.Unmarshal));
- }
-
- foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, context))
- {
- yield return statement;
- }
- }
-
- public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.GetNativeTypeConstructorArguments(info, context);
- }
-
- public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context)
- {
- return _innerMarshaller.UsesNativeIdentifier(info, context);
- }
-
- ///
- /// Rewrite assignment expressions to the native identifier to cast to IntPtr.
- /// This handles the case where the native type of a non-blittable managed type is a pointer,
- /// which are unsupported in generic type parameters.
- ///
- private sealed class PointerNativeTypeAssignmentRewriter : CSharpSyntaxRewriter
- {
- private readonly string _nativeIdentifier;
- private readonly PointerTypeSyntax _nativeType;
-
- public PointerNativeTypeAssignmentRewriter(string nativeIdentifier, PointerTypeSyntax nativeType)
- {
- _nativeIdentifier = nativeIdentifier;
- _nativeType = nativeType;
- }
-
- public override SyntaxNode VisitAssignmentExpression(AssignmentExpressionSyntax node)
- {
- if (node.Left.ToString() == _nativeIdentifier)
- {
- return node.WithRight(
- CastExpression(MarshallerHelpers.SystemIntPtrType, node.Right));
- }
-
- if (node.Right.ToString() == _nativeIdentifier)
- {
- return node.WithRight(CastExpression(_nativeType, node.Right));
- }
-
- return base.VisitAssignmentExpression(node);
- }
-
- public override SyntaxNode? VisitArgument(ArgumentSyntax node)
- {
- if (node.Expression.ToString() == _nativeIdentifier)
- {
- return node.WithExpression(
- CastExpression(_nativeType, node.Expression));
- }
-
- return base.VisitArgument(node);
- }
- }
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs
index 514baa76bb5f9..0fd72c2bd72f1 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs
@@ -13,7 +13,7 @@ namespace Microsoft.Interop
///
/// The base interface for implementing various aspects of the custom native type and collection marshalling specs.
///
- internal interface ICustomTypeMarshallingStrategyBase
+ internal interface ICustomTypeMarshallingStrategy
{
TypeSyntax AsNativeType(TypePositionInfo info);
@@ -30,10 +30,7 @@ internal interface ICustomTypeMarshallingStrategyBase
IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context);
bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context);
- }
- internal interface ICustomTypeMarshallingStrategy : ICustomTypeMarshallingStrategyBase
- {
IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context);
IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context);
IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context);
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs
index a6dd7678f254f..d6bfac0cbe6da 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs
@@ -272,15 +272,18 @@ public bool AnyIncomingEdge(int to)
public static IEnumerable GetDependentElementsOfMarshallingInfo(
MarshallingInfo elementMarshallingInfo)
{
- if (elementMarshallingInfo is NativeLinearCollectionMarshallingInfo_V1 nestedCollection)
+ if (elementMarshallingInfo is NativeLinearCollectionMarshallingInfo nestedCollection)
{
if (nestedCollection.ElementCountInfo is CountElementCountInfo { ElementInfo: TypePositionInfo nestedCountElement })
{
yield return nestedCountElement;
}
- foreach (TypePositionInfo nestedElements in GetDependentElementsOfMarshallingInfo(nestedCollection.ElementMarshallingInfo))
+ foreach (KeyValuePair mode in nestedCollection.Marshallers.Modes)
{
- yield return nestedElements;
+ foreach (TypePositionInfo nestedElements in GetDependentElementsOfMarshallingInfo(mode.Value.CollectionElementMarshallingInfo))
+ {
+ yield return nestedElements;
+ }
}
}
}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs
index 62977de2de3e4..3c3f921711228 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs
@@ -99,14 +99,6 @@ public sealed record UnmanagedBlittableMarshallingInfo(
bool IsStrictlyBlittable
) : MarshallingInfo;
- [Flags]
- public enum CustomTypeMarshallerPinning
- {
- None = 0,
- ManagedType = 0x1,
- NativeType = 0x2
- }
-
public abstract record CountInfo
{
private protected CountInfo() { }
@@ -156,49 +148,11 @@ public sealed record NativeLinearCollectionMarshallingInfo(
Marshallers,
IsPinnableManagedType);
- ///
- /// User-applied System.Runtime.InteropServices.NativeMarshallingAttribute
- ///
- public record NativeMarshallingAttributeInfo_V1(
- ManagedTypeInfo NativeMarshallingType,
- ManagedTypeInfo? NativeValueType,
- CustomTypeMarshallerDirection Direction,
- CustomTypeMarshallerFeatures MarshallingFeatures,
- CustomTypeMarshallerPinning PinningFeatures,
- bool IsStrictlyBlittable,
- ManagedTypeInfo? BufferElementType,
- int? BufferSize) : MarshallingInfo;
-
///
/// The type of the element is a SafeHandle-derived type with no marshalling attributes.
///
public sealed record SafeHandleMarshallingInfo(bool AccessibleDefaultConstructor, bool IsAbstract) : MarshallingInfo;
- ///
- /// User-applied System.Runtime.InteropServices.NativeMarshallingAttribute
- /// with a contiguous collection marshaller
- ///
- public sealed record NativeLinearCollectionMarshallingInfo_V1(
- ManagedTypeInfo NativeMarshallingType,
- ManagedTypeInfo? NativeValueType,
- CustomTypeMarshallerDirection Direction,
- CustomTypeMarshallerFeatures MarshallingFeatures,
- CustomTypeMarshallerPinning PinningFeatures,
- int? BufferSize,
- CountInfo ElementCountInfo,
- ManagedTypeInfo ElementType,
- MarshallingInfo ElementMarshallingInfo) : NativeMarshallingAttributeInfo_V1(
- NativeMarshallingType,
- NativeValueType,
- Direction,
- MarshallingFeatures,
- PinningFeatures,
- IsStrictlyBlittable: false,
- SpecialTypeInfo.Byte,
- BufferSize
- );
-
-
///
/// Marshalling information is lacking because of support not because it is
/// unknown or non-existent. Includes information about element types in case
@@ -591,200 +545,73 @@ private MarshallingInfo CreateNativeMarshallingInfo(
ImmutableHashSet inspectedElements,
ref int maxIndirectionDepthUsed)
{
- if (ManualTypeMarshallingHelper.HasEntryPointMarshallerAttribute(entryPointType))
+ if (!ManualTypeMarshallingHelper.HasEntryPointMarshallerAttribute(entryPointType))
{
- if (!entryPointType.IsStatic)
- {
- _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.MarshallerTypeMustBeStatic), entryPointType.ToDisplayString(), type.ToDisplayString());
- return NoMarshallingInfo.Instance;
- }
+ return NoMarshallingInfo.Instance;
+ }
- ManagedTypeInfo entryPointTypeInfo = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(entryPointType);
- bool isPinnableManagedType = !isMarshalUsingAttribute && ManualTypeMarshallingHelper.FindGetPinnableReference(type) is not null;
+ if (!entryPointType.IsStatic)
+ {
+ _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.MarshallerTypeMustBeStatic), entryPointType.ToDisplayString(), type.ToDisplayString());
+ return NoMarshallingInfo.Instance;
+ }
- bool isLinearCollectionMarshalling = ManualTypeMarshallingHelper.IsLinearCollectionEntryPoint(entryPointType);
- if (isLinearCollectionMarshalling)
- {
- // Update the entry point type with the type arguments based on the managed type
- if (type is IArrayTypeSymbol arrayManagedType)
- {
- if (entryPointType.Arity != 2)
- {
- _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.MarshallerEntryPointTypeMustMatchArity), entryPointType.ToDisplayString(), type.ToDisplayString());
- return NoMarshallingInfo.Instance;
- }
+ ManagedTypeInfo entryPointTypeInfo = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(entryPointType);
+ bool isPinnableManagedType = !isMarshalUsingAttribute && ManualTypeMarshallingHelper.FindGetPinnableReference(type) is not null;
- entryPointType = entryPointType.ConstructedFrom.Construct(
- arrayManagedType.ElementType,
- entryPointType.TypeArguments.Last());
- }
- else if (type is INamedTypeSymbol namedManagedType)
- {
- // Entry point type for linear collection marshalling must have the arity of the managed type + 1
- // for the element unmanaged type placeholder
- if (entryPointType.Arity != namedManagedType.Arity + 1)
- {
- _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.MarshallerEntryPointTypeMustMatchArity), entryPointType.ToDisplayString(), type.ToDisplayString());
- return NoMarshallingInfo.Instance;
- }
-
- entryPointType = entryPointType.ConstructedFrom.Construct(
- namedManagedType.TypeArguments.Add(entryPointType.TypeArguments.Last()).ToArray());
- }
- else
+ bool isLinearCollectionMarshalling = ManualTypeMarshallingHelper.IsLinearCollectionEntryPoint(entryPointType);
+ if (isLinearCollectionMarshalling)
+ {
+ // Update the entry point type with the type arguments based on the managed type
+ if (type is IArrayTypeSymbol arrayManagedType)
+ {
+ if (entryPointType.Arity != 2)
{
_diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.MarshallerEntryPointTypeMustMatchArity), entryPointType.ToDisplayString(), type.ToDisplayString());
return NoMarshallingInfo.Instance;
}
- int maxIndirectionDepthUsedLocal = maxIndirectionDepthUsed;
- Func getMarshallingInfoForElement = (ITypeSymbol elementType) => GetMarshallingInfo(elementType, new Dictionary(), 1, ImmutableHashSet.Empty, ref maxIndirectionDepthUsedLocal);
- if (ManualTypeMarshallingHelper.TryGetLinearCollectionMarshallersFromEntryType(entryPointType, type, _compilation, getMarshallingInfoForElement, out CustomTypeMarshallers? marshallers))
- {
- maxIndirectionDepthUsed = maxIndirectionDepthUsedLocal;
- return new NativeLinearCollectionMarshallingInfo(
- entryPointTypeInfo,
- marshallers.Value,
- isPinnableManagedType,
- parsedCountInfo,
- ManagedTypeInfo.CreateTypeInfoForTypeSymbol(entryPointType.TypeParameters.Last()));
- }
+ entryPointType = entryPointType.ConstructedFrom.Construct(
+ arrayManagedType.ElementType,
+ entryPointType.TypeArguments.Last());
}
- else
+ else if (type is INamedTypeSymbol namedManagedType)
{
- if (ManualTypeMarshallingHelper.TryGetValueMarshallersFromEntryType(entryPointType, type, _compilation, out CustomTypeMarshallers? marshallers))
+ // Entry point type for linear collection marshalling must have the arity of the managed type + 1
+ // for the element unmanaged type placeholder
+ if (entryPointType.Arity != namedManagedType.Arity + 1)
{
- return new NativeMarshallingAttributeInfo(entryPointTypeInfo, marshallers.Value, isPinnableManagedType);
- }
- }
- }
-
- return CreateNativeMarshallingInfo_V1(type, entryPointType, attrData, isMarshalUsingAttribute, indirectionLevel, parsedCountInfo, useSiteAttributes, inspectedElements, ref maxIndirectionDepthUsed);
- }
-
- private MarshallingInfo CreateNativeMarshallingInfo_V1(
- ITypeSymbol type,
- INamedTypeSymbol nativeType,
- AttributeData attrData,
- bool isMarshalUsingAttribute,
- int indirectionLevel,
- CountInfo parsedCountInfo,
- Dictionary useSiteAttributes,
- ImmutableHashSet inspectedElements,
- ref int maxIndirectionDepthUsed)
- {
- if (nativeType.IsUnboundGenericType)
- {
- if (isMarshalUsingAttribute)
- {
- _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.NativeGenericTypeMustBeClosedOrMatchArityMessage), nativeType.ToDisplayString());
- return NoMarshallingInfo.Instance;
- }
- else if (type is INamedTypeSymbol namedType)
- {
- if (namedType.Arity != nativeType.Arity)
- {
- _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.NativeGenericTypeMustBeClosedOrMatchArityMessage), nativeType.ToDisplayString());
+ _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.MarshallerEntryPointTypeMustMatchArity), entryPointType.ToDisplayString(), type.ToDisplayString());
return NoMarshallingInfo.Instance;
}
- else
- {
- nativeType = nativeType.ConstructedFrom.Construct(namedType.TypeArguments.ToArray());
- }
+
+ entryPointType = entryPointType.ConstructedFrom.Construct(
+ namedManagedType.TypeArguments.Add(entryPointType.TypeArguments.Last()).ToArray());
}
else
{
- _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.NativeGenericTypeMustBeClosedOrMatchArityMessage), nativeType.ToDisplayString());
+ _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.MarshallerEntryPointTypeMustMatchArity), entryPointType.ToDisplayString(), type.ToDisplayString());
return NoMarshallingInfo.Instance;
}
- }
-
- var (_, _, customTypeMarshallerData) = ManualTypeMarshallingHelper_V1.GetMarshallerShapeInfo(nativeType);
- if (customTypeMarshallerData is null)
- {
- return NoMarshallingInfo.Instance;
- }
- if (customTypeMarshallerData.Value.Kind == CustomTypeMarshallerKind.LinearCollection)
- {
- INamedTypeSymbol readOnlySpanOfT = _compilation.GetTypeByMetadataName(TypeNames.System_ReadOnlySpan_Metadata)!;
- if (!ManualTypeMarshallingHelper_V1.TryGetElementTypeFromLinearCollectionMarshaller(nativeType, readOnlySpanOfT, out ITypeSymbol elementType))
+ int maxIndirectionDepthUsedLocal = maxIndirectionDepthUsed;
+ Func getMarshallingInfoForElement = (ITypeSymbol elementType) => GetMarshallingInfo(elementType, new Dictionary(), 1, ImmutableHashSet.Empty, ref maxIndirectionDepthUsedLocal);
+ if (ManualTypeMarshallingHelper.TryGetLinearCollectionMarshallersFromEntryType(entryPointType, type, _compilation, getMarshallingInfoForElement, out CustomTypeMarshallers? marshallers))
{
- _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.CollectionNativeTypeMustHaveRequiredShapeMessage), nativeType.ToDisplayString());
- return NoMarshallingInfo.Instance;
+ maxIndirectionDepthUsed = maxIndirectionDepthUsedLocal;
+ return new NativeLinearCollectionMarshallingInfo(
+ entryPointTypeInfo,
+ marshallers.Value,
+ isPinnableManagedType,
+ parsedCountInfo,
+ ManagedTypeInfo.CreateTypeInfoForTypeSymbol(entryPointType.TypeParameters.Last()));
}
-
- CustomTypeMarshallerPinning pinning = ManualTypeMarshallingHelper_V1.GetMarshallerPinningFeatures(nativeType, isMarshalUsingAttribute ? null : type);
- IMethodSymbol? toNativeValueMethod = ManualTypeMarshallingHelper_V1.FindToNativeValueMethod(nativeType);
- ManagedTypeInfo? nativeValueType = toNativeValueMethod is not null ? ManagedTypeInfo.CreateTypeInfoForTypeSymbol(toNativeValueMethod.ReturnType) : null;
- return new NativeLinearCollectionMarshallingInfo_V1(
- ManagedTypeInfo.CreateTypeInfoForTypeSymbol(nativeType),
- nativeValueType,
- customTypeMarshallerData.Value.Direction,
- customTypeMarshallerData.Value.Features,
- pinning,
- customTypeMarshallerData.Value.BufferSize,
- parsedCountInfo,
- ManagedTypeInfo.CreateTypeInfoForTypeSymbol(elementType),
- GetMarshallingInfo(elementType, useSiteAttributes, indirectionLevel + 1, inspectedElements, ref maxIndirectionDepthUsed));
}
-
- return CreateNativeMarshallingInfoForValue_V1(
- type,
- nativeType,
- attrData,
- customTypeMarshallerData.Value,
- allowPinningManagedType: !isMarshalUsingAttribute);
- }
-
- private MarshallingInfo CreateNativeMarshallingInfoForValue_V1(
- ITypeSymbol type,
- INamedTypeSymbol nativeType,
- AttributeData attrData,
- CustomTypeMarshallerData_V1 customTypeMarshallerData,
- bool allowPinningManagedType)
- {
- ManagedTypeInfo? bufferElementTypeInfo = null;
- if (customTypeMarshallerData.Features.HasFlag(CustomTypeMarshallerFeatures.CallerAllocatedBuffer))
+ else if (ManualTypeMarshallingHelper.TryGetValueMarshallersFromEntryType(entryPointType, type, _compilation, out CustomTypeMarshallers? marshallers))
{
- ITypeSymbol? bufferElementType = null;
- INamedTypeSymbol spanOfT = _compilation.GetTypeByMetadataName(TypeNames.System_Span_Metadata)!;
- foreach (IMethodSymbol ctor in nativeType.Constructors)
- {
- if (ManualTypeMarshallingHelper_V1.IsCallerAllocatedSpanConstructor(ctor, type, spanOfT, customTypeMarshallerData.Kind, out bufferElementType))
- break;
- }
-
- // Attribute data may be null when using runtime-provided marshallers by default for certain types (strings, for example)
- // without the user explicitly putting an attribute on the type or parameter. The marshallers should have the correct shape
- // already in thoses cases, so the diagnostic here is not so interesting.
- if (bufferElementType is null)
- {
- if (attrData is not null)
- {
- _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(SR.ValueInCallerAllocatedBufferRequiresSpanConstructorMessage), nativeType.ToDisplayString(), type.ToDisplayString());
- }
-
- return NoMarshallingInfo.Instance;
- }
-
- bufferElementTypeInfo = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(bufferElementType);
+ return new NativeMarshallingAttributeInfo(entryPointTypeInfo, marshallers.Value, isPinnableManagedType);
}
-
- CustomTypeMarshallerPinning pinning = ManualTypeMarshallingHelper_V1.GetMarshallerPinningFeatures(nativeType, allowPinningManagedType ? type : null);
-
- IMethodSymbol? toNativeValueMethod = ManualTypeMarshallingHelper_V1.FindToNativeValueMethod(nativeType);
- ManagedTypeInfo? nativeValueType = toNativeValueMethod is not null ? ManagedTypeInfo.CreateTypeInfoForTypeSymbol(toNativeValueMethod.ReturnType) : null;
-
- return new NativeMarshallingAttributeInfo_V1(
- ManagedTypeInfo.CreateTypeInfoForTypeSymbol(nativeType),
- nativeValueType,
- customTypeMarshallerData.Direction,
- customTypeMarshallerData.Features,
- pinning,
- nativeType.IsStrictlyBlittable(),
- bufferElementTypeInfo,
- customTypeMarshallerData.BufferSize);
+ return NoMarshallingInfo.Instance;
}
private bool TryCreateTypeBasedMarshallingInfo(
@@ -932,33 +759,9 @@ private MarshallingInfo CreateArrayMarshallingInfo(
ManagedTypeInfo.CreateTypeInfoForTypeSymbol(arrayMarshaller.TypeParameters.Last()));
}
}
- else
- {
- arrayMarshaller = arrayMarshaller.Construct(typeArgumentToInsert);
- }
- var (_, _, customTypeMarshallerData) = ManualTypeMarshallingHelper_V1.GetMarshallerShapeInfo(arrayMarshaller);
- Debug.Assert(customTypeMarshallerData is not null);
-
- ITypeSymbol? nativeValueType = ManualTypeMarshallingHelper_V1.FindToNativeValueMethod(arrayMarshaller)?.ReturnType;
-
- INamedTypeSymbol readOnlySpanOfT = _compilation.GetTypeByMetadataName(TypeNames.System_ReadOnlySpan_Metadata)!;
- if (!ManualTypeMarshallingHelper_V1.TryGetElementTypeFromLinearCollectionMarshaller(arrayMarshaller, readOnlySpanOfT, out elementType))
- {
- Debug.Fail("Runtime-provided array marshallers should have a valid shape");
- return NoMarshallingInfo.Instance;
- }
-
- return new NativeLinearCollectionMarshallingInfo_V1(
- NativeMarshallingType: ManagedTypeInfo.CreateTypeInfoForTypeSymbol(arrayMarshaller),
- NativeValueType: nativeValueType is not null ? ManagedTypeInfo.CreateTypeInfoForTypeSymbol(nativeValueType) : null,
- Direction: customTypeMarshallerData.Value.Direction,
- MarshallingFeatures: customTypeMarshallerData.Value.Features,
- PinningFeatures: CustomTypeMarshallerPinning.NativeType,
- customTypeMarshallerData.Value.BufferSize,
- ElementCountInfo: countInfo,
- ElementType: ManagedTypeInfo.CreateTypeInfoForTypeSymbol(elementType),
- ElementMarshallingInfo: elementMarshallingInfo);
+ Debug.WriteLine("Default marshallers for arrays should be a valid shape.");
+ return NoMarshallingInfo.Instance;
}
private MarshallingInfo CreateStringMarshallingInfo(
@@ -999,15 +802,7 @@ private MarshallingInfo CreateStringMarshallingInfo(
}
}
- var (_, _, customTypeMarshallerData) = ManualTypeMarshallingHelper_V1.GetMarshallerShapeInfo(stringMarshaller);
- Debug.Assert(customTypeMarshallerData is not null);
-
- return CreateNativeMarshallingInfoForValue_V1(
- type,
- stringMarshaller,
- null,
- customTypeMarshallerData.Value,
- allowPinningManagedType: marshallerName is TypeNames.Utf16StringMarshaller);
+ return new MissingSupportMarshallingInfo();
}
private MarshallingInfo GetBlittableMarshallingInfo(ITypeSymbol type)
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj
index 02621feb27336..d2dd79ffb36dc 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj
@@ -9,16 +9,8 @@
-
-
-
-
-
+
+
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs
index b7670ed2e49f6..7fab9de7c407a 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs
@@ -81,10 +81,10 @@ public enum Stage
public Stage CurrentStage { get; init; } = Stage.Invalid;
///
- /// CustomTypeMarshallerDirection.In means method import like [LibraryImport].
- /// CustomTypeMarshallerDirection.Out means method export like in [UnmanagedCallersOnly] or in [JSExport]
+ /// CustomTypeMarshallingDirection.In means method import like [LibraryImport].
+ /// CustomTypeMarshallingDirection.Out means method export like in [UnmanagedCallersOnly] or in [JSExport]
///
- public CustomTypeMarshallerDirection Direction { get; init; } = CustomTypeMarshallerDirection.In;
+ public CustomTypeMarshallingDirection Direction { get; init; } = CustomTypeMarshallingDirection.In;
///
/// Gets the currently targeted framework and version for stub code generation.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
index 6edf393c32e81..7059257114698 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
@@ -13,9 +13,6 @@ public static class TypeNames
public const string MarshalUsingAttribute = "System.Runtime.InteropServices.Marshalling.MarshalUsingAttribute";
- public const string CustomTypeMarshallerAttribute = "System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerAttribute";
- public const string CustomTypeMarshallerAttributeGenericPlaceholder = "System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerAttribute.GenericPlaceholder";
-
public const string CustomMarshallerAttribute = "System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute";
public const string CustomMarshallerAttributeGenericPlaceholder = CustomMarshallerAttribute + ".GenericPlaceholder";
public const string ContiguousCollectionMarshallerAttribute = "System.Runtime.InteropServices.Marshalling.ContiguousCollectionMarshallerAttribute";
diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs
index 940490d75dc28..f9e3fcdfb7390 100644
--- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs
+++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs
@@ -2200,72 +2200,6 @@ public ref struct ManagedToUnmanagedIn
public void Free() { throw null; }
}
}
-
- [System.AttributeUsageAttribute(System.AttributeTargets.Struct | System.AttributeTargets.Class)]
- public sealed partial class ContiguousCollectionMarshallerAttribute : System.Attribute
- {
- }
-
- [System.AttributeUsageAttribute(System.AttributeTargets.Struct | System.AttributeTargets.Class, AllowMultiple = true)]
- public sealed partial class CustomMarshallerAttribute : System.Attribute
- {
- public CustomMarshallerAttribute(System.Type managedType, System.Runtime.InteropServices.Marshalling.MarshalMode marshalMode, System.Type marshallerType) { }
- public System.Type ManagedType { get { throw null; } }
- public System.Runtime.InteropServices.Marshalling.MarshalMode MarshalMode { get { throw null; } }
- public System.Type MarshallerType { get { throw null; } }
- public struct GenericPlaceholder
- {
- }
- }
-
- [System.AttributeUsageAttribute(System.AttributeTargets.Struct)]
- public sealed partial class CustomTypeMarshallerAttribute : System.Attribute
- {
- public CustomTypeMarshallerAttribute(System.Type managedType, System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerKind marshallerKind = System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerKind.Value) { }
- public System.Type ManagedType { get { throw null; } }
- public System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerKind MarshallerKind { get { throw null; } }
- public int BufferSize { get { throw null; } set { } }
- public System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerDirection Direction { get { throw null; } set { } }
- public System.Runtime.InteropServices.Marshalling.CustomTypeMarshallerFeatures Features { get { throw null; } set { } }
- public struct GenericPlaceholder
- {
- }
- }
- [System.FlagsAttribute]
- public enum CustomTypeMarshallerDirection
- {
- [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
- None = 0,
- In = 0x1,
- Out = 0x2,
- Ref = In | Out,
- }
- [System.FlagsAttribute]
- public enum CustomTypeMarshallerFeatures
- {
- None = 0,
- UnmanagedResources = 0x1,
- CallerAllocatedBuffer = 0x2,
- TwoStageMarshalling = 0x4
- }
- public enum CustomTypeMarshallerKind
- {
- Value,
- LinearCollection
- }
- public enum MarshalMode
- {
- Default = 0,
- ManagedToUnmanagedIn = 1,
- ManagedToUnmanagedRef = 2,
- ManagedToUnmanagedOut = 3,
- UnmanagedToManagedIn = 4,
- UnmanagedToManagedRef = 5,
- UnmanagedToManagedOut = 6,
- ElementIn = 7,
- ElementRef = 8,
- ElementOut = 9
- }
[System.AttributeUsageAttribute(System.AttributeTargets.Parameter | System.AttributeTargets.ReturnValue, AllowMultiple = true)]
public sealed partial class MarshalUsingAttribute : System.Attribute
{
@@ -2277,12 +2211,6 @@ public MarshalUsingAttribute(System.Type nativeType) { }
public int ElementIndirectionDepth { get { throw null; } set { } }
public const string ReturnsCountValue = "return-value";
}
- [System.AttributeUsageAttribute(System.AttributeTargets.Struct | System.AttributeTargets.Class | System.AttributeTargets.Enum | System.AttributeTargets.Delegate)]
- public sealed partial class NativeMarshallingAttribute : System.Attribute
- {
- public NativeMarshallingAttribute(System.Type nativeType) { }
- public System.Type NativeType { get { throw null; } }
- }
[System.CLSCompliant(false)]
[System.Runtime.InteropServices.Marshalling.CustomMarshallerAttribute(typeof(CustomMarshallerAttribute.GenericPlaceholder*[]),
System.Runtime.InteropServices.Marshalling.MarshalMode.Default,
diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/SpanMarshallers.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/SpanMarshallers.cs
deleted file mode 100644
index 3e9af57776a96..0000000000000
--- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/SpanMarshallers.cs
+++ /dev/null
@@ -1,270 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-
-namespace System.Runtime.InteropServices.Marshalling
-{
- // Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack.
- // Number kept small to ensure that P/Invokes with a lot of array parameters doesn't
- // blow the stack since this is a new optimization in the code-generated interop.
- [CustomTypeMarshaller(typeof(ReadOnlySpan<>), CustomTypeMarshallerKind.LinearCollection, Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling, BufferSize = 0x200)]
- public unsafe ref struct ReadOnlySpanMarshaller
- {
- private ReadOnlySpan _managedSpan;
- private readonly int _sizeOfNativeElement;
- private IntPtr _allocatedMemory;
-
- public ReadOnlySpanMarshaller(int sizeOfNativeElement)
- : this()
- {
- _sizeOfNativeElement = sizeOfNativeElement;
- }
-
- public ReadOnlySpanMarshaller(ReadOnlySpan managed, int sizeOfNativeElement)
- :this(managed, Span.Empty, sizeOfNativeElement)
- {
- }
-
- public ReadOnlySpanMarshaller(ReadOnlySpan managed, Span stackSpace, int sizeOfNativeElement)
- {
- _allocatedMemory = default;
- _sizeOfNativeElement = sizeOfNativeElement;
- if (managed.Length == 0)
- {
- _managedSpan = default;
- NativeValueStorage = default;
- return;
- }
- _managedSpan = managed;
- int spaceToAllocate = managed.Length * sizeOfNativeElement;
- if (spaceToAllocate <= stackSpace.Length)
- {
- NativeValueStorage = stackSpace[0..spaceToAllocate];
- }
- else
- {
- _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate);
- NativeValueStorage = new Span((void*)_allocatedMemory, spaceToAllocate);
- }
- }
-
- public ReadOnlySpan GetManagedValuesSource() => _managedSpan;
-
- public Span GetNativeValuesDestination() => NativeValueStorage;
-
- private Span NativeValueStorage { get; }
-
- public ref byte GetPinnableReference() => ref MemoryMarshal.GetReference(NativeValueStorage);
-
- public byte* ToNativeValue() => (byte*)Unsafe.AsPointer(ref GetPinnableReference());
-
- public void FreeNative()
- {
- Marshal.FreeCoTaskMem(_allocatedMemory);
- }
- }
-
- [CustomTypeMarshaller(typeof(Span<>), CustomTypeMarshallerKind.LinearCollection, Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling, BufferSize = 0x200)]
- public unsafe ref struct SpanMarshaller
- {
- private Span _managedSpan;
- private readonly int _sizeOfNativeElement;
- private IntPtr _allocatedMemory;
-
- public SpanMarshaller(int sizeOfNativeElement)
- : this()
- {
- _sizeOfNativeElement = sizeOfNativeElement;
- }
-
- public SpanMarshaller(Span managed, int sizeOfNativeElement)
- :this(managed, Span.Empty, sizeOfNativeElement)
- {
- }
-
- public SpanMarshaller(Span managed, Span stackSpace, int sizeOfNativeElement)
- {
- _allocatedMemory = default;
- _sizeOfNativeElement = sizeOfNativeElement;
- if (managed.Length == 0)
- {
- _managedSpan = default;
- NativeValueStorage = default;
- return;
- }
- _managedSpan = managed;
- int spaceToAllocate = managed.Length * sizeOfNativeElement;
- if (spaceToAllocate <= stackSpace.Length)
- {
- NativeValueStorage = stackSpace[0..spaceToAllocate];
- }
- else
- {
- _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate);
- NativeValueStorage = new Span((void*)_allocatedMemory, spaceToAllocate);
- }
- }
-
- private Span NativeValueStorage { get; set; }
-
- public ReadOnlySpan GetManagedValuesSource() => _managedSpan;
- public Span GetManagedValuesDestination(int length) => _managedSpan = new T[length];
- public Span GetNativeValuesDestination() => NativeValueStorage;
- public ReadOnlySpan GetNativeValuesSource(int length) => NativeValueStorage = new Span((void*)_allocatedMemory, length * _sizeOfNativeElement);
- public ref byte GetPinnableReference() => ref NativeValueStorage.GetPinnableReference();
- public byte* ToNativeValue() => (byte*)Unsafe.AsPointer(ref GetPinnableReference());
- public void FromNativeValue(byte* value) => _allocatedMemory = (IntPtr)value;
-
- public Span ToManaged()
- {
- return _managedSpan;
- }
-
- public void FreeNative()
- {
- Marshal.FreeCoTaskMem(_allocatedMemory);
- }
- }
-
- [CustomTypeMarshaller(typeof(Span<>), CustomTypeMarshallerKind.LinearCollection, Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling, BufferSize = 0x200)]
- public unsafe ref struct NeverNullSpanMarshaller
- {
- private SpanMarshaller _inner;
-
- public NeverNullSpanMarshaller(int sizeOfNativeElement)
- : this()
- {
- _inner = new SpanMarshaller(sizeOfNativeElement);
- }
-
- public NeverNullSpanMarshaller(Span managed, int sizeOfNativeElement)
- {
- _inner = new SpanMarshaller(managed, sizeOfNativeElement);
- }
-
- public NeverNullSpanMarshaller(Span managed, Span stackSpace, int sizeOfNativeElement)
- {
- _inner = new SpanMarshaller(managed, stackSpace, sizeOfNativeElement);
- }
-
-
- public ReadOnlySpan GetManagedValuesSource() => _inner.GetManagedValuesSource();
- public Span GetManagedValuesDestination(int length) => _inner.GetManagedValuesDestination(length);
- public Span GetNativeValuesDestination() => _inner.GetNativeValuesDestination();
- public ReadOnlySpan GetNativeValuesSource(int length) => _inner.GetNativeValuesSource(length);
- public ref byte GetPinnableReference() => ref _inner.GetPinnableReference();
- public byte* ToNativeValue() => _inner.GetManagedValuesSource().Length == 0 ? (byte*)0xa5a5a5a5 : (byte*)Unsafe.AsPointer(ref GetPinnableReference());
- public void FromNativeValue(byte* value) => _inner.FromNativeValue(value);
-
- public Span ToManaged() => _inner.ToManaged();
-
- public void FreeNative()
- {
- _inner.FreeNative();
- }
- }
-
- [CustomTypeMarshaller(typeof(ReadOnlySpan<>), CustomTypeMarshallerKind.LinearCollection, Direction = CustomTypeMarshallerDirection.In, Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling, BufferSize = 0x200)]
- public unsafe ref struct NeverNullReadOnlySpanMarshaller
- {
- private ReadOnlySpanMarshaller _inner;
-
- public NeverNullReadOnlySpanMarshaller(int sizeOfNativeElement)
- : this()
- {
- _inner = new ReadOnlySpanMarshaller(sizeOfNativeElement);
- }
-
- public NeverNullReadOnlySpanMarshaller(ReadOnlySpan managed, int sizeOfNativeElement)
- {
- _inner = new ReadOnlySpanMarshaller