Skip to content

Commit

Permalink
[mono][aot] Emit native-to-managed wrappers for [UnmanagedCallersOnly…
Browse files Browse the repository at this point in the history
…] methods in non-full aot mode as well. (#80918)
  • Loading branch information
vargaz authored Jan 27, 2023
1 parent 084998c commit 741fa51
Showing 1 changed file with 100 additions and 66 deletions.
166 changes: 100 additions & 66 deletions src/mono/mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,24 @@ ignore_cfg (MonoCompile *cfg)
return !cfg || cfg->skip;
}

static gboolean
mono_aot_mode_is_full (MonoAotOptions *opts)
{
return opts->mode == MONO_AOT_MODE_FULL;
}

static gboolean
mono_aot_mode_is_interp (MonoAotOptions *opts)
{
return opts->interp;
}

static gboolean
mono_aot_mode_is_hybrid (MonoAotOptions *opts)
{
return opts->mode == MONO_AOT_MODE_HYBRID;
}

static void
aot_printf (MonoAotCompile *acfg, const gchar *format, ...)
{
Expand Down Expand Up @@ -514,6 +532,27 @@ aot_printerrf (MonoAotCompile *acfg, const gchar *format, ...)
va_end (args);
}

static void
report_error (MonoAotCompile *acfg, gboolean fatal, const char *format, ...)
{
FILE *output;
va_list args;

if (acfg->logfile)
output = acfg->logfile;
else
output = stderr;

va_start (args, format);
vfprintf (output, format, args);
va_end (args);

if (acfg->is_full_aot && !acfg->aot_opts.allow_errors && fatal) {
fprintf (output, "FullAOT cannot continue if there are errors.\n");
exit (1);
}
}

static void
report_loader_error (MonoAotCompile *acfg, MonoError *error, gboolean fatal, const char *format, ...)
{
Expand Down Expand Up @@ -5070,9 +5109,58 @@ add_wrappers (MonoAotCompile *acfg)
}
}

/* StructureToPtr/PtrToStructure wrappers */
rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_TYPEDEF]);
for (int i = 0; i < rows; ++i) {
ERROR_DECL (error);
MonoClass *klass;

token = MONO_TOKEN_TYPE_DEF | (i + 1);
klass = mono_class_get_checked (acfg->image, token, error);

if (!klass) {
mono_error_cleanup (error);
continue;
}

if ((m_class_is_valuetype (klass) || ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT))
&& !mono_class_is_gtd (klass) && can_marshal_struct (klass) &&
!(m_class_get_nested_in (klass) && strstr (m_class_get_name (m_class_get_nested_in (klass)), "<PrivateImplementationDetails>") == m_class_get_name (m_class_get_nested_in (klass)))) {
add_method (acfg, mono_marshal_get_struct_to_ptr (klass));
add_method (acfg, mono_marshal_get_ptr_to_struct (klass));
}
}

rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_TYPESPEC]);
for (int i = 0; i < rows; ++i) {
ERROR_DECL (error);
MonoClass *klass;

token = MONO_TOKEN_TYPE_SPEC | (i + 1);
klass = mono_class_get_checked (acfg->image, token, error);

if (!klass) {
mono_error_cleanup (error);
continue;
}

if (m_class_is_ginst (klass) && !mono_class_is_open_constructed_type (m_class_get_byval_arg (klass)) && can_marshal_struct (klass)) {
add_method (acfg, mono_marshal_get_struct_to_ptr (klass));
add_method (acfg, mono_marshal_get_ptr_to_struct (klass));
}
}
}

static void
add_native_to_managed_wrappers (MonoAotCompile *acfg)
{
MonoMethod *method;
MonoMethodSignature *sig;
guint32 token;

GString *export_symbols = g_string_new ("");
/* native-to-managed wrappers */
rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_METHOD]);
int rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_METHOD]);
for (int i = 0; i < rows; ++i) {
ERROR_DECL (error);

Expand Down Expand Up @@ -5198,9 +5286,9 @@ MONO_RESTORE_WARNING
MonoMethod *wrapper;

if (!(method->flags & METHOD_ATTRIBUTE_STATIC)) {
g_warning ("AOT restriction: Method '%s' must be static since it is decorated with [UnmanagedCallers].",
mono_method_full_name (method, TRUE));
exit (1);
report_error (acfg, FALSE, "AOT restriction: Method '%s' must be static since it is decorated with [UnmanagedCallers].",
mono_method_full_name (method, TRUE));
continue;
}

MonoDecodeCustomAttr *decoded_args = mono_reflection_create_custom_attr_data_args_noalloc (acfg->image, e->ctor, e->data, e->data_size, error);
Expand All @@ -5217,7 +5305,10 @@ MONO_RESTORE_WARNING
mono_reflection_free_custom_attr_data_args_noalloc (decoded_args);

wrapper = mono_marshal_get_managed_wrapper (method, NULL, 0, error);
mono_error_assert_ok (error);
if (!is_ok (error)) {
report_loader_error (acfg, error, FALSE, "Unable to generate native entry point '%s' due to '%s'.", mono_method_get_full_name (method), mono_error_get_message (error));
continue;
}

add_method (acfg, wrapper);
if (export_name) {
Expand All @@ -5229,8 +5320,9 @@ MONO_RESTORE_WARNING
g_free (cattr);
}

if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
if (mono_aot_mode_is_full (&acfg->aot_opts) &&
((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))) {
add_method (acfg, mono_marshal_get_native_wrapper (method, TRUE, TRUE));
}
}
Expand All @@ -5247,47 +5339,6 @@ MONO_RESTORE_WARNING
g_free (export_symbols_out);
fclose (export_symbols_outfile);
}

/* StructureToPtr/PtrToStructure wrappers */
rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_TYPEDEF]);
for (int i = 0; i < rows; ++i) {
ERROR_DECL (error);
MonoClass *klass;

token = MONO_TOKEN_TYPE_DEF | (i + 1);
klass = mono_class_get_checked (acfg->image, token, error);

if (!klass) {
mono_error_cleanup (error);
continue;
}

if ((m_class_is_valuetype (klass) || ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT))
&& !mono_class_is_gtd (klass) && can_marshal_struct (klass) &&
!(m_class_get_nested_in (klass) && strstr (m_class_get_name (m_class_get_nested_in (klass)), "<PrivateImplementationDetails>") == m_class_get_name (m_class_get_nested_in (klass)))) {
add_method (acfg, mono_marshal_get_struct_to_ptr (klass));
add_method (acfg, mono_marshal_get_ptr_to_struct (klass));
}
}

rows = table_info_get_rows (&acfg->image->tables [MONO_TABLE_TYPESPEC]);
for (int i = 0; i < rows; ++i) {
ERROR_DECL (error);
MonoClass *klass;

token = MONO_TOKEN_TYPE_SPEC | (i + 1);
klass = mono_class_get_checked (acfg->image, token, error);

if (!klass) {
mono_error_cleanup (error);
continue;
}

if (m_class_is_ginst (klass) && !mono_class_is_open_constructed_type (m_class_get_byval_arg (klass)) && can_marshal_struct (klass)) {
add_method (acfg, mono_marshal_get_struct_to_ptr (klass));
add_method (acfg, mono_marshal_get_ptr_to_struct (klass));
}
}
}

static gboolean
Expand Down Expand Up @@ -5349,24 +5400,6 @@ method_has_type_vars (MonoMethod *method)
return FALSE;
}

static
gboolean mono_aot_mode_is_full (MonoAotOptions *opts)
{
return opts->mode == MONO_AOT_MODE_FULL;
}

static
gboolean mono_aot_mode_is_interp (MonoAotOptions *opts)
{
return opts->interp;
}

static
gboolean mono_aot_mode_is_hybrid (MonoAotOptions *opts)
{
return opts->mode == MONO_AOT_MODE_HYBRID;
}

static void add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, const char *ref);

static void
Expand Down Expand Up @@ -12596,6 +12629,7 @@ collect_methods (MonoAotCompile *acfg)

if (mono_aot_mode_is_full (&acfg->aot_opts))
add_wrappers (acfg);
add_native_to_managed_wrappers (acfg);
return TRUE;
}

Expand Down

0 comments on commit 741fa51

Please sign in to comment.