sunnycase 6 anni fa
parent
commit
8d25cca4b6

+ 2 - 2
src/Native/natsu.runtime.cpp

@@ -57,10 +57,10 @@ native_int ops::ldlen(const O &obj)
     return (intptr_t)stack_to<gc_obj_ref<RawSzArrayData>>(obj)->Count;
 }
 
-void ops::throw_(const stack::O &obj)
+void ops::throw_(gc_obj_ref<Exception> obj)
 {
     check_null_obj_ref(obj);
-    throw make_exception(stack_to<gc_obj_ref<Exception>>(obj));
+    throw make_exception(obj);
 }
 
 #ifndef _MSC_VER

+ 48 - 669
src/Native/natsu.runtime.h

@@ -120,7 +120,7 @@ gc_obj_ref<T> gc_new()
 }
 
 template <class T>
-gc_obj_ref<::System_Private_CoreLib::System::SZArray_1<T>> gc_new_array(stack::int32 length)
+gc_obj_ref<::System_Private_CoreLib::System::SZArray_1<T>> gc_new_array(int32_t length)
 {
     using obj_t = ::System_Private_CoreLib::System::SZArray_1<T>;
     auto size = sizeof(obj_t) + (size_t)length.value_ * sizeof(T);
@@ -246,12 +246,6 @@ clr_finally<TCall> make_finally(TCall &&call)
 {
     return { std::forward<TCall>(call) };
 }
-
-template <class TFrom>
-auto stack_from(const TFrom &value);
-
-template <class TTo, class TFrom>
-auto stack_to(TFrom &&value);
 }
 
 namespace natsu
@@ -471,37 +465,37 @@ namespace stack
         template <class T>
         struct box_impl
         {
-            O operator()(T value)
+            auto operator()(T value)
             {
                 auto box = gc_new<T>();
                 *box = value;
-                return stack_from(box);
+                return box;
             }
         };
 
         template <class T>
         struct box_impl<gc_obj_ref<T>>
         {
-            O operator()(const gc_obj_ref<T> &value) const noexcept
+            gc_obj_ref<T> operator()(const gc_obj_ref<T> &value) const noexcept
             {
-                return stack_from(value);
+                return value;
             }
         };
 
         template <class T>
         struct box_impl<::System_Private_CoreLib::System::Nullable_1<T>>
         {
-            O operator()(const ::System_Private_CoreLib::System::Nullable_1<T> &value) const noexcept
+            auto operator()(const ::System_Private_CoreLib::System::Nullable_1<T> &value) const noexcept
             {
                 if (value.hasValue)
                 {
                     auto box = gc_new<T>();
                     box->value__ = value;
-                    return stack_from(box);
+                    return box;
                 }
                 else
                 {
-                    return null;
+                    return natsu::null;
                 }
             }
         };
@@ -606,10 +600,10 @@ namespace stack
             }
         };
 
-        template <class T>
+        template <class TFrom, class TTo>
         struct isinst_impl
         {
-            O operator()(const O &obj) const noexcept
+            gc_obj_ref<TTo> operator()(gc_obj_ref<TFrom> obj) const noexcept
             {
                 if (obj && obj.header().vtable_as<typename natsu::to_clr_type_t<T>::VTable>())
                     return obj;
@@ -683,250 +677,29 @@ namespace stack
                 return stack_to<TTo>(obj);
             }
         };
-    }
-}
 
-template <class TFrom>
-auto stack_from(const TFrom &value)
-{
-    return stack::details::stack_from_impl<std::decay_t<TFrom>>()(value);
-}
+        template <class T1, class T2>
+        struct ceq_impl
+        {
+            int32_t operator()(const T1 &lhs, const T2 rhs) const noexcept
+            {
+                return lhs == rhs;
+            }
+        };
 
-template <class TTo, class TFrom>
-auto stack_to(TFrom &&value)
-{
-    return stack::details::stack_to_impl<std::decay_t<TFrom>, TTo>()(std::forward<TFrom>(value));
+        template <class T1, class T2>
+        struct cgt_un_impl
+        {
+            int32_t operator()(const T1 &lhs, const T2 rhs) const noexcept
+            {
+                return std::lhs == rhs;
+            }
+        };
+    }
 }
 
 namespace ops
 {
-#define BINARY_OP_IMPL(name, op, A, B, Ret, Med, Cast)                                          \
-    inline Ret name##_(const A &lhs, const B &rhs) noexcept                                     \
-    {                                                                                           \
-        return static_cast<Cast>(static_cast<Med>(lhs.value_) op static_cast<Med>(rhs.value_)); \
-    }
-
-    BINARY_OP_IMPL(add, +, stack::int32, stack::int32, stack::int32, int32_t, int32_t);
-    BINARY_OP_IMPL(add, +, stack::int32, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(add, +, stack::int32, stack::Ref, stack::Ref, intptr_t, uintptr_t);
-    BINARY_OP_IMPL(add, +, stack::int64, stack::int64, stack::int64, int64_t, int64_t);
-    BINARY_OP_IMPL(add, +, stack::native_int, stack::int32, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(add, +, stack::native_int, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(add, +, stack::native_int, stack::Ref, stack::Ref, intptr_t, uintptr_t);
-    BINARY_OP_IMPL(add, +, stack::F, stack::F, stack::F, double, double);
-    BINARY_OP_IMPL(add, +, stack::Ref, stack::int32, stack::Ref, intptr_t, uintptr_t);
-    BINARY_OP_IMPL(add, +, stack::Ref, stack::native_int, stack::Ref, intptr_t, uintptr_t);
-
-    BINARY_OP_IMPL(sub, -, stack::int32, stack::int32, stack::int32, int32_t, int32_t);
-    BINARY_OP_IMPL(sub, -, stack::int32, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(sub, -, stack::int64, stack::int64, stack::int64, int64_t, int64_t);
-    BINARY_OP_IMPL(sub, -, stack::native_int, stack::int32, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(sub, -, stack::native_int, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(sub, -, stack::F, stack::F, stack::F, double, double);
-    BINARY_OP_IMPL(sub, -, stack::Ref, stack::int32, stack::Ref, intptr_t, uintptr_t);
-    BINARY_OP_IMPL(sub, -, stack::Ref, stack::native_int, stack::Ref, intptr_t, uintptr_t);
-    BINARY_OP_IMPL(sub, -, stack::Ref, stack::Ref, stack::native_int, intptr_t, intptr_t);
-
-    BINARY_OP_IMPL(mul, *, stack::int32, stack::int32, stack::int32, int32_t, int32_t);
-    BINARY_OP_IMPL(mul, *, stack::int32, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(mul, *, stack::int64, stack::int64, stack::int64, int64_t, int64_t);
-    BINARY_OP_IMPL(mul, *, stack::native_int, stack::int32, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(mul, *, stack::native_int, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(mul, *, stack::F, stack::F, stack::F, double, double);
-
-    BINARY_OP_IMPL(div, /, stack::int32, stack::int32, stack::int32, int32_t, int32_t);
-    BINARY_OP_IMPL(div, /, stack::int32, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(div, /, stack::int64, stack::int64, stack::int64, int64_t, int64_t);
-    BINARY_OP_IMPL(div, /, stack::native_int, stack::int32, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(div, /, stack::native_int, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(div, /, stack::F, stack::F, stack::F, double, double);
-
-    BINARY_OP_IMPL(rem, %, stack::int32, stack::int32, stack::int32, int32_t, int32_t);
-    BINARY_OP_IMPL(rem, %, stack::int32, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(rem, %, stack::int64, stack::int64, stack::int64, int64_t, int64_t);
-    BINARY_OP_IMPL(rem, %, stack::native_int, stack::int32, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(rem, %, stack::native_int, stack::native_int, stack::native_int, intptr_t, intptr_t);
-
-    BINARY_OP_IMPL(and, &, stack::int32, stack::int32, stack::int32, int32_t, int32_t);
-    BINARY_OP_IMPL(and, &, stack::int32, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(and, &, stack::int64, stack::int64, stack::int64, int64_t, int64_t);
-    BINARY_OP_IMPL(and, &, stack::native_int, stack::int32, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(and, &, stack::native_int, stack::native_int, stack::native_int, intptr_t, intptr_t);
-
-    BINARY_OP_IMPL(or, |, stack::int32, stack::int32, stack::int32, int32_t, int32_t);
-    BINARY_OP_IMPL(or, |, stack::int32, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(or, |, stack::int64, stack::int64, stack::int64, int64_t, int64_t);
-    BINARY_OP_IMPL(or, |, stack::native_int, stack::int32, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(or, |, stack::native_int, stack::native_int, stack::native_int, intptr_t, intptr_t);
-
-    BINARY_OP_IMPL(xor, ^, stack::int32, stack::int32, stack::int32, int32_t, int32_t);
-    BINARY_OP_IMPL(xor, ^, stack::int32, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(xor, ^, stack::int64, stack::int64, stack::int64, int64_t, int64_t);
-    BINARY_OP_IMPL(xor, ^, stack::native_int, stack::int32, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(xor, ^, stack::native_int, stack::native_int, stack::native_int, intptr_t, intptr_t);
-
-    BINARY_OP_IMPL(shl, <<, stack::int32, stack::int32, stack::int32, int32_t, int32_t);
-    BINARY_OP_IMPL(shl, <<, stack::int32, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(shl, <<, stack::int64, stack::int32, stack::int64, int64_t, int64_t);
-    BINARY_OP_IMPL(shl, <<, stack::native_int, stack::int32, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(shl, <<, stack::native_int, stack::native_int, stack::native_int, intptr_t, intptr_t);
-
-    BINARY_OP_IMPL(shr, >>, stack::int32, stack::int32, stack::int32, int32_t, int32_t);
-    BINARY_OP_IMPL(shr, >>, stack::int32, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(shr, >>, stack::int64, stack::int32, stack::int64, int64_t, int64_t);
-    BINARY_OP_IMPL(shr, >>, stack::native_int, stack::int32, stack::native_int, intptr_t, intptr_t);
-    BINARY_OP_IMPL(shr, >>, stack::native_int, stack::native_int, stack::native_int, intptr_t, intptr_t);
-
-    BINARY_OP_IMPL(div_un, /, stack::int32, stack::int32, stack::int32, uint32_t, int32_t);
-    BINARY_OP_IMPL(div_un, /, stack::int32, stack::native_int, stack::native_int, uintptr_t, intptr_t);
-    BINARY_OP_IMPL(div_un, /, stack::int64, stack::int64, stack::int64, uint64_t, int64_t);
-    BINARY_OP_IMPL(div_un, /, stack::native_int, stack::int32, stack::native_int, uintptr_t, intptr_t);
-    BINARY_OP_IMPL(div_un, /, stack::native_int, stack::native_int, stack::native_int, uintptr_t, intptr_t);
-    BINARY_OP_IMPL(div_un, /, stack::F, stack::F, stack::F, double, double);
-
-    BINARY_OP_IMPL(rem_un, %, stack::int32, stack::int32, stack::int32, uint32_t, int32_t);
-    BINARY_OP_IMPL(rem_un, %, stack::int32, stack::native_int, stack::native_int, uintptr_t, intptr_t);
-    BINARY_OP_IMPL(rem_un, %, stack::int64, stack::int64, stack::int64, uint64_t, int64_t);
-    BINARY_OP_IMPL(rem_un, %, stack::native_int, stack::int32, stack::native_int, uintptr_t, intptr_t);
-    BINARY_OP_IMPL(rem_un, %, stack::native_int, stack::native_int, stack::native_int, uintptr_t, intptr_t);
-
-    BINARY_OP_IMPL(shr_un, >>, stack::int32, stack::int32, stack::int32, uint32_t, int32_t);
-    BINARY_OP_IMPL(shr_un, >>, stack::int32, stack::native_int, stack::native_int, uintptr_t, intptr_t);
-    BINARY_OP_IMPL(shr_un, >>, stack::int64, stack::int32, stack::int64, uint64_t, int64_t);
-    BINARY_OP_IMPL(shr_un, >>, stack::native_int, stack::int32, stack::native_int, uintptr_t, intptr_t);
-    BINARY_OP_IMPL(shr_un, >>, stack::native_int, stack::native_int, stack::native_int, uintptr_t, intptr_t);
-
-#undef BINARY_OP_IMPL
-
-    inline stack::F rem_(const stack::F &lhs, const stack::F &rhs) noexcept
-    {
-        return fmod(lhs.value_, rhs.value_);
-    }
-
-#define UNARY_OP_IMPL(name, op, A, Med, Cast)                        \
-    inline A name##_(const A &value) noexcept                        \
-    {                                                                \
-        return static_cast<Cast>(op static_cast<Med>(value.value_)); \
-    }
-
-    UNARY_OP_IMPL(neg, -, stack::int32, int32_t, int32_t);
-    UNARY_OP_IMPL(neg, -, stack::int64, int64_t, int64_t);
-    UNARY_OP_IMPL(neg, -, stack::native_int, intptr_t, intptr_t);
-    UNARY_OP_IMPL(neg, -, stack::F, double, double);
-
-    UNARY_OP_IMPL(not, ~, stack::int32, int32_t, int32_t);
-    UNARY_OP_IMPL(not, ~, stack::int64, int64_t, int64_t);
-    UNARY_OP_IMPL(not, ~, stack::native_int, intptr_t, intptr_t);
-
-#undef UNARY_OP_IMPL
-
-#define COMPARE_OP_IMPL(name, op, A, B, Med)                                         \
-    inline stack::int32 name##_(const A &lhs, const B &rhs) noexcept                 \
-    {                                                                                \
-        return static_cast<Med>(lhs.value_) op static_cast<Med>(rhs.value_) ? 1 : 0; \
-    }
-
-    COMPARE_OP_IMPL(clt, <, stack::int32, stack::int32, int32_t);
-    COMPARE_OP_IMPL(clt, <, stack::int32, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(clt, <, stack::int64, stack::int64, int64_t);
-    COMPARE_OP_IMPL(clt, <, stack::native_int, stack::int32, intptr_t);
-    COMPARE_OP_IMPL(clt, <, stack::native_int, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(clt, <, stack::F, stack::F, double);
-    COMPARE_OP_IMPL(clt, <, stack::Ref, stack::Ref, intptr_t);
-
-    COMPARE_OP_IMPL(cle, <=, stack::int32, stack::int32, int32_t);
-    COMPARE_OP_IMPL(cle, <=, stack::int32, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(cle, <=, stack::int64, stack::int64, int64_t);
-    COMPARE_OP_IMPL(cle, <=, stack::native_int, stack::int32, intptr_t);
-    COMPARE_OP_IMPL(cle, <=, stack::native_int, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(cle, <=, stack::F, stack::F, double);
-    COMPARE_OP_IMPL(cle, <=, stack::Ref, stack::Ref, intptr_t);
-
-    COMPARE_OP_IMPL(ceq, ==, stack::int32, stack::int32, int32_t);
-    COMPARE_OP_IMPL(ceq, ==, stack::int32, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(ceq, ==, stack::int64, stack::int64, int64_t);
-    COMPARE_OP_IMPL(ceq, ==, stack::native_int, stack::int32, intptr_t);
-    COMPARE_OP_IMPL(ceq, ==, stack::native_int, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(ceq, ==, stack::native_int, stack::Ref, intptr_t);
-    COMPARE_OP_IMPL(ceq, ==, stack::F, stack::F, double);
-    COMPARE_OP_IMPL(ceq, ==, stack::Ref, stack::Ref, intptr_t);
-    COMPARE_OP_IMPL(ceq, ==, stack::Ref, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(ceq, ==, stack::O, stack::O, intptr_t);
-
-    COMPARE_OP_IMPL(cge, >=, stack::int32, stack::int32, int32_t);
-    COMPARE_OP_IMPL(cge, >=, stack::int32, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(cge, >=, stack::int64, stack::int64, int64_t);
-    COMPARE_OP_IMPL(cge, >=, stack::native_int, stack::int32, intptr_t);
-    COMPARE_OP_IMPL(cge, >=, stack::native_int, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(cge, >=, stack::F, stack::F, double);
-    COMPARE_OP_IMPL(cge, >=, stack::Ref, stack::Ref, intptr_t);
-
-    COMPARE_OP_IMPL(cgt, >, stack::int32, stack::int32, int32_t);
-    COMPARE_OP_IMPL(cgt, >, stack::int32, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(cgt, >, stack::int64, stack::int64, int64_t);
-    COMPARE_OP_IMPL(cgt, >, stack::native_int, stack::int32, intptr_t);
-    COMPARE_OP_IMPL(cgt, >, stack::native_int, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(cgt, >, stack::F, stack::F, double);
-    COMPARE_OP_IMPL(cgt, >, stack::Ref, stack::Ref, intptr_t);
-
-    COMPARE_OP_IMPL(cne, !=, stack::int32, stack::int32, int32_t);
-    COMPARE_OP_IMPL(cne, !=, stack::int32, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(cne, !=, stack::int64, stack::int64, int64_t);
-    COMPARE_OP_IMPL(cne, !=, stack::native_int, stack::int32, intptr_t);
-    COMPARE_OP_IMPL(cne, !=, stack::native_int, stack::native_int, intptr_t);
-    COMPARE_OP_IMPL(cne, !=, stack::F, stack::F, double);
-    COMPARE_OP_IMPL(cne, !=, stack::Ref, stack::Ref, intptr_t);
-    COMPARE_OP_IMPL(cne, !=, stack::O, stack::O, intptr_t);
-
-    COMPARE_OP_IMPL(clt_un, <, stack::int32, stack::int32, uint32_t);
-    COMPARE_OP_IMPL(clt_un, <, stack::int32, stack::native_int, uintptr_t);
-    COMPARE_OP_IMPL(clt_un, <, stack::int64, stack::int64, uint64_t);
-    COMPARE_OP_IMPL(clt_un, <, stack::native_int, stack::int32, uintptr_t);
-    COMPARE_OP_IMPL(clt_un, <, stack::native_int, stack::native_int, uintptr_t);
-    COMPARE_OP_IMPL(clt_un, <, stack::F, stack::F, double);
-    COMPARE_OP_IMPL(clt_un, <, stack::Ref, stack::Ref, uintptr_t);
-
-    COMPARE_OP_IMPL(cle_un, <=, stack::int32, stack::int32, uint32_t);
-    COMPARE_OP_IMPL(cle_un, <=, stack::int32, stack::native_int, uintptr_t);
-    COMPARE_OP_IMPL(cle_un, <=, stack::int64, stack::int64, uint64_t);
-    COMPARE_OP_IMPL(cle_un, <=, stack::native_int, stack::int32, uintptr_t);
-    COMPARE_OP_IMPL(cle_un, <=, stack::native_int, stack::native_int, uintptr_t);
-    COMPARE_OP_IMPL(cle_un, <=, stack::F, stack::F, double);
-    COMPARE_OP_IMPL(cle_un, <=, stack::Ref, stack::Ref, uintptr_t);
-
-    COMPARE_OP_IMPL(cge_un, >=, stack::int32, stack::int32, uint32_t);
-    COMPARE_OP_IMPL(cge_un, >=, stack::int32, stack::native_int, uintptr_t);
-    COMPARE_OP_IMPL(cge_un, >=, stack::int64, stack::int64, uint64_t);
-    COMPARE_OP_IMPL(cge_un, >=, stack::native_int, stack::int32, uintptr_t);
-    COMPARE_OP_IMPL(cge_un, >=, stack::native_int, stack::native_int, uintptr_t);
-    COMPARE_OP_IMPL(cge_un, >=, stack::F, stack::F, double);
-    COMPARE_OP_IMPL(cge_un, >=, stack::Ref, stack::Ref, uintptr_t);
-
-    COMPARE_OP_IMPL(cgt_un, >, stack::int32, stack::int32, uint32_t);
-    COMPARE_OP_IMPL(cgt_un, >, stack::int32, stack::native_int, uintptr_t);
-    COMPARE_OP_IMPL(cgt_un, >, stack::int64, stack::int64, uint64_t);
-    COMPARE_OP_IMPL(cgt_un, >, stack::native_int, stack::int32, uintptr_t);
-    COMPARE_OP_IMPL(cgt_un, >, stack::native_int, stack::native_int, uintptr_t);
-    COMPARE_OP_IMPL(cgt_un, >, stack::F, stack::F, double);
-    COMPARE_OP_IMPL(cgt_un, >, stack::Ref, stack::Ref, uintptr_t);
-    // TODO: invalid in ECMA335?, but roslyn generates
-    COMPARE_OP_IMPL(cgt_un, >, stack::O, stack::O, uintptr_t);
-
-    COMPARE_OP_IMPL(cne_un, !=, stack::int32, stack::int32, uint32_t);
-    COMPARE_OP_IMPL(cne_un, !=, stack::int32, stack::native_int, uintptr_t);
-    COMPARE_OP_IMPL(cne_un, !=, stack::int64, stack::int64, uint64_t);
-    COMPARE_OP_IMPL(cne_un, !=, stack::native_int, stack::int32, uintptr_t);
-    COMPARE_OP_IMPL(cne_un, !=, stack::native_int, stack::native_int, uintptr_t);
-    COMPARE_OP_IMPL(cne_un, !=, stack::native_int, stack::Ref, uintptr_t);
-    COMPARE_OP_IMPL(cne_un, !=, stack::F, stack::F, double);
-    COMPARE_OP_IMPL(cne_un, !=, stack::Ref, stack::Ref, uintptr_t);
-    COMPARE_OP_IMPL(cne_un, !=, stack::Ref, stack::native_int, uintptr_t);
-    COMPARE_OP_IMPL(cne_un, !=, stack::O, stack::O, uintptr_t);
-
-#undef COMPARE_OP_IMPL
-
-    stack::native_int ldlen(const stack::O &obj);
-
     template <class T, class... TArgs>
     auto newobj(TArgs... args)
     {
@@ -934,67 +707,61 @@ namespace ops
         {
             T value;
             value._ctor(value, std::forward<TArgs>(args)...);
-            return stack_from(value);
+            return value;
         }
         else if constexpr (std::is_same_v<T, ::System_Private_CoreLib::System::String>)
         {
             auto value = ::System_Private_CoreLib::System::String::_s_Ctor(std::forward<TArgs>(args)...);
-            return stack_from(value);
+            return value;
         }
         else
         {
             auto value = gc_new<T>();
             value->_ctor(value, std::forward<TArgs>(args)...);
-            return stack_from(value);
+            return value;
         }
     }
 
     template <class TFrom>
-    stack::O box(TFrom &&value) noexcept
+    auto box(TFrom &&value) noexcept
     {
         return stack::details::box_impl<std::decay_t<TFrom>>()(std::forward<TFrom>(value));
     }
 
-    template <class T>
-    stack::Ref unbox(const stack::O &obj)
+    template <class TFrom, class TTo>
+    auto unbox(TFrom &&obj)
     {
-        return stack::details::unbox_impl<T>()(obj);
+        return stack::details::unbox_impl<TTo>()(obj);
     }
 
-    template <class T>
-    auto unbox_any(const stack::O &obj)
+    template <class TFrom, class TTo>
+    auto unbox_any(TFrom &&obj)
     {
         return stack::details::unbox_any_impl<T>()(obj);
     }
 
     template <class TFrom>
-    stack::Ref ref(TFrom &value) noexcept
-    {
-        return reinterpret_cast<uintptr_t>(&value);
-    }
-
-    template <class TTo, class TFrom>
-    auto access(TFrom &&value) noexcept
+    natsu::gc_ref<TFrom> ref(TFrom &value) noexcept
     {
-        return stack::details::access_impl<std::decay_t<TFrom>, TTo>()(std::forward<TFrom>(value));
+        return natsu::gc_ref_from_ref(&value);
     }
 
     template <class TFrom>
-    void initobj(const stack::Ref &addr) noexcept
+    void initobj(gc_ref<TFrom> addr) noexcept
     {
         std::memset((void *)addr.value_, 0, sizeof(TFrom));
     }
 
     template <class TFrom>
-    void initobj(const stack::native_int &addr) noexcept
+    void initobj(intptr_t addr) noexcept
     {
-        std::memset((void *)addr.value_, 0, sizeof(TFrom));
+        std::memset((void *)addr, 0, sizeof(TFrom));
     }
 
-    template <class T>
-    stack::O isinst(const stack::O &obj) noexcept
+    template <class TFrom, class TTo>
+    auto isinst(gc_obj_ref<TFrom> obj) noexcept
     {
-        return stack::details::isinst_impl<T>()(obj);
+        return stack::details::isinst_impl<TFrom, TTo>()(obj);
     }
 
     template <class T>
@@ -1003,377 +770,11 @@ namespace ops
         return stack::details::castclass_impl<T>()(obj);
     }
 
-#define LDELEM_IMPL(name, type, value_type)                                                         \
-    inline value_type ldelem_##name(const stack::O &obj, stack::int32 index)                        \
-    {                                                                                               \
-        using ::System_Private_CoreLib::System::SZArray_1;                                          \
-        return stack_from(stack_to<gc_obj_ref<SZArray_1<type>>>(obj)->at((uint32_t)index.value_));  \
-    }                                                                                               \
-    inline value_type ldelem_##name(const stack::O &obj, stack::native_int index)                   \
-    {                                                                                               \
-        using ::System_Private_CoreLib::System::SZArray_1;                                          \
-        return stack_from(stack_to<gc_obj_ref<SZArray_1<type>>>(obj)->at((uintptr_t)index.value_)); \
-    }
-
-    LDELEM_IMPL(i1, int8_t, stack::int32);
-    LDELEM_IMPL(i2, int16_t, stack::int32);
-    LDELEM_IMPL(i4, int32_t, stack::int32);
-    LDELEM_IMPL(i8, int64_t, stack::int64);
-    LDELEM_IMPL(r4, float, stack::F);
-    LDELEM_IMPL(r8, double, stack::F);
-    LDELEM_IMPL(i, ::System_Private_CoreLib::System::IntPtr, stack::native_int);
-    LDELEM_IMPL(u1, uint8_t, stack::int32);
-    LDELEM_IMPL(u2, uint16_t, stack::int32);
-    LDELEM_IMPL(u4, uint32_t, stack::int32);
-    LDELEM_IMPL(u8, uint64_t, stack::int64);
-    LDELEM_IMPL(u, ::System_Private_CoreLib::System::UIntPtr, stack::native_int);
-
-    inline stack::O ldelem_ref(const stack::O &obj, stack::int32 index)
-    {
-        using ::System_Private_CoreLib::System::Object;
-        using ::System_Private_CoreLib::System::SZArray_1;
-        return stack_from(stack_to<gc_obj_ref<SZArray_1<Object>>>(obj)->at((uint32_t)index.value_));
-    }
-
-    inline stack::O ldelem_ref(const stack::O &obj, stack::native_int index)
-    {
-        using ::System_Private_CoreLib::System::Object;
-        using ::System_Private_CoreLib::System::SZArray_1;
-        return stack_from(stack_to<gc_obj_ref<SZArray_1<Object>>>(obj)->at((uintptr_t)index.value_));
-    }
-
     template <class T>
-    inline auto ldelem(const stack::O &obj, stack::int32 index)
+    constexpr auto unsign(T value) noexcept
     {
-        using ::System_Private_CoreLib::System::Object;
-        using ::System_Private_CoreLib::System::SZArray_1;
-        return stack_from(stack_to<gc_obj_ref<SZArray_1<T>>>(obj)->at((uint32_t)index.value_));
-    }
-
-    template <class T>
-    inline auto ldelem(const stack::O &obj, stack::native_int index)
-    {
-        using ::System_Private_CoreLib::System::Object;
-        using ::System_Private_CoreLib::System::SZArray_1;
-        return stack_from(stack_to<gc_obj_ref<SZArray_1<T>>>(obj)->at((uintptr_t)index.value_));
-    }
-
-#undef LDELEM_IMPL
-
-#define STELEM_IMPL(name, type, value_type, cast)                                                       \
-    inline void stelem_##name(const stack::O &obj, stack::int32 index, value_type value)                \
-    {                                                                                                   \
-        using ::System_Private_CoreLib::System::SZArray_1;                                              \
-        stack_to<gc_obj_ref<SZArray_1<type>>>(obj)->at(index.value_) = static_cast<cast>(value.value_); \
-    }
-
-    STELEM_IMPL(i1, int8_t, stack::int32, int8_t);
-    STELEM_IMPL(i2, int16_t, stack::int32, int16_t);
-    STELEM_IMPL(i4, int32_t, stack::int32, int32_t);
-    STELEM_IMPL(i8, int64_t, stack::int64, int64_t);
-    STELEM_IMPL(r4, float, stack::F, float);
-    STELEM_IMPL(r8, double, stack::F, double);
-    STELEM_IMPL(i, ::System_Private_CoreLib::System::IntPtr, stack::native_int, intptr_t);
-
-    inline void stelem_ref(const stack::O &obj, stack::int32 index, stack::O value)
-    {
-        using ::System_Private_CoreLib::System::Object;
-        using ::System_Private_CoreLib::System::SZArray_1;
-        stack_to<gc_obj_ref<SZArray_1<Object>>>(obj)->at(index.value_) = stack_to<gc_obj_ref<Object>>(value);
-    }
-
-    template <class T, class TStack>
-    void stelem(const stack::O &obj, stack::int32 index, TStack value)
-    {
-        using ::System_Private_CoreLib::System::Object;
-        using ::System_Private_CoreLib::System::SZArray_1;
-        stack_to<gc_obj_ref<SZArray_1<T>>>(obj)->at((uint32_t)index.value_) = stack_to<variable_type_t<T>>(value);
-    }
-
-    template <class T, class TStack>
-    void stelem(const stack::O &obj, stack::native_int index, TStack value)
-    {
-        using ::System_Private_CoreLib::System::Object;
-        using ::System_Private_CoreLib::System::SZArray_1;
-        stack_to<gc_obj_ref<SZArray_1<T>>>(obj)->at((uint32_t)index.value_) = stack_to<variable_type_t<T>>(value);
-    }
-
-#undef STELEM_IMPL
-
-#define LDIND_IMPL(name, type, ret, cast)                                 \
-    inline ret ldind_##name(stack::native_int addr)                       \
-    {                                                                     \
-        return static_cast<cast>(*reinterpret_cast<type *>(addr.value_)); \
-    }                                                                     \
-    inline ret ldind_##name(stack::Ref addr)                              \
-    {                                                                     \
-        return static_cast<cast>(*reinterpret_cast<type *>(addr.value_)); \
-    }
-
-    LDIND_IMPL(i1, int8_t, stack::int32, int32_t);
-    LDIND_IMPL(i2, int16_t, stack::int32, int32_t);
-    LDIND_IMPL(i4, int32_t, stack::int32, int32_t);
-    LDIND_IMPL(i8, int64_t, stack::int64, int64_t);
-    LDIND_IMPL(r4, float, stack::F, double);
-    LDIND_IMPL(r8, double, stack::F, double);
-    LDIND_IMPL(i, intptr_t, stack::native_int, intptr_t);
-    LDIND_IMPL(ref, uintptr_t, stack::O, uintptr_t);
-    LDIND_IMPL(u1, uint8_t, stack::int32, int32_t);
-    LDIND_IMPL(u2, uint16_t, stack::int32, int32_t);
-    LDIND_IMPL(u4, uint32_t, stack::int32, int32_t);
-
-#undef LDIND_IMPL
-
-#define STIND_IMPL(name, type, value_type)                                        \
-    inline void stind_##name(stack::native_int addr, value_type value)            \
-    {                                                                             \
-        *reinterpret_cast<type *>(addr.value_) = static_cast<type>(value.value_); \
-    }                                                                             \
-    inline void stind_##name(stack::Ref addr, value_type value)                   \
-    {                                                                             \
-        *reinterpret_cast<type *>(addr.value_) = static_cast<type>(value.value_); \
-    }
-
-    STIND_IMPL(i1, int8_t, stack::int32);
-    STIND_IMPL(i2, int16_t, stack::int32);
-    STIND_IMPL(i4, int32_t, stack::int32);
-    STIND_IMPL(i8, int64_t, stack::int64);
-    STIND_IMPL(r4, float, stack::F);
-    STIND_IMPL(r8, double, stack::F);
-    STIND_IMPL(i, intptr_t, stack::native_int);
-    STIND_IMPL(ref, uintptr_t, stack::O);
-
-#undef STIND_IMPL
-
-#define CONV_IMPL(name, value_type, ret, med_cast, cast)               \
-    inline ret conv_##name(value_type value)                           \
-    {                                                                  \
-        return static_cast<cast>(static_cast<med_cast>(value.value_)); \
-    }
-
-    CONV_IMPL(i1, stack::int32, stack::int32, int8_t, int32_t);
-    CONV_IMPL(i1, stack::int64, stack::int32, int8_t, int32_t);
-    CONV_IMPL(i1, stack::native_int, stack::int32, int8_t, int32_t);
-    CONV_IMPL(i1, stack::F, stack::int32, int8_t, int32_t);
-
-    CONV_IMPL(i2, stack::int32, stack::int32, int16_t, int32_t);
-    CONV_IMPL(i2, stack::int64, stack::int32, int16_t, int32_t);
-    CONV_IMPL(i2, stack::native_int, stack::int32, int16_t, int32_t);
-    CONV_IMPL(i2, stack::F, stack::int32, int16_t, int32_t);
-
-    CONV_IMPL(i4, stack::int32, stack::int32, int32_t, int32_t);
-    CONV_IMPL(i4, stack::int64, stack::int32, int32_t, int32_t);
-    CONV_IMPL(i4, stack::native_int, stack::int32, int32_t, int32_t);
-    CONV_IMPL(i4, stack::F, stack::int32, int32_t, int32_t);
-
-    CONV_IMPL(i8, stack::int32, stack::int64, int64_t, int64_t);
-    CONV_IMPL(i8, stack::int64, stack::int64, int64_t, int64_t);
-    CONV_IMPL(i8, stack::native_int, stack::int64, int64_t, int64_t);
-    CONV_IMPL(i8, stack::F, stack::int64, int64_t, int64_t);
-    CONV_IMPL(i8, stack::Ref, stack::int64, int64_t, int64_t);
-    CONV_IMPL(i8, stack::O, stack::int64, int64_t, int64_t);
-
-    CONV_IMPL(i, stack::int32, stack::native_int, intptr_t, intptr_t);
-    CONV_IMPL(i, stack::int64, stack::native_int, intptr_t, intptr_t);
-    CONV_IMPL(i, stack::native_int, stack::native_int, intptr_t, intptr_t);
-    CONV_IMPL(i, stack::F, stack::native_int, intptr_t, intptr_t);
-    CONV_IMPL(i, stack::Ref, stack::native_int, intptr_t, intptr_t);
-    CONV_IMPL(i, stack::O, stack::native_int, intptr_t, intptr_t);
-
-    CONV_IMPL(r4, stack::int32, stack::F, float, double);
-    CONV_IMPL(r4, stack::int64, stack::F, float, double);
-    CONV_IMPL(r4, stack::native_int, stack::F, float, double);
-    CONV_IMPL(r4, stack::F, stack::F, float, double);
-
-    CONV_IMPL(r8, stack::int32, stack::F, double, double);
-    CONV_IMPL(r8, stack::int64, stack::F, double, double);
-    CONV_IMPL(r8, stack::native_int, stack::F, double, double);
-    CONV_IMPL(r8, stack::F, stack::F, double, double);
-
-    CONV_IMPL(u1, stack::int32, stack::int32, uint8_t, int32_t);
-    CONV_IMPL(u1, stack::int64, stack::int32, uint8_t, int32_t);
-    CONV_IMPL(u1, stack::native_int, stack::int32, uint8_t, int32_t);
-    CONV_IMPL(u1, stack::F, stack::int32, uint8_t, int32_t);
-
-    CONV_IMPL(u2, stack::int32, stack::int32, uint16_t, int32_t);
-    CONV_IMPL(u2, stack::int64, stack::int32, uint16_t, int32_t);
-    CONV_IMPL(u2, stack::native_int, stack::int32, uint16_t, int32_t);
-    CONV_IMPL(u2, stack::F, stack::int32, uint16_t, int32_t);
-
-    CONV_IMPL(u4, stack::int32, stack::int32, uint32_t, int32_t);
-    CONV_IMPL(u4, stack::int64, stack::int32, uint32_t, int32_t);
-    CONV_IMPL(u4, stack::native_int, stack::int32, uint32_t, int32_t);
-    CONV_IMPL(u4, stack::F, stack::int32, uint32_t, int32_t);
-
-    CONV_IMPL(u8, stack::int32, stack::int64, uint64_t, int64_t);
-    CONV_IMPL(u8, stack::int64, stack::int64, uint64_t, int64_t);
-    CONV_IMPL(u8, stack::native_int, stack::int64, uint64_t, int64_t);
-    CONV_IMPL(u8, stack::F, stack::int64, uint64_t, int64_t);
-    CONV_IMPL(u8, stack::Ref, stack::int64, uint64_t, int64_t);
-    CONV_IMPL(u8, stack::O, stack::int64, uint64_t, int64_t);
-
-    CONV_IMPL(u, stack::int32, stack::native_int, uintptr_t, intptr_t);
-    CONV_IMPL(u, stack::int64, stack::native_int, uintptr_t, intptr_t);
-    CONV_IMPL(u, stack::native_int, stack::native_int, uintptr_t, intptr_t);
-    CONV_IMPL(u, stack::F, stack::native_int, uintptr_t, intptr_t);
-    CONV_IMPL(u, stack::Ref, stack::native_int, uintptr_t, intptr_t);
-    CONV_IMPL(u, stack::O, stack::native_int, uintptr_t, intptr_t);
-
-#undef CONV_IMPL
-
-#define CONV_OVF_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>::lowest() || v1 > std::numeric_limits<med_cast>::max()) \
-            throw_overflow_exception();                                                                \
-        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);
-    CONV_OVF_IMPL(i1, stack::F, stack::int32, double, int8_t, int32_t);
-
-    CONV_OVF_IMPL(i2, stack::int32, stack::int32, int32_t, int16_t, int32_t);
-    CONV_OVF_IMPL(i2, stack::int64, stack::int32, int64_t, int16_t, int32_t);
-    CONV_OVF_IMPL(i2, stack::native_int, stack::int32, intptr_t, int16_t, int32_t);
-    CONV_OVF_IMPL(i2, stack::F, stack::int32, double, int16_t, int32_t);
-
-    CONV_OVF_IMPL(i4, stack::int32, stack::int32, int32_t, int32_t, int32_t);
-    CONV_OVF_IMPL(i4, stack::int64, stack::int32, int64_t, int32_t, int32_t);
-    CONV_OVF_IMPL(i4, stack::native_int, stack::int32, intptr_t, int32_t, int32_t);
-    CONV_OVF_IMPL(i4, stack::F, stack::int32, double, int32_t, int32_t);
-
-    CONV_OVF_IMPL(i8, stack::int32, stack::int64, int32_t, int64_t, int64_t);
-    CONV_OVF_IMPL(i8, stack::int64, stack::int64, int64_t, int64_t, int64_t);
-    CONV_OVF_IMPL(i8, stack::native_int, stack::int64, intptr_t, int64_t, int64_t);
-    CONV_OVF_IMPL(i8, stack::F, stack::int64, double, int64_t, int64_t);
-    CONV_OVF_IMPL(i8, stack::Ref, stack::int64, intptr_t, int64_t, int64_t);
-    CONV_OVF_IMPL(i8, stack::O, stack::int64, intptr_t, int64_t, int64_t);
-
-    CONV_OVF_IMPL(i, stack::int32, stack::native_int, int32_t, intptr_t, intptr_t);
-    CONV_OVF_IMPL(i, stack::int64, stack::native_int, int64_t, intptr_t, intptr_t);
-    CONV_OVF_IMPL(i, stack::native_int, stack::native_int, intptr_t, intptr_t, intptr_t);
-    CONV_OVF_IMPL(i, stack::F, stack::native_int, double, intptr_t, intptr_t);
-    CONV_OVF_IMPL(i, stack::Ref, stack::native_int, intptr_t, intptr_t, intptr_t);
-    CONV_OVF_IMPL(i, stack::O, stack::native_int, intptr_t, intptr_t, intptr_t);
-
-    CONV_OVF_IMPL(u1, stack::int32, stack::int32, int32_t, uint8_t, int32_t);
-    CONV_OVF_IMPL(u1, stack::int64, stack::int32, int64_t, uint8_t, int32_t);
-    CONV_OVF_IMPL(u1, stack::native_int, stack::int32, intptr_t, uint8_t, int32_t);
-    CONV_OVF_IMPL(u1, stack::F, stack::int32, double, uint8_t, int32_t);
-
-    CONV_OVF_IMPL(u2, stack::int32, stack::int32, int32_t, uint16_t, int32_t);
-    CONV_OVF_IMPL(u2, stack::int64, stack::int32, int64_t, uint16_t, int32_t);
-    CONV_OVF_IMPL(u2, stack::native_int, stack::int32, intptr_t, uint16_t, int32_t);
-    CONV_OVF_IMPL(u2, stack::F, stack::int32, double, uint16_t, int32_t);
-
-    CONV_OVF_IMPL(u4, stack::int32, stack::int32, int32_t, uint32_t, int32_t);
-    CONV_OVF_IMPL(u4, stack::int64, stack::int32, int64_t, uint32_t, int32_t);
-    CONV_OVF_IMPL(u4, stack::native_int, stack::int32, intptr_t, uint32_t, int32_t);
-    CONV_OVF_IMPL(u4, stack::F, stack::int32, double, uint32_t, int32_t);
-
-    CONV_OVF_IMPL(u8, stack::int32, stack::int64, int32_t, uint64_t, int64_t);
-    CONV_OVF_IMPL(u8, stack::int64, stack::int64, int64_t, uint64_t, int64_t);
-    CONV_OVF_IMPL(u8, stack::native_int, stack::int64, intptr_t, uint64_t, int64_t);
-    CONV_OVF_IMPL(u8, stack::F, stack::int64, double, uint64_t, int64_t);
-    CONV_OVF_IMPL(u8, stack::Ref, stack::int64, intptr_t, uint64_t, int64_t);
-    CONV_OVF_IMPL(u8, stack::O, stack::int64, intptr_t, uint64_t, int64_t);
-
-    CONV_OVF_IMPL(u, stack::int32, stack::native_int, int32_t, uintptr_t, intptr_t);
-    CONV_OVF_IMPL(u, stack::int64, stack::native_int, int64_t, uintptr_t, intptr_t);
-    CONV_OVF_IMPL(u, stack::native_int, stack::native_int, intptr_t, uintptr_t, intptr_t);
-    CONV_OVF_IMPL(u, stack::F, stack::native_int, double, uintptr_t, intptr_t);
-    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_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
-
-    template <class T>
-    stack::Ref ldelema(const stack::O &obj, stack::int32 index)
-    {
-        using ::System_Private_CoreLib::System::SZArray_1;
-        return stack_from(stack_to<gc_obj_ref<SZArray_1<T>>>(obj)->ref_at(index.value_));
-    }
-
-    template <class T>
-    auto ldobj(const stack::Ref &addr)
-    {
-        return stack_from(*reinterpret_cast<T *>(addr.value_));
-    }
-
-    template <class T, class TStack>
-    void stobj(const TStack &src, const stack::Ref &dest)
-    {
-        *reinterpret_cast<T *>(dest.value_) = stack_to<T>(src);
+        using unsigned_type = std::make_unsigned<T>::type;
+        return static_cast<unsigned_type>(value);
     }
 
     template <class T>
@@ -1382,29 +783,7 @@ namespace ops
         return { runtime_type_holder<natsu::to_clr_type_t<T>>::get() };
     }
 
-    [[noreturn]] void throw_(const stack::O &obj);
-
-    inline stack::native_int localloc(const stack::int32 &size)
-    {
-        return reinterpret_cast<intptr_t>(alloca(size.value_));
-    }
-
-    inline stack::native_int localloc(const stack::native_int &size)
-    {
-        return reinterpret_cast<intptr_t>(alloca(size.value_));
-    }
-
-    template <class T>
-    stack::native_int ldftn(T func)
-    {
-        return reinterpret_cast<intptr_t>(func);
-    }
-
-    template <class T>
-    stack::int32 Sizeof()
-    {
-        return static_cast<int32_t>(sizeof(T));
-    }
+    [[noreturn]] void throw_(gc_obj_ref<::System_Private_CoreLib::System::Exception> obj);
 }
 
 template <class T>

+ 11 - 12
src/Native/natsu.typedef.h

@@ -101,12 +101,18 @@ struct vtable_holder
 {
     static const constexpr T value = T();
 
-    static constexpr const T &get()
+    static constexpr const T &get() noexcept
     {
         return value;
     }
 };
 
+template <class T>
+auto &vtable() noexcept
+{
+    return vtable_holder<typename T::VTable>::get();
+}
+
 typedef struct _vtable
 {
     uint32_t ElementSize;
@@ -398,7 +404,7 @@ struct gc_ptr<void>
     }
 };
 
-template <class T>
+template <class T = ::System_Private_CoreLib::System::Object>
 struct gc_obj_ref
 {
     T *ptr_;
@@ -413,15 +419,8 @@ struct gc_obj_ref
     {
     }
 
-    template <class U>
-    gc_obj_ref(gc_obj_ref<U> &&other) noexcept
-        : ptr_(reinterpret_cast<T *>(other.ptr_))
-    {
-        other.ptr_ = nullptr;
-    }
-
     template <class U, class = std::enable_if_t<std::is_convertible_v<U *, T *>>>
-    gc_obj_ref(const gc_obj_ref<U> &other) noexcept
+    constexpr gc_obj_ref(const gc_obj_ref<U> &other) noexcept
         : ptr_(static_cast<T *>(other.ptr_))
     {
     }
@@ -447,9 +446,9 @@ struct gc_obj_ref
         return ptr_;
     }
 
-    explicit operator uintptr_t() const noexcept
+    operator gc_obj_ref<>() const noexcept
     {
-        return reinterpret_cast<uintptr_t>(ptr_);
+        return gc_obj_ref<>(reinterpret_cast<::System_Private_CoreLib::System::Object *>(ptr_));
     }
 
     template <class U>

+ 34 - 5
src/Natsu.Compiler/EvaluationStack.cs

@@ -23,6 +23,8 @@ namespace Natsu.Compiler
     {
         public StackTypeCode Code;
 
+        public TypeSig TypeSig;
+
         public string Name;
     }
 
@@ -32,6 +34,8 @@ namespace Natsu.Compiler
 
         public string Expression { get; set; }
 
+        public bool Computed { get; set; }
+
         public override string ToString()
         {
             return $"{Type}, {Expression}";
@@ -72,20 +76,45 @@ namespace Natsu.Compiler
             }
             else
             {
+                //var id = $"_v{_paramIndex++}";
+                //_writer.Ident(Ident).WriteLine($"auto {id} = {entry.Expression};");
+                //_stackValues.Push(new StackEntry { Type = entry.Type, Expression = id });
+                _stackValues.Push(entry);
+            }
+        }
+
+        public void Compute()
+        {
+            var entry = _stackValues.Peek();
+            if (!entry.Computed)
+            {
+                _stackValues.Pop();
                 var id = $"_v{_paramIndex++}";
                 _writer.Ident(Ident).WriteLine($"auto {id} = {entry.Expression};");
-                _stackValues.Push(new StackEntry { Type = entry.Type, Expression = id });
+                var newEntry = new StackEntry { Type = entry.Type, Expression = id, Computed = true };
+                _stackValues.Push(newEntry);
             }
         }
 
-        public void Push(StackType type, string expression)
+        public void Dup()
+        {
+            Compute();
+            Push(Peek());
+        }
+
+        public void Push(StackType type, string expression, bool computed = false)
+        {
+            Push(new StackEntry { Type = type, Expression = expression, Computed = computed });
+        }
+
+        public void Push(ITypeDefOrRef type, string expression, bool computed = false)
         {
-            Push(new StackEntry { Type = type, Expression = expression });
+            Push(new StackEntry { Type = TypeUtils.GetStackType(type.ToTypeSig()), Expression = expression, Computed = computed });
         }
 
-        public void Push(StackTypeCode type, string expression)
+        public void Push(TypeSig type, string expression, bool computed = false)
         {
-            Push(new StackEntry { Type = new StackType { Code = type }, Expression = expression });
+            Push(new StackEntry { Type = TypeUtils.GetStackType(type), Expression = expression, Computed = computed });
         }
 
         public StackEntry Pop()

+ 195 - 124
src/Natsu.Compiler/ILImporter.cs

@@ -16,6 +16,7 @@ namespace Natsu.Compiler
         private readonly TextWriter _writer;
         private readonly int _ident;
         private readonly MethodDef _method;
+        private readonly CorLibTypes _corLibTypes;
         private List<SpillSlot> _spillSlots = new List<SpillSlot>();
         private Dictionary<ExceptionHandler, ExceptionHandlerContext> _exceptions = new Dictionary<ExceptionHandler, ExceptionHandlerContext>();
         private int _paramIndex;
@@ -25,8 +26,9 @@ namespace Natsu.Compiler
         public List<string> UserStrings { get; set; }
         public string ModuleName { get; set; }
 
-        public ILImporter(MethodDef method, TextWriter writer, int ident)
+        public ILImporter(CorLibTypes corLibTypes, MethodDef method, TextWriter writer, int ident)
         {
+            _corLibTypes = corLibTypes;
             _method = method;
             _writer = writer;
             _ident = ident;
@@ -328,7 +330,7 @@ namespace Natsu.Compiler
 
         private void WriteInstruction(TextWriter writer, Instruction op, EvaluationStack stack, int ident, BasicBlock block)
         {
-            var emitter = new OpEmitter { ModuleName = ModuleName, UserStrings = UserStrings, Method = _method, Op = op, Stack = stack, Ident = ident, Block = block, Writer = writer };
+            var emitter = new OpEmitter { CorLibTypes = _corLibTypes, ModuleName = ModuleName, UserStrings = UserStrings, Method = _method, Op = op, Stack = stack, Ident = ident, Block = block, Writer = writer };
             bool isSpecial = true;
 
             if (op.IsLdarg())
@@ -820,6 +822,7 @@ namespace Natsu.Compiler
         public TextWriter Writer { get; set; }
         public string ModuleName { get; set; }
         public List<string> UserStrings { get; set; }
+        public CorLibTypes CorLibTypes { get; set; }
 
         // Unary
 
@@ -828,24 +831,24 @@ namespace Natsu.Compiler
 
         // Binary
 
-        public void Add() => Binary("add");
-        public void Sub() => Binary("sub");
-        public void Mul() => Binary("mul");
-        public void Div() => Binary("div");
-        public void Div_Un() => Binary("div_un");
-        public void Rem() => Binary("rem");
-        public void Rem_Un() => Binary("rem_un");
-        public void And() => Binary("and");
-        public void Or() => Binary("or");
-        public void Xor() => Binary("xor");
-        public void Shl() => Binary("shl");
-        public void Shr() => Binary("shr");
-        public void Shr_Un() => Binary("shr_un");
-        public void Clt() => Compare("clt");
-        public void Clt_Un() => Compare("clt_un");
-        public void Ceq() => Compare("ceq");
-        public void Cgt() => Compare("cgt");
-        public void Cgt_Un() => Compare("cgt_un");
+        public void Add() => Binary("+");
+        public void Sub() => Binary("-");
+        public void Mul() => Binary("*");
+        public void Div() => Binary("/");
+        public void Div_Un() => Binary_Un("/");
+        public void Rem() => Binary("%");
+        public void Rem_Un() => Binary_Un("%");
+        public void And() => Binary("&");
+        public void Or() => Binary("|");
+        public void Xor() => Binary("^");
+        public void Shl() => Binary("<<");
+        public void Shr() => Binary(">>");
+        public void Shr_Un() => Binary_Un("shr_un");
+        public void Clt() => Compare("<");
+        public void Clt_Un() => Compare_Un("<");
+        public void Ceq() => Compare("==");
+        public void Cgt() => Compare(">");
+        public void Cgt_Un() => Compare_Un(">");
 
         // Branch
 
@@ -855,7 +858,18 @@ namespace Natsu.Compiler
         public void Blt_Un() => BranchCompare("clt_un");
         public void Ble() => BranchCompare("cle");
         public void Ble_Un() => BranchCompare("cle_un");
-        public void Beq() => BranchCompare("ceq");
+
+        public void Beq()
+        {
+            var v2 = Stack.Pop();
+            var v1 = Stack.Pop();
+            var nextOp = (Instruction)Op.Operand;
+            Writer.Ident(Ident).WriteLine($"if ({v1.Expression} == {v2.Expression})");
+            Writer.Ident(Ident + 1).WriteLine($"goto {ILUtils.GetLabel(Method, nextOp, Block)};");
+            Writer.Ident(Ident).WriteLine("else");
+            Writer.Ident(Ident + 1).WriteLine($"goto {ILUtils.GetFallthroughLabel(Method, Op, Block)};");
+        }
+
         public void Bge() => BranchCompare("cge");
         public void Bge_Un() => BranchCompare("cge_un");
         public void Bgt() => BranchCompare("cgt");
@@ -865,51 +879,56 @@ namespace Natsu.Compiler
 
         // Conversion
 
-        public void Conv_I1() => Conversion(StackTypeCode.Int32, "i1");
-        public void Conv_I2() => Conversion(StackTypeCode.Int32, "i2");
-        public void Conv_I4() => Conversion(StackTypeCode.Int32, "i4");
-        public void Conv_I8() => Conversion(StackTypeCode.Int64, "i8");
-        public void Conv_I() => Conversion(StackTypeCode.NativeInt, "i");
-        public void Conv_R4() => Conversion(StackTypeCode.F, "r4");
-        public void Conv_R8() => Conversion(StackTypeCode.F, "r8");
-        public void Conv_U1() => Conversion(StackTypeCode.Int32, "u1");
-        public void Conv_U2() => Conversion(StackTypeCode.Int32, "u2");
-        public void Conv_U4() => Conversion(StackTypeCode.Int32, "u4");
-        public void Conv_U8() => Conversion(StackTypeCode.Int64, "u8");
-        public void Conv_U() => Conversion(StackTypeCode.NativeInt, "u");
-        public void Conv_Ovf_I1() => Conversion(StackTypeCode.Int32, "ovf_i1");
-        public void Conv_Ovf_I2() => Conversion(StackTypeCode.Int32, "ovf_i2");
-        public void Conv_Ovf_I4() => Conversion(StackTypeCode.Int32, "ovf_i4");
-        public void Conv_Ovf_I8() => Conversion(StackTypeCode.Int64, "ovf_i8");
-        public void Conv_Ovf_I() => Conversion(StackTypeCode.NativeInt, "ovf_i");
-        public void Conv_Ovf_U1() => Conversion(StackTypeCode.Int32, "ovf_u1");
-        public void Conv_Ovf_U2() => Conversion(StackTypeCode.Int32, "ovf_u2");
-        public void Conv_Ovf_U4() => Conversion(StackTypeCode.Int32, "ovf_u4");
-        public void Conv_Ovf_U8() => Conversion(StackTypeCode.Int64, "ovf_u8");
-        public void Conv_Ovf_U() => Conversion(StackTypeCode.NativeInt, "ovf_u");
-        public void Conv_Ovf_I1_Un() => Conversion(StackTypeCode.Int32, "ovf_i1_un");
-        public void Conv_Ovf_I2_Un() => Conversion(StackTypeCode.Int32, "ovf_i2_un");
-        public void Conv_Ovf_I4_Un() => Conversion(StackTypeCode.Int32, "ovf_i4_un");
-        public void Conv_Ovf_I8_Un() => Conversion(StackTypeCode.Int64, "ovf_i8_un");
-        public void Conv_Ovf_I_Un() => Conversion(StackTypeCode.NativeInt, "ovf_i_un");
-        public void Conv_Ovf_U1_Un() => Conversion(StackTypeCode.Int32, "ovf_u1_un");
-        public void Conv_Ovf_U2_Un() => Conversion(StackTypeCode.Int32, "ovf_u2_un");
-        public void Conv_Ovf_U4_Un() => Conversion(StackTypeCode.Int32, "ovf_u4_un");
-        public void Conv_Ovf_U8_Un() => Conversion(StackTypeCode.Int64, "ovf_u8_un");
-        public void Conv_Ovf_U_Un() => Conversion(StackTypeCode.NativeInt, "ovf_u_un");
+        public void Conv_I1() => Conversion(CorLibTypes.SByte, "i1");
+        public void Conv_I2() => Conversion(CorLibTypes.Int16, "i2");
+        public void Conv_I4() => Conversion(CorLibTypes.Int32, "i4");
+        public void Conv_I8() => Conversion(CorLibTypes.Int64, "i8");
+        public void Conv_I() => Conversion(CorLibTypes.IntPtr, "i");
+        public void Conv_R4() => Conversion(CorLibTypes.Single, "r4");
+        public void Conv_R8() => Conversion(CorLibTypes.Double, "r8");
+        public void Conv_U1() => Conversion(CorLibTypes.Byte, "u1");
+        public void Conv_U2() => Conversion(CorLibTypes.UInt16, "u2");
+        public void Conv_U4() => Conversion(CorLibTypes.UInt32, "u4");
+        public void Conv_U8() => Conversion(CorLibTypes.UInt64, "u8");
+        public void Conv_U() => Conversion(CorLibTypes.UIntPtr, "u");
+        public void Conv_Ovf_I1() => Conversion(CorLibTypes.SByte, "ovf_i1");
+        public void Conv_Ovf_I2() => Conversion(CorLibTypes.Int16, "ovf_i2");
+        public void Conv_Ovf_I4() => Conversion(CorLibTypes.Int32, "ovf_i4");
+        public void Conv_Ovf_I8() => Conversion(CorLibTypes.Int64, "ovf_i8");
+        public void Conv_Ovf_I() => Conversion(CorLibTypes.IntPtr, "ovf_i");
+        public void Conv_Ovf_U1() => Conversion(CorLibTypes.Byte, "ovf_u1");
+        public void Conv_Ovf_U2() => Conversion(CorLibTypes.UInt16, "ovf_u2");
+        public void Conv_Ovf_U4() => Conversion(CorLibTypes.UInt32, "ovf_u4");
+        public void Conv_Ovf_U8() => Conversion(CorLibTypes.UInt64, "ovf_u8");
+        public void Conv_Ovf_U() => Conversion(CorLibTypes.UIntPtr, "ovf_u");
+        public void Conv_Ovf_I1_Un() => Conversion(CorLibTypes.SByte, "ovf_i1_un");
+        public void Conv_Ovf_I2_Un() => Conversion(CorLibTypes.Int16, "ovf_i2_un");
+        public void Conv_Ovf_I4_Un() => Conversion(CorLibTypes.Int32, "ovf_i4_un");
+        public void Conv_Ovf_I8_Un() => Conversion(CorLibTypes.Int64, "ovf_i8_un");
+        public void Conv_Ovf_I_Un() => Conversion(CorLibTypes.IntPtr, "ovf_i_un");
+        public void Conv_Ovf_U1_Un() => Conversion(CorLibTypes.Byte, "ovf_u1_un");
+        public void Conv_Ovf_U2_Un() => Conversion(CorLibTypes.UInt16, "ovf_u2_un");
+        public void Conv_Ovf_U4_Un() => Conversion(CorLibTypes.UInt32, "ovf_u4_un");
+        public void Conv_Ovf_U8_Un() => Conversion(CorLibTypes.UInt64, "ovf_u8_un");
+        public void Conv_Ovf_U_Un() => Conversion(CorLibTypes.UIntPtr, "ovf_u_un");
 
         // Ldind
-        public void Ldind_I1() => Ldind(StackTypeCode.Int32, "i1");
-        public void Ldind_I2() => Ldind(StackTypeCode.Int32, "i2");
-        public void Ldind_I4() => Ldind(StackTypeCode.Int32, "i4");
-        public void Ldind_I8() => Ldind(StackTypeCode.Int64, "i8");
-        public void Ldind_R4() => Ldind(StackTypeCode.F, "r4");
-        public void Ldind_R8() => Ldind(StackTypeCode.F, "r8");
-        public void Ldind_I() => Ldind(StackTypeCode.NativeInt, "i");
-        public void Ldind_Ref() => Ldind(StackTypeCode.O, "ref");
-        public void Ldind_U1() => Ldind(StackTypeCode.Int32, "u1");
-        public void Ldind_U2() => Ldind(StackTypeCode.Int32, "u2");
-        public void Ldind_U4() => Ldind(StackTypeCode.Int32, "u4");
+        public void Ldind_I1() => Ldind(CorLibTypes.SByte, "i1");
+        public void Ldind_I2() => Ldind(CorLibTypes.Int16, "i2");
+        public void Ldind_I4() => Ldind(CorLibTypes.Int32, "i4");
+        public void Ldind_I8() => Ldind(CorLibTypes.Int64, "i8");
+        public void Ldind_R4() => Ldind(CorLibTypes.Single, "r4");
+        public void Ldind_R8() => Ldind(CorLibTypes.Double, "r8");
+        public void Ldind_I() => Ldind(CorLibTypes.IntPtr, "i");
+        public void Ldind_Ref()
+        {
+            var addr = Stack.Pop();
+            Stack.Push(addr.Type.TypeSig.Next, $"::natsu::ops::ldind_ref({addr.Expression})");
+        }
+
+        public void Ldind_U1() => Ldind(CorLibTypes.Byte, "u1");
+        public void Ldind_U2() => Ldind(CorLibTypes.UInt16, "u2");
+        public void Ldind_U4() => Ldind(CorLibTypes.UInt32, "u4");
 
         // Stind
         public void Stind_I1() => Stind("i1");
@@ -922,17 +941,23 @@ namespace Natsu.Compiler
         public void Stind_Ref() => Stind("ref");
 
         // Ldelem
-        public void Ldelem_I1() => Ldelem(StackTypeCode.Int32, "i1");
-        public void Ldelem_I2() => Ldelem(StackTypeCode.Int32, "i2");
-        public void Ldelem_I4() => Ldelem(StackTypeCode.Int32, "i4");
-        public void Ldelem_I8() => Ldelem(StackTypeCode.Int64, "i8");
-        public void Ldelem_R4() => Ldelem(StackTypeCode.F, "r4");
-        public void Ldelem_R8() => Ldelem(StackTypeCode.F, "r8");
-        public void Ldelem_I() => Ldelem(StackTypeCode.NativeInt, "i");
-        public void Ldelem_Ref() => Ldelem(StackTypeCode.O, "ref");
-        public void Ldelem_U1() => Ldelem(StackTypeCode.Int32, "u1");
-        public void Ldelem_U2() => Ldelem(StackTypeCode.Int32, "u2");
-        public void Ldelem_U4() => Ldelem(StackTypeCode.Int32, "u4");
+        public void Ldelem_I1() => Ldelem(CorLibTypes.SByte, "i1");
+        public void Ldelem_I2() => Ldelem(CorLibTypes.Int16, "i2");
+        public void Ldelem_I4() => Ldelem(CorLibTypes.Int32, "i4");
+        public void Ldelem_I8() => Ldelem(CorLibTypes.Int64, "i8");
+        public void Ldelem_R4() => Ldelem(CorLibTypes.Single, "r4");
+        public void Ldelem_R8() => Ldelem(CorLibTypes.Double, "r8");
+        public void Ldelem_I() => Ldelem(CorLibTypes.IntPtr, "i");
+        public void Ldelem_Ref()
+        {
+            var index = Stack.Pop();
+            var array = Stack.Pop();
+            var elemType = array.Type.TypeSig.Next;
+            Stack.Push(elemType.ToTypeDefOrRef(), $"{array.Expression}->at({index.Expression})");
+        }
+        public void Ldelem_U1() => Ldelem(CorLibTypes.Byte, "u1");
+        public void Ldelem_U2() => Ldelem(CorLibTypes.UInt16, "u2");
+        public void Ldelem_U4() => Ldelem(CorLibTypes.UInt32, "u4");
 
         // Stelem
         public void Stelem_I1() => Stelem("i1");
@@ -948,7 +973,7 @@ namespace Natsu.Compiler
         {
             var param = Op.GetParameter(Method.Parameters.ToList());
             var paramName = param.IsHiddenThisParameter ? "_this" : param.ToString();
-            Stack.Push(TypeUtils.GetStackType(param.Type), $"::natsu::stack_from({paramName})");
+            Stack.Push(TypeUtils.GetStackType(param.Type), $"{paramName}", computed: true);
         }
 
         public void Starg()
@@ -963,31 +988,35 @@ namespace Natsu.Compiler
         {
             var param = Op.GetParameter(Method.Parameters.ToList());
             var paramName = param.IsHiddenThisParameter ? "_this" : param.ToString();
-            Stack.Push(StackTypeCode.Ref, $"::natsu::ops::ref({paramName})");
+            Stack.Push(TypeUtils.GetStackType(new ByRefSig(param.Type)), $"::natsu::ops::ref({paramName})", computed: true);
         }
 
         public void LdcI4()
         {
             var value = Op.GetLdcI4Value();
-            Stack.Push(StackTypeCode.Int32, $"::natsu::stack::int32({TypeUtils.LiteralConstant(value)})");
+            Stack.Push(new StackType { Code = StackTypeCode.Int32, Name = "int32_t" },
+                $"{TypeUtils.LiteralConstant(value)}", computed: true);
         }
 
         public void Ldc_I8()
         {
             var value = (long)Op.Operand;
-            Stack.Push(StackTypeCode.Int64, $"::natsu::stack::int64({TypeUtils.LiteralConstant(value)})");
+            Stack.Push(new StackType { Code = StackTypeCode.Int64, Name = "int64_t" },
+                $"{TypeUtils.LiteralConstant(value)}", computed: true);
         }
 
         public void Ldc_R4()
         {
             var value = (float)Op.Operand;
-            Stack.Push(StackTypeCode.F, $"::natsu::stack::F({TypeUtils.LiteralConstant(value)})");
+            Stack.Push(new StackType { Code = StackTypeCode.F, Name = "float" },
+                $"{TypeUtils.LiteralConstant(value)}", computed: true);
         }
 
         public void Ldc_R8()
         {
             var value = (double)Op.Operand;
-            Stack.Push(StackTypeCode.F, $"::natsu::stack::F({TypeUtils.LiteralConstant(value)})");
+            Stack.Push(new StackType { Code = StackTypeCode.F, Name = "double" },
+                $"{TypeUtils.LiteralConstant(value)}", computed: true);
         }
 
         public void Call()
@@ -1022,7 +1051,7 @@ namespace Natsu.Compiler
             if (stackType.Code == StackTypeCode.Void)
                 Stack.Push(stackType, expr);
             else
-                Stack.Push(stackType, $"::natsu::stack_from({expr})");
+                Stack.Push(stackType, $"{expr}");
         }
 
         public void Callvirt()
@@ -1033,6 +1062,7 @@ namespace Natsu.Compiler
             var parasCount = method.Params.Count;
             for (int i = parasCount - 1; i >= 0; i--)
                 para.Add((method.Params[i], Stack.Pop()));
+            Stack.Compute();
             para.Add((TypeUtils.ThisType(member.DeclaringType), Stack.Pop()));
 
             var tGen = (member.DeclaringType as TypeSpec)?.TryGetGenericInstSig()?.GenericArguments.ToList()
@@ -1042,10 +1072,10 @@ namespace Natsu.Compiler
             string expr;
             if (Stack.Constrained != null)
             {
-                Stack.Push(StackTypeCode.O, $"::natsu::ops::box(*::natsu::stack_to<{TypeUtils.EscapeVariableTypeName(new ByRefSig(Stack.Constrained.ToTypeSig()))}>({para[0].src.Expression}))");
+                Stack.Push(para[0].destType.ToTypeDefOrRef(), $"::natsu::ops::box(*{para[0].src.Expression})");
                 para[0] = (para[0].destType, Stack.Pop());
 
-                expr = $"{para[0].src.Expression}.header().template vtable_as<typename {TypeUtils.EscapeTypeName(member.DeclaringType)}::VTable>()->{TypeUtils.EscapeMethodName(member)}({string.Join(", ", para.Select(x => CastExpression(x.destType, x.src, tGen)))})";
+                expr = $"::natsu::vtable<{TypeUtils.EscapeTypeName(Stack.Constrained)}>().{TypeUtils.EscapeMethodName(member)}({string.Join(", ", para.Select(x => CastExpression(x.destType, x.src, tGen)))})";
 
                 Stack.Constrained = null;
             }
@@ -1058,12 +1088,33 @@ namespace Natsu.Compiler
             if (stackType.Code == StackTypeCode.Void)
                 Stack.Push(stackType, expr);
             else
-                Stack.Push(stackType, $"::natsu::stack_from({expr})");
+                Stack.Push(stackType, $"{expr}");
         }
 
         private static string CastExpression(TypeSig destType, StackEntry src, IList<TypeSig> genArgs = null)
         {
-            return $"::natsu::stack_to<{TypeUtils.EscapeVariableTypeName(destType, hasGen: 1, genArgs: genArgs)}>({src.Expression})";
+            return $"{src.Expression}";
+        }
+
+        private static string MakeUnsignedExpression(StackEntry src)
+        {
+            // Try parse literal
+            var exp = src.Expression;
+            if (uint.TryParse(exp, out var u4))
+            {
+                return $"{u4}U";
+            }
+            else if (ulong.TryParse(exp, out var u8))
+            {
+                return $"{u8}ULL";
+            }
+            else
+            {
+                if (src.Type.Code == StackTypeCode.F)
+                    return src.Expression;
+                else
+                    return $"::natsu::ops::unsign({src.Expression})";
+            }
         }
 
         public void Nop()
@@ -1098,13 +1149,13 @@ namespace Natsu.Compiler
         public void Ldloc()
         {
             var local = Op.GetLocal(Method.Body.Variables.ToList());
-            Stack.Push(TypeUtils.GetStackType(local.Type), $"::natsu::stack_from({TypeUtils.GetLocalName(local, Method)})");
+            Stack.Push(TypeUtils.GetStackType(local.Type), $"{TypeUtils.GetLocalName(local, Method)}", computed: true);
         }
 
         public void Ldloca()
         {
             var local = Op.GetLocal(Method.Body.Variables.ToList());
-            Stack.Push(StackTypeCode.Ref, $"::natsu::ops::ref({TypeUtils.GetLocalName(local, Method)})");
+            Stack.Push(TypeUtils.GetStackType(new ByRefSig(local.Type)), $"::natsu::ops::ref({TypeUtils.GetLocalName(local, Method)})", computed: true);
         }
 
         public void Stloc()
@@ -1136,14 +1187,28 @@ namespace Natsu.Compiler
         {
             var v2 = Stack.Pop();
             var v1 = Stack.Pop();
-            Stack.Push(v1.Type, $"::natsu::ops::{op}_({v1.Expression}, {v2.Expression})");
+            Stack.Push(v1.Type, $"({v1.Expression} {op} {v2.Expression})");
+        }
+
+        public void Binary_Un(string op)
+        {
+            var v2 = Stack.Pop();
+            var v1 = Stack.Pop();
+            Stack.Push(v1.Type, $"({MakeUnsignedExpression(v1)} {op} {MakeUnsignedExpression(v2)})");
         }
 
         public void Compare(string op)
         {
             var v2 = Stack.Pop();
             var v1 = Stack.Pop();
-            Stack.Push(StackTypeCode.Int32, $"::natsu::ops::{op}_({v1.Expression}, {v2.Expression})");
+            Stack.Push(CorLibTypes.Boolean, $"({v1.Expression} {op} {v2.Expression})");
+        }
+
+        public void Compare_Un(string op)
+        {
+            var v2 = Stack.Pop();
+            var v1 = Stack.Pop();
+            Stack.Push(CorLibTypes.Boolean, $"({MakeUnsignedExpression(v1)} {op} {MakeUnsignedExpression(v2)})");
         }
 
         private void BranchUnconditional(int ident, Instruction op)
@@ -1175,7 +1240,8 @@ namespace Natsu.Compiler
         public void Ldstr()
         {
             var value = (string)Op.Operand;
-            Stack.Push(StackTypeCode.O, $"::natsu::stack_from(::{ModuleName}::user_string_{UserStrings.Count}.get())");
+            Stack.Push(new StackType { Code = StackTypeCode.O, Name = "::natsu::gc_obj_ref<::System_Private_CoreLib::System::String>" },
+                $"::{ ModuleName}::user_string_{UserStrings.Count}.get()");
             UserStrings.Add(value);
         }
 
@@ -1187,7 +1253,7 @@ namespace Natsu.Compiler
                 : "::natsu::static_holder<typename" + TypeUtils.EscapeTypeName(field.DeclaringType) + "::Static>::get()." + TypeUtils.EscapeIdentifier(field.Name);
             var fieldType = field.FieldSig.Type;
 
-            Stack.Push(TypeUtils.GetStackType(fieldType), $"::natsu::stack_from({expr})");
+            Stack.Push(TypeUtils.GetStackType(fieldType), $"{expr}");
         }
 
         public void Ldfld()
@@ -1195,10 +1261,10 @@ namespace Natsu.Compiler
             var target = Stack.Pop();
             var field = (IField)Op.Operand;
             var thisType = TypeUtils.ThisType(field.DeclaringType);
-            string expr = $"::natsu::ops::access<{TypeUtils.EscapeVariableTypeName(thisType)}>({target.Expression})->" + TypeUtils.EscapeIdentifier(field.Name);
+            string expr = $"{target.Expression}->" + TypeUtils.EscapeIdentifier(field.Name);
             var fieldType = field.FieldSig.Type;
 
-            Stack.Push(TypeUtils.GetStackType(fieldType), $"::natsu::stack_from({expr})");
+            Stack.Push(TypeUtils.GetStackType(fieldType), $"{expr}");
         }
 
         public void Ldflda()
@@ -1206,24 +1272,26 @@ namespace Natsu.Compiler
             var target = Stack.Pop();
             var field = (IField)Op.Operand;
             var thisType = TypeUtils.ThisType(field.DeclaringType);
+            var fieldType = field.FieldSig.Type;
             if (TypeUtils.IsCppBasicType(field.DeclaringType))
             {
-                Stack.Push(StackTypeCode.Ref, $"::natsu::ops::ref({target.Expression})");
+                Stack.Push(TypeUtils.GetStackType(new ByRefSig(fieldType)), $"::natsu::ops::ref({target.Expression})", computed: true);
             }
             else
             {
-                string expr = $"::natsu::stack_to<{TypeUtils.EscapeVariableTypeName(thisType)}>({target.Expression})->" + TypeUtils.EscapeIdentifier(field.Name);
-                Stack.Push(StackTypeCode.Ref, $"::natsu::ops::ref({expr})");
+                string expr = $"{target.Expression}->" + TypeUtils.EscapeIdentifier(field.Name);
+                Stack.Push(TypeUtils.GetStackType(new ByRefSig(fieldType)), $"::natsu::ops::ref({expr})", computed: true);
             }
         }
 
         public void Ldsflda()
         {
             var field = (IField)Op.Operand;
+            var fieldType = field.FieldSig.Type;
             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})");
+            Stack.Push(TypeUtils.GetStackType(new ByRefSig(fieldType)), $"::natsu::ops::ref({expr})", computed: true);
         }
 
         public void Stsfld()
@@ -1237,7 +1305,7 @@ namespace Natsu.Compiler
                 : "::natsu::static_holder<typename" + TypeUtils.EscapeTypeName(field.DeclaringType) + "::Static>::get()." + TypeUtils.EscapeIdentifier(field.Name);
             var fieldType = field.FieldSig.Type;
 
-            Writer.Ident(Ident).WriteLine($"{expr} = ::natsu::stack_to<{TypeUtils.EscapeVariableTypeName(fieldType)}>({value.Expression});");
+            Writer.Ident(Ident).WriteLine($"{expr} = {value.Expression};");
         }
 
         public void Stfld()
@@ -1246,17 +1314,17 @@ namespace Natsu.Compiler
             var target = Stack.Pop();
             var field = (IField)Op.Operand;
             var thisType = TypeUtils.ThisType(field.DeclaringType);
-            string expr = $"::natsu::stack_to<{TypeUtils.EscapeVariableTypeName(thisType)}>({target.Expression})->" + TypeUtils.EscapeIdentifier(field.Name);
+            string expr = $"{target.Expression}->" + TypeUtils.EscapeIdentifier(field.Name);
             var fieldType = field.FieldSig.Type;
 
-            Writer.Ident(Ident).WriteLine($"{expr} = ::natsu::stack_to<{TypeUtils.EscapeVariableTypeName(fieldType)}>({value.Expression});");
+            Writer.Ident(Ident).WriteLine($"{expr} = {value.Expression};");
         }
 
         public void Newarr()
         {
             var type = (ITypeDefOrRef)Op.Operand;
             var len = Stack.Pop();
-            Stack.Push(StackTypeCode.O, $"::natsu::stack_from(::natsu::gc_new_array<{TypeUtils.EscapeTypeName(type)}>({len.Expression}))");
+            Stack.Push(new SZArraySig(type.ToTypeSig()).ToTypeDefOrRef(), $"::natsu::gc_new_array<{TypeUtils.EscapeTypeName(type)}>({len.Expression})");
         }
 
         public void Initobj()
@@ -1278,14 +1346,14 @@ namespace Natsu.Compiler
             para.Reverse();
             var genSig = member.DeclaringType.TryGetGenericInstSig();
             var expr = $"::natsu::ops::newobj<{TypeUtils.EscapeTypeName(member.DeclaringType, cppBasicType: true)}>({string.Join(", ", para.Select(x => CastExpression(x.destType, x.src, genSig?.GenericArguments)))})";
-            Stack.Push(StackTypeCode.O, expr);
+            Stack.Push(TypeUtils.GetStackType(member.DeclaringType.ToTypeSig()), expr);
         }
 
         public void Ldobj()
         {
             var type = (ITypeDefOrRef)Op.Operand;
             var addr = Stack.Pop();
-            Stack.Push(StackTypeCode.O, $"::natsu::ops::ldobj<{TypeUtils.EscapeVariableTypeName(type)}>({addr.Expression})");
+            Stack.Push(TypeUtils.GetStackType(type.ToTypeSig()), $"::natsu::ops::ldobj<{TypeUtils.EscapeVariableTypeName(type)}>({addr.Expression})");
         }
 
         public void Stobj()
@@ -1306,49 +1374,52 @@ namespace Natsu.Compiler
         {
             var type = (ITypeDefOrRef)Op.Operand;
             var obj = Stack.Pop();
-            Stack.Push(StackTypeCode.O, $"::natsu::ops::isinst<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({obj.Expression})");
+            Stack.Push(TypeUtils.GetStackType(type.ToTypeSig()), $"::natsu::ops::isinst<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({obj.Expression})");
         }
 
         public void Unbox_Any()
         {
             var type = (ITypeDefOrRef)Op.Operand;
             var obj = Stack.Pop();
-            Stack.Push(StackTypeCode.O, $"::natsu::ops::unbox_any<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({obj.Expression})");
+            Stack.Push(TypeUtils.GetStackType(type.ToTypeSig()), $"::natsu::ops::unbox_any<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({obj.Expression})");
         }
 
         public void Unbox()
         {
             var type = (ITypeDefOrRef)Op.Operand;
             var obj = Stack.Pop();
-            Stack.Push(StackTypeCode.Ref, $"::natsu::ops::unbox<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({obj.Expression})");
+            Stack.Push(TypeUtils.GetStackType(new ByRefSig(type.ToTypeSig())), $"::natsu::ops::unbox<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({obj.Expression})");
         }
 
         public void Castclass()
         {
             var type = (ITypeDefOrRef)Op.Operand;
             var obj = Stack.Pop();
-            Stack.Push(StackTypeCode.O, $"::natsu::ops::castclass<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({obj.Expression})");
+            Stack.Push(TypeUtils.GetStackType(type.ToTypeSig()), $"::natsu::ops::castclass<{TypeUtils.EscapeTypeName(type, cppBasicType: true)}>({obj.Expression})");
         }
 
         public void Ldlen()
         {
             var target = Stack.Pop();
-            Stack.Push(StackTypeCode.NativeInt, $"::natsu::ops::ldlen({target.Expression})");
+            Stack.Push(CorLibTypes.UIntPtr, $"{target.Expression}->length()");
         }
 
         public void Localloc()
         {
             var size = Stack.Pop();
-            Stack.Push(StackTypeCode.NativeInt, $"::natsu::ops::localloc({size.Expression})");
+            Stack.Push(CorLibTypes.UIntPtr, $"::natsu::ops::localloc({size.Expression})");
         }
 
-        private void Conversion(StackTypeCode stackType, string type)
+        private void Conversion(TypeSig stackType, string type)
         {
             var value = Stack.Pop();
-            Stack.Push(stackType, $"::natsu::ops::conv_{type}({value.Expression})");
+            var expr = value.Expression;
+            if (TypeUtils.IsRefOrPtr(value.Type.Code))
+                expr += ".ptr_";
+            Stack.Push(stackType, $"static_cast<{TypeUtils.EscapeVariableTypeName(stackType)}>({expr})");
         }
 
-        private void Ldind(StackTypeCode stackType, string type)
+        private void Ldind(TypeSig stackType, string type)
         {
             var addr = Stack.Pop();
             Stack.Push(stackType, $"::natsu::ops::ldind_{type}({addr.Expression})");
@@ -1361,11 +1432,11 @@ namespace Natsu.Compiler
             Writer.Ident(Ident).WriteLine($"::natsu::ops::stind_{type}({addr.Expression}, {value.Expression});");
         }
 
-        private void Ldelem(StackTypeCode stackType, string type)
+        private void Ldelem(TypeSig stackType, string type)
         {
             var index = Stack.Pop();
             var array = Stack.Pop();
-            Stack.Push(stackType, $"::natsu::ops::ldelem_{type}({array.Expression}, {index.Expression})");
+            Stack.Push(stackType, $"{array.Expression}->at({index.Expression})");
         }
 
         private void Stelem(string type)
@@ -1373,7 +1444,8 @@ namespace Natsu.Compiler
             var value = Stack.Pop();
             var index = Stack.Pop();
             var array = Stack.Pop();
-            Writer.Ident(Ident).WriteLine($"::natsu::ops::stelem_{type}({array.Expression}, {index.Expression}, {value.Expression});");
+            //Writer.Ident(Ident).WriteLine($"::natsu::ops::stelem_{type}({array.Expression}, {index.Expression}, {value.Expression});");
+            Writer.Ident(Ident).WriteLine($"{array.Expression}->at({index.Expression}) = {value.Expression};");
         }
 
         public void Ldelem()
@@ -1398,25 +1470,24 @@ namespace Natsu.Compiler
             var type = (ITypeDefOrRef)Op.Operand;
             var index = Stack.Pop();
             var array = Stack.Pop();
-            Stack.Push(StackTypeCode.Ref, $"::natsu::ops::ldelema<{TypeUtils.EscapeTypeName(type)}>({array.Expression}, {index.Expression})");
+            Stack.Push(TypeUtils.GetStackType(new ByRefSig(type.ToTypeSig())), $"::natsu::ops::ldelema<{TypeUtils.EscapeTypeName(type)}>({array.Expression}, {index.Expression})");
         }
 
         public void Box()
         {
             var type = (ITypeDefOrRef)Op.Operand;
             var value = Stack.Pop();
-            Stack.Push(StackTypeCode.O, $"::natsu::ops::box({CastExpression(type.ToTypeSig(), value)})");
+            Stack.Push(new StackType { Code = StackTypeCode.O, Name = "::natsu::gc_obj_ref<>" }, $"::natsu::ops::box({CastExpression(type.ToTypeSig(), value)})");
         }
 
         public void Ldnull()
         {
-            Stack.Push(StackTypeCode.O, $"::natsu::stack::null");
+            Stack.Push(new StackType { Code = StackTypeCode.O, Name = "::natsu::gc_obj_ref<>" }, $"::natsu::null");
         }
 
         public void Dup()
         {
-            var value = Stack.Peek();
-            Stack.Push(value);
+            Stack.Dup();
         }
 
         public void Ldftn()
@@ -1439,7 +1510,7 @@ namespace Natsu.Compiler
                 expr = $"{ TypeUtils.EscapeTypeName(member.DeclaringType)}::{TypeUtils.EscapeMethodName(member, hasParamType: false)}";
             }
 
-            Stack.Push(StackTypeCode.NativeInt, $"::natsu::ops::ldftn({expr})");
+            Stack.Push(new StackType { Code = StackTypeCode.NativeInt, Name = "uintptr_t" }, $"::natsu::ops::ldftn({expr})");
         }
 
         public void Ldvirtftn()
@@ -1461,7 +1532,7 @@ namespace Natsu.Compiler
                 expr = $"{obj.Expression}.header().template vtable_as<typename {TypeUtils.EscapeTypeName(member.DeclaringType)}::VTable>()->{TypeUtils.EscapeMethodName(member)}";
             }
 
-            Stack.Push(StackTypeCode.NativeInt, $"::natsu::ops::ldftn({expr})");
+            Stack.Push(new StackType { Code = StackTypeCode.NativeInt, Name = "uintptr_t" }, $"::natsu::ops::ldftn({expr})");
         }
 
         public void Switch()
@@ -1483,7 +1554,7 @@ namespace Natsu.Compiler
         public void Sizeof()
         {
             var type = (ITypeDefOrRef)Op.Operand;
-            Stack.Push(StackTypeCode.Int32, $"::natsu::ops::Sizeof<{TypeUtils.EscapeTypeName(type)}>()");
+            Stack.Push(new StackType { Code = StackTypeCode.Int32, Name = "int32_t" }, $"::natsu::ops::Sizeof<{TypeUtils.EscapeTypeName(type)}>()");
         }
     }
 }

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

@@ -1023,7 +1023,7 @@ namespace Natsu.Compiler
 
             }
 
-            var importer = new ILImporter(method, writer, ident) { UserStrings = _userStrings, ModuleName = TypeUtils.EscapeModuleName(_module.Assembly) };
+            var importer = new ILImporter(_corLibTypes, method, writer, ident) { UserStrings = _userStrings, ModuleName = TypeUtils.EscapeModuleName(_module.Assembly) };
             importer.ImportNormalBlocks();
             importer.ImportExceptionBlocks();
             importer.Gencode();

+ 52 - 28
src/Natsu.Compiler/TypeUtils.cs

@@ -111,7 +111,7 @@ namespace Natsu.Compiler
                     throw new NotSupportedException();
             }
 
-            return new StackType { Code = code, Name = EscapeVariableTypeName(type) };
+            return new StackType { Code = code, Name = EscapeVariableTypeName(type), TypeSig = type };
         }
 
         public static TypeSig ThisType(ITypeDefOrRef type)
@@ -679,15 +679,19 @@ namespace Natsu.Compiler
         {
             var text = value switch
             {
-                char i => ((ushort)i).ToString(),
-                byte i => i.ToString(),
-                sbyte i => i.ToString(),
-                ushort i => i.ToString(),
-                short i => i.ToString(),
-                uint i => i.ToString(),
-                int i => i.ToString(),
+                char i => char.IsLetterOrDigit(i) || char.IsSymbol(i) ? $"u'{i.ToString()}'" : $"u'\\x{((ushort)i).ToString("x")}'",
+                byte i => $"uint8_t({i.ToString()})",
+                sbyte i => $"int8_t({i.ToString()})",
+                ushort i => $"uint16_t({i.ToString()})",
+                short i => $"int16_t({i.ToString()})",
+                uint i => i.ToString() + "U",
+                int i => i == int.MinValue
+                    ? "int32_t(0x" + Unsafe.As<int, uint>(ref i).ToString("X") + ") /* " + i.ToString() + "*/"
+                    : i.ToString(),
                 ulong i => i.ToString() + "ULL",
-                long i => "::natsu::to_int64(0x" + Unsafe.As<long, ulong>(ref i).ToString("X") + ") /* " + i.ToString() + "*/",
+                long i => i == long.MinValue
+                    ? "int64_t(0x" + Unsafe.As<long, ulong>(ref i).ToString("X") + ") /* " + i.ToString() + "*/"
+                    : i.ToString() + "LL",
                 float i => EscapeFloat(i),
                 double i => EscapeFloat(i),
 
@@ -767,25 +771,28 @@ namespace Natsu.Compiler
 
         public static string EscapeStackTypeName(StackType stackType)
         {
-            switch (stackType.Code)
-            {
-                case StackTypeCode.Int32:
-                    return "::natsu::stack::int32";
-                case StackTypeCode.Int64:
-                    return "::natsu::stack::int64";
-                case StackTypeCode.NativeInt:
-                    return "::natsu::stack::native_int";
-                case StackTypeCode.F:
-                    return "::natsu::stack::F";
-                case StackTypeCode.O:
-                    return "::natsu::stack::O";
-                case StackTypeCode.Ref:
-                    return "::natsu::stack::Ref";
-                default:
-                    if (string.IsNullOrEmpty(stackType.Name))
-                        throw new NotSupportedException(stackType.ToString());
-                    return stackType.Name;
-            }
+            if (!string.IsNullOrEmpty(stackType.Name))
+                return stackType.Name;
+
+            throw new NotSupportedException(stackType.ToString());
+
+            //switch (stackType.Code)
+            //{
+            //    case StackTypeCode.Int32:
+            //        return "::natsu::stack::int32";
+            //    case StackTypeCode.Int64:
+            //        return "::natsu::stack::int64";
+            //    case StackTypeCode.NativeInt:
+            //        return "::natsu::stack::native_int";
+            //    case StackTypeCode.F:
+            //        return "::natsu::stack::F";
+            //    case StackTypeCode.O:
+            //        return "::natsu::stack::O";
+            //    case StackTypeCode.Ref:
+            //        return "::natsu::stack::Ref";
+            //    default:
+            //        throw new NotSupportedException(stackType.ToString());
+            //}
         }
 
         public static string EscapeCSharpTypeName(string name)
@@ -872,5 +879,22 @@ namespace Natsu.Compiler
 
             return localName ?? $"_l{local.Index}";
         }
+
+        public static bool IsRefOrPtr(StackTypeCode type)
+        {
+            switch (type)
+            {
+                case StackTypeCode.Int32:
+                case StackTypeCode.Int64:
+                case StackTypeCode.NativeInt:
+                case StackTypeCode.F:
+                    return false;
+                case StackTypeCode.O:
+                case StackTypeCode.Ref:
+                    return true;
+                default:
+                    throw new NotSupportedException();
+            }
+        }
     }
 }