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

Parse CallConvSwift in CoreCLR/NativeAOT #96707

Merged
merged 16 commits into from
Jan 30, 2024
Merged
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
1 change: 1 addition & 0 deletions src/coreclr/inc/corhdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1715,6 +1715,7 @@ typedef enum LoadHintEnum
#define CMOD_CALLCONV_NAME_STDCALL "CallConvStdcall"
#define CMOD_CALLCONV_NAME_THISCALL "CallConvThiscall"
#define CMOD_CALLCONV_NAME_FASTCALL "CallConvFastcall"
#define CMOD_CALLCONV_NAME_SWIFT "CallConvSwift"
#define CMOD_CALLCONV_NAME_SUPPRESSGCTRANSITION "CallConvSuppressGCTransition"
#define CMOD_CALLCONV_NAME_MEMBERFUNCTION "CallConvMemberFunction"

Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,8 @@ enum class CorInfoCallConvExtension
// New calling conventions supported with the extensible calling convention encoding go here.
CMemberFunction,
StdcallMemberFunction,
FastcallMemberFunction
FastcallMemberFunction,
Swift
};

#ifdef TARGET_X86
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5592,7 +5592,8 @@ void Compiler::impCheckForPInvokeCall(
// return here without inlining the native call.
if (unmanagedCallConv == CorInfoCallConvExtension::Managed ||
unmanagedCallConv == CorInfoCallConvExtension::Fastcall ||
unmanagedCallConv == CorInfoCallConvExtension::FastcallMemberFunction)
unmanagedCallConv == CorInfoCallConvExtension::FastcallMemberFunction ||
unmanagedCallConv == CorInfoCallConvExtension::Swift)
{
return;
}
Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1590,6 +1590,9 @@ private static CorInfoCallConvExtension ToCorInfoCallConvExtension(UnmanagedCall
case UnmanagedCallingConventions.Fastcall:
result = CorInfoCallConvExtension.Fastcall;
break;
case UnmanagedCallingConventions.Swift:
result = CorInfoCallConvExtension.Swift;
break;
default:
ThrowHelper.ThrowInvalidProgramException();
result = CorInfoCallConvExtension.Managed; // unreachable
Expand Down Expand Up @@ -4099,7 +4102,7 @@ private uint getJitFlags(ref CORJIT_FLAGS flags, uint sizeInBytes)

#if READYTORUN
// TODO: enable this check in full AOT
if (Marshaller.IsMarshallingRequired(this.MethodBeingCompiled.Signature, Array.Empty<ParameterMetadata>(), ((MetadataType)this.MethodBeingCompiled.OwningType).Module)) // Only blittable arguments
if (Marshaller.IsMarshallingRequired(this.MethodBeingCompiled.Signature, ((MetadataType)this.MethodBeingCompiled.OwningType).Module, this.MethodBeingCompiled.GetUnmanagedCallersOnlyMethodCallingConventions())) // Only blittable arguments
{
ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramNonBlittableTypes, this.MethodBeingCompiled);
}
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,8 @@ public enum CorInfoCallConvExtension
// New calling conventions supported with the extensible calling convention encoding go here.
CMemberFunction,
StdcallMemberFunction,
FastcallMemberFunction
FastcallMemberFunction,
Swift
}

public enum CORINFO_CALLINFO_FLAGS
Expand Down
jkoritzinsky marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public enum UnmanagedCallingConventions
// Unmanaged = 0x00000009, - this one is always translated to cdecl/stdcall

// The ones higher than 0xF are defined by the type system
// There are no such calling conventions yet.
Swift = 0x00000010
}

public static class CallingConventionExtensions
Expand Down Expand Up @@ -135,6 +135,25 @@ public static UnmanagedCallingConventions GetPInvokeMethodCallingConventions(thi
return result;
}

public static UnmanagedCallingConventions GetDelegateCallingConventions(this TypeDesc delegateType)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method doesn't appear used. Is that intentional?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the usage of it during a refactor. I think it's still useful to have, but we can remove it and re-add later when we have a use case.

{
Debug.Assert(delegateType.IsDelegate);

if (delegateType is EcmaType ecmaDelegate)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Might want to either do delegateType.GetTypeDefinition() is EcmaType ecmaDelegate or assert the type is not generic so that we just don't do bad codegen if we ever allow interop with generic delegates.

{
MethodSignatureFlags unmanagedCallConv = ecmaDelegate.GetDelegatePInvokeFlags().UnmanagedCallingConvention;
if (unmanagedCallConv != MethodSignatureFlags.None)
{
Debug.Assert((int)MethodSignatureFlags.UnmanagedCallingConventionCdecl == (int)UnmanagedCallingConventions.Cdecl
&& (int)MethodSignatureFlags.UnmanagedCallingConventionStdCall == (int)UnmanagedCallingConventions.Stdcall
&& (int)MethodSignatureFlags.UnmanagedCallingConventionThisCall == (int)UnmanagedCallingConventions.Thiscall);
return (UnmanagedCallingConventions)unmanagedCallConv;
}
}

return GetPlatformDefaultUnmanagedCallingConvention(delegateType.Context);
}

private static UnmanagedCallingConventions GetUnmanagedCallingConventionFromAttribute(CustomAttributeValue<TypeDesc> attributeWithCallConvsArray, TypeSystemContext context)
{
ImmutableArray<CustomAttributeTypedArgument<TypeDesc>> callConvArray = default;
Expand Down Expand Up @@ -181,6 +200,7 @@ private static UnmanagedCallingConventions AccumulateCallingConventions(Unmanage
"CallConvThiscall" => UnmanagedCallingConventions.Thiscall,
"CallConvSuppressGCTransition" => UnmanagedCallingConventions.IsSuppressGcTransition,
"CallConvMemberFunction" => UnmanagedCallingConventions.IsMemberFunction,
"CallConvSwift" => UnmanagedCallingConventions.Swift,
_ => null
};

Expand Down Expand Up @@ -218,6 +238,7 @@ public static EmbeddedSignatureData[] EncodeAsEmbeddedSignatureData(this Unmanag
UnmanagedCallingConventions.Stdcall => "CallConvStdcall",
UnmanagedCallingConventions.Fastcall => "CallConvFastcall",
UnmanagedCallingConventions.Thiscall => "CallConvThiscall",
UnmanagedCallingConventions.Swift => "CallConvSwift",
_ => throw new InvalidProgramException()
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,18 @@ public static bool IsMarshallingRequired(MethodDesc targetMethod)
return false;
}

public static bool IsMarshallingRequired(MethodSignature methodSig, ModuleDesc moduleContext, UnmanagedCallingConventions callingConvention)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callingConvention parameter is not used, is it intentional?

Why do we need a new overload though? I would expect the existing IsMarshallingRequired to get an extra callingConvention argument if answer to this now depends on the calling convention as well (or why can we still decide it without the calling convention in the other overload?).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the other overload, we can extract the calling convention from the MethodSignature. This overload is for UnmanagedCallersOnly methods where the callconv is in the attribute, not the managed signature.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter is still unused, is that intentional?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's intentional that it's unused.

{
Marshaller[] marshallers = GetMarshallersForSignature(methodSig, System.Array.Empty<ParameterMetadata>(), moduleContext);
for (int i = 0; i < marshallers.Length; i++)
{
if (marshallers[i].IsMarshallingRequired())
return true;
}

return false;
}

public static bool IsMarshallingRequired(MethodSignature methodSig, ParameterMetadata[] paramMetadata, ModuleDesc moduleContext)
{
Marshaller[] marshallers = GetMarshallersForSignature(methodSig, paramMetadata, moduleContext);
Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/vm/callconvbuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ namespace
BASE_CALL_CONV(CMOD_CALLCONV_NAME_CDECL, C) \
BASE_CALL_CONV(CMOD_CALLCONV_NAME_STDCALL, Stdcall) \
BASE_CALL_CONV(CMOD_CALLCONV_NAME_THISCALL, Thiscall) \
BASE_CALL_CONV(CMOD_CALLCONV_NAME_FASTCALL, Fastcall)
BASE_CALL_CONV(CMOD_CALLCONV_NAME_FASTCALL, Fastcall) \
BASE_CALL_CONV(CMOD_CALLCONV_NAME_SWIFT, Swift)

#define DECLARE_MOD_CALL_CONVS \
CALL_CONV_MODIFIER(CMOD_CALLCONV_NAME_SUPPRESSGCTRANSITION, CALL_CONV_MOD_SUPPRESSGCTRANSITION) \
Expand Down Expand Up @@ -176,6 +177,8 @@ namespace
return CorInfoCallConvExtension::FastcallMemberFunction;
case CorInfoCallConvExtension::Thiscall:
return CorInfoCallConvExtension::Thiscall;
case CorInfoCallConvExtension::Swift:
return CorInfoCallConvExtension::Swift;
jkoritzinsky marked this conversation as resolved.
Show resolved Hide resolved
default:
_ASSERTE("Calling convention is not an unmanaged base calling convention.");
return baseCallConv;
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/corelib.h
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,7 @@ DEFINE_CLASS(CALLCONV_THISCALL, CompilerServices, CallConvThi
DEFINE_CLASS(CALLCONV_FASTCALL, CompilerServices, CallConvFastcall)
DEFINE_CLASS(CALLCONV_SUPPRESSGCTRANSITION, CompilerServices, CallConvSuppressGCTransition)
DEFINE_CLASS(CALLCONV_MEMBERFUNCTION, CompilerServices, CallConvMemberFunction)
DEFINE_CLASS(CALLCONV_SWIFT, CompilerServices, CallConvSwift)

DEFINE_CLASS_U(Interop, SafeHandle, SafeHandle)
DEFINE_FIELD_U(_ctorStackTrace, SafeHandle, m_ctorStackTrace)
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/dllimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3167,7 +3167,6 @@ HRESULT NDirect::HasNAT_LAttribute(IMDInternalImport *pInternalImport, mdToken t
return S_FALSE;
}


// Either MD or signature & module must be given.
/*static*/
BOOL NDirect::MarshalingRequired(
Expand Down Expand Up @@ -4257,7 +4256,8 @@ static void CreateNDirectStubAccessMetadata(
{
if (unmgdCallConv == CorInfoCallConvExtension::Managed ||
unmgdCallConv == CorInfoCallConvExtension::Fastcall ||
unmgdCallConv == CorInfoCallConvExtension::FastcallMemberFunction)
unmgdCallConv == CorInfoCallConvExtension::FastcallMemberFunction ||
unmgdCallConv == CorInfoCallConvExtension::Swift)
{
COMPlusThrow(kTypeLoadException, IDS_INVALID_PINVOKE_CALLCONV);
}
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/vm/stubgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2819,6 +2819,9 @@ void ILStubLinker::SetStubTargetCallingConv(CorInfoCallConvExtension callConv)
m_nativeFnSigBuilder.AddCallConvModOpt(GetToken(CoreLibBinder::GetClass(CLASS__CALLCONV_FASTCALL)));
m_nativeFnSigBuilder.AddCallConvModOpt(GetToken(CoreLibBinder::GetClass(CLASS__CALLCONV_MEMBERFUNCTION)));
break;
case CorInfoCallConvExtension::Swift:
m_nativeFnSigBuilder.AddCallConvModOpt(GetToken(CoreLibBinder::GetClass(CLASS__CALLCONV_SWIFT)));
break;
default:
_ASSERTE("Unknown calling convention. Unable to encode it in the native function pointer signature.");
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Runtime.CompilerServices;

namespace System.Runtime.InteropServices.Swift
{
Expand All @@ -19,7 +20,8 @@ namespace System.Runtime.InteropServices.Swift
/// </code>
/// </para>
/// </remarks>
[CLSCompliantAttribute(false)]
[CLSCompliant(false)]
[Intrinsic]
jkoritzinsky marked this conversation as resolved.
Show resolved Hide resolved
public readonly unsafe struct SwiftSelf
{
/// <summary>
Expand Down Expand Up @@ -52,7 +54,8 @@ public SwiftSelf(void* value)
/// </code>
/// </para>
/// </remarks>
[CLSCompliantAttribute(false)]
[CLSCompliant(false)]
[Intrinsic]
public readonly unsafe struct SwiftError
{
/// <summary>
Expand Down
Loading