Index: mini.c =================================================================== --- mini.c (revision 53280) +++ mini.c (working copy) @@ -2568,13 +2568,54 @@ return mono_emit_jit_icall (cfg, bblock, alloc_ftn, iargs, ip); } + +/** is klass Nullable? */ +static gboolean +type_is_nullable (MonoClass* klass) +{ + return klass->generic_class != NULL && + klass->generic_class->container_class == mono_defaults.generic_nullable_class; +} + +/** if klass is T? return T */ +static MonoClass* +type_get_nullable_param (MonoClass* klass) +{ + g_assert (type_is_nullable (klass)); + + return klass->generic_class->inst->type_argv [0]; +} + + + +/** + * Handles unbox of a Nullable, returning a temp variable + * where the result is stored + */ +static int +handle_unbox_nullable (MonoCompile* cfg, MonoBasicBlock* bblock, MonoInst* val, const guchar *ip, MonoClass* klass) +{ + MonoMethod* method = mono_class_get_method_from_name (klass, "Unbox", 1); + return mono_emit_method_call_spilled (cfg, bblock, method, mono_method_signature (method), &val, ip, NULL); +} + + + static MonoInst * handle_box (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *val, const guchar *ip, MonoClass *klass) { MonoInst *dest, *vtoffset, *add, *vstore; int temp; + if (type_is_nullable (klass)) { + MonoMethod* method = mono_class_get_method_from_name (klass, "Box", 1); + temp = mono_emit_method_call_spilled (cfg, bblock, method, mono_method_signature (method), &val, ip, NULL); + NEW_TEMPLOAD (cfg, dest, temp); + return dest; + } + + temp = handle_alloc (cfg, bblock, klass, TRUE, ip); NEW_TEMPLOAD (cfg, dest, temp); NEW_ICONST (cfg, vtoffset, sizeof (MonoObject)); @@ -5039,6 +5080,15 @@ break; } + if (type_is_nullable (klass)) { + int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass); + NEW_TEMPLOAD (cfg, *sp, v); + sp ++; + ip += 5; + break; + + } + MONO_INST_NEW (cfg, ins, OP_UNBOXCAST); ins->type = STACK_OBJ; ins->inst_left = *sp; @@ -5089,6 +5139,15 @@ if (!klass) goto load_error; + if (type_is_nullable (klass)) { + int v = handle_unbox_nullable (cfg, bblock, *sp, ip, klass); + NEW_TEMPLOADA (cfg, *sp, v); + sp ++; + ip += 5; + break; + } + + /* Needed by the code generated in inssel.brg */ mono_get_got_var (cfg);