Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

NotImplementedException thrown when trying to compile with function pointers #8199

Closed
john-h-k opened this issue Jun 9, 2020 · 15 comments · Fixed by #8200
Closed

NotImplementedException thrown when trying to compile with function pointers #8199

john-h-k opened this issue Jun 9, 2020 · 15 comments · Fixed by #8200

Comments

@john-h-k
Copy link
Contributor

john-h-k commented Jun 9, 2020

I try to build my project as the samples suggest (The project doesn't use reflection anywhere, unless 'REFLECTION' is defined which it isn't here).

I get this output with absolutely nothing else

     at ILCompiler.MetadataManager.IsReflectionBlocked(TypeDesc type)
     at ILCompiler.MetadataManager.IsReflectionBlocked(Instantiation instantiation)
     at ILCompiler.MetadataManager.IsReflectionBlocked(MethodDesc method)
     at ILCompiler.DependencyAnalysis.ExactMethodInstantiationsNode.IsMethodEligibleForTracking(NodeFactory factory, MethodDesc method)
     at ILCompiler.DependencyAnalysis.ExactMethodInstantiationsNode.GetExactMethodInstantiationDependenciesForMethod(DependencyList& dependencies, NodeFactory factory, MethodDesc method)
     at ILCompiler.MetadataManager.GetDependenciesDueToReflectability(DependencyList& dependencies, NodeFactory factory, MethodDesc method)
     at ILCompiler.DependencyAnalysis.CodeBasedDependencyAlgorithm.AddDependenciesDueToMethodCodePresence(DependencyList& dependencies, NodeFactory factory, MethodDesc method)
     at ILCompiler.DependencyAnalysis.ScannedMethodNode.InitializeDependencies(NodeFactory factory, IEnumerable`1 dependencies)
     at ILCompiler.ILScanner.CompileSingleMethod(ScannedMethodNode methodCodeNodeNeedingCode)
     at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
  --- End of stack trace from previous location where exception was thrown ---
     at System.Threading.ThreadPoolWorkQueue.Dispatch()
  System.NotImplementedException: The method or operation is not implemented.
     at ILCompiler.MetadataManager.IsReflectionBlocked(TypeDesc type)
     at ILCompiler.MetadataManager.IsReflectionBlocked(Instantiation instantiation)
     at ILCompiler.MetadataManager.IsReflectionBlocked(MethodDesc method)
     at ILCompiler.DependencyAnalysis.ExactMethodInstantiationsNode.IsMethodEligibleForTracking(NodeFactory factory, MethodDesc method)
     at ILCompiler.DependencyAnalysis.ExactMethodInstantiationsNode.GetExactMethodInstantiationDependenciesForMethod(DependencyList& dependencies, NodeFactory factory, MethodDesc method)
     at ILCompiler.MetadataManager.GetDependenciesDueToReflectability(DependencyList& dependencies, NodeFactory factory, MethodDesc method)
     at ILCompiler.DependencyAnalysis.CodeBasedDependencyAlgorithm.AddDependenciesDueToMethodCodePresence(DependencyList& dependencies, NodeFactory factory, MethodDesc method)
     at ILCompiler.DependencyAnalysis.ScannedMethodNode.InitializeDependencies(NodeFactory factory, IEnumerable`1 dependencies)
     at ILCompiler.ILScanner.CompileSingleMethod(ScannedMethodNode methodCodeNodeNeedingCode)
     at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
  --- End of stack trace from previous location where exception was thrown ---
     at System.Threading.ThreadPoolWorkQueue.Dispatch()```
@Suchiman
Copy link
Contributor

Suchiman commented Jun 9, 2020

Are you using function pointers? ( https://github.com/dotnet/csharplang/blob/master/proposals/function-pointers.md )

case TypeFlags.FunctionPointer:
throw new NotImplementedException();

@john-h-k
Copy link
Contributor Author

john-h-k commented Jun 9, 2020

..yeah that will be it. I was told they were supported by someone else, apologies

cc @reflectronic 😒

@tannergooding
Copy link
Member

@MichalStrehovsky, is there an existing issue tracking function pointer support? Seems like it might be worth it given the language support being added and the runtime support being extended (UnmanagedCallableOnly, etc)

@john-h-k john-h-k changed the title NotImplementedException thrown when trying to compile NotImplementedException thrown when trying to compile with function pointers Jun 9, 2020
@Suchiman
Copy link
Contributor

Suchiman commented Jun 9, 2020

That shouldn't be too hard to fix or workaround, this code is responsible for detecting if it's permitted to reflect upon that. CoreRT supports UnmanagedCallersOnly and uses Calli intrinsics in a lot of places. I'll have a stab at fixing this.

@Suchiman
Copy link
Contributor

Suchiman commented Jun 9, 2020

@john-h-k do you have sample code that triggers this? And how did you compile it 😅 ? I'm using latest VS2019 preview and .NET 5.0 Preview 4 but this isn't recognized but sharplab on roslyn master branch compiles it.

@john-h-k
Copy link
Contributor Author

john-h-k commented Jun 9, 2020

The sample code is just a method that takes a funcptr. I used the preview tooling on roslyn's MyGet feed

Specifically

<PackageReference Include="Microsoft.Net.Compilers.Toolset" Version="3.7.0-3.20302.9">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
</PackageReference>

@tannergooding
Copy link
Member

It's basically as simple as:

  <PropertyGroup>
    <RestoreSources>
      https://api.nuget.org/v3/index.json;
      https://dotnet.myget.org/F/roslyn/api/v3/index.json;
    </RestoreSources>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Net.Compilers.Toolset" Version="3.7.0-3.20302.9" />
  </ItemGroup>

Noting that 3.7.0-3.20302.9 was the first nightly to include function pointers and is a week old now.
Also noting that Microsoft.Net.Compilers.Toolset isn't recommended for long term use and that VS IntelliSense (and potentially other bits) won't work for the new language features.

@Suchiman
Copy link
Contributor

Suchiman commented Jun 9, 2020

I'm using

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <LangVersion>preview</LangVersion>
    <RestoreSources>
      https://api.nuget.org/v3/index.json;
      https://dotnet.myget.org/F/roslyn/api/v3/index.json;
      https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json;
    </RestoreSources>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.DotNet.ILCompiler" Version="1.0.0-alpha-*" />
    <PackageReference Include="Microsoft.Net.Compilers.Toolset" Version="3.7.0-3.20302.9">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>

</Project>

and

using System;

namespace ConsoleApp92
{
    unsafe class Program
    {
        public static void Log() 
        {
            Console.WriteLine("Works!");
        }

        public static void Test(delegate*<void> del)
        {
            del();
        }

        static void Main(string[] args)
        {
            delegate*<void> a1 = &Log; // Log()

            Test(a1);
        }
    }
}

which compiles fine with dotnet publish -c Release -r win-x64 and prints

> .\bin\Release\net5.0\win-x64\native\ConsoleApp92.exe
Works!

@Suchiman
Copy link
Contributor

Suchiman commented Jun 9, 2020

Ah, i've got it, Test has to be generic.

@MichalStrehovsky
Copy link
Member

The project doesn't use reflection anywhere, unless 'REFLECTION' is defined which it isn't here

This code is responsible for figuring out whether the type is potentially visible from reflection. Types that are not visible from reflection can have more optimizations applied to them.

is there an existing issue tracking function pointer support?

Nope, it will probably just come down to a bug or two. Most of the system is aware of them (the place that is throwing is aware too, I was just lazy to implement the ~10 lines to handle it.

@Suchiman The method needs to be non-virtual generic to trigger the bug.

@john-h-k
Copy link
Contributor Author

john-h-k commented Jun 9, 2020

Is it basically just IsReflectionBlocked for each param and then the return?

@MichalStrehovsky
Copy link
Member

The fix will be to cast to a FunctionPointerType, go over the signature and check IsBlocked on each of the types in the signature. I'll mark this up for grabs, but if nobody volunteers, I can fix this later.

@Suchiman
Copy link
Contributor

Suchiman commented Jun 9, 2020

@MichalStrehovsky oh here's another one

// TODO Internal.TypeSystem.TypeFlags.FunctionPointer (Runtime parsing also not yet implemented)
case Internal.TypeSystem.TypeFlags.FunctionPointer:
throw new NotImplementedException("FunctionPointer signature");

@MichalStrehovsky
Copy link
Member

@MichalStrehovsky oh here's another one

That one you can probably hit with:

class P
{
    static Type Gimme<T>() => typeof(delegate*<T>);
    static void Main()
    {
        typeof(P).GetMethod("Gimme").MakeGenericMethod(typeof(object)).Invoke(null, Array.Empty<Type>();
    }
}

The fix for that right now would be just to pretend it's an IntPtr, but that might change depending on how dotnet/runtime#11354 turns out.

@Suchiman
Copy link
Contributor

Suchiman commented Jun 9, 2020

I actually did hit it with this code, i still didn't manage to hit the original issue in of this case 😆

using System;

unsafe class Program
{
    static void Log()
    {
        Console.WriteLine("Works!");
    }

    static void Test<T>(delegate*<void> del)
    {
        del();
    }

    static void Main(string[] args)
    {
        delegate*<void> a1 = &Log; // Log()

        Test<string>(a1);
    }
}

Suchiman added a commit to Suchiman/corert that referenced this issue Jun 9, 2020
Suchiman added a commit to Suchiman/corert that referenced this issue Jun 9, 2020
Suchiman added a commit to Suchiman/corert that referenced this issue Jun 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants