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

Representation of function pointer types in the reflection stack #11354

Closed
2 of 3 tasks
Tracked by #44327
MichalStrehovsky opened this issue Oct 29, 2018 · 25 comments
Closed
2 of 3 tasks
Tracked by #44327
Assignees
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Reflection Cost:M Work that requires one engineer up to 2 weeks enhancement Product code improvement that does NOT require public API changes/additions
Milestone

Comments

@MichalStrehovsky
Copy link
Member

MichalStrehovsky commented Oct 29, 2018

dotnet/csharplang#1951 discusses adding function pointer types to the C# language. The CLR has supported these for a while, but there are areas (such as the reflection stack), where function pointer types are weird/unhandled.

While this will just be a corner area of the C# language, we should probably at least track this:

  • Can we fix ldtoken method explicit instance int32 *(int32) not to return the token of System.IntPtr?
  • Can we use System.Reflection.Pointer to reflection invoke methods that take/return function pointers?
  • Do we need new APIs to inspect/reflection emit function pointer types?
@danmoseley
Copy link
Member

@MichalStrehovsky marked future.

@mjsabby
Copy link
Contributor

mjsabby commented Jul 16, 2019

Do you know off the top of your head how complicated it is to do the first one?

@MichalStrehovsky
Copy link
Member Author

Do you know off the top of your head how complicated it is to do the first one?

No, I didn't look into it beyond trying that single line and being happy that I didn't have to add any extra work to .NET Native/CoreRT backlog at that time.

@msftgits msftgits transferred this issue from dotnet/coreclr Jan 31, 2020
@msftgits msftgits added this to the Future milestone Jan 31, 2020
@maryamariyan maryamariyan added the untriaged New issue has not been triaged by the area owner label Feb 26, 2020
@steveharter steveharter added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Mar 19, 2020
@GrabYourPitchforks
Copy link
Member

Sample syntax below - here's a method that takes a function pointer of type int -> void as an argument.

public unsafe static void M(delegate*<int, void> ptr) {
}

@GrabYourPitchforks GrabYourPitchforks added enhancement Product code improvement that does NOT require public API changes/additions and removed untriaged New issue has not been triaged by the area owner labels Mar 19, 2020
@GrabYourPitchforks GrabYourPitchforks modified the milestones: Future, 5.0 Mar 19, 2020
@GrabYourPitchforks
Copy link
Member

We should do this for 5.0 since function pointers support is being added imminently.

@mjsabby
Copy link
Contributor

mjsabby commented Jun 17, 2020

I hope the "we should do this for 5.0" still applies and we're tracking this as part of the overall function pointers work.

@GrabYourPitchforks
Copy link
Member

At the moment it's not currently funded for 5.0 - it's more of a stretch goal. If it's blocking you let us know and we can mark it as such. Then we can pull resources from other things to address it.

@mjsabby
Copy link
Contributor

mjsabby commented Jun 19, 2020

Yeah this is pretty impactful since I'm wanting to freeze these objects and it is not possible to find which are fnptrs arrays. I'm ok if I can work around it somehow but I don't think I'm able to.

@GrabYourPitchforks GrabYourPitchforks self-assigned this Jul 7, 2020
@mjsabby
Copy link
Contributor

mjsabby commented Jul 12, 2020

@GrabYourPitchforks I see you self-assigned this, does this mean it'll happen in 5.0?!

@GrabYourPitchforks
Copy link
Member

Still not funded, but I'm growing increasingly worried that if we don't address it in 5.0 it'll be too difficult to address in 6.0 due to compat. So going to see if we can slam this in at the last minute. It'll definitely be a roller coaster. :)

@ThadHouse
Copy link
Contributor

Now that 5.0 has released, and I'm switching my functions that used to take IntPtr to function pointers, I'm running into this issue.

I have the following interface (simplified of course)

public interface IThing {
    void Function(delegate* unmanaged[Cdecl]<int, void> cb); // This used to be an IntPtr cb
}

I'm generating at runtime using Reflection.Emit an implementation of this interface. However, with function pointers, this does not seem possible. When I iterate the parameters of that function, the parameter just shows up as an IntPtr, with now way to detect its a function pointer. If I generate the function using IntPtr, the signature doesn't match, and the importer fails with a TypeLoadException basically that the interface is not implemented.

@ghost ghost added the needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration label Aug 17, 2021
@MSDN-WhiteKnight
Copy link
Contributor

How the reflection API to represent function pointers information should look like? I think there are two options:

  1. Create new Signature type, that would contain information about calling convention, return type and parameter types
  2. Use the existing MethodInfo type, and return the special dummy instances that would support CallingConvention, GetParameters and ReturnType, but have any other members no-op or throwing NotSupportedException.

The first looks more pleasant, but with second more existing code operating on MethodInfo could be reused.

@MichalStrehovsky
Copy link
Member Author

One immediate problem with calling conventions is that we decided to encode them as modifiers going forward, but modifiers tend to disappear as reflection stack handles them.

In particular:

ldtoken string[]
stloc.0
ldloca 0
ldtoken string modopt (MyModifier)[]
call instance bool valuetype [System.Runtime]System.RuntimeTypeHandle::Equals(valuetype [System.Runtime]System.RuntimeTypeHandle)
brtrue StringArrayModifiedStringArrayOK
ldc.i4.1
ret

They disappear when we do LDTOKEN.

We'll need some special rules if we want to preserve that in typeof for function pointers. We are going to break compat in that direction anyway (since they're all loaded as IntPtr right now), but there might be other places that rely on modopts disappearing.

@joperezr joperezr removed the needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration label Aug 17, 2021
@joperezr joperezr moved this from Needs triage to Future in Triage POD for Meta, Reflection, etc Aug 17, 2021
@jkotas
Copy link
Member

jkotas commented Feb 21, 2022

CoreCLR and Mono reflection stacks represent function pointers differently today. For examle, Console.WriteLine(typeof(delegate*<int>).FullName) prints System.IntPtr on CoreCLR vs. System.MonoFNPtrFakeClass on Mono. That's also something that has to be unified to fix this issue.

@ghost ghost moved this from Future to Needs triage in Triage POD for Meta, Reflection, etc Feb 21, 2022
@ghost ghost added the needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration label Feb 21, 2022
@steveharter
Copy link
Member

Moving to 8.0; we need to update the API and design based on feedback from #71516.

@AndyAyersMS
Copy link
Member

FWIW the jit currently mis-optimizes some cases involving function type comparison.

The fix is in #72136 where the jit will defer to the runtime to decide what sort of optimizations can apply. If/when the runtime type for function pointers changes those new bits of jit interface can potentially be revised to enable a little more optimization.

@jkotas

This comment was marked as off-topic.

@AndyAyersMS

This comment was marked as off-topic.

@IS4Code
Copy link

IS4Code commented Dec 1, 2022

What's the status of this? I hope Type.GetFunctionPointerReturnType, Type.GetFunctionPointerParameterTypes and Type.MakeFunctionPointerType will finally be possible, so that the full CLI type system can finally be expressible using reflection and emit (well, except for modopts and modreqs I guess). I hope Pointer.Box will work too!

@steveharter
Copy link
Member

What's the status of this?

Currently a design is being created. The reflection features for 8.0 are tracked here.

I hope Pointer.Box will work too!

This will be covered in the design. Here's the current section:

System.Pointer

The System.Reflection.Pointer class is useful to pass a pointer address and type together and was introduced to pass a pointer using reflection APIs which are based on passing arrays of System.Object. Essentially it is a Tuple<Type, IntPtr> although currently Pointer does not expose a property to obtain the Type.

There is no proposal here to either extend Pointer or add a new FunctionPointer. If code wants to pass a function pointer with reflection, it will have to pass both the Type and IntPtr separately. If the need to do so becomes more obvious, a new FunctionPointer type should be a value type, not a reference type like Pointer, since newer reflection APIs will not force boxing to occur.

@steveharter steveharter removed the needs-further-triage Issue has been initially triaged, but needs deeper consideration or reconsideration label Dec 5, 2022
@steveharter
Copy link
Member

The design is ready for review at dotnet/designs#282

@steveharter
Copy link
Member

Closing; implemented in #81006

@dotnet dotnet locked as resolved and limited conversation to collaborators Mar 26, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Reflection Cost:M Work that requires one engineer up to 2 weeks enhancement Product code improvement that does NOT require public API changes/additions
Projects
No open projects
Development

No branches or pull requests