-
Notifications
You must be signed in to change notification settings - Fork 5.1k
[mono][wasm] marshal-ilgen is dropped when not required #86035
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
58fc204
Replicating naricc's PInvokeScanner.
jandupej 538ed14
MarshalingPInvokeScanner now detects and outputs incompatible assembl…
jandupej 927ad6b
Allowing void return type.
jandupej cfa8ded
PInvoke
jandupej 3954e44
Merge branch 'main' into marshal-analyzer-metadata
jandupej 2309940
Two-pass searching in progress.
jandupej a1e9294
Second pass resolves inconclusive types.
jandupej a70d7b6
Cleanup.
jandupej 6afe913
Merge branch 'main' into marshal-analyzer-metadata
jandupej 1f7c84b
Modifying the wasm toolchain to omit marshal-ilgen when possible.
jandupej dff107a
Hopefully fix incorrect app dir.
jandupej 5e9dabe
Added definitions to MarshalingPInvokeScannerPath hopefully where nee…
jandupej fd6a283
Adding definitions of MarshalingPInvokeScannerPath to more locations.
jandupej 082cf44
Adding missing references to PInvoke scanner.
jandupej 2c7d9c1
Changed task ordering, assemblies list.
jandupej d08e012
Removed metadata load context.
jandupej c2e83a9
Fixed code analyzer issues.
jandupej b3c5d6b
Fixed file name.
jandupej 018e20d
Moved MarshalingPInvokeScanner to MonoTargetsTask.
jandupej 41af118
Removed BlazorApp.
jandupej e9bee29
Implemented more marshaling validation rules, removed warning message…
jandupej 2299d21
Catching bad image exceptions, giving reason for requiring marshal-il…
jandupej c08b19a
Cleaned up references to standalone MarshalingPInvokeScanner project,…
jandupej dd1e1af
More cleanup.
jandupej 1156958
Fixed P/Invoke return value in marshal-lightweight.
jandupej 0205cee
Merge branch 'main' into marshal-analyzer-metadata
jandupej 46ddaea
Merge branch 'main' into marshal-analyzer-metadata
jandupej f4b60c7
Removed incompatible assemblies listing.
jandupej a54d680
Restoring minimal functionality to marshal-ilgen-stub.
jandupej cb1197b
Addressed feedback.
jandupej ad226d4
Tweaked identification of blittable types. Added explanation to Compa…
jandupej 8fc0bbe
Moved PInvokeCollector.cs and SignatureMapper.cs back to WasmAppBuilder.
jandupej c20beef
Addressed feedback.
jandupej File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
157 changes: 157 additions & 0 deletions
157
src/tasks/MonoTargetsTasks/MarshalingPInvokeScanner/MarshalingPInvokeScanner.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Runtime.CompilerServices; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Reflection.Metadata; | ||
using System.Reflection.Metadata.Ecma335; | ||
using System.Collections.Immutable; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Reflection; | ||
using System.Reflection.PortableExecutable; | ||
using Microsoft.Build.Framework; | ||
using Microsoft.Build.Utilities; | ||
|
||
jandupej marked this conversation as resolved.
Show resolved
Hide resolved
|
||
namespace MonoTargetsTasks | ||
{ | ||
public class MarshalingPInvokeScanner : Task | ||
{ | ||
[Required] | ||
public string[] Assemblies { get; set; } = Array.Empty<string>(); | ||
|
||
[Output] | ||
public string[]? IncompatibleAssemblies { get; private set; } | ||
|
||
public override bool Execute() | ||
{ | ||
if (Assemblies is null || Assemblies!.Length == 0) | ||
{ | ||
Log.LogError($"{nameof(MarshalingPInvokeScanner)}.{nameof(Assemblies)} cannot be empty"); | ||
return false; | ||
} | ||
|
||
try | ||
{ | ||
ExecuteInternal(); | ||
return !Log.HasLoggedErrors; | ||
} | ||
catch (LogAsErrorException e) | ||
{ | ||
Log.LogError(e.Message); | ||
return false; | ||
} | ||
} | ||
|
||
private void ExecuteInternal() | ||
{ | ||
IncompatibleAssemblies = ScanAssemblies(Assemblies); | ||
} | ||
|
||
private string[] ScanAssemblies(string[] assemblies) | ||
{ | ||
HashSet<string> incompatible = new HashSet<string>(); | ||
MinimalMarshalingTypeCompatibilityProvider mmtcp = new(Log); | ||
foreach (string aname in assemblies) | ||
{ | ||
if (IsAssemblyIncompatible(aname, mmtcp)) | ||
incompatible.Add(aname); | ||
} | ||
|
||
if (mmtcp.IsSecondPassNeeded) | ||
{ | ||
foreach (string aname in assemblies) | ||
ResolveInconclusiveTypes(incompatible, aname, mmtcp); | ||
} | ||
|
||
return incompatible.ToArray(); | ||
} | ||
|
||
private static string GetMethodName(MetadataReader mr, MethodDefinition md) => mr.GetString(md.Name); | ||
|
||
private void ResolveInconclusiveTypes(HashSet<string> incompatible, string assyPath, MinimalMarshalingTypeCompatibilityProvider mmtcp) | ||
{ | ||
string assyName = MetadataReader.GetAssemblyName(assyPath).Name!; | ||
HashSet<string> inconclusiveTypes = mmtcp.GetInconclusiveTypesForAssembly(assyName); | ||
if(inconclusiveTypes.Count == 0) | ||
return; | ||
|
||
using FileStream file = new FileStream(assyPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); | ||
using PEReader peReader = new PEReader(file); | ||
MetadataReader mdtReader = peReader.GetMetadataReader(); | ||
|
||
SignatureDecoder<Compatibility, object> decoder = new(mmtcp, mdtReader, null!); | ||
|
||
foreach (TypeDefinitionHandle typeDefHandle in mdtReader.TypeDefinitions) | ||
{ | ||
TypeDefinition typeDef = mdtReader.GetTypeDefinition(typeDefHandle); | ||
string fullTypeName = string.Join(":", mdtReader.GetString(typeDef.Namespace), mdtReader.GetString(typeDef.Name)); | ||
|
||
// This is not perfect, but should work right for enums defined in other assemblies, | ||
// which is the only case where we use Compatibility.Inconclusive. | ||
if (inconclusiveTypes.Contains(fullTypeName) && | ||
mmtcp.GetTypeFromDefinition(mdtReader, typeDefHandle, 0) != Compatibility.Compatible) | ||
{ | ||
Log.LogMessage(MessageImportance.Low, string.Format("Type {0} is marshaled and requires marshal-ilgen.", fullTypeName)); | ||
|
||
incompatible.Add("(unknown assembly)"); | ||
} | ||
} | ||
} | ||
|
||
private bool IsAssemblyIncompatible(string assyPath, MinimalMarshalingTypeCompatibilityProvider mmtcp) | ||
{ | ||
using FileStream file = new FileStream(assyPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); | ||
using PEReader peReader = new PEReader(file); | ||
MetadataReader mdtReader = peReader.GetMetadataReader(); | ||
|
||
foreach(CustomAttributeHandle attrHandle in mdtReader.CustomAttributes) | ||
{ | ||
CustomAttribute attr = mdtReader.GetCustomAttribute(attrHandle); | ||
|
||
if(attr.Constructor.Kind == HandleKind.MethodDefinition) | ||
{ | ||
MethodDefinitionHandle mdh = (MethodDefinitionHandle)attr.Constructor; | ||
MethodDefinition md = mdtReader.GetMethodDefinition(mdh); | ||
TypeDefinitionHandle tdh = md.GetDeclaringType(); | ||
TypeDefinition td = mdtReader.GetTypeDefinition(tdh); | ||
|
||
if(mdtReader.GetString(td.Namespace) == "System.Runtime.CompilerServices" && | ||
mdtReader.GetString(td.Name) == "DisableRuntimeMarshallingAttribute") | ||
return false; | ||
} | ||
} | ||
|
||
foreach (TypeDefinitionHandle typeDefHandle in mdtReader.TypeDefinitions) | ||
{ | ||
TypeDefinition typeDef = mdtReader.GetTypeDefinition(typeDefHandle); | ||
string ns = mdtReader.GetString(typeDef.Namespace); | ||
string name = mdtReader.GetString(typeDef.Name); | ||
|
||
foreach(MethodDefinitionHandle mthDefHandle in typeDef.GetMethods()) | ||
{ | ||
MethodDefinition mthDef = mdtReader.GetMethodDefinition(mthDefHandle); | ||
if(!mthDef.Attributes.HasFlag(MethodAttributes.PinvokeImpl)) | ||
continue; | ||
|
||
BlobReader sgnBlobReader = mdtReader.GetBlobReader(mthDef.Signature); | ||
SignatureDecoder<Compatibility, object> decoder = new(mmtcp, mdtReader, null!); | ||
|
||
MethodSignature<Compatibility> sgn = decoder.DecodeMethodSignature(ref sgnBlobReader); | ||
if(sgn.ReturnType == Compatibility.Incompatible || sgn.ParameterTypes.Any(p => p == Compatibility.Incompatible)) | ||
{ | ||
Log.LogMessage(MessageImportance.Low, string.Format("Assembly {0} requires marhsal-ilgen for method {1}.{2}:{3} (first pass).", | ||
assyPath, ns, name, mdtReader.GetString(mthDef.Name))); | ||
|
||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.