diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs index 19d0315a0a0b0..33b08510d4fe8 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs @@ -16,7 +16,7 @@ internal sealed class JSExportCodeGenerator : JSCodeGenerator { private readonly BoundGenerators _marshallers; - private readonly StubCodeContext _context; + private readonly StubIdentifierContext _context; private readonly JSExportData _jsExportData; private readonly JSSignatureContext _signatureContext; @@ -29,21 +29,24 @@ public JSExportCodeGenerator( { _signatureContext = signatureContext; _jsExportData = attributeData; - _context = new NativeToManagedStubCodeContext(ReturnIdentifier, ReturnIdentifier) - { - CodeEmitOptions = new(SkipInit: true) - }; - _marshallers = BoundGenerators.Create(argTypes, generatorResolver, _context, new EmptyJSGenerator(), out var bindingFailures); + _marshallers = BoundGenerators.Create(argTypes, generatorResolver, StubCodeContext.DefaultNativeToManagedStub, new EmptyJSGenerator(), out var bindingFailures); diagnosticsBag.ReportGeneratorDiagnostics(bindingFailures); - if (_marshallers.ManagedReturnMarshaller.UsesNativeIdentifier(_context)) + if (_marshallers.ManagedReturnMarshaller.UsesNativeIdentifier) { // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. - _context = new NativeToManagedStubCodeContext(ReturnIdentifier, ReturnNativeIdentifier) + _context = new DefaultIdentifierContext(ReturnIdentifier, ReturnNativeIdentifier, MarshalDirection.UnmanagedToManaged) + { + CodeEmitOptions = new(SkipInit: true), + }; + } + else + { + _context = new DefaultIdentifierContext(ReturnIdentifier, ReturnIdentifier, MarshalDirection.UnmanagedToManaged) { - CodeEmitOptions = new(SkipInit: true) + CodeEmitOptions = new(SkipInit: true), }; } @@ -53,7 +56,7 @@ public JSExportCodeGenerator( IBoundMarshallingGenerator spanArg = _marshallers.SignatureMarshallers.FirstOrDefault(m => m.TypeInfo.MarshallingAttributeInfo is JSMarshallingInfo(_, JSSpanTypeInfo)); if (spanArg != default) { - diagnosticsBag.ReportGeneratorDiagnostic(new GeneratorDiagnostic.NotSupported(spanArg.TypeInfo, _context) + diagnosticsBag.ReportGeneratorDiagnostic(new GeneratorDiagnostic.NotSupported(spanArg.TypeInfo) { NotSupportedDetails = SR.SpanAndTaskNotSupported }); @@ -160,9 +163,9 @@ public StatementSyntax GenerateJSExportRegistration() private ArgumentSyntax CreateSignaturesSyntax() { - IEnumerable types = _marshallers.ManagedReturnMarshaller is IJSMarshallingGenerator jsGen ? jsGen.GenerateBind(_context) : []; + IEnumerable types = _marshallers.ManagedReturnMarshaller is IJSMarshallingGenerator jsGen ? jsGen.GenerateBind() : []; types = types - .Concat(_marshallers.NativeParameterMarshallers.OfType().SelectMany(p => p.GenerateBind(_context))); + .Concat(_marshallers.NativeParameterMarshallers.OfType().SelectMany(p => p.GenerateBind())); return Argument(ArrayCreationExpression(ArrayType(IdentifierName(Constants.JSMarshalerTypeGlobal)) .WithRankSpecifiers(SingletonList(ArrayRankSpecifier(SingletonSeparatedList(OmittedArraySizeExpression()))))) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratorFactory.cs index dd9cc9eb56ec6..f5f61c413bc11 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratorFactory.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSGeneratorFactory.cs @@ -19,7 +19,7 @@ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) if (info.IsByRef || info.ByValueContentsMarshalKind != ByValueContentsMarshalKind.Default) { // out of scope for Net7.0 - return ResolvedGenerator.NotSupported(info, new(info, context) + return ResolvedGenerator.NotSupported(info, context, new(info) { NotSupportedDetails = SR.InOutRefNotSupported }); @@ -28,7 +28,7 @@ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) ResolvedGenerator fail(string failReason) { - return ResolvedGenerator.NotSupported(info, new(info, context) + return ResolvedGenerator.NotSupported(info, context, new(info) { NotSupportedDetails = failReason }); @@ -39,16 +39,16 @@ ResolvedGenerator fail(string failReason) { // invalid case { TypeInfo: JSInvalidTypeInfo }: - return ResolvedGenerator.NotSupported(info, new(info, context)); + return ResolvedGenerator.NotSupported(info, context, new(info)); // void case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.DiscardNoWait }: - return ResolvedGenerator.Resolved(new VoidGenerator(info, MarshalerType.DiscardNoWait)); + return ResolvedGenerator.Resolved(new VoidGenerator(info, context, MarshalerType.DiscardNoWait)); case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.Discard }: case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.Void }: case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.None }: case { TypeInfo: JSSimpleTypeInfo(KnownManagedType.Void), JSType: JSTypeFlags.Missing }: - return ResolvedGenerator.Resolved(new VoidGenerator(info, jsMarshalingInfo.JSType == JSTypeFlags.Void ? MarshalerType.Void : MarshalerType.Discard)); + return ResolvedGenerator.Resolved(new VoidGenerator(info, context, jsMarshalingInfo.JSType == JSTypeFlags.Void ? MarshalerType.Void : MarshalerType.Discard)); // discard no void case { JSType: JSTypeFlags.Discard }: @@ -60,73 +60,73 @@ ResolvedGenerator fail(string failReason) // primitive case { TypeInfo: JSSimpleTypeInfo simple }: - return Create(info, isToJs, simple.KnownType, Array.Empty(), jsMarshalingInfo.JSType, Array.Empty(), fail); + return Create(info, context, isToJs, simple.KnownType, [], jsMarshalingInfo.JSType, Array.Empty(), fail); // nullable case { TypeInfo: JSNullableTypeInfo nullable }: - return Create(info, isToJs, nullable.KnownType, new[] { nullable.ResultTypeInfo.KnownType }, jsMarshalingInfo.JSType, null, fail); + return Create(info, context, isToJs, nullable.KnownType, [nullable.ResultTypeInfo.KnownType], jsMarshalingInfo.JSType, null, fail); // array case { TypeInfo: JSArrayTypeInfo array }: - return Create(info, isToJs, array.KnownType, new[] { array.ElementTypeInfo.KnownType }, jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail); + return Create(info, context, isToJs, array.KnownType, [array.ElementTypeInfo.KnownType], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail); // array segment case { TypeInfo: JSArraySegmentTypeInfo segment }: - return Create(info, isToJs, segment.KnownType, new[] { segment.ElementTypeInfo.KnownType }, jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail); + return Create(info, context, isToJs, segment.KnownType, [segment.ElementTypeInfo.KnownType], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail); // span case { TypeInfo: JSSpanTypeInfo span }: - return Create(info, isToJs, span.KnownType, new[] { span.ElementTypeInfo.KnownType }, jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail); + return Create(info, context, isToJs, span.KnownType, [span.ElementTypeInfo.KnownType], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail); // task case { TypeInfo: JSTaskTypeInfo(JSSimpleTypeInfo(KnownManagedType.Void)) task }: - return Create(info, isToJs, task.KnownType, Array.Empty(), jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail); + return Create(info, context, isToJs, task.KnownType, [], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail); case { TypeInfo: JSTaskTypeInfo task }: - return Create(info, isToJs, task.KnownType, new[] { task.ResultTypeInfo.KnownType }, jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail); + return Create(info, context, isToJs, task.KnownType, [task.ResultTypeInfo.KnownType], jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail); // action + function case { TypeInfo: JSFunctionTypeInfo function }: - return Create(info, isToJs, function.KnownType, function.ArgsTypeInfo.Select(a => a.KnownType).ToArray(), jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail); + return Create(info, context, isToJs, function.KnownType, function.ArgsTypeInfo.Select(a => a.KnownType).ToArray(), jsMarshalingInfo.JSType, jsMarshalingInfo.JSTypeArguments, fail); default: - return ResolvedGenerator.NotSupported(info, new(info, context)); + return ResolvedGenerator.NotSupported(info, context, new(info)); } } - internal static ResolvedGenerator Create(TypePositionInfo info, bool isToJs, KnownManagedType marshaledType, KnownManagedType[] argumentTypes, JSTypeFlags jsType, JSTypeFlags[] jsTypeArguments, Func failWithReason) + internal static ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context, bool isToJs, KnownManagedType marshaledType, KnownManagedType[] argumentTypes, JSTypeFlags jsType, JSTypeFlags[] jsTypeArguments, Func failWithReason) { switch (marshaledType) { // primitive - case KnownManagedType.Boolean when jsType == JSTypeFlags.Boolean: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Boolean)); - case KnownManagedType.Byte when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Byte)); - case KnownManagedType.Char when jsType == JSTypeFlags.String: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Char)); - case KnownManagedType.Int16 when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Int16)); - case KnownManagedType.Int32 when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Int32)); - case KnownManagedType.Int64 when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Int52)); - case KnownManagedType.Int64 when jsType == JSTypeFlags.BigInt: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.BigInt64)); - case KnownManagedType.Single when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Single)); - case KnownManagedType.Double when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Double)); - case KnownManagedType.IntPtr when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.IntPtr)); - case KnownManagedType.DateTime when jsType == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.DateTime)); - case KnownManagedType.DateTimeOffset when jsType == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.DateTimeOffset)); - case KnownManagedType.Exception when jsType == JSTypeFlags.Error: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Exception)); - case KnownManagedType.JSObject when jsType == JSTypeFlags.Object: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.JSObject)); - case KnownManagedType.String when jsType == JSTypeFlags.String: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.String)); - case KnownManagedType.Object when jsType == JSTypeFlags.Any: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Object)); + case KnownManagedType.Boolean when jsType == JSTypeFlags.Boolean: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Boolean)); + case KnownManagedType.Byte when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Byte)); + case KnownManagedType.Char when jsType == JSTypeFlags.String: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Char)); + case KnownManagedType.Int16 when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int16)); + case KnownManagedType.Int32 when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int32)); + case KnownManagedType.Int64 when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int52)); + case KnownManagedType.Int64 when jsType == JSTypeFlags.BigInt: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.BigInt64)); + case KnownManagedType.Single when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Single)); + case KnownManagedType.Double when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Double)); + case KnownManagedType.IntPtr when jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.IntPtr)); + case KnownManagedType.DateTime when jsType == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.DateTime)); + case KnownManagedType.DateTimeOffset when jsType == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.DateTimeOffset)); + case KnownManagedType.Exception when jsType == JSTypeFlags.Error: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Exception)); + case KnownManagedType.JSObject when jsType == JSTypeFlags.Object: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.JSObject)); + case KnownManagedType.String when jsType == JSTypeFlags.String: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.String)); + case KnownManagedType.Object when jsType == JSTypeFlags.Any: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Object)); // primitive missing - case KnownManagedType.Boolean when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Boolean)); - case KnownManagedType.Byte when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Byte)); - case KnownManagedType.Char when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Char)); - case KnownManagedType.Int16 when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Int16)); - case KnownManagedType.Int32 when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Int32)); - case KnownManagedType.Single when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Single)); - case KnownManagedType.Double when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Double)); - case KnownManagedType.IntPtr when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.IntPtr)); - case KnownManagedType.Exception when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.Exception)); - case KnownManagedType.JSObject when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.JSObject)); - case KnownManagedType.String when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, MarshalerType.String)); + case KnownManagedType.Boolean when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Boolean)); + case KnownManagedType.Byte when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Byte)); + case KnownManagedType.Char when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Char)); + case KnownManagedType.Int16 when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int16)); + case KnownManagedType.Int32 when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Int32)); + case KnownManagedType.Single when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Single)); + case KnownManagedType.Double when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Double)); + case KnownManagedType.IntPtr when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.IntPtr)); + case KnownManagedType.Exception when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.Exception)); + case KnownManagedType.JSObject when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.JSObject)); + case KnownManagedType.String when jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new PrimitiveJSGenerator(info, context, MarshalerType.String)); // primitive forced case KnownManagedType.Int64 when jsType == JSTypeFlags.Missing: @@ -136,28 +136,28 @@ internal static ResolvedGenerator Create(TypePositionInfo info, bool isToJs, Kno return failWithReason(SR.Format(SR.UseJSMarshalAsAttribute, info.ManagedType.FullTypeName)); // nullable - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Boolean && jsType == JSTypeFlags.Boolean: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Boolean)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Byte)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Char && jsType == JSTypeFlags.String: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Byte)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int16 && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Int16)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Int32)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int64 && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Int52)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int64 && jsType == JSTypeFlags.BigInt: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.BigInt64)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Double)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Single && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Single)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.IntPtr && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.IntPtr)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.DateTime && jsType == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.DateTime)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.DateTimeOffset && jsType == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.DateTimeOffset)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Boolean && jsType == JSTypeFlags.Boolean: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Boolean)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Byte)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Char && jsType == JSTypeFlags.String: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Byte)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int16 && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Int16)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Int32)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int64 && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Int52)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int64 && jsType == JSTypeFlags.BigInt: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.BigInt64)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Double)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Single && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Single)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.IntPtr && jsType == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.IntPtr)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.DateTime && jsType == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.DateTime)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.DateTimeOffset && jsType == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.DateTimeOffset)); // nullable missing - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Boolean && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Boolean)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Byte)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Char && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Byte)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int16 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Int16)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Int32)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Single && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Single)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.Double)); - case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.IntPtr && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, MarshalerType.IntPtr)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Boolean && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Boolean)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Byte)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Char && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Byte)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int16 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Int16)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Int32)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Single && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Single)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.Double)); + case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.IntPtr && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new NullableJSGenerator(info, context, MarshalerType.IntPtr)); // nullable forced case KnownManagedType.Nullable when argumentTypes[0] == KnownManagedType.Int64 && jsType == JSTypeFlags.Missing: @@ -169,37 +169,37 @@ internal static ResolvedGenerator Create(TypePositionInfo info, bool isToJs, Kno return failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)); // task - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes.Length == 0 && jsTypeArguments[0] == JSTypeFlags.Void: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Void)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Byte && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Byte)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Boolean && jsTypeArguments[0] == JSTypeFlags.Boolean: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Boolean)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Char && jsTypeArguments[0] == JSTypeFlags.String: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Char)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int16 && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Int16)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int32 && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Int32)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int64 && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Int52)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int64 && jsTypeArguments[0] == JSTypeFlags.BigInt: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.BigInt64)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.IntPtr && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.IntPtr)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Double && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Double)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Single && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Single)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.JSObject && jsTypeArguments[0] == JSTypeFlags.Object: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.JSObject)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.String && jsTypeArguments[0] == JSTypeFlags.String: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.String)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Exception && jsTypeArguments[0] == JSTypeFlags.Error: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Exception)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.DateTime && jsTypeArguments[0] == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.DateTime)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.DateTimeOffset && jsTypeArguments[0] == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.DateTimeOffset)); - case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Object && jsTypeArguments[0] == JSTypeFlags.Any: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Object)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes.Length == 0 && jsTypeArguments[0] == JSTypeFlags.Void: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Void)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Byte && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Byte)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Boolean && jsTypeArguments[0] == JSTypeFlags.Boolean: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Boolean)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Char && jsTypeArguments[0] == JSTypeFlags.String: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Char)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int16 && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Int16)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int32 && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Int32)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int64 && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Int52)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int64 && jsTypeArguments[0] == JSTypeFlags.BigInt: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.BigInt64)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.IntPtr && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.IntPtr)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Double && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Double)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Single && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Single)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.JSObject && jsTypeArguments[0] == JSTypeFlags.Object: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.JSObject)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.String && jsTypeArguments[0] == JSTypeFlags.String: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.String)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Exception && jsTypeArguments[0] == JSTypeFlags.Error: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Exception)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.DateTime && jsTypeArguments[0] == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.DateTime)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.DateTimeOffset && jsTypeArguments[0] == JSTypeFlags.Date: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.DateTimeOffset)); + case KnownManagedType.Task when jsType == JSTypeFlags.Promise && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Object && jsTypeArguments[0] == JSTypeFlags.Any: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Object)); // task missing - case KnownManagedType.Task when jsType == JSTypeFlags.Missing && argumentTypes.Length == 0: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Void)); - case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Boolean && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Boolean)); - case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Byte)); - case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Char && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Char)); - case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Int16 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Int16)); - case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Int32)); - case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Single && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Single)); - case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Double)); - case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.IntPtr && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.IntPtr)); - case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.JSObject && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.JSObject)); - case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.String && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.String)); - case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Exception && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, MarshalerType.Exception)); + case KnownManagedType.Task when jsType == JSTypeFlags.Missing && argumentTypes.Length == 0: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Void)); + case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Boolean && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Boolean)); + case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Byte)); + case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Char && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Char)); + case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Int16 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Int16)); + case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Int32)); + case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Single && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Single)); + case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Double)); + case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.IntPtr && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.IntPtr)); + case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.JSObject && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.JSObject)); + case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.String && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.String)); + case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Exception && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new TaskJSGenerator(info, context, MarshalerType.Exception)); // task forced case KnownManagedType.Task when argumentTypes[0] == KnownManagedType.Int64 && jsType == JSTypeFlags.Missing: @@ -212,19 +212,19 @@ internal static ResolvedGenerator Create(TypePositionInfo info, bool isToJs, Kno return failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)); // array - case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Byte && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, MarshalerType.Byte)); - case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.String && jsTypeArguments[0] == JSTypeFlags.String: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, MarshalerType.String)); - case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Double && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, MarshalerType.Double)); - case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int32 && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, MarshalerType.Int32)); - case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.JSObject && jsTypeArguments[0] == JSTypeFlags.Object: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, MarshalerType.JSObject)); - case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Object && jsTypeArguments[0] == JSTypeFlags.Any: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, MarshalerType.Object)); + case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Byte && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Byte)); + case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.String && jsTypeArguments[0] == JSTypeFlags.String: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.String)); + case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Double && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Double)); + case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Int32 && jsTypeArguments[0] == JSTypeFlags.Number: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Int32)); + case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.JSObject && jsTypeArguments[0] == JSTypeFlags.Object: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.JSObject)); + case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1 && argumentTypes[0] == KnownManagedType.Object && jsTypeArguments[0] == JSTypeFlags.Any: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Object)); // array missing - case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, MarshalerType.Byte)); - case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.String && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, MarshalerType.String)); - case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, MarshalerType.Double)); - case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, MarshalerType.Int32)); - case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.JSObject && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, MarshalerType.JSObject)); + case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.Byte && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Byte)); + case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.String && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.String)); + case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.Double && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Double)); + case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.Int32 && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.Int32)); + case KnownManagedType.Array when argumentTypes[0] == KnownManagedType.JSObject && jsType == JSTypeFlags.Missing: return ResolvedGenerator.Resolved(new ArrayJSGenerator(info, context, MarshalerType.JSObject)); case KnownManagedType.Array when jsType == JSTypeFlags.Array && jsTypeArguments.Length == 1: return failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)); @@ -235,9 +235,9 @@ internal static ResolvedGenerator Create(TypePositionInfo info, bool isToJs, Kno // span view case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView && jsTypeArguments.Length != 0: return failWithReason(null); - case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Byte: return ResolvedGenerator.Resolved(new SpanJSGenerator(info, MarshalerType.Byte)); - case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Int32: return ResolvedGenerator.Resolved(new SpanJSGenerator(info, MarshalerType.Int32)); - case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Double: return ResolvedGenerator.Resolved(new SpanJSGenerator(info, MarshalerType.Double)); + case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Byte: return ResolvedGenerator.Resolved(new SpanJSGenerator(info, context, MarshalerType.Byte)); + case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Int32: return ResolvedGenerator.Resolved(new SpanJSGenerator(info, context, MarshalerType.Int32)); + case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Double: return ResolvedGenerator.Resolved(new SpanJSGenerator(info, context, MarshalerType.Double)); case KnownManagedType.Span when jsType == JSTypeFlags.MemoryView: return failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)); @@ -251,9 +251,9 @@ internal static ResolvedGenerator Create(TypePositionInfo info, bool isToJs, Kno // segment view case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView && jsTypeArguments.Length != 0: return failWithReason(null); - case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Byte: return ResolvedGenerator.Resolved(new ArraySegmentJSGenerator(info, MarshalerType.Byte)); - case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Int32: return ResolvedGenerator.Resolved(new ArraySegmentJSGenerator(info, MarshalerType.Int32)); - case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Double: return ResolvedGenerator.Resolved(new ArraySegmentJSGenerator(info, MarshalerType.Double)); + case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Byte: return ResolvedGenerator.Resolved(new ArraySegmentJSGenerator(info, context, MarshalerType.Byte)); + case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Int32: return ResolvedGenerator.Resolved(new ArraySegmentJSGenerator(info, context, MarshalerType.Int32)); + case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView && argumentTypes[0] == KnownManagedType.Double: return ResolvedGenerator.Resolved(new ArraySegmentJSGenerator(info, context, MarshalerType.Double)); case KnownManagedType.ArraySegment when jsType == JSTypeFlags.MemoryView: return failWithReason(SR.Format(SR.TypeNotSupportedName, info.ManagedType.FullTypeName)); @@ -281,7 +281,7 @@ internal static ResolvedGenerator Create(TypePositionInfo info, bool isToJs, Kno { return failWithReason(SR.Format(SR.FuncArgumentNotSupported, argumentTypes[i])); } - var gen = Create(info, isToJs ^ (!isReturn), argumentTypes[i], Array.Empty(), jsTypeArguments[i], Array.Empty(), failWithReason); + var gen = Create(info, context, isToJs ^ (!isReturn), argumentTypes[i], Array.Empty(), jsTypeArguments[i], Array.Empty(), failWithReason); argsMarshalers.Add(((BaseJSGenerator)gen.Generator).Type); } var maxArgs = marshaledType == KnownManagedType.Action ? 3 : 4; @@ -290,7 +290,7 @@ internal static ResolvedGenerator Create(TypePositionInfo info, bool isToJs, Kno { return failWithReason(SR.FuncTooManyArgs); } - return ResolvedGenerator.Resolved(new FuncJSGenerator(info, marshaledType == KnownManagedType.Action, argsMarshallerTypes)); + return ResolvedGenerator.Resolved(new FuncJSGenerator(info, context, marshaledType == KnownManagedType.Action, argsMarshallerTypes)); case KnownManagedType.Action when jsType == JSTypeFlags.Function: case KnownManagedType.Function when jsType == JSTypeFlags.Function: return failWithReason(SR.FuncWrongArgumentCount); diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs index fe5d0459624b7..7891bec53f218 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs @@ -15,7 +15,7 @@ namespace Microsoft.Interop.JavaScript internal abstract class JSCodeGenerator { public const string ReturnIdentifier = "__retVal"; - public const string ReturnNativeIdentifier = $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}"; + public const string ReturnNativeIdentifier = $"{ReturnIdentifier}{StubIdentifierContext.GeneratedNativeIdentifierSuffix}"; public const string InvokeSucceededIdentifier = "__invokeSucceeded"; } @@ -23,7 +23,7 @@ internal sealed class JSImportCodeGenerator : JSCodeGenerator { private readonly BoundGenerators _marshallers; - private readonly StubCodeContext _context; + private readonly StubIdentifierContext _context; private readonly JSImportData _jsImportData; private readonly JSSignatureContext _signatureContext; @@ -36,18 +36,22 @@ public JSImportCodeGenerator( { _jsImportData = attributeData; _signatureContext = signatureContext; - _context = new ManagedToNativeStubCodeContext(ReturnIdentifier, ReturnIdentifier) - { - CodeEmitOptions = new(SkipInit: true) - }; - _marshallers = BoundGenerators.Create(argTypes, generatorResolver, _context, new EmptyJSGenerator(), out var bindingFailures); + + _marshallers = BoundGenerators.Create(argTypes, generatorResolver, StubCodeContext.DefaultManagedToNativeStub, new EmptyJSGenerator(), out var bindingFailures); diagnosticsBag.ReportGeneratorDiagnostics(bindingFailures); - if (_marshallers.ManagedReturnMarshaller.UsesNativeIdentifier(_context)) + if (_marshallers.ManagedReturnMarshaller.UsesNativeIdentifier) { // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. - _context = new ManagedToNativeStubCodeContext(ReturnIdentifier, ReturnNativeIdentifier) + _context = new DefaultIdentifierContext(ReturnIdentifier, ReturnNativeIdentifier, MarshalDirection.ManagedToUnmanaged) + { + CodeEmitOptions = new(SkipInit: true) + }; + } + else + { + _context = new DefaultIdentifierContext(ReturnIdentifier, ReturnIdentifier, MarshalDirection.ManagedToUnmanaged) { CodeEmitOptions = new(SkipInit: true) }; @@ -59,7 +63,7 @@ public JSImportCodeGenerator( IBoundMarshallingGenerator spanArg = _marshallers.SignatureMarshallers.FirstOrDefault(m => m.TypeInfo.MarshallingAttributeInfo is JSMarshallingInfo(_, JSSpanTypeInfo)); if (spanArg != default) { - diagnosticsBag.ReportGeneratorDiagnostic(new GeneratorDiagnostic.NotSupported(spanArg.TypeInfo, _context) + diagnosticsBag.ReportGeneratorDiagnostic(new GeneratorDiagnostic.NotSupported(spanArg.TypeInfo) { NotSupportedDetails = SR.SpanAndTaskNotSupported }); @@ -151,9 +155,9 @@ private void BindSyntax(List statementsToUpdate) private ArgumentSyntax CreateSignaturesSyntax() { - IEnumerable types = _marshallers.ManagedReturnMarshaller is IJSMarshallingGenerator jsGen ? jsGen.GenerateBind(_context) : []; + IEnumerable types = _marshallers.ManagedReturnMarshaller is IJSMarshallingGenerator jsGen ? jsGen.GenerateBind() : []; types = types - .Concat(_marshallers.NativeParameterMarshallers.OfType().SelectMany(p => p.GenerateBind(_context))); + .Concat(_marshallers.NativeParameterMarshallers.OfType().SelectMany(p => p.GenerateBind())); return Argument(ArrayCreationExpression(ArrayType(IdentifierName(Constants.JSMarshalerTypeGlobal)) .WithRankSpecifiers(SingletonList(ArrayRankSpecifier(SingletonSeparatedList(OmittedArraySizeExpression()))))) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArrayJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArrayJSGenerator.cs index f6c7e6e6cab83..5d7d55c644bd7 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArrayJSGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArrayJSGenerator.cs @@ -13,18 +13,16 @@ internal sealed class ArrayJSGenerator : PrimitiveJSGenerator { private readonly MarshalerType _elementMarshalerType; - public ArrayJSGenerator(TypePositionInfo info, MarshalerType elementMarshalerType) - : base(info, MarshalerType.Array) + public ArrayJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType elementMarshalerType) + : base(info, context, MarshalerType.Array) { _elementMarshalerType = elementMarshalerType; } - public override IEnumerable GenerateBind(StubCodeContext context) + public override IEnumerable GenerateBind() { yield return InvocationExpression(MarshalerTypeName(Type), ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(_elementMarshalerType))))); } - - public override IBoundMarshallingGenerator Rebind(TypePositionInfo info) => new ArrayJSGenerator(info, _elementMarshalerType); } } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArraySegmentJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArraySegmentJSGenerator.cs index 9e9cd1aabb0ed..f3785d8bf7e12 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArraySegmentJSGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/ArraySegmentJSGenerator.cs @@ -12,18 +12,16 @@ internal sealed class ArraySegmentJSGenerator : PrimitiveJSGenerator { private readonly MarshalerType _elementMarshalerType; - public ArraySegmentJSGenerator(TypePositionInfo info, MarshalerType elementMarshalerType) - : base(info, MarshalerType.ArraySegment) + public ArraySegmentJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType elementMarshalerType) + : base(info, context, MarshalerType.ArraySegment) { _elementMarshalerType = elementMarshalerType; } - public override IEnumerable GenerateBind(StubCodeContext context) + public override IEnumerable GenerateBind() { yield return InvocationExpression(MarshalerTypeName(Type), ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(_elementMarshalerType))))); } - - public override IBoundMarshallingGenerator Rebind(TypePositionInfo info) => new ArraySegmentJSGenerator(info, _elementMarshalerType); } } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/BaseJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/BaseJSGenerator.cs index 8b4d324fc589c..1f6eef2346545 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/BaseJSGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/BaseJSGenerator.cs @@ -23,27 +23,29 @@ protected BaseJSGenerator(MarshalerType marshalerType, IBoundMarshallingGenerato public TypePositionInfo TypeInfo => _inner.TypeInfo; + public StubCodeContext CodeContext => _inner.CodeContext; + public ManagedTypeInfo NativeType => _inner.NativeType; public SignatureBehavior NativeSignatureBehavior => _inner.NativeSignatureBehavior; - public ValueBoundaryBehavior GetValueBoundaryBehavior(StubCodeContext context) => _inner.GetValueBoundaryBehavior(context); + public ValueBoundaryBehavior ValueBoundaryBehavior => _inner.ValueBoundaryBehavior; - public virtual bool UsesNativeIdentifier(StubCodeContext context) => _inner.UsesNativeIdentifier(context); + public virtual bool UsesNativeIdentifier => _inner.UsesNativeIdentifier; - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => _inner.SupportsByValueMarshalKind(marshalKind, context, out diagnostic); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, out GeneratorDiagnostic? diagnostic) + => _inner.SupportsByValueMarshalKind(marshalKind, out diagnostic); - public virtual IEnumerable GenerateBind(StubCodeContext context) + public virtual IEnumerable GenerateBind() { yield return MarshalerTypeName(Type); } - public virtual IEnumerable Generate(StubCodeContext context) + public virtual IEnumerable Generate(StubIdentifierContext context) { string argName = context.GetAdditionalIdentifier(TypeInfo, "js_arg"); - if (context.CurrentStage == StubCodeContext.Stage.Setup) + if (context.CurrentStage == StubIdentifierContext.Stage.Setup) { if (!TypeInfo.IsManagedReturnPosition) { @@ -87,7 +89,5 @@ protected static IdentifierNameSyntax GetToJSMethod(MarshalerType marshalerType) return IdentifierName(Constants.ToJSMethod); } } - - public abstract IBoundMarshallingGenerator Rebind(TypePositionInfo info); } } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/EmptyJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/EmptyJSGenerator.cs index 4cd1b3aa9e803..e9704fbdc04d2 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/EmptyJSGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/EmptyJSGenerator.cs @@ -10,11 +10,11 @@ namespace Microsoft.Interop.JavaScript internal sealed class EmptyJSGenerator : IUnboundMarshallingGenerator { public ManagedTypeInfo AsNativeType(TypePositionInfo info) => info.ManagedType; - public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) => Array.Empty(); + public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext identifierContext) => Array.Empty(); public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) => SignatureBehavior.ManagedTypeAndAttributes; public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) => ValueBoundaryBehavior.ManagedIdentifier; - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) + => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => false; } } 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 bb2101993f943..d4d7f785c5536 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 @@ -16,20 +16,20 @@ internal sealed class FuncJSGenerator : BaseJSGenerator private readonly bool _isAction; private readonly MarshalerType[] _argumentMarshalerTypes; - public FuncJSGenerator(TypePositionInfo info, bool isAction, MarshalerType[] argumentMarshalerTypes) - : base(isAction ? MarshalerType.Action : MarshalerType.Function, new Forwarder().Bind(info)) + public FuncJSGenerator(TypePositionInfo info, StubCodeContext context, bool isAction, MarshalerType[] argumentMarshalerTypes) + : base(isAction ? MarshalerType.Action : MarshalerType.Function, new Forwarder().Bind(info, context)) { _isAction = isAction; _argumentMarshalerTypes = argumentMarshalerTypes; } - public override IEnumerable GenerateBind(StubCodeContext context) + public override IEnumerable GenerateBind() { var args = _argumentMarshalerTypes.Select(x => Argument(MarshalerTypeName(x))).ToList(); yield return InvocationExpression(MarshalerTypeName(Type), ArgumentList(SeparatedList(args))); } - public override IEnumerable Generate(StubCodeContext context) + public override IEnumerable Generate(StubIdentifierContext context) { string argName = context.GetAdditionalIdentifier(TypeInfo, "js_arg"); var target = TypeInfo.IsManagedReturnPosition @@ -45,12 +45,12 @@ public override IEnumerable Generate(StubCodeContext context) .Select(a => a.Syntax) .ToArray(); - if (context.CurrentStage == StubCodeContext.Stage.UnmarshalCapture && context.Direction == MarshalDirection.ManagedToUnmanaged && TypeInfo.IsManagedReturnPosition) + if (context.CurrentStage == StubIdentifierContext.Stage.UnmarshalCapture && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && TypeInfo.IsManagedReturnPosition) { yield return ToManagedMethod(target, source, jsty); } - if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == MarshalDirection.UnmanagedToManaged && TypeInfo.IsManagedReturnPosition) + if (context.CurrentStage == StubIdentifierContext.Stage.Marshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && TypeInfo.IsManagedReturnPosition) { yield return ToJSMethod(target, source, jsty); } @@ -60,12 +60,12 @@ public override IEnumerable Generate(StubCodeContext context) yield return x; } - if (context.CurrentStage == StubCodeContext.Stage.PinnedMarshal && context.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsManagedReturnPosition) + if (context.CurrentStage == StubIdentifierContext.Stage.PinnedMarshal && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsManagedReturnPosition) { yield return ToJSMethod(target, source, jsty); } - if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsManagedReturnPosition) + if (context.CurrentStage == StubIdentifierContext.Stage.Unmarshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsManagedReturnPosition) { yield return ToManagedMethod(target, source, jsty); } @@ -73,8 +73,7 @@ public override IEnumerable Generate(StubCodeContext context) private ExpressionStatementSyntax ToManagedMethod(string target, ArgumentSyntax source, JSFunctionTypeInfo info) { - List arguments = new List(); - arguments.Add(source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword))); + List arguments = [source.WithRefOrOutKeyword(Token(SyntaxKind.OutKeyword))]; for (int i = 0; i < info.ArgsTypeInfo.Length; i++) { var sourceType = info.ArgsTypeInfo[i]; @@ -95,8 +94,7 @@ private ExpressionStatementSyntax ToManagedMethod(string target, ArgumentSyntax private ExpressionStatementSyntax ToJSMethod(string target, ArgumentSyntax source, JSFunctionTypeInfo info) { - List arguments = new List(); - arguments.Add(source); + List arguments = [source]; for (int i = 0; i < info.ArgsTypeInfo.Length; i++) { var sourceType = info.ArgsTypeInfo[i]; @@ -115,9 +113,6 @@ private ExpressionStatementSyntax ToJSMethod(string target, ArgumentSyntax sourc .WithArgumentList(ArgumentList(SeparatedList(arguments)))); } - public override IBoundMarshallingGenerator Rebind(TypePositionInfo info) => new FuncJSGenerator(info, _isAction, _argumentMarshalerTypes); - - private static ArgumentSyntax ArgToJS(int i, TypeSyntax sourceType, MarshalerType marshalerType) => Argument(ParenthesizedLambdaExpression() .WithModifiers(TokenList(Token(SyntaxKind.StaticKeyword))) .WithParameterList(ParameterList(SeparatedList(new[]{ diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/IJSMarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/IJSMarshallingGenerator.cs index d250048c393c8..f60406b21e869 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/IJSMarshallingGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/IJSMarshallingGenerator.cs @@ -8,6 +8,6 @@ namespace Microsoft.Interop.JavaScript { internal interface IJSMarshallingGenerator : IBoundMarshallingGenerator { - IEnumerable GenerateBind(StubCodeContext context); + IEnumerable GenerateBind(); } } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/NullableJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/NullableJSGenerator.cs index 2b9a5f5175d49..191c475f1330f 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/NullableJSGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/NullableJSGenerator.cs @@ -10,17 +10,15 @@ namespace Microsoft.Interop.JavaScript { internal sealed class NullableJSGenerator : PrimitiveJSGenerator { - public NullableJSGenerator(TypePositionInfo info, MarshalerType resultMarshalerType) - : base(info, resultMarshalerType) + public NullableJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType resultMarshalerType) + : base(info, context, resultMarshalerType) { } - public override IEnumerable GenerateBind(StubCodeContext context) + public override IEnumerable GenerateBind() { yield return InvocationExpression(MarshalerTypeName(MarshalerType.Nullable), ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(Type))))); } - - public override IBoundMarshallingGenerator Rebind(TypePositionInfo info) => new NullableJSGenerator(info, Type); } } 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 5d2ed3963ae6d..5da5c9db17975 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 @@ -16,13 +16,13 @@ public PrimitiveJSGenerator(MarshalerType marshalerType, IBoundMarshallingGenera { } - public PrimitiveJSGenerator(TypePositionInfo info, MarshalerType marshalerType) - : base(marshalerType, new Forwarder().Bind(info)) + public PrimitiveJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType marshalerType) + : base(marshalerType, new Forwarder().Bind(info, context)) { } // TODO order parameters in such way that affinity capturing parameters are emitted first - public override IEnumerable Generate(StubCodeContext context) + public override IEnumerable Generate(StubIdentifierContext context) { string argName = context.GetAdditionalIdentifier(TypeInfo, "js_arg"); var target = TypeInfo.IsManagedReturnPosition @@ -33,12 +33,12 @@ public override IEnumerable Generate(StubCodeContext context) ? Argument(IdentifierName(context.GetIdentifiers(TypeInfo).native)) : _inner.AsArgument(context); - if (context.CurrentStage == StubCodeContext.Stage.UnmarshalCapture && context.Direction == MarshalDirection.ManagedToUnmanaged && TypeInfo.IsManagedReturnPosition) + if (context.CurrentStage == StubIdentifierContext.Stage.UnmarshalCapture && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && TypeInfo.IsManagedReturnPosition) { yield return ToManagedMethod(target, source); } - if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == MarshalDirection.UnmanagedToManaged && TypeInfo.IsManagedReturnPosition) + if (context.CurrentStage == StubIdentifierContext.Stage.Marshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && TypeInfo.IsManagedReturnPosition) { yield return ToJSMethod(target, source); } @@ -48,12 +48,12 @@ public override IEnumerable Generate(StubCodeContext context) yield return x; } - if (context.CurrentStage == StubCodeContext.Stage.PinnedMarshal && context.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsManagedReturnPosition) + if (context.CurrentStage == StubIdentifierContext.Stage.PinnedMarshal && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsManagedReturnPosition) { yield return ToJSMethod(target, source); } - if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsManagedReturnPosition) + if (context.CurrentStage == StubIdentifierContext.Stage.Unmarshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsManagedReturnPosition) { yield return ToManagedMethod(target, source); } @@ -82,8 +82,5 @@ private ExpressionStatementSyntax ToJSMethod(string target, ArgumentSyntax sourc IdentifierName(target), GetToJSMethod(Type))) .WithArgumentList(ArgumentList(SingletonSeparatedList(ToJSMethodRefOrOut(source))))); } - - public override IBoundMarshallingGenerator Rebind(TypePositionInfo info) - => new PrimitiveJSGenerator(Type, _inner.Rebind(info)); } } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/SpanJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/SpanJSGenerator.cs index 8319c6477172c..afaedf597b6fe 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/SpanJSGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/SpanJSGenerator.cs @@ -12,18 +12,16 @@ internal sealed class SpanJSGenerator : PrimitiveJSGenerator { private readonly MarshalerType _elementMarshalerType; - public SpanJSGenerator(TypePositionInfo info, MarshalerType elementMarshalerType) - : base(info, MarshalerType.Span) + public SpanJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType elementMarshalerType) + : base(info, context, MarshalerType.Span) { _elementMarshalerType = elementMarshalerType; } - public override IEnumerable GenerateBind(StubCodeContext context) + public override IEnumerable GenerateBind() { yield return InvocationExpression(MarshalerTypeName(Type), ArgumentList(SingletonSeparatedList(Argument(MarshalerTypeName(_elementMarshalerType))))); } - - public override IBoundMarshallingGenerator Rebind(TypePositionInfo info) => new SpanJSGenerator(info, _elementMarshalerType); } } 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 5f8023de1e66b..381f4dac81374 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 @@ -13,13 +13,13 @@ internal sealed class TaskJSGenerator : BaseJSGenerator { private readonly MarshalerType _resultMarshalerType; - public TaskJSGenerator(TypePositionInfo info, MarshalerType resultMarshalerType) - : base(MarshalerType.Task, new Forwarder().Bind(info)) + public TaskJSGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType resultMarshalerType) + : base(MarshalerType.Task, new Forwarder().Bind(info, context)) { _resultMarshalerType = resultMarshalerType; } - public override IEnumerable GenerateBind(StubCodeContext context) + public override IEnumerable GenerateBind() { var jsty = (JSTaskTypeInfo)((JSMarshallingInfo)TypeInfo.MarshallingAttributeInfo).TypeInfo; if (jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void)) @@ -33,7 +33,7 @@ public override IEnumerable GenerateBind(StubCodeContext conte } } - public override IEnumerable Generate(StubCodeContext context) + public override IEnumerable Generate(StubIdentifierContext context) { var jsty = (JSTaskTypeInfo)((JSMarshallingInfo)TypeInfo.MarshallingAttributeInfo).TypeInfo; @@ -46,14 +46,14 @@ public override IEnumerable Generate(StubCodeContext context) ? Argument(IdentifierName(context.GetIdentifiers(TypeInfo).native)) : _inner.AsArgument(context); - if (context.CurrentStage == StubCodeContext.Stage.UnmarshalCapture && context.Direction == MarshalDirection.ManagedToUnmanaged && TypeInfo.IsManagedReturnPosition) + if (context.CurrentStage == StubIdentifierContext.Stage.UnmarshalCapture && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && TypeInfo.IsManagedReturnPosition) { yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void) ? ToManagedMethodVoid(target, source) : ToManagedMethod(target, source, jsty.ResultTypeInfo.Syntax); } - if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == MarshalDirection.UnmanagedToManaged && TypeInfo.IsManagedReturnPosition) + if (context.CurrentStage == StubIdentifierContext.Stage.Marshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && TypeInfo.IsManagedReturnPosition) { yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void) ? ToJSMethodVoid(target, source) @@ -65,14 +65,14 @@ public override IEnumerable Generate(StubCodeContext context) yield return x; } - if (context.CurrentStage == StubCodeContext.Stage.PinnedMarshal && context.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsManagedReturnPosition) + if (context.CurrentStage == StubIdentifierContext.Stage.PinnedMarshal && CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsManagedReturnPosition) { yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void) ? ToJSMethodVoid(target, source) : ToJSMethod(target, source, jsty.ResultTypeInfo.Syntax); } - if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsManagedReturnPosition) + if (context.CurrentStage == StubIdentifierContext.Stage.Unmarshal && CodeContext.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsManagedReturnPosition) { yield return jsty.ResultTypeInfo is JSSimpleTypeInfo(KnownManagedType.Void) ? ToManagedMethodVoid(target, source) @@ -138,7 +138,5 @@ private ExpressionStatementSyntax ToJSMethod(string target, ArgumentSyntax sourc Argument(IdentifierName("__task_result")), }))))))))})))); } - - public override IBoundMarshallingGenerator Rebind(TypePositionInfo info) => new TaskJSGenerator(info, _resultMarshalerType); } } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/VoidGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/VoidGenerator.cs index c1def8aa74fef..2177f5436e431 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/VoidGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/VoidGenerator.cs @@ -5,9 +5,5 @@ namespace Microsoft.Interop.JavaScript { - internal sealed class VoidGenerator(TypePositionInfo info, MarshalerType marshalerType) : BaseJSGenerator(marshalerType, new Forwarder().Bind(info)) - { - public override IBoundMarshallingGenerator Rebind(TypePositionInfo info) - => new VoidGenerator(info, Type); - } + internal sealed class VoidGenerator(TypePositionInfo info, StubCodeContext context, MarshalerType marshalerType) : BaseJSGenerator(marshalerType, new Forwarder().Bind(info, context)); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ConvertComImportToGeneratedComInterfaceAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ConvertComImportToGeneratedComInterfaceAnalyzer.cs index ad3b8d97f8f45..edb396095fb19 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ConvertComImportToGeneratedComInterfaceAnalyzer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/ConvertComImportToGeneratedComInterfaceAnalyzer.cs @@ -87,9 +87,6 @@ public override void Initialize(AnalysisContext context) mayRequireAdditionalWork = diagnostics.Diagnostics.Any(); bool anyExplicitlyUnsupportedInfo = false; - var managedToNativeStubCodeContext = new ManagedToNativeStubCodeContext("return", "nativeReturn"); - var nativeToManagedStubCodeContext = new NativeToManagedStubCodeContext("return", "nativeReturn"); - var forwarder = new Forwarder(); // We don't actually need the bound generators. We just need them to be attempted to be bound to determine if the generator will be able to bind them. BoundGenerators generators = BoundGenerators.Create(targetSignatureContext.ElementTypeInformation, new CallbackGeneratorResolver((info, context) => @@ -97,17 +94,17 @@ public override void Initialize(AnalysisContext context) if (s_unsupportedTypeNames.Contains(info.ManagedType.FullTypeName)) { anyExplicitlyUnsupportedInfo = true; - return ResolvedGenerator.Resolved(forwarder.Bind(info)); + return ResolvedGenerator.Resolved(forwarder.Bind(info, context)); } if (HasUnsupportedMarshalAsInfo(info)) { anyExplicitlyUnsupportedInfo = true; - return ResolvedGenerator.Resolved(forwarder.Bind(info)); + return ResolvedGenerator.Resolved(forwarder.Bind(info, context)); } if (info.MarshallingAttributeInfo is TrackedMarshallingInfo(TrackedMarshallingInfoAnnotation.ExplicitlyUnsupported, _)) { anyExplicitlyUnsupportedInfo = true; - return ResolvedGenerator.Resolved(forwarder.Bind(info)); + return ResolvedGenerator.Resolved(forwarder.Bind(info, context)); } if (info.MarshallingAttributeInfo is TrackedMarshallingInfo(TrackedMarshallingInfoAnnotation annotation, var inner)) { @@ -118,13 +115,13 @@ public override void Initialize(AnalysisContext context) info = info with { MarshallingAttributeInfo = inner }; } // Run both factories and collect any binding failures. - ResolvedGenerator unmanagedToManagedGenerator = unmanagedToManagedFactory.Create(info, nativeToManagedStubCodeContext); - ResolvedGenerator managedToUnmanagedGenerator = managedToUnmanagedFactory.Create(info, managedToNativeStubCodeContext); + ResolvedGenerator unmanagedToManagedGenerator = unmanagedToManagedFactory.Create(info, StubCodeContext.DefaultNativeToManagedStub); + ResolvedGenerator managedToUnmanagedGenerator = managedToUnmanagedFactory.Create(info, StubCodeContext.DefaultManagedToNativeStub); return managedToUnmanagedGenerator with { Diagnostics = managedToUnmanagedGenerator.Diagnostics.AddRange(unmanagedToManagedGenerator.Diagnostics) }; - }), managedToNativeStubCodeContext, forwarder, out var generatorDiagnostics); + }), StubCodeContext.DefaultManagedToNativeStub, forwarder, out var generatorDiagnostics); mayRequireAdditionalWork |= generatorDiagnostics.Any(diag => diag.IsFatal); @@ -164,7 +161,7 @@ private static MarshallingInfoParser CreateComImportMarshallingInfoParser(StubEn new NativeMarshallingAttributeParser(env.Compilation, diagnostics), new ComInterfaceMarshallingInfoProvider(env.Compilation)), ImmutableArray.Create( - new SafeHandleMarshallingInfoProvider(env.Compilation, method.ContainingType), + new SafeHandleMarshallingInfoProvider(env.Compilation), new ExplicitlyUnsupportedMarshallingInfoProvider(), // We don't support arrays, so we don't include the array marshalling info provider. Instead, we include our "explicitly unsupported" provider. new CharMarshallingInfoProvider(defaultInfo), new TrackingStringMarshallingInfoProvider(new StringMarshallingInfoProvider(env.Compilation, diagnostics, unparsedAttributeData, defaultInfo)), // We need to mark when we see string types to ensure we offer a code-fix that adds the string marshalling info. diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGeneratorHelpers.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGeneratorHelpers.cs index 2527ffb9e282a..91a3a956a024b 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGeneratorHelpers.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGeneratorHelpers.cs @@ -19,7 +19,7 @@ private static IMarshallingGeneratorResolver CreateGeneratorResolver(Environment => DefaultMarshallingGeneratorResolver.Create(env, direction, TypeNames.GeneratedComInterfaceAttribute_ShortName, [ new StructAsHResultMarshallerFactory(), - new ManagedHResultExceptionGeneratorResolver(direction), + new ManagedHResultExceptionGeneratorResolver(), new ComInterfaceDispatchMarshallingResolver(), ]); diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs index c194e771e139f..e85905a0ee7f7 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs @@ -128,7 +128,6 @@ private MethodDeclarationSyntax GenerateShadow() { // DeclarationCopiedFromBaseDeclaration() // => (()this).(); - var forwarder = new Forwarder(); return MethodDeclaration(GenerationContext.SignatureContext.StubReturnType, MethodInfo.MethodName) .WithModifiers(TokenList(Token(SyntaxKind.NewKeyword))) .WithAttributeLists(List(GenerationContext.SignatureContext.AdditionalAttributes.Concat(MethodInfo.Attributes.Select(a => a.GenerateAttributeList())))) @@ -142,7 +141,7 @@ private MethodDeclarationSyntax GenerateShadow() CastExpression(OriginalDeclaringInterface.Info.Type.Syntax, IdentifierName("this"))), IdentifierName(MethodInfo.MethodName)), ArgumentList( - SeparatedList(GenerationContext.SignatureContext.ManagedParameters.Select(p => forwarder.Bind(p).AsArgument(new ManagedStubCodeContext()))))))) + SeparatedList(GenerationContext.SignatureContext.ManagedParameters.Select(p => Argument(IdentifierName(p.InstanceIdentifier)))))))) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedStubCodeContext.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedStubCodeContext.cs deleted file mode 100644 index 207ae29537f6e..0000000000000 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedStubCodeContext.cs +++ /dev/null @@ -1,17 +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; - -namespace Microsoft.Interop -{ - /// - /// Stub code context for generating code that does not cross a native/managed boundary - /// - internal sealed record ManagedStubCodeContext : StubCodeContext - { - public override bool SingleFrameSpansNativeContext => throw new NotImplementedException(); - - public override bool AdditionalTemporaryStateLivesAcrossStages => throw new NotImplementedException(); - } -} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ComInterfaceDispatchMarshallingResolver.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ComInterfaceDispatchMarshallingResolver.cs index 74bb700d56cc3..145ed0b583014 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ComInterfaceDispatchMarshallingResolver.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ComInterfaceDispatchMarshallingResolver.cs @@ -21,8 +21,8 @@ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) if (info.MarshallingAttributeInfo is ComInterfaceDispatchMarshallingInfo) { return context.Direction == MarshalDirection.UnmanagedToManaged - ? ResolvedGenerator.Resolved(new Marshaller().Bind(info)) - : ResolvedGenerator.Resolved(KeepAliveThisMarshaller.Instance.Bind(info)); + ? ResolvedGenerator.Resolved(new Marshaller().Bind(info, context)) + : ResolvedGenerator.Resolved(KeepAliveThisMarshaller.Instance.Bind(info, context)); } else { @@ -37,9 +37,9 @@ public ManagedTypeInfo AsNativeType(TypePositionInfo info) => $"{TypeNames.GlobalAlias + TypeNames.System_Runtime_InteropServices_ComWrappers_ComInterfaceDispatch}*", $"{TypeNames.System_Runtime_InteropServices_ComWrappers_ComInterfaceDispatch}*", IsFunctionPointer: false); - public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) { - if (context.CurrentStage != StubCodeContext.Stage.Unmarshal) + if (context.CurrentStage != StubIdentifierContext.Stage.Unmarshal) { yield break; } @@ -64,8 +64,8 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) => SignatureBehavior.NativeType; public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) => ValueBoundaryBehavior.NativeIdentifier; - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) + => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/KeepAliveThisMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/KeepAliveThisMarshaller.cs index 424213080775c..0d1cc0a7c9639 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/KeepAliveThisMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/KeepAliveThisMarshaller.cs @@ -15,9 +15,9 @@ internal sealed class KeepAliveThisMarshaller : IUnboundMarshallingGenerator public static readonly KeepAliveThisMarshaller Instance = new(); public ManagedTypeInfo AsNativeType(TypePositionInfo info) => info.ManagedType; - public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) { - if (context.CurrentStage != StubCodeContext.Stage.NotifyForSuccessfulInvoke) + if (context.CurrentStage != StubIdentifierContext.Stage.NotifyForSuccessfulInvoke) { return []; } @@ -32,8 +32,8 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) => SignatureBehavior.NativeType; public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) => ValueBoundaryBehavior.ManagedIdentifier; - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) + => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => false; } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ManagedHResultExceptionGeneratorResolver.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ManagedHResultExceptionGeneratorResolver.cs index 1af732f2b47f5..8f8254fa6f625 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ManagedHResultExceptionGeneratorResolver.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ManagedHResultExceptionGeneratorResolver.cs @@ -15,25 +15,14 @@ internal sealed record ManagedHResultExceptionMarshallingInfo : MarshallingInfo; internal sealed class ManagedHResultExceptionGeneratorResolver : IMarshallingGeneratorResolver { - private readonly MarshalDirection _direction; - - public ManagedHResultExceptionGeneratorResolver(MarshalDirection direction) - { - if (direction is not (MarshalDirection.ManagedToUnmanaged or MarshalDirection.UnmanagedToManaged)) - { - throw new ArgumentOutOfRangeException(nameof(direction)); - } - _direction = direction; - } - public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) { if (info.MarshallingAttributeInfo is ManagedHResultExceptionMarshallingInfo) { - return ResolvedGenerator.Resolved(_direction switch + return ResolvedGenerator.Resolved(context.Direction switch { - MarshalDirection.UnmanagedToManaged => new UnmanagedToManagedMarshaller().Bind(info), - MarshalDirection.ManagedToUnmanaged => new ManagedToUnmanagedMarshaller().Bind(info), + MarshalDirection.UnmanagedToManaged => new UnmanagedToManagedMarshaller().Bind(info, context), + MarshalDirection.ManagedToUnmanaged => new ManagedToUnmanagedMarshaller().Bind(info, context), _ => throw new UnreachableException() }); } @@ -46,11 +35,11 @@ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) private sealed class ManagedToUnmanagedMarshaller : IUnboundMarshallingGenerator { public ManagedTypeInfo AsNativeType(TypePositionInfo info) => info.ManagedType; - public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) { Debug.Assert(info.MarshallingAttributeInfo is ManagedHResultExceptionMarshallingInfo); - if (context.CurrentStage != StubCodeContext.Stage.NotifyForSuccessfulInvoke) + if (context.CurrentStage != StubIdentifierContext.Stage.NotifyForSuccessfulInvoke) { yield break; } @@ -66,19 +55,19 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) => SignatureBehavior.NativeType; public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) => ValueBoundaryBehavior.ManagedIdentifier; - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) + => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => false; } private sealed class UnmanagedToManagedMarshaller : IUnboundMarshallingGenerator { public ManagedTypeInfo AsNativeType(TypePositionInfo info) => info.ManagedType; - public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) { Debug.Assert(info.MarshallingAttributeInfo is ManagedHResultExceptionMarshallingInfo); - if (context.CurrentStage != StubCodeContext.Stage.NotifyForSuccessfulInvoke) + if (context.CurrentStage != StubIdentifierContext.Stage.NotifyForSuccessfulInvoke) { yield break; } @@ -103,8 +92,8 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) => SignatureBehavior.NativeType; public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) => ValueBoundaryBehavior.ManagedIdentifier; - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) + => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => false; } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ObjectUnwrapperResolver.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ObjectUnwrapperResolver.cs index 44c0bb257916f..29b758c6ce5e6 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ObjectUnwrapperResolver.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/ObjectUnwrapperResolver.cs @@ -19,8 +19,8 @@ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) if (info.MarshallingAttributeInfo is ObjectUnwrapperInfo) { return context.Direction == MarshalDirection.UnmanagedToManaged - ? ResolvedGenerator.Resolved(new Marshaller().Bind(info)) - : ResolvedGenerator.Resolved(KeepAliveThisMarshaller.Instance.Bind(info)); + ? ResolvedGenerator.Resolved(new Marshaller().Bind(info, context)) + : ResolvedGenerator.Resolved(KeepAliveThisMarshaller.Instance.Bind(info, context)); } else { @@ -31,11 +31,11 @@ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) private sealed class Marshaller : IUnboundMarshallingGenerator { public ManagedTypeInfo AsNativeType(TypePositionInfo info) => new PointerTypeInfo("void*", "void*", false); - public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) { Debug.Assert(info.MarshallingAttributeInfo is ObjectUnwrapperInfo); TypeSyntax unwrapperType = ((ObjectUnwrapperInfo)info.MarshallingAttributeInfo).UnwrapperType; - if (context.CurrentStage != StubCodeContext.Stage.Unmarshal) + if (context.CurrentStage != StubIdentifierContext.Stage.Unmarshal) { yield break; } @@ -59,8 +59,8 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) => SignatureBehavior.NativeType; public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, StubCodeContext context) => ValueBoundaryBehavior.NativeIdentifier; - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) + => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/StructAsHResultMarshallerFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/StructAsHResultMarshallerFactory.cs index a9bd1619b6429..af66c1c2d709f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/StructAsHResultMarshallerFactory.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/StructAsHResultMarshallerFactory.cs @@ -19,7 +19,7 @@ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) // Value type with MarshalAs(UnmanagedType.Error), to be marshalled as an unmanaged HRESULT. if (info is { ManagedType: ValueTypeInfo, MarshallingAttributeInfo: MarshalAsInfo(UnmanagedType.Error, _) }) { - return ResolvedGenerator.Resolved(s_marshaller.Bind(info)); + return ResolvedGenerator.Resolved(s_marshaller.Bind(info, context)); } return ResolvedGenerator.UnresolvedGenerator; @@ -29,14 +29,14 @@ private sealed class Marshaller : IUnboundMarshallingGenerator { public ManagedTypeInfo AsNativeType(TypePositionInfo info) => SpecialTypeInfo.Int32; - public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) { var (managed, unmanaged) = context.GetIdentifiers(info); switch (context.CurrentStage) { - case StubCodeContext.Stage.Marshal: - if (MarshallerHelpers.GetMarshalDirection(info, context) is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) + case StubIdentifierContext.Stage.Marshal: + if (MarshallerHelpers.GetMarshalDirection(info, codeContext) is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) { // unmanaged = Unsafe.BitCast(managed); yield return AssignmentStatement( @@ -53,8 +53,8 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont Argument(IdentifierName(managed)))); } break; - case StubCodeContext.Stage.Unmarshal: - if (MarshallerHelpers.GetMarshalDirection(info, context) is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional) + case StubIdentifierContext.Stage.Unmarshal: + if (MarshallerHelpers.GetMarshalDirection(info, codeContext) is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional) { // managed = Unsafe.BitCast(unmanaged); yield return AssignmentStatement( @@ -91,8 +91,8 @@ public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, Stu return ValueBoundaryBehavior.NativeIdentifier; } - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) + => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnmanagedToManagedStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnmanagedToManagedStubGenerator.cs index 86938e1a98dfe..04897fb03d763 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnmanagedToManagedStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnmanagedToManagedStubGenerator.cs @@ -17,22 +17,25 @@ internal sealed class UnmanagedToManagedStubGenerator private readonly BoundGenerators _marshallers; - private readonly NativeToManagedStubCodeContext _context; + private readonly StubIdentifierContext _context; public UnmanagedToManagedStubGenerator( ImmutableArray argTypes, GeneratorDiagnosticsBag diagnosticsBag, IMarshallingGeneratorResolver generatorResolver) { - _context = new NativeToManagedStubCodeContext(ReturnIdentifier, ReturnIdentifier); - _marshallers = BoundGenerators.Create(argTypes, generatorResolver, _context, new Forwarder(), out var bindingDiagnostics); + _marshallers = BoundGenerators.Create(argTypes, generatorResolver, StubCodeContext.DefaultNativeToManagedStub, new Forwarder(), out var bindingDiagnostics); diagnosticsBag.ReportGeneratorDiagnostics(bindingDiagnostics); - if (_marshallers.NativeReturnMarshaller.UsesNativeIdentifier(_context)) + if (_marshallers.NativeReturnMarshaller.UsesNativeIdentifier) { // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. - _context = new NativeToManagedStubCodeContext(ReturnIdentifier, $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}"); + _context = new DefaultIdentifierContext(ReturnIdentifier, $"{ReturnIdentifier}{StubIdentifierContext.GeneratedNativeIdentifierSuffix}", MarshalDirection.UnmanagedToManaged); + } + else + { + _context = new DefaultIdentifierContext(ReturnIdentifier, ReturnIdentifier, MarshalDirection.UnmanagedToManaged); } } @@ -46,11 +49,10 @@ public UnmanagedToManagedStubGenerator( /// public BlockSyntax GenerateStubBody(ExpressionSyntax methodToInvoke) { - List setupStatements = new(); GeneratedStatements statements = GeneratedStatements.Create( _marshallers, - _context, - methodToInvoke); + StubCodeContext.DefaultNativeToManagedStub, + _context, methodToInvoke); Debug.Assert(statements.CleanupCalleeAllocated.IsEmpty); bool shouldInitializeVariables = @@ -59,27 +61,29 @@ public BlockSyntax GenerateStubBody(ExpressionSyntax methodToInvoke) || !statements.ManagedExceptionCatchClauses.IsEmpty; VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForUnmanagedToManaged(_marshallers, _context, shouldInitializeVariables); - setupStatements.AddRange(declarations.Initializations); - setupStatements.AddRange(declarations.Variables); - setupStatements.AddRange(statements.Setup); - - List tryStatements = new(); - tryStatements.AddRange(statements.GuaranteedUnmarshal); - tryStatements.AddRange(statements.Unmarshal); - - tryStatements.Add(statements.InvokeStatement); - - tryStatements.AddRange(statements.NotifyForSuccessfulInvoke); - tryStatements.AddRange(statements.Marshal); - tryStatements.AddRange(statements.PinnedMarshal); + List setupStatements = + [ + .. declarations.Initializations, + .. declarations.Variables, + .. statements.Setup, + ]; + + List tryStatements = + [ + .. statements.GuaranteedUnmarshal, + .. statements.Unmarshal, + statements.InvokeStatement, + .. statements.NotifyForSuccessfulInvoke, + .. statements.Marshal, + .. statements.PinnedMarshal, + ]; List allStatements = setupStatements; - List finallyStatements = new(); SyntaxList catchClauses = List(statements.ManagedExceptionCatchClauses); - finallyStatements.AddRange(statements.CleanupCallerAllocated); - if (finallyStatements.Count > 0) + ImmutableArray finallyStatements = statements.CleanupCallerAllocated; + if (finallyStatements.Length > 0) { allStatements.Add( TryStatement(Block(tryStatements), catchClauses, FinallyClause(Block(finallyStatements)))); diff --git a/src/libraries/System.Runtime.InteropServices/gen/DownlevelLibraryImportGenerator/ForwarderResolver.cs b/src/libraries/System.Runtime.InteropServices/gen/DownlevelLibraryImportGenerator/ForwarderResolver.cs index a87be394a86fc..6b7a68fc19eb3 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/DownlevelLibraryImportGenerator/ForwarderResolver.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/DownlevelLibraryImportGenerator/ForwarderResolver.cs @@ -11,6 +11,6 @@ internal sealed class ForwarderResolver : IMarshallingGeneratorResolver { private static readonly Forwarder s_forwarder = new Forwarder(); - public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) => ResolvedGenerator.Resolved(s_forwarder.Bind(info)); + public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) => ResolvedGenerator.Resolved(s_forwarder.Bind(info, context)); } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs index 79b6a3558f6ae..9d0d19bab2bc6 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs @@ -152,8 +152,6 @@ private static bool IsEligibleDllImport( mayRequireAdditionalWork = diagnostics.Diagnostics.Any(); bool anyExplicitlyUnsupportedInfo = false; - var stubCodeContext = new ManagedToNativeStubCodeContext("return", "nativeReturn"); - var forwarder = new Forwarder(); // We don't actually need the bound generators. We just need them to be attempted to be bound to determine if the generator will be able to bind them. _ = BoundGenerators.Create(targetSignatureContext.ElementTypeInformation, new CallbackGeneratorResolver((info, context) => @@ -161,15 +159,15 @@ private static bool IsEligibleDllImport( if (s_unsupportedTypeNames.Contains(info.ManagedType.FullTypeName)) { anyExplicitlyUnsupportedInfo = true; - return ResolvedGenerator.Resolved(forwarder.Bind(info)); + return ResolvedGenerator.Resolved(forwarder.Bind(info, context)); } if (HasUnsupportedMarshalAsInfo(info)) { anyExplicitlyUnsupportedInfo = true; - return ResolvedGenerator.Resolved(forwarder.Bind(info)); + return ResolvedGenerator.Resolved(forwarder.Bind(info, context)); } - return factory.Create(info, stubCodeContext); - }), stubCodeContext, forwarder, out var bindingFailures); + return factory.Create(info, context); + }), StubCodeContext.DefaultManagedToNativeStub, forwarder, out var bindingFailures); mayRequireAdditionalWork |= bindingFailures.Any(d => d.IsFatal); diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/ForwarderResolver.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/ForwarderResolver.cs index a87be394a86fc..6b7a68fc19eb3 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/ForwarderResolver.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/ForwarderResolver.cs @@ -11,6 +11,6 @@ internal sealed class ForwarderResolver : IMarshallingGeneratorResolver { private static readonly Forwarder s_forwarder = new Forwarder(); - public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) => ResolvedGenerator.Resolved(s_forwarder.Bind(info)); + public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) => ResolvedGenerator.Resolved(s_forwarder.Bind(info, context)); } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/BoundGenerators.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/BoundGenerators.cs index c98ab2d263c5a..335aca92cab2a 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/BoundGenerators.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/BoundGenerators.cs @@ -20,7 +20,7 @@ private BoundGenerators() { } public static BoundGenerators Create(ImmutableArray elementTypeInfo, IMarshallingGeneratorResolver generatorResolver, StubCodeContext context, IUnboundMarshallingGenerator fallbackGenerator, out ImmutableArray generatorBindingDiagnostics) { - IBoundMarshallingGenerator defaultBoundGenerator = fallbackGenerator.Bind(new TypePositionInfo(SpecialTypeInfo.Void, NoMarshallingInfo.Instance)); + IBoundMarshallingGenerator defaultBoundGenerator = fallbackGenerator.Bind(new TypePositionInfo(SpecialTypeInfo.Void, NoMarshallingInfo.Instance), context); BoundGenerators result = new(); ImmutableArray.Builder signatureMarshallers = ImmutableArray.CreateBuilder(); @@ -155,7 +155,7 @@ IBoundMarshallingGenerator CreateGenerator(TypePositionInfo p, IMarshallingGener { ResolvedGenerator generator = factory.Create(p, context); generatorDiagnostics.AddRange(generator.Diagnostics); - return generator.IsResolvedWithoutErrors ? generator.Generator : fallbackGenerator.Bind(p); + return generator.IsResolvedWithoutErrors ? generator.Generator : fallbackGenerator.Bind(p, context); } } @@ -171,7 +171,7 @@ IBoundMarshallingGenerator CreateGenerator(TypePositionInfo p, IMarshallingGener public ImmutableArray NativeParameterMarshallers { get; private init; } - public (ParameterListSyntax ParameterList, TypeSyntax ReturnType, AttributeListSyntax? ReturnTypeAttributes) GenerateTargetMethodSignatureData(StubCodeContext context) + public (ParameterListSyntax ParameterList, TypeSyntax ReturnType, AttributeListSyntax? ReturnTypeAttributes) GenerateTargetMethodSignatureData(StubIdentifierContext context) { return ( ParameterList( @@ -212,7 +212,7 @@ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) if (info.IsNativeReturnPosition && generator.Generator.NativeType != _nativeReturnType) { - return ResolvedGenerator.NotSupported(info, new(info, context) + return ResolvedGenerator.NotSupported(info, context, new(info) { NotSupportedDetails = SR.MarshallerInNativeReturnPositionMustMatchNativeReturnType }); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubCodeContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DefaultIdentifierContext.cs similarity index 54% rename from src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubCodeContext.cs rename to src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DefaultIdentifierContext.cs index bb92b557c8179..9785b52b4cc00 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubCodeContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DefaultIdentifierContext.cs @@ -5,46 +5,45 @@ using System.Diagnostics; namespace Microsoft.Interop { - public sealed record ManagedToNativeStubCodeContext : StubCodeContext + public sealed record DefaultIdentifierContext : StubIdentifierContext { - public override bool SingleFrameSpansNativeContext => true; - - public override bool AdditionalTemporaryStateLivesAcrossStages => true; - private const string InvokeReturnIdentifier = "__invokeRetVal"; private const string InvokeReturnIdentifierNative = "__invokeRetValUnmanaged"; private readonly string _returnIdentifier; private readonly string _nativeReturnIdentifier; + private readonly MarshalDirection _direction; - public ManagedToNativeStubCodeContext( + public DefaultIdentifierContext( string returnIdentifier, - string nativeReturnIdentifier) + string nativeReturnIdentifier, + MarshalDirection direction) { _returnIdentifier = returnIdentifier; _nativeReturnIdentifier = nativeReturnIdentifier; + _direction = direction; } public override (string managed, string native) GetIdentifiers(TypePositionInfo info) { - // If the info is in the managed return position, then we need to generate a name to use + // If the info is in the stub return position, then we need to generate a name to use // for both the managed and native values since there is no name in the signature for the return value. - if (info.IsManagedReturnPosition) + if (MarshallerHelpers.IsInStubReturnPosition(info, _direction)) { + // If the info is in the native exception position, + // then we're going to return using name of the native return identifier. + // We use the provided instance identifier as that represents + // the name of the exception variable specified in the catch clause. + if (info.IsManagedExceptionPosition) + { + return (info.InstanceIdentifier, _nativeReturnIdentifier); + } return (_returnIdentifier, _nativeReturnIdentifier); } - // If the info is in the native return position but is not in the managed return position, + // If the info is in the invocation return position but is not in the stub return position, // then that means that the stub is introducing an additional info for the return position. // This means that there is no name in source for this info, so we must provide one here. - // We can't use ReturnIdentifier or ReturnNativeIdentifier since that will be used by the managed return value. - // Additionally, since all use cases today of a TypePositionInfo in the native position but not the managed - // are for infos that aren't in the managed signature at all (PreserveSig scenario), we don't have a name - // that we can use from source. - // If this changes, the assert below will trigger and we will need to decide what to do. - // As a result, we generate another name for the native return value - // and use the same name for native and managed. - else if (info.IsNativeReturnPosition) + else if (MarshallerHelpers.IsInInvocationReturnPosition(info, _direction)) { - Debug.Assert(info.ManagedIndex == TypePositionInfo.UnsetIndex); return (InvokeReturnIdentifier, InvokeReturnIdentifierNative); } else diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DefaultMarshallingInfoParser.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DefaultMarshallingInfoParser.cs index 7a587c58d8083..a0a51229597c8 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DefaultMarshallingInfoParser.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DefaultMarshallingInfoParser.cs @@ -64,7 +64,7 @@ public static MarshallingInfoParser Create(StubEnvironment env, GeneratorDiagnos new NativeMarshallingAttributeParser(env.Compilation, diagnostics), new ComInterfaceMarshallingInfoProvider(env.Compilation)), ImmutableArray.Create( - new SafeHandleMarshallingInfoProvider(env.Compilation, method.ContainingType), + new SafeHandleMarshallingInfoProvider(env.Compilation), new ArrayMarshallingInfoProvider(env.Compilation), new CharMarshallingInfoProvider(defaultInfo), new StringMarshallingInfoProvider(env.Compilation, diagnostics, unparsedAttributeData, defaultInfo), diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/GeneratedStatements.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/GeneratedStatements.cs index 1376235bf1b47..3beed9f31c2ec 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/GeneratedStatements.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/GeneratedStatements.cs @@ -26,40 +26,41 @@ public struct GeneratedStatements public ImmutableArray ManagedExceptionCatchClauses { get; init; } - public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeContext context) + public static GeneratedStatements Create(BoundGenerators marshallers, StubIdentifierContext context) { return new GeneratedStatements { - Setup = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Setup }), - Marshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Marshal }), - Pin = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Pin }).Cast().ToImmutableArray(), - PinnedMarshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.PinnedMarshal }), + Setup = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubIdentifierContext.Stage.Setup }), + Marshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubIdentifierContext.Stage.Marshal }), + Pin = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubIdentifierContext.Stage.Pin }).Cast().ToImmutableArray(), + PinnedMarshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubIdentifierContext.Stage.PinnedMarshal }), InvokeStatement = EmptyStatement(), - Unmarshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.UnmarshalCapture }) - .AddRange(GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.Unmarshal })), - NotifyForSuccessfulInvoke = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.NotifyForSuccessfulInvoke }), - GuaranteedUnmarshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.GuaranteedUnmarshal }), - CleanupCallerAllocated = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.CleanupCallerAllocated }), - CleanupCalleeAllocated = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubCodeContext.Stage.CleanupCalleeAllocated }), + Unmarshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubIdentifierContext.Stage.UnmarshalCapture }) + .AddRange(GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubIdentifierContext.Stage.Unmarshal })), + NotifyForSuccessfulInvoke = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubIdentifierContext.Stage.NotifyForSuccessfulInvoke }), + GuaranteedUnmarshal = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubIdentifierContext.Stage.GuaranteedUnmarshal }), + CleanupCallerAllocated = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubIdentifierContext.Stage.CleanupCallerAllocated }), + CleanupCalleeAllocated = GenerateStatementsForStubContext(marshallers, context with { CurrentStage = StubIdentifierContext.Stage.CleanupCalleeAllocated }), ManagedExceptionCatchClauses = GenerateCatchClauseForManagedException(marshallers, context) }; } - public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeContext context, ExpressionSyntax expressionToInvoke) + + public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeContext codeContext, StubIdentifierContext context, ExpressionSyntax expressionToInvoke) { GeneratedStatements statements = Create(marshallers, context); - if (context.Direction == MarshalDirection.ManagedToUnmanaged) + if (codeContext.Direction == MarshalDirection.ManagedToUnmanaged) { return statements with { - InvokeStatement = GenerateStatementForNativeInvoke(marshallers, context with { CurrentStage = StubCodeContext.Stage.Invoke }, expressionToInvoke) + InvokeStatement = GenerateStatementForNativeInvoke(marshallers, context with { CurrentStage = StubIdentifierContext.Stage.Invoke }, expressionToInvoke) }; } - else if (context.Direction == MarshalDirection.UnmanagedToManaged) + else if (codeContext.Direction == MarshalDirection.UnmanagedToManaged) { return statements with { - InvokeStatement = GenerateStatementForManagedInvoke(marshallers, context with { CurrentStage = StubCodeContext.Stage.Invoke }, expressionToInvoke) + InvokeStatement = GenerateStatementForManagedInvoke(marshallers, context with { CurrentStage = StubIdentifierContext.Stage.Invoke }, expressionToInvoke) }; } else @@ -68,7 +69,7 @@ public static GeneratedStatements Create(BoundGenerators marshallers, StubCodeCo } } - private static ImmutableArray GenerateStatementsForStubContext(BoundGenerators marshallers, StubCodeContext context) + private static ImmutableArray GenerateStatementsForStubContext(BoundGenerators marshallers, StubIdentifierContext context) { ImmutableArray.Builder statementsToUpdate = ImmutableArray.CreateBuilder(); foreach (IBoundMarshallingGenerator marshaller in marshallers.SignatureMarshallers) @@ -87,9 +88,9 @@ private static ImmutableArray GenerateStatementsForStubContext( return statementsToUpdate.ToImmutable(); } - private static ExpressionStatementSyntax GenerateStatementForNativeInvoke(BoundGenerators marshallers, StubCodeContext context, ExpressionSyntax expressionToInvoke) + private static ExpressionStatementSyntax GenerateStatementForNativeInvoke(BoundGenerators marshallers, StubIdentifierContext context, ExpressionSyntax expressionToInvoke) { - if (context.CurrentStage != StubCodeContext.Stage.Invoke) + if (context.CurrentStage != StubIdentifierContext.Stage.Invoke) { throw new ArgumentException("CurrentStage must be Invoke"); } @@ -109,7 +110,7 @@ private static ExpressionStatementSyntax GenerateStatementForNativeInvoke(BoundG var (managed, native) = context.GetIdentifiers(marshallers.NativeReturnMarshaller.TypeInfo); - string targetIdentifier = marshallers.NativeReturnMarshaller.UsesNativeIdentifier(context) + string targetIdentifier = marshallers.NativeReturnMarshaller.UsesNativeIdentifier ? native : managed; @@ -121,9 +122,9 @@ private static ExpressionStatementSyntax GenerateStatementForNativeInvoke(BoundG } - private static ExpressionStatementSyntax GenerateStatementForManagedInvoke(BoundGenerators marshallers, StubCodeContext context, ExpressionSyntax expressionToInvoke) + private static ExpressionStatementSyntax GenerateStatementForManagedInvoke(BoundGenerators marshallers, StubIdentifierContext context, ExpressionSyntax expressionToInvoke) { - if (context.CurrentStage != StubCodeContext.Stage.Invoke) + if (context.CurrentStage != StubIdentifierContext.Stage.Invoke) { throw new ArgumentException("CurrentStage must be Invoke"); } @@ -148,7 +149,7 @@ private static ExpressionStatementSyntax GenerateStatementForManagedInvoke(Bound invoke)); } - private static ImmutableArray GenerateCatchClauseForManagedException(BoundGenerators marshallers, StubCodeContext context) + private static ImmutableArray GenerateCatchClauseForManagedException(BoundGenerators marshallers, StubIdentifierContext context) { if (!marshallers.HasManagedExceptionMarshaller) { @@ -161,9 +162,9 @@ private static ImmutableArray GenerateCatchClauseForManagedEx var (managed, _) = context.GetIdentifiers(managedExceptionMarshaller.TypeInfo); catchClauseBuilder.AddRange( - managedExceptionMarshaller.Generate(context with { CurrentStage = StubCodeContext.Stage.Marshal })); + managedExceptionMarshaller.Generate(context with { CurrentStage = StubIdentifierContext.Stage.Marshal })); catchClauseBuilder.AddRange( - managedExceptionMarshaller.Generate(context with { CurrentStage = StubCodeContext.Stage.PinnedMarshal })); + managedExceptionMarshaller.Generate(context with { CurrentStage = StubIdentifierContext.Stage.PinnedMarshal })); return ImmutableArray.Create( CatchClause( CatchDeclaration(TypeSyntaxes.System_Exception, Identifier(managed)), @@ -171,21 +172,21 @@ private static ImmutableArray GenerateCatchClauseForManagedEx Block(List(catchClauseBuilder)))); } - private static SyntaxTriviaList GenerateStageTrivia(StubCodeContext.Stage stage) + private static SyntaxTriviaList GenerateStageTrivia(StubIdentifierContext.Stage stage) { string comment = stage switch { - StubCodeContext.Stage.Setup => "Perform required setup.", - StubCodeContext.Stage.Marshal => "Convert managed data to native data.", - StubCodeContext.Stage.Pin => "Pin data in preparation for calling the P/Invoke.", - StubCodeContext.Stage.PinnedMarshal => "Convert managed data to native data that requires the managed data to be pinned.", - StubCodeContext.Stage.Invoke => "Call the P/Invoke.", - StubCodeContext.Stage.UnmarshalCapture => "Capture the native data into marshaller instances in case conversion to managed data throws an exception.", - StubCodeContext.Stage.Unmarshal => "Convert native data to managed data.", - StubCodeContext.Stage.CleanupCallerAllocated => "Perform cleanup of caller allocated resources.", - StubCodeContext.Stage.CleanupCalleeAllocated => "Perform cleanup of callee allocated resources.", - StubCodeContext.Stage.NotifyForSuccessfulInvoke => "Keep alive any managed objects that need to stay alive across the call.", - StubCodeContext.Stage.GuaranteedUnmarshal => "Convert native data to managed data even in the case of an exception during the non-cleanup phases.", + StubIdentifierContext.Stage.Setup => "Perform required setup.", + StubIdentifierContext.Stage.Marshal => "Convert managed data to native data.", + StubIdentifierContext.Stage.Pin => "Pin data in preparation for calling the P/Invoke.", + StubIdentifierContext.Stage.PinnedMarshal => "Convert managed data to native data that requires the managed data to be pinned.", + StubIdentifierContext.Stage.Invoke => "Call the P/Invoke.", + StubIdentifierContext.Stage.UnmarshalCapture => "Capture the native data into marshaller instances in case conversion to managed data throws an exception.", + StubIdentifierContext.Stage.Unmarshal => "Convert native data to managed data.", + StubIdentifierContext.Stage.CleanupCallerAllocated => "Perform cleanup of caller allocated resources.", + StubIdentifierContext.Stage.CleanupCalleeAllocated => "Perform cleanup of callee allocated resources.", + StubIdentifierContext.Stage.NotifyForSuccessfulInvoke => "Keep alive any managed objects that need to stay alive across the call.", + StubIdentifierContext.Stage.GuaranteedUnmarshal => "Convert native data to managed data even in the case of an exception during the non-cleanup phases.", _ => throw new ArgumentOutOfRangeException(nameof(stage)) }; diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/LinearCollectionElementIdentifierContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/LinearCollectionElementIdentifierContext.cs new file mode 100644 index 0000000000000..22e3008cf650b --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/LinearCollectionElementIdentifierContext.cs @@ -0,0 +1,68 @@ +// 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.Text; + +namespace Microsoft.Interop +{ + internal sealed record LinearCollectionElementIdentifierContext : StubIdentifierContext + { + private readonly StubIdentifierContext _globalContext; + private readonly TypePositionInfo _elementInfo; + private readonly string _managedSpanIdentifier; + private readonly string _nativeSpanIdentifier; + private readonly int _elementIndirectionLevel; + + public string IndexerIdentifier => MarshallerHelpers.GetIndexerIdentifier(_elementIndirectionLevel - 1); + + /// + /// Create a for marshalling elements of an collection. + /// + /// The type information for elements in the collection. Used to determine which identifiers to provide. + /// The indirection level of the elements in the collection. + /// The identifier of the managed value storage cast to the target element type. + /// The identifier of the native value storage cast to the target element type. + /// The context in which we are marshalling the collection that owns these elements. + public LinearCollectionElementIdentifierContext( + StubIdentifierContext globalContext, + TypePositionInfo elementInfo, + string managedSpanIdentifier, + string nativeSpanIdentifier, + int elementIndirectionLevel) + { + _globalContext = globalContext; + _elementInfo = elementInfo; + _managedSpanIdentifier = managedSpanIdentifier; + _nativeSpanIdentifier = nativeSpanIdentifier; + _elementIndirectionLevel = elementIndirectionLevel; + } + + /// + /// Get managed and native instance identifiers for the + /// + /// Object for which to get identifiers + /// Managed and native identifiers + public override (string managed, string native) GetIdentifiers(TypePositionInfo info) + { + // For this element info, index into the marshaller spans. + if (_elementInfo.PositionsEqual(info)) + { + return ( + $"{_managedSpanIdentifier}[{IndexerIdentifier}]", + $"{_nativeSpanIdentifier}[{IndexerIdentifier}]" + ); + } + // For other element infos, return the names from the global context. + else + { + return _globalContext.GetIdentifiers(info); + } + } + + public override string GetAdditionalIdentifier(TypePositionInfo info, string name) + { + return $"{_nativeSpanIdentifier}__{IndexerIdentifier}__{name}"; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/LinearCollectionElementMarshallingCodeContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/LinearCollectionElementMarshallingCodeContext.cs deleted file mode 100644 index 26990febc94b1..0000000000000 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/LinearCollectionElementMarshallingCodeContext.cs +++ /dev/null @@ -1,76 +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; - -namespace Microsoft.Interop -{ - internal sealed record LinearCollectionElementMarshallingCodeContext : StubCodeContext - { - private readonly string _managedSpanIdentifier; - private readonly string _nativeSpanIdentifier; - - public override bool SingleFrameSpansNativeContext => false; - - public override bool AdditionalTemporaryStateLivesAcrossStages => false; - - public string IndexerIdentifier { get; } - - /// - /// Create a for marshalling elements of an collection. - /// - /// The current marshalling stage. - /// The indexer in the loop to get the element to marshal from the collection. - /// The identifier of the native value storage cast to the target element type. - /// The parent context. - public LinearCollectionElementMarshallingCodeContext( - Stage currentStage, - string managedSpanIdentifier, - string nativeSpanIdentifier, - StubCodeContext parentContext) - { - CurrentStage = currentStage; - IndexerIdentifier = CalculateIndexerIdentifierBasedOnParentContext(parentContext); - _managedSpanIdentifier = managedSpanIdentifier; - _nativeSpanIdentifier = nativeSpanIdentifier; - ParentContext = parentContext; - Direction = ParentContext.Direction; - CodeEmitOptions = ParentContext.CodeEmitOptions; - } - - /// - /// Get managed and native instance identifiers for the - /// - /// Object for which to get identifiers - /// Managed and native identifiers - public override (string managed, string native) GetIdentifiers(TypePositionInfo info) - { - return ( - $"{_managedSpanIdentifier}[{IndexerIdentifier}]", - $"{_nativeSpanIdentifier}[{IndexerIdentifier}]" - ); - } - - public override string GetAdditionalIdentifier(TypePositionInfo info, string name) - { - return $"{_nativeSpanIdentifier}__{IndexerIdentifier}__{name}"; - } - - private static string CalculateIndexerIdentifierBasedOnParentContext(StubCodeContext? parentContext) - { - int i = 0; - while (parentContext is StubCodeContext context) - { - if (context is LinearCollectionElementMarshallingCodeContext) - { - i++; - } - parentContext = context.ParentContext; - } - - // Follow a progression of indexers of the following form: - // __i0, __i1, __i2, __i3, etc/ - return $"__i{i}"; - } - } -} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubGenerator.cs index 446247e8cc3be..392b83946a5b1 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubGenerator.cs @@ -45,7 +45,7 @@ public sealed class ManagedToNativeStubGenerator private readonly bool _setLastError; private readonly BoundGenerators _marshallers; - private readonly ManagedToNativeStubCodeContext _context; + private readonly DefaultIdentifierContext _context; public ManagedToNativeStubGenerator( ImmutableArray argTypes, @@ -56,18 +56,25 @@ public ManagedToNativeStubGenerator( { _setLastError = setLastError; - _context = new ManagedToNativeStubCodeContext(ReturnIdentifier, ReturnIdentifier); - _marshallers = BoundGenerators.Create(argTypes, generatorResolver, _context, new Forwarder(), out var bindingDiagnostics); + _marshallers = BoundGenerators.Create(argTypes, generatorResolver, StubCodeContext.DefaultManagedToNativeStub, new Forwarder(), out var bindingDiagnostics); diagnosticsBag.ReportGeneratorDiagnostics(bindingDiagnostics); - if (_marshallers.ManagedReturnMarshaller.UsesNativeIdentifier(_context)) + if (_marshallers.ManagedReturnMarshaller.UsesNativeIdentifier) { // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. - _context = new ManagedToNativeStubCodeContext(ReturnIdentifier, $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}"); + _context = new DefaultIdentifierContext(ReturnIdentifier, $"{ReturnIdentifier}{StubIdentifierContext.GeneratedNativeIdentifierSuffix}", MarshalDirection.ManagedToUnmanaged) + { + CodeEmitOptions = codeEmitOptions + }; + } + else + { + _context = new DefaultIdentifierContext(ReturnIdentifier, ReturnIdentifier, MarshalDirection.ManagedToUnmanaged) + { + CodeEmitOptions = codeEmitOptions + }; } - - _context = _context with { CodeEmitOptions = codeEmitOptions }; bool noMarshallingNeeded = true; @@ -101,7 +108,7 @@ public string GetNativeIdentifier(TypePositionInfo info) /// public BlockSyntax GenerateStubBody(string targetIdentifier) { - GeneratedStatements statements = GeneratedStatements.Create(_marshallers, _context, IdentifierName(targetIdentifier)); + GeneratedStatements statements = GeneratedStatements.Create(_marshallers, StubCodeContext.DefaultManagedToNativeStub, _context, IdentifierName(targetIdentifier)); bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.CleanupCallerAllocated.IsEmpty || !statements.CleanupCalleeAllocated.IsEmpty; VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForManagedToUnmanaged(_marshallers, _context, shouldInitializeVariables); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorResolver.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorResolver.cs index 0796dc42251f8..771043dcb1ae5 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorResolver.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorResolver.cs @@ -62,66 +62,28 @@ public ExpressionOrNotSupported(GeneratorDiagnostic.NotSupported notSupportedDia } } - private ExpressionOrNotSupported GetNumElementsExpressionFromMarshallingInfo(TypePositionInfo info, CountInfo count, StubCodeContext context) + private GeneratorDiagnostic.NotSupported? ValidateCountInfo(TypePositionInfo info, CountInfo count, StubCodeContext context, out bool countInfoRequiresCast) { - switch (count) - { - case SizeAndParamIndexInfo(int size, SizeAndParamIndexInfo.UnspecifiedParam): - return new(GetConstSizeExpression(size)); - case ConstSizeCountInfo(int size): - return new(GetConstSizeExpression(size)); - case SizeAndParamIndexInfo(SizeAndParamIndexInfo.UnspecifiedConstSize, TypePositionInfo param): - { - return GetExpressionForParam(param, out bool isIntType) switch - { - (ExpressionSyntax expr, null) => new(isIntType ? expr : CheckedExpression(SyntaxKind.CheckedExpression, expr)), - (null, GeneratorDiagnostic.NotSupported notSupported) => new(notSupported), - (not null, not null) => throw new UnreachableException() - }; - } - case SizeAndParamIndexInfo(int size, TypePositionInfo param): - return GetExpressionForParam(param, out bool _) switch - { - (ExpressionSyntax expr, null) => new( - CheckedExpression(SyntaxKind.CheckedExpression, - BinaryExpression(SyntaxKind.AddExpression, - GetConstSizeExpression(size), - expr))), - (null, GeneratorDiagnostic.NotSupported notSupported) => new(notSupported), - (not null, not null) => throw new UnreachableException() - }; - case CountElementCountInfo(TypePositionInfo elementInfo): - { - return GetExpressionForParam(elementInfo, out bool isIntType) switch - { - (ExpressionSyntax expr, null) => new(isIntType ? expr : CheckedExpression(SyntaxKind.CheckedExpression, expr)), - (null, GeneratorDiagnostic.NotSupported notSupported) => new(notSupported), - (not null, not null) => throw new UnreachableException() - }; - } - default: - return new(new GeneratorDiagnostic.NotSupported(info, context) - { - NotSupportedDetails = SR.ArraySizeMustBeSpecified - }); - } - - static LiteralExpressionSyntax GetConstSizeExpression(int size) - { - return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(size)); - } + countInfoRequiresCast = false; + return count switch + { + SizeAndParamIndexInfo(_, SizeAndParamIndexInfo.UnspecifiedParam) => null, + ConstSizeCountInfo => null, + SizeAndParamIndexInfo(_, TypePositionInfo param) => ValidateNumElementsExpression(param, out countInfoRequiresCast), + CountElementCountInfo(TypePositionInfo elementInfo) => ValidateNumElementsExpression(elementInfo, out countInfoRequiresCast), + _ => new GeneratorDiagnostic.NotSupported(info) + { + NotSupportedDetails = SR.ArraySizeMustBeSpecified + }, + }; - ExpressionOrNotSupported GetExpressionForParam(TypePositionInfo paramInfo, out bool isIntType) + GeneratorDiagnostic.NotSupported? ValidateNumElementsExpression(TypePositionInfo paramInfo, out bool requiresCast) { - ExpressionSyntax numElementsExpression = GetIndexedNumElementsExpression( - context, - paramInfo, - out int numIndirectionLevels); - + requiresCast = false; ManagedTypeInfo type = paramInfo.ManagedType; MarshallingInfo marshallingInfo = paramInfo.MarshallingAttributeInfo; - for (int i = 0; i < numIndirectionLevels; i++) + for (int i = 0; i < context.ElementIndirectionLevel; i++) { if (marshallingInfo is NativeLinearCollectionMarshallingInfo collectionInfo) { @@ -131,59 +93,24 @@ ExpressionOrNotSupported GetExpressionForParam(TypePositionInfo paramInfo, out b } else { - isIntType = false; - return new(new GeneratorDiagnostic.NotSupported(info, context) + return new GeneratorDiagnostic.NotSupported(info) { NotSupportedDetails = SR.CollectionSizeParamTypeMustBeIntegral - }); + }; } } if (type is not SpecialTypeInfo specialType || !specialType.SpecialType.IsIntegralType()) { - isIntType = false; - return new(new GeneratorDiagnostic.NotSupported(info, context) + return new GeneratorDiagnostic.NotSupported(info) { NotSupportedDetails = SR.CollectionSizeParamTypeMustBeIntegral - }); - } - - isIntType = specialType.SpecialType == SpecialType.System_Int32; - return new(isIntType - ? numElementsExpression - : CastExpression( - PredefinedType(Token(SyntaxKind.IntKeyword)), - ParenthesizedExpression(numElementsExpression))); - } - - static ExpressionSyntax GetIndexedNumElementsExpression(StubCodeContext context, TypePositionInfo numElementsInfo, out int numIndirectionLevels) - { - Stack indexerStack = new(); - - StubCodeContext? currentContext = context; - StubCodeContext lastContext = null!; - - while (currentContext is not null) - { - if (currentContext is LinearCollectionElementMarshallingCodeContext collectionContext) - { - indexerStack.Push(collectionContext.IndexerIdentifier); - } - lastContext = currentContext; - currentContext = currentContext.ParentContext; + }; } - numIndirectionLevels = indexerStack.Count; - - ExpressionSyntax indexedNumElements = IdentifierName(lastContext.GetIdentifiers(numElementsInfo).managed); - while (indexerStack.Count > 0) - { - NameSyntax indexer = IdentifierName(indexerStack.Pop()); - indexedNumElements = ElementAccessExpression(indexedNumElements) - .AddArgumentListArguments(Argument(indexer)); - } + requiresCast = specialType.SpecialType != SpecialType.System_Int32; - return indexedNumElements; + return null; } } @@ -218,13 +145,13 @@ private ResolvedGenerator CreateCustomNativeTypeMarshaller(TypePositionInfo info { if (ValidateCustomNativeTypeMarshallingSupported(info, context, marshalInfo) is GeneratorDiagnostic.NotSupported diagnostic) { - return ResolvedGenerator.NotSupported(info, diagnostic); + return ResolvedGenerator.NotSupported(info, context, diagnostic); } CustomTypeMarshallerData marshallerData = GetMarshallerDataForTypePositionInfo(marshalInfo.Marshallers, info, context); if (!ValidateRuntimeMarshallingOptions(marshallerData)) { - return ResolvedGenerator.NotSupported(info, new(info, context) + return ResolvedGenerator.NotSupported(info, context, new(info) { NotSupportedDetails = SR.RuntimeMarshallingMustBeDisabled, DiagnosticProperties = AddDisableRuntimeMarshallingAttributeProperties @@ -238,13 +165,13 @@ private ResolvedGenerator CreateCustomNativeTypeMarshaller(TypePositionInfo info ICustomTypeMarshallingStrategy marshallingStrategy; if (marshallerData.HasState) { - marshallingStrategy = new StatefulValueMarshalling(marshallerData.MarshallerType, marshallerData.NativeType, marshallerData.Shape); + marshallingStrategy = new StatefulValueMarshalling(info, context, marshallerData.MarshallerType, marshallerData.NativeType, marshallerData.Shape); if (marshallerData.Shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) marshallingStrategy = new StatefulCallerAllocatedBufferMarshalling(marshallingStrategy, marshallerData.MarshallerType.Syntax, marshallerData.BufferElementType.Syntax); } else { - marshallingStrategy = new StatelessValueMarshalling(marshallerData.MarshallerType.Syntax, marshallerData.NativeType, marshallerData.Shape); + marshallingStrategy = new StatelessValueMarshalling(info, context, marshallerData.MarshallerType.Syntax, marshallerData.NativeType, marshallerData.Shape); if (marshallerData.Shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) marshallingStrategy = new StatelessCallerAllocatedBufferMarshalling(marshallingStrategy, marshallerData.MarshallerType.Syntax, marshallerData.BufferElementType.Syntax, isLinearCollectionMarshalling: false); @@ -266,7 +193,7 @@ private ResolvedGenerator CreateCustomNativeTypeMarshaller(TypePositionInfo info } } - IBoundMarshallingGenerator marshallingGenerator = new CustomTypeMarshallingGenerator(info, marshallingStrategy, ByValueMarshalKindSupportDescriptor.Default, marshallerData.Shape.HasFlag(MarshallerShape.StatelessPinnableReference)); + IBoundMarshallingGenerator marshallingGenerator = new CustomTypeMarshallingGenerator(marshallingStrategy, ByValueMarshalKindSupportDescriptor.Default, marshallerData.Shape.HasFlag(MarshallerShape.StatelessPinnableReference)); if (marshallerData.Shape.HasFlag(MarshallerShape.StatelessPinnableReference)) { @@ -286,11 +213,12 @@ private ResolvedGenerator CreateNativeCollectionMarshaller( { InstanceIdentifier = info.InstanceIdentifier, ManagedIndex = info.ManagedIndex, + NativeIndex = info.NativeIndex, RefKind = CreateElementRefKind(info.RefKind, info.ByValueContentsMarshalKind) }; ResolvedGenerator resolvedElementMarshaller = _elementGeneratorResolver.Create( elementInfo, - new LinearCollectionElementMarshallingCodeContext(StubCodeContext.Stage.Setup, string.Empty, string.Empty, context)); + StubCodeContext.CreateElementMarshallingContext(context)); if (!resolvedElementMarshaller.IsResolvedWithoutErrors) { @@ -298,16 +226,16 @@ private ResolvedGenerator CreateNativeCollectionMarshaller( } IBoundMarshallingGenerator elementMarshaller = resolvedElementMarshaller.Generator; - ExpressionSyntax numElementsExpression = LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)); + CountInfo countInfo = marshalInfo.ElementCountInfo; + bool countInfoRequiresCast = false; if (MarshallerHelpers.GetMarshalDirection(info, context) != MarshalDirection.ManagedToUnmanaged) { // In this case, we need a numElementsExpression supplied from metadata, so we'll calculate it here. - ExpressionOrNotSupported numElementsExpressionResult = GetNumElementsExpressionFromMarshallingInfo(info, marshalInfo.ElementCountInfo, context); - if (numElementsExpressionResult is (_, GeneratorDiagnostic.NotSupported notSupportedDiagnostic)) + GeneratorDiagnostic.NotSupported? countInfoDiagnostic = ValidateCountInfo(info, countInfo, context, out countInfoRequiresCast); + if (countInfoDiagnostic is not null) { - return ResolvedGenerator.NotSupported(info, notSupportedDiagnostic); + return ResolvedGenerator.NotSupported(info, context, countInfoDiagnostic); } - numElementsExpression = numElementsExpressionResult.Expression; } // Insert the unmanaged element type into the marshaller type @@ -331,7 +259,7 @@ private ResolvedGenerator CreateNativeCollectionMarshaller( if (marshallerData.HasState) { - marshallingStrategy = new StatefulValueMarshalling(marshallerType, nativeType, marshallerData.Shape); + marshallingStrategy = new StatefulValueMarshalling(info, context, marshallerType, nativeType, marshallerData.Shape); if (marshallerData.Shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) { // Check if the buffer element type is actually the unmanaged element type @@ -342,7 +270,7 @@ private ResolvedGenerator CreateNativeCollectionMarshaller( } var freeStrategy = GetFreeStrategy(info, context); - IElementsMarshallingCollectionSource collectionSource = new StatefulLinearCollectionSource(); + IElementsMarshallingCollectionSource collectionSource = new StatefulLinearCollectionSource(info, context); ElementsMarshalling elementsMarshalling = CreateElementsMarshalling(marshallerData, elementMarshaller, unmanagedElementType, collectionSource); if (freeStrategy == FreeStrategy.FreeOriginal) @@ -350,7 +278,7 @@ private ResolvedGenerator CreateNativeCollectionMarshaller( marshallingStrategy = new UnmanagedToManagedOwnershipTrackingStrategy(marshallingStrategy); } - marshallingStrategy = new StatefulLinearCollectionMarshalling(marshallingStrategy, marshallerData.Shape, numElementsExpression, elementsMarshalling, freeStrategy != FreeStrategy.NoFree); + marshallingStrategy = new StatefulLinearCollectionMarshalling(marshallingStrategy, marshallerData.Shape, countInfo, countInfoRequiresCast, elementsMarshalling, freeStrategy != FreeStrategy.NoFree); if (freeStrategy == FreeStrategy.FreeOriginal) { @@ -364,11 +292,11 @@ private ResolvedGenerator CreateNativeCollectionMarshaller( } else { - marshallingStrategy = new StatelessLinearCollectionSpaceAllocator(marshallerTypeSyntax, nativeType, marshallerData.Shape, numElementsExpression); + marshallingStrategy = new StatelessLinearCollectionSpaceAllocator(info, context, marshallerTypeSyntax, nativeType, marshallerData.Shape, countInfo, countInfoRequiresCast); var freeStrategy = GetFreeStrategy(info, context); - IElementsMarshallingCollectionSource collectionSource = new StatelessLinearCollectionSource(marshallerTypeSyntax); + IElementsMarshallingCollectionSource collectionSource = new StatelessLinearCollectionSource(info, context, marshallerTypeSyntax); if (freeStrategy == FreeStrategy.FreeOriginal) { marshallingStrategy = new UnmanagedToManagedOwnershipTrackingStrategy(marshallingStrategy); @@ -376,7 +304,7 @@ private ResolvedGenerator CreateNativeCollectionMarshaller( ElementsMarshalling elementsMarshalling = CreateElementsMarshalling(marshallerData, elementMarshaller, unmanagedElementType, collectionSource); - marshallingStrategy = new StatelessLinearCollectionMarshalling(marshallingStrategy, elementsMarshalling, nativeType, marshallerData.Shape, numElementsExpression, freeStrategy != FreeStrategy.NoFree); + marshallingStrategy = new StatelessLinearCollectionMarshalling(marshallingStrategy, elementsMarshalling, nativeType, marshallerData.Shape, countInfo, countInfoRequiresCast, freeStrategy != FreeStrategy.NoFree); if (marshallerData.Shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) { @@ -411,7 +339,7 @@ private ResolvedGenerator CreateNativeCollectionMarshaller( // Elements in the collection must be blittable to use the pinnable marshaller. bool isPinned = marshallerData.Shape.HasFlag(MarshallerShape.StatelessPinnableReference) && elementIsBlittable; - IBoundMarshallingGenerator marshallingGenerator = new CustomTypeMarshallingGenerator(info, marshallingStrategy, byValueMarshalKindSupport, isPinned); + IBoundMarshallingGenerator marshallingGenerator = new CustomTypeMarshallingGenerator(marshallingStrategy, byValueMarshalKindSupport, isPinned); if (isPinned) { marshallingGenerator = new StaticPinnableManagedValueMarshaller(marshallingGenerator, marshallerTypeSyntax); @@ -493,7 +421,7 @@ private static TypeSyntax ReplacePlaceholderSyntaxWithUnmanagedTypeSyntax( if (elementDirection == MarshalDirection.UnmanagedToManaged && !marshalInfo.Marshallers.IsDefinedOrDefault(Options.UnmanagedToManagedMode)) { - return new(info, context) + return new(info) { NotSupportedDetails = SR.Format(SR.UnmanagedToManagedMissingRequiredMarshaller, marshalInfo.EntryPointType.FullTypeName) }; @@ -503,7 +431,7 @@ private static TypeSyntax ReplacePlaceholderSyntaxWithUnmanagedTypeSyntax( if (elementDirection == MarshalDirection.Bidirectional && !marshalInfo.Marshallers.IsDefinedOrDefault(Options.BidirectionalMode)) { - return new(info, context) + return new(info) { NotSupportedDetails = SR.Format(SR.BidirectionalMissingRequiredMarshaller, marshalInfo.EntryPointType.FullTypeName) }; @@ -513,7 +441,7 @@ private static TypeSyntax ReplacePlaceholderSyntaxWithUnmanagedTypeSyntax( if (elementDirection == MarshalDirection.ManagedToUnmanaged && !marshalInfo.Marshallers.IsDefinedOrDefault(Options.ManagedToUnmanagedMode)) { - return new(info, context) + return new(info) { NotSupportedDetails = SR.Format(SR.ManagedToUnmanagedMissingRequiredMarshaller, marshalInfo.EntryPointType.FullTypeName) }; diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs index d9efb372bc52b..99fc1329955df 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs @@ -34,16 +34,16 @@ public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, Stu return ValueBoundaryBehavior.AddressOfNativeIdentifier; } - public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) { - if (!info.IsByRef || context.IsInStubReturnPosition(info)) + if (!info.IsByRef || codeContext.IsInStubReturnPosition(info)) yield break; (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); - if (context.SingleFrameSpansNativeContext) + if (codeContext.SingleFrameSpansNativeContext) { - if (context.CurrentStage == StubCodeContext.Stage.Pin) + if (context.CurrentStage == StubIdentifierContext.Stage.Pin) { yield return FixedStatement( VariableDeclaration( @@ -62,14 +62,14 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont yield break; } - MarshalDirection elementMarshalling = MarshallerHelpers.GetMarshalDirection(info, context); + MarshalDirection direction = MarshallerHelpers.GetMarshalDirection(info, codeContext); switch (context.CurrentStage) { - case StubCodeContext.Stage.Setup: + case StubIdentifierContext.Stage.Setup: break; - case StubCodeContext.Stage.Marshal: - if (elementMarshalling is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional && info.IsByRef) + case StubIdentifierContext.Stage.Marshal: + if (direction is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional && info.IsByRef) { yield return ExpressionStatement( AssignmentExpression( @@ -79,8 +79,8 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont } break; - case StubCodeContext.Stage.Unmarshal: - if (elementMarshalling is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional && info.IsByRef) + case StubIdentifierContext.Stage.Unmarshal: + if (direction is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional && info.IsByRef) { yield return ExpressionStatement( AssignmentExpression( @@ -99,7 +99,7 @@ public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) return info.IsByRef && !context.IsInStubReturnPosition(info) && !context.SingleFrameSpansNativeContext; } - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) + => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshallerResolver.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshallerResolver.cs index 239b446c1c8ad..602753d4e509e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshallerResolver.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshallerResolver.cs @@ -26,12 +26,12 @@ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) { if (runtimeMarshallingDisabled || blittableInfo.IsStrictlyBlittable) { - return ResolvedGenerator.Resolved(s_blittable.Bind(info)); + return ResolvedGenerator.Resolved(s_blittable.Bind(info, context)); } return ResolvedGenerator.NotSupported( info, - new GeneratorDiagnostic.NotSupported(info, context) + context, new GeneratorDiagnostic.NotSupported(info) { NotSupportedDetails = SR.RuntimeMarshallingMustBeDisabled, DiagnosticProperties = AddDisableRuntimeMarshallingAttributeProperties diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs index e50484399c980..5b272699863fc 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs @@ -47,15 +47,15 @@ public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, Stu return ValueBoundaryBehavior.NativeIdentifier; } - public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) { - MarshalDirection elementMarshalDirection = MarshallerHelpers.GetMarshalDirection(info, context); + MarshalDirection elementMarshalDirection = MarshallerHelpers.GetMarshalDirection(info, codeContext); (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); switch (context.CurrentStage) { - case StubCodeContext.Stage.Setup: + case StubIdentifierContext.Stage.Setup: break; - case StubCodeContext.Stage.Marshal: + case StubIdentifierContext.Stage.Marshal: // = ()( ? _trueValue : _falseValue); if (elementMarshalDirection is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) { @@ -72,7 +72,7 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont } break; - case StubCodeContext.Stage.Unmarshal: + case StubIdentifierContext.Stage.Unmarshal: if (elementMarshalDirection is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional) { // = == _trueValue; @@ -97,8 +97,8 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) + => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); } /// diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BreakingChangeDetector.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BreakingChangeDetector.cs index 02e73d70b011e..6906b9b2bcc05 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BreakingChangeDetector.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BreakingChangeDetector.cs @@ -29,7 +29,7 @@ public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) gen = ResolvedGenerator.ResolvedWithDiagnostics( gen.Generator, gen.Diagnostics.Add( - new GeneratorDiagnostic.NotRecommended(info, context) + new GeneratorDiagnostic.NotRecommended(info) { Details = SR.InVariantShouldBeRef })); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs index 867bfb4102cb1..0f3b07fadf7d2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs @@ -22,10 +22,10 @@ public ByValueContentsMarshalKindValidator(IMarshallingGeneratorResolver inner) public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) { ResolvedGenerator generator = _inner.Create(info, context); - return generator.IsResolvedWithoutErrors ? ValidateByValueMarshalKind(context, generator) : generator; + return generator.IsResolvedWithoutErrors ? ValidateByValueMarshalKind(generator, context) : generator; } - private static ResolvedGenerator ValidateByValueMarshalKind(StubCodeContext context, ResolvedGenerator generator) + private static ResolvedGenerator ValidateByValueMarshalKind(ResolvedGenerator generator, StubCodeContext context) { if (generator.Generator.IsForwarder()) { @@ -34,12 +34,12 @@ private static ResolvedGenerator ValidateByValueMarshalKind(StubCodeContext cont return generator; } - var support = generator.Generator.SupportsByValueMarshalKind(generator.Generator.TypeInfo.ByValueContentsMarshalKind, context, out GeneratorDiagnostic? diagnostic); + var support = generator.Generator.SupportsByValueMarshalKind(generator.Generator.TypeInfo.ByValueContentsMarshalKind, out GeneratorDiagnostic? diagnostic); Debug.Assert(support == ByValueMarshalKindSupport.Supported || diagnostic is not null); return support switch { ByValueMarshalKindSupport.Supported => generator, - ByValueMarshalKindSupport.NotSupported => ResolvedGenerator.ResolvedWithDiagnostics(s_forwarder.Bind(generator.Generator.TypeInfo), generator.Diagnostics.Add(diagnostic!)), + ByValueMarshalKindSupport.NotSupported => ResolvedGenerator.ResolvedWithDiagnostics(s_forwarder.Bind(generator.Generator.TypeInfo, context), generator.Diagnostics.Add(diagnostic!)), ByValueMarshalKindSupport.Unnecessary => generator with { Diagnostics = generator.Diagnostics.Add(diagnostic!) }, ByValueMarshalKindSupport.NotRecommended => generator with { Diagnostics = generator.Diagnostics.Add(diagnostic!) }, _ => throw new UnreachableException() diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs index c2329f1e1eefc..d8aab60196a10 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueMarshalKindSupportDescriptor.cs @@ -9,27 +9,26 @@ namespace Microsoft.Interop { public record struct ByValueMarshalKindSupportInfo(ByValueMarshalKindSupport Support, string? details) { - public ByValueMarshalKindSupport GetSupport(TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) + public ByValueMarshalKindSupport GetSupport(TypePositionInfo info, out GeneratorDiagnostic? diagnostic) { diagnostic = Support switch { ByValueMarshalKindSupport.Supported => null, ByValueMarshalKindSupport.NotRecommended => - new GeneratorDiagnostic.NotRecommended(info, context) + new GeneratorDiagnostic.NotRecommended(info) { Details = details }, ByValueMarshalKindSupport.Unnecessary => new GeneratorDiagnostic.UnnecessaryData( info, - context, ImmutableArray.Create(info.ByValueMarshalAttributeLocations.OutLocation)) { UnnecessaryDataName = SR.InOutAttributes, UnnecessaryDataDetails = details }, ByValueMarshalKindSupport.NotSupported => - new GeneratorDiagnostic.NotSupported(info, context) + new GeneratorDiagnostic.NotSupported(info) { NotSupportedDetails = details }, @@ -40,7 +39,7 @@ public ByValueMarshalKindSupport GetSupport(TypePositionInfo info, StubCodeConte } /// - /// Provides an implementation of through + /// Provides an implementation of through /// public record ByValueMarshalKindSupportDescriptor( ByValueMarshalKindSupportInfo DefaultSupport, @@ -69,14 +68,14 @@ public record ByValueMarshalKindSupportDescriptor( /// /// Returns the support for the ByValueContentsMarshalKind, and if it is not , diagnostic is not null /// - public ByValueMarshalKindSupport GetSupport(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) + public ByValueMarshalKindSupport GetSupport(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) { if (info.IsByRef) { // ByRef with ByValue attributes is not allowed if (marshalKind != ByValueContentsMarshalKind.Default) { - diagnostic = new GeneratorDiagnostic.NotSupported(info, context) + diagnostic = new GeneratorDiagnostic.NotSupported(info) { NotSupportedDetails = SR.InOutAttributeByRefNotSupported }; @@ -96,10 +95,10 @@ public ByValueMarshalKindSupport GetSupport(ByValueContentsMarshalKind marshalKi return marshalKind switch { - ByValueContentsMarshalKind.Default => DefaultSupport.GetSupport(info, context, out diagnostic), - ByValueContentsMarshalKind.In => InSupport.GetSupport(info, context, out diagnostic), - ByValueContentsMarshalKind.Out => OutSupport.GetSupport(info, context, out diagnostic), - ByValueContentsMarshalKind.InOut => InOutSupport.GetSupport(info, context, out diagnostic), + ByValueContentsMarshalKind.Default => DefaultSupport.GetSupport(info, out diagnostic), + ByValueContentsMarshalKind.In => InSupport.GetSupport(info, out diagnostic), + ByValueContentsMarshalKind.Out => OutSupport.GetSupport(info, out diagnostic), + ByValueContentsMarshalKind.InOut => InOutSupport.GetSupport(info, out diagnostic), _ => throw new UnreachableException() }; } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs index 80b9a53d9fb7e..829ccb985102c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs @@ -44,13 +44,13 @@ public SignatureBehavior GetNativeSignatureBehavior(TypePositionInfo info) return info.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; } - public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) { (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); - if (IsPinningPathSupported(info, context)) + if (IsPinningPathSupported(info, codeContext)) { - if (context.CurrentStage == StubCodeContext.Stage.Pin) + if (context.CurrentStage == StubIdentifierContext.Stage.Pin) { // fixed (char* = &) yield return FixedStatement( @@ -79,13 +79,13 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont yield break; } - MarshalDirection elementMarshalDirection = MarshallerHelpers.GetMarshalDirection(info, context); + MarshalDirection elementMarshalDirection = MarshallerHelpers.GetMarshalDirection(info, codeContext); switch (context.CurrentStage) { - case StubCodeContext.Stage.Setup: + case StubIdentifierContext.Stage.Setup: break; - case StubCodeContext.Stage.Marshal: + case StubIdentifierContext.Stage.Marshal: if (elementMarshalDirection is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) { // There's an implicit conversion from char to ushort, @@ -101,7 +101,7 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont } break; - case StubCodeContext.Stage.Unmarshal: + case StubIdentifierContext.Stage.Unmarshal: if (elementMarshalDirection is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional) { yield return ExpressionStatement( @@ -134,9 +134,9 @@ private static bool IsPinningPathSupported(TypePositionInfo info, StubCodeContex } private static string PinnedIdentifier(string identifier) => $"{identifier}__pinned"; - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) { - return ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic); + return ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshallingGeneratorResolver.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshallingGeneratorResolver.cs index f4e7092a10194..9a22319125775 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshallingGeneratorResolver.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshallingGeneratorResolver.cs @@ -37,7 +37,7 @@ private ResolvedGenerator CreateCharMarshaller(TypePositionInfo info, StubCodeCo if (marshalInfo is NoMarshallingInfo) { // [Compat] Require explicit marshalling information. - return ResolvedGenerator.NotSupported(info, new(info, context) + return ResolvedGenerator.NotSupported(info, context, new(info) { NotSupportedDetails = string.Format(SR.MarshallingStringOrCharAsUndefinedNotSupported, _stringMarshallingAttribute) }); @@ -50,7 +50,7 @@ private ResolvedGenerator CreateCharMarshaller(TypePositionInfo info, StubCodeCo { case UnmanagedType.I2: case UnmanagedType.U2: - return ResolvedGenerator.Resolved(_useBlittableMarshallerForUtf16 ? s_blittable.Bind(info) : s_utf16Char.Bind(info)); + return ResolvedGenerator.Resolved(_useBlittableMarshallerForUtf16 ? s_blittable.Bind(info, context) : s_utf16Char.Bind(info, context)); } } else if (marshalInfo is MarshallingInfoStringSupport marshalStringInfo) @@ -58,21 +58,21 @@ private ResolvedGenerator CreateCharMarshaller(TypePositionInfo info, StubCodeCo switch (marshalStringInfo.CharEncoding) { case CharEncoding.Utf16: - return ResolvedGenerator.Resolved(_useBlittableMarshallerForUtf16 ? s_blittable.Bind(info) : s_utf16Char.Bind(info)); + return ResolvedGenerator.Resolved(_useBlittableMarshallerForUtf16 ? s_blittable.Bind(info, context) : s_utf16Char.Bind(info, context)); case CharEncoding.Utf8: - return ResolvedGenerator.NotSupported(info, new(info, context) // [Compat] UTF-8 is not supported for char + return ResolvedGenerator.NotSupported(info, context, new(info) // [Compat] UTF-8 is not supported for char { NotSupportedDetails = SR.Format(SR.MarshallingCharAsSpecifiedStringMarshallingNotSupported, nameof(CharEncoding.Utf8)) }); case CharEncoding.Custom: - return ResolvedGenerator.NotSupported(info, new(info, context) + return ResolvedGenerator.NotSupported(info, context, new(info) { NotSupportedDetails = SR.MarshallingCharAsStringMarshallingCustomNotSupported }); } } - return ResolvedGenerator.NotSupported(info, new(info, context)); + return ResolvedGenerator.NotSupported(info, context, new(info)); } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomTypeMarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomTypeMarshallingGenerator.cs index 5b59bdc655b8b..259f1e3bd977c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomTypeMarshallingGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomTypeMarshallingGenerator.cs @@ -10,78 +10,77 @@ namespace Microsoft.Interop /// /// Implements generating code for an instance. /// - internal sealed class CustomTypeMarshallingGenerator(TypePositionInfo info, ICustomTypeMarshallingStrategy nativeTypeMarshaller, ByValueMarshalKindSupportDescriptor byValueContentsMarshallingSupport, bool isPinned) + internal sealed class CustomTypeMarshallingGenerator(ICustomTypeMarshallingStrategy nativeTypeMarshaller, ByValueMarshalKindSupportDescriptor byValueContentsMarshallingSupport, bool isPinned) : IBoundMarshallingGenerator { - public ValueBoundaryBehavior GetValueBoundaryBehavior(StubCodeContext context) - { - return info.IsByRef ? ValueBoundaryBehavior.AddressOfNativeIdentifier : ValueBoundaryBehavior.NativeIdentifier; - } + public ValueBoundaryBehavior ValueBoundaryBehavior => TypeInfo.IsByRef ? ValueBoundaryBehavior.AddressOfNativeIdentifier : ValueBoundaryBehavior.NativeIdentifier; - public ManagedTypeInfo NativeType => nativeTypeMarshaller.AsNativeType(info); + public ManagedTypeInfo NativeType => nativeTypeMarshaller.NativeType; - public SignatureBehavior NativeSignatureBehavior => info.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; + public SignatureBehavior NativeSignatureBehavior => TypeInfo.IsByRef ? SignatureBehavior.PointerToNativeType : SignatureBehavior.NativeType; - public TypePositionInfo TypeInfo => info; + public TypePositionInfo TypeInfo => nativeTypeMarshaller.TypeInfo; - public IEnumerable Generate(StubCodeContext context) + public StubCodeContext CodeContext => nativeTypeMarshaller.CodeContext; + + public IEnumerable Generate(StubIdentifierContext context) { - MarshalDirection elementMarshalDirection = MarshallerHelpers.GetMarshalDirection(info, context); + MarshalDirection elementMarshalDirection = MarshallerHelpers.GetMarshalDirection(TypeInfo, CodeContext); // Although custom native type marshalling doesn't support [In] or [Out] by value marshalling, // other marshallers that wrap this one might, so we handle the correct cases here. switch (context.CurrentStage) { - case StubCodeContext.Stage.Setup: - return nativeTypeMarshaller.GenerateSetupStatements(info, context); - case StubCodeContext.Stage.Marshal: + case StubIdentifierContext.Stage.Setup: + return nativeTypeMarshaller.GenerateSetupStatements(context); + case StubIdentifierContext.Stage.Marshal: if (elementMarshalDirection is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional - || (context.Direction == MarshalDirection.UnmanagedToManaged && ShouldGenerateByValueOutMarshalling(context))) + || (CodeContext.Direction == MarshalDirection.UnmanagedToManaged && ShouldGenerateByValueOutMarshalling)) { - return nativeTypeMarshaller.GenerateMarshalStatements(info, context); + return nativeTypeMarshaller.GenerateMarshalStatements(context); } break; - case StubCodeContext.Stage.Pin: - if (context.SingleFrameSpansNativeContext && elementMarshalDirection is MarshalDirection.ManagedToUnmanaged) + case StubIdentifierContext.Stage.Pin: + if (CodeContext.SingleFrameSpansNativeContext && elementMarshalDirection is MarshalDirection.ManagedToUnmanaged) { - return nativeTypeMarshaller.GeneratePinStatements(info, context); + return nativeTypeMarshaller.GeneratePinStatements(context); } break; - case StubCodeContext.Stage.PinnedMarshal: + case StubIdentifierContext.Stage.PinnedMarshal: if (elementMarshalDirection is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) { - return nativeTypeMarshaller.GeneratePinnedMarshalStatements(info, context); + return nativeTypeMarshaller.GeneratePinnedMarshalStatements(context); } break; - case StubCodeContext.Stage.NotifyForSuccessfulInvoke: + case StubIdentifierContext.Stage.NotifyForSuccessfulInvoke: if (elementMarshalDirection is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) { - return nativeTypeMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); + return nativeTypeMarshaller.GenerateNotifyForSuccessfulInvokeStatements(context); } break; - case StubCodeContext.Stage.UnmarshalCapture: + case StubIdentifierContext.Stage.UnmarshalCapture: if (elementMarshalDirection is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional) { - return nativeTypeMarshaller.GenerateUnmarshalCaptureStatements(info, context); + return nativeTypeMarshaller.GenerateUnmarshalCaptureStatements(context); } break; - case StubCodeContext.Stage.Unmarshal: + case StubIdentifierContext.Stage.Unmarshal: if (elementMarshalDirection is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional - || (context.Direction == MarshalDirection.ManagedToUnmanaged && ShouldGenerateByValueOutMarshalling(context))) + || (CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && ShouldGenerateByValueOutMarshalling)) { - return nativeTypeMarshaller.GenerateUnmarshalStatements(info, context); + return nativeTypeMarshaller.GenerateUnmarshalStatements(context); } break; - case StubCodeContext.Stage.GuaranteedUnmarshal: + case StubIdentifierContext.Stage.GuaranteedUnmarshal: if (elementMarshalDirection is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional - || (context.Direction == MarshalDirection.ManagedToUnmanaged && ShouldGenerateByValueOutMarshalling(context))) + || (CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && ShouldGenerateByValueOutMarshalling)) { - return nativeTypeMarshaller.GenerateGuaranteedUnmarshalStatements(info, context); + return nativeTypeMarshaller.GenerateGuaranteedUnmarshalStatements(context); } break; - case StubCodeContext.Stage.CleanupCallerAllocated: - return nativeTypeMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(info, context); - case StubCodeContext.Stage.CleanupCalleeAllocated: - return nativeTypeMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(info, context); + case StubIdentifierContext.Stage.CleanupCallerAllocated: + return nativeTypeMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(context); + case StubIdentifierContext.Stage.CleanupCalleeAllocated: + return nativeTypeMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(context); default: break; } @@ -89,25 +88,17 @@ public IEnumerable Generate(StubCodeContext context) return Array.Empty(); } - private bool ShouldGenerateByValueOutMarshalling(StubCodeContext context) - { - return - info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out) - && byValueContentsMarshallingSupport.GetSupport(info.ByValueContentsMarshalKind, info, context, out _) != ByValueMarshalKindSupport.NotSupported - && !info.IsByRef + private bool ShouldGenerateByValueOutMarshalling + => TypeInfo.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out) + && byValueContentsMarshallingSupport.GetSupport(TypeInfo.ByValueContentsMarshalKind, TypeInfo, out _) != ByValueMarshalKindSupport.NotSupported + && !TypeInfo.IsByRef && !isPinned; - } - public bool UsesNativeIdentifier(StubCodeContext context) - { - return nativeTypeMarshaller.UsesNativeIdentifier(info, context); - } + public bool UsesNativeIdentifier => nativeTypeMarshaller.UsesNativeIdentifier; - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context, out GeneratorDiagnostic? diagnostic) + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, out GeneratorDiagnostic? diagnostic) { - return byValueContentsMarshallingSupport.GetSupport(marshalKind, info, context, out diagnostic); + return byValueContentsMarshallingSupport.GetSupport(marshalKind, TypeInfo, out diagnostic); } - - public IBoundMarshallingGenerator Rebind(TypePositionInfo newInfo) => new CustomTypeMarshallingGenerator(newInfo, nativeTypeMarshaller, byValueContentsMarshallingSupport, isPinned); } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs index 318af7b4e3f59..180442555d009 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs @@ -27,15 +27,15 @@ public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, Stu return info.IsByRef ? ValueBoundaryBehavior.AddressOfNativeIdentifier : ValueBoundaryBehavior.NativeIdentifier; } - public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) { - MarshalDirection elementMarshalDirection = MarshallerHelpers.GetMarshalDirection(info, context); + MarshalDirection elementMarshalDirection = MarshallerHelpers.GetMarshalDirection(info, codeContext); (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); switch (context.CurrentStage) { - case StubCodeContext.Stage.Setup: + case StubIdentifierContext.Stage.Setup: break; - case StubCodeContext.Stage.Marshal: + case StubIdentifierContext.Stage.Marshal: if (elementMarshalDirection is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) { // = != null ? Marshal.GetFunctionPointerForDelegate() : default; @@ -54,7 +54,7 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont LiteralExpression(SyntaxKind.DefaultLiteralExpression))); } break; - case StubCodeContext.Stage.Unmarshal: + case StubIdentifierContext.Stage.Unmarshal: if (elementMarshalDirection is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional) { // = != default : Marshal.GetDelegateForFunctionPointer<>() : null; @@ -76,7 +76,7 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont LiteralExpression(SyntaxKind.NullLiteralExpression))); } break; - case StubCodeContext.Stage.NotifyForSuccessfulInvoke: + case StubIdentifierContext.Stage.NotifyForSuccessfulInvoke: if (elementMarshalDirection is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) { yield return ExpressionStatement( @@ -92,7 +92,7 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) + => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs index 95a3db5e47bcf..5fcd07703ccb0 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -14,10 +15,13 @@ namespace Microsoft.Interop { internal interface IElementsMarshallingCollectionSource { - InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo info, StubCodeContext context); - InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, StubCodeContext context); - InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context); - InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context); + TypePositionInfo TypeInfo { get; } + StubCodeContext CodeContext { get; } + + InvocationExpressionSyntax GetUnmanagedValuesDestination(StubIdentifierContext context); + InvocationExpressionSyntax GetManagedValuesSource(StubIdentifierContext context); + InvocationExpressionSyntax GetUnmanagedValuesSource(StubIdentifierContext context); + InvocationExpressionSyntax GetManagedValuesDestination(StubIdentifierContext context); } internal abstract class ElementsMarshalling @@ -34,12 +38,12 @@ protected ElementsMarshalling(IElementsMarshallingCollectionSource collectionSou /// < GetUnmanagedValuesDestination >.Clear(); /// /// - public StatementSyntax GenerateClearUnmanagedDestination(TypePositionInfo info, StubCodeContext context) + public StatementSyntax GenerateClearUnmanagedDestination(StubIdentifierContext context) { // .Clear(); return MethodInvocationStatement( - CollectionSource.GetUnmanagedValuesDestination(info, context), + CollectionSource.GetUnmanagedValuesDestination(context), IdentifierName("Clear")); } /// @@ -47,28 +51,66 @@ public StatementSyntax GenerateClearUnmanagedDestination(TypePositionInfo info, /// < GetManagedValuesDestination >.Clear(); /// /// - public StatementSyntax GenerateClearManagedValuesDestination(TypePositionInfo info, StubCodeContext context) + public StatementSyntax GenerateClearManagedValuesDestination(StubIdentifierContext context) { // .Clear(); return MethodInvocationStatement( - CollectionSource.GetManagedValuesDestination(info, context), + CollectionSource.GetManagedValuesDestination(context), IdentifierName("Clear")); } - public abstract StatementSyntax GenerateSetupStatement(TypePositionInfo info, StubCodeContext context); - public abstract StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalStatement(TypePositionInfo info, StubCodeContext context); - public abstract StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCodeContext context); - public abstract StatementSyntax GenerateManagedToUnmanagedByValueOutUnmarshalStatement(TypePositionInfo info, StubCodeContext context); + public static ExpressionSyntax GenerateNumElementsExpression(CountInfo count, bool countInfoRequiresCast, StubCodeContext codeContext, StubIdentifierContext context) + { + ExpressionSyntax numElementsExpression = count switch + { + SizeAndParamIndexInfo(int size, SizeAndParamIndexInfo.UnspecifiedParam) => GetConstSizeExpression(size), + ConstSizeCountInfo(int size) => GetConstSizeExpression(size), + SizeAndParamIndexInfo(SizeAndParamIndexInfo.UnspecifiedConstSize, TypePositionInfo param) => GetExpressionForParam(param), + SizeAndParamIndexInfo(int size, TypePositionInfo param) => CheckedExpression(SyntaxKind.CheckedExpression, + BinaryExpression(SyntaxKind.AddExpression, + GetConstSizeExpression(size), + GetExpressionForParam(param))), + CountElementCountInfo(TypePositionInfo elementInfo) => GetExpressionForParam(elementInfo), + _ => throw new UnreachableException("Count info should have been verified in generator resolution") + }; - public abstract StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCodeContext context); - public abstract StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, StubCodeContext context); + if (countInfoRequiresCast) + { + if (numElementsExpression.IsKind(SyntaxKind.CheckedExpression)) + { + numElementsExpression = ((CheckedExpressionSyntax)numElementsExpression).Expression; + } + numElementsExpression = CheckedExpression(SyntaxKind.CheckedExpression, + CastExpression( + PredefinedType(Token(SyntaxKind.IntKeyword)), + ParenthesizedExpression(numElementsExpression))); + } + + return numElementsExpression; + + static LiteralExpressionSyntax GetConstSizeExpression(int size) + { + return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(size)); + } + + ExpressionSyntax GetExpressionForParam(TypePositionInfo paramInfo) + { + return MarshallerHelpers.GetIndexedManagedElementExpression(paramInfo, codeContext, context); + } + } + + public abstract StatementSyntax GenerateSetupStatement(StubIdentifierContext context); + public abstract StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalStatement(StubIdentifierContext context); + public abstract StatementSyntax GenerateMarshalStatement(StubIdentifierContext context); + public abstract StatementSyntax GenerateManagedToUnmanagedByValueOutUnmarshalStatement(StubIdentifierContext context); + + public abstract StatementSyntax GenerateUnmarshalStatement(StubIdentifierContext context); + public abstract StatementSyntax GenerateElementCleanupStatement(StubIdentifierContext context); } -#pragma warning disable SA1400 // Access modifier should be declared https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3659 file static class ElementsMarshallingCollectionSourceExtensions -#pragma warning restore SA1400 // Access modifier should be declared { - public static StatementSyntax GetNumElementsAssignmentFromManagedValuesSource(this IElementsMarshallingCollectionSource source, TypePositionInfo info, StubCodeContext context) + public static StatementSyntax GetNumElementsAssignmentFromManagedValuesSource(this IElementsMarshallingCollectionSource source, TypePositionInfo info, StubIdentifierContext context) { var numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); // = .Length; @@ -78,11 +120,11 @@ public static StatementSyntax GetNumElementsAssignmentFromManagedValuesSource(th IdentifierName(numElementsIdentifier), MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - source.GetManagedValuesSource(info, context), + source.GetManagedValuesSource(context), IdentifierName("Length")))); } - public static StatementSyntax GetNumElementsAssignmentFromManagedValuesDestination(this IElementsMarshallingCollectionSource source, TypePositionInfo info, StubCodeContext context) + public static StatementSyntax GetNumElementsAssignmentFromManagedValuesDestination(this IElementsMarshallingCollectionSource source, TypePositionInfo info, StubIdentifierContext context) { var numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); // = .Length; @@ -92,7 +134,7 @@ public static StatementSyntax GetNumElementsAssignmentFromManagedValuesDestinati IdentifierName(numElementsIdentifier), MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - source.GetManagedValuesDestination(info, context), + source.GetManagedValuesDestination(context), IdentifierName("Length")))); } } @@ -100,19 +142,12 @@ public static StatementSyntax GetNumElementsAssignmentFromManagedValuesDestinati /// /// Support for marshalling blittable elements /// - internal sealed class BlittableElementsMarshalling : ElementsMarshalling + internal sealed class BlittableElementsMarshalling( + TypeSyntax managedElementType, + TypeSyntax unmanagedElementType, + IElementsMarshallingCollectionSource collectionSource) : ElementsMarshalling(collectionSource) { - private readonly TypeSyntax _managedElementType; - private readonly TypeSyntax _unmanagedElementType; - - public BlittableElementsMarshalling(TypeSyntax managedElementType, TypeSyntax unmanagedElementType, IElementsMarshallingCollectionSource collectionSource) - : base(collectionSource) - { - _managedElementType = managedElementType; - _unmanagedElementType = unmanagedElementType; - } - - public override StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalStatement(TypePositionInfo info, StubCodeContext context) + public override StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalStatement(StubIdentifierContext context) { // MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(), .Length) ExpressionSyntax destination = CastToManagedIfNecessary( @@ -123,33 +158,33 @@ public override StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalState MethodInvocation( TypeSyntaxes.System_Runtime_InteropServices_MemoryMarshal, IdentifierName("GetReference"), - Argument(CollectionSource.GetUnmanagedValuesSource(info, context)))), + Argument(CollectionSource.GetUnmanagedValuesSource(context)))), Argument( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - CollectionSource.GetUnmanagedValuesSource(info, context), + CollectionSource.GetUnmanagedValuesSource(context), IdentifierName("Length"))))); // .CopyTo(); return MethodInvocationStatement( - CollectionSource.GetManagedValuesDestination(info, context), + CollectionSource.GetManagedValuesDestination(context), IdentifierName("CopyTo"), Argument(destination)); } - public override StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCodeContext context) + public override StatementSyntax GenerateMarshalStatement(StubIdentifierContext context) { - ExpressionSyntax destination = CastToManagedIfNecessary(CollectionSource.GetUnmanagedValuesDestination(info, context)); + ExpressionSyntax destination = CastToManagedIfNecessary(CollectionSource.GetUnmanagedValuesDestination(context)); // .CopyTo(); return MethodInvocationStatement( - CollectionSource.GetManagedValuesSource(info, context), + CollectionSource.GetManagedValuesSource(context), IdentifierName("CopyTo"), Argument(destination)); } - public override StatementSyntax GenerateManagedToUnmanagedByValueOutUnmarshalStatement(TypePositionInfo info, StubCodeContext context) + public override StatementSyntax GenerateManagedToUnmanagedByValueOutUnmarshalStatement(StubIdentifierContext context) { - ExpressionSyntax source = CastToManagedIfNecessary(CollectionSource.GetUnmanagedValuesDestination(info, context)); + ExpressionSyntax source = CastToManagedIfNecessary(CollectionSource.GetUnmanagedValuesDestination(context)); // MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(), .Length) ExpressionSyntax destination = MethodInvocation( @@ -159,10 +194,10 @@ public override StatementSyntax GenerateManagedToUnmanagedByValueOutUnmarshalSta MethodInvocation( TypeSyntaxes.System_Runtime_InteropServices_MemoryMarshal, IdentifierName("GetReference"), - Argument(CollectionSource.GetManagedValuesSource(info, context)))), + Argument(CollectionSource.GetManagedValuesSource(context)))), Argument( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - CollectionSource.GetManagedValuesSource(info, context), + CollectionSource.GetManagedValuesSource(context), IdentifierName("Length")))); // .CopyTo(); @@ -176,21 +211,21 @@ public override StatementSyntax GenerateManagedToUnmanagedByValueOutUnmarshalSta Argument(destination))); } - public override StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCodeContext context) + public override StatementSyntax GenerateUnmarshalStatement(StubIdentifierContext context) { - ExpressionSyntax source = CastToManagedIfNecessary(CollectionSource.GetUnmanagedValuesSource(info, context)); + ExpressionSyntax source = CastToManagedIfNecessary(CollectionSource.GetUnmanagedValuesSource(context)); // .CopyTo(); return MethodInvocationStatement( source, IdentifierName("CopyTo"), - Argument(CollectionSource.GetManagedValuesDestination(info, context))); + Argument(CollectionSource.GetManagedValuesDestination(context))); } private ExpressionSyntax CastToManagedIfNecessary(ExpressionSyntax expression) { // Skip the cast if the managed and unmanaged element types are the same - if (_unmanagedElementType.IsEquivalentTo(_managedElementType)) + if (unmanagedElementType.IsEquivalentTo(managedElementType)) return expression; // MemoryMarshal.Cast<, >() @@ -200,14 +235,14 @@ private ExpressionSyntax CastToManagedIfNecessary(ExpressionSyntax expression) Identifier("Cast"), TypeArgumentList(SeparatedList(new[] { - _unmanagedElementType, - _managedElementType + unmanagedElementType, + managedElementType }))), Argument(expression)); } - public override StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, StubCodeContext context) => EmptyStatement(); - public override StatementSyntax GenerateSetupStatement(TypePositionInfo info, StubCodeContext context) => EmptyStatement(); + public override StatementSyntax GenerateElementCleanupStatement(StubIdentifierContext context) => EmptyStatement(); + public override StatementSyntax GenerateSetupStatement(StubIdentifierContext context) => EmptyStatement(); } /// @@ -218,10 +253,10 @@ internal sealed class NonBlittableElementsMarshalling( IBoundMarshallingGenerator elementMarshaller, IElementsMarshallingCollectionSource collectionSource) : ElementsMarshalling(collectionSource) { - public override StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCodeContext context) + public override StatementSyntax GenerateMarshalStatement(StubIdentifierContext context) { - string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context); - string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); + string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(CollectionSource.TypeInfo, context); + string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(CollectionSource.TypeInfo, context); // ReadOnlySpan = // Span = @@ -232,14 +267,14 @@ public override StatementSyntax GenerateMarshalStatement(TypePositionInfo info, Declare( ReadOnlySpanOf(elementMarshaller.TypeInfo.ManagedType.Syntax), managedSpanIdentifier, - CollectionSource.GetManagedValuesSource(info, context)), + CollectionSource.GetManagedValuesSource(context)), Declare( SpanOf(unmanagedElementType), nativeSpanIdentifier, - CollectionSource.GetUnmanagedValuesDestination(info, context)) + CollectionSource.GetUnmanagedValuesDestination(context)) }; // If it is a multidimensional array, we will just clear each allocated span. - if (ShouldCleanUpAllElements(info, context)) + if (ShouldCleanUpAllElements(CollectionSource.TypeInfo, CollectionSource.CodeContext)) { // .Clear() statements.Add(MethodInvocationStatement( @@ -247,20 +282,20 @@ public override StatementSyntax GenerateMarshalStatement(TypePositionInfo info, IdentifierName("Clear"))); } statements.Add(GenerateContentsMarshallingStatement( - info, context, MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(MarshallerHelpers.GetManagedSpanIdentifier(info, context)), + IdentifierName(MarshallerHelpers.GetManagedSpanIdentifier(CollectionSource.TypeInfo, context)), IdentifierName("Length")), - elementMarshaller, StubCodeContext.Stage.Marshal)); + elementMarshaller, + StubIdentifierContext.Stage.Marshal)); return Block(statements); } - public override StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCodeContext context) + public override StatementSyntax GenerateUnmarshalStatement(StubIdentifierContext context) { - string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context); - string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(CollectionSource.TypeInfo, context); + string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(CollectionSource.TypeInfo, context); + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(CollectionSource.TypeInfo, context); // ReadOnlySpan = // Span = @@ -269,29 +304,28 @@ public override StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info Declare( ReadOnlySpanOf(unmanagedElementType), nativeSpanIdentifier, - CollectionSource.GetUnmanagedValuesSource(info, context)), + CollectionSource.GetUnmanagedValuesSource(context)), Declare( SpanOf(elementMarshaller.TypeInfo.ManagedType.Syntax), managedSpanIdentifier, - CollectionSource.GetManagedValuesDestination(info, context)), + CollectionSource.GetManagedValuesDestination(context)), GenerateContentsMarshallingStatement( - info, context, IdentifierName(numElementsIdentifier), - elementMarshaller, StubCodeContext.Stage.UnmarshalCapture, - StubCodeContext.Stage.Unmarshal)); + elementMarshaller, + StubIdentifierContext.Stage.UnmarshalCapture, StubIdentifierContext.Stage.Unmarshal)); } - public override StatementSyntax GenerateManagedToUnmanagedByValueOutUnmarshalStatement(TypePositionInfo info, StubCodeContext context) + public override StatementSyntax GenerateManagedToUnmanagedByValueOutUnmarshalStatement(StubIdentifierContext context) { // Use ManagedSource and NativeDestination spans for by-value marshalling since we're just marshalling back the contents, // not the array itself. // This code is ugly since we're now enforcing readonly safety with ReadOnlySpan for all other scenarios, // but this is an uncommon case so we don't want to design the API around enabling just it. - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context); + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(CollectionSource.TypeInfo, context); + string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(CollectionSource.TypeInfo, context); - var setNumElements = CollectionSource.GetNumElementsAssignmentFromManagedValuesSource(info, context); + var setNumElements = CollectionSource.GetNumElementsAssignmentFromManagedValuesSource(CollectionSource.TypeInfo, context); // Span = MemoryMarshal.CreateSpan(ref Unsafe.AsRef(in .GetPinnableReference(), )); LocalDeclarationStatementSyntax managedValuesDeclaration = Declare(SpanOf(elementMarshaller.TypeInfo.ManagedType.Syntax), @@ -305,34 +339,33 @@ public override StatementSyntax GenerateManagedToUnmanagedByValueOutUnmarshalSta IdentifierName("AsRef"), InArgument( MethodInvocation( - CollectionSource.GetManagedValuesSource(info, context), + CollectionSource.GetManagedValuesSource(context), IdentifierName("GetPinnableReference"))))), Argument(IdentifierName(numElementsIdentifier)))); // Span = - string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); + string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(CollectionSource.TypeInfo, context); LocalDeclarationStatementSyntax unmanagedValuesDeclaration = Declare( SpanOf(unmanagedElementType), nativeSpanIdentifier, - CollectionSource.GetUnmanagedValuesDestination(info, context)); + CollectionSource.GetUnmanagedValuesDestination(context)); return Block( setNumElements, managedValuesDeclaration, unmanagedValuesDeclaration, GenerateContentsMarshallingStatement( - info, context, IdentifierName(numElementsIdentifier), - elementMarshaller, StubCodeContext.Stage.UnmarshalCapture, - StubCodeContext.Stage.Unmarshal)); + elementMarshaller, + StubIdentifierContext.Stage.UnmarshalCapture, StubIdentifierContext.Stage.Unmarshal)); } - public override StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, StubCodeContext context) + public override StatementSyntax GenerateElementCleanupStatement(StubIdentifierContext context) { - string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); + string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(CollectionSource.TypeInfo, context); ExpressionSyntax indexConstraintName; - if (!UsesLastIndexMarshalled(info, context)) + if (!UsesLastIndexMarshalled(CollectionSource.TypeInfo, CollectionSource.CodeContext)) { indexConstraintName = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nativeSpanIdentifier), @@ -340,10 +373,9 @@ public override StatementSyntax GenerateElementCleanupStatement(TypePositionInfo } else { - indexConstraintName = IdentifierName(MarshallerHelpers.GetLastIndexMarshalledIdentifier(info, context)); + indexConstraintName = IdentifierName(MarshallerHelpers.GetLastIndexMarshalledIdentifier(CollectionSource.TypeInfo, context)); } StatementSyntax contentsCleanupStatements = GenerateContentsMarshallingStatement( - info, context, indexConstraintName, elementMarshaller, @@ -351,11 +383,11 @@ public override StatementSyntax GenerateElementCleanupStatement(TypePositionInfo if (contentsCleanupStatements.IsKind(SyntaxKind.EmptyStatement)) { - if (UsesLastIndexMarshalled(info, context)) + if (UsesLastIndexMarshalled(CollectionSource.TypeInfo, CollectionSource.CodeContext)) { return AssignmentStatement( IdentifierName("_"), - IdentifierName(MarshallerHelpers.GetLastIndexMarshalledIdentifier(info, context))); + IdentifierName(MarshallerHelpers.GetLastIndexMarshalledIdentifier(CollectionSource.TypeInfo, context))); } return EmptyStatement(); } @@ -364,23 +396,23 @@ public override StatementSyntax GenerateElementCleanupStatement(TypePositionInfo Declare( ReadOnlySpanOf(unmanagedElementType), nativeSpanIdentifier, - MarshallerHelpers.GetMarshalDirection(info, context) == MarshalDirection.ManagedToUnmanaged - ? CollectionSource.GetUnmanagedValuesDestination(info, context) - : CollectionSource.GetUnmanagedValuesSource(info, context)), + MarshallerHelpers.GetMarshalDirection(CollectionSource.TypeInfo, CollectionSource.CodeContext) == MarshalDirection.ManagedToUnmanaged + ? CollectionSource.GetUnmanagedValuesDestination(context) + : CollectionSource.GetUnmanagedValuesSource(context)), contentsCleanupStatements); } - public override StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalStatement(TypePositionInfo info, StubCodeContext context) + public override StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalStatement(StubIdentifierContext context) { // Use ManagedSource and NativeDestination spans for by-value marshalling since we're just marshalling back the contents, // not the array itself. // This code is ugly since we're now enforcing readonly safety with ReadOnlySpan for all other scenarios, // but this is an uncommon case so we don't want to design the API around enabling just it. - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context); - string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(CollectionSource.TypeInfo, context); + string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(CollectionSource.TypeInfo, context); + string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(CollectionSource.TypeInfo, context); - var setNumElements = CollectionSource.GetNumElementsAssignmentFromManagedValuesDestination(info, context); + var setNumElements = CollectionSource.GetNumElementsAssignmentFromManagedValuesDestination(CollectionSource.TypeInfo, context); // Span = MemoryMarshal.CreateSpan(ref Unsafe.AsRef(in .GetPinnableReference()), ); LocalDeclarationStatementSyntax unmanagedValuesSource = Declare( @@ -395,7 +427,7 @@ public override StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalState IdentifierName("AsRef"), InArgument( MethodInvocation( - CollectionSource.GetUnmanagedValuesSource(info, context), + CollectionSource.GetUnmanagedValuesSource(context), IdentifierName("GetPinnableReference"))))), Argument(IdentifierName(numElementsIdentifier)))); @@ -408,18 +440,18 @@ public override StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalState VariableDeclarator( Identifier(managedSpanIdentifier)) .WithInitializer(EqualsValueClause( - CollectionSource.GetManagedValuesDestination(info, context)))))); + CollectionSource.GetManagedValuesDestination(context)))))); - StubCodeContext.Stage[] stagesToGenerate; + StubIdentifierContext.Stage[] stagesToGenerate; // Until we separate CalleeAllocated cleanup and CallerAllocated cleanup in unmanaged to managed, we'll need this hack - if (context.Direction is MarshalDirection.UnmanagedToManaged && info.ByValueContentsMarshalKind is ByValueContentsMarshalKind.Out) + if (CollectionSource.CodeContext.Direction is MarshalDirection.UnmanagedToManaged && CollectionSource.TypeInfo.ByValueContentsMarshalKind is ByValueContentsMarshalKind.Out) { - stagesToGenerate = new[] { StubCodeContext.Stage.Marshal, StubCodeContext.Stage.PinnedMarshal }; + stagesToGenerate = [StubIdentifierContext.Stage.Marshal, StubIdentifierContext.Stage.PinnedMarshal]; } else { - stagesToGenerate = new[] { StubCodeContext.Stage.Marshal, StubCodeContext.Stage.PinnedMarshal, StubCodeContext.Stage.CleanupCallerAllocated, StubCodeContext.Stage.CleanupCalleeAllocated }; + stagesToGenerate = [StubIdentifierContext.Stage.Marshal, StubIdentifierContext.Stage.PinnedMarshal, StubIdentifierContext.Stage.CleanupCallerAllocated, StubIdentifierContext.Stage.CleanupCalleeAllocated]; } return Block( @@ -427,56 +459,48 @@ public override StatementSyntax GenerateUnmanagedToManagedByValueOutMarshalState unmanagedValuesSource, managedValuesDestination, GenerateContentsMarshallingStatement( - info, context, IdentifierName(numElementsIdentifier), new FreeAlwaysOwnedOriginalValueGenerator(elementMarshaller), stagesToGenerate)); } - private static List GenerateElementStages( - TypePositionInfo info, - StubCodeContext context, + private List GenerateElementStages( + StubIdentifierContext context, IBoundMarshallingGenerator elementMarshaller, - out LinearCollectionElementMarshallingCodeContext elementSetupSubContext, - out TypePositionInfo localElementInfo, - params StubCodeContext.Stage[] stagesToGeneratePerElement) + out LinearCollectionElementIdentifierContext elementSetupSubContext, + params StubIdentifierContext.Stage[] stagesToGeneratePerElement) { - string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context); - string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); - elementSetupSubContext = new LinearCollectionElementMarshallingCodeContext( - StubCodeContext.Stage.Setup, + string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(CollectionSource.TypeInfo, context); + string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(CollectionSource.TypeInfo, context); + StubCodeContext elementCodeContext = StubCodeContext.CreateElementMarshallingContext(CollectionSource.CodeContext); + elementSetupSubContext = new LinearCollectionElementIdentifierContext( + context, + elementMarshaller.TypeInfo, managedSpanIdentifier, nativeSpanIdentifier, - context); - - IBoundMarshallingGenerator localMarshaller = elementMarshaller.Rebind(elementMarshaller.TypeInfo with + elementCodeContext.ElementIndirectionLevel) { - InstanceIdentifier = info.InstanceIdentifier, - RefKind = info.IsByRef ? info.RefKind : info.ByValueContentsMarshalKind.GetRefKindForByValueContentsKind(), - ManagedIndex = info.ManagedIndex, - NativeIndex = info.NativeIndex - }); - - localElementInfo = localMarshaller.TypeInfo; + CurrentStage = StubIdentifierContext.Stage.Setup, + CodeEmitOptions = context.CodeEmitOptions + }; - List elementStatements = new(); - foreach (StubCodeContext.Stage stage in stagesToGeneratePerElement) + List elementStatements = []; + foreach (StubIdentifierContext.Stage stage in stagesToGeneratePerElement) { var elementSubContext = elementSetupSubContext with { CurrentStage = stage }; - elementStatements.AddRange(localMarshaller.Generate(elementSubContext)); + elementStatements.AddRange(elementMarshaller.Generate(elementSubContext)); } return elementStatements; } - private static StatementSyntax GenerateContentsMarshallingStatement( - TypePositionInfo info, - StubCodeContext context, + private StatementSyntax GenerateContentsMarshallingStatement( + StubIdentifierContext context, ExpressionSyntax lengthExpression, IBoundMarshallingGenerator elementMarshaller, - params StubCodeContext.Stage[] stagesToGeneratePerElement) + params StubIdentifierContext.Stage[] stagesToGeneratePerElement) { - var elementStatements = GenerateElementStages(info, context, elementMarshaller, out var elementSetupSubContext, out var localElementInfo, stagesToGeneratePerElement); + var elementStatements = GenerateElementStages(context, elementMarshaller, out var elementSetupSubContext, stagesToGeneratePerElement); if (elementStatements.Count != 0) { @@ -486,7 +510,7 @@ private static StatementSyntax GenerateContentsMarshallingStatement( if (elementMarshaller.NativeType is PointerTypeInfo nativeTypeInfo) { - PointerNativeTypeAssignmentRewriter rewriter = new(elementSetupSubContext.GetIdentifiers(localElementInfo).native, (PointerTypeSyntax)nativeTypeInfo.Syntax); + PointerNativeTypeAssignmentRewriter rewriter = new(elementSetupSubContext.GetIdentifiers(elementMarshaller.TypeInfo).native, (PointerTypeSyntax)nativeTypeInfo.Syntax); marshallingStatement = (StatementSyntax)rewriter.Visit(marshallingStatement); } @@ -494,11 +518,11 @@ private static StatementSyntax GenerateContentsMarshallingStatement( var forLoop = ForLoop(elementSetupSubContext.IndexerIdentifier, lengthExpression) .WithStatement(marshallingStatement); // If we're tracking LastIndexMarshalled, increment that each iteration as well. - if (UsesLastIndexMarshalled(info, context) && stagesToGeneratePerElement.Contains(StubCodeContext.Stage.Marshal)) + if (UsesLastIndexMarshalled(CollectionSource.TypeInfo, CollectionSource.CodeContext) && stagesToGeneratePerElement.Contains(StubIdentifierContext.Stage.Marshal)) { forLoop = forLoop.AddIncrementors( PrefixUnaryExpression(SyntaxKind.PreIncrementExpression, - IdentifierName(MarshallerHelpers.GetLastIndexMarshalledIdentifier(info, context)))); + IdentifierName(MarshallerHelpers.GetLastIndexMarshalledIdentifier(CollectionSource.TypeInfo, context)))); } return forLoop; } @@ -523,21 +547,19 @@ private static bool UsesLastIndexMarshalled(TypePositionInfo info, StubCodeConte private static bool ShouldCleanUpAllElements(TypePositionInfo info, StubCodeContext context) { - _ = info; - _ = context; - // AdditionalTemporaryStateLivesAcrossStages implies that it is an outer collection + // ElementIndirectionLevel != 0 means that we are in a collection // Out parameters means that the contents are created by the P/Invoke and assumed to have successfully created all elements - return !context.AdditionalTemporaryStateLivesAcrossStages || info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out || info.RefKind == RefKind.Out || info.IsNativeReturnPosition; + return context.ElementIndirectionLevel != 0 || info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out || info.RefKind == RefKind.Out || info.IsNativeReturnPosition; } - public override StatementSyntax GenerateSetupStatement(TypePositionInfo info, StubCodeContext context) - => UsesLastIndexMarshalled(info, context) + public override StatementSyntax GenerateSetupStatement(StubIdentifierContext context) + => UsesLastIndexMarshalled(CollectionSource.TypeInfo, CollectionSource.CodeContext) ? LocalDeclarationStatement( VariableDeclaration( PredefinedType(Token(SyntaxKind.IntKeyword)), SingletonSeparatedList( VariableDeclarator( - Identifier(MarshallerHelpers.GetLastIndexMarshalledIdentifier(info, context)), + Identifier(MarshallerHelpers.GetLastIndexMarshalledIdentifier(CollectionSource.TypeInfo, context)), null, EqualsValueClause(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0))))))) : EmptyStatement(); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs index e90ceb2327856..f0b804d9f9dc8 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs @@ -24,14 +24,14 @@ public ValueBoundaryBehavior GetValueBoundaryBehavior(TypePositionInfo info, Stu return ValueBoundaryBehavior.ManagedIdentifier; } - public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + public IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) { return Array.Empty(); } public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => false; - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, context, out diagnostic); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic) + => ByValueMarshalKindSupportDescriptor.Default.GetSupport(marshalKind, info, out diagnostic); } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/GeneratorDiagnostic.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/GeneratorDiagnostic.cs index 02820335ec176..00a13f71cc2b2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/GeneratorDiagnostic.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/GeneratorDiagnostic.cs @@ -10,10 +10,9 @@ namespace Microsoft.Interop { public abstract record GeneratorDiagnostic { - private GeneratorDiagnostic(TypePositionInfo typePositionInfo, StubCodeContext stubCodeContext, bool isFatal) + private GeneratorDiagnostic(TypePositionInfo typePositionInfo, bool isFatal) { TypePositionInfo = typePositionInfo; - StubCodeContext = stubCodeContext; IsFatal = isFatal; } @@ -22,12 +21,11 @@ private GeneratorDiagnostic(TypePositionInfo typePositionInfo, StubCodeContext s /// public ImmutableDictionary DiagnosticProperties { get; init; } = ImmutableDictionary.Empty; public TypePositionInfo TypePositionInfo { get; } - public StubCodeContext StubCodeContext { get; } public bool IsFatal { get; } public abstract DiagnosticInfo ToDiagnosticInfo(DiagnosticDescriptor descriptor, Location location, string elementName); - public sealed record NotSupported(TypePositionInfo TypePositionInfo, StubCodeContext Context) : GeneratorDiagnostic(TypePositionInfo, Context, isFatal: true) + public sealed record NotSupported(TypePositionInfo TypePositionInfo) : GeneratorDiagnostic(TypePositionInfo, isFatal: true) { /// /// [Optional] Specific reason marshalling of the supplied type isn't supported. @@ -44,7 +42,7 @@ public override DiagnosticInfo ToDiagnosticInfo(DiagnosticDescriptor descriptor, } } - public sealed record UnnecessaryData(TypePositionInfo TypePositionInfo, StubCodeContext StubCodeContext, ImmutableArray UnnecessaryDataLocations) : GeneratorDiagnostic(TypePositionInfo, StubCodeContext, isFatal: false) + public sealed record UnnecessaryData(TypePositionInfo TypePositionInfo, ImmutableArray UnnecessaryDataLocations) : GeneratorDiagnostic(TypePositionInfo, isFatal: false) { public required string UnnecessaryDataName { get; init; } public string? UnnecessaryDataDetails { get; init; } @@ -63,7 +61,7 @@ public override DiagnosticInfo ToDiagnosticInfo(DiagnosticDescriptor descriptor, } } - public sealed record NotRecommended(TypePositionInfo TypePositionInfo, StubCodeContext StubCodeContext) : GeneratorDiagnostic(TypePositionInfo, StubCodeContext, isFatal: false) + public sealed record NotRecommended(TypePositionInfo TypePositionInfo) : GeneratorDiagnostic(TypePositionInfo, isFatal: false) { public string? Details { get; init; } 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 53223656b7ddf..649d3e97fac31 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 @@ -11,28 +11,32 @@ namespace Microsoft.Interop /// internal interface ICustomTypeMarshallingStrategy { - ManagedTypeInfo AsNativeType(TypePositionInfo info); + TypePositionInfo TypeInfo { get; } - IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context); + StubCodeContext CodeContext { get; } - IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context); + ManagedTypeInfo NativeType { get; } - IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context); + IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(StubIdentifierContext context); - IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context); + IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(StubIdentifierContext context); - IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context); + IEnumerable GenerateGuaranteedUnmarshalStatements(StubIdentifierContext context); - IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context); + IEnumerable GenerateMarshalStatements(StubIdentifierContext context); - IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context); + IEnumerable GenerateNotifyForSuccessfulInvokeStatements(StubIdentifierContext context); - IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context); + IEnumerable GeneratePinnedMarshalStatements(StubIdentifierContext context); - IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context); + IEnumerable GeneratePinStatements(StubIdentifierContext context); - IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context); + IEnumerable GenerateSetupStatements(StubIdentifierContext context); - bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context); + IEnumerable GenerateUnmarshalCaptureStatements(StubIdentifierContext context); + + IEnumerable GenerateUnmarshalStatements(StubIdentifierContext context); + + bool UsesNativeIdentifier { get; } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalAsMarshallingGeneratorResolver.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalAsMarshallingGeneratorResolver.cs index 55f9b2f2d0734..6f4721b71fd5e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalAsMarshallingGeneratorResolver.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshalAsMarshallingGeneratorResolver.cs @@ -51,7 +51,7 @@ public ResolvedGenerator Create( or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Single }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.R4, _) } or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Double }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.R8, _) }: // TODO: Report the MarshalAs attribute as unnecessary - return ResolvedGenerator.Resolved(s_blittable.Bind(info)); + return ResolvedGenerator.Resolved(s_blittable.Bind(info, context)); // Enum with no marshalling info case { ManagedType: EnumTypeInfo enumType, MarshallingAttributeInfo: NoMarshallingInfo }: @@ -59,37 +59,37 @@ public ResolvedGenerator Create( SpecialType underlyingSpecialType = enumType.UnderlyingType; if (underlyingSpecialType == SpecialType.System_Boolean || underlyingSpecialType == SpecialType.System_Char) { - return ResolvedGenerator.NotSupported(info, new(info, context)); + return ResolvedGenerator.NotSupported(info, context, new(info)); } - return ResolvedGenerator.Resolved(s_blittable.Bind(info)); + return ResolvedGenerator.Resolved(s_blittable.Bind(info, context)); // Pointer with no marshalling info case { ManagedType: PointerTypeInfo{ IsFunctionPointer: false }, MarshallingAttributeInfo: NoMarshallingInfo }: - return ResolvedGenerator.Resolved(s_blittable.Bind(info)); + return ResolvedGenerator.Resolved(s_blittable.Bind(info, context)); // Function pointer with no marshalling info case { ManagedType: PointerTypeInfo { IsFunctionPointer: true }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.FunctionPtr, _) }: - return ResolvedGenerator.Resolved(s_blittable.Bind(info)); + return ResolvedGenerator.Resolved(s_blittable.Bind(info, context)); // Bool with marshalling info case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Boolean }, MarshallingAttributeInfo: MarshalAsInfo(UnmanagedType.U1, _) }: - return ResolvedGenerator.Resolved(s_byteBool.Bind(info)); + return ResolvedGenerator.Resolved(s_byteBool.Bind(info, context)); case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Boolean }, MarshallingAttributeInfo: MarshalAsInfo(UnmanagedType.I1, _) }: - return ResolvedGenerator.Resolved(s_signed_byteBool.Bind(info)); + return ResolvedGenerator.Resolved(s_signed_byteBool.Bind(info, context)); case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Boolean }, MarshallingAttributeInfo: MarshalAsInfo(UnmanagedType.U4, _) }: - return ResolvedGenerator.Resolved(s_winBool.Bind(info)); + return ResolvedGenerator.Resolved(s_winBool.Bind(info, context)); case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Boolean }, MarshallingAttributeInfo: MarshalAsInfo(UnmanagedType.I4 or UnmanagedType.Bool, _) }: - return ResolvedGenerator.Resolved(s_signed_winBool.Bind(info)); + return ResolvedGenerator.Resolved(s_signed_winBool.Bind(info, context)); case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Boolean }, MarshallingAttributeInfo: MarshalAsInfo(UnmanagedType.VariantBool, _) }: - return ResolvedGenerator.Resolved(s_variantBool.Bind(info)); + return ResolvedGenerator.Resolved(s_variantBool.Bind(info, context)); // Delegate types case { ManagedType: DelegateTypeInfo, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.FunctionPtr, _) }: - return ResolvedGenerator.Resolved(s_delegate.Bind(info)); + return ResolvedGenerator.Resolved(s_delegate.Bind(info, context)); // void case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Void } }: - return ResolvedGenerator.Resolved(s_forwarder.Bind(info)); + return ResolvedGenerator.Resolved(s_forwarder.Bind(info, context)); default: return ResolvedGenerator.UnresolvedGenerator; 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 25e09c52a6008..7c7e4b5c609dd 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 @@ -61,31 +61,47 @@ public static StatementSyntax CreateGetLastSystemErrorStatement(string lastError public static StatementSyntax CreateSetLastPInvokeErrorStatement(string lastErrorIdentifier) => MethodInvocationStatement(TypeSyntaxes.System_Runtime_InteropServices_Marshal, IdentifierName("SetLastPInvokeError"), Argument(IdentifierName(lastErrorIdentifier))); - public static string GetMarshallerIdentifier(TypePositionInfo info, StubCodeContext context) + public static string GetMarshallerIdentifier(TypePositionInfo info, StubIdentifierContext context) { return context.GetAdditionalIdentifier(info, "marshaller"); } - public static string GetManagedSpanIdentifier(TypePositionInfo info, StubCodeContext context) + public static string GetManagedSpanIdentifier(TypePositionInfo info, StubIdentifierContext context) { return context.GetAdditionalIdentifier(info, "managedSpan"); } - public static string GetNativeSpanIdentifier(TypePositionInfo info, StubCodeContext context) + public static string GetNativeSpanIdentifier(TypePositionInfo info, StubIdentifierContext context) { return context.GetAdditionalIdentifier(info, "nativeSpan"); } - public static string GetNumElementsIdentifier(TypePositionInfo info, StubCodeContext context) + public static string GetNumElementsIdentifier(TypePositionInfo info, StubIdentifierContext context) { return context.GetAdditionalIdentifier(info, "numElements"); } - public static string GetLastIndexMarshalledIdentifier(TypePositionInfo info, StubCodeContext context) + public static string GetLastIndexMarshalledIdentifier(TypePositionInfo info, StubIdentifierContext context) { return context.GetAdditionalIdentifier(info, "lastIndexMarshalled"); } + public static string GetIndexerIdentifier(int i) + { + return $"__i{i}"; + } + + public static ExpressionSyntax GetIndexedManagedElementExpression(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context) + { + ExpressionSyntax indexedManagedElement = IdentifierName(context.GetIdentifiers(info).managed); + for (int i = 0; i < codeContext.ElementIndirectionLevel; i++) + { + indexedManagedElement = ElementAccessExpression(indexedManagedElement) + .AddArgumentListArguments(Argument(IdentifierName(GetIndexerIdentifier(i)))); + } + return indexedManagedElement; + } + internal static bool CanUseCallerAllocatedBuffer(TypePositionInfo info, StubCodeContext context) { return context.SingleFrameSpansNativeContext && (!info.IsByRef || info.RefKind == RefKind.In || info.RefKind == RefKind.RefReadOnlyParameter); @@ -241,7 +257,7 @@ public static IEnumerable GetDependentElementsOfMarshallingInf } // private static readonly InvocationExpressionSyntax SkipInitInvocation = - public static StatementSyntax SkipInitOrDefaultInit(TypePositionInfo info, StubCodeContext context) + public static StatementSyntax SkipInitOrDefaultInit(TypePositionInfo info, StubIdentifierContext context) { if (info.ManagedType is not PointerTypeInfo && info.ManagedType is not ValueTypeInfo { IsByRefLike: true } @@ -263,7 +279,7 @@ public static StatementSyntax SkipInitOrDefaultInit(TypePositionInfo info, StubC } } - public static StatementSyntax DefaultInit(TypePositionInfo info, StubCodeContext context) + public static StatementSyntax DefaultInit(TypePositionInfo info, StubIdentifierContext context) { // Assign out params to default return AssignmentStatement( @@ -334,19 +350,19 @@ public static MarshalDirection GetMarshalDirection(TypePositionInfo info, StubCo /// /// Returns which stage cleanup should be performed for the parameter. /// - public static StubCodeContext.Stage GetCleanupStage(TypePositionInfo info, StubCodeContext context) + public static StubIdentifierContext.Stage GetCleanupStage(TypePositionInfo info, StubCodeContext context) { // Unmanaged to managed doesn't properly handle lifetimes right now and will default to the original behavior. // Failures will only occur when marshalling fails, and would only cause leaks, not double frees. // See https://github.com/dotnet/runtime/issues/89483 for more details if (context.Direction is MarshalDirection.UnmanagedToManaged) - return StubCodeContext.Stage.CleanupCallerAllocated; + return StubIdentifierContext.Stage.CleanupCallerAllocated; return GetMarshalDirection(info, context) switch { - MarshalDirection.UnmanagedToManaged => StubCodeContext.Stage.CleanupCalleeAllocated, - MarshalDirection.ManagedToUnmanaged => StubCodeContext.Stage.CleanupCallerAllocated, - MarshalDirection.Bidirectional => StubCodeContext.Stage.CleanupCallerAllocated, + MarshalDirection.UnmanagedToManaged => StubIdentifierContext.Stage.CleanupCalleeAllocated, + MarshalDirection.ManagedToUnmanaged => StubIdentifierContext.Stage.CleanupCallerAllocated, + MarshalDirection.Bidirectional => StubIdentifierContext.Stage.CleanupCallerAllocated, _ => throw new UnreachableException() }; } @@ -446,5 +462,35 @@ public static SyntaxToken GetManagedArgumentRefKindKeyword(TypePositionInfo type _ => throw new NotImplementedException($"Support for some RefKind: {typeInfo.RefKind}") }; } + + /// + /// Compute if the provided element is the return element for the stub that is being generated (not any inner call). + /// + /// The element information + /// true if the element is in the return position for this stub; otherwise, false. + public static bool IsInStubReturnPosition(TypePositionInfo info, MarshalDirection direction) + { + return direction switch + { + MarshalDirection.ManagedToUnmanaged => info.IsManagedReturnPosition, + MarshalDirection.UnmanagedToManaged => info.IsNativeReturnPosition, + _ => throw new ArgumentException("Cannot determine the return position of a bidirectional stub", nameof(direction)), + }; + } + + /// + /// Compute if the provided element is the return element for the invocation in the stub. + /// + /// The element information + /// true if the element is in the return position for the invocation; otherwise, false. + public static bool IsInInvocationReturnPosition(TypePositionInfo info, MarshalDirection direction) + { + return direction switch + { + MarshalDirection.ManagedToUnmanaged => info.IsNativeReturnPosition, + MarshalDirection.UnmanagedToManaged => info.IsManagedReturnPosition, + _ => throw new ArgumentException("Cannot determine the return position of a bidirectional stub", nameof(direction)), + }; + } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs index 631a3fb171692..fad741c769ce4 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs @@ -39,17 +39,17 @@ public enum ValueBoundaryBehavior ManagedIdentifier, /// - /// The native identifier provided by should be passed by value. + /// The native identifier provided by should be passed by value. /// NativeIdentifier, /// - /// The address of the native identifier provided by should be passed by value. + /// The address of the native identifier provided by should be passed by value. /// AddressOfNativeIdentifier, /// - /// The native identifier provided by should be cast to the native type. + /// The native identifier provided by should be cast to the native type. /// CastNativeIdentifier } @@ -87,6 +87,11 @@ public interface IBoundMarshallingGenerator /// TypePositionInfo TypeInfo { get; } + /// + /// The context into which this generator is bound and will generate code. + /// + StubCodeContext CodeContext { get; } + /// /// Get the native type for the bound element of the generator. /// @@ -101,8 +106,8 @@ public interface IBoundMarshallingGenerator /// Get the shape of how the value represented by this generator should be passed at the managed/native boundary in the provided /// /// Code generation context - /// How to represent the unmanaged value at the managed/unmanaged boudary - ValueBoundaryBehavior GetValueBoundaryBehavior(StubCodeContext context); + /// How to represent the unmanaged value at the managed/unmanaged boundary + ValueBoundaryBehavior ValueBoundaryBehavior { get; } /// /// Generate code for marshalling @@ -111,11 +116,11 @@ public interface IBoundMarshallingGenerator /// List of statements to be added to the P/Invoke stub /// /// The generator should return the appropriate statements based on the - /// of . - /// For , any statements not of type + /// of . + /// For , any statements not of type /// will be ignored. /// - IEnumerable Generate(StubCodeContext context); + IEnumerable Generate(StubIdentifierContext context); /// /// Returns whether or not this marshaller uses an identifier for the native value in addition @@ -124,9 +129,9 @@ public interface IBoundMarshallingGenerator /// Code generation context /// If the marshaller uses an identifier for the native value, true; otherwise, false. /// - /// of may not be valid. + /// of may not be valid. /// - bool UsesNativeIdentifier(StubCodeContext context); + bool UsesNativeIdentifier { get; } /// /// Returns if the given ByValueContentsMarshalKind is supported in the current marshalling context. @@ -140,14 +145,7 @@ public interface IBoundMarshallingGenerator /// It should be non-null if the value is not /// /// If the provided is supported and if it is required to specify the requested behavior. - ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context, out GeneratorDiagnostic? diagnostic); - - /// - /// Create a new instance of this generator bound to a different . - /// - /// The new info to bind to. - /// A new instance of this marshaller bound to . - IBoundMarshallingGenerator Rebind(TypePositionInfo info); + ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, out GeneratorDiagnostic? diagnostic); } /// @@ -155,7 +153,7 @@ public interface IBoundMarshallingGenerator /// /// The element info. /// The unbound generator - internal sealed class BoundMarshallingGenerator(TypePositionInfo info, IUnboundMarshallingGenerator unbound) : IBoundMarshallingGenerator + internal sealed class BoundMarshallingGenerator(TypePositionInfo info, StubCodeContext context, IUnboundMarshallingGenerator unbound) : IBoundMarshallingGenerator { internal bool IsForwarder => unbound is Forwarder; @@ -163,20 +161,20 @@ internal sealed class BoundMarshallingGenerator(TypePositionInfo info, IUnboundM public TypePositionInfo TypeInfo => info; + public StubCodeContext CodeContext => context; + public ManagedTypeInfo NativeType => unbound.AsNativeType(TypeInfo); public SignatureBehavior NativeSignatureBehavior => unbound.GetNativeSignatureBehavior(TypeInfo); - public IEnumerable Generate(StubCodeContext context) => unbound.Generate(TypeInfo, context); - - public ValueBoundaryBehavior GetValueBoundaryBehavior(StubCodeContext context) => unbound.GetValueBoundaryBehavior(TypeInfo, context); + public IEnumerable Generate(StubIdentifierContext context) => unbound.Generate(TypeInfo, CodeContext, context); - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => unbound.SupportsByValueMarshalKind(marshalKind, TypeInfo, context, out diagnostic); + public ValueBoundaryBehavior ValueBoundaryBehavior => unbound.GetValueBoundaryBehavior(TypeInfo, context); - public bool UsesNativeIdentifier(StubCodeContext context) => unbound.UsesNativeIdentifier(TypeInfo, context); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, out GeneratorDiagnostic? diagnostic) + => unbound.SupportsByValueMarshalKind(marshalKind, TypeInfo, out diagnostic); - public IBoundMarshallingGenerator Rebind(TypePositionInfo info) => new BoundMarshallingGenerator(info, unbound); + public bool UsesNativeIdentifier => unbound.UsesNativeIdentifier(TypeInfo, context); } public static class UnboundMarshallingGeneratorExtensions @@ -187,7 +185,8 @@ public static class UnboundMarshallingGeneratorExtensions /// The unbound generator /// The element info /// A generator wrapper that is bound to this info. - public static IBoundMarshallingGenerator Bind(this IUnboundMarshallingGenerator unbound, TypePositionInfo info) => new BoundMarshallingGenerator(info, unbound); + /// + public static IBoundMarshallingGenerator Bind(this IUnboundMarshallingGenerator unbound, TypePositionInfo info, StubCodeContext context) => new BoundMarshallingGenerator(info, context, unbound); } /// @@ -221,15 +220,16 @@ public interface IUnboundMarshallingGenerator /// Generate code for marshalling /// /// Object to marshal - /// Code generation context + /// Code generation context + /// Context to get identifiers /// List of statements to be added to the P/Invoke stub /// /// The generator should return the appropriate statements based on the - /// of . - /// For , any statements not of type + /// of . + /// For , any statements not of type /// will be ignored. /// - IEnumerable Generate(TypePositionInfo info, StubCodeContext context); + IEnumerable Generate(TypePositionInfo info, StubCodeContext codeContext, StubIdentifierContext context); /// /// Returns whether or not this marshaller uses an identifier for the native value in addition @@ -238,9 +238,6 @@ public interface IUnboundMarshallingGenerator /// Object to marshal /// Code generation context /// If the marshaller uses an identifier for the native value, true; otherwise, false. - /// - /// of may not be valid. - /// bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context); /// @@ -249,12 +246,11 @@ public interface IUnboundMarshallingGenerator /// /// The marshal kind. /// The TypePositionInfo of the parameter. - /// The marshalling context. /// /// The diagnostic to report if the return value is not . /// It should be non-null if the value is not /// /// If the provided is supported and if it is required to specify the requested behavior. - ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, StubCodeContext context, out GeneratorDiagnostic? diagnostic); + ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, TypePositionInfo info, out GeneratorDiagnostic? diagnostic); } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs index cedc6f8aad1d9..c54b58cb0e03a 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorExtensions.cs @@ -56,7 +56,7 @@ public static TypeSyntax AsReturnType(this IBoundMarshallingGenerator generator) /// /// The marshalling generator for this /// The stub marshalling context - public static ParameterSyntax AsParameter(this IBoundMarshallingGenerator generator, StubCodeContext context) + public static ParameterSyntax AsParameter(this IBoundMarshallingGenerator generator, StubIdentifierContext context) { SignatureBehavior behavior = generator.NativeSignatureBehavior; if (behavior == SignatureBehavior.ManagedTypeAndAttributes) @@ -64,13 +64,13 @@ public static ParameterSyntax AsParameter(this IBoundMarshallingGenerator genera return GenerateForwardingParameter(generator.TypeInfo, context.GetIdentifiers(generator.TypeInfo).managed); } string identifierName; - if (context.Direction == MarshalDirection.ManagedToUnmanaged) + if (generator.CodeContext.Direction == MarshalDirection.ManagedToUnmanaged) { // This name doesn't get introduced into the stub's scope, so we can make it pretty // and reuse the native identifier identifierName = context.GetIdentifiers(generator.TypeInfo).native; } - else if (context.Direction == MarshalDirection.UnmanagedToManaged) + else if (generator.CodeContext.Direction == MarshalDirection.UnmanagedToManaged) { // This name is introduced into the stub's scope. // When we are passing the managed identifier as-is, we can just use that name everywhere. @@ -80,7 +80,7 @@ public static ParameterSyntax AsParameter(this IBoundMarshallingGenerator genera // before we assign it to the managed value. (string managed, string native) = context.GetIdentifiers(generator.TypeInfo); string param = context.GetAdditionalIdentifier(generator.TypeInfo, ParameterIdentifierSuffix); - identifierName = generator.GetValueBoundaryBehavior(context) switch + identifierName = generator.ValueBoundaryBehavior switch { ValueBoundaryBehavior.ManagedIdentifier => generator.TypeInfo.IsByRef ? param : managed, ValueBoundaryBehavior.NativeIdentifier or ValueBoundaryBehavior.CastNativeIdentifier => native, @@ -136,11 +136,11 @@ private static ParameterSyntax GenerateForwardingParameter(TypePositionInfo info /// The marshalling generator for this /// Object to marshal /// Marshalling context - public static ArgumentSyntax AsArgument(this IBoundMarshallingGenerator generator, StubCodeContext context) + public static ArgumentSyntax AsArgument(this IBoundMarshallingGenerator generator, StubIdentifierContext context) { TypePositionInfo info = generator.TypeInfo; (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); - return generator.GetValueBoundaryBehavior(context) switch + return generator.ValueBoundaryBehavior switch { ValueBoundaryBehavior.ManagedIdentifier when !info.IsByRef => Argument(IdentifierName(managedIdentifier)), ValueBoundaryBehavior.ManagedIdentifier when info.IsByRef => Argument(IdentifierName(managedIdentifier)).WithRefKindKeyword(MarshallerHelpers.GetManagedArgumentRefKindKeyword(info)), @@ -151,7 +151,7 @@ public static ArgumentSyntax AsArgument(this IBoundMarshallingGenerator generato }; } - public static ArgumentSyntax AsManagedArgument(this IBoundMarshallingGenerator generator, StubCodeContext context) + public static ArgumentSyntax AsManagedArgument(this IBoundMarshallingGenerator generator, StubIdentifierContext context) { TypePositionInfo info = generator.TypeInfo; var (managedIdentifier, _) = context.GetIdentifiers(info); @@ -162,7 +162,7 @@ public static ArgumentSyntax AsManagedArgument(this IBoundMarshallingGenerator g return Argument(IdentifierName(managedIdentifier)); } - public static ExpressionSyntax GenerateNativeByRefInitialization(this IBoundMarshallingGenerator generator, StubCodeContext context) + public static ExpressionSyntax GenerateNativeByRefInitialization(this IBoundMarshallingGenerator generator, StubIdentifierContext context) { TypePositionInfo info = generator.TypeInfo; string paramIdentifier = context.GetAdditionalIdentifier(info, ParameterIdentifierSuffix); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/NoMarshallingInfoErrorResolver.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/NoMarshallingInfoErrorResolver.cs index 0d8668a3d2ddc..be1471935946d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/NoMarshallingInfoErrorResolver.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/NoMarshallingInfoErrorResolver.cs @@ -17,7 +17,7 @@ public ResolvedGenerator Create( { if (info.MarshallingAttributeInfo is NoMarshallingInfo && CustomTypeToErrorMessageMap.TryGetValue(info.ManagedType, out string errorMessage)) { - return ResolvedGenerator.NotSupported(info, new(info, context) + return ResolvedGenerator.NotSupported(info, context, new(info) { NotSupportedDetails = errorMessage }); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/NotSupportedResolver.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/NotSupportedResolver.cs index 24bebb5f8b89c..212e194e1eea7 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/NotSupportedResolver.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/NotSupportedResolver.cs @@ -6,6 +6,6 @@ namespace Microsoft.Interop public sealed class NotSupportedResolver : IMarshallingGeneratorResolver { public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context) => - ResolvedGenerator.NotSupported(info, new(info, context)); + ResolvedGenerator.NotSupported(info, context, new(info)); } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ResolvedGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ResolvedGenerator.cs index bd446b0d75925..b9723cbac35a6 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ResolvedGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ResolvedGenerator.cs @@ -22,9 +22,9 @@ public static ResolvedGenerator Resolved(IBoundMarshallingGenerator generator) return new(generator, ImmutableArray.Empty); } - public static ResolvedGenerator NotSupported(TypePositionInfo info, GeneratorDiagnostic.NotSupported notSupportedDiagnostic) + public static ResolvedGenerator NotSupported(TypePositionInfo info, StubCodeContext context, GeneratorDiagnostic.NotSupported notSupportedDiagnostic) { - return new(s_forwarder.Bind(info), ImmutableArray.Create(notSupportedDiagnostic)); + return new(s_forwarder.Bind(info, context), ImmutableArray.Create(notSupportedDiagnostic)); } public static ResolvedGenerator ResolvedWithDiagnostics(IBoundMarshallingGenerator generator, ImmutableArray diagnostics) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs index 1137f6ceecaa8..6cc20f83a48e0 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs @@ -10,33 +10,24 @@ namespace Microsoft.Interop { - internal sealed class StatefulValueMarshalling : ICustomTypeMarshallingStrategy + internal sealed class StatefulValueMarshalling(TypePositionInfo info, StubCodeContext stubContext, ManagedTypeInfo marshallerType, ManagedTypeInfo unmanagedType, MarshallerShape shape) : ICustomTypeMarshallingStrategy { internal const string MarshallerIdentifier = "marshaller"; - private readonly ManagedTypeInfo _marshallerType; - private readonly ManagedTypeInfo _unmanagedType; - private readonly MarshallerShape _shape; - public StatefulValueMarshalling(ManagedTypeInfo marshallerType, ManagedTypeInfo unmanagedType, MarshallerShape shape) - { - _marshallerType = marshallerType; - _unmanagedType = unmanagedType; - _shape = shape; - } + public ManagedTypeInfo NativeType => unmanagedType; - public ManagedTypeInfo AsNativeType(TypePositionInfo info) - { - return _unmanagedType; - } + public bool UsesNativeIdentifier => true; + + public TypePositionInfo TypeInfo => info; - public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; + public StubCodeContext CodeContext => stubContext; - public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(StubIdentifierContext context) { - if (MarshallerHelpers.GetCleanupStage(info, context) is not StubCodeContext.Stage.CleanupCallerAllocated) + if (MarshallerHelpers.GetCleanupStage(info, stubContext) is not StubIdentifierContext.Stage.CleanupCallerAllocated) yield break; - if (!_shape.HasFlag(MarshallerShape.Free)) + if (!shape.HasFlag(MarshallerShape.Free)) yield break; // .Free(); @@ -45,12 +36,12 @@ public IEnumerable GenerateCleanupCallerAllocatedResourcesState IdentifierName(ShapeMemberNames.Free)); } - public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(StubIdentifierContext context) { - if (MarshallerHelpers.GetCleanupStage(info, context) is not StubCodeContext.Stage.CleanupCalleeAllocated) + if (MarshallerHelpers.GetCleanupStage(info, stubContext) is not StubIdentifierContext.Stage.CleanupCalleeAllocated) yield break; - if (!_shape.HasFlag(MarshallerShape.Free)) + if (!shape.HasFlag(MarshallerShape.Free)) yield break; // .Free(); @@ -59,9 +50,9 @@ public IEnumerable GenerateCleanupCalleeAllocatedResourcesState IdentifierName(ShapeMemberNames.Free)); } - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateGuaranteedUnmarshalStatements(StubIdentifierContext context) { - if (!_shape.HasFlag(MarshallerShape.GuaranteedUnmarshal)) + if (!shape.HasFlag(MarshallerShape.GuaranteedUnmarshal)) yield break; (string managedIdentifier, _) = context.GetIdentifiers(info); @@ -74,9 +65,9 @@ public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePo IdentifierName(ShapeMemberNames.Value.Stateful.ToManagedFinally))); } - public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateMarshalStatements(StubIdentifierContext context) { - if (!_shape.HasFlag(MarshallerShape.ToUnmanaged)) + if (!shape.HasFlag(MarshallerShape.ToUnmanaged)) yield break; (string managedIdentifier, _) = context.GetIdentifiers(info); @@ -88,9 +79,9 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i Argument(IdentifierName(managedIdentifier))); } - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GeneratePinnedMarshalStatements(StubIdentifierContext context) { - if (!_shape.HasFlag(MarshallerShape.ToUnmanaged) && !_shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) + if (!shape.HasFlag(MarshallerShape.ToUnmanaged) && !shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) yield break; (_, string nativeIdentifier) = context.GetIdentifiers(info); @@ -103,9 +94,9 @@ public IEnumerable GeneratePinnedMarshalStatements(TypePosition IdentifierName(ShapeMemberNames.Value.Stateful.ToUnmanaged))); } - public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateUnmarshalStatements(StubIdentifierContext context) { - if (!_shape.HasFlag(MarshallerShape.ToManaged)) + if (!shape.HasFlag(MarshallerShape.ToManaged)) yield break; (string managedIdentifier, _) = context.GetIdentifiers(info); @@ -118,9 +109,9 @@ public IEnumerable GenerateUnmarshalStatements(TypePositionInfo IdentifierName(ShapeMemberNames.Value.Stateful.ToManaged))); } - public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateUnmarshalCaptureStatements(StubIdentifierContext context) { - if (!_shape.HasFlag(MarshallerShape.ToManaged) && !_shape.HasFlag(MarshallerShape.GuaranteedUnmarshal)) + if (!shape.HasFlag(MarshallerShape.ToManaged) && !shape.HasFlag(MarshallerShape.GuaranteedUnmarshal)) yield break; (_, string nativeIdentifier) = context.GetIdentifiers(info); @@ -132,11 +123,11 @@ public IEnumerable GenerateUnmarshalCaptureStatements(TypePosit Argument(IdentifierName(nativeIdentifier))); } - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateSetupStatements(StubIdentifierContext context) { // = new(); LocalDeclarationStatementSyntax declaration = Declare( - _marshallerType.Syntax, + marshallerType.Syntax, context.GetAdditionalIdentifier(info, MarshallerIdentifier), ImplicitObjectCreationExpression(ArgumentList(), initializer: null)); @@ -146,7 +137,7 @@ public IEnumerable GenerateSetupStatements(TypePositionInfo inf // In particular, this can interact poorly with the caller-allocated-buffer marshalling // support and make the simple `marshaller.FromManaged(managed, stackalloc X[i])` expression // illegal. Mark the marshaller type as scoped so the compiler knows that it won't escape. - if (_marshallerType is ValueTypeInfo { IsByRefLike: true }) + if (marshallerType is ValueTypeInfo { IsByRefLike: true }) { declaration = declaration.AddModifiers(Token(SyntaxKind.ScopedKeyword)); } @@ -154,9 +145,9 @@ public IEnumerable GenerateSetupStatements(TypePositionInfo inf yield return declaration; } - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GeneratePinStatements(StubIdentifierContext context) { - if (!_shape.HasFlag(MarshallerShape.StatefulPinnableReference)) + if (!shape.HasFlag(MarshallerShape.StatefulPinnableReference)) yield break; string unusedIdentifier = context.GetAdditionalIdentifier(info, "unused"); @@ -170,9 +161,9 @@ public IEnumerable GeneratePinStatements(TypePositionInfo info, EmptyStatement()); } - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(StubIdentifierContext context) { - if (!_shape.HasFlag(MarshallerShape.OnInvoked)) + if (!shape.HasFlag(MarshallerShape.OnInvoked)) yield break; // .OnInvoked(); @@ -181,7 +172,7 @@ public IEnumerable GenerateNotifyForSuccessfulInvokeStatements( IdentifierName(ShapeMemberNames.Value.Stateful.OnInvoked)); } - public static string GetMarshallerIdentifier(TypePositionInfo info, StubCodeContext context) + public static string GetMarshallerIdentifier(TypePositionInfo info, StubIdentifierContext context) { return context.GetAdditionalIdentifier(info, MarshallerIdentifier); } @@ -190,99 +181,90 @@ public static string GetMarshallerIdentifier(TypePositionInfo info, StubCodeCont /// /// Marshaller that enables support for a stackalloc constructor variant on a native type. /// - internal sealed class StatefulCallerAllocatedBufferMarshalling : ICustomTypeMarshallingStrategy + internal sealed class StatefulCallerAllocatedBufferMarshalling(ICustomTypeMarshallingStrategy innerMarshaller, TypeSyntax marshallerType, TypeSyntax bufferElementType) : ICustomTypeMarshallingStrategy { - private readonly ICustomTypeMarshallingStrategy _innerMarshaller; - private readonly TypeSyntax _marshallerType; - private readonly TypeSyntax _bufferElementType; - - public StatefulCallerAllocatedBufferMarshalling(ICustomTypeMarshallingStrategy innerMarshaller, TypeSyntax marshallerType, TypeSyntax bufferElementType) - { - _innerMarshaller = innerMarshaller; - _marshallerType = marshallerType; - _bufferElementType = bufferElementType; - } - - public ManagedTypeInfo AsNativeType(TypePositionInfo info) - { - return _innerMarshaller.AsNativeType(info); - } + public ManagedTypeInfo NativeType => innerMarshaller.NativeType; - public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(StubIdentifierContext context) { - return _innerMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(info, context); + return innerMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(context); } - public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(StubIdentifierContext context) { - return _innerMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(info, context); + return innerMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(context); } - public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateMarshalStatements(StubIdentifierContext context) { - if (MarshallerHelpers.CanUseCallerAllocatedBuffer(info, context)) + if (MarshallerHelpers.CanUseCallerAllocatedBuffer(TypeInfo, CodeContext)) { return GenerateCallerAllocatedBufferMarshalStatements(); } - return _innerMarshaller.GenerateMarshalStatements(info, context); + return innerMarshaller.GenerateMarshalStatements(context); IEnumerable GenerateCallerAllocatedBufferMarshalStatements() { - (string managedIdentifier, _) = context.GetIdentifiers(info); + (string managedIdentifier, _) = context.GetIdentifiers(TypeInfo); // .FromManaged(, stackalloc [.BufferSize]); yield return MethodInvocationStatement( - IdentifierName(context.GetAdditionalIdentifier(info, StatefulValueMarshalling.MarshallerIdentifier)), + IdentifierName(context.GetAdditionalIdentifier(TypeInfo, StatefulValueMarshalling.MarshallerIdentifier)), IdentifierName(ShapeMemberNames.Value.Stateful.FromManaged), Argument(IdentifierName(managedIdentifier)), Argument(StackAllocArrayCreationExpression( ArrayType( - _bufferElementType, + bufferElementType, SingletonList(ArrayRankSpecifier(SingletonSeparatedList( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerType, + marshallerType, IdentifierName(ShapeMemberNames.BufferSize))))))))); } } - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GeneratePinnedMarshalStatements(StubIdentifierContext context) { - return _innerMarshaller.GeneratePinnedMarshalStatements(info, context); + return innerMarshaller.GeneratePinnedMarshalStatements(context); } - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GeneratePinStatements(StubIdentifierContext context) { - return _innerMarshaller.GeneratePinStatements(info, context); + return innerMarshaller.GeneratePinStatements(context); } - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateSetupStatements(StubIdentifierContext context) { - return _innerMarshaller.GenerateSetupStatements(info, context); + return innerMarshaller.GenerateSetupStatements(context); } - public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateUnmarshalCaptureStatements(StubIdentifierContext context) { - return _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context); + return innerMarshaller.GenerateUnmarshalCaptureStatements(context); } - public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateUnmarshalStatements(StubIdentifierContext context) { - return _innerMarshaller.GenerateUnmarshalStatements(info, context); + return innerMarshaller.GenerateUnmarshalStatements(context); } - public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) - { - return _innerMarshaller.UsesNativeIdentifier(info, context); - } + public bool UsesNativeIdentifier => innerMarshaller.UsesNativeIdentifier; + + public TypePositionInfo TypeInfo => innerMarshaller.TypeInfo; - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context); - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); + public StubCodeContext CodeContext => innerMarshaller.CodeContext; + + public IEnumerable GenerateGuaranteedUnmarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateGuaranteedUnmarshalStatements(context); + public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(StubIdentifierContext context) => innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(context); } - internal sealed class StatefulLinearCollectionSource : IElementsMarshallingCollectionSource + internal sealed class StatefulLinearCollectionSource(TypePositionInfo info, StubCodeContext codeContext) : IElementsMarshallingCollectionSource { - public InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo info, StubCodeContext context) + public TypePositionInfo TypeInfo => info; + + public StubCodeContext CodeContext => codeContext; + + public InvocationExpressionSyntax GetUnmanagedValuesDestination(StubIdentifierContext context) { string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); @@ -292,7 +274,7 @@ public InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo IdentifierName(ShapeMemberNames.LinearCollection.Stateful.GetUnmanagedValuesDestination)); } - public InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetManagedValuesSource(StubIdentifierContext context) { string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); @@ -302,7 +284,7 @@ public InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, IdentifierName(ShapeMemberNames.LinearCollection.Stateful.GetManagedValuesSource)); } - public InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetUnmanagedValuesSource(StubIdentifierContext context) { string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); @@ -314,7 +296,7 @@ public InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info Argument(IdentifierName(numElementsIdentifier))); } - public InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetManagedValuesDestination(StubIdentifierContext context) { string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); @@ -330,37 +312,23 @@ public InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo i /// /// Marshaller that enables support for marshalling elements of a collection via a native type that implements the LinearCollection marshalling spec. /// - internal sealed class StatefulLinearCollectionMarshalling : ICustomTypeMarshallingStrategy + internal sealed class StatefulLinearCollectionMarshalling( + ICustomTypeMarshallingStrategy innerMarshaller, + MarshallerShape shape, + CountInfo countInfo, + bool castCountInfo, + ElementsMarshalling elementsMarshalling, + bool cleanupElements) : ICustomTypeMarshallingStrategy { - private readonly ICustomTypeMarshallingStrategy _innerMarshaller; - private readonly MarshallerShape _shape; - private readonly ExpressionSyntax _numElementsExpression; - private readonly ElementsMarshalling _elementsMarshalling; - private readonly bool _cleanupElements; - - public StatefulLinearCollectionMarshalling( - ICustomTypeMarshallingStrategy innerMarshaller, - MarshallerShape shape, - ExpressionSyntax numElementsExpression, - ElementsMarshalling elementsMarshalling, - bool cleanupElements) - { - _innerMarshaller = innerMarshaller; - _shape = shape; - _numElementsExpression = numElementsExpression; - _elementsMarshalling = elementsMarshalling; - _cleanupElements = cleanupElements; - } - - public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _innerMarshaller.AsNativeType(info); + public ManagedTypeInfo NativeType => innerMarshaller.NativeType; - public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(StubIdentifierContext context) { // We don't have anything to cleanup specifically related to this value, just the elements. We let the element marshaller decide whether to cleanup in callee or caller cleanup stage - if (!_cleanupElements) + if (!cleanupElements) yield break; - StatementSyntax elementCleanup = _elementsMarshalling.GenerateElementCleanupStatement(info, context); + StatementSyntax elementCleanup = elementsMarshalling.GenerateElementCleanupStatement(context); if (!elementCleanup.IsKind(SyntaxKind.EmptyStatement)) { @@ -368,13 +336,13 @@ public IEnumerable GenerateCleanupCallerAllocatedResourcesState } } - public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(StubIdentifierContext context) { // We don't have anything to cleanup specifically related to this value, just the elements. We let the element marshaller decide whether to cleanup in callee or caller cleanup stage - if (!_cleanupElements) + if (!cleanupElements) yield break; - StatementSyntax elementCleanup = _elementsMarshalling.GenerateElementCleanupStatement(info, context); + StatementSyntax elementCleanup = elementsMarshalling.GenerateElementCleanupStatement(context); if (!elementCleanup.IsKind(SyntaxKind.EmptyStatement)) { @@ -382,169 +350,178 @@ public IEnumerable GenerateCleanupCalleeAllocatedResourcesState } } - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context); + public IEnumerable GenerateGuaranteedUnmarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateGuaranteedUnmarshalStatements(context); - public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateMarshalStatements(StubIdentifierContext context) { - foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context)) + foreach (StatementSyntax statement in innerMarshaller.GenerateMarshalStatements(context)) { yield return statement; } - if (context.Direction == MarshalDirection.ManagedToUnmanaged && !info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out) + if (CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsByRef && TypeInfo.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. - yield return _elementsMarshalling.GenerateClearUnmanagedDestination(info, context); + yield return elementsMarshalling.GenerateClearUnmanagedDestination(context); yield break; } - if (context.Direction == MarshalDirection.UnmanagedToManaged && !info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) + if (CodeContext.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsByRef && TypeInfo.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) { // If the parameter is marshalled by-value [Out] or [In, Out], then we need to unmarshal the contents of the collection // into the passed-in collection value. - yield return _elementsMarshalling.GenerateUnmanagedToManagedByValueOutMarshalStatement(info, context); + yield return elementsMarshalling.GenerateUnmanagedToManagedByValueOutMarshalStatement(context); yield break; } - if (!_shape.HasFlag(MarshallerShape.ToUnmanaged) && !_shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) + if (!shape.HasFlag(MarshallerShape.ToUnmanaged) && !shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) yield break; - yield return _elementsMarshalling.GenerateMarshalStatement(info, context); + yield return elementsMarshalling.GenerateMarshalStatement(context); } - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinnedMarshalStatements(info, context); - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinStatements(info, context); - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(StubIdentifierContext context) => innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(context); + public IEnumerable GeneratePinnedMarshalStatements(StubIdentifierContext context) => innerMarshaller.GeneratePinnedMarshalStatements(context); + public IEnumerable GeneratePinStatements(StubIdentifierContext context) => innerMarshaller.GeneratePinStatements(context); + public IEnumerable GenerateSetupStatements(StubIdentifierContext context) { - foreach (StatementSyntax statement in _innerMarshaller.GenerateSetupStatements(info, context)) + foreach (StatementSyntax statement in innerMarshaller.GenerateSetupStatements(context)) { yield return statement; } - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - // int ; - yield return Declare( - PredefinedType(Token(SyntaxKind.IntKeyword)), - numElementsIdentifier, - initializeToDefault: false); + // When we're marshalling a collection and its elements only from managed to unmanaged, + // we don't need to declare the numElements local, as it's not used. + if (MarshallerHelpers.GetMarshalDirection(TypeInfo, CodeContext) is not MarshalDirection.ManagedToUnmanaged + || TypeInfo.ByValueContentsMarshalKind != ByValueContentsMarshalKind.Default) + { + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(TypeInfo, context); + // int ; + yield return Declare( + PredefinedType(Token(SyntaxKind.IntKeyword)), + numElementsIdentifier, + initializeToDefault: false); + + // Use the numElements local to ensure the compiler doesn't give errors for using an uninitialized variable. + // The value may be used in cleanup before it has been initialized, so this is not safe. + yield return MarshallerHelpers.SkipInitOrDefaultInit( + new TypePositionInfo(SpecialTypeInfo.Int32, NoMarshallingInfo.Instance) + { + InstanceIdentifier = numElementsIdentifier + }, context); + } - var elementsSetup = _elementsMarshalling.GenerateSetupStatement(info, context); + var elementsSetup = elementsMarshalling.GenerateSetupStatement(context); if (elementsSetup is not EmptyStatementSyntax) { yield return elementsSetup; } - // Use the numElements local to ensure the compiler doesn't give errors for using an uninitialized variable. - // The value may be used in cleanup before it has been initialized, so this is not safe. - yield return MarshallerHelpers.SkipInitOrDefaultInit( - new TypePositionInfo(SpecialTypeInfo.Int32, NoMarshallingInfo.Instance) - { - InstanceIdentifier = numElementsIdentifier - }, context); } - public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateUnmarshalStatements(StubIdentifierContext context) { - if (context.Direction == MarshalDirection.ManagedToUnmanaged && !info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) + if (CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsByRef && TypeInfo.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) { // If the parameter is marshalled by-value [Out] or [In, Out], then we need to unmarshal the contents of the collection // into the passed-in collection value. - yield return _elementsMarshalling.GenerateManagedToUnmanagedByValueOutUnmarshalStatement(info, context); + yield return elementsMarshalling.GenerateManagedToUnmanagedByValueOutUnmarshalStatement(context); yield break; } - if (context.Direction == MarshalDirection.UnmanagedToManaged && !info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out) + if (CodeContext.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsByRef && TypeInfo.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. - yield return _elementsMarshalling.GenerateClearManagedValuesDestination(info, context); + yield return elementsMarshalling.GenerateClearManagedValuesDestination(context); yield break; } - if (!_shape.HasFlag(MarshallerShape.ToManaged)) + if (!shape.HasFlag(MarshallerShape.ToManaged)) { yield break; } - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(TypeInfo, context); // = ; - yield return AssignmentStatement(IdentifierName(numElementsIdentifier), _numElementsExpression); + yield return AssignmentStatement(IdentifierName(numElementsIdentifier), ElementsMarshalling.GenerateNumElementsExpression(countInfo, castCountInfo, CodeContext, context)); - yield return _elementsMarshalling.GenerateUnmarshalStatement(info, context); + yield return elementsMarshalling.GenerateUnmarshalStatement(context); - foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, context)) + foreach (StatementSyntax statement in innerMarshaller.GenerateUnmarshalStatements(context)) { yield return statement; } } - public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context); + public IEnumerable GenerateUnmarshalCaptureStatements(StubIdentifierContext context) => innerMarshaller.GenerateUnmarshalCaptureStatements(context); + + public bool UsesNativeIdentifier => true; - public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; + public TypePositionInfo TypeInfo => innerMarshaller.TypeInfo; + + public StubCodeContext CodeContext => innerMarshaller.CodeContext; } /// /// Marshaller that enables calling the Free method on a stateful marshaller. /// - internal sealed class StatefulFreeMarshalling : ICustomTypeMarshallingStrategy + internal sealed class StatefulFreeMarshalling(ICustomTypeMarshallingStrategy innerMarshaller) : ICustomTypeMarshallingStrategy { - private readonly ICustomTypeMarshallingStrategy _innerMarshaller; + public ManagedTypeInfo NativeType => innerMarshaller.NativeType; - public StatefulFreeMarshalling(ICustomTypeMarshallingStrategy innerMarshaller) + public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(StubIdentifierContext context) { - _innerMarshaller = innerMarshaller; - } - - public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _innerMarshaller.AsNativeType(info); - - public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) - { - foreach (var statement in _innerMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(info, context)) + foreach (var statement in innerMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(context)) { yield return statement; } - if (MarshallerHelpers.GetCleanupStage(info, context) is not StubCodeContext.Stage.CleanupCallerAllocated) + if (MarshallerHelpers.GetCleanupStage(TypeInfo, CodeContext) is not StubIdentifierContext.Stage.CleanupCallerAllocated) yield break; - string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); + string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(TypeInfo, context); // .Free(); yield return MethodInvocationStatement( IdentifierName(marshaller), IdentifierName(ShapeMemberNames.Free)); } - public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(StubIdentifierContext context) { - foreach (var statement in _innerMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(info, context)) + foreach (var statement in innerMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(context)) { yield return statement; } - if (MarshallerHelpers.GetCleanupStage(info, context) is not StubCodeContext.Stage.CleanupCalleeAllocated) + if (MarshallerHelpers.GetCleanupStage(TypeInfo, CodeContext) is not StubIdentifierContext.Stage.CleanupCalleeAllocated) yield break; - string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(info, context); + string marshaller = StatefulValueMarshalling.GetMarshallerIdentifier(TypeInfo, context); // .Free(); yield return MethodInvocationStatement( IdentifierName(marshaller), IdentifierName(ShapeMemberNames.Free)); } - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context); - public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateMarshalStatements(info, context); + public IEnumerable GenerateGuaranteedUnmarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateGuaranteedUnmarshalStatements(context); + + public IEnumerable GenerateMarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateMarshalStatements(context); + + public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(StubIdentifierContext context) => innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(context); + public IEnumerable GeneratePinnedMarshalStatements(StubIdentifierContext context) => innerMarshaller.GeneratePinnedMarshalStatements(context); + public IEnumerable GeneratePinStatements(StubIdentifierContext context) => innerMarshaller.GeneratePinStatements(context); + public IEnumerable GenerateSetupStatements(StubIdentifierContext context) => innerMarshaller.GenerateSetupStatements(context); + + public IEnumerable GenerateUnmarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateUnmarshalStatements(context); - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinnedMarshalStatements(info, context); - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinStatements(info, context); - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateSetupStatements(info, context); + public IEnumerable GenerateUnmarshalCaptureStatements(StubIdentifierContext context) => innerMarshaller.GenerateUnmarshalCaptureStatements(context); - public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalStatements(info, context); + public bool UsesNativeIdentifier => innerMarshaller.UsesNativeIdentifier; - public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context); + public TypePositionInfo TypeInfo => innerMarshaller.TypeInfo; - public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.UsesNativeIdentifier(info, context); + public StubCodeContext CodeContext => innerMarshaller.CodeContext; } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs index b15cf616a4d53..ad4135078dc4f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs @@ -13,33 +13,23 @@ namespace Microsoft.Interop /// /// Stateless marshalling support for a type that has a custom unmanaged type. /// - internal sealed class StatelessValueMarshalling : ICustomTypeMarshallingStrategy + internal sealed class StatelessValueMarshalling(TypePositionInfo info, StubCodeContext codeContext, TypeSyntax marshallerTypeSyntax, ManagedTypeInfo unmanagedType, MarshallerShape shape) : ICustomTypeMarshallingStrategy { - private readonly TypeSyntax _marshallerTypeSyntax; - private readonly ManagedTypeInfo _unmanagedType; - private readonly MarshallerShape _shape; + public ManagedTypeInfo NativeType => unmanagedType; - public StatelessValueMarshalling(TypeSyntax marshallerTypeSyntax, ManagedTypeInfo unmanagedType, MarshallerShape shape) - { - _marshallerTypeSyntax = marshallerTypeSyntax; - _unmanagedType = unmanagedType; - _shape = shape; - } + public bool UsesNativeIdentifier => true; - public ManagedTypeInfo AsNativeType(TypePositionInfo info) - { - return _unmanagedType; - } + public TypePositionInfo TypeInfo => info; - public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; + public StubCodeContext CodeContext => codeContext; - public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); + public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(StubIdentifierContext context) => Array.Empty(); - public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); + public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(StubIdentifierContext context) => Array.Empty(); - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateGuaranteedUnmarshalStatements(StubIdentifierContext context) { - if (!_shape.HasFlag(MarshallerShape.GuaranteedUnmarshal)) + if (!shape.HasFlag(MarshallerShape.GuaranteedUnmarshal)) yield break; (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); @@ -51,15 +41,15 @@ public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePo IdentifierName(managedIdentifier), InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, + marshallerTypeSyntax, IdentifierName(ShapeMemberNames.Value.Stateless.ConvertToManagedFinally)), ArgumentList(SingletonSeparatedList( Argument(IdentifierName(nativeIdentifier))))))); } - public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateMarshalStatements(StubIdentifierContext context) { - if (!_shape.HasFlag(MarshallerShape.ToUnmanaged) && !_shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) + if (!shape.HasFlag(MarshallerShape.ToUnmanaged) && !shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) yield break; (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); @@ -67,12 +57,12 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i // .ConvertToUnmanaged() ExpressionSyntax convertToUnmanaged = InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, + marshallerTypeSyntax, IdentifierName(ShapeMemberNames.Value.Stateless.ConvertToUnmanaged)), ArgumentList(SingletonSeparatedList( Argument(IdentifierName(managedIdentifier))))); - if (_unmanagedType == SpecialTypeInfo.Void) + if (unmanagedType == SpecialTypeInfo.Void) { // To support our exception marshalling scenarios, we allow a "marshal to void" marshaller. // In this case, we don't assign the result to the native identifier because there is no native identifier. @@ -88,7 +78,7 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i convertToUnmanaged); - if (_unmanagedType is PointerTypeInfo pointer) + if (unmanagedType is PointerTypeInfo pointer) { var rewriter = new PointerNativeTypeAssignmentRewriter(assignment.Right.ToString(), (PointerTypeSyntax)pointer.Syntax); assignment = (AssignmentExpressionSyntax)rewriter.Visit(assignment); @@ -96,14 +86,14 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i yield return ExpressionStatement(assignment); } - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GeneratePinnedMarshalStatements(StubIdentifierContext context) { return Array.Empty(); } - public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateUnmarshalStatements(StubIdentifierContext context) { - if (!_shape.HasFlag(MarshallerShape.ToManaged)) + if (!shape.HasFlag(MarshallerShape.ToManaged)) yield break; (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); @@ -115,28 +105,28 @@ public IEnumerable GenerateUnmarshalStatements(TypePositionInfo IdentifierName(managedIdentifier), InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, + marshallerTypeSyntax, IdentifierName(ShapeMemberNames.Value.Stateless.ConvertToManaged)), ArgumentList(SingletonSeparatedList( Argument(IdentifierName(nativeIdentifier))))))); } - public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateUnmarshalCaptureStatements(StubIdentifierContext context) { return Array.Empty(); } - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateSetupStatements(StubIdentifierContext context) { return Array.Empty(); } - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GeneratePinStatements(StubIdentifierContext context) { return Array.Empty(); } - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(StubIdentifierContext context) { return Array.Empty(); } @@ -145,38 +135,27 @@ public IEnumerable GenerateNotifyForSuccessfulInvokeStatements( /// /// Marshaller that enables support for a stackalloc constructor variant on a native type. /// - internal sealed class StatelessCallerAllocatedBufferMarshalling : ICustomTypeMarshallingStrategy + internal sealed class StatelessCallerAllocatedBufferMarshalling(ICustomTypeMarshallingStrategy innerMarshaller, TypeSyntax marshallerType, TypeSyntax bufferElementType, bool isLinearCollectionMarshalling) : ICustomTypeMarshallingStrategy { - private readonly ICustomTypeMarshallingStrategy _innerMarshaller; - private readonly TypeSyntax _marshallerType; - private readonly TypeSyntax _bufferElementType; - private readonly bool _isLinearCollectionMarshalling; + public ManagedTypeInfo NativeType => innerMarshaller.NativeType; + public TypePositionInfo TypeInfo => innerMarshaller.TypeInfo; + public StubCodeContext CodeContext => innerMarshaller.CodeContext; + public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(StubIdentifierContext context) => innerMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(context); + public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(StubIdentifierContext context) => innerMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(context); + public IEnumerable GenerateGuaranteedUnmarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateGuaranteedUnmarshalStatements(context); - public StatelessCallerAllocatedBufferMarshalling(ICustomTypeMarshallingStrategy innerMarshaller, TypeSyntax marshallerType, TypeSyntax bufferElementType, bool isLinearCollectionMarshalling) + public IEnumerable GenerateMarshalStatements(StubIdentifierContext context) { - _innerMarshaller = innerMarshaller; - _marshallerType = marshallerType; - _bufferElementType = bufferElementType; - _isLinearCollectionMarshalling = isLinearCollectionMarshalling; - } - - public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _innerMarshaller.AsNativeType(info); - public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(info, context); - public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(info, context); - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context); - - public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) - { - if (MarshallerHelpers.CanUseCallerAllocatedBuffer(info, context)) + if (MarshallerHelpers.CanUseCallerAllocatedBuffer(TypeInfo, CodeContext)) { return GenerateCallerAllocatedBufferMarshalStatements(); } - return _innerMarshaller.GenerateMarshalStatements(info, context); + return innerMarshaller.GenerateMarshalStatements(context); IEnumerable GenerateCallerAllocatedBufferMarshalStatements() { - string bufferIdentifier = context.GetAdditionalIdentifier(info, "buffer"); + string bufferIdentifier = context.GetAdditionalIdentifier(TypeInfo, "buffer"); // Span = stackalloc [.BufferSize]; yield return LocalDeclarationStatement( @@ -184,24 +163,24 @@ IEnumerable GenerateCallerAllocatedBufferMarshalStatements() GenericName( Identifier(TypeNames.System_Span), TypeArgumentList( - SingletonSeparatedList(_bufferElementType))), + SingletonSeparatedList(bufferElementType))), SingletonSeparatedList( VariableDeclarator(bufferIdentifier) .WithInitializer(EqualsValueClause( StackAllocArrayCreationExpression( ArrayType( - _bufferElementType, + bufferElementType, SingletonList(ArrayRankSpecifier(SingletonSeparatedList( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerType, + marshallerType, IdentifierName(ShapeMemberNames.BufferSize)) )))))))))); - (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(TypeInfo); - if (_isLinearCollectionMarshalling) + if (isLinearCollectionMarshalling) { - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(TypeInfo, context); // = .AllocateContainerForUnmanagedElements(, , out ); yield return ExpressionStatement( @@ -210,7 +189,7 @@ IEnumerable GenerateCallerAllocatedBufferMarshalStatements() IdentifierName(nativeIdentifier), InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerType, + marshallerType, IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForUnmanagedElements)), ArgumentList(SeparatedList(new ArgumentSyntax[] { @@ -221,7 +200,7 @@ IEnumerable GenerateCallerAllocatedBufferMarshalStatements() }))))); // Linear collections have additional marshalling required using the inner marshaller - foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context)) + foreach (StatementSyntax statement in innerMarshaller.GenerateMarshalStatements(context)) { yield return statement; } @@ -235,7 +214,7 @@ IEnumerable GenerateCallerAllocatedBufferMarshalStatements() IdentifierName(nativeIdentifier), InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerType, + marshallerType, IdentifierName(ShapeMemberNames.Value.Stateless.ConvertToUnmanaged)), ArgumentList(SeparatedList(new ArgumentSyntax[] { @@ -246,35 +225,32 @@ IEnumerable GenerateCallerAllocatedBufferMarshalStatements() } } - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinnedMarshalStatements(info, context); - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinStatements(info, context); - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateSetupStatements(info, context); - public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context); - public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalStatements(info, context); - public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.UsesNativeIdentifier(info, context); + public IEnumerable GeneratePinnedMarshalStatements(StubIdentifierContext context) => innerMarshaller.GeneratePinnedMarshalStatements(context); + public IEnumerable GeneratePinStatements(StubIdentifierContext context) => innerMarshaller.GeneratePinStatements(context); + public IEnumerable GenerateSetupStatements(StubIdentifierContext context) => innerMarshaller.GenerateSetupStatements(context); + public IEnumerable GenerateUnmarshalCaptureStatements(StubIdentifierContext context) => innerMarshaller.GenerateUnmarshalCaptureStatements(context); + public IEnumerable GenerateUnmarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateUnmarshalStatements(context); + public bool UsesNativeIdentifier => innerMarshaller.UsesNativeIdentifier; - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); + public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(StubIdentifierContext context) => innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(context); } - internal sealed class StatelessFreeMarshalling : ICustomTypeMarshallingStrategy + internal sealed class StatelessFreeMarshalling(ICustomTypeMarshallingStrategy innerMarshaller, TypeSyntax marshallerType) : ICustomTypeMarshallingStrategy { - private readonly ICustomTypeMarshallingStrategy _innerMarshaller; - private readonly TypeSyntax _marshallerType; + public bool UsesNativeIdentifier => innerMarshaller.UsesNativeIdentifier; - public StatelessFreeMarshalling(ICustomTypeMarshallingStrategy innerMarshaller, TypeSyntax marshallerType) - { - _innerMarshaller = innerMarshaller; - _marshallerType = marshallerType; - } + public TypePositionInfo TypeInfo => innerMarshaller.TypeInfo; - public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _innerMarshaller.AsNativeType(info); + public StubCodeContext CodeContext => innerMarshaller.CodeContext; - public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public ManagedTypeInfo NativeType => innerMarshaller.NativeType; + + public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(StubIdentifierContext context) { - if (MarshallerHelpers.GetCleanupStage(info, context) is not StubCodeContext.Stage.CleanupCallerAllocated) + if (MarshallerHelpers.GetCleanupStage(TypeInfo, CodeContext) is not StubIdentifierContext.Stage.CleanupCallerAllocated) yield break; - foreach (StatementSyntax statement in _innerMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(info, context)) + foreach (StatementSyntax statement in innerMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(context)) { yield return statement; } @@ -282,18 +258,18 @@ public IEnumerable GenerateCleanupCallerAllocatedResourcesState yield return ExpressionStatement( InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerType, + marshallerType, IdentifierName(ShapeMemberNames.Free)), ArgumentList(SingletonSeparatedList( - Argument(IdentifierName(context.GetIdentifiers(info).native)))))); + Argument(IdentifierName(context.GetIdentifiers(TypeInfo).native)))))); } - public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(StubIdentifierContext context) { - if (MarshallerHelpers.GetCleanupStage(info, context) is not StubCodeContext.Stage.CleanupCalleeAllocated) + if (MarshallerHelpers.GetCleanupStage(TypeInfo, CodeContext) is not StubIdentifierContext.Stage.CleanupCalleeAllocated) yield break; - foreach (StatementSyntax statement in _innerMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(info, context)) + foreach (StatementSyntax statement in innerMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(context)) { yield return statement; } @@ -301,93 +277,85 @@ public IEnumerable GenerateCleanupCalleeAllocatedResourcesState yield return ExpressionStatement( InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerType, + marshallerType, IdentifierName(ShapeMemberNames.Free)), ArgumentList(SingletonSeparatedList( - Argument(IdentifierName(context.GetIdentifiers(info).native)))))); + Argument(IdentifierName(context.GetIdentifiers(TypeInfo).native)))))); } - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context); - public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateMarshalStatements(info, context); - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinnedMarshalStatements(info, context); - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinStatements(info, context); - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateSetupStatements(info, context); - public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context); - public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalStatements(info, context); - public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.UsesNativeIdentifier(info, context); + public IEnumerable GenerateGuaranteedUnmarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateGuaranteedUnmarshalStatements(context); + public IEnumerable GenerateMarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateMarshalStatements(context); + public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(StubIdentifierContext context) => innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(context); + public IEnumerable GeneratePinnedMarshalStatements(StubIdentifierContext context) => innerMarshaller.GeneratePinnedMarshalStatements(context); + public IEnumerable GeneratePinStatements(StubIdentifierContext context) => innerMarshaller.GeneratePinStatements(context); + public IEnumerable GenerateSetupStatements(StubIdentifierContext context) => innerMarshaller.GenerateSetupStatements(context); + public IEnumerable GenerateUnmarshalCaptureStatements(StubIdentifierContext context) => innerMarshaller.GenerateUnmarshalCaptureStatements(context); + public IEnumerable GenerateUnmarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateUnmarshalStatements(context); } /// /// Marshaller type that enables allocating space for marshalling a linear collection using a marshaller that implements the LinearCollection marshalling spec. /// - internal sealed class StatelessLinearCollectionSpaceAllocator : ICustomTypeMarshallingStrategy + internal sealed class StatelessLinearCollectionSpaceAllocator(TypePositionInfo info, StubCodeContext codeContext, TypeSyntax marshallerTypeSyntax, ManagedTypeInfo unmanagedType, MarshallerShape shape, CountInfo countInfo, bool countInfoRequiresCast) : ICustomTypeMarshallingStrategy { - private readonly TypeSyntax _marshallerTypeSyntax; - private readonly ManagedTypeInfo _unmanagedType; - private readonly MarshallerShape _shape; - private readonly ExpressionSyntax _numElementsExpression; + public ManagedTypeInfo NativeType => unmanagedType; - public StatelessLinearCollectionSpaceAllocator(TypeSyntax marshallerTypeSyntax, ManagedTypeInfo unmanagedType, MarshallerShape shape, ExpressionSyntax numElementsExpression) - { - _marshallerTypeSyntax = marshallerTypeSyntax; - _unmanagedType = unmanagedType; - _shape = shape; - _numElementsExpression = numElementsExpression; - } + public TypePositionInfo TypeInfo => info; - public ManagedTypeInfo AsNativeType(TypePositionInfo info) - { - return _unmanagedType; - } + public StubCodeContext CodeContext => codeContext; - public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(StubIdentifierContext context) { - if (MarshallerHelpers.GetCleanupStage(info, context) is not StubCodeContext.Stage.CleanupCallerAllocated) + // If we clean up in a different stage, we don't need to do anything here + if (MarshallerHelpers.GetCleanupStage(TypeInfo, CodeContext) is not StubIdentifierContext.Stage.CleanupCallerAllocated) yield break; - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - // = ; - yield return ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - IdentifierName(numElementsIdentifier), - _numElementsExpression)); + if (MarshallerHelpers.GetMarshalDirection(TypeInfo, CodeContext) != MarshalDirection.ManagedToUnmanaged) + { + // If we are marshalling from unmanaged to managed, we need to get the number of elements again. + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(TypeInfo, context); + // = ; + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(numElementsIdentifier), + ElementsMarshalling.GenerateNumElementsExpression(countInfo, countInfoRequiresCast, CodeContext, context))); + } } - public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(StubIdentifierContext context) { - if (MarshallerHelpers.GetCleanupStage(info, context) is not StubCodeContext.Stage.CleanupCalleeAllocated) + if (MarshallerHelpers.GetCleanupStage(TypeInfo, CodeContext) is not StubIdentifierContext.Stage.CleanupCalleeAllocated) yield break; - if (MarshallerHelpers.GetMarshalDirection(info, context) == MarshalDirection.ManagedToUnmanaged) + if (MarshallerHelpers.GetMarshalDirection(TypeInfo, CodeContext) == MarshalDirection.ManagedToUnmanaged) { yield return EmptyStatement(); yield break; } - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(TypeInfo, context); // = ; yield return ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(numElementsIdentifier), - _numElementsExpression)); + ElementsMarshalling.GenerateNumElementsExpression(countInfo, countInfoRequiresCast, CodeContext, context))); } - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateGuaranteedUnmarshalStatements(StubIdentifierContext context) { - if (!_shape.HasFlag(MarshallerShape.GuaranteedUnmarshal)) + if (!shape.HasFlag(MarshallerShape.GuaranteedUnmarshal)) yield break; - (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(TypeInfo); + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(TypeInfo, context); yield return ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(numElementsIdentifier), - _numElementsExpression)); + ElementsMarshalling.GenerateNumElementsExpression(countInfo, countInfoRequiresCast, CodeContext, context))); // = .AllocateContainerForManagedElementsFinally(, ); yield return ExpressionStatement( @@ -396,7 +364,7 @@ public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePo IdentifierName(managedIdentifier), InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, + marshallerTypeSyntax, IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForManagedElementsFinally)), ArgumentList(SeparatedList(new ArgumentSyntax[] { @@ -405,17 +373,17 @@ public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePo }))))); } - public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateMarshalStatements(StubIdentifierContext context) { - if (!_shape.HasFlag(MarshallerShape.ToUnmanaged) && !_shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) + if (!shape.HasFlag(MarshallerShape.ToUnmanaged) && !shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) yield break; - if (_shape.HasFlag(MarshallerShape.ToUnmanaged) - && !(_shape.HasFlag(MarshallerShape.CallerAllocatedBuffer) - && MarshallerHelpers.CanUseCallerAllocatedBuffer(info, context))) + if (shape.HasFlag(MarshallerShape.ToUnmanaged) + && !(shape.HasFlag(MarshallerShape.CallerAllocatedBuffer) + && MarshallerHelpers.CanUseCallerAllocatedBuffer(TypeInfo, CodeContext))) { - (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(TypeInfo); + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(TypeInfo, context); // = .AllocateContainerForUnmanagedElements(, out ); yield return ExpressionStatement( @@ -424,7 +392,7 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i IdentifierName(nativeIdentifier), InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, + marshallerTypeSyntax, IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForUnmanagedElements)), ArgumentList(SeparatedList(new ArgumentSyntax[] { @@ -435,13 +403,13 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i } } - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(StubIdentifierContext context) => Array.Empty(); + public IEnumerable GeneratePinnedMarshalStatements(StubIdentifierContext context) => Array.Empty(); + public IEnumerable GeneratePinStatements(StubIdentifierContext context) => Array.Empty(); + public IEnumerable GenerateSetupStatements(StubIdentifierContext context) { // int ; - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(TypeInfo, context); yield return LocalDeclarationStatement( VariableDeclaration( PredefinedType(Token(SyntaxKind.IntKeyword)), @@ -456,26 +424,26 @@ public IEnumerable GenerateSetupStatements(TypePositionInfo inf }, context); } - public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); + public IEnumerable GenerateUnmarshalCaptureStatements(StubIdentifierContext context) => Array.Empty(); - public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateUnmarshalStatements(StubIdentifierContext context) { - if (context.Direction == MarshalDirection.ManagedToUnmanaged && !info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) + if (CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsByRef && TypeInfo.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) { yield break; } - if (!_shape.HasFlag(MarshallerShape.ToManaged)) + if (!shape.HasFlag(MarshallerShape.ToManaged)) yield break; - (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(TypeInfo); + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(TypeInfo, context); yield return ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(numElementsIdentifier), - _numElementsExpression)); + ElementsMarshalling.GenerateNumElementsExpression(countInfo, countInfoRequiresCast, CodeContext, context))); // = .AllocateContainerForManagedElements(, ); yield return ExpressionStatement( @@ -484,7 +452,7 @@ public IEnumerable GenerateUnmarshalStatements(TypePositionInfo IdentifierName(managedIdentifier), InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, + marshallerTypeSyntax, IdentifierName(ShapeMemberNames.LinearCollection.Stateless.AllocateContainerForManagedElements)), ArgumentList(SeparatedList(new ArgumentSyntax[] { @@ -493,19 +461,16 @@ public IEnumerable GenerateUnmarshalStatements(TypePositionInfo }))))); } - public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; + public bool UsesNativeIdentifier => true; } - internal sealed class StatelessLinearCollectionSource : IElementsMarshallingCollectionSource + internal sealed class StatelessLinearCollectionSource(TypePositionInfo info, StubCodeContext codeContext, TypeSyntax marshallerTypeSyntax) : IElementsMarshallingCollectionSource { - private readonly TypeSyntax _marshallerTypeSyntax; + public TypePositionInfo TypeInfo => info; - public StatelessLinearCollectionSource(TypeSyntax marshallerTypeSyntax) - { - _marshallerTypeSyntax = marshallerTypeSyntax; - } + public StubCodeContext CodeContext => codeContext; - public InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetUnmanagedValuesDestination(StubIdentifierContext context) { string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); string nativeIdentifier = context.GetIdentifiers(info).native; @@ -514,7 +479,7 @@ public InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo return InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, + marshallerTypeSyntax, IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetUnmanagedValuesDestination)), ArgumentList(SeparatedList(new ArgumentSyntax[] { @@ -523,20 +488,20 @@ public InvocationExpressionSyntax GetUnmanagedValuesDestination(TypePositionInfo }))); } - public InvocationExpressionSyntax GetManagedValuesSource(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetManagedValuesSource(StubIdentifierContext context) { // .GetManagedValuesSource() string managedIdentifier = context.GetIdentifiers(info).managed; return InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, + marshallerTypeSyntax, IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetManagedValuesSource)), ArgumentList(SingletonSeparatedList( Argument(IdentifierName(managedIdentifier))))); } - public InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetUnmanagedValuesSource(StubIdentifierContext context) { string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); string nativeIdentifier = context.GetIdentifiers(info).native; @@ -545,7 +510,7 @@ public InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info return InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, + marshallerTypeSyntax, IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetUnmanagedValuesSource)), ArgumentList(SeparatedList(new ArgumentSyntax[] { @@ -554,7 +519,7 @@ public InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info }))); } - public InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context) + public InvocationExpressionSyntax GetManagedValuesDestination(StubIdentifierContext context) { string managedIdentifier = context.GetIdentifiers(info).managed; @@ -562,7 +527,7 @@ public InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo i return InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - _marshallerTypeSyntax, + marshallerTypeSyntax, IdentifierName(ShapeMemberNames.LinearCollection.Stateless.GetManagedValuesDestination)), ArgumentList(SingletonSeparatedList(Argument(IdentifierName(managedIdentifier))))); } @@ -571,186 +536,191 @@ public InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo i /// /// Marshaller that enables support for marshalling elements of a collection via a marshaller type that implements the contiguous collection marshalling shape. /// - internal sealed class StatelessLinearCollectionMarshalling : ICustomTypeMarshallingStrategy + internal sealed class StatelessLinearCollectionMarshalling( + ICustomTypeMarshallingStrategy spaceMarshallingStrategy, + ElementsMarshalling elementsMarshalling, + ManagedTypeInfo unmanagedType, + MarshallerShape shape, + CountInfo countInfo, + bool castCountInfo, + bool cleanupElementsAndSpace) : ICustomTypeMarshallingStrategy { - private readonly ICustomTypeMarshallingStrategy _spaceMarshallingStrategy; - private readonly ElementsMarshalling _elementsMarshalling; - private readonly ManagedTypeInfo _unmanagedType; - private readonly MarshallerShape _shape; - private readonly ExpressionSyntax _numElementsExpression; - private readonly bool _cleanupElementsAndSpace; - - public StatelessLinearCollectionMarshalling( - ICustomTypeMarshallingStrategy spaceMarshallingStrategy, - ElementsMarshalling elementsMarshalling, - ManagedTypeInfo unmanagedType, - MarshallerShape shape, - ExpressionSyntax numElementsExpression, - bool cleanupElementsAndSpace) - { - _spaceMarshallingStrategy = spaceMarshallingStrategy; - _elementsMarshalling = elementsMarshalling; - _unmanagedType = unmanagedType; - _shape = shape; - _numElementsExpression = numElementsExpression; - _cleanupElementsAndSpace = cleanupElementsAndSpace; - } + public bool UsesNativeIdentifier => true; + + public TypePositionInfo TypeInfo => spaceMarshallingStrategy.TypeInfo; + + public StubCodeContext CodeContext => spaceMarshallingStrategy.CodeContext; - public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _unmanagedType; + public ManagedTypeInfo NativeType => unmanagedType; - public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(StubIdentifierContext context) { - if (!_cleanupElementsAndSpace) + if (!cleanupElementsAndSpace) { yield break; } - StatementSyntax elementCleanup = _elementsMarshalling.GenerateElementCleanupStatement(info, context); + StatementSyntax elementCleanup = elementsMarshalling.GenerateElementCleanupStatement(context); if (!elementCleanup.IsKind(SyntaxKind.EmptyStatement)) { - // If we don't have the numElements variable still available from unmarshal or marshal stage, we need to reassign that again - if (!context.AdditionalTemporaryStateLivesAcrossStages) + // If we don't have the numElements variable still available from unmarshal or marshal stage, we need to reassign that again. + + if (!CodeContext.AdditionalTemporaryStateLivesAcrossStages) { - // = ; - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); - yield return ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - IdentifierName(numElementsIdentifier), - _numElementsExpression)); + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(TypeInfo, context); + if (countInfo is NoCountInfo && MarshallerHelpers.GetMarshalDirection(TypeInfo, CodeContext) == MarshalDirection.ManagedToUnmanaged) + { + // When marshalling from managed to unmanaged, we may not have count info. + // For now, just set to 0. + // See https://github.com/dotnet/runtime/issues/93423 for a tracking issue. + + // = 0; + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(numElementsIdentifier), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)))); + } + else + { + // = ; + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(numElementsIdentifier), + ElementsMarshalling.GenerateNumElementsExpression(countInfo, castCountInfo, CodeContext, context))); + } } yield return elementCleanup; } - if (MarshallerHelpers.GetCleanupStage(info, context) is StubCodeContext.Stage.CleanupCallerAllocated) + if (MarshallerHelpers.GetCleanupStage(TypeInfo, CodeContext) is StubIdentifierContext.Stage.CleanupCallerAllocated) { - foreach (var statement in _spaceMarshallingStrategy.GenerateCleanupCallerAllocatedResourcesStatements(info, context)) + foreach (var statement in spaceMarshallingStrategy.GenerateCleanupCallerAllocatedResourcesStatements(context)) { yield return statement; } } } - public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(StubIdentifierContext context) { - if (!_cleanupElementsAndSpace) + if (!cleanupElementsAndSpace) { yield break; } - StatementSyntax elementCleanup = _elementsMarshalling.GenerateElementCleanupStatement(info, context); + StatementSyntax elementCleanup = elementsMarshalling.GenerateElementCleanupStatement(context); if (!elementCleanup.IsKind(SyntaxKind.EmptyStatement)) { // If we don't have the numElements variable still available from unmarshal or marshal stage, we need to reassign that again - if (!context.AdditionalTemporaryStateLivesAcrossStages) + if (!CodeContext.AdditionalTemporaryStateLivesAcrossStages) { // = ; - string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(TypeInfo, context); yield return ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(numElementsIdentifier), - _numElementsExpression)); + ElementsMarshalling.GenerateNumElementsExpression(countInfo, castCountInfo, CodeContext, context))); } yield return elementCleanup; } - if (MarshallerHelpers.GetCleanupStage(info, context) is StubCodeContext.Stage.CleanupCallerAllocated) + if (MarshallerHelpers.GetCleanupStage(TypeInfo, CodeContext) is StubIdentifierContext.Stage.CleanupCallerAllocated) { - foreach (var statement in _spaceMarshallingStrategy.GenerateCleanupCalleeAllocatedResourcesStatements(info, context)) + foreach (var statement in spaceMarshallingStrategy.GenerateCleanupCalleeAllocatedResourcesStatements(context)) { yield return statement; } } } - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _spaceMarshallingStrategy.GenerateGuaranteedUnmarshalStatements(info, context); + public IEnumerable GenerateGuaranteedUnmarshalStatements(StubIdentifierContext context) => spaceMarshallingStrategy.GenerateGuaranteedUnmarshalStatements(context); - public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateMarshalStatements(StubIdentifierContext context) { - if (context.Direction == MarshalDirection.ManagedToUnmanaged && !info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out) + if (CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsByRef && TypeInfo.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. - yield return _elementsMarshalling.GenerateClearUnmanagedDestination(info, context); + yield return elementsMarshalling.GenerateClearUnmanagedDestination(context); yield break; } - if (context.Direction == MarshalDirection.UnmanagedToManaged && !info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) + if (CodeContext.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsByRef && TypeInfo.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) { // If the parameter is marshalled by-value [Out] or [In, Out], then we need to unmarshal the contents of the collection // into the passed-in collection value. - yield return _elementsMarshalling.GenerateUnmanagedToManagedByValueOutMarshalStatement(info, context); + yield return elementsMarshalling.GenerateUnmanagedToManagedByValueOutMarshalStatement(context); yield break; } - foreach (var statement in _spaceMarshallingStrategy.GenerateMarshalStatements(info, context)) + foreach (var statement in spaceMarshallingStrategy.GenerateMarshalStatements(context)) { yield return statement; } - if (!_shape.HasFlag(MarshallerShape.ToUnmanaged) && !_shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) + if (!shape.HasFlag(MarshallerShape.ToUnmanaged) && !shape.HasFlag(MarshallerShape.CallerAllocatedBuffer)) yield break; - yield return _elementsMarshalling.GenerateMarshalStatement(info, context); + yield return elementsMarshalling.GenerateMarshalStatement(context); } - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _spaceMarshallingStrategy.GenerateNotifyForSuccessfulInvokeStatements(info, context); - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _spaceMarshallingStrategy.GeneratePinnedMarshalStatements(info, context); - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _spaceMarshallingStrategy.GeneratePinStatements(info, context); + public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(StubIdentifierContext context) => spaceMarshallingStrategy.GenerateNotifyForSuccessfulInvokeStatements(context); + public IEnumerable GeneratePinnedMarshalStatements(StubIdentifierContext context) => spaceMarshallingStrategy.GeneratePinnedMarshalStatements(context); + public IEnumerable GeneratePinStatements(StubIdentifierContext context) => spaceMarshallingStrategy.GeneratePinStatements(context); - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateSetupStatements(StubIdentifierContext context) { - foreach (var s in _spaceMarshallingStrategy.GenerateSetupStatements(info, context)) + foreach (var s in spaceMarshallingStrategy.GenerateSetupStatements(context)) yield return s; - var elementsSetup = _elementsMarshalling.GenerateSetupStatement(info, context); + var elementsSetup = elementsMarshalling.GenerateSetupStatement(context); if (elementsSetup is not EmptyStatementSyntax) { yield return elementsSetup; } } - public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); + public IEnumerable GenerateUnmarshalCaptureStatements(StubIdentifierContext context) => Array.Empty(); - public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateUnmarshalStatements(StubIdentifierContext context) { - if (context.Direction == MarshalDirection.ManagedToUnmanaged && !info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) + if (CodeContext.Direction == MarshalDirection.ManagedToUnmanaged && !TypeInfo.IsByRef && TypeInfo.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) { // If the parameter is marshalled by-value [Out] or [In, Out], then we need to unmarshal the contents of the collection // into the passed-in collection value. - yield return _elementsMarshalling.GenerateManagedToUnmanagedByValueOutUnmarshalStatement(info, context); + yield return elementsMarshalling.GenerateManagedToUnmanagedByValueOutUnmarshalStatement(context); yield break; } - if (context.Direction == MarshalDirection.UnmanagedToManaged && !info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out) + if (CodeContext.Direction == MarshalDirection.UnmanagedToManaged && !TypeInfo.IsByRef && TypeInfo.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. - yield return _elementsMarshalling.GenerateClearManagedValuesDestination(info, context); - foreach (var statement in _spaceMarshallingStrategy.GenerateUnmarshalStatements(info, context)) + yield return elementsMarshalling.GenerateClearManagedValuesDestination(context); + foreach (var statement in spaceMarshallingStrategy.GenerateUnmarshalStatements(context)) { yield return statement; } yield break; } - if (!_shape.HasFlag(MarshallerShape.ToManaged)) + if (!shape.HasFlag(MarshallerShape.ToManaged)) { yield break; } else { - foreach (var statement in _spaceMarshallingStrategy.GenerateUnmarshalStatements(info, context)) + foreach (var statement in spaceMarshallingStrategy.GenerateUnmarshalStatements(context)) { yield return statement; } - yield return _elementsMarshalling.GenerateUnmarshalStatement(info, context); + yield return elementsMarshalling.GenerateUnmarshalStatement(context); } } - - public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs index 366d1877b9e04..dbb7fcabb2221 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StaticPinnableManagedValueMarshaller.cs @@ -14,31 +14,36 @@ public sealed class StaticPinnableManagedValueMarshaller(IBoundMarshallingGenera { public TypePositionInfo TypeInfo => innerMarshallingGenerator.TypeInfo; + public StubCodeContext CodeContext => innerMarshallingGenerator.CodeContext; + public ManagedTypeInfo NativeType => innerMarshallingGenerator.NativeType; public SignatureBehavior NativeSignatureBehavior => innerMarshallingGenerator.NativeSignatureBehavior; - public ValueBoundaryBehavior GetValueBoundaryBehavior(StubCodeContext context) + public ValueBoundaryBehavior ValueBoundaryBehavior { - if (IsPinningPathSupported(context)) + get { - if (NativeType.Syntax is PointerTypeSyntax pointerType - && pointerType.ElementType is PredefinedTypeSyntax predefinedType - && predefinedType.Keyword.IsKind(SyntaxKind.VoidKeyword)) + if (IsPinningPathSupported(CodeContext)) { - return ValueBoundaryBehavior.NativeIdentifier; + if (NativeType.Syntax is PointerTypeSyntax pointerType + && pointerType.ElementType is PredefinedTypeSyntax predefinedType + && predefinedType.Keyword.IsKind(SyntaxKind.VoidKeyword)) + { + return Interop.ValueBoundaryBehavior.NativeIdentifier; + } + + // Cast to native type if it is not void* + return Interop.ValueBoundaryBehavior.CastNativeIdentifier; } - // Cast to native type if it is not void* - return ValueBoundaryBehavior.CastNativeIdentifier; + return innerMarshallingGenerator.ValueBoundaryBehavior; } - - return innerMarshallingGenerator.GetValueBoundaryBehavior( context); } - public IEnumerable Generate(StubCodeContext context) + public IEnumerable Generate(StubIdentifierContext context) { - if (IsPinningPathSupported(context)) + if (IsPinningPathSupported(CodeContext)) { return GeneratePinningPath(context); } @@ -46,14 +51,17 @@ public IEnumerable Generate(StubCodeContext context) return innerMarshallingGenerator.Generate(context); } - public bool UsesNativeIdentifier(StubCodeContext context) + public bool UsesNativeIdentifier { - if (IsPinningPathSupported(context)) + get { - return false; - } + if (IsPinningPathSupported(CodeContext)) + { + return false; + } - return innerMarshallingGenerator.UsesNativeIdentifier(context); + return innerMarshallingGenerator.UsesNativeIdentifier; + } } private bool IsPinningPathSupported(StubCodeContext context) @@ -61,9 +69,9 @@ private bool IsPinningPathSupported(StubCodeContext context) return context.SingleFrameSpansNativeContext && !TypeInfo.IsByRef && !context.IsInStubReturnPosition(TypeInfo); } - private IEnumerable GeneratePinningPath(StubCodeContext context) + private IEnumerable GeneratePinningPath(StubIdentifierContext context) { - if (context.CurrentStage == StubCodeContext.Stage.Pin) + if (context.CurrentStage == StubIdentifierContext.Stage.Pin) { (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(innerMarshallingGenerator.TypeInfo); @@ -88,11 +96,9 @@ private IEnumerable GeneratePinningPath(StubCodeContext context } } - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context, out GeneratorDiagnostic? diagnostic) + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, out GeneratorDiagnostic? diagnostic) { - return innerMarshallingGenerator.SupportsByValueMarshalKind(marshalKind, context, out diagnostic); + return innerMarshallingGenerator.SupportsByValueMarshalKind(marshalKind, out diagnostic); } - - public IBoundMarshallingGenerator Rebind(TypePositionInfo info) => innerMarshallingGenerator.Rebind(info); } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/UnmanagedToManagedOwnershipTrackingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/UnmanagedToManagedOwnershipTrackingStrategy.cs index dd1b6a2e19209..03e384ca60e3f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/UnmanagedToManagedOwnershipTrackingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/UnmanagedToManagedOwnershipTrackingStrategy.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; @@ -13,24 +14,23 @@ namespace Microsoft.Interop /// Marshalling strategy that introduces a variable to hold the initial value of the provided and a variable to track if the original value has been replaced. /// /// - internal sealed class UnmanagedToManagedOwnershipTrackingStrategy : ICustomTypeMarshallingStrategy + internal sealed class UnmanagedToManagedOwnershipTrackingStrategy(ICustomTypeMarshallingStrategy innerMarshaller) : ICustomTypeMarshallingStrategy { - private readonly ICustomTypeMarshallingStrategy _innerMarshaller; + public ManagedTypeInfo NativeType => innerMarshaller.NativeType; - public UnmanagedToManagedOwnershipTrackingStrategy(ICustomTypeMarshallingStrategy innerMarshaller) - { - _innerMarshaller = innerMarshaller; - } + public bool UsesNativeIdentifier => innerMarshaller.UsesNativeIdentifier; - public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _innerMarshaller.AsNativeType(info); + public TypePositionInfo TypeInfo => innerMarshaller.TypeInfo; - public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(info, context); - public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(info, context); + public StubCodeContext CodeContext => innerMarshaller.CodeContext; - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context); - public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(StubIdentifierContext context) => innerMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(context); + public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(StubIdentifierContext context) => innerMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(context); + + public IEnumerable GenerateGuaranteedUnmarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateGuaranteedUnmarshalStatements(context); + public IEnumerable GenerateMarshalStatements(StubIdentifierContext context) { - foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context)) + foreach (StatementSyntax statement in innerMarshaller.GenerateMarshalStatements(context)) { yield return statement; } @@ -41,17 +41,17 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i // = true; yield return ExpressionStatement( AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, - IdentifierName(context.GetAdditionalIdentifier(info, OwnershipTrackingHelpers.OwnOriginalValueIdentifier)), + IdentifierName(context.GetAdditionalIdentifier(TypeInfo, OwnershipTrackingHelpers.OwnOriginalValueIdentifier)), LiteralExpression(SyntaxKind.TrueLiteralExpression))); } - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinnedMarshalStatements(info, context); + public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(StubIdentifierContext context) => innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(context); + public IEnumerable GeneratePinnedMarshalStatements(StubIdentifierContext context) => innerMarshaller.GeneratePinnedMarshalStatements(context); - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinStatements(info, context); - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GeneratePinStatements(StubIdentifierContext context) => innerMarshaller.GeneratePinStatements(context); + public IEnumerable GenerateSetupStatements(StubIdentifierContext context) { - foreach (StatementSyntax statement in _innerMarshaller.GenerateSetupStatements(info, context)) + foreach (StatementSyntax statement in innerMarshaller.GenerateSetupStatements(context)) { yield return statement; } @@ -62,96 +62,98 @@ public IEnumerable GenerateSetupStatements(TypePositionInfo inf PredefinedType(Token(SyntaxKind.BoolKeyword)), SingletonSeparatedList( VariableDeclarator( - Identifier(context.GetAdditionalIdentifier(info, OwnershipTrackingHelpers.OwnOriginalValueIdentifier)), + Identifier(context.GetAdditionalIdentifier(TypeInfo, OwnershipTrackingHelpers.OwnOriginalValueIdentifier)), null, EqualsValueClause( LiteralExpression(SyntaxKind.FalseLiteralExpression)))))); - yield return OwnershipTrackingHelpers.DeclareOriginalValueIdentifier(info, context, AsNativeType(info)); + yield return OwnershipTrackingHelpers.DeclareOriginalValueIdentifier(TypeInfo, context, NativeType); } - public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context); + public IEnumerable GenerateUnmarshalCaptureStatements(StubIdentifierContext context) => innerMarshaller.GenerateUnmarshalCaptureStatements(context); - public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalStatements(info, context); - public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.UsesNativeIdentifier(info, context); + public IEnumerable GenerateUnmarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateUnmarshalStatements(context); } /// /// Marshalling strategy that uses the tracking variables introduced by to cleanup the original value if the original value is owned - /// in the stage. + /// in the stage. /// - internal sealed class CleanupOwnedOriginalValueMarshalling : ICustomTypeMarshallingStrategy + internal sealed class CleanupOwnedOriginalValueMarshalling(ICustomTypeMarshallingStrategy innerMarshaller) : ICustomTypeMarshallingStrategy { - private readonly ICustomTypeMarshallingStrategy _innerMarshaller; + public ManagedTypeInfo NativeType => innerMarshaller.NativeType; - public CleanupOwnedOriginalValueMarshalling(ICustomTypeMarshallingStrategy innerMarshaller) - { - _innerMarshaller = innerMarshaller; - } + public bool UsesNativeIdentifier => innerMarshaller.UsesNativeIdentifier; + + public TypePositionInfo TypeInfo => innerMarshaller.TypeInfo; - public ManagedTypeInfo AsNativeType(TypePositionInfo info) => _innerMarshaller.AsNativeType(info); + public StubCodeContext CodeContext => innerMarshaller.CodeContext; - public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCallerAllocatedResourcesStatements(StubIdentifierContext context) { - if (MarshallerHelpers.GetCleanupStage(info, context) is not StubCodeContext.Stage.CleanupCallerAllocated) + if (MarshallerHelpers.GetCleanupStage(TypeInfo, CodeContext) is not StubIdentifierContext.Stage.CleanupCallerAllocated) yield break; // if () // { // // } yield return IfStatement( - IdentifierName(context.GetAdditionalIdentifier(info, OwnershipTrackingHelpers.OwnOriginalValueIdentifier)), - Block(_innerMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(info, new OwnedValueCodeContext(context)))); + IdentifierName(context.GetAdditionalIdentifier(TypeInfo, OwnershipTrackingHelpers.OwnOriginalValueIdentifier)), + Block(innerMarshaller.GenerateCleanupCallerAllocatedResourcesStatements(new OwnedValueCodeContext(context)))); } - public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(TypePositionInfo info, StubCodeContext context) + public IEnumerable GenerateCleanupCalleeAllocatedResourcesStatements(StubIdentifierContext context) { - if (MarshallerHelpers.GetCleanupStage(info, context) is not StubCodeContext.Stage.CleanupCalleeAllocated) + if (MarshallerHelpers.GetCleanupStage(TypeInfo, CodeContext) is not StubIdentifierContext.Stage.CleanupCalleeAllocated) yield break; // if () // { // // } yield return IfStatement( - IdentifierName(context.GetAdditionalIdentifier(info, OwnershipTrackingHelpers.OwnOriginalValueIdentifier)), - Block(_innerMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(info, new OwnedValueCodeContext(context)))); + IdentifierName(context.GetAdditionalIdentifier(TypeInfo, OwnershipTrackingHelpers.OwnOriginalValueIdentifier)), + Block(innerMarshaller.GenerateCleanupCalleeAllocatedResourcesStatements(new OwnedValueCodeContext(context)))); } - public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context); - public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateMarshalStatements(info, context); + public IEnumerable GenerateGuaranteedUnmarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateGuaranteedUnmarshalStatements(context); + public IEnumerable GenerateMarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateMarshalStatements(context); - public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); - public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinnedMarshalStatements(info, context); + public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(StubIdentifierContext context) => innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(context); + public IEnumerable GeneratePinnedMarshalStatements(StubIdentifierContext context) => innerMarshaller.GeneratePinnedMarshalStatements(context); - public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinStatements(info, context); - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateSetupStatements(info, context); + public IEnumerable GeneratePinStatements(StubIdentifierContext context) => innerMarshaller.GeneratePinStatements(context); + public IEnumerable GenerateSetupStatements(StubIdentifierContext context) => innerMarshaller.GenerateSetupStatements(context); - public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalCaptureStatements(info, context); + public IEnumerable GenerateUnmarshalCaptureStatements(StubIdentifierContext context) => innerMarshaller.GenerateUnmarshalCaptureStatements(context); - public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateUnmarshalStatements(info, context); - public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.UsesNativeIdentifier(info, context); + public IEnumerable GenerateUnmarshalStatements(StubIdentifierContext context) => innerMarshaller.GenerateUnmarshalStatements(context); } /// /// Marshalling strategy to cache the initial value of a given in a local variable and cleanup that value in the cleanup stage. - /// Useful in scenarios where the value is always owned in all code-paths that reach the stage, so additional ownership tracking is extraneous. + /// Useful in scenarios where the value is always owned in all code-paths that reach the stage, so additional ownership tracking is extraneous. /// internal sealed class FreeAlwaysOwnedOriginalValueGenerator(IBoundMarshallingGenerator inner) : IBoundMarshallingGenerator { + public ManagedTypeInfo NativeType => inner.NativeType; + public TypePositionInfo TypeInfo => inner.TypeInfo; - public ManagedTypeInfo NativeType => inner.NativeType; + public StubCodeContext CodeContext => inner.CodeContext; public SignatureBehavior NativeSignatureBehavior => inner.NativeSignatureBehavior; - public IEnumerable Generate(StubCodeContext context) + public bool UsesNativeIdentifier => inner.UsesNativeIdentifier; + public ValueBoundaryBehavior ValueBoundaryBehavior => inner.ValueBoundaryBehavior; + + public IEnumerable Generate(StubIdentifierContext context) { - if (context.CurrentStage == StubCodeContext.Stage.Setup) + if (context.CurrentStage == StubIdentifierContext.Stage.Setup) { return GenerateSetupStatements(); } - if (context.CurrentStage == StubCodeContext.Stage.CleanupCallerAllocated) + if (context.CurrentStage == StubIdentifierContext.Stage.CleanupCallerAllocated) { return GenerateStatementsFromInner(new OwnedValueCodeContext(context)); } @@ -160,44 +162,32 @@ public IEnumerable Generate(StubCodeContext context) IEnumerable GenerateSetupStatements() { - foreach (var statement in GenerateStatementsFromInner(context)) - { - yield return statement; - } - - yield return OwnershipTrackingHelpers.DeclareOriginalValueIdentifier(inner.TypeInfo, context, NativeType); + return [ + ..GenerateStatementsFromInner(new OwnedValueCodeContext(context)), + OwnershipTrackingHelpers.DeclareOriginalValueIdentifier(inner.TypeInfo, context, NativeType) + ]; } - IEnumerable GenerateStatementsFromInner(StubCodeContext contextForStage) + IEnumerable GenerateStatementsFromInner(StubIdentifierContext contextForStage) { return inner.Generate(contextForStage); } } - public ValueBoundaryBehavior GetValueBoundaryBehavior(StubCodeContext context) => inner.GetValueBoundaryBehavior(context); - public IBoundMarshallingGenerator Rebind(TypePositionInfo info) => new FreeAlwaysOwnedOriginalValueGenerator(inner.Rebind(info)); - public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context, out GeneratorDiagnostic? diagnostic) - => inner.SupportsByValueMarshalKind(marshalKind, context, out diagnostic); - public bool UsesNativeIdentifier(StubCodeContext context) => inner.UsesNativeIdentifier(context); + public ByValueMarshalKindSupport SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, out GeneratorDiagnostic? diagnostic) + => inner.SupportsByValueMarshalKind(marshalKind, out diagnostic); } -#pragma warning disable SA1400 // Access modifier should be declared https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3659 - file sealed record OwnedValueCodeContext : StubCodeContext -#pragma warning restore SA1400 // Access modifier should be declared + file sealed record OwnedValueCodeContext : StubIdentifierContext { - private readonly StubCodeContext _innerContext; + private readonly StubIdentifierContext _innerContext; - public OwnedValueCodeContext(StubCodeContext innerContext) + public OwnedValueCodeContext(StubIdentifierContext innerContext) { _innerContext = innerContext; CurrentStage = innerContext.CurrentStage; - Direction = innerContext.Direction; } - public override bool SingleFrameSpansNativeContext => _innerContext.SingleFrameSpansNativeContext; - - public override bool AdditionalTemporaryStateLivesAcrossStages => _innerContext.AdditionalTemporaryStateLivesAcrossStages; - public override (string managed, string native) GetIdentifiers(TypePositionInfo info) { var (managed, _) = _innerContext.GetIdentifiers(info); @@ -207,14 +197,12 @@ public override (string managed, string native) GetIdentifiers(TypePositionInfo public override string GetAdditionalIdentifier(TypePositionInfo info, string name) => _innerContext.GetAdditionalIdentifier(info, name); } -#pragma warning disable SA1400 // Access modifier should be declared https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3659 file static class OwnershipTrackingHelpers -#pragma warning restore SA1400 // Access modifier should be declared { public const string OwnOriginalValueIdentifier = "ownOriginal"; public const string OriginalValueIdentifier = "original"; - public static StatementSyntax DeclareOriginalValueIdentifier(TypePositionInfo info, StubCodeContext context, ManagedTypeInfo nativeType) + public static StatementSyntax DeclareOriginalValueIdentifier(TypePositionInfo info, StubIdentifierContext context, ManagedTypeInfo nativeType) { // = ; return LocalDeclarationStatement( diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/NativeToManagedStubCodeContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/NativeToManagedStubCodeContext.cs deleted file mode 100644 index 51c71838b76e2..0000000000000 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/NativeToManagedStubCodeContext.cs +++ /dev/null @@ -1,63 +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.Diagnostics; -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace Microsoft.Interop -{ - public sealed record NativeToManagedStubCodeContext : StubCodeContext - { - public override bool SingleFrameSpansNativeContext => false; - - public override bool AdditionalTemporaryStateLivesAcrossStages => true; - - private const string InvokeReturnIdentifier = "__invokeRetVal"; - private const string InvokeReturnIdentifierNative = "__invokeRetValUnmanaged"; - private readonly string _returnIdentifier; - private readonly string _nativeReturnIdentifier; - - public NativeToManagedStubCodeContext( - string returnIdentifier, - string nativeReturnIdentifier) - { - _returnIdentifier = returnIdentifier; - _nativeReturnIdentifier = nativeReturnIdentifier; - Direction = MarshalDirection.UnmanagedToManaged; - } - - public override (string managed, string native) GetIdentifiers(TypePositionInfo info) - { - // If the info is in the native return position, then we need to generate a name to use - // for both the managed and native values since there is no name in the signature for the return value. - if (info.IsNativeReturnPosition) - { - // If the info is in the native exception position, - // then we're going to return using name of the native return identifier. - // We use the provided instance identifier as that represents - // the name of the exception variable specified in the catch clause. - if (info.IsManagedExceptionPosition) - { - return (info.InstanceIdentifier, _nativeReturnIdentifier); - } - return (_returnIdentifier, _nativeReturnIdentifier); - } - // If the info is in the managed return position but is not in the native return position, - // then that means that the stub is introducing an additional info for the return position. - // This element can be in any position in the native signature, - // but since it isn't in the managed signature, there is no name in source for this info, so we must provide one here. - // We can't use ReturnIdentifier or ReturnNativeIdentifier since that will be used by the return value of the stub itself. - // As a result, we generate another name for the native return value. - if (info.IsManagedReturnPosition) - { - return (InvokeReturnIdentifier, InvokeReturnIdentifierNative); - } - - // If the info isn't in either the managed or native return position, - // then we can use the base implementation since we have an identifier name provided - // in the original metadata. - return base.GetIdentifiers(info); - } - } -} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SafeHandleMarshallingInfoProvider.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SafeHandleMarshallingInfoProvider.cs index 94635163c1b37..030dd7ab6720c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SafeHandleMarshallingInfoProvider.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SafeHandleMarshallingInfoProvider.cs @@ -13,34 +13,28 @@ namespace Microsoft.Interop /// /// This class supports generating marshalling info for SafeHandle-derived types. /// - public sealed class SafeHandleMarshallingInfoProvider : ITypeBasedMarshallingInfoProvider + public sealed class SafeHandleMarshallingInfoProvider(Compilation compilation) : ITypeBasedMarshallingInfoProvider { - private readonly Compilation _compilation; - private readonly INamedTypeSymbol _safeHandleMarshallerType; - private readonly ITypeSymbol _containingScope; - - public SafeHandleMarshallingInfoProvider(Compilation compilation, ITypeSymbol containingScope) - { - _compilation = compilation; - _safeHandleMarshallerType = compilation.GetBestTypeByMetadataName(TypeNames.System_Runtime_InteropServices_Marshalling_SafeHandleMarshaller_Metadata); - _containingScope = containingScope; - } + private readonly INamedTypeSymbol? _safeHandleType = compilation.GetBestTypeByMetadataName(TypeNames.System_Runtime_InteropServices_SafeHandle); + private readonly INamedTypeSymbol? _safeHandleMarshallerType = compilation.GetBestTypeByMetadataName(TypeNames.System_Runtime_InteropServices_Marshalling_SafeHandleMarshaller_Metadata); public bool CanProvideMarshallingInfoForType(ITypeSymbol type) { - // Check for an implicit SafeHandle conversion. + // Check if type derives from SafHandle // The SafeHandle type might not be defined if we're using one of the test CoreLib implementations used for NativeAOT. - ITypeSymbol? safeHandleType = _compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_SafeHandle); - if (safeHandleType is not null) + if (_safeHandleType is null) { - CodeAnalysis.Operations.CommonConversion conversion = _compilation.ClassifyCommonConversion(type, safeHandleType); - if (conversion.Exists - && conversion.IsImplicit - && (conversion.IsReference || conversion.IsIdentity)) + return false; + } + + for (ITypeSymbol? currentType = type; currentType is not null; currentType = currentType.BaseType) + { + if (currentType.Equals(_safeHandleType, SymbolEqualityComparer.Default)) { return true; } } + return false; } @@ -70,7 +64,7 @@ public MarshallingInfo GetMarshallingInfo(ITypeSymbol type, int indirectionDepth if (!ManualTypeMarshallingHelper.TryGetValueMarshallersFromEntryType( entryPointType, type, - _compilation, + compilation, out CustomTypeMarshallers? marshallers)) { return NoMarshallingInfo.Instance; 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 8d57df05486b2..7a39afb5c5d9c 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 @@ -3,142 +3,53 @@ using System; using System.Collections.Generic; +using System.Text; namespace Microsoft.Interop { - public abstract record StubCodeContext + /// + /// A description of how the code generator will combine the code from different stages of the stub and how it will call into any native context of the stub. + /// + /// The stub's code is emitted in a single frame and the native context is a callee of that frame. + /// Additional state defined by code generators is preserved across all stages of the generated stub. + /// General options that control how code is emitted. + /// The direction the stub is calling. + /// + /// Stubs that emit code into a single frame that spans the native context can do two things: + /// + /// A fixed statement can be used on an individual value in the stage and the pointer can be passed to native code. + /// Memory can be allocated via the stackalloc keyword and will live through the full native context of the call. + /// + /// + /// When is false, any additional variables can only be considered to have the state they had immediately after a setup phase. + /// + public sealed record StubCodeContext( + bool SingleFrameSpansNativeContext, + bool AdditionalTemporaryStateLivesAcrossStages, + MarshalDirection Direction) { - /// - /// Code generation stage - /// - public enum Stage - { - /// - /// Invalid stage - /// - Invalid, - - /// - /// Perform any setup required - /// - Setup, - - /// - /// Convert managed data to native data - /// - Marshal, - - /// - /// Pin data in preparation for calling the generated P/Invoke - /// - Pin, - - /// - /// Convert managed data to native data, assuming that any values pinned in the stage are pinned. - /// - PinnedMarshal, - - /// - /// Call the generated P/Invoke - /// - /// - /// should provide the - /// argument to pass to the P/Invoke - /// - Invoke, - - /// - /// Capture native values to ensure that we do not leak if an exception is thrown during unmarshalling - /// - UnmarshalCapture, - - /// - /// Convert native data to managed data - /// - Unmarshal, - - /// - /// Notify a marshaller object that the Invoke stage and all stages preceding the Invoke stage - /// successfully completed without any exceptions. - /// - NotifyForSuccessfulInvoke, + public static readonly StubCodeContext DefaultManagedToNativeStub = new( + SingleFrameSpansNativeContext: true, + AdditionalTemporaryStateLivesAcrossStages: true, + Direction: MarshalDirection.ManagedToUnmanaged); - /// - /// Perform any cleanup required on caller allocated resources - /// - CleanupCallerAllocated, + public static readonly StubCodeContext DefaultNativeToManagedStub = new( + SingleFrameSpansNativeContext: false, + AdditionalTemporaryStateLivesAcrossStages: true, + Direction: MarshalDirection.UnmanagedToManaged); - /// - /// Perform any cleanup required on callee allocated resources - /// - CleanupCalleeAllocated, - - /// - /// Convert native data to managed data even in the case of an exception during - /// the non-cleanup phases. - /// - GuaranteedUnmarshal - } - - public CodeEmitOptions CodeEmitOptions { get; init; } = new(SkipInit: true); - - /// - /// The current stage being generated. - /// - public Stage CurrentStage { get; init; } = Stage.Invalid; - - public MarshalDirection Direction { get; init; } = MarshalDirection.ManagedToUnmanaged; - - /// - /// The stub emits code that runs in a single stack frame and the frame spans over the native context. - /// - /// - /// Stubs that emit code into a single frame that spans the native context can do two things: - /// - /// A fixed statement can be used on an individual value in the stage and the pointer can be passed to native code. - /// Memory can be allocated via the stackalloc keyword and will live through the full native context of the call. - /// - /// - public abstract bool SingleFrameSpansNativeContext { get; } - - /// - /// Additional variables other than the {managedIdentifier} and {nativeIdentifier} variables can be added to the stub to track additional state for the marshaller in the stub in the Setup phase, and they will live across all phases of the stub. - /// - /// - /// When this property is false, any additional variables can only be considered to have the state they had immediately after the Setup phase. - /// - public abstract bool AdditionalTemporaryStateLivesAcrossStages { get; } - - /// - /// If this context is a nested context, return the parent context. Otherwise, return null. - /// - public StubCodeContext? ParentContext { get; protected init; } - - /// - /// Suffix for all generated native identifiers. - /// - public const string GeneratedNativeIdentifierSuffix = "_native"; - - /// - /// Get managed and native instance identifiers for the - /// - /// Object for which to get identifiers - /// Managed and native identifiers - public virtual (string managed, string native) GetIdentifiers(TypePositionInfo info) + public static StubCodeContext CreateElementMarshallingContext(StubCodeContext containingContext) { - return (info.InstanceIdentifier, $"__{info.InstanceIdentifier.TrimStart('@')}{GeneratedNativeIdentifierSuffix}"); + return new StubCodeContext( + SingleFrameSpansNativeContext: false, + AdditionalTemporaryStateLivesAcrossStages: false, + Direction: containingContext.Direction) + { + ElementIndirectionLevel = containingContext.ElementIndirectionLevel + 1, + }; } - /// - /// Compute identifiers that are unique for this generator - /// - /// TypePositionInfo the new identifier is used in service of. - /// Name of variable. - /// New identifier name for use. - public virtual string GetAdditionalIdentifier(TypePositionInfo info, string name) - { - return $"{GetIdentifiers(info).native}__{name}"; - } + public int ElementIndirectionLevel { get; init; } /// /// Compute if the provided element is the return element for the stub that is being generated (not any inner call). @@ -147,16 +58,7 @@ public virtual string GetAdditionalIdentifier(TypePositionInfo info, string name /// true if the element is in the return position for this stub; otherwise, false. public bool IsInStubReturnPosition(TypePositionInfo info) { - if (Direction == MarshalDirection.ManagedToUnmanaged) - { - return info.IsManagedReturnPosition; - } - else if (Direction == MarshalDirection.UnmanagedToManaged) - { - return info.IsNativeReturnPosition; - } - - throw new InvalidOperationException("Stub contexts should not be bidirectional"); + return MarshallerHelpers.IsInStubReturnPosition(info, Direction); } - } + }; } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubIdentifierContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubIdentifierContext.cs new file mode 100644 index 0000000000000..97b75be2babe2 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubIdentifierContext.cs @@ -0,0 +1,119 @@ +// 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; + +namespace Microsoft.Interop +{ + public abstract record StubIdentifierContext + { + /// + /// Code generation stage + /// + public enum Stage + { + /// + /// Invalid stage + /// + Invalid, + + /// + /// Perform any setup required + /// + Setup, + + /// + /// Convert managed data to native data + /// + Marshal, + + /// + /// Pin data in preparation for calling the generated P/Invoke + /// + Pin, + + /// + /// Convert managed data to native data, assuming that any values pinned in the stage are pinned. + /// + PinnedMarshal, + + /// + /// Call the generated P/Invoke + /// + /// + /// should provide the + /// argument to pass to the P/Invoke + /// + Invoke, + + /// + /// Capture native values to ensure that we do not leak if an exception is thrown during unmarshalling + /// + UnmarshalCapture, + + /// + /// Convert native data to managed data + /// + Unmarshal, + + /// + /// Notify a marshaller object that the Invoke stage and all stages preceding the Invoke stage + /// successfully completed without any exceptions. + /// + NotifyForSuccessfulInvoke, + + /// + /// Perform any cleanup required on caller allocated resources + /// + CleanupCallerAllocated, + + /// + /// Perform any cleanup required on callee allocated resources + /// + CleanupCalleeAllocated, + + /// + /// Convert native data to managed data even in the case of an exception during + /// the non-cleanup phases. + /// + GuaranteedUnmarshal + } + + /// + /// The current stage being generated. + /// + public Stage CurrentStage { get; init; } = Stage.Invalid; + + /// + /// Options to control how some code constructs are emitted. + /// + public CodeEmitOptions CodeEmitOptions { get; init; } + + /// + /// Suffix for all generated native identifiers. + /// + public const string GeneratedNativeIdentifierSuffix = "_native"; + + /// + /// Get managed and native instance identifiers for the + /// + /// Object for which to get identifiers + /// Managed and native identifiers + public virtual (string managed, string native) GetIdentifiers(TypePositionInfo info) + { + return (info.InstanceIdentifier, $"__{info.InstanceIdentifier.TrimStart('@')}{GeneratedNativeIdentifierSuffix}"); + } + + /// + /// Compute identifiers that are unique for this generator + /// + /// TypePositionInfo the new identifier is used in service of. + /// Name of variable. + /// New identifier name for use. + public virtual string GetAdditionalIdentifier(TypePositionInfo info, string name) + { + return $"{GetIdentifiers(info).native}__{name}"; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs index 69654c34c4f75..f3b6b790ec4d4 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs @@ -80,6 +80,11 @@ public static int IncrementIndex(int index) public int NativeIndex { get; init; } = UnsetIndex; public bool IsExplicitThis { get; init; } + public bool PositionsEqual(TypePositionInfo other) + { + return ManagedIndex == other.ManagedIndex && NativeIndex == other.NativeIndex; + } + public static TypePositionInfo CreateForParameter(IParameterSymbol paramSymbol, MarshallingInfo marshallingInfo, Compilation compilation) { var (byValueContentsMarshalKind, inLocation, outLocation) = GetByValueContentsMarshalKind(paramSymbol.GetAttributes(), compilation); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/VariableDeclarations.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/VariableDeclarations.cs index 76436ca50b299..fb10fd2f74aae 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/VariableDeclarations.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/VariableDeclarations.cs @@ -13,7 +13,7 @@ public struct VariableDeclarations { public ImmutableArray Initializations { get; init; } public ImmutableArray Variables { get; init; } - public static VariableDeclarations GenerateDeclarationsForManagedToUnmanaged(BoundGenerators marshallers, StubCodeContext context, bool initializeDeclarations) + public static VariableDeclarations GenerateDeclarationsForManagedToUnmanaged(BoundGenerators marshallers, StubIdentifierContext context, bool initializeDeclarations) { ImmutableArray.Builder initializations = ImmutableArray.CreateBuilder(); ImmutableArray.Builder variables = ImmutableArray.CreateBuilder(); @@ -52,7 +52,7 @@ public static VariableDeclarations GenerateDeclarationsForManagedToUnmanaged(Bou Variables = variables.ToImmutable() }; - static void AppendVariableDeclarations(ImmutableArray.Builder statementsToUpdate, IBoundMarshallingGenerator marshaller, StubCodeContext context, bool initializeToDefault) + static void AppendVariableDeclarations(ImmutableArray.Builder statementsToUpdate, IBoundMarshallingGenerator marshaller, StubIdentifierContext context, bool initializeToDefault) { (string managed, string native) = context.GetIdentifiers(marshaller.TypeInfo); @@ -66,7 +66,7 @@ static void AppendVariableDeclarations(ImmutableArray.Builder initializations = ImmutableArray.CreateBuilder(); ImmutableArray.Builder variables = ImmutableArray.CreateBuilder(); @@ -109,14 +109,14 @@ public static VariableDeclarations GenerateDeclarationsForUnmanagedToManaged(Bou Variables = variables.ToImmutable() }; - static void AppendVariableDeclarations(ImmutableArray.Builder statementsToUpdate, IBoundMarshallingGenerator marshaller, StubCodeContext context, bool initializeToDefault) + static void AppendVariableDeclarations(ImmutableArray.Builder statementsToUpdate, IBoundMarshallingGenerator marshaller, StubIdentifierContext context, bool initializeToDefault) { (string managed, string native) = context.GetIdentifiers(marshaller.TypeInfo); // Declare variable for return value if (marshaller.TypeInfo.IsNativeReturnPosition) { - bool nativeReturnUsesNativeIdentifier = marshaller.UsesNativeIdentifier(context); + bool nativeReturnUsesNativeIdentifier = marshaller.UsesNativeIdentifier; // Always initialize the return value. statementsToUpdate.Add(Declare( @@ -134,12 +134,12 @@ static void AppendVariableDeclarations(ImmutableArray CustomCollections() yield return new[] { ID(), customCollectionMarshallingCodeSnippets.Stateful.DefaultModeByValueInParameter }; yield return new[] { ID(), customCollectionMarshallingCodeSnippets.Stateful.DefaultModeReturnValue }; yield return new[] { ID(), customCollectionMarshallingCodeSnippets.Stateful.CustomElementMarshalling }; - yield return new[] { ID(), CodeSnippets.CollectionsOfCollectionsStress }; } [Theory] @@ -451,6 +450,12 @@ public async Task ValidateSnippets(string id, string source) await VerifyCS.VerifySourceGeneratorAsync(source); } + [Fact] + public async Task CollectionsOfCollectionsStress() + { + await VerifyCS.VerifySourceGeneratorAsync(CodeSnippets.CollectionsOfCollectionsStress); + } + public static IEnumerable CodeSnippetsToCompileWithPreprocessorSymbols() { yield return new object[] { ID(), CodeSnippets.PreprocessorIfAroundFullFunctionDefinition("Foo"), new string[] { "Foo" } }; diff --git a/src/libraries/System.Transactions.Local/System.Transactions.Local.sln b/src/libraries/System.Transactions.Local/System.Transactions.Local.sln index aab3e44e236fa..58eb24bb5b4ad 100644 --- a/src/libraries/System.Transactions.Local/System.Transactions.Local.sln +++ b/src/libraries/System.Transactions.Local/System.Transactions.Local.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35218.33 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{B67D04B7-C5ED-44ED-8DB3-8AD788232A5C}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Collections", "..\System.Collections\ref\System.Collections.csproj", "{6D254833-6EC5-4E3E-96CE-1D97CD66B35F}" @@ -39,11 +43,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{2ECC9D1A-2EF EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9D6D84CE-3891-482B-B7C0-0089CF93CF45}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "tools\gen", "{19FA1AAF-FBDF-4CF9-A432-8A98400E8598}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{19FA1AAF-FBDF-4CF9-A432-8A98400E8598}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "tools\src", "{29620C15-7580-40A6-A591-73A49C572FA2}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{29620C15-7580-40A6-A591-73A49C572FA2}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "tools\ref", "{C394810F-6A50-48E6-BCAB-91C55AEB92AA}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{C394810F-6A50-48E6-BCAB-91C55AEB92AA}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{770FE0B0-1496-4DBA-9E91-FAA63BE58272}" EndProject @@ -123,26 +127,30 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {B67D04B7-C5ED-44ED-8DB3-8AD788232A5C} = {E66BBFB5-F07D-4986-89C0-F0E395DD5BA1} - {C5519C4C-69AF-4437-8594-D2A019119988} = {E66BBFB5-F07D-4986-89C0-F0E395DD5BA1} {6D254833-6EC5-4E3E-96CE-1D97CD66B35F} = {B4E1F144-E017-4E02-8320-DB7467E42BF8} - {8D9731A5-CB30-4AAA-9A3B-9C937352623F} = {B4E1F144-E017-4E02-8320-DB7467E42BF8} - {7CC8FC26-F825-4B5D-9E38-6CE8382BEEAC} = {B4E1F144-E017-4E02-8320-DB7467E42BF8} - {0C886713-72D7-43C7-A1BB-72CD0F8430D2} = {B4E1F144-E017-4E02-8320-DB7467E42BF8} {75D2D615-58E5-41BB-9C57-FFC2F01B4931} = {2ECC9D1A-2EF1-4411-98D1-AFFCDAAF9D05} {693EEDDE-2643-4F1D-B531-1AB4D733B7F4} = {2ECC9D1A-2EF1-4411-98D1-AFFCDAAF9D05} {2A01A433-50B7-4CFA-AA76-CB51971535BB} = {2ECC9D1A-2EF1-4411-98D1-AFFCDAAF9D05} {193FBAA0-BAE2-484A-BB0E-1ADDDC810FC9} = {2ECC9D1A-2EF1-4411-98D1-AFFCDAAF9D05} + {8D9731A5-CB30-4AAA-9A3B-9C937352623F} = {B4E1F144-E017-4E02-8320-DB7467E42BF8} + {7CC8FC26-F825-4B5D-9E38-6CE8382BEEAC} = {B4E1F144-E017-4E02-8320-DB7467E42BF8} + {0C886713-72D7-43C7-A1BB-72CD0F8430D2} = {B4E1F144-E017-4E02-8320-DB7467E42BF8} {6BFF19CB-C412-4D12-AA55-68D61F69C4F7} = {9D6D84CE-3891-482B-B7C0-0089CF93CF45} + {C5519C4C-69AF-4437-8594-D2A019119988} = {E66BBFB5-F07D-4986-89C0-F0E395DD5BA1} {EB7DBBB8-0923-48C1-AB88-F3FF987C2449} = {19FA1AAF-FBDF-4CF9-A432-8A98400E8598} {14F12A3F-AA5E-4F20-B8E6-DFCCEE1FBB71} = {19FA1AAF-FBDF-4CF9-A432-8A98400E8598} - {19FA1AAF-FBDF-4CF9-A432-8A98400E8598} = {770FE0B0-1496-4DBA-9E91-FAA63BE58272} {2B4AEC4E-E5B8-402D-B938-65C8D8ED0248} = {29620C15-7580-40A6-A591-73A49C572FA2} {5345D79E-E437-431E-BB9C-65AC54626DC0} = {29620C15-7580-40A6-A591-73A49C572FA2} - {29620C15-7580-40A6-A591-73A49C572FA2} = {770FE0B0-1496-4DBA-9E91-FAA63BE58272} {95F76D76-11E8-4551-8786-D304D698C91B} = {C394810F-6A50-48E6-BCAB-91C55AEB92AA} + {19FA1AAF-FBDF-4CF9-A432-8A98400E8598} = {770FE0B0-1496-4DBA-9E91-FAA63BE58272} + {29620C15-7580-40A6-A591-73A49C572FA2} = {770FE0B0-1496-4DBA-9E91-FAA63BE58272} {C394810F-6A50-48E6-BCAB-91C55AEB92AA} = {770FE0B0-1496-4DBA-9E91-FAA63BE58272} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {197B13C9-4EA6-408B-8EF6-B551B2A58A89} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\..\tools\illink\src\ILLink.Shared\ILLink.Shared.projitems*{14f12a3f-aa5e-4f20-b8e6-dfccee1fbb71}*SharedItemsImports = 5 + ..\..\tools\illink\src\ILLink.Shared\ILLink.Shared.projitems*{5345d79e-e437-431e-bb9c-65ac54626dc0}*SharedItemsImports = 5 + EndGlobalSection EndGlobal