Skip to content
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

[wasm] Don't log errors for unsupported cases in PInvokeCollector #113212

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions src/tasks/WasmAppBuilder/IcallTableGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,11 @@ private void ProcessType(Type type)

try
{
AddSignature(type, method);
AddSignatureForMethod(method);
}
catch (Exception ex) when (ex is not LogAsErrorException)
catch (Exception ex)
{
Log.Warning("WASM0001", $"Could not get icall, or callbacks for method '{type.FullName}::{method.Name}' because '{ex.Message}'");
Log.Warning("WASM0001", $"Skipping '{type.FullName}.{method.Name}' because processing it caused an exception: {ex}");
continue;
}

Expand Down Expand Up @@ -193,7 +193,7 @@ private void ProcessType(Type type)
}
catch (NotImplementedException nie)
{
Log.Warning("WASM0001", $"Failed to generate icall function for method '[{method.DeclaringType!.Assembly.GetName().Name}] {className}::{method.Name}'" +
Log.Warning("WASM0001", $"Failed to generate icall function for method '[{method.DeclaringType!.Assembly.GetName().Name}] {className}.{method.Name}'" +
$" because type '{nie.Message}' is not supported for parameter named '{par.Name}'. Ignoring.");
return null;
}
Expand All @@ -204,15 +204,13 @@ private void ProcessType(Type type)
return sig.ToString();
}

void AddSignature(Type type, MethodInfo method)
void AddSignatureForMethod(MethodInfo method)
{
string? signature = SignatureMapper.MethodToSignature(method, Log);
if (signature == null)
{
throw new LogAsErrorException($"Unsupported parameter type in method '{type.FullName}.{method.Name}'");
}

if (_signatures.Add(signature))
if (signature == null)
Log.Warning("WASM0001", $"Skipping method '{type.FullName}.{method.Name}' because the icall signature couldn't be determined.");
else if (_signatures.Add(signature))
Log.LogMessage(MessageImportance.Low, $"Adding icall signature {signature} for method '{type.FullName}.{method.Name}'");
}
}
Expand Down
90 changes: 33 additions & 57 deletions src/tasks/WasmAppBuilder/PInvokeCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,33 +68,36 @@ public PInvokeCollector(LogAdapter log)

public void CollectPInvokes(List<PInvoke> pinvokes, List<PInvokeCallback> callbacks, HashSet<string> signatures, Type type)
{
foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
try
{
try
foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
{
CollectPInvokesForMethod(method);
if (DoesMethodHaveCallbacks(method, Log))
if (DoesMethodHaveCallbacks(method))
callbacks.Add(new PInvokeCallback(method));
}
catch (Exception ex) when (ex is not LogAsErrorException)

if (PInvokeTableGenerator.HasAttribute(type, "System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute"))
{
Log.Warning("WASM0001", $"Could not get pinvoke, or callbacks for method '{type.FullName}::{method.Name}' because '{ex}'");
var method = type.GetMethod("Invoke");

if (method != null)
AddSignatureForMethod(method);
}
}

if (HasAttribute(type, "System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute"))
catch (Exception ex)
{
var method = type.GetMethod("Invoke");
Log.Warning("WASM0001", $"Skipping type '{type.FullName}' because processing it caused an exception: {ex}");
}

if (method != null)
{
string? signature = SignatureMapper.MethodToSignature(method!, Log);
if (signature == null)
throw new NotSupportedException($"Unsupported parameter type in method '{type.FullName}.{method.Name}'");
void AddSignatureForMethod(MethodInfo method)
{
string? signature = SignatureMapper.MethodToSignature(method, Log);

if (signatures.Add(signature))
Log.LogMessage(MessageImportance.Low, $"Adding pinvoke signature {signature} for method '{type.FullName}.{method.Name}'");
}
if (signature == null)
Log.Warning("WASM0001", $"Skipping method '{type.FullName}.{method.Name}' because the pinvoke signature couldn't be determined.");
else if (signatures.Add(signature))
Log.LogMessage(MessageImportance.Low, $"Adding pinvoke signature {signature} for method '{type.FullName}.{method.Name}'");
}

void CollectPInvokesForMethod(MethodInfo method)
Expand All @@ -107,25 +110,18 @@ void CollectPInvokesForMethod(MethodInfo method)
var entrypoint = (string)dllimport.NamedArguments.First(arg => arg.MemberName == "EntryPoint").TypedValue.Value!;
pinvokes.Add(new PInvoke(entrypoint, module, method, wasmLinkage));

string? signature = SignatureMapper.MethodToSignature(method, Log);
if (signature == null)
{
throw new NotSupportedException($"Unsupported parameter type in method '{type.FullName}.{method.Name}'");
}

if (signatures.Add(signature))
Log.LogMessage(MessageImportance.Low, $"Adding pinvoke signature {signature} for method '{type.FullName}.{method.Name}'");
AddSignatureForMethod(method);
}
}

bool DoesMethodHaveCallbacks(MethodInfo method, LogAdapter log)
bool DoesMethodHaveCallbacks(MethodInfo method)
{
if (!MethodHasCallbackAttributes(method))
return false;

if (TryIsMethodGetParametersUnsupported(method, out string? reason))
if (PInvokeTableGenerator.TryIsMethodGetParametersUnsupported(method, out string? reason))
{
Log.Warning("WASM0001", $"Skipping callback '{method.DeclaringType!.FullName}::{method.Name}' because '{reason}'.");
Log.Warning("WASM0001", $"Skipping callback '{type.FullName}.{method.Name}' because '{reason}'.");
return false;
}

Expand All @@ -135,13 +131,19 @@ bool DoesMethodHaveCallbacks(MethodInfo method, LogAdapter log)
// No DisableRuntimeMarshalling attribute, so check if the params/ret-type are
// blittable
bool isVoid = method.ReturnType.FullName == "System.Void";
if (!isVoid && !IsBlittable(method.ReturnType, log))
Error($"The return type '{method.ReturnType.FullName}' of pinvoke callback method '{method}' needs to be blittable.");
if (!isVoid && !PInvokeTableGenerator.IsBlittable(method.ReturnType, Log))
{
Log.Warning("WASM0001", $"Skipping callback '{type.FullName}.{method.Name}' because the return type '{method.ReturnType.FullName}' isn't blittable.");
return false;
}

foreach (var p in method.GetParameters())
{
if (!IsBlittable(p.ParameterType, log))
Error("Parameter types of pinvoke callback method '" + method + "' needs to be blittable.");
if (!PInvokeTableGenerator.IsBlittable(p.ParameterType, Log))
{
Log.Warning("WASM0001", $"Skipping callback '{type.FullName}.{method.Name}' because the parameter type '{p.ParameterType.FullName}' isn't blittable.");
return false;
}
}

return true;
Expand Down Expand Up @@ -169,32 +171,6 @@ static bool MethodHasCallbackAttributes(MethodInfo method)
}
}

public static bool IsBlittable(Type type, LogAdapter log) => PInvokeTableGenerator.IsBlittable(type, log);

private static void Error(string msg) => throw new LogAsErrorException(msg);

internal static bool HasAttribute(MemberInfo element, params string[] attributeNames) => PInvokeTableGenerator.HasAttribute(element, attributeNames);

private static bool TryIsMethodGetParametersUnsupported(MethodInfo method, [NotNullWhen(true)] out string? reason)
{
try
{
method.GetParameters();
}
catch (NotSupportedException nse)
{
reason = nse.Message;
return true;
}
catch
{
// not concerned with other exceptions
}

reason = null;
return false;
}

private bool HasAssemblyDisableRuntimeMarshallingAttribute(Assembly assembly)
{
if (!_assemblyDisableRuntimeMarshallingAttributeCache.TryGetValue(assembly, out var value))
Expand Down
4 changes: 2 additions & 2 deletions src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ private static string PickCTypeNameForUnknownType(Type t)

// FIXME: System.Reflection.MetadataLoadContext can't decode function pointer types
// https://github.com/dotnet/runtime/issues/43791
private static bool TryIsMethodGetParametersUnsupported(MethodInfo method, [NotNullWhen(true)] out string? reason)
public static bool TryIsMethodGetParametersUnsupported(MethodInfo method, [NotNullWhen(true)] out string? reason)
{
try
{
Expand Down Expand Up @@ -267,7 +267,7 @@ private static bool TryIsMethodGetParametersUnsupported(MethodInfo method, [NotN
{
// Don't use method.ToString() or any of it's parameters, or return type
// because at least one of those are unsupported, and will throw
Log.Warning("WASM0001", $"Skipping pinvoke '{pinvoke.Method.DeclaringType!.FullName}::{pinvoke.Method.Name}' because '{reason}'.");
Log.Warning("WASM0001", $"Skipping pinvoke '{pinvoke.Method.DeclaringType!.FullName}.{pinvoke.Method.Name}' because '{reason}'.");

pinvoke.Skip = true;
return null;
Expand Down
Loading