File mono-6.12-unsafe-nullref.diff of Package mono
diff --git a/mcs/class/corlib/System.Runtime.CompilerServices/Unsafe.cs b/mcs/class/corlib/System.Runtime.CompilerServices/Unsafe.cs
index 318bf290b74..4173be89f79 100644
--- a/mcs/class/corlib/System.Runtime.CompilerServices/Unsafe.cs
+++ b/mcs/class/corlib/System.Runtime.CompilerServices/Unsafe.cs
@@ -158,5 +158,39 @@ public static bool IsAddressLessThan<T>(ref T left, ref T right)
{
return ref AddByteOffset (ref source, (IntPtr)(void*)byteOffset);
}
+
+ /// <summary>
+ /// Returns a by-ref to type <typeparamref name="T"/> that is a null reference.
+ /// </summary>
+ [Intrinsic]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref T NullRef<T>()
+ {
+ return ref Unsafe.AsRef<T>(null);
+
+ // ldc.i4.0
+ // conv.u
+ // ret
+ }
+
+ /// <summary>
+ /// Returns if a given by-ref to type <typeparamref name="T"/> is a null reference.
+ /// </summary>
+ /// <remarks>
+ /// This check is conceptually similar to "(void*)(&source) == nullptr".
+ /// </remarks>
+ [Intrinsic]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsNullRef<T>(ref T source)
+ {
+ return Unsafe.AsPointer(ref source) == null;
+
+ // ldarg.0
+ // ldc.i4.0
+ // conv.u
+ // ceq
+ // ret
+ }
+
}
}
diff --git a/mcs/class/corlib/System.Runtime.CompilerServices/Unsafe.il b/mcs/class/corlib/System.Runtime.CompilerServices/Unsafe.il
index c432c6229e6..a9a0ddbfdd9 100644
--- a/mcs/class/corlib/System.Runtime.CompilerServices/Unsafe.il
+++ b/mcs/class/corlib/System.Runtime.CompilerServices/Unsafe.il
@@ -373,4 +373,22 @@
unbox !!T
ret
}
-}
\ No newline at end of file
+
+ .method public hidebysig static !!T& NullRef<T> () cil managed aggressiveinlining
+ {
+ .maxstack 1
+ ldc.i4.0
+ conv.u
+ ret
+ }
+
+ .method public hidebysig static bool IsNullRef<T> (!!T& 'source') cil managed aggressiveinlining
+ {
+ .maxstack 2
+ ldarg.0
+ ldc.i4.0
+ conv.u
+ ceq
+ ret
+ }
+}
diff --git a/mono/mini/intrinsics.c b/mono/mini/intrinsics.c
index f0a7b694045..7ee98cc5c87 100644
--- a/mono/mini/intrinsics.c
+++ b/mono/mini/intrinsics.c
@@ -573,6 +573,32 @@ emit_unsafe_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignatu
EMIT_NEW_BIALU (cfg, ins, OP_PSUB, dreg, args [1]->dreg, args [0]->dreg);
ins->type = STACK_PTR;
return ins;
+#if 0
+ } else if (!strcmp (cmethod->name, "NullRef")) {
+ g_assert (ctx);
+ g_assert (ctx->method_inst);
+ g_assert (ctx->method_inst->type_argc == 1);
+ g_assert (fsig->param_count == 0);
+
+ dreg = alloc_preg (cfg);
+ EMIT_NEW_ICONST (cfg, ins, 0); //< ldc.i4.0
+ EMIT_NEW_UNALU (cfg, ins, OP_MOVE, dreg, args [0]->dreg); //< conv.u
+ ins->type = STACK_OBJ;
+ ins->klass = mono_get_object_class ();
+ return ins;
+ } else if (!strcmp (cmethod->name, "IsNullRef")) {
+ g_assert (ctx);
+ g_assert (ctx->method_inst);
+ g_assert (ctx->method_inst->type_argc == 1);
+ g_assert (fsig->param_count == 1);
+
+ dreg = alloc_preg (cfg);
+ EMIT_NEW_ICONST (cfg, ins, 0); //< ldc.i4.0
+ EMIT_NEW_UNALU (cfg, ins, OP_MOVE, dreg, args [0]->dreg); //< conv.u
+ EMIT_NEW_BIALU (cfg, ins, OP_COMPARE, -1, args [0]->dreg, args [1]->dreg); //< ceq
+ EMIT_NEW_UNALU (cfg, ins, OP_PCEQ, dreg, -1); //< ceq over *pointer size
+ return ins;
+#endif
}
#ifdef ENABLE_NETCORE
else if (!strcmp (cmethod->name, "InitBlockUnaligned")) {