-
Notifications
You must be signed in to change notification settings - Fork 5.3k
New function pointer APIs #123819
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
base: main
Are you sure you want to change the base?
New function pointer APIs #123819
Changes from all commits
12c00b0
d100b0f
2fb7104
370bba8
6334ac3
db884d6
646c698
34a4aa8
911ab4c
6a79794
10480d6
36efdd7
235a1eb
3e69ba5
992f8ef
5208c79
3cda7fb
ad985be
03a405f
f559fc9
541b4e1
e1de07c
58e0b44
9f1e007
ff157db
ffbc5af
9a86dc8
af07d0c
3ebe1d3
a41d0f0
5bfe315
d57d7c3
d325940
4afdc6c
7f28b72
5f1bbf0
03501f2
d1afecf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -105,6 +105,51 @@ internal static SignatureHelper GetMethodSigHelper(Module? mod, CallingConventio | |
| return new SignatureHelper(mod, intCall, returnType, null, null); | ||
| } | ||
|
|
||
| internal static SignatureHelper GetMethodSigHelper(DynamicScope scope, Type functionPointerType) | ||
| { | ||
| Debug.Assert(functionPointerType.IsFunctionPointer); | ||
|
|
||
| Type retType = functionPointerType.GetFunctionPointerReturnType(); | ||
| Type[] retTypeModReqs = retType.GetRequiredCustomModifiers(); | ||
| Type[] retTypeModOpts = retType.GetOptionalCustomModifiers(); | ||
| Type[] paramTypes = functionPointerType.GetFunctionPointerParameterTypes(); | ||
| Type[][] paramModReqs = new Type[paramTypes.Length][]; | ||
| Type[][] paramModOpts = new Type[paramTypes.Length][]; | ||
|
|
||
| retType = retType.UnderlyingSystemType; | ||
|
|
||
| for (int i = 0; i < paramTypes.Length; i++) | ||
| { | ||
| paramModReqs[i] = paramTypes[i].GetRequiredCustomModifiers(); | ||
| paramModOpts[i] = paramTypes[i].GetOptionalCustomModifiers(); | ||
| paramTypes[i] = paramTypes[i].UnderlyingSystemType; | ||
| } | ||
|
|
||
| MdSigCallingConvention callConv = MdSigCallingConvention.Default; | ||
|
|
||
| if (functionPointerType.IsUnmanagedFunctionPointer) | ||
| { | ||
| callConv = MdSigCallingConvention.Unmanaged; | ||
|
|
||
| if (functionPointerType.GetFunctionPointerCallingConventions() is { Length: 1 } conventions) | ||
| { | ||
| callConv = conventions[0].FullName switch | ||
| { | ||
| "System.Runtime.CompilerServices.CallConvCdecl" => MdSigCallingConvention.C, | ||
| "System.Runtime.CompilerServices.CallConvStdcall" => MdSigCallingConvention.StdCall, | ||
| "System.Runtime.CompilerServices.CallConvThiscall" => MdSigCallingConvention.ThisCall, | ||
| "System.Runtime.CompilerServices.CallConvFastcall" => MdSigCallingConvention.FastCall, | ||
| _ => MdSigCallingConvention.Unmanaged | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| SignatureHelper sig = new(null, callConv); | ||
| sig.AddDynamicArgument(scope, retType, retTypeModReqs, retTypeModOpts, false); | ||
| sig.AddArguments(scope, paramTypes, paramModReqs, paramModOpts); | ||
| return sig; | ||
| } | ||
|
|
||
| public static SignatureHelper GetLocalVarSigHelper() | ||
| { | ||
| return GetLocalVarSigHelper(null); | ||
|
|
@@ -320,8 +365,8 @@ private void AddOneArgTypeHelper(Type clsArgument, Type[]? requiredCustomModifie | |
| AddOneArgTypeHelper(clsArgument); | ||
| } | ||
|
|
||
| private void AddOneArgTypeHelper(Type clsArgument) { AddOneArgTypeHelperWorker(clsArgument, false); } | ||
| private void AddOneArgTypeHelperWorker(Type clsArgument, bool lastWasGenericInst) | ||
| private void AddOneArgTypeHelper(Type clsArgument, DynamicScope? scope = null) { AddOneArgTypeHelperWorker(clsArgument, false, scope); } | ||
| private void AddOneArgTypeHelperWorker(Type clsArgument, bool lastWasGenericInst, DynamicScope? scope) | ||
| { | ||
| if (clsArgument.IsGenericParameter) | ||
| { | ||
|
|
@@ -336,7 +381,7 @@ private void AddOneArgTypeHelperWorker(Type clsArgument, bool lastWasGenericInst | |
| { | ||
| AddElementType(CorElementType.ELEMENT_TYPE_GENERICINST); | ||
|
|
||
| AddOneArgTypeHelperWorker(clsArgument.GetGenericTypeDefinition(), true); | ||
| AddOneArgTypeHelperWorker(clsArgument.GetGenericTypeDefinition(), true, scope); | ||
|
|
||
| Type[] args = clsArgument.GetGenericArguments(); | ||
|
|
||
|
|
@@ -424,6 +469,25 @@ private void AddOneArgTypeHelperWorker(Type clsArgument, bool lastWasGenericInst | |
| AddData(0); | ||
| } | ||
| } | ||
| else if (clsArgument.IsFunctionPointer) | ||
| { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we throw NotSupportedException for I assume that it can be hit with (non-persistent) Reflection.Emit. Is that right? We may want to add a test that validates it is throwing (and not crashing or producing bad output).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, or by just invoking |
||
| if (scope == null) | ||
| throw new NotSupportedException(SR.NotSupported_FunctionPointerSignature); | ||
|
|
||
| AddData((int)CorElementType.ELEMENT_TYPE_FNPTR); | ||
| SignatureHelper sig = GetMethodSigHelper(scope, clsArgument); | ||
| byte[] bytes = sig.GetSignature(); | ||
|
|
||
| if (m_currSig + bytes.Length > m_signature.Length) | ||
| { | ||
| m_signature = ExpandArray(m_signature, m_signature.Length + bytes.Length); | ||
| } | ||
|
|
||
| for (int i = 0; i < bytes.Length; i++) | ||
| { | ||
| m_signature[m_currSig++] = bytes[i]; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| CorElementType type = CorElementType.ELEMENT_TYPE_MAX; | ||
|
|
@@ -729,9 +793,10 @@ internal byte[] InternalGetSignatureArray() | |
| return temp; | ||
| } | ||
|
|
||
| internal void AddDynamicArgument(DynamicScope dynamicScope, Type clsArgument, Type[]? requiredCustomModifiers, Type[]? optionalCustomModifiers) | ||
| internal void AddDynamicArgument(DynamicScope dynamicScope, Type clsArgument, Type[]? requiredCustomModifiers, Type[]? optionalCustomModifiers, bool incrementArgCount = true) | ||
| { | ||
| IncrementArgCounts(); | ||
| if (incrementArgCount) | ||
| IncrementArgCounts(); | ||
|
|
||
| Debug.Assert(clsArgument != null); | ||
|
|
||
|
|
@@ -744,12 +809,6 @@ internal void AddDynamicArgument(DynamicScope dynamicScope, Type clsArgument, Ty | |
| if (t is not RuntimeType rtType) | ||
| throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(optionalCustomModifiers)); | ||
|
|
||
| if (t.HasElementType) | ||
| throw new ArgumentException(SR.Argument_ArraysInvalid, nameof(optionalCustomModifiers)); | ||
|
|
||
| if (t.ContainsGenericParameters) | ||
| throw new ArgumentException(SR.Argument_GenericsInvalid, nameof(optionalCustomModifiers)); | ||
|
|
||
| AddElementType(CorElementType.ELEMENT_TYPE_CMOD_OPT); | ||
|
|
||
| int token = dynamicScope.GetTokenFor(rtType.TypeHandle); | ||
|
|
@@ -767,12 +826,6 @@ internal void AddDynamicArgument(DynamicScope dynamicScope, Type clsArgument, Ty | |
| if (t is not RuntimeType rtType) | ||
| throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(requiredCustomModifiers)); | ||
|
|
||
| if (t.HasElementType) | ||
| throw new ArgumentException(SR.Argument_ArraysInvalid, nameof(requiredCustomModifiers)); | ||
|
|
||
| if (t.ContainsGenericParameters) | ||
| throw new ArgumentException(SR.Argument_GenericsInvalid, nameof(requiredCustomModifiers)); | ||
|
|
||
| AddElementType(CorElementType.ELEMENT_TYPE_CMOD_REQD); | ||
|
|
||
| int token = dynamicScope.GetTokenFor(rtType.TypeHandle); | ||
|
|
@@ -781,7 +834,18 @@ internal void AddDynamicArgument(DynamicScope dynamicScope, Type clsArgument, Ty | |
| } | ||
| } | ||
|
|
||
| AddOneArgTypeHelper(clsArgument); | ||
| AddOneArgTypeHelper(clsArgument, dynamicScope); | ||
jgh07 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| internal void AddArguments(DynamicScope dynamicScope, Type[]? arguments, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers) | ||
| { | ||
| if (arguments is null) | ||
| return; | ||
|
|
||
| for (int i = 0; i < arguments.Length; i++) | ||
| { | ||
| AddDynamicArgument(dynamicScope, arguments[i], requiredCustomModifiers?[i], optionalCustomModifiers?[i]); | ||
| } | ||
| } | ||
|
|
||
| #endregion | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,16 @@ public abstract void EmitCalli(OpCode opcode, CallingConventions callingConventi | |
|
|
||
| public abstract void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type? returnType, Type[]? parameterTypes); | ||
|
|
||
| /// <summary> | ||
| /// Puts a <see cref="OpCodes.Calli"/> instruction onto the Microsoft intermediate language (MSIL) stream, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kept this description largely the same as the existing overloads. I think it might make more sense to update it though, since as far as I'm concerned the term MSIL was dropped in favor of CIL. |
||
| /// specifying the type of the function pointer to indirectly call. | ||
| /// </summary> | ||
| /// <param name="functionPointerType"> | ||
| /// The type of the function pointer to indirectly call. | ||
| /// The specified type must represent a function pointer type. | ||
| /// </param> | ||
| public virtual void EmitCalli(Type functionPointerType) => throw new NotSupportedException(SR.NotSupported_SubclassOverride); | ||
|
|
||
| public abstract void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[]? optionalParameterTypes); | ||
|
|
||
| public abstract void Emit(OpCode opcode, SignatureHelper signature); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.