Author: benm
Date: 2005-12-05 20:13:29 -0500 (Mon, 05 Dec 2005)
New Revision: 53961
Added:
trunk/mono/mono/mini/generics.2.cs
Modified:
trunk/mono/mono/metadata/ChangeLog
trunk/mono/mono/metadata/appdomain.c
trunk/mono/mono/metadata/class-internals.h
trunk/mono/mono/metadata/class.c
trunk/mono/mono/metadata/domain.c
trunk/mono/mono/mini/ChangeLog
trunk/mono/mono/mini/Makefile.am
trunk/mono/mono/mini/inssel.brg
trunk/mono/mono/mini/mini.c
Log:
In mini:
2005-12-05 Ben Maurer <[EMAIL PROTECTED]>
Support for boxing and unboxing nullable types as well as the
isinst operation on nullables, per the CLI ammendment.
* inssel.brg (CEE_ISINST): Special case for nullable
* mini.c (handle_unbox_nullable): new method
(handle_box): Special case for nullable types
(mono_method_to_ir): Call handle_unbox_nullable in correct
places.
* generics.2.cs: New test suite
* Makefile.am: Support for regression tests with generics.
In metadata:
2005-12-05 Ben Maurer <[EMAIL PROTECTED]>
Beginning of support for nullable types in the runtime. Parts of
this patch are from Martin.
* appdomain.c (MONO_CORLIB_VERSION): Bump
* domain.c (mono_init_internal): get the nullable type
* class.c (mono_class_is_nullable): New method
(mono_class_get_nullable_param): New mehod
(mono_class_create_generic): In types T? set cast_class to T
* class-internals.h (MonoDefaults): new nullable default class
(mono_class_get_nullable_param, mono_class_get_nullable_param):
new methods.
Modified: trunk/mono/mono/metadata/ChangeLog
===================================================================
--- trunk/mono/mono/metadata/ChangeLog 2005-12-06 00:20:40 UTC (rev 53960)
+++ trunk/mono/mono/metadata/ChangeLog 2005-12-06 01:13:29 UTC (rev 53961)
@@ -1,3 +1,20 @@
+2005-12-05 Ben Maurer <[EMAIL PROTECTED]>
+
+ Beginning of support for nullable types in the runtime. Parts of
+ this patch are from Martin.
+
+ * appdomain.c (MONO_CORLIB_VERSION): Bump
+
+ * domain.c (mono_init_internal): get the nullable type
+
+ * class.c (mono_class_is_nullable): New method
+ (mono_class_get_nullable_param): New mehod
+ (mono_class_create_generic): In types T? set cast_class to T
+
+ * class-internals.h (MonoDefaults): new nullable default class
+ (mono_class_get_nullable_param, mono_class_get_nullable_param):
+ new methods.
+
2005-12-05 Raja R Harinath <[EMAIL PROTECTED]>
* metadata.c (select_container): New. Refactor code to select the
Modified: trunk/mono/mono/metadata/appdomain.c
===================================================================
--- trunk/mono/mono/metadata/appdomain.c 2005-12-06 00:20:40 UTC (rev
53960)
+++ trunk/mono/mono/metadata/appdomain.c 2005-12-06 01:13:29 UTC (rev
53961)
@@ -30,7 +30,7 @@
#include <mono/metadata/threadpool.h>
#include <mono/utils/mono-uri.h>
-#define MONO_CORLIB_VERSION 43
+#define MONO_CORLIB_VERSION 44
CRITICAL_SECTION mono_delegate_section;
Modified: trunk/mono/mono/metadata/class-internals.h
===================================================================
--- trunk/mono/mono/metadata/class-internals.h 2005-12-06 00:20:40 UTC (rev
53960)
+++ trunk/mono/mono/metadata/class-internals.h 2005-12-06 01:13:29 UTC (rev
53961)
@@ -682,6 +682,7 @@
MonoClass *runtimesecurityframe_class;
MonoClass *executioncontext_class;
MonoClass *generic_array_class;
+ MonoClass *generic_nullable_class;
} MonoDefaults;
extern MonoDefaults mono_defaults;
@@ -772,5 +773,8 @@
MonoArrayType *mono_dup_array_type (MonoArrayType *a);
MonoMethodSignature *mono_metadata_signature_deep_dup (MonoMethodSignature
*sig);
+gboolean mono_class_is_nullable (MonoClass *klass);
+MonoClass *mono_class_get_nullable_param (MonoClass *klass);
+
#endif /* __MONO_METADATA_CLASS_INTERBALS_H__ */
Modified: trunk/mono/mono/metadata/class.c
===================================================================
--- trunk/mono/mono/metadata/class.c 2005-12-06 00:20:40 UTC (rev 53960)
+++ trunk/mono/mono/metadata/class.c 2005-12-06 01:13:29 UTC (rev 53961)
@@ -2719,6 +2719,23 @@
return class;
}
+/** is klass Nullable<T>? */
+gboolean
+mono_class_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 */
+MonoClass*
+mono_class_get_nullable_param (MonoClass *klass)
+{
+ g_assert (mono_class_is_nullable (klass));
+ return mono_class_from_mono_type (klass->generic_class->inst->type_argv
[0]);
+}
+
/*
* Create the `MonoClass' for an instantiation of a generic type.
* We only do this if we actually need it.
@@ -2754,6 +2771,9 @@
klass->cast_class = klass->element_class = klass;
+ if (mono_class_is_nullable (klass))
+ klass->cast_class = klass->element_class =
mono_class_get_nullable_param (klass);
+
if (gclass->generic_class.is_dynamic) {
klass->instance_size = gklass->instance_size;
klass->class_size = gklass->class_size;
Modified: trunk/mono/mono/metadata/domain.c
===================================================================
--- trunk/mono/mono/metadata/domain.c 2005-12-06 00:20:40 UTC (rev 53960)
+++ trunk/mono/mono/metadata/domain.c 2005-12-06 01:13:29 UTC (rev 53961)
@@ -758,12 +758,14 @@
mono_defaults.corlib, "System.Threading", "ExecutionContext");
/*
- * Note that mono_defaults.generic_array_class is only non-NULL if we're
+ * Note that mono_defaults.generic_*_class is only non-NULL if we're
* using the 2.0 corlib.
*/
mono_class_init (mono_defaults.array_class);
mono_defaults.generic_array_class = mono_class_from_name (
mono_defaults.corlib, "System", "Array/InternalArray`1");
+ mono_defaults.generic_nullable_class = mono_class_from_name (
+ mono_defaults.corlib, "System", "Nullable`1");
domain->friendly_name = g_path_get_basename (filename);
Modified: trunk/mono/mono/mini/ChangeLog
===================================================================
--- trunk/mono/mono/mini/ChangeLog 2005-12-06 00:20:40 UTC (rev 53960)
+++ trunk/mono/mono/mini/ChangeLog 2005-12-06 01:13:29 UTC (rev 53961)
@@ -1,3 +1,19 @@
+2005-12-05 Ben Maurer <[EMAIL PROTECTED]>
+
+ Support for boxing and unboxing nullable types as well as the
+ isinst operation on nullables, per the CLI ammendment.
+
+ * inssel.brg (CEE_ISINST): Special case for nullable
+
+ * mini.c (handle_unbox_nullable): new method
+ (handle_box): Special case for nullable types
+ (mono_method_to_ir): Call handle_unbox_nullable in correct
+ places.
+
+ * generics.2.cs: New test suite
+
+ * Makefile.am: Support for regression tests with generics.
+
2005-12-03 Zoltan Varga <[EMAIL PROTECTED]>
* mini-amd64.c (emit_load_volatile_arguments): Add loading of arguments
Modified: trunk/mono/mono/mini/Makefile.am
===================================================================
--- trunk/mono/mono/mini/Makefile.am 2005-12-06 00:20:40 UTC (rev 53960)
+++ trunk/mono/mono/mini/Makefile.am 2005-12-06 01:13:29 UTC (rev 53961)
@@ -29,11 +29,17 @@
$(libgc_static_libs) \
$(ICU_LIBS)
-RUNTIME = MONO_PATH=$(mcs_topdir)/class/lib/default
$(top_builddir)/runtime/mono-wrapper
+CLASS1=$(mcs_topdir)/class/lib/default
+CLASS2=$(mcs_topdir)/class/lib/net_2_0
-MCS = $(RUNTIME) $(mcs_topdir)/class/lib/default/mcs.exe -unsafe -nowarn:0162
-ILASM = $(RUNTIME) $(mcs_topdir)/class/lib/default/ilasm.exe
+RUNTIME = MONO_PATH=$(CLASS1) $(top_builddir)/runtime/mono-wrapper
+RUNTIME2 = MONO_PATH=$(CLASS2) $(top_builddir)/runtime/mono-wrapper
+MCS = $(RUNTIME) $(CLASS1)/mcs.exe -unsafe -nowarn:0162
+GMCS = $(RUNTIME2) $(CLASS2)/gmcs.exe -unsafe -nowarn:0162
+ILASM = $(RUNTIME) $(CLASS1)/ilasm.exe
+
+
AM_CFLAGS = \
-I$(top_srcdir) \
$(LIBGC_CFLAGS) \
@@ -213,7 +219,7 @@
test.cs
regtests=basic.exe arrays.exe basic-float.exe basic-math.exe basic-long.exe
objects.exe basic-calls.exe iltests.exe exceptions.exe bench.exe
-
+regtests2=generics.exe
common_BURGSRC= $(srcdir)/inssel.brg $(srcdir)/inssel-float.brg
if X86
@@ -308,6 +314,9 @@
$(libs) \
$(PLATFORM_LIB)
+%.exe: %.2.cs TestDriver.dll
+ $(GMCS) -out:$@ $< -r:TestDriver.dll
+
%.exe: %.cs TestDriver.dll
$(MCS) /out:$*.exe /unsafe $< /r:TestDriver.dll
@@ -371,12 +380,18 @@
checktests: $(regtests)
for i in $(regtests); do $(RUNTIME) $$i; done
-rcheck: mono $(regtests)
+checktests2: $(regtests2)
+ for i in $(regtests); do $(RUNTIME2) $$i; done
+
+rcheck: mono $(regtests) $(regtests2)
$(RUNTIME) --regression $(regtests)
+ $(RUNTIME2) --regression $(regtests2)
aotcheck: mono $(regtests)
for i in $(regtests); do $(RUNTIME) --aot $$i; done
+ for i in $(regtests2); do $(RUNTIME2) --aot $$i; done
$(RUNTIME) --verbose --regression $(regtests)
+ $(RUNTIME2) --verbose --regression $(regtests2)
rm -f *.exe.so
bench: mono test.exe
Added: trunk/mono/mono/mini/generics.2.cs
===================================================================
--- trunk/mono/mono/mini/generics.2.cs 2005-12-06 00:20:40 UTC (rev 53960)
+++ trunk/mono/mono/mini/generics.2.cs 2005-12-06 01:13:29 UTC (rev 53961)
@@ -0,0 +1,44 @@
+using System;
+
+class Tests {
+
+ static int Main ()
+ {
+ return TestDriver.RunTests (typeof (Tests));
+ }
+
+ public static int test_1_nullable_unbox ()
+ {
+ return Unbox<int?> (1).Value;
+ }
+
+ public static int test_1_nullable_unbox_null ()
+ {
+ return Unbox<int?> (null).HasValue ? 0 : 1;
+ }
+
+ public static int test_1_nullable_box ()
+ {
+ return (int) Box<int?> (1);
+ }
+
+ public static int test_1_nullable_box_null ()
+ {
+ return Box<int?> (null) == null ? 1 : 0;
+ }
+
+ public static int test_1_isinst_nullable ()
+ {
+ object o = 1;
+ return (o is int?) ? 1 : 0;
+ }
+
+ static object Box<T> (T t)
+ {
+ return t;
+ }
+
+ static T Unbox <T> (object o) {
+ return (T) o;
+ }
+}
Property changes on: trunk/mono/mono/mini/generics.2.cs
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/mono/mono/mini/inssel.brg
===================================================================
--- trunk/mono/mono/mini/inssel.brg 2005-12-06 00:20:40 UTC (rev 53960)
+++ trunk/mono/mono/mini/inssel.brg 2005-12-06 01:13:29 UTC (rev 53961)
@@ -1068,6 +1068,10 @@
/* the object_is_null target simply copies the
input register to the output */
mini_emit_isninst_cast (s, eclass_reg,
klass->cast_class, false_label, object_is_null);
}
+ } else if (mono_class_is_nullable (klass)) {
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, vtable_reg,
G_STRUCT_OFFSET (MonoVTable, klass));
+ /* the object_is_null target simply copies the input
register to the output */
+ mini_emit_isninst_cast (s, klass_reg,
klass->cast_class, false_label, object_is_null);
} else {
if (!s->compile_aot && !(s->opt & MONO_OPT_SHARED) &&
(klass->flags & TYPE_ATTRIBUTE_SEALED)) {
/* the remoting code is broken, access the
class for now */
Modified: trunk/mono/mono/mini/mini.c
===================================================================
--- trunk/mono/mono/mini/mini.c 2005-12-06 00:20:40 UTC (rev 53960)
+++ trunk/mono/mono/mini/mini.c 2005-12-06 01:13:29 UTC (rev 53961)
@@ -2568,13 +2568,35 @@
return mono_emit_jit_icall (cfg, bblock, alloc_ftn, iargs, ip);
}
+
+/**
+ * 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 (mono_class_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 +5061,14 @@
break;
}
+ if (mono_class_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 +5119,14 @@
if (!klass)
goto load_error;
+ if (mono_class_is_nullable (klass)) {
+ int v = handle_unbox_nullable (cfg, bblock,
*sp, ip, klass);
+ NEW_TEMPLOAD (cfg, *sp, v);
+ sp ++;
+ ip += 5;
+ break;
+ }
+
/* Needed by the code generated in inssel.brg */
mono_get_got_var (cfg);
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches