sunnycase 6 years ago
parent
commit
c0127bc25c

+ 1 - 0
CMakeLists.txt

@@ -22,6 +22,7 @@ set(CMAKE_CXX_STANDARD 17)
 
 if (MSVC)
     add_definitions(/D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS /DNOMINMAX /DUNICODE)
+    add_compile_options(/wd4102)
 else()
     add_compile_options(-Wno-multichar)
 endif()

+ 11 - 0
src/Chino.Chip.Emulator/HAL/IO/Console.cs

@@ -3,6 +3,7 @@ using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
 
 namespace Chino.Chip.Emulator.HAL.IO
 {
@@ -15,6 +16,16 @@ namespace Chino.Chip.Emulator.HAL.IO
             InstallConsoleReadThread();
         }
 
+        private void OnReceive(ConsoleEvent e)
+        {
+            EventsBuffer.TryWrite(MemoryMarshal.CreateReadOnlySpan(ref e, 1));
+            if(e.Type== ConsoleEventType.KeyEvent)
+            {
+                if (e.Key.KeyDown)
+                    ChipControl.Write(e.Key.Char.ToString());
+            }
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private extern void InstallConsoleReadThread();
     }

+ 1 - 1
src/Native/arch/emulator/crt.cpp

@@ -10,7 +10,7 @@ void ChipControl::_s_Initialize()
     system(" ");
 
     auto dev = make_object<Chip::Emulator::HAL::IO::Console>();
-    Chip::Emulator::HAL::IO::Console::Install_(dev);
+    Chip::Emulator::HAL::IO::Console::Install(dev);
 }
 
 void ChipControl::_s_Write(gc_obj_ref<String> message)

+ 6 - 3
src/Native/arch/emulator/hal/io/console.cpp

@@ -30,11 +30,14 @@ void ConsoleReadThread(void *arg)
         {
             auto &record = input_records[i];
             cio::ConsoleEvent cevent;
+
             switch (record.EventType)
             {
             case KEY_EVENT:
-                if (record.Event.KeyEvent.bKeyDown)
-                    putchar(record.Event.KeyEvent.uChar.UnicodeChar);
+                cevent._Type_k__BackingField = cio::ConsoleEventType::KeyEvent;
+                cevent._Key_k__BackingField._KeyDown_k__BackingField = record.Event.KeyEvent.bKeyDown;
+                cevent._Key_k__BackingField._Char_k__BackingField = record.Event.KeyEvent.uChar.UnicodeChar;
+                this_->OnReceive(this_, cevent);
                 break;
             default:
                 break;
@@ -44,7 +47,7 @@ void ConsoleReadThread(void *arg)
 }
 }
 
-void Console::InstallConsoleReadThread_(::natsu::gc_obj_ref<::Chino_Chip_Emulator::Chino::Chip::Emulator::HAL::IO::Console> _this)
+void Console::InstallConsoleReadThread(::natsu::gc_obj_ref<::Chino_Chip_Emulator::Chino::Chip::Emulator::HAL::IO::Console> _this)
 {
     auto thread = _beginthread(ConsoleReadThread, 0, _this.ptr_);
     assert(thread);

+ 10 - 10
src/Native/natsu.fcall.cpp

@@ -8,34 +8,34 @@ using namespace System_Private_CorLib::System;
 using namespace System_Private_CorLib::System::Diagnostics;
 using namespace System_Private_CorLib::System::Runtime::CompilerServices;
 
-Int32 Array::GetLength_System__Int32(gc_obj_ref<Array> _this, Int32 dimension)
+Int32 Array::GetLength(gc_obj_ref<Array> _this, Int32 dimension)
 {
     if (dimension != 0)
         throw_exception<IndexOutOfRangeException>();
     return (intptr_t)_this.cast<RawSzArrayData>()->Count;
 }
 
-Int32 Array::get_Rank_(gc_obj_ref<Array> _this)
+Int32 Array::get_Rank(gc_obj_ref<Array> _this)
 {
     return 1;
 }
 
-Int32 Array::get_Length_(gc_obj_ref<Array> _this)
+Int32 Array::get_Length(gc_obj_ref<Array> _this)
 {
     return (intptr_t)_this.cast<RawSzArrayData>()->Count;
 }
 
-Int64 Array::get_LongLength_(gc_obj_ref<Array> _this)
+Int64 Array::get_LongLength(gc_obj_ref<Array> _this)
 {
     return (intptr_t)_this.cast<RawSzArrayData>()->Count;
 }
 
-Int32 Array::GetUpperBound_System__Int32(gc_obj_ref<Array> _this, Int32 dimension)
+Int32 Array::GetUpperBound(gc_obj_ref<Array> _this, Int32 dimension)
 {
-    return GetLength_System__Int32(_this, dimension);
+    return GetLength(_this, dimension);
 }
 
-Int32 Array::GetLowerBound_System__Int32(gc_obj_ref<Array> _this, Int32 dimension)
+Int32 Array::GetLowerBound(gc_obj_ref<Array> _this, Int32 dimension)
 {
     if (dimension != 0)
         throw_exception<IndexOutOfRangeException>();
@@ -73,20 +73,20 @@ void Buffer::_s_Memmove(gc_ptr<Byte> dest, gc_ptr<Byte> src, UInt64 len)
     std::memmove(dest, src, len);
 }
 
-gc_obj_ref<Type> Object::GetType_(::natsu::gc_obj_ref<Object> _this)
+gc_obj_ref<Type> Object::GetType(::natsu::gc_obj_ref<Object> _this)
 {
     check_null_obj_ref(_this);
     return ::natsu::null;
 }
 
-Char String::get_Chars_System__Int32(gc_obj_ref<String> _this, Int32 index)
+Char String::get_Chars(gc_obj_ref<String> _this, Int32 index)
 {
     if ((uint32_t)index >= (uint32_t)_this->_stringLength)
         throw_exception<IndexOutOfRangeException>();
     return (&_this->_firstChar)[index];
 }
 
-Int32 String::get_Length_(gc_obj_ref<String> _this)
+Int32 String::get_Length(gc_obj_ref<String> _this)
 {
     return _this->_stringLength;
 }

+ 116 - 1
src/Native/natsu.runtime.h

@@ -147,6 +147,21 @@ auto make_object(TArgs... args)
     }
 }
 
+template <class T>
+auto make_object_uninit()
+{
+    if constexpr (is_value_type_v<T>)
+    {
+        T value;
+        return value;
+    }
+    else
+    {
+        auto value = gc_new<T>();
+        return value;
+    }
+}
+
 template <class T>
 natsu_exception make_exception(gc_obj_ref<T> exception)
 {
@@ -1356,8 +1371,108 @@ void System::ByReference_1<T>::_ctor(::natsu::gc_ref<System::ByReference_1<T>> _
 }
 
 template <class T>
-::natsu::gc_ref<::natsu::variable_type_t<T>> System::ByReference_1<T>::get_Value_(::natsu::gc_ref<System::ByReference_1<T>> _this)
+::natsu::gc_ref<::natsu::variable_type_t<T>> System::ByReference_1<T>::get_Value(::natsu::gc_ref<System::ByReference_1<T>> _this)
 {
     return ::natsu::gc_ref_from_ref(*reinterpret_cast<::natsu::variable_type_t<T> *>(static_cast<intptr_t>(_this->_value)));
 }
+
+template <class T>
+::natsu::gc_ptr<void> Internal::Runtime::CompilerServices::Unsafe::_s_AsPointer(::natsu::gc_ref<::natsu::variable_type_t<T>> value)
+{
+    return ::natsu::gc_ptr<void>(value.ptr_);
+}
+
+template <class T>
+::System_Private_CorLib::System::Int32 Internal::Runtime::CompilerServices::Unsafe::_s_SizeOf()
+{
+    return sizeof(T);
+}
+
+template <class T>
+::natsu::variable_type_t<T> Internal::Runtime::CompilerServices::Unsafe::_s_As(::natsu::gc_obj_ref<::System_Private_CorLib::System::Object> value)
+{
+    return ::natsu::gc_obj_ref<T>(reinterpret_cast<T *>(value.ptr_));
+}
+
+template <class TFrom, class TTo>
+::natsu::gc_ref<::natsu::variable_type_t<TTo>> Internal::Runtime::CompilerServices::Unsafe::_s_As(::natsu::gc_ref<::natsu::variable_type_t<TFrom>> source)
+{
+    return ::natsu::gc_ref_from_ref(*reinterpret_cast<::natsu::variable_type_t<TTo> *>(source.ptr_));
+}
+
+template <class T>
+::System_Private_CorLib::System::Boolean Internal::Runtime::CompilerServices::Unsafe::_s_AreSame(::natsu::gc_ref<::natsu::variable_type_t<T>> left, ::natsu::gc_ref<::natsu::variable_type_t<T>> right)
+{
+    return left.ptr_ == right.ptr_;
+}
+
+template <class T>
+::System_Private_CorLib::System::Boolean Internal::Runtime::CompilerServices::Unsafe::_s_IsAddressGreaterThan(::natsu::gc_ref<::natsu::variable_type_t<T>> left, ::natsu::gc_ref<::natsu::variable_type_t<T>> right)
+{
+    return left.ptr_ > right.ptr_;
+}
+
+template <class T>
+::System_Private_CorLib::System::Boolean Internal::Runtime::CompilerServices::Unsafe::_s_IsAddressLessThan(::natsu::gc_ref<::natsu::variable_type_t<T>> left, ::natsu::gc_ref<::natsu::variable_type_t<T>> right)
+{
+    return left.ptr_ < right.ptr_;
+}
+
+template <class T>
+::natsu::variable_type_t<T> Internal::Runtime::CompilerServices::Unsafe::_s_ReadUnaligned(::natsu::gc_ptr<void> source)
+{
+    auto obj = natsu::make_object_uninit<T>();
+    if constexpr (natsu::is_value_type_v<T>)
+        std::memcpy(&obj, source.ptr_, sizeof(T));
+    else
+        std::memcpy(obj.ptr_, source.ptr_, sizeof(T));
+    return obj;
+}
+
+template <class T>
+::natsu::variable_type_t<T> Internal::Runtime::CompilerServices::Unsafe::_s_ReadUnaligned(::natsu::gc_ref<::System_Private_CorLib::System::Byte> source)
+{
+    auto obj = natsu::make_object_uninit<T>();
+    if constexpr (natsu::is_value_type_v<T>)
+        std::memcpy(&obj, source.ptr_, sizeof(T));
+    else
+        std::memcpy(obj.ptr_, source.ptr_, sizeof(T));
+    return obj;
+}
+
+template <class T>
+void Internal::Runtime::CompilerServices::Unsafe::_s_WriteUnaligned(::natsu::gc_ptr<void> destination, ::natsu::variable_type_t<T> value)
+{
+    if constexpr (natsu::is_value_type_v<T>)
+        std::memcpy(destination.ptr_, &value, sizeof(T));
+    else
+        std::memcpy(destination.ptr_, value.ptr_, sizeof(T));
+}
+
+template <class T>
+void Internal::Runtime::CompilerServices::Unsafe::_s_WriteUnaligned(::natsu::gc_ref<::System_Private_CorLib::System::Byte> destination, ::natsu::variable_type_t<T> value)
+{
+    if constexpr (natsu::is_value_type_v<T>)
+        std::memcpy(destination.ptr_, &value, sizeof(T));
+    else
+        std::memcpy(destination.ptr_, value.ptr_, sizeof(T));
+}
+
+template <class T>
+::natsu::gc_ref<::natsu::variable_type_t<T>> Internal::Runtime::CompilerServices::Unsafe::_s_AddByteOffset(::natsu::gc_ref<::natsu::variable_type_t<T>> source, ::System_Private_CorLib::System::IntPtr byteOffset)
+{
+    return ::natsu::gc_ref<::natsu::variable_type_t<T>>(reinterpret_cast<uintptr_t>(source.ptr_) + reinterpret_cast<intptr_t>(byteOffset._value.ptr_));
+}
+
+template <class T>
+::natsu::gc_ref<::natsu::variable_type_t<T>> Internal::Runtime::CompilerServices::Unsafe::_s_AsRef(::natsu::gc_ref<::natsu::variable_type_t<T>> source)
+{
+    return source;
+}
+
+template <class T>
+::System_Private_CorLib::System::IntPtr Internal::Runtime::CompilerServices::Unsafe::_s_ByteOffset(::natsu::gc_ref<::natsu::variable_type_t<T>> origin, ::natsu::gc_ref<::natsu::variable_type_t<T>> target)
+{
+    return reinterpret_cast<intptr_t>(target.ptr_) - reinterpret_cast<intptr_t>(origin.ptr_);
+}
 }

+ 21 - 4
src/Native/natsu.typedef.h

@@ -94,7 +94,7 @@ struct static_holder
 template <class T>
 struct vtable_holder
 {
-    static const T value;
+    static const constexpr T value = T();
 
     static constexpr const T &get()
     {
@@ -102,12 +102,14 @@ struct vtable_holder
     }
 };
 
-template <class T>
-const T vtable_holder<T>::value;
-
 typedef struct _vtable
 {
     virtual void dummy() const noexcept {}
+
+    template <class TFunc>
+    constexpr void override_vfunc_impl(std::string_view name, TFunc func)
+    {
+    }
 } vtable_t;
 
 enum object_attributes
@@ -482,11 +484,20 @@ struct vtable_impl;
 template <class TBase, class TIFace>
 struct vtable_impl<TBase, TIFace, true>
 {
+    template <class TFunc>
+    constexpr void override_vfunc_impl(std::string_view name, TFunc func)
+    {
+    }
 };
 
 template <class TBase, class TIFace>
 struct vtable_impl<TBase, TIFace, false> : public TIFace
 {
+    template <class TFunc>
+    constexpr void override_vfunc_impl(std::string_view name, TFunc func)
+    {
+        TIFace::override_vfunc_impl(name, func);
+    }
 };
 
 template <class TBase, class TIFace>
@@ -495,6 +506,12 @@ using vtable_impl_t = vtable_impl<TBase, TIFace, std::is_base_of_v<TIFace, TBase
 template <class TBase, class... TIFaces>
 struct vtable_class : public TBase, public vtable_impl_t<TBase, TIFaces>...
 {
+    template <class TFunc>
+    constexpr void override_vfunc(std::string_view name, TFunc func)
+    {
+        TBase::override_vfunc_impl(name, func);
+        int ignore[] = { 0, (vtable_impl_t<TBase, TIFaces>::override_vfunc_impl(name, func), 0)... };
+    }
 };
 }
 

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

@@ -884,11 +884,11 @@ namespace Natsu.Compiler
             {
                 var genArgs = gen.GenericArguments;
                 tGen.AddRange(genArgs);
-                expr = $"{TypeUtils.EscapeTypeName(member.DeclaringType)}::{TypeUtils.EscapeMethodName(member)}<{string.Join(", ", gen.GenericArguments.Select(x => TypeUtils.EscapeTypeName(x)))}>({string.Join(", ", para.Select((x, i) => CastExpression(x.destType, x.src, genArgs)))})";
+                expr = $"{TypeUtils.EscapeTypeName(member.DeclaringType)}::{TypeUtils.EscapeMethodName(member, hasParamType: false)}<{string.Join(", ", gen.GenericArguments.Select(x => TypeUtils.EscapeTypeName(x)))}>({string.Join(", ", para.Select((x, i) => CastExpression(x.destType, x.src, genArgs)))})";
             }
             else
             {
-                expr = $"{ TypeUtils.EscapeTypeName(member.DeclaringType)}::{TypeUtils.EscapeMethodName(member)}({string.Join(", ", para.Select(x => CastExpression(x.destType, x.src, tGen)))})";
+                expr = $"{ TypeUtils.EscapeTypeName(member.DeclaringType)}::{TypeUtils.EscapeMethodName(member, hasParamType: false)}({string.Join(", ", para.Select(x => CastExpression(x.destType, x.src, tGen)))})";
             }
 
             var stackType = TypeUtils.GetStackType(method.RetType);

+ 51 - 25
src/Natsu.Compiler/Program.cs

@@ -16,23 +16,24 @@ namespace Natsu.Compiler
         {
             @"..\..\..\..\..\out\bin\netcoreapp3.0\Chino.Kernel.dll",
             @"..\..\..\..\..\out\bin\netcoreapp3.0\Chino.Core.dll",
-            @"..\..\..\..\..\out\bin\netcoreapp3.0\Chino.Chip.K210.dll",
+            //@"..\..\..\..\..\out\bin\netcoreapp3.0\Chino.Chip.K210.dll",
             @"..\..\..\..\..\out\bin\netcoreapp3.0\Chino.Chip.Emulator.dll",
             @"..\..\..\..\..\out\bin\netcoreapp3.0\System.Private.CorLib.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.Diagnostics.Debug.dll",
-            @"..\..\..\..\..\out\bin\netcoreapp3.0\System.Runtime.InteropServices.dll",
-            @"..\..\..\..\..\out\bin\netcoreapp3.0\System.Threading.dll",
-            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), @".nuget\packages\bitfields\0.1.0\lib\netstandard1.0\BitFields.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.Diagnostics.Debug.dll",
+            //@"..\..\..\..\..\out\bin\netcoreapp3.0\System.Runtime.InteropServices.dll",
+            //@"..\..\..\..\..\out\bin\netcoreapp3.0\System.Threading.dll",
+            //Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), @".nuget\packages\bitfields\0.1.0\lib\netstandard1.0\BitFields.dll")
         };
 
         static void Main(string[] args)
         {
+            var ctx = ModuleDef.CreateModuleContext();
             foreach (var path in _modulePaths)
             {
-                var module = ModuleDefMD.Load(path);
+                var module = ModuleDefMD.Load(path, ctx);
                 var generator = new Generator(module);
                 generator.Generate();
             }
@@ -569,6 +570,9 @@ namespace Natsu.Compiler
             WriteVTableCtor(writer, type, ident + 1);
             writer.WriteLine();
 
+            WriteVTableOverrideImpl(writer, type, ident + 1);
+            writer.WriteLine();
+
             foreach (var method in type.TypeDef.Methods)
             {
                 if (!method.IsInstanceConstructor && !method.IsStatic)
@@ -653,7 +657,7 @@ namespace Natsu.Compiler
                 writer.Ident(ident).Write("static " + TypeUtils.EscapeVariableTypeName(method.ReturnType) + " ");
             else
                 writer.Ident(ident);
-            writer.Write(TypeUtils.EscapeMethodName(method, hasExplicit: true) + "(");
+            writer.Write(TypeUtils.EscapeMethodName(method, hasParamType: false, hasExplicit: true) + "(");
             WriteParameterList(writer, method.Parameters);
             writer.WriteLine($");");
         }
@@ -753,7 +757,7 @@ namespace Natsu.Compiler
             writer.Write(TypeUtils.EscapeTypeName(method.DeclaringType, hasModuleName: false));
             if (method.IsStaticConstructor)
                 writer.Write("::Static");
-            writer.Write("::" + TypeUtils.EscapeMethodName(method, hasExplicit: true) + "(");
+            writer.Write("::" + TypeUtils.EscapeMethodName(method, hasParamType: false, hasExplicit: true) + "(");
             WriteParameterList(writer, method.Parameters);
             writer.WriteLine(")");
             writer.Ident(ident).WriteLine("{");
@@ -805,20 +809,20 @@ namespace Natsu.Compiler
                     {
                         if (method.Name.Contains("."))
                         {
-                            var explict = method.Name.String;
-                            explict = explict.Substring(0, explict.LastIndexOf('.'));
-                            explict = explict.Replace(".", "::");
-                            writer.Ident(ident + 1).Write(explict);
-                            writer.Write("::VTable::");
-                            writer.Write(TypeUtils.EscapeMethodName(method));
-                            writer.Write(" = ");
-                            writer.WriteLine("_imp_" + TypeUtils.EscapeMethodName(method, hasExplicit: true) + ";");
+                            foreach (var ov in method.Overrides)
+                            {
+                                writer.Ident(ident + 1).Write(TypeUtils.EscapeTypeName(ov.MethodDeclaration.DeclaringType));
+                                writer.Write("::VTable::");
+                                writer.Write(TypeUtils.EscapeMethodName(ov.MethodDeclaration));
+                                writer.Write(" = ");
+                                writer.WriteLine("_imp_" + TypeUtils.EscapeMethodName(method, hasExplicit: true) + ";");
+                            }
                         }
                         else if (!method.IsNewSlot)
                         {
-                            writer.Ident(ident + 1).Write(TypeUtils.EscapeMethodName(method));
-                            writer.Write(" = ");
-                            writer.WriteLine("_imp_" + TypeUtils.EscapeMethodName(method) + ";");
+                            writer.Ident(ident + 1).Write("override_vfunc");
+                            writer.Write("(R\"NS(" + method.Name + ")NS\", ");
+                            writer.WriteLine("_imp_" + TypeUtils.EscapeMethodName(method) + ");");
                         }
                     }
                 }
@@ -827,6 +831,28 @@ namespace Natsu.Compiler
             writer.Ident(ident).WriteLine("}");
         }
 
+        private void WriteVTableOverrideImpl(StreamWriter writer, TypeDesc type, int ident)
+        {
+            writer.Ident(ident).WriteLine("template <class TFunc>");
+            writer.Ident(ident).WriteLine("constexpr void override_vfunc_impl(std::string_view name, TFunc func)");
+            writer.Ident(ident).WriteLine("{");
+
+            foreach (var method in type.TypeDef.Methods)
+            {
+                if (!method.IsInstanceConstructor && !method.IsStatic)
+                {
+                    if (method.IsVirtual && method.IsNewSlot && !method.Name.Contains("."))
+                    {
+                        writer.Ident(ident + 1).WriteLine($@"if (name == ""{method.Name}""sv)");
+                        writer.Ident(ident + 2).WriteLine($@"if constexpr (std::is_same_v<TFunc, decltype({TypeUtils.EscapeMethodName(method)})>)");
+                        writer.Ident(ident + 3).WriteLine(TypeUtils.EscapeMethodName(method) + " = func;");
+                    }
+                }
+            }
+
+            writer.Ident(ident).WriteLine("}");
+        }
+
         private void WriteVTableMethodDeclare(TextWriter writer, int ident, MethodDef method)
         {
             var methodGens = new List<string>();
@@ -862,7 +888,7 @@ namespace Natsu.Compiler
             else
             {
                 writer.Ident(ident).Write(TypeUtils.EscapeVariableTypeName(method.ReturnType) + " ");
-                writer.Write(TypeUtils.EscapeMethodName(method) + "(");
+                writer.Write(TypeUtils.EscapeMethodName(method, hasParamType: true) + "(");
                 WriteParameterList(writer, method.Parameters, isVTable: true);
                 writer.WriteLine(") const;");
             }
@@ -891,7 +917,7 @@ namespace Natsu.Compiler
             writer.Write("::VTable::");
             if (method.IsVirtual)
                 writer.Write("_imp_");
-            writer.Write(TypeUtils.EscapeMethodName(method, hasExplicit: true) + "(");
+            writer.Write(TypeUtils.EscapeMethodName(method, hasParamType: true, hasExplicit: true) + "(");
             WriteParameterList(writer, method.Parameters, isVTable: true);
             if (method.IsVirtual)
                 writer.WriteLine(")");
@@ -906,7 +932,7 @@ namespace Natsu.Compiler
             {
                 writer.Ident(ident + 1).Write("return ");
                 writer.Write(TypeUtils.EscapeTypeName(method.DeclaringType));
-                writer.Write("::" + TypeUtils.EscapeMethodName(method, hasExplicit: true) + "(");
+                writer.Write("::" + TypeUtils.EscapeMethodName(method, hasParamType: false, hasExplicit: true) + "(");
                 WriteParameterList(writer, method.Parameters, hasType: false, isVTable: true);
                 writer.WriteLine(");");
             }

+ 92 - 16
src/Natsu.Compiler/TypeUtils.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Text;
@@ -114,7 +115,8 @@ namespace Natsu.Compiler
 
         public static TypeSig ThisType(ITypeDefOrRef type)
         {
-            if (type.IsValueType)
+            var typeDef = type.ResolveTypeDef();
+            if (typeDef?.IsValueType ?? false || type.IsValueType)
                 return new ByRefSig(type.ToTypeSig());
             return type.ToTypeSig();
         }
@@ -314,7 +316,20 @@ namespace Natsu.Compiler
             return name.Replace('.', '_');
         }
 
-        public static string EscapeMethodName(IMethod method, bool hasExplicit = false)
+        public static string EscapeMethodParamsType(IMethod method)
+        {
+            var sb = new StringBuilder();
+            for (int i = 0; i < method.MethodSig.Params.Count; i++)
+            {
+                sb.Append(EscapeVariableTypeName(method.MethodSig.Params[i]));
+                if (i != method.MethodSig.Params.Count - 1)
+                    sb.Append(", ");
+            }
+
+            return sb.ToString();
+        }
+
+        public static string EscapeMethodName(IMethod method, bool hasParamType = true, bool hasExplicit = false)
         {
             if (method.Name == ".ctor")
                 return "_ctor";
@@ -325,25 +340,20 @@ namespace Natsu.Compiler
                     sb.Append(EscapeIdentifier(method.Name.String));
                 else
                     sb.Append(EscapeIdentifier(method.Name.String.Split('.').Last()));
-                sb.Append("_");
 
-                for (int i = 0; i < method.MethodSig.Params.Count; i++)
+                if (hasParamType)
                 {
-                    EscapeMethodTypeName(sb, method.MethodSig.Params[i]);
-                    if (i != method.MethodSig.Params.Count - 1)
-                        sb.Append("_");
+                    sb.Append("_");
+
+                    for (int i = 0; i < method.MethodSig.Params.Count; i++)
+                    {
+                        EscapeMethodTypeName(sb, method.MethodSig.Params[i]);
+                        if (i != method.MethodSig.Params.Count - 1)
+                            sb.Append("_");
+                    }
                 }
 
                 var name = EscapeIdentifier(sb.ToString());
-                if (name == "get_Current_" && method.MethodSig.RetType.ElementType == ElementType.Object)
-                    return "get_Current_O";
-                if (name == "GetEnumerator_")
-                {
-                    if (method.MethodSig.RetType.FullName.Contains("System.Collections.IEnumerator"))
-                        return "GetEnumerator_O";
-                    if (method.MethodSig.RetType.FullName.Contains("System.Collections.Generic.IEnumerator"))
-                        return "GetEnumerator_G";
-                }
 
                 return name;
             }
@@ -614,5 +624,71 @@ namespace Natsu.Compiler
                     return stackType.Name;
             }
         }
+
+        public static string EscapeCSharpTypeName(string name)
+        {
+            return EscapeCSharpTypeNameCore(new StringReader(name));
+        }
+
+        private static string EscapeCSharpTypeNameCore(TextReader name)
+        {
+            var sb = new StringBuilder();
+            var genSb = new StringBuilder();
+            int count = 0;
+            while (name.Peek() != -1)
+            {
+                var c = (char)name.Peek();
+                if (c == '.')
+                {
+                    name.Read();
+                    sb.Append("::");
+                }
+                else if (c == '<')
+                {
+                    name.Read();
+                    count = 1;
+                    sb.Append("_");
+                    var nest = EscapeCSharpTypeNameCore(name);
+                    genSb.Append('<');
+                    genSb.Append(nest);
+                }
+                else if (c == ',')
+                {
+                    name.Read();
+                    if (count != 0)
+                    {
+                        count++;
+                        var nest = EscapeCSharpTypeNameCore(name);
+                        genSb.Append(", ");
+                        genSb.Append(nest);
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+                else if (c == '>')
+                {
+                    if (count != 0)
+                    {
+                        name.Read();
+                        sb.Append(count);
+                        sb.Append(genSb);
+                        sb.Append('>');
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+                else
+                {
+                    name.Read();
+                    sb.Append(c);
+                }
+            }
+
+            return sb.ToString();
+        }
     }
 }

+ 1 - 0
src/System.Memory/TypeForwards.cs

@@ -3,3 +3,4 @@ using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
 [assembly: TypeForwardedTo(typeof(MemoryExtensions))]
+[assembly: TypeForwardedTo(typeof(MemoryMarshal))]

+ 27 - 118
src/System.Private.CorLib/Internal/System/Runtime/CompilerServices/Unsafe.cs

@@ -38,60 +38,32 @@ namespace Internal.Runtime.CompilerServices
         /// </summary>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void* AsPointer<T>(ref T value)
-        {
-            throw new PlatformNotSupportedException();
-
-            // ldarg.0
-            // conv.u
-            // ret
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern void* AsPointer<T>(ref T value);
 
         /// <summary>
         /// Returns the size of an object of the given type parameter.
         /// </summary>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static int SizeOf<T>()
-        {
-#if CORECLR
-            typeof(T).ToString(); // Type token used by the actual method body
-#endif
-            throw new PlatformNotSupportedException();
-
-            // sizeof !!0
-            // ret
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern int SizeOf<T>();
 
         /// <summary>
         /// Casts the given object to the specified type, performs no dynamic type checking.
         /// </summary>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static T As<T>(object value) where T : class
-        {
-            throw new PlatformNotSupportedException();
-
-            // ldarg.0
-            // ret
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern T As<T>(object value) where T : class;
 
         /// <summary>
         /// Reinterprets the given reference as a reference to a value of type <typeparamref name="TTo"/>.
         /// </summary>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static ref TTo As<TFrom, TTo>(ref TFrom source)
-        {
-            throw new PlatformNotSupportedException();
-
-            // ldarg.0
-            // ret
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern ref TTo As<TFrom, TTo>(ref TFrom source);
 
         /// <summary>
         /// Adds an element offset to the given reference.
@@ -157,7 +129,7 @@ namespace Internal.Runtime.CompilerServices
         /// </summary>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
         public static bool AreSame<T>(ref T left, ref T right)
         {
             throw new PlatformNotSupportedException();
@@ -177,16 +149,8 @@ namespace Internal.Runtime.CompilerServices
         /// </remarks>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static bool IsAddressGreaterThan<T>(ref T left, ref T right)
-        {
-            throw new PlatformNotSupportedException();
-
-            // ldarg.0
-            // ldarg.1
-            // cgt.un
-            // ret
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern bool IsAddressGreaterThan<T>(ref T left, ref T right);
 
         /// <summary>
         /// Determines whether the memory address referenced by <paramref name="left"/> is less than
@@ -197,16 +161,8 @@ namespace Internal.Runtime.CompilerServices
         /// </remarks>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static bool IsAddressLessThan<T>(ref T left, ref T right)
-        {
-            throw new PlatformNotSupportedException();
-
-            // ldarg.0
-            // ldarg.1
-            // clt.un
-            // ret
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern bool IsAddressLessThan<T>(ref T left, ref T right);
 
         /// <summary>
         /// Initializes a block of memory at the given location with a given initial value 
@@ -226,81 +182,40 @@ namespace Internal.Runtime.CompilerServices
         /// </summary>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static T ReadUnaligned<T>(void* source)
-        {
-#if CORECLR
-            typeof(T).ToString(); // Type token used by the actual method body
-            throw new PlatformNotSupportedException();
-#else
-            return Unsafe.As<byte, T>(ref *(byte*)source);
-#endif
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern T ReadUnaligned<T>(void* source);
 
         /// <summary>
         /// Reads a value of type <typeparamref name="T"/> from the given location.
         /// </summary>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static T ReadUnaligned<T>(ref byte source)
-        {
-#if CORECLR
-            typeof(T).ToString(); // Type token used by the actual method body
-            throw new PlatformNotSupportedException();
-#else
-            return Unsafe.As<byte, T>(ref source);
-#endif
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern T ReadUnaligned<T>(ref byte source);
 
         /// <summary>
         /// Writes a value of type <typeparamref name="T"/> to the given location.
         /// </summary>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void WriteUnaligned<T>(void* destination, T value)
-        {
-#if CORECLR
-            typeof(T).ToString(); // Type token used by the actual method body
-            throw new PlatformNotSupportedException();
-#else
-            Unsafe.As<byte, T>(ref *(byte*)destination) = value;
-#endif
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern void WriteUnaligned<T>(void* destination, T value);
 
         /// <summary>
         /// Writes a value of type <typeparamref name="T"/> to the given location.
         /// </summary>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void WriteUnaligned<T>(ref byte destination, T value)
-        {
-#if CORECLR
-            typeof(T).ToString(); // Type token used by the actual method body
-            throw new PlatformNotSupportedException();
-#else
-            Unsafe.As<byte, T>(ref destination) = value;
-#endif
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern void WriteUnaligned<T>(ref byte destination, T value);
 
         /// <summary>
         /// Adds an element offset to the given reference.
         /// </summary>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static ref T AddByteOffset<T>(ref T source, IntPtr byteOffset)
-        {
-            // This method is implemented by the toolchain
-            throw new PlatformNotSupportedException();
-
-            // ldarg.0
-            // ldarg.1
-            // add
-            // ret
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern ref T AddByteOffset<T>(ref T source, IntPtr byteOffset);
 
         /// <summary>
         /// Reads a value of type <typeparamref name="T"/> from the given location.
@@ -362,21 +277,15 @@ namespace Internal.Runtime.CompilerServices
         /// </summary>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static ref T AsRef<T>(in T source)
-        {
-            throw new PlatformNotSupportedException();
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern ref T AsRef<T>(in T source);
 
         /// <summary>
         /// Determines the byte offset from origin to target from the given references.
         /// </summary>
         [Intrinsic]
         [NonVersionable]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static IntPtr ByteOffset<T>(ref T origin, ref T target)
-        {
-            throw new PlatformNotSupportedException();
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.InternalCall)]
+        public static extern IntPtr ByteOffset<T>(ref T origin, ref T target);
     }
 }

+ 232 - 0
src/System.Private.CorLib/System/Threading/Volatile.cs

@@ -0,0 +1,232 @@
+// 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.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using System.Runtime.Versioning;
+using Internal.Runtime.CompilerServices;
+
+namespace System.Threading
+{
+    /// <summary>Methods for accessing memory with volatile semantics.</summary>
+    public static unsafe class Volatile
+    {
+        // The VM may replace these implementations with more efficient ones in some cases.
+        // In coreclr, for example, see getILIntrinsicImplementationForVolatile() in jitinterface.cpp.
+
+        #region Boolean
+        private struct VolatileBoolean { public volatile bool Value; }
+
+        [Intrinsic]
+        [NonVersionable]
+        public static bool Read(ref bool location) =>
+            Unsafe.As<bool, VolatileBoolean>(ref location).Value;
+
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref bool location, bool value) =>
+            Unsafe.As<bool, VolatileBoolean>(ref location).Value = value;
+        #endregion
+        
+        #region Byte
+        private struct VolatileByte { public volatile byte Value; }
+
+        [Intrinsic]
+        [NonVersionable]
+        public static byte Read(ref byte location) =>
+            Unsafe.As<byte, VolatileByte>(ref location).Value;
+
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref byte location, byte value) =>
+            Unsafe.As<byte, VolatileByte>(ref location).Value = value;
+        #endregion
+
+        #region Double
+        [Intrinsic]
+        [NonVersionable]
+        public static double Read(ref double location)
+        {
+            long result = Read(ref Unsafe.As<double, long>(ref location));
+            return *(double*)&result;
+        }
+
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref double location, double value) =>
+            Write(ref Unsafe.As<double, long>(ref location), *(long*)&value);
+        #endregion
+
+        #region Int16
+        private struct VolatileInt16 { public volatile short Value; }
+
+        [Intrinsic]
+        [NonVersionable]
+        public static short Read(ref short location) =>
+            Unsafe.As<short, VolatileInt16>(ref location).Value;
+
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref short location, short value) =>
+            Unsafe.As<short, VolatileInt16>(ref location).Value = value;
+        #endregion
+
+        #region Int32
+        private struct VolatileInt32 { public volatile int Value; }
+
+        [Intrinsic]
+        [NonVersionable]
+        public static int Read(ref int location) =>
+            Unsafe.As<int, VolatileInt32>(ref location).Value;
+
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref int location, int value) =>
+            Unsafe.As<int, VolatileInt32>(ref location).Value = value;
+        #endregion
+
+        #region Int64
+        [Intrinsic]
+        [NonVersionable]
+        public static long Read(ref long location) =>
+#if BIT64
+            (long)Unsafe.As<long, VolatileIntPtr>(ref location).Value;
+#else
+            // On 32-bit machines, we use Interlocked, since an ordinary volatile read would not be atomic.
+            Interlocked.CompareExchange(ref location, 0, 0);
+#endif
+
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref long location, long value) =>
+#if BIT64
+            Unsafe.As<long, VolatileIntPtr>(ref location).Value = (IntPtr)value;
+#else
+            // On 32-bit, we use Interlocked, since an ordinary volatile write would not be atomic.
+            Interlocked.Exchange(ref location, value);
+#endif
+        #endregion
+
+        #region IntPtr
+        private struct VolatileIntPtr { public volatile IntPtr Value; }
+
+        [Intrinsic]
+        [NonVersionable]
+        public static IntPtr Read(ref IntPtr location) =>
+            Unsafe.As<IntPtr, VolatileIntPtr>(ref location).Value;
+
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref IntPtr location, IntPtr value) =>
+            Unsafe.As<IntPtr, VolatileIntPtr>(ref location).Value = value;
+        #endregion
+
+        #region SByte
+        private struct VolatileSByte { public volatile sbyte Value; }
+
+        [CLSCompliant(false)]
+        [Intrinsic]
+        [NonVersionable]
+        public static sbyte Read(ref sbyte location) =>
+            Unsafe.As<sbyte, VolatileSByte>(ref location).Value;
+
+        [CLSCompliant(false)]
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref sbyte location, sbyte value) =>
+            Unsafe.As<sbyte, VolatileSByte>(ref location).Value = value;
+        #endregion
+
+        #region Single
+        private struct VolatileSingle { public volatile float Value; }
+
+        [Intrinsic]
+        [NonVersionable]
+        public static float Read(ref float location) =>
+            Unsafe.As<float, VolatileSingle>(ref location).Value;
+
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref float location, float value) =>
+            Unsafe.As<float, VolatileSingle>(ref location).Value = value;
+        #endregion
+
+        #region UInt16
+        private struct VolatileUInt16 { public volatile ushort Value; }
+
+        [CLSCompliant(false)]
+        [Intrinsic]
+        [NonVersionable]
+        public static ushort Read(ref ushort location) =>
+            Unsafe.As<ushort, VolatileUInt16>(ref location).Value;
+
+        [CLSCompliant(false)]
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref ushort location, ushort value) =>
+            Unsafe.As<ushort, VolatileUInt16>(ref location).Value = value;
+        #endregion
+
+        #region UInt32
+        private struct VolatileUInt32 { public volatile uint Value; }
+
+        [CLSCompliant(false)]
+        [Intrinsic]
+        [NonVersionable]
+        public static uint Read(ref uint location) =>
+            Unsafe.As<uint, VolatileUInt32>(ref location).Value;
+
+        [CLSCompliant(false)]
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref uint location, uint value) =>
+            Unsafe.As<uint, VolatileUInt32>(ref location).Value = value;
+        #endregion
+
+        #region UInt64
+        [CLSCompliant(false)]
+        [Intrinsic]
+        [NonVersionable]
+        public static ulong Read(ref ulong location) =>
+            (ulong)Read(ref Unsafe.As<ulong, long>(ref location));
+
+        [CLSCompliant(false)]
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref ulong location, ulong value) =>
+            Write(ref Unsafe.As<ulong, long>(ref location), (long)value);
+        #endregion
+
+        #region UIntPtr
+        private struct VolatileUIntPtr { public volatile UIntPtr Value; }
+
+        [CLSCompliant(false)]
+        [Intrinsic]
+        [NonVersionable]
+        public static UIntPtr Read(ref UIntPtr location) =>
+            Unsafe.As<UIntPtr, VolatileUIntPtr>(ref location).Value;
+
+        [CLSCompliant(false)]
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write(ref UIntPtr location, UIntPtr value) =>
+            Unsafe.As<UIntPtr, VolatileUIntPtr>(ref location).Value = value;
+        #endregion
+
+        #region T
+        private struct VolatileObject { public volatile object? Value; }
+
+        [Intrinsic]
+        [NonVersionable]
+        [return: NotNullIfNotNull("location")]
+        public static T Read<T>(ref T location) where T : class? =>
+            Unsafe.As<T>(Unsafe.As<T, VolatileObject>(ref location).Value);
+
+        [Intrinsic]
+        [NonVersionable]
+        public static void Write<T>([NotNullIfNotNull("value")] ref T location, T value) where T : class? =>
+            Unsafe.As<T, VolatileObject>(ref location).Value = value;
+        #endregion
+    }
+}

+ 2 - 1
src/System.Threading/TypeForwards.cs

@@ -2,4 +2,5 @@
 using System.Runtime.CompilerServices;
 using System.Threading;
 
-[assembly: TypeForwardedTo(typeof(Interlocked))]
+[assembly: TypeForwardedTo(typeof(Interlocked))]
+[assembly: TypeForwardedTo(typeof(Volatile))]