Adding SkipInit to Internal.Runtime.CompilerServices.Unsafe (dotnet/coreclr#27377)
authorTanner Gooding <tagoo@outlook.com>
Wed, 23 Oct 2019 03:23:12 +0000 (20:23 -0700)
committerJan Kotas <jkotas@microsoft.com>
Wed, 23 Oct 2019 03:23:12 +0000 (20:23 -0700)
* Adding SkipInit to Internal.Runtime.CompilerServices.Unsafe

* Updating the runtime to handle Unsafe.SkipInit

* Updating Decimal.DecCalc to use Unsafe.SkipInit

* Removing 'workaround for CS0165' comments

Commit migrated from https://github.com/dotnet/coreclr/commit/9bc350f2e7a0b21f1c7d71ffda5ae1797fb5caff

src/coreclr/src/tools/crossgen2/Common/TypeSystem/IL/Stubs/UnsafeIntrinsics.cs
src/coreclr/src/vm/jitinterface.cpp
src/coreclr/src/vm/metasig.h
src/coreclr/src/vm/mscorlib.h
src/libraries/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/Unsafe.cs
src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs

index d7c3ab5..c0e0ea1 100644 (file)
@@ -82,6 +82,8 @@ namespace Internal.IL.Stubs
                         (byte)ILOpcode.ldc_i4_0, (byte)ILOpcode.conv_u,
                         (byte)ILOpcode.prefix1, unchecked((byte)ILOpcode.ceq),
                         (byte)ILOpcode.ret }, Array.Empty<LocalVariableDefinition>(), null);
+                case "SkipInit":
+                    return new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ret }, Array.Empty<LocalVariableDefinition>(), null);
             }
 
             return null;
index c8bb31f..2b23197 100644 (file)
@@ -7338,6 +7338,17 @@ bool getILIntrinsicImplementationForUnsafe(MethodDesc * ftn,
         methInfo->options = (CorInfoOptions)0;
         return true;
     }
+    else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__SKIPINIT)->GetMemberDef())
+    {
+        static BYTE ilcode[] = { CEE_RET };
+
+        methInfo->ILCode = const_cast<BYTE*>(ilcode);
+        methInfo->ILCodeSize = sizeof(ilcode);
+        methInfo->maxStack = 0;
+        methInfo->EHcount = 0;
+        methInfo->options = (CorInfoOptions)0;
+        return true;
+    }
 
     return false;
 }
index 42a52e3..2c04b45 100644 (file)
@@ -303,6 +303,7 @@ DEFINE_METASIG(GM(Obj_RetT, IMAGE_CEE_CS_CALLCONV_DEFAULT, 1, j, M(0)))
 DEFINE_METASIG(GM(RefT_Int_RetRefT, IMAGE_CEE_CS_CALLCONV_DEFAULT, 1, r(M(0)) i, r(M(0))))
 DEFINE_METASIG(GM(RefT_IntPtr_RetRefT, IMAGE_CEE_CS_CALLCONV_DEFAULT, 1, r(M(0)) I, r(M(0))))
 DEFINE_METASIG(GM(PtrVoid_Int_RetPtrVoid, IMAGE_CEE_CS_CALLCONV_DEFAULT, 1, P(v) i, P(v)))
+DEFINE_METASIG(GM(RefT_RetVoid, IMAGE_CEE_CS_CALLCONV_DEFAULT, 1, r(M(0)), v))
 
 DEFINE_METASIG_T(SM(SafeHandle_RefBool_RetIntPtr, C(SAFE_HANDLE) r(F), I ))
 DEFINE_METASIG_T(SM(SafeHandle_RetVoid, C(SAFE_HANDLE), v ))
index d01294b..339b3b9 100644 (file)
@@ -717,6 +717,7 @@ DEFINE_METHOD(UNSAFE,               BYREF_READ_UNALIGNED,   ReadUnaligned, GM_Re
 DEFINE_METHOD(UNSAFE,               BYREF_WRITE_UNALIGNED,  WriteUnaligned, GM_RefByte_T_RetVoid)
 DEFINE_METHOD(UNSAFE,               PTR_READ_UNALIGNED,     ReadUnaligned, GM_PtrVoid_RetT)
 DEFINE_METHOD(UNSAFE,               PTR_WRITE_UNALIGNED,    WriteUnaligned, GM_PtrVoid_T_RetVoid)
+DEFINE_METHOD(UNSAFE,               SKIPINIT,               SkipInit, GM_RefT_RetVoid)
 
 DEFINE_CLASS(INTERLOCKED,           Threading,              Interlocked)
 DEFINE_METHOD(INTERLOCKED,          COMPARE_EXCHANGE_T,     CompareExchange, GM_RefT_T_T_RetT)
index 485c157..7c5f9f7 100644 (file)
@@ -422,5 +422,18 @@ namespace Internal.Runtime.CompilerServices
             // ceq
             // ret
         }
+
+        /// <summary>
+        /// Bypasses definite assignment rules by taking advantage of <c>out</c> semantics.
+        /// </summary>
+        [Intrinsic]
+        [NonVersionable]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void SkipInit<T>(out T value)
+        {
+            throw new PlatformNotSupportedException();
+
+            // ret
+        }
     }
 }
index 7f92b1d..eb5deb9 100644 (file)
@@ -990,8 +990,7 @@ ThrowOverflow:
 
                     // Have to scale by a bunch. Move the number to a buffer where it has room to grow as it's scaled.
                     //
-                    Buf24 bufNum;
-                    _ = &bufNum; // workaround for CS0165
+                    Unsafe.SkipInit(out Buf24 bufNum);
                     DebugPoison(ref bufNum);
 
                     bufNum.Low64 = low64;
@@ -1340,8 +1339,7 @@ ThrowOverflow:
 
                 ulong tmp;
                 uint hiProd;
-                Buf24 bufProd;
-                _ = &bufProd; // workaround for CS0165
+                Unsafe.SkipInit(out Buf24 bufProd);
                 DebugPoison(ref bufProd);
 
                 if ((d1.High | d1.Mid) == 0)
@@ -1922,8 +1920,7 @@ ReturnZero:
             /// </summary>
             internal static unsafe void VarDecDiv(ref DecCalc d1, ref DecCalc d2)
             {
-                Buf12 bufQuo;
-                _ = &bufQuo; // workaround for CS0165
+                Unsafe.SkipInit(out Buf12 bufQuo);
                 DebugPoison(ref bufQuo);
 
                 uint power;
@@ -2024,8 +2021,7 @@ ReturnZero:
 
                     // Shift both dividend and divisor left by curScale.
                     //
-                    Buf16 bufRem;
-                    _ = &bufRem; // workaround for CS0165
+                    Unsafe.SkipInit(out Buf16 bufRem);
                     DebugPoison(ref bufRem);
 
                     bufRem.Low64 = d1.Low64 << curScale;
@@ -2094,8 +2090,7 @@ ReturnZero:
                         //
                         // Start by finishing the shift left by curScale.
                         //
-                        Buf12 bufDivisor;
-                        _ = &bufDivisor; // workaround for CS0165
+                        Unsafe.SkipInit(out Buf12 bufDivisor);
                         DebugPoison(ref bufDivisor);
 
                         bufDivisor.Low64 = divisor;
@@ -2248,8 +2243,7 @@ ThrowOverflow:
                     {
                         d1.uflags = d2.uflags;
                         // Try to scale up dividend to match divisor.
-                        Buf12 bufQuo;
-                        unsafe { _ = &bufQuo; } // workaround for CS0165
+                        Unsafe.SkipInit(out Buf12 bufQuo);
                         DebugPoison(ref bufQuo);
 
                         bufQuo.Low64 = d1.Low64;
@@ -2309,8 +2303,7 @@ ThrowOverflow:
                     tmp = d2.Mid;
                 int shift = BitOperations.LeadingZeroCount(tmp);
 
-                Buf28 b;
-                _ = &b; // workaround for CS0165
+                Unsafe.SkipInit(out Buf28 b);
                 DebugPoison(ref b);
 
                 b.Buf24.Low64 = d1.Low64 << shift;
@@ -2365,8 +2358,7 @@ ThrowOverflow:
                 }
                 else
                 {
-                    Buf12 bufDivisor;
-                    _ = &bufDivisor; // workaround for CS0165
+                    Unsafe.SkipInit(out Buf12 bufDivisor);
                     DebugPoison(ref bufDivisor);
 
                     bufDivisor.Low64 = d2.Low64 << shift;