Skip to content

Commit

Permalink
[sre] Emit a memberref token for fields,methods of a gtd
Browse files Browse the repository at this point in the history
This can happen when emitting code like:
```
  class Foo<T> {
    T elt;
    public T getter () {
      return elt;  // ILGenerator.Emit (OpCodes.Ldfld, /*FieldBuilder of Foo::elt*/)
    };
  }
```

the old incorrect code emitted a fielddef token for Foo::elt, but it should be a
memberref for Foo<!0>::elt.

Likewise, if we have
```
class Foo<T> {
  public T f () { /*...*/}
  public void g () {
    var x = f (); // ILGenerator.Emit (OpCodes.Call, /* MethodBuilder of Foo::f */)
    /*... */
  }
}
```

Fixes mono#6192

the old incorrect code would emit a fieldref token for Foo::f but it should be
a memberref for Foo<!0>::f
  • Loading branch information
lambdageek committed Dec 20, 2017
1 parent d4ffec6 commit 3a0de97
Showing 1 changed file with 12 additions and 2 deletions.
14 changes: 12 additions & 2 deletions mono/metadata/sre.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,12 @@ is_field_on_inst (MonoClassField *field)
return mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->is_dynamic;
}

static gboolean
is_field_on_gtd (MonoClassField *field)
{
return mono_class_is_gtd (field->parent);
}

#ifndef DISABLE_REFLECTION_EMIT
static guint32
mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoClassField *field)
Expand Down Expand Up @@ -1159,7 +1165,8 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj,
} else
token = mono_image_get_inflated_method_token (assembly, method);
} else if ((method->klass->image == &assembly->image) &&
!mono_class_is_ginst (method->klass)) {
!mono_class_is_ginst (method->klass) &&
!mono_class_is_gtd (method->klass)) {
static guint32 method_table_idx = 0xffffff;
if (method->klass->wastypebuilder) {
/* we use the same token as the one that was assigned
Expand Down Expand Up @@ -1198,10 +1205,13 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj,
} else if (strcmp (klass->name, "MonoField") == 0) {
MonoReflectionFieldHandle f = MONO_HANDLE_CAST (MonoReflectionField, obj);
MonoClassField *field = MONO_HANDLE_GETVAL (f, field);
if ((field->parent->image == &assembly->image) && !is_field_on_inst (field)) {
if ((field->parent->image == &assembly->image) &&
!is_field_on_gtd (field) &&
!is_field_on_inst (field)) {
static guint32 field_table_idx = 0xffffff;
field_table_idx --;
token = MONO_TOKEN_FIELD_DEF | field_table_idx;
g_assert (!mono_class_is_gtd (field->parent));
how_collide = MONO_DYN_IMAGE_TOK_NEW;
} else {
guint32 fieldref_token = mono_image_get_fieldref_token (assembly, field);
Expand Down

0 comments on commit 3a0de97

Please sign in to comment.