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

[mono] Add runtime support for Swift calling convention on x64 and arm64 #94764

Merged
merged 156 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
156 commits
Select commit Hold shift + click to select a range
5136aaf
Add README.md
kotlarmilos Sep 13, 2023
674a156
Merge branch 'dotnet:main' into poc/swift-interop-direct-pinvoke
kotlarmilos Sep 13, 2023
9fc9402
Update build steps
kotlarmilos Sep 13, 2023
d279a03
Add experiment templates as unit tests
kotlarmilos Sep 13, 2023
de27030
Update README.md
kotlarmilos Sep 13, 2023
476a605
Update README.md
kotlarmilos Sep 13, 2023
b1b69d3
Update README.md
kotlarmilos Sep 14, 2023
a95aca8
Update README.md
kotlarmilos Sep 14, 2023
6c8e477
Update README.md
kotlarmilos Sep 14, 2023
b06c840
Merge branch 'dotnet:main' into poc/swift-interop-direct-pinvoke
kotlarmilos Sep 19, 2023
7810e56
Fix the MathLibrary.swift
kotlarmilos Sep 19, 2023
6d9d67f
Update README.md
kotlarmilos Sep 19, 2023
87adeed
Update README.md
kotlarmilos Sep 20, 2023
0716fda
Add Swift ABI details
kotlarmilos Sep 21, 2023
ab53067
Merge branch 'poc/swift-interop-direct-pinvoke' of https://github.com…
kotlarmilos Sep 21, 2023
675619f
Update README.md
kotlarmilos Sep 21, 2023
24a8a01
Add tasks to the README.md
kotlarmilos Sep 21, 2023
11d60cc
Script that exports and demangles Swift symbols
kotlarmilos Sep 21, 2023
e8169f0
Update README.md
kotlarmilos Sep 21, 2023
8584918
Merge branch 'dotnet:main' into poc/swift-interop-direct-pinvoke
kotlarmilos Oct 9, 2023
279a594
Add custom attributes for Swift calling convention
kotlarmilos Oct 12, 2023
acc15a0
Add runtime support for Swift error handling
kotlarmilos Oct 12, 2023
5ea8755
Add sample test
kotlarmilos Oct 12, 2023
7a69077
Add Swift error handling on minijit arm64
kotlarmilos Oct 15, 2023
ebe4116
Update README.md
kotlarmilos Oct 16, 2023
0c40694
Merge branch 'dotnet:main' into poc/swift-interop-direct-pinvoke
kotlarmilos Oct 26, 2023
71d33f4
Add mini arm64 support for Swift self context
kotlarmilos Oct 27, 2023
7bcf61f
Remove redundant movx instruction
kotlarmilos Oct 27, 2023
7d9f73d
Merge branch 'dotnet:main' into poc/swift-interop-direct-pinvoke
kotlarmilos Oct 30, 2023
5973ff5
Update Swift types according to the design document
kotlarmilos Oct 31, 2023
ffc173a
Add mini arm64 support for Swift self and error registers
kotlarmilos Oct 31, 2023
907c69a
[interp] Add interpreter support for Swift calling convention
kotlarmilos Nov 2, 2023
42680b1
[inter] Simplify Swift calling convention support
kotlarmilos Nov 2, 2023
2cce70f
[mono] Add mini and interpreter support for swift calling convention …
kotlarmilos Nov 2, 2023
a702f0d
[mono] Update Swift interop smoke test
kotlarmilos Nov 2, 2023
5bc2693
[mono] Update Swift interop smoke test
kotlarmilos Nov 2, 2023
78b974a
[mono] Add ArgSwiftError in emit_move_args
kotlarmilos Nov 3, 2023
a4ab558
Merge branch 'dotnet:main' into poc/swift-interop-direct-pinvoke
kotlarmilos Nov 3, 2023
ece53c2
Force ArgSwiftError to be allocated on stack
matouskozak Nov 6, 2023
a862485
Revert "[mono] Add ArgSwiftError in emit_move_args"
matouskozak Nov 6, 2023
6a5dda2
[mono] Add helper functions for checking for Swift context classes
kotlarmilos Nov 6, 2023
e2b6fe9
[mono] Fix ArgSwift registers index
kotlarmilos Nov 6, 2023
b3cb4cb
[mono] Avoid allocating context registers on arm64
kotlarmilos Nov 7, 2023
68ad76d
[mono] Add smoke tests for Swift calling convention
kotlarmilos Nov 7, 2023
1efac9d
[mono] Avoid allocating context registers on x64
kotlarmilos Nov 7, 2023
74dc8c9
[mono] Simplify interp support for amd64
kotlarmilos Nov 7, 2023
fd1b036
Exclude coreclr runtime flavor
kotlarmilos Nov 7, 2023
458c1e4
Update README.md
kotlarmilos Nov 7, 2023
2939996
Remove helper script
kotlarmilos Nov 7, 2023
8298058
[mono] Simplify arguments check with helper macros
kotlarmilos Nov 7, 2023
5447ccd
Add build script for native libs
kotlarmilos Nov 9, 2023
7e04140
Merge branch 'dotnet:main' into poc/swift-interop-direct-pinvoke
kotlarmilos Nov 9, 2023
64157c5
Build native Swift libraries after test build
matouskozak Nov 10, 2023
6b3a52f
Revert "Build native Swift libraries after test build"
matouskozak Nov 14, 2023
6077b22
[mono] Add params check for Swift calling convention in mini runtime
kotlarmilos Nov 14, 2023
af416eb
[mono] Add basic runtime tests for the Swift calling convention
kotlarmilos Nov 14, 2023
cc9c619
Update README.md
matouskozak Nov 15, 2023
89f46b8
Fix README.md formatting
kotlarmilos Nov 15, 2023
20eb7a6
Add comments for the Swift types
kotlarmilos Nov 15, 2023
ae08445
Fix lint; remove trailing spaces
kotlarmilos Nov 15, 2023
5a225b5
Resolve CI failures
kotlarmilos Nov 15, 2023
ac7f565
Remove static functions from mini.h file
kotlarmilos Nov 15, 2023
b945d4d
Fix CI failures
kotlarmilos Nov 15, 2023
18fcbae
Merge branch 'dotnet:main' into poc/swift-interop-direct-pinvoke
kotlarmilos Nov 15, 2023
4c6c0c1
Revert API changes
kotlarmilos Nov 15, 2023
0587a55
Update README.md
kotlarmilos Nov 15, 2023
56bcb1b
[interp] Simplify register allocation in CallContext
kotlarmilos Nov 16, 2023
a5afdbe
[mono] Remove mono_arch_get_swift_error from unsupported architectures
kotlarmilos Nov 17, 2023
2faea55
Update src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeM…
kotlarmilos Nov 17, 2023
05a8c1c
[mono] Add ext_callconv to the MonoMethodSignature
kotlarmilos Nov 17, 2023
b67c3c6
[mono] Throw NotImplementedException Swift calling convention on not …
kotlarmilos Nov 17, 2023
4dad320
[mono] Simplify runtime tests and add error logging
kotlarmilos Nov 17, 2023
c088a57
[mono] Add better error logging in test cases
kotlarmilos Nov 17, 2023
91e6955
Update src/native/public/mono/metadata/details/metadata-types.h
kotlarmilos Nov 21, 2023
9327d1e
Update src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs
kotlarmilos Nov 21, 2023
5df0523
[tests] Update Swift tests to utilize Assert.True with error message
kotlarmilos Nov 21, 2023
fc9178e
Remove README.md
kotlarmilos Nov 21, 2023
738d14d
[tests] Document Swift error offset constants in the tests
kotlarmilos Nov 21, 2023
dccf89e
Update MONO_ARCH_HAVE_SWIFTCALL condition
kotlarmilos Nov 21, 2023
9a8cc67
Update src/tests/Interop/Swift/SwiftInvalidCallConv/SwiftInvalidCallC…
kotlarmilos Nov 22, 2023
8c5cf81
disable swift interop tests on mono windows
Nov 22, 2023
6ee1c1e
[tests] Update conditions to match Assert.True
kotlarmilos Nov 22, 2023
5c5daad
[tests] Simplify error handling tests by taking Error instead of Unsa…
kotlarmilos Nov 23, 2023
f412721
add process isolation to runtime tests
Nov 27, 2023
8c53ad6
Merge branch 'poc/swift-interop-direct-pinvoke' of github.com:kotlarm…
Nov 27, 2023
9482a79
enable Swift tests on Apple OS
matouskozak Nov 27, 2023
883d645
Revert "enable Swift tests on Apple OS"
matouskozak Nov 27, 2023
4f788fc
enable Swift tests on OSX
matouskozak Nov 27, 2023
1e19be8
Merge branch 'dotnet:main' into poc/swift-interop-direct-pinvoke
kotlarmilos Dec 4, 2023
7b689a2
Add pointer deallocation in SwiftError test
kotlarmilos Dec 4, 2023
152fa6e
Use NativeLibrary.Free for Swift interop scenarios
kotlarmilos Dec 4, 2023
c732e25
Update src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs
kotlarmilos Dec 4, 2023
40f6e35
Use ReadOnlySpan in GetErrorMessageFromSwift
kotlarmilos Dec 4, 2023
ab3e840
Use ReadOnlySpan in GetErrorMessageFromSwift
kotlarmilos Dec 4, 2023
c29a35f
Use NativeMemory.Free in GetErrorMessageFromSwift
kotlarmilos Dec 4, 2023
8663c3c
Simplify GetErrorMessageFromSwift to copy zero-terminated C string
kotlarmilos Dec 5, 2023
3ed6733
remove OutputType Exe from tests
matouskozak Dec 5, 2023
cb20690
[mono][interp] Implement context register backup and restore mechanism
kotlarmilos Dec 6, 2023
da5279b
remove BuildAsStandalone
matouskozak Dec 7, 2023
a32421a
[mono][interp] Refactor context register backup and restore mechanism
kotlarmilos Dec 7, 2023
3b1b4dd
add expected error printout
matouskozak Dec 7, 2023
37230be
null-terminate error message string
matouskozak Dec 7, 2023
c25d435
Revert "null-terminate error message string"
matouskozak Dec 8, 2023
a57307f
refactor SwiftErrorHandling to use NSString
matouskozak Dec 8, 2023
1fe9611
Update src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs
matouskozak Dec 9, 2023
e256556
Update src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs
matouskozak Dec 9, 2023
e9ce7d9
Change PtrToStringUTF8 to PtrToStringUni
matouskozak Dec 9, 2023
91a3263
Change Swift to receive Int32 instead of Int
matouskozak Dec 11, 2023
5e9f6fc
Merge branch 'dotnet:main' into poc/swift-interop-direct-pinvoke
kotlarmilos Dec 11, 2023
97a74cc
null-terminate error message in swift
matouskozak Dec 12, 2023
5384dce
Revert "null-terminate error message in swift"
matouskozak Dec 12, 2023
7103cfc
Retrieve both content and length of error message
matouskozak Dec 12, 2023
ed2a7dc
Don't allocate amd64_rbx for Swift calling convention
kotlarmilos Dec 13, 2023
8e18dc3
Merge branch 'poc/swift-interop-direct-pinvoke' of https://github.com…
kotlarmilos Dec 13, 2023
7961e29
Update src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs
matouskozak Dec 13, 2023
5e1afb5
Add missing case for ArgSwiftSelf
kotlarmilos Dec 13, 2023
d9da03d
[mono] Fix invalid calling convention counter
kotlarmilos Dec 15, 2023
061934d
Merge branch 'dotnet:main' into poc/swift-interop-direct-pinvoke
kotlarmilos Jan 3, 2024
eb3103e
Merge branch 'main' of https://github.com/kotlarmilos/runtime into po…
kotlarmilos Jan 11, 2024
672ac92
[mono] Resolve conflicts in SwiftTypes.cs and CallConvSwift class
kotlarmilos Jan 11, 2024
dfc5de6
[mono] Copy ext_callconv property
kotlarmilos Jan 11, 2024
0984ffc
Refactor mono_marshal_get_native_wrapper to add non-primitive argumen…
kotlarmilos Jan 11, 2024
eaf9aa2
[mono] Implement sig->ext_callconv encoding and decoding
kotlarmilos Jan 15, 2024
fe19a09
[mini] Use MONO_ARCH_HAVE_SWIFTCALL to condition ctx regs on supporte…
kotlarmilos Jan 15, 2024
f93e231
[mono] Resolve tramp warnings
kotlarmilos Jan 15, 2024
2d5b9f5
[mini] Remove unused func
kotlarmilos Jan 15, 2024
60749f4
[mono] Add ext_callconv flag for encoding and decoding
kotlarmilos Jan 15, 2024
fa085d9
move swift defines and macros to mini.h
matouskozak Jan 16, 2024
bc19659
Merge branch 'main' into poc/swift-interop-direct-pinvoke
matouskozak Jan 16, 2024
5309a58
Revert "move swift defines and macros to mini.h"
matouskozak Jan 16, 2024
735b84e
initialize ext_callconv
matouskozak Jan 16, 2024
f444eae
ifdef mono_arch_get_swift_error
matouskozak Jan 16, 2024
fe6e270
refactor swift error and self class getters
matouskozak Jan 16, 2024
39b8bd0
make cmake architecture specific
matouskozak Jan 17, 2024
eccc6a3
[mono] Use SwiftError as a ref argument instead of raw pointer
kotlarmilos Jan 18, 2024
a6f3369
[mono] Refactor mini to store and load Swift context regs directly in…
kotlarmilos Jan 18, 2024
0b3920e
Revert unnecessary changes
kotlarmilos Jan 18, 2024
0e4a48c
[mini] Always pass SwiftSelf as ArgVtypeInIRegs via dedicated ctx reg
kotlarmilos Jan 18, 2024
2b3d6ff
[mono] Update Swift context registers allocation for P/Invoke
kotlarmilos Jan 22, 2024
f7528f8
[mini] Fix formatting and remove unnecessary code
kotlarmilos Jan 23, 2024
2a1b7c2
[mini] Resolve feedback and remove unnecessary code
kotlarmilos Jan 23, 2024
cdaff6c
[mini] Align arm64 and amd64 implementation to use the existing arg i…
kotlarmilos Jan 23, 2024
1af3d21
[mini] Add swift_error_index to the CallInfo to mark the arg ins as v…
kotlarmilos Jan 23, 2024
d243462
[mini] Move selferror store ins to emit_move_return_value
kotlarmilos Jan 24, 2024
6f36c21
Fix lint
kotlarmilos Jan 24, 2024
a60f392
[mini] Preserve Swift error register value during the P/Invoke call
kotlarmilos Jan 25, 2024
bd11b7b
Merge branch 'dotnet:main' into poc/swift-interop-direct-pinvoke
kotlarmilos Jan 26, 2024
2b2b75e
[mono] Allow SwiftError*, ref SwiftError, and function pointers in Ca…
kotlarmilos Jan 26, 2024
6e54b5b
[mono] Remove unused code and fix lint
kotlarmilos Jan 30, 2024
426802e
[mono] Avoid g_assert for Swift ctx regs
kotlarmilos Jan 30, 2024
4e09785
Update src/mono/mono/metadata/marshal.c
kotlarmilos Jan 31, 2024
89d211c
Update src/mono/mono/metadata/marshal.h
kotlarmilos Jan 31, 2024
d450fb1
Update Swift runtime tests to use blittable types
kotlarmilos Jan 31, 2024
1a39a88
[mono] Simplify register allocation and interp native call context
kotlarmilos Feb 2, 2024
c2e354f
Merge branch 'poc/swift-interop-direct-pinvoke' of github.com:kotlarm…
matouskozak Feb 4, 2024
1405a98
align ArgSwiftError on x64
matouskozak Feb 5, 2024
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
2 changes: 1 addition & 1 deletion src/mono/mono/metadata/icall.c
Original file line number Diff line number Diff line change
Expand Up @@ -2812,7 +2812,7 @@ ves_icall_RuntimeType_GetCallingConventionFromFunctionPointerInternal (MonoQCall
MonoType *type = type_handle.type;
g_assert (type->type == MONO_TYPE_FNPTR);
// FIXME: Once we address: https://github.com/dotnet/runtime/issues/90308 this should not be needed anymore
return GUINT_TO_INT8 (type->data.method->suppress_gc_transition ? MONO_CALL_UNMANAGED_MD : type->data.method->call_convention);
return GUINT_TO_INT8 (mono_method_signature_has_ext_callconv (type->data.method, MONO_EXT_CALLCONV_SUPPRESS_GC_TRANSITION) ? MONO_CALL_UNMANAGED_MD : type->data.method->call_convention);
}

MonoBoolean
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/metadata/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,7 @@ inflate_generic_signature_checked (MonoImage *image, MonoMethodSignature *sig, M
res->explicit_this = sig->explicit_this;
res->call_convention = sig->call_convention;
res->pinvoke = sig->pinvoke;
res->ext_callconv = sig->ext_callconv;
res->generic_param_count = sig->generic_param_count;
res->sentinelpos = sig->sentinelpos;
res->has_type_parameters = is_open;
Expand Down
249 changes: 134 additions & 115 deletions src/mono/mono/metadata/marshal.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ static GENERATE_TRY_GET_CLASS_WITH_CACHE (suppress_gc_transition_attribute, "Sys
static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_callers_only_attribute, "System.Runtime.InteropServices", "UnmanagedCallersOnlyAttribute")
static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_callconv_attribute, "System.Runtime.InteropServices", "UnmanagedCallConvAttribute")

GENERATE_TRY_GET_CLASS_WITH_CACHE (swift_error, "System.Runtime.InteropServices.Swift", "SwiftError")
GENERATE_TRY_GET_CLASS_WITH_CACHE (swift_self, "System.Runtime.InteropServices.Swift", "SwiftSelf")

static gboolean type_is_blittable (MonoType *type);

static IlgenCallbacksToMono ilgenCallbacksToMono = {
Expand Down Expand Up @@ -3232,6 +3235,8 @@ mono_marshal_set_callconv_for_type(MonoType *type, MonoMethodSignature *csig, gb
csig->call_convention = MONO_CALL_FASTCALL;
else if (!strcmp (class_name, "CallConvThiscall"))
csig->call_convention = MONO_CALL_THISCALL;
else if (!strcmp (class_name, "CallConvSwift"))
csig->ext_callconv |= MONO_EXT_CALLCONV_SWIFTCALL;
else if (!strcmp (class_name, "CallConvSuppressGCTransition") && skip_gc_trans != NULL)
*skip_gc_trans = TRUE;
}
Expand Down Expand Up @@ -3358,8 +3363,10 @@ mono_marshal_set_signature_callconv_from_attribute(MonoMethodSignature *sig, Mon
sig->call_convention = MONO_CALL_THISCALL;
else if (!strcmp (name, "Fastcall"))
sig->call_convention = MONO_CALL_FASTCALL;
else if (!strcmp (name, "Swift"))
sig->ext_callconv |= MONO_EXT_CALLCONV_SWIFTCALL;
else if (!strcmp (name, "SuppressGCTransition"))
sig->suppress_gc_transition = 1;
sig->ext_callconv |= MONO_EXT_CALLCONV_SUPPRESS_GC_TRANSITION;
// TODO: Support CallConvMemberFunction?
// TODO: Support multiple calling convetions?
// - Switch MonoCallConvention enum values to powers of 2
Expand Down Expand Up @@ -3427,23 +3434,31 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
MonoMethodSignature *sig, *csig;
MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *) method;
MonoMethodBuilder *mb;
MonoMarshalSpec **mspecs;
MonoMarshalSpec **mspecs = NULL;
MonoMethod *res;
GHashTable *cache;
gboolean pinvoke = FALSE;
gboolean skip_gc_trans = FALSE;
gboolean pinvoke_not_found = FALSE;
gpointer iter;
ERROR_DECL (emitted_error);
WrapperInfo *info;
MonoType *string_type;
GHashTable **cache_ptr;
ERROR_DECL (emitted_error);

g_assert (method != NULL);
g_assertf (mono_method_signature_internal (method)->pinvoke, "%s flags:%X iflags:%X param_count:%X",
method->name, method->flags, method->iflags, mono_method_signature_internal (method)->param_count);

GHashTable **cache_ptr;

MonoType *string_type = m_class_get_byval_arg (mono_defaults.string_class);
if (MONO_CLASS_IS_IMPORT (method->klass)) {
kotlarmilos marked this conversation as resolved.
Show resolved Hide resolved
/* The COM code is not AOT compatible, it calls mono_custom_attrs_get_attr_checked () */
if (aot)
return method;
#ifndef DISABLE_COM
return mono_cominterop_get_native_wrapper (method);
#else
g_assert_not_reached ();
#endif
}

if (aot) {
if (check_exceptions)
Expand All @@ -3470,17 +3485,6 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
}
}

if (MONO_CLASS_IS_IMPORT (method->klass)) {
/* The COM code is not AOT compatible, it calls mono_custom_attrs_get_attr_checked () */
if (aot)
return method;
#ifndef DISABLE_COM
return mono_cominterop_get_native_wrapper (method);
#else
g_assert_not_reached ();
#endif
}

sig = mono_method_signature_internal (method);

if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
Expand All @@ -3493,12 +3497,30 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
mono_error_set_generic_error (emitted_error, "System", "MissingMethodException", "Method contains unsupported native code");
else if (!aot)
mono_lookup_pinvoke_call_internal (method, emitted_error);
} else {
if (!aot || (method->klass == mono_defaults.string_class))
piinfo->addr = mono_lookup_internal_call (method);
} else if (!aot || (method->klass == mono_defaults.string_class)) {
piinfo->addr = mono_lookup_internal_call (method);
}
}

mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);
mb->method->save_lmf = 1;

if (G_UNLIKELY (pinvoke && mono_method_has_unmanaged_callers_only_attribute (method))) {
/*
* In AOT mode and embedding scenarios, it is possible that the icall is not registered in the runtime doing the AOT compilation.
* Emit a wrapper that throws a NotSupportedException.
*/
get_marshal_cb ()->mb_emit_exception (mb, "System", "NotSupportedException", "Method canot be marked with both DllImportAttribute and UnmanagedCallersOnlyAttribute");
goto emit_exception_for_error;
} else if (!pinvoke && !piinfo->addr && !aot) {
/* if there's no code but the error isn't set, just use a fairly generic exception. */
if (is_ok (emitted_error))
mono_error_set_generic_error (emitted_error, "System", "MissingMethodException", "");
get_marshal_cb ()->mb_emit_exception_for_error (mb, emitted_error);
goto emit_exception_for_error;
}

string_type = m_class_get_byval_arg (mono_defaults.string_class);
/* hack - redirect certain string constructors to CreateString */
if (piinfo->addr == ves_icall_System_String_ctor_RedirectToCreateString) {
MonoMethod *m;
Expand Down Expand Up @@ -3555,133 +3577,130 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions,
return res;
}

mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_MANAGED_TO_NATIVE);

mb->method->save_lmf = 1;

if (G_UNLIKELY (pinvoke && mono_method_has_unmanaged_callers_only_attribute (method))) {
/* emit a wrapper that throws a NotSupportedException */
get_marshal_cb ()->mb_emit_exception (mb, "System", "NotSupportedException", "Method canot be marked with both DllImportAttribute and UnmanagedCallersOnlyAttribute");

info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
info->d.managed_to_native.method = method;

csig = mono_metadata_signature_dup_full (get_method_image (method), sig);
csig->pinvoke = 0;
res = mono_mb_create_and_cache_full (cache, method, mb, csig,
csig->param_count + 16, info, NULL);
mono_mb_free (mb);

return res;
}

/*
* In AOT mode and embedding scenarios, it is possible that the icall is not
* registered in the runtime doing the AOT compilation.
*/
/* Handled at runtime */
pinvoke_not_found = !pinvoke && !piinfo->addr && !aot;
if (pinvoke_not_found) {
/* if there's no code but the error isn't set, just use a fairly generic exception. */
if (is_ok (emitted_error))
mono_error_set_generic_error (emitted_error, "System", "MissingMethodException", "");
get_marshal_cb ()->mb_emit_exception_for_error (mb, emitted_error);
mono_error_cleanup (emitted_error);

info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
info->d.managed_to_native.method = method;

csig = mono_metadata_signature_dup_full (get_method_image (method), sig);
csig->pinvoke = 0;
res = mono_mb_create_and_cache_full (cache, method, mb, csig,
csig->param_count + 16, info, NULL);
mono_mb_free (mb);

return res;
}

/* internal calls: we simply push all arguments and call the method (no conversions) */
if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
if (sig->hasthis)
csig = mono_metadata_signature_dup_add_this (get_method_image (method), sig, method->klass);
else
csig = mono_metadata_signature_dup_full (get_method_image (method), sig);

//printf ("%s\n", mono_method_full_name (method, 1));

/* hack - string constructors returns a value */
if (method->string_ctor)
csig->ret = string_type;

get_marshal_cb ()->emit_native_icall_wrapper (mb, method, csig, check_exceptions, aot, piinfo);
} else {
g_assert(pinvoke);

info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
info->d.managed_to_native.method = method;
csig = mono_metadata_signature_dup_full (get_method_image (method), sig);
mono_marshal_set_callconv_from_modopt (method, csig, FALSE);

csig = mono_metadata_signature_dup_full (get_method_image (method), csig);
csig->pinvoke = 0;
res = mono_mb_create_and_cache_full (cache, method, mb, csig, csig->param_count + 16,
info, NULL);
mspecs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
mono_method_get_marshal_info (method, mspecs);

mono_mb_free (mb);
return res;
}
if (mono_class_try_get_suppress_gc_transition_attribute_class ()) {
MonoCustomAttrInfo *cinfo;
ERROR_DECL (error);

g_assert (pinvoke);
cinfo = mono_custom_attrs_from_method_checked (method, error);
mono_error_assert_ok (error);
gboolean found = FALSE;
if (cinfo) {
for (int i = 0; i < cinfo->num_attrs; ++i) {
MonoClass *ctor_class = cinfo->attrs [i].ctor->klass;
if (ctor_class == mono_class_try_get_suppress_gc_transition_attribute_class ()) {
found = TRUE;
break;
}
}
}
if (found)
skip_gc_trans = TRUE;
if (cinfo && !cinfo->cached)
mono_custom_attrs_free (cinfo);
}

csig = mono_metadata_signature_dup_full (get_method_image (method), sig);
mono_marshal_set_callconv_from_modopt (method, csig, FALSE);
if (csig->call_convention == MONO_CALL_DEFAULT) {
/* If the calling convention has not been set, check the UnmanagedCallConv attribute */
mono_marshal_set_callconv_from_unmanaged_callconv_attribute (method, csig, &skip_gc_trans);
}

mspecs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
mono_method_get_marshal_info (method, mspecs);
if (mono_method_signature_has_ext_callconv (csig, MONO_EXT_CALLCONV_SWIFTCALL)) {
Copy link
Member

Choose a reason for hiding this comment

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

@kotlarmilos @vargaz Do we need to prevent these m2n swiftcall wrappers from being inlined? I think there's logic in the mini-arm64 and mini-amd64 backends that depends on the pinvoke bit of the signature.

Copy link
Member Author

Choose a reason for hiding this comment

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

Is the inlining performed before or after the lowering process? Do the method prolog and epilog get inlined as well?

ArgSwiftError is handled differently in the method prolog, which could be affected when it is inlined. Also, there is a potential problem related to context registers clobbering when wrappers are inlined.

Copy link
Contributor

Choose a reason for hiding this comment

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

These wrappers are not inlined right now.

MonoClass *swift_self = mono_class_try_get_swift_self_class ();
MonoClass *swift_error = mono_class_try_get_swift_error_class ();
MonoClass *swift_error_ptr = mono_class_create_ptr (m_class_get_this_arg (swift_error));
int swift_error_args = 0, swift_self_args = 0;
for (int i = 0; i < method->signature->param_count; ++i) {
MonoClass *param_klass = mono_class_from_mono_type_internal (method->signature->params [i]);
if (param_klass) {
if (param_klass == swift_error && !m_type_is_byref (method->signature->params [i])) {
swift_error_args = swift_self_args = 0;
mono_error_set_generic_error (emitted_error, "System", "InvalidProgramException", "SwiftError argument must be passed by reference.");
break;
} else if (param_klass == swift_error || param_klass == swift_error_ptr) {
swift_error_args++;
} else if (param_klass == swift_self) {
swift_self_args++;
} else if (!m_class_is_blittable (param_klass) && m_class_get_this_arg (param_klass)->type != MONO_TYPE_FNPTR) {
swift_error_args = swift_self_args = 0;
mono_error_set_generic_error (emitted_error, "System", "InvalidProgramException", "Passing non-primitive value types to a P/Invoke with the Swift calling convention is unsupported.");
break;
}
}
}

if (mono_class_try_get_suppress_gc_transition_attribute_class ()) {
MonoCustomAttrInfo *cinfo;
ERROR_DECL (error);
if (swift_self_args > 1 || swift_error_args > 1) {
mono_error_set_generic_error (emitted_error, "System", "InvalidProgramException", "Method signature contains multiple SwiftSelf or SwiftError arguments.");
}

cinfo = mono_custom_attrs_from_method_checked (method, error);
mono_error_assert_ok (error);
gboolean found = FALSE;
if (cinfo) {
for (int i = 0; i < cinfo->num_attrs; ++i) {
MonoClass *ctor_class = cinfo->attrs [i].ctor->klass;
if (ctor_class == mono_class_try_get_suppress_gc_transition_attribute_class ()) {
found = TRUE;
break;
}
if (!is_ok (emitted_error)) {
get_marshal_cb ()->mb_emit_exception_for_error (mb, emitted_error);
goto emit_exception_for_error;
}
}
if (found)
skip_gc_trans = TRUE;
if (cinfo && !cinfo->cached)
mono_custom_attrs_free (cinfo);
}

if (csig->call_convention == MONO_CALL_DEFAULT) {
/* If the calling convention has not been set, check the UnmanagedCallConv attribute */
mono_marshal_set_callconv_from_unmanaged_callconv_attribute (method, csig, &skip_gc_trans);
MonoNativeWrapperFlags flags = aot ? EMIT_NATIVE_WRAPPER_AOT : (MonoNativeWrapperFlags)0;
flags |= check_exceptions ? EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS : (MonoNativeWrapperFlags)0;
flags |= skip_gc_trans ? EMIT_NATIVE_WRAPPER_SKIP_GC_TRANS : (MonoNativeWrapperFlags)0;
flags |= runtime_marshalling_enabled (get_method_image (method)) ? EMIT_NATIVE_WRAPPER_RUNTIME_MARSHALLING_ENABLED : (MonoNativeWrapperFlags)0;

mono_marshal_emit_native_wrapper (get_method_image (mb->method), mb, csig, piinfo, mspecs, piinfo->addr, flags);
}

MonoNativeWrapperFlags flags = aot ? EMIT_NATIVE_WRAPPER_AOT : (MonoNativeWrapperFlags)0;
flags |= check_exceptions ? EMIT_NATIVE_WRAPPER_CHECK_EXCEPTIONS : (MonoNativeWrapperFlags)0;
flags |= skip_gc_trans ? EMIT_NATIVE_WRAPPER_SKIP_GC_TRANS : (MonoNativeWrapperFlags)0;
flags |= runtime_marshalling_enabled (get_method_image (method)) ? EMIT_NATIVE_WRAPPER_RUNTIME_MARSHALLING_ENABLED : (MonoNativeWrapperFlags)0;
info = mono_wrapper_info_create (mb, method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)
? WRAPPER_SUBTYPE_NONE
: WRAPPER_SUBTYPE_PINVOKE);

mono_marshal_emit_native_wrapper (get_method_image (mb->method), mb, csig, piinfo, mspecs, piinfo->addr, flags);
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_PINVOKE);
info->d.managed_to_native.method = method;

if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
csig = mono_metadata_signature_dup_full (get_method_image (method), sig);
csig->pinvoke = 0;
res = mono_mb_create_and_cache_full (cache, method, mb, csig, csig->param_count + 16,
info, NULL);
mono_mb_free (mb);

for (int i = sig->param_count; i >= 0; i--)
if (mspecs [i])
mono_metadata_free_marshal_spec (mspecs [i]);
g_free (mspecs);
if (mspecs) {
for (int i = sig->param_count; i >= 0; i--)
if (mspecs [i])
mono_metadata_free_marshal_spec (mspecs [i]);
g_free (mspecs);
}

return res;
goto leave;

emit_exception_for_error:
mono_error_cleanup (emitted_error);
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
info->d.managed_to_native.method = method;

csig = mono_metadata_signature_dup_full (get_method_image (method), sig);
csig->pinvoke = 0;
res = mono_mb_create_and_cache_full (cache, method, mb, csig,
csig->param_count + 16, info, NULL);

leave:
mono_mb_free (mb);
return res;
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/mono/mono/metadata/marshal.h
Original file line number Diff line number Diff line change
Expand Up @@ -771,4 +771,7 @@ mono_mb_create_and_cache_full (GHashTable *cache, gpointer key,
IlgenCallbacksToMono*
mono_marshal_get_mono_callbacks_for_ilgen (void);

GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL (swift_self)
GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL (swift_error)

#endif /* __MONO_MARSHAL_H__ */
13 changes: 12 additions & 1 deletion src/mono/mono/metadata/metadata-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -656,11 +656,17 @@ struct _MonoMethodSignature {
unsigned int pinvoke : 1;
unsigned int is_inflated : 1;
unsigned int has_type_parameters : 1;
unsigned int suppress_gc_transition : 1;
unsigned int marshalling_disabled : 1;
uint8_t ext_callconv; // see MonoExtCallConv
MonoType *params [MONO_ZERO_LEN_ARRAY];
};

typedef enum {
MONO_EXT_CALLCONV_SUPPRESS_GC_TRANSITION = 0x01,
MONO_EXT_CALLCONV_SWIFTCALL = 0x02,
/// see MonoMethodSignature:ext_callconv - only 8 bits
} MonoExtCallConv;

/*
* AOT cache configuration loaded from config files.
* Doesn't really belong here.
Expand Down Expand Up @@ -1275,4 +1281,9 @@ mono_class_set_deferred_type_load_failure (MonoClass *klass, const char * fmt, .
gboolean
mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...);

static inline gboolean
mono_method_signature_has_ext_callconv (MonoMethodSignature *sig, MonoExtCallConv flags) {
return (sig->ext_callconv & flags) != 0;
}

#endif /* __MONO_METADATA_INTERNALS_H__ */
Loading
Loading