diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs index b4bf0941bdcdb..4ced83dc3bf5d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs @@ -109,7 +109,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) context.RegisterConcatenatedSyntaxOutputs(generateSingleStub.Select((data, ct) => data.Item1), "LibraryImports.g.cs"); } - private static List GenerateSyntaxForForwardedAttributes(AttributeData? suppressGCTransitionAttribute, AttributeData? unmanagedCallConvAttribute, AttributeData? defaultDllImportSearchPathsAttribute) + private static List GenerateSyntaxForForwardedAttributes(AttributeData? suppressGCTransitionAttribute, AttributeData? unmanagedCallConvAttribute, AttributeData? defaultDllImportSearchPathsAttribute, AttributeData? wasmImportLinkageAttribute) { const string CallConvsField = "CallConvs"; // Manually rehydrate the forwarded attributes with fully qualified types so we don't have to worry about any using directives. @@ -153,6 +153,10 @@ private static List GenerateSyntaxForForwardedAttributes(Attrib LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal((int)defaultDllImportSearchPathsAttribute.ConstructorArguments[0].Value!)))))); } + if (wasmImportLinkageAttribute is not null) + { + attributes.Add(Attribute(NameSyntaxes.WasmImportLinkageAttribute)); + } return attributes; } @@ -223,12 +227,14 @@ private static IncrementalStubGenerationContext CalculateStubInformation( INamedTypeSymbol? suppressGCTransitionAttrType = environment.SuppressGCTransitionAttrType; INamedTypeSymbol? unmanagedCallConvAttrType = environment.UnmanagedCallConvAttrType; INamedTypeSymbol? defaultDllImportSearchPathsAttrType = environment.DefaultDllImportSearchPathsAttrType; + INamedTypeSymbol? wasmImportLinkageAttrType = environment.WasmImportLinkageAttrType; // Get any attributes of interest on the method AttributeData? generatedDllImportAttr = null; AttributeData? lcidConversionAttr = null; AttributeData? suppressGCTransitionAttribute = null; AttributeData? unmanagedCallConvAttribute = null; AttributeData? defaultDllImportSearchPathsAttribute = null; + AttributeData? wasmImportLinkageAttribute = null; foreach (AttributeData attr in symbol.GetAttributes()) { if (attr.AttributeClass is not null @@ -252,6 +258,10 @@ private static IncrementalStubGenerationContext CalculateStubInformation( { defaultDllImportSearchPathsAttribute = attr; } + else if (wasmImportLinkageAttrType is not null && SymbolEqualityComparer.Default.Equals(attr.AttributeClass, wasmImportLinkageAttrType)) + { + wasmImportLinkageAttribute = attr; + } } Debug.Assert(generatedDllImportAttr is not null); @@ -299,7 +309,7 @@ private static IncrementalStubGenerationContext CalculateStubInformation( var methodSyntaxTemplate = new ContainingSyntax(originalSyntax.Modifiers, SyntaxKind.MethodDeclaration, originalSyntax.Identifier, originalSyntax.TypeParameterList); - List additionalAttributes = GenerateSyntaxForForwardedAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute, defaultDllImportSearchPathsAttribute); + List additionalAttributes = GenerateSyntaxForForwardedAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute, defaultDllImportSearchPathsAttribute, wasmImportLinkageAttribute); return new IncrementalStubGenerationContext( signatureContext, containingTypeContext, diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubEnvironment.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubEnvironment.cs index 81a769f1d3b6e..afa95ea0ef63e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubEnvironment.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubEnvironment.cs @@ -73,5 +73,19 @@ public INamedTypeSymbol? DefaultDllImportSearchPathsAttrType return _defaultDllImportSearchPathsAttrType.Value; } } + + private Optional _wasmImportLinkageAttrType; + public INamedTypeSymbol? WasmImportLinkageAttrType + { + get + { + if (_wasmImportLinkageAttrType.HasValue) + { + return _wasmImportLinkageAttrType.Value; + } + _wasmImportLinkageAttrType = new Optional(Compilation.GetTypeByMetadataName(TypeNames.WasmImportLinkageAttribute)); + return _wasmImportLinkageAttrType.Value; + } + } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs index 818e9d0094941..2fe9b606b21ea 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs @@ -39,6 +39,9 @@ public static class NameSyntaxes private static NameSyntax? _UnmanagedCallersOnlyAttribute; public static NameSyntax UnmanagedCallersOnlyAttribute => _UnmanagedCallersOnlyAttribute ??= ParseName(TypeNames.GlobalAlias + TypeNames.UnmanagedCallersOnlyAttribute); + + private static NameSyntax? _WasmImportLinkageAttribute; + public static NameSyntax WasmImportLinkageAttribute => _WasmImportLinkageAttribute ??= ParseName(TypeNames.GlobalAlias + TypeNames.WasmImportLinkageAttribute); } public static class TypeSyntaxes @@ -312,5 +315,6 @@ public static string MarshalEx(InteropGenerationOptions options) public const string CallConvMemberFunctionName = "System.Runtime.CompilerServices.CallConvMemberFunction"; public const string Nint = "nint"; public const string ComVariantMarshaller = "System.Runtime.InteropServices.Marshalling.ComVariantMarshaller"; + public const string WasmImportLinkageAttribute = "System.Runtime.InteropServices.WasmImportLinkageAttribute"; } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AttributeForwarding.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AttributeForwarding.cs index 4abb9a12c1dd0..5a2b4ba19468f 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AttributeForwarding.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AttributeForwarding.cs @@ -21,6 +21,7 @@ public class AttributeForwarding [Theory] [InlineData("SuppressGCTransition", "System.Runtime.InteropServices.SuppressGCTransitionAttribute")] [InlineData("UnmanagedCallConv", "System.Runtime.InteropServices.UnmanagedCallConvAttribute")] + [InlineData("WasmImportLinkage", "System.Runtime.InteropServices.WasmImportLinkageAttribute")] public async Task KnownParameterlessAttribute(string attributeSourceName, string attributeMetadataName) { string source = $$"""