+ klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
+ if (!klass->element_class)
+ klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
+ klass->instance_size = klass->element_class->instance_size;
+ klass->size_inited = 1;
+ /*
+ * this is almost safe to do with enums and it's needed to be able
+ * to create objects of the enum type (for use in SetConstant).
+ */
+ /* FIXME: Does this mean enums can't have method overrides ? */
+ mono_class_setup_vtable (klass, NULL, 0);
+ }
+}
+
+static MonoMethod*
+reflection_methodbuilder_to_mono_method (MonoClass *klass,
+ ReflectionMethodBuilder *rmb,
+ MonoMethodSignature *sig)
+{
+ MonoMethod *m;
+ MonoMethodNormal *pm;
+
+ if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+ (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
+ m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
+ else
+ m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
+
+ pm = (MonoMethodNormal*)m;
+
+ m->slot = -1;
+ m->flags = rmb->attrs;
+ m->iflags = rmb->iattrs;
+ m->name = mono_string_to_utf8 (rmb->name);
+ m->klass = klass;
+ m->signature = sig;
+ m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
+
+ if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
+ if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
+ m->string_ctor = 1;
+
+ m->addr = mono_lookup_internal_call (m);
+ m->signature->pinvoke = 1;
+ } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
+ /* TODO */
+ m->signature->pinvoke = 1;
+ return m;
+ } else if (!m->klass->dummy &&
+ !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
+ !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
+ MonoMethodHeader *header;
+ guint32 code_size;
+ gint32 max_stack, i;
+ gint32 num_locals = 0;
+ gint32 num_clauses = 0;
+ guint8 *code;
+
+ if (rmb->ilgen) {
+ code = mono_array_addr (rmb->ilgen->code, guint8, 0);
+ code_size = rmb->ilgen->code_len;
+ max_stack = rmb->ilgen->max_stack;
+ num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
+ if (rmb->ilgen->ex_handlers)
+ num_clauses = method_count_clauses (rmb->ilgen);
+ } else {
+ if (rmb->code) {
+ code = mono_array_addr (rmb->code, guint8, 0);
+ code_size = mono_array_length (rmb->code);
+ /* we probably need to run a verifier on the code... */
+ max_stack = 8;
+ }
+ else {
+ code = NULL;
+ code_size = 0;
+ max_stack = 8;
+ }
+ }
+
+ header = g_malloc0 (sizeof (MonoMethodHeader) +
+ (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+ header->code_size = code_size;
+ header->code = g_malloc (code_size);
+ memcpy ((char*)header->code, code, code_size);
+ header->max_stack = max_stack;
+ header->init_locals = rmb->init_locals;
+ header->num_locals = num_locals;
+
+ for (i = 0; i < num_locals; ++i) {
+ MonoReflectionLocalBuilder *lb =
+ mono_array_get (rmb->ilgen->locals,
+ MonoReflectionLocalBuilder*, i);
+
+ header->locals [i] = g_new0 (MonoType, 1);
+ memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
+ }
+
+ header->num_clauses = num_clauses;
+ if (num_clauses) {
+ header->clauses = method_encode_clauses (klass->image->assembly->dynamic,
+ rmb->ilgen,
+ num_clauses);
+ }
+
+ pm->header = header;
+ }
+
+ return m;
+}
+
+static MonoMethod*
+ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
+{
+ ReflectionMethodBuilder rmb;
+ const char *name;
+ MonoMethodSignature *sig;
+
+ name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
+
+ sig = ctor_builder_to_signature (mb);
+
+ rmb.ilgen = mb->ilgen;
+ rmb.parameters = mb->parameters;
+ rmb.pinfo = mb->pinfo;
+ rmb.attrs = mb->attrs | METHOD_ATTRIBUTE_RT_SPECIAL_NAME;
+ rmb.iattrs = mb->iattrs;
+ rmb.call_conv = mb->call_conv;
+ rmb.type = mb->type;
+ rmb.name = mono_string_new (mono_domain_get (), name);
+ rmb.table_idx = &mb->table_idx;
+ rmb.init_locals = mb->init_locals;
+ rmb.code = NULL;
+
+ mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+ mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
+
+ if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
+ /* ilgen is no longer needed */
+ mb->ilgen = NULL;
+ }
+
+ return mb->mhandle;
+}
+
+static MonoMethod*
+methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
+{
+ ReflectionMethodBuilder rmb;
+ MonoMethodSignature *sig;
+
+ sig = method_builder_to_signature (mb);
+
+ rmb.ilgen = mb->ilgen;
+ rmb.parameters = mb->parameters;
+ rmb.pinfo = mb->pinfo;
+ rmb.attrs = mb->attrs;
+ rmb.iattrs = mb->iattrs;
+ rmb.call_conv = mb->call_conv;
+ rmb.type = mb->type;
+ rmb.name = mb->name;
+ rmb.table_idx = &mb->table_idx;
+ rmb.init_locals = mb->init_locals;
+ rmb.code = mb->code;
+
+ mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
+ mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
+
+ if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->save) {
+ /* ilgen is no longer needed */
+ mb->ilgen = NULL;
+ }
+ return mb->mhandle;
+}
+
+static void
+ensure_runtime_vtable (MonoClass *klass)
+{
+ MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ int i, num, j, onum;
+ MonoMethod **overrides;
+
+ if (!tb || klass->wastypebuilder)
+ return;
+ if (klass->parent)
+ ensure_runtime_vtable (klass->parent);
+
+ num = tb->ctors? mono_array_length (tb->ctors): 0;
+ num += tb->methods? mono_array_length (tb->methods): 0;
+ klass->method.count = num;
+ klass->methods = g_new (MonoMethod*, num);
+ num = tb->ctors? mono_array_length (tb->ctors): 0;
+ for (i = 0; i < num; ++i)
+ klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
+ num = tb->methods? mono_array_length (tb->methods): 0;
+ j = i;
+ for (i = 0; i < num; ++i)
+ klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
+
+ klass->wastypebuilder = TRUE;
+ if (tb->interfaces) {
+ klass->interface_count = mono_array_length (tb->interfaces);
+ klass->interfaces = g_new (MonoClass*, klass->interface_count);
+ for (i = 0; i < klass->interface_count; ++i) {
+ MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
+ klass->interfaces [i] = mono_class_from_mono_type (iface->type);
+ }
+ }
+
+ if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
+ for (i = 0; i < klass->method.count; ++i)
+ klass->methods [i]->slot = i;
+
+ /* Overrides */
+ onum = 0;
+ if (tb->methods) {
+ for (i = 0; i < mono_array_length (tb->methods); ++i) {
+ MonoReflectionMethodBuilder *mb =
+ mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
+ if (mb->override_method)
+ onum ++;
+ }
+ }
+
+ overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
+
+ if (tb->methods) {
+ onum = 0;
+ for (i = 0; i < mono_array_length (tb->methods); ++i) {
+ MonoReflectionMethodBuilder *mb =
+ mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
+ if (mb->override_method) {
+ /* FIXME: What if 'override_method' is a MethodBuilder ? */
+ overrides [onum * 2] =
+ mb->override_method->method;
+ overrides [onum * 2 + 1] =
+ mb->mhandle;
+
+ g_assert (mb->mhandle);
+
+ onum ++;
+ }
+ }
+ }
+
+ mono_class_setup_vtable (klass, overrides, onum);
+}
+
+static void
+typebuilder_setup_fields (MonoClass *klass)
+{
+ MonoReflectionTypeBuilder *tb = klass->reflection_info;
+ MonoReflectionFieldBuilder *fb;
+ MonoClassField *field;
+ const char *p, *p2;
+ int i;
+ guint32 len, idx;
+
+ klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
+ klass->field.first = 0;
+ klass->field.last = klass->field.count;
+
+ if (!klass->field.count)
+ return;
+
+ klass->fields = g_new0 (MonoClassField, klass->field.count);
+
+ for (i = 0; i < klass->field.count; ++i) {
+ fb = mono_array_get (tb->fields, gpointer, i);
+ field = &klass->fields [i];
+ field->name = mono_string_to_utf8 (fb->name);
+ if (fb->attrs) {
+ /* FIXME: handle type modifiers */
+ field->type = g_memdup (fb->type->type, sizeof (MonoType));
+ field->type->attrs = fb->attrs;
+ } else {
+ field->type = fb->type->type;
+ }
+ if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
+ field->data = mono_array_addr (fb->rva_data, char, 0);
+ if (fb->offset != -1)
+ field->offset = fb->offset;
+ field->parent = klass;
+ fb->handle = field;
+ mono_save_custom_attrs (klass->image, field, fb->cattrs);
+
+ if (fb->def_value) {
+ field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
+ MonoDynamicAssembly *assembly = klass->image->assembly->dynamic;
+ field->def_value = g_new0 (MonoConstant, 1);
+ idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
+ /* Copy the data from the blob since it might get realloc-ed */
+ p = assembly->blob.data + idx;
+ len = mono_metadata_decode_blob_size (p, &p2);
+ len += p2 - p;
+ field->def_value->value = g_malloc (len);
+ memcpy (field->def_value->value, p, len);
+ }
+ }
+ mono_class_layout_fields (klass);
+}
+
+MonoReflectionType*
+mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
+{
+ MonoClass *klass;
+ MonoReflectionType* res;
+
+ MONO_ARCH_SAVE_REGS;
+
+ klass = my_mono_class_from_mono_type (tb->type.type);
+
+ mono_save_custom_attrs (klass->image, klass, tb->cattrs);
+
+ /*
+ * Fields to set in klass:
+ * the various flags: delegate/unicode/contextbound etc.
+ * nested_classes
+ * properties
+ * events
+ */
+ klass->flags = tb->attrs;
+ klass->element_class = klass;
+
+ if (!((MonoDynamicAssembly*)klass->image->assembly->dynamic)->run)
+ /* No need to fully construct the type */
+ return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
+
+ /* enums are done right away */
+ if (!klass->enumtype)
+ ensure_runtime_vtable (klass);
+
+ /* fields and object layout */
+ if (klass->parent) {
+ if (!klass->parent->size_inited)
+ mono_class_init (klass->parent);
+ klass->instance_size += klass->parent->instance_size;
+ klass->class_size += klass->parent->class_size;
+ klass->min_align = klass->parent->min_align;
+ } else {
+ klass->instance_size = sizeof (MonoObject);
+ klass->min_align = 1;