rendered paste bodyIndex: 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<T>? */
+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<T>, 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);