Bladeren bron

Fix ovf cast

sunnycase 6 jaren geleden
bovenliggende
commit
44b1f9c0bd

+ 9 - 1
src/Chino.Kernel/Program.cs

@@ -38,7 +38,15 @@ namespace Chino.Kernel
                       terminal.Write(item + ", ");
 
                   terminal.WriteLine();
-                  terminal.Ready();
+                  //terminal.Ready();
+
+                  var sw = new Stopwatch();
+                  sw.Start();
+                  int sum = 0;
+                  for (int i = 0; i < 10000; i++)
+                      sum += i;
+                  sw.Stop();
+                  terminal.WriteLine($"Benchmark: {sw.ElapsedMilliseconds.ToString()} ms");
               });
 
             systemThread.Description = "System";

+ 1 - 0
src/Native/CMakeLists.txt

@@ -15,6 +15,7 @@ set(SRCS natsu.fcall.cpp
          Generated/System.Collections.cpp
          Generated/System.Diagnostics.Debug.cpp
          Generated/System.Runtime.cpp
+         Generated/System.Runtime.Extensions.cpp
          Generated/Chino.Core.cpp
          Generated/Chino.Kernel.cpp
          Generated/BitFields.cpp)

+ 16 - 0
src/Native/arch/emulator/environment.cpp

@@ -1,4 +1,5 @@
 #include "System.Private.CoreLib.h"
+#include "System.Runtime.Extensions.h"
 #include "win_utils.h"
 #include <Windows.h>
 #include <algorithm>
@@ -7,6 +8,7 @@
 
 using namespace natsu;
 using namespace System_Private_CoreLib::System;
+using namespace System_Runtime_Extensions::System::Diagnostics;
 
 int32_t Environment::_s_GetProcessorCount()
 {
@@ -31,3 +33,17 @@ int32_t Environment::_s_GetProcessorCount()
 
     return logical_core_count;
 }
+
+int64_t Stopwatch::_s_QueryPerformanceFrequency()
+{
+    int64_t value;
+    THROW_WIN32_IF_NOT(QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER *>(&value)));
+    return value;
+}
+
+int64_t Stopwatch::_s_QueryPerformanceCounter()
+{
+    int64_t value;
+    THROW_WIN32_IF_NOT(QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&value)));
+    return value;
+}

+ 66 - 57
src/Native/natsu.runtime.h

@@ -1230,6 +1230,15 @@ namespace ops
         return static_cast<cast>(static_cast<med_cast>(v1));                                           \
     }
 
+#define CONV_OVF_UN_IMPL(name, value_type, ret, pre_cast, med_cast, cast) \
+    inline ret conv_ovf_##name(value_type value)                          \
+    {                                                                     \
+        auto v1 = static_cast<pre_cast>(value.value_);                    \
+        if (v1 > std::numeric_limits<med_cast>::max())                    \
+            throw_overflow_exception();                                   \
+        return static_cast<cast>(static_cast<med_cast>(v1));              \
+    }
+
     CONV_OVF_IMPL(i1, stack::int32, stack::int32, int32_t, int8_t, int32_t);
     CONV_OVF_IMPL(i1, stack::int64, stack::int32, int64_t, int8_t, int32_t);
     CONV_OVF_IMPL(i1, stack::native_int, stack::int32, intptr_t, int8_t, int32_t);
@@ -1288,63 +1297,63 @@ namespace ops
     CONV_OVF_IMPL(u, stack::Ref, stack::native_int, intptr_t, uintptr_t, intptr_t);
     CONV_OVF_IMPL(u, stack::O, stack::native_int, intptr_t, uintptr_t, intptr_t);
 
-    CONV_OVF_IMPL(i1_un, stack::int32, stack::int32, uint32_t, int8_t, int32_t);
-    CONV_OVF_IMPL(i1_un, stack::int64, stack::int32, uint64_t, int8_t, int32_t);
-    CONV_OVF_IMPL(i1_un, stack::native_int, stack::int32, uintptr_t, int8_t, int32_t);
-    CONV_OVF_IMPL(i1_un, stack::F, stack::int32, double, int8_t, int32_t);
-
-    CONV_OVF_IMPL(i2_un, stack::int32, stack::int32, uint32_t, int16_t, int32_t);
-    CONV_OVF_IMPL(i2_un, stack::int64, stack::int32, uint64_t, int16_t, int32_t);
-    CONV_OVF_IMPL(i2_un, stack::native_int, stack::int32, uintptr_t, int16_t, int32_t);
-    CONV_OVF_IMPL(i2_un, stack::F, stack::int32, double, int16_t, int32_t);
-
-    CONV_OVF_IMPL(i4_un, stack::int32, stack::int32, uint32_t, int32_t, int32_t);
-    CONV_OVF_IMPL(i4_un, stack::int64, stack::int32, uint64_t, int32_t, int32_t);
-    CONV_OVF_IMPL(i4_un, stack::native_int, stack::int32, uintptr_t, int32_t, int32_t);
-    CONV_OVF_IMPL(i4_un, stack::F, stack::int32, double, int32_t, int32_t);
-
-    CONV_OVF_IMPL(i8_un, stack::int32, stack::int64, uint32_t, int64_t, int64_t);
-    CONV_OVF_IMPL(i8_un, stack::int64, stack::int64, uint64_t, int64_t, int64_t);
-    CONV_OVF_IMPL(i8_un, stack::native_int, stack::int64, uintptr_t, int64_t, int64_t);
-    CONV_OVF_IMPL(i8_un, stack::F, stack::int64, double, int64_t, int64_t);
-    CONV_OVF_IMPL(i8_un, stack::Ref, stack::int64, uintptr_t, int64_t, int64_t);
-    CONV_OVF_IMPL(i8_un, stack::O, stack::int64, uintptr_t, int64_t, int64_t);
-
-    CONV_OVF_IMPL(i_un, stack::int32, stack::native_int, uint32_t, intptr_t, intptr_t);
-    CONV_OVF_IMPL(i_un, stack::int64, stack::native_int, uint64_t, intptr_t, intptr_t);
-    CONV_OVF_IMPL(i_un, stack::native_int, stack::native_int, uintptr_t, intptr_t, intptr_t);
-    CONV_OVF_IMPL(i_un, stack::F, stack::native_int, double, intptr_t, intptr_t);
-    CONV_OVF_IMPL(i_un, stack::Ref, stack::native_int, uintptr_t, intptr_t, intptr_t);
-    CONV_OVF_IMPL(i_un, stack::O, stack::native_int, uintptr_t, intptr_t, intptr_t);
-
-    CONV_OVF_IMPL(u1_un, stack::int32, stack::int32, uint32_t, uint8_t, int32_t);
-    CONV_OVF_IMPL(u1_un, stack::int64, stack::int32, uint64_t, uint8_t, int32_t);
-    CONV_OVF_IMPL(u1_un, stack::native_int, stack::int32, uintptr_t, uint8_t, int32_t);
-    CONV_OVF_IMPL(u1_un, stack::F, stack::int32, double, uint8_t, int32_t);
-
-    CONV_OVF_IMPL(u2_un, stack::int32, stack::int32, uint32_t, uint16_t, int32_t);
-    CONV_OVF_IMPL(u2_un, stack::int64, stack::int32, uint64_t, uint16_t, int32_t);
-    CONV_OVF_IMPL(u2_un, stack::native_int, stack::int32, uintptr_t, uint16_t, int32_t);
-    CONV_OVF_IMPL(u2_un, stack::F, stack::int32, double, uint16_t, int32_t);
-
-    CONV_OVF_IMPL(u4_un, stack::int32, stack::int32, uint32_t, uint32_t, int32_t);
-    CONV_OVF_IMPL(u4_un, stack::int64, stack::int32, uint64_t, uint32_t, int32_t);
-    CONV_OVF_IMPL(u4_un, stack::native_int, stack::int32, uintptr_t, uint32_t, int32_t);
-    CONV_OVF_IMPL(u4_un, stack::F, stack::int32, double, uint32_t, int32_t);
-
-    CONV_OVF_IMPL(u8_un, stack::int32, stack::int64, uint32_t, uint64_t, int64_t);
-    CONV_OVF_IMPL(u8_un, stack::int64, stack::int64, uint64_t, uint64_t, int64_t);
-    CONV_OVF_IMPL(u8_un, stack::native_int, stack::int64, uintptr_t, uint64_t, int64_t);
-    CONV_OVF_IMPL(u8_un, stack::F, stack::int64, double, uint64_t, int64_t);
-    CONV_OVF_IMPL(u8_un, stack::Ref, stack::int64, uintptr_t, uint64_t, int64_t);
-    CONV_OVF_IMPL(u8_un, stack::O, stack::int64, uintptr_t, uint64_t, int64_t);
-
-    CONV_OVF_IMPL(u_un, stack::int32, stack::native_int, uint32_t, uintptr_t, intptr_t);
-    CONV_OVF_IMPL(u_un, stack::int64, stack::native_int, uint64_t, uintptr_t, intptr_t);
-    CONV_OVF_IMPL(u_un, stack::native_int, stack::native_int, uintptr_t, uintptr_t, intptr_t);
-    CONV_OVF_IMPL(u_un, stack::F, stack::native_int, double, uintptr_t, intptr_t);
-    CONV_OVF_IMPL(u_un, stack::Ref, stack::native_int, uintptr_t, uintptr_t, intptr_t);
-    CONV_OVF_IMPL(u_un, stack::O, stack::native_int, uintptr_t, uintptr_t, intptr_t);
+    CONV_OVF_UN_IMPL(i1_un, stack::int32, stack::int32, uint32_t, int8_t, int32_t);
+    CONV_OVF_UN_IMPL(i1_un, stack::int64, stack::int32, uint64_t, int8_t, int32_t);
+    CONV_OVF_UN_IMPL(i1_un, stack::native_int, stack::int32, uintptr_t, int8_t, int32_t);
+    CONV_OVF_UN_IMPL(i1_un, stack::F, stack::int32, double, int8_t, int32_t);
+
+    CONV_OVF_UN_IMPL(i2_un, stack::int32, stack::int32, uint32_t, int16_t, int32_t);
+    CONV_OVF_UN_IMPL(i2_un, stack::int64, stack::int32, uint64_t, int16_t, int32_t);
+    CONV_OVF_UN_IMPL(i2_un, stack::native_int, stack::int32, uintptr_t, int16_t, int32_t);
+    CONV_OVF_UN_IMPL(i2_un, stack::F, stack::int32, double, int16_t, int32_t);
+
+    CONV_OVF_UN_IMPL(i4_un, stack::int32, stack::int32, uint32_t, int32_t, int32_t);
+    CONV_OVF_UN_IMPL(i4_un, stack::int64, stack::int32, uint64_t, int32_t, int32_t);
+    CONV_OVF_UN_IMPL(i4_un, stack::native_int, stack::int32, uintptr_t, int32_t, int32_t);
+    CONV_OVF_UN_IMPL(i4_un, stack::F, stack::int32, double, int32_t, int32_t);
+
+    CONV_OVF_UN_IMPL(i8_un, stack::int32, stack::int64, uint32_t, int64_t, int64_t);
+    CONV_OVF_UN_IMPL(i8_un, stack::int64, stack::int64, uint64_t, int64_t, int64_t);
+    CONV_OVF_UN_IMPL(i8_un, stack::native_int, stack::int64, uintptr_t, int64_t, int64_t);
+    CONV_OVF_UN_IMPL(i8_un, stack::F, stack::int64, double, int64_t, int64_t);
+    CONV_OVF_UN_IMPL(i8_un, stack::Ref, stack::int64, uintptr_t, int64_t, int64_t);
+    CONV_OVF_UN_IMPL(i8_un, stack::O, stack::int64, uintptr_t, int64_t, int64_t);
+
+    CONV_OVF_UN_IMPL(i_un, stack::int32, stack::native_int, uint32_t, intptr_t, intptr_t);
+    CONV_OVF_UN_IMPL(i_un, stack::int64, stack::native_int, uint64_t, intptr_t, intptr_t);
+    CONV_OVF_UN_IMPL(i_un, stack::native_int, stack::native_int, uintptr_t, intptr_t, intptr_t);
+    CONV_OVF_UN_IMPL(i_un, stack::F, stack::native_int, double, intptr_t, intptr_t);
+    CONV_OVF_UN_IMPL(i_un, stack::Ref, stack::native_int, uintptr_t, intptr_t, intptr_t);
+    CONV_OVF_UN_IMPL(i_un, stack::O, stack::native_int, uintptr_t, intptr_t, intptr_t);
+
+    CONV_OVF_UN_IMPL(u1_un, stack::int32, stack::int32, uint32_t, uint8_t, int32_t);
+    CONV_OVF_UN_IMPL(u1_un, stack::int64, stack::int32, uint64_t, uint8_t, int32_t);
+    CONV_OVF_UN_IMPL(u1_un, stack::native_int, stack::int32, uintptr_t, uint8_t, int32_t);
+    CONV_OVF_UN_IMPL(u1_un, stack::F, stack::int32, double, uint8_t, int32_t);
+
+    CONV_OVF_UN_IMPL(u2_un, stack::int32, stack::int32, uint32_t, uint16_t, int32_t);
+    CONV_OVF_UN_IMPL(u2_un, stack::int64, stack::int32, uint64_t, uint16_t, int32_t);
+    CONV_OVF_UN_IMPL(u2_un, stack::native_int, stack::int32, uintptr_t, uint16_t, int32_t);
+    CONV_OVF_UN_IMPL(u2_un, stack::F, stack::int32, double, uint16_t, int32_t);
+
+    CONV_OVF_UN_IMPL(u4_un, stack::int32, stack::int32, uint32_t, uint32_t, int32_t);
+    CONV_OVF_UN_IMPL(u4_un, stack::int64, stack::int32, uint64_t, uint32_t, int32_t);
+    CONV_OVF_UN_IMPL(u4_un, stack::native_int, stack::int32, uintptr_t, uint32_t, int32_t);
+    CONV_OVF_UN_IMPL(u4_un, stack::F, stack::int32, double, uint32_t, int32_t);
+
+    CONV_OVF_UN_IMPL(u8_un, stack::int32, stack::int64, uint32_t, uint64_t, int64_t);
+    CONV_OVF_UN_IMPL(u8_un, stack::int64, stack::int64, uint64_t, uint64_t, int64_t);
+    CONV_OVF_UN_IMPL(u8_un, stack::native_int, stack::int64, uintptr_t, uint64_t, int64_t);
+    CONV_OVF_UN_IMPL(u8_un, stack::F, stack::int64, double, uint64_t, int64_t);
+    CONV_OVF_UN_IMPL(u8_un, stack::Ref, stack::int64, uintptr_t, uint64_t, int64_t);
+    CONV_OVF_UN_IMPL(u8_un, stack::O, stack::int64, uintptr_t, uint64_t, int64_t);
+
+    CONV_OVF_UN_IMPL(u_un, stack::int32, stack::native_int, uint32_t, uintptr_t, intptr_t);
+    CONV_OVF_UN_IMPL(u_un, stack::int64, stack::native_int, uint64_t, uintptr_t, intptr_t);
+    CONV_OVF_UN_IMPL(u_un, stack::native_int, stack::native_int, uintptr_t, uintptr_t, intptr_t);
+    CONV_OVF_UN_IMPL(u_un, stack::F, stack::native_int, double, uintptr_t, intptr_t);
+    CONV_OVF_UN_IMPL(u_un, stack::Ref, stack::native_int, uintptr_t, uintptr_t, intptr_t);
+    CONV_OVF_UN_IMPL(u_un, stack::O, stack::native_int, uintptr_t, uintptr_t, intptr_t);
 
 #undef CONV_OVF_IMPL
 

+ 3 - 3
src/Natsu.Compiler/ILImporter.cs

@@ -1155,7 +1155,7 @@ namespace Natsu.Compiler
         public void Ldsfld()
         {
             var field = (IField)Op.Operand;
-            string expr = Method.IsStaticConstructor && Method.DeclaringType == field.DeclaringType.Scope
+            string expr = Method.IsStaticConstructor && TypeUtils.IsSameType(Method.DeclaringType, field.DeclaringType)
                 ? TypeUtils.EscapeIdentifier(field.Name)
                 : "::natsu::static_holder<typename" + TypeUtils.EscapeTypeName(field.DeclaringType) + "::Static>::get()." + TypeUtils.EscapeIdentifier(field.Name);
             var fieldType = field.FieldSig.Type;
@@ -1193,7 +1193,7 @@ namespace Natsu.Compiler
         public void Ldsflda()
         {
             var field = (IField)Op.Operand;
-            string expr = Method.IsStaticConstructor && Method.DeclaringType == field.DeclaringType
+            string expr = Method.IsStaticConstructor && TypeUtils.IsSameType(Method.DeclaringType, field.DeclaringType)
                 ? TypeUtils.EscapeIdentifier(field.Name)
                 : "::natsu::static_holder<typename" + TypeUtils.EscapeTypeName(field.DeclaringType) + "::Static>::get()." + TypeUtils.EscapeIdentifier(field.Name);
             Stack.Push(StackTypeCode.Ref, $"::natsu::ops::ref({expr})");
@@ -1205,7 +1205,7 @@ namespace Natsu.Compiler
                 ;
             var value = Stack.Pop();
             var field = (IField)Op.Operand;
-            string expr = Method.IsStaticConstructor && Method.DeclaringType == field.DeclaringType.ScopeType
+            string expr = Method.IsStaticConstructor && TypeUtils.IsSameType(Method.DeclaringType, field.DeclaringType)
                 ? TypeUtils.EscapeIdentifier(field.Name)
                 : "::natsu::static_holder<typename" + TypeUtils.EscapeTypeName(field.DeclaringType) + "::Static>::get()." + TypeUtils.EscapeIdentifier(field.Name);
             var fieldType = field.FieldSig.Type;

+ 1 - 1
src/Natsu.Compiler/Program.cs

@@ -22,7 +22,7 @@ namespace Natsu.Compiler
             //@"..\..\..\..\..\out\bin\netcoreapp3.0\System.Collections.dll",
             //@"..\..\..\..\..\out\bin\netcoreapp3.0\System.Memory.dll",
             //@"..\..\..\..\..\out\bin\netcoreapp3.0\System.Runtime.dll",
-            //@"..\..\..\..\..\out\bin\netcoreapp3.0\System.Runtime.Extensions.dll",
+            @"..\..\..\..\..\out\bin\netcoreapp3.0\System.Runtime.Extensions.dll",
             //@"..\..\..\..\..\out\bin\netcoreapp3.0\System.Diagnostics.Debug.dll",
             //@"..\..\..\..\..\out\bin\netcoreapp3.0\System.Runtime.InteropServices.dll",
             //@"..\..\..\..\..\out\bin\netcoreapp3.0\System.Threading.dll",

+ 5 - 0
src/Natsu.Compiler/TypeUtils.cs

@@ -852,5 +852,10 @@ namespace Natsu.Compiler
 
             return sb.ToString();
         }
+
+        public static bool IsSameType(ITypeDefOrRef type1, ITypeDefOrRef type2)
+        {
+            return type1 == type2 || type1 == type2.Scope;
+        }
     }
 }

+ 17 - 0
src/System.Runtime.Extensions/System/Diagnostics/Stopwatch.NatsuCLR.cs

@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.CompilerServices;
+
+namespace System.Diagnostics
+{
+    public partial class Stopwatch
+    {
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern long QueryPerformanceFrequency();
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern long QueryPerformanceCounter();
+    }
+}

+ 149 - 0
src/System.Runtime.Extensions/System/Diagnostics/Stopwatch.cs

@@ -0,0 +1,149 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics
+{
+    // This class uses high-resolution performance counter if the installed
+    // hardware supports it. Otherwise, the class will fall back to DateTime
+    // and uses ticks as a measurement.
+
+    public partial class Stopwatch
+    {
+        private const long TicksPerMillisecond = 10000;
+        private const long TicksPerSecond = TicksPerMillisecond * 1000;
+
+        private long _elapsed;
+        private long _startTimeStamp;
+        private bool _isRunning;
+
+        // "Frequency" stores the frequency of the high-resolution performance counter, 
+        // if one exists. Otherwise it will store TicksPerSecond. 
+        // The frequency cannot change while the system is running,
+        // so we only need to initialize it once. 
+        public static readonly long Frequency;
+        public static readonly bool IsHighResolution;
+
+        // performance-counter frequency, in counts per ticks.
+        // This can speed up conversion from high frequency performance-counter 
+        // to ticks. 
+        private static readonly double s_tickFrequency;
+
+        static Stopwatch()
+        {
+            Frequency = QueryPerformanceFrequency();
+            IsHighResolution = true;
+            s_tickFrequency = (double)TicksPerSecond / Frequency;
+        }
+
+        public Stopwatch()
+        {
+            Reset();
+        }
+
+        public void Start()
+        {
+            // Calling start on a running Stopwatch is a no-op.
+            if (!_isRunning)
+            {
+                _startTimeStamp = GetTimestamp();
+                _isRunning = true;
+            }
+        }
+
+        public static Stopwatch StartNew()
+        {
+            Stopwatch s = new Stopwatch();
+            s.Start();
+            return s;
+        }
+
+        public void Stop()
+        {
+            // Calling stop on a stopped Stopwatch is a no-op.
+            if (_isRunning)
+            {
+                long endTimeStamp = GetTimestamp();
+                long elapsedThisPeriod = endTimeStamp - _startTimeStamp;
+                _elapsed += elapsedThisPeriod;
+                _isRunning = false;
+
+                if (_elapsed < 0)
+                {
+                    // When measuring small time periods the Stopwatch.Elapsed* 
+                    // properties can return negative values.  This is due to 
+                    // bugs in the basic input/output system (BIOS) or the hardware
+                    // abstraction layer (HAL) on machines with variable-speed CPUs
+                    // (e.g. Intel SpeedStep).
+
+                    _elapsed = 0;
+                }
+            }
+        }
+
+        public void Reset()
+        {
+            _elapsed = 0;
+            _isRunning = false;
+            _startTimeStamp = 0;
+        }
+
+        // Convenience method for replacing {sw.Reset(); sw.Start();} with a single sw.Restart()
+        public void Restart()
+        {
+            _elapsed = 0;
+            _startTimeStamp = GetTimestamp();
+            _isRunning = true;
+        }
+
+        public bool IsRunning
+        {
+            get { return _isRunning; }
+        }
+
+        public TimeSpan Elapsed
+        {
+            get { return new TimeSpan(GetElapsedDateTimeTicks()); }
+        }
+
+        public long ElapsedMilliseconds
+        {
+            get { return GetElapsedDateTimeTicks() / TicksPerMillisecond; }
+        }
+
+        public long ElapsedTicks
+        {
+            get { return GetRawElapsedTicks(); }
+        }
+
+        public static long GetTimestamp()
+        {
+            Debug.Assert(IsHighResolution);
+            return QueryPerformanceCounter();
+        }
+
+        // Get the elapsed ticks.        
+        private long GetRawElapsedTicks()
+        {
+            long timeElapsed = _elapsed;
+
+            if (_isRunning)
+            {
+                // If the Stopwatch is running, add elapsed time since
+                // the Stopwatch is started last time. 
+                long currentTimeStamp = GetTimestamp();
+                long elapsedUntilNow = currentTimeStamp - _startTimeStamp;
+                timeElapsed += elapsedUntilNow;
+            }
+            return timeElapsed;
+        }
+
+        // Get the elapsed ticks.        
+        private long GetElapsedDateTimeTicks()
+        {
+            Debug.Assert(IsHighResolution);
+            // convert high resolution perf counter to DateTime ticks
+            return unchecked((long)(GetRawElapsedTicks() * s_tickFrequency));
+        }
+    }
+}