Skip to content

Commit 4b94961

Browse files
[release/9.0-staging] Ignore modopts/modreqs for UnsafeAccessor field targets (#109709)
* Ignore modopts/modreqs for `UnsafeAccessor` field targets The generated IL remains correct and doesn't require a .volatile prefix for the generated accessor. This is based off of what Roslyn currently emits if a getter was available. * Update mono --------- Co-authored-by: Aaron R Robinson <[email protected]>
1 parent ab50806 commit 4b94961

File tree

6 files changed

+48
-24
lines changed

6 files changed

+48
-24
lines changed

src/coreclr/vm/prestub.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1497,7 +1497,7 @@ namespace
14971497

14981498
TokenPairList list { nullptr };
14991499
MetaSig::CompareState state{ &list };
1500-
state.IgnoreCustomModifiers = false;
1500+
state.IgnoreCustomModifiers = true;
15011501
if (!DoesFieldMatchUnsafeAccessorDeclaration(cxt, pField, state))
15021502
continue;
15031503

src/mono/mono/metadata/class.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2580,7 +2580,7 @@ mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoTyp
25802580
MonoClassField *gfield = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
25812581
g_assert (gfield != NULL);
25822582
MonoType *field_type = gfield->type;
2583-
if (!mono_metadata_type_equal_full (type, field_type, TRUE))
2583+
if (!mono_metadata_type_equal_full (type, field_type, MONO_TYPE_EQ_FLAGS_SIG_ONLY))
25842584
continue;
25852585
}
25862586
return field;

src/mono/mono/metadata/marshal-lightweight.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2305,8 +2305,8 @@ emit_unsafe_accessor_field_wrapper (MonoMethodBuilder *mb, gboolean inflate_gene
23052305
}
23062306

23072307
MonoClassField *target_field = mono_class_get_field_from_name_full (target_class, member_name, NULL);
2308-
if (target_field == NULL || !mono_metadata_type_equal_full (target_field->type, m_class_get_byval_arg (mono_class_from_mono_type_internal (ret_type)), TRUE)) {
2309-
mono_mb_emit_exception_full (mb, "System", "MissingFieldException",
2308+
if (target_field == NULL || !mono_metadata_type_equal_full (target_field->type, m_class_get_byval_arg (mono_class_from_mono_type_internal (ret_type)), MONO_TYPE_EQ_FLAGS_SIG_ONLY | MONO_TYPE_EQ_FLAG_IGNORE_CMODS)) {
2309+
mono_mb_emit_exception_full (mb, "System", "MissingFieldException",
23102310
g_strdup_printf("No '%s' in '%s'. Or the type of '%s' doesn't match", member_name, m_class_get_name (target_class), member_name));
23112311
return;
23122312
}
@@ -2403,7 +2403,7 @@ inflate_method (MonoClass *klass, MonoMethod *method, MonoMethod *accessor_metho
24032403
if ((context.class_inst != NULL) || (context.method_inst != NULL))
24042404
result = mono_class_inflate_generic_method_checked (method, &context, error);
24052405
mono_error_assert_ok (error);
2406-
2406+
24072407
return result;
24082408
}
24092409

@@ -2425,13 +2425,13 @@ emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, gboolean inflate_gener
24252425
mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "Invalid usage of UnsafeAccessorAttribute.");
24262426
return;
24272427
}
2428-
2428+
24292429
MonoClass *target_class = mono_class_from_mono_type_internal (target_type);
24302430

24312431
ERROR_DECL(find_method_error);
24322432

24332433
MonoMethodSignature *member_sig = ctor_sig_from_accessor_sig (mb, sig);
2434-
2434+
24352435
MonoClass *in_class = target_class;
24362436

24372437
MonoMethod *target_method = mono_unsafe_accessor_find_ctor (in_class, member_sig, target_class, find_method_error);
@@ -2506,7 +2506,7 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, gboolean inflate_gen
25062506
emit_missing_method_error (mb, find_method_error, member_name);
25072507
return;
25082508
}
2509-
2509+
25102510
g_assert (target_method->klass == target_class);
25112511

25122512
emit_unsafe_accessor_ldargs (mb, sig, !hasthis ? 1 : 0);
@@ -2733,7 +2733,7 @@ emit_swift_lowered_struct_load (MonoMethodBuilder *mb, MonoMethodSignature *csig
27332733
}
27342734
}
27352735

2736-
/* Swift struct lowering handling causes csig to have additional arguments.
2736+
/* Swift struct lowering handling causes csig to have additional arguments.
27372737
* This function returns the index of the argument in the csig that corresponds to the argument in the original signature.
27382738
*/
27392739
static int

src/mono/mono/metadata/metadata-internals.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1021,8 +1021,14 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open);
10211021

10221022
MONO_API void mono_type_get_desc (GString *res, MonoType *type, mono_bool include_namespace);
10231023

1024+
enum {
1025+
MONO_TYPE_EQ_FLAGS_NONE = 0,
1026+
MONO_TYPE_EQ_FLAGS_SIG_ONLY = 1,
1027+
MONO_TYPE_EQ_FLAG_IGNORE_CMODS = 2,
1028+
};
1029+
10241030
gboolean
1025-
mono_metadata_type_equal_full (MonoType *t1, MonoType *t2, gboolean signature_only);
1031+
mono_metadata_type_equal_full (MonoType *t1, MonoType *t2, int flags);
10261032

10271033
MonoMarshalSpec *
10281034
mono_metadata_parse_marshal_spec_full (MonoImage *image, MonoImage *parent_image, const char *ptr);

src/mono/mono/metadata/metadata.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@ typedef struct {
4545
MonoGenericContext context;
4646
} MonoInflatedMethodSignature;
4747

48-
enum {
49-
MONO_TYPE_EQ_FLAGS_SIG_ONLY = 1,
50-
MONO_TYPE_EQ_FLAG_IGNORE_CMODS = 2,
51-
};
52-
5348
static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container, gboolean transient,
5449
const char *ptr, const char **rptr, MonoError *error);
5550

@@ -2936,7 +2931,7 @@ aggregate_modifiers_equal (gconstpointer ka, gconstpointer kb)
29362931
for (int i = 0; i < amods1->count; ++i) {
29372932
if (amods1->modifiers [i].required != amods2->modifiers [i].required)
29382933
return FALSE;
2939-
if (!mono_metadata_type_equal_full (amods1->modifiers [i].type, amods2->modifiers [i].type, TRUE))
2934+
if (!mono_metadata_type_equal_full (amods1->modifiers [i].type, amods2->modifiers [i].type, MONO_TYPE_EQ_FLAGS_SIG_ONLY))
29402935
return FALSE;
29412936
}
29422937
return TRUE;
@@ -5936,24 +5931,23 @@ do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, int equiv_flags)
59365931
gboolean
59375932
mono_metadata_type_equal (MonoType *t1, MonoType *t2)
59385933
{
5939-
return do_mono_metadata_type_equal (t1, t2, 0);
5934+
return do_mono_metadata_type_equal (t1, t2, MONO_TYPE_EQ_FLAGS_NONE);
59405935
}
59415936

59425937
/**
59435938
* mono_metadata_type_equal_full:
59445939
* \param t1 a type
59455940
* \param t2 another type
5946-
* \param signature_only if signature only comparison should be made
5941+
* \param flags flags used to modify comparison logic
59475942
*
5948-
* Determine if \p t1 and \p t2 are signature compatible if \p signature_only is TRUE, otherwise
5949-
* behaves the same way as mono_metadata_type_equal.
5950-
* The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, FALSE).
5951-
* \returns TRUE if \p t1 and \p t2 are equal taking \p signature_only into account.
5943+
* Determine if \p t1 and \p t2 are compatible based on the supplied flags.
5944+
* The function mono_metadata_type_equal(a, b) is just a shortcut for mono_metadata_type_equal_full(a, b, MONO_TYPE_EQ_FLAGS_NONE).
5945+
* \returns TRUE if \p t1 and \p t2 are equal.
59525946
*/
59535947
gboolean
5954-
mono_metadata_type_equal_full (MonoType *t1, MonoType *t2, gboolean signature_only)
5948+
mono_metadata_type_equal_full (MonoType *t1, MonoType *t2, int flags)
59555949
{
5956-
return do_mono_metadata_type_equal (t1, t2, signature_only ? MONO_TYPE_EQ_FLAGS_SIG_ONLY : 0);
5950+
return do_mono_metadata_type_equal (t1, t2, flags);
59575951
}
59585952

59595953
enum {

src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,30 @@ public static void Verify_AccessAllFields_CorElementType()
328328
extern static ref delegate*<void> GetFPtr(ref AllFields f);
329329
}
330330

331+
// Contains fields that have modopts/modreqs
332+
struct FieldsWithModifiers
333+
{
334+
private static volatile int s_vInt;
335+
private volatile int _vInt;
336+
}
337+
338+
[Fact]
339+
public static void Verify_AccessFieldsWithModifiers()
340+
{
341+
Console.WriteLine($"Running {nameof(Verify_AccessFieldsWithModifiers)}");
342+
343+
FieldsWithModifiers fieldsWithModifiers = default;
344+
345+
GetStaticVolatileInt(ref fieldsWithModifiers) = default;
346+
GetVolatileInt(ref fieldsWithModifiers) = default;
347+
348+
[UnsafeAccessor(UnsafeAccessorKind.StaticField, Name="s_vInt")]
349+
extern static ref int GetStaticVolatileInt(ref FieldsWithModifiers f);
350+
351+
[UnsafeAccessor(UnsafeAccessorKind.Field, Name="_vInt")]
352+
extern static ref int GetVolatileInt(ref FieldsWithModifiers f);
353+
}
354+
331355
[Fact]
332356
public static void Verify_AccessStaticMethodClass()
333357
{

0 commit comments

Comments
 (0)