Просмотр исходного кода

Workaround for msvc lambda capture

Guo Hui 6 лет назад
Родитель
Сommit
c5354bc969
3 измененных файлов с 46 добавлено и 32 удалено
  1. 6 12
      src/Native/natsu.typedef.h
  2. 39 19
      src/Natsu.Compiler/ILImporter.cs
  3. 1 1
      src/Natsu.Compiler/Program.cs

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

@@ -256,6 +256,12 @@ public:
     {
     }
 
+    clr_volatile &operator=(const clr_volatile<T> &other) noexcept
+    {
+        value_.store(other.load(), std::memory_order_release);
+        return *this;
+    }
+
     clr_volatile &operator=(const T &other) noexcept
     {
         value_.store(other, std::memory_order_release);
@@ -648,24 +654,12 @@ constexpr bool operator==(std::nullptr_t, const gc_obj_ref<T> &rhs) noexcept
     return !rhs.ptr_;
 }
 
-template <class T>
-constexpr bool operator>(const gc_obj_ref<T> &lhs, std::nullptr_t) noexcept
-{
-    return lhs.ptr_;
-}
-
 template <class T, class U>
 constexpr bool operator<(const gc_ptr<T> &lhs, const gc_ptr<U> &rhs) noexcept
 {
     return reinterpret_cast<uintptr_t>(lhs.ptr_) < reinterpret_cast<uintptr_t>(rhs.ptr_);
 }
 
-template <class T>
-constexpr bool operator<(const gc_ptr<T> &lhs, uintptr_t rhs) noexcept
-{
-    return reinterpret_cast<uintptr_t>(lhs.ptr_) < rhs;
-}
-
 template <class T>
 constexpr bool operator<(uintptr_t lhs, const gc_ptr<T> &rhs) noexcept
 {

+ 39 - 19
src/Natsu.Compiler/ILImporter.cs

@@ -17,7 +17,6 @@ namespace Natsu.Compiler
         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;
         private int _blockId;
@@ -170,21 +169,24 @@ namespace Natsu.Compiler
         internal void Gencode()
         {
             var visited = new HashSet<BasicBlock>();
-            VisitBlock(_ident, _headBlock, visited);
+            var spills = new List<SpillSlot>();
+            VisitBlock(_ident, _headBlock, visited, spills);
+            WriteSpills(spills, _writer, _ident);
+            visited.Clear();
+            VisitBlockText(_headBlock, _writer, visited);
+        }
 
+        private void WriteSpills(List<SpillSlot> spills, TextWriter writer, int ident)
+        {
             var spillsName = new HashSet<string>();
             // spills
-            foreach (var spill in _spillSlots.Distinct())
+            foreach (var spill in spills.Distinct())
             {
                 if (spillsName.Add(spill.Name))
-                    _writer.Ident(_ident).WriteLine($"{TypeUtils.EscapeStackTypeName(spill.Entry.Type)} {spill.Name};");
+                    writer.Ident(ident).WriteLine($"{TypeUtils.EscapeStackTypeName(spill.Entry.Type)} {spill.Name};");
             }
-
-            visited.Clear();
-            VisitBlockText(_headBlock, _writer, visited);
         }
 
-
         private void VisitBlockText(BasicBlock block, TextWriter writer, HashSet<BasicBlock> visited)
         {
             var blocks = new List<BasicBlock>();
@@ -207,7 +209,7 @@ namespace Natsu.Compiler
             }
         }
 
-        private void VisitBlock(int ident, BasicBlock block, HashSet<BasicBlock> visited, StringWriter writer = null, EvaluationStack stack = null)
+        private void VisitBlock(int ident, BasicBlock block, HashSet<BasicBlock> visited, List<SpillSlot> spills, StringWriter writer = null, EvaluationStack stack = null)
         {
             visited.Add(block);
 
@@ -241,8 +243,20 @@ namespace Natsu.Compiler
                         instW.Ident(ident).WriteLine("{");
                         ident += 1;
                         stack.Ident = ident;
-                        instW.Ident(ident).WriteLine("auto _scope_finally = natsu::make_finally([&]{");
-                        VisitBlock(ident + 1, tryEnter.Value.HeadBlock, new HashSet<BasicBlock>(), stack: tryEnterStack);
+                        var captures = new List<string>();
+                        // locals
+                        foreach (var local in _method.Body.Variables)
+                            captures.Add("&" + TypeUtils.GetLocalName(local, _method));
+                        foreach(var param in _method.Parameters)
+                        {
+                            var paramName = param.IsHiddenThisParameter ? "_this" : param.ToString();
+                            captures.Add("&" + paramName);
+                        }
+
+                        instW.Ident(ident).WriteLine($"auto _scope_finally = natsu::make_finally([{string.Join(", ", captures)}]{{");
+                        var finallySpills = new List<SpillSlot>();
+                        VisitBlock(ident + 1, tryEnter.Value.HeadBlock, new HashSet<BasicBlock>(), finallySpills, stack: tryEnterStack);
+                        WriteSpills(finallySpills, instW, ident + 1);
                         VisitBlockText(tryEnter.Value.HeadBlock, instW, visited);
                         instW.Ident(ident).WriteLine("});");
                         tryEnter.Value.EnterProcessed = true;
@@ -283,7 +297,7 @@ namespace Natsu.Compiler
             // export spills
             while (block.Next.Count != 0 && !stack.Empty)
             {
-                var spill = AddSpillSlot(slotIndex++, stack.Pop(), block);
+                var spill = AddSpillSlot(slotIndex++, stack.Pop(), block, spills);
                 writer.Ident(ident).WriteLine($"{spill.Name} = {spill.Entry.Expression};");
                 block.Spills.Add(spill);
             }
@@ -296,15 +310,15 @@ namespace Natsu.Compiler
             foreach (var next in block.Next)
             {
                 if (!visited.Contains(next))
-                    VisitBlock(ident, next, visited);
+                    VisitBlock(ident, next, visited, spills);
             }
         }
 
-        private SpillSlot AddSpillSlot(int index, StackEntry stackEntry, BasicBlock block)
+        private SpillSlot AddSpillSlot(int index, StackEntry stackEntry, BasicBlock block, List<SpillSlot> spills)
         {
             if (block.Next != null)
             {
-                foreach (var slot in _spillSlots)
+                foreach (var slot in spills)
                 {
                     if (slot.Next != block.Next && slot.Index == index)
                     {
@@ -313,7 +327,7 @@ namespace Natsu.Compiler
                             if (block.Next.Contains(next))
                             {
                                 var newSlot = new SpillSlot { Index = slot.Index, Name = slot.Name, Entry = stackEntry, Next = block.Next };
-                                _spillSlots.Add(newSlot);
+                                spills.Add(newSlot);
                                 return newSlot;
                             }
                         }
@@ -323,7 +337,7 @@ namespace Natsu.Compiler
 
             {
                 var slot = new SpillSlot { Index = index, Name = "_s" + _nextSpillSlot++.ToString(), Entry = stackEntry, Next = block.Next };
-                _spillSlots.Add(slot);
+                spills.Add(slot);
                 return slot;
             }
         }
@@ -1310,14 +1324,20 @@ namespace Natsu.Compiler
         {
             var v2 = Stack.Pop();
             var v1 = Stack.Pop();
-            Stack.Push(CorLibTypes.Boolean, $"({v1.Expression} {op} {v2.Expression})");
+            if (op == ">" && v2.Type.Name == "std::nullptr_t")
+                Stack.Push(CorLibTypes.Boolean, $"bool({v1.Expression})");
+            else
+                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)})");
+            if (op == ">" && v2.Type.Name == "std::nullptr_t")
+                Stack.Push(CorLibTypes.Boolean, $"bool({v1.Expression})");
+            else
+                Stack.Push(CorLibTypes.Boolean, $"({MakeUnsignedExpression(v1)} {op} {MakeUnsignedExpression(v2)})");
         }
 
         private void BranchUnconditional(int ident, Instruction op)

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

@@ -72,7 +72,7 @@ namespace Natsu.Compiler
             using (var sha256 = SHA256.Create())
             {
                 digest = Convert.ToBase64String(sha256.ComputeHash(File.ReadAllBytes(_module.Location)));
-#if true
+#if false
                 if (HasOutputUptodate(Path.Combine(outputPath, $"{_module.Assembly.Name}.h"), digest))
                     return;
 #endif