changeset 32261:6d2f6ca0996f

VM fix unwind table for ignored outputs Exception in nested expression erronously executed opcode CLEAR_IGNORE_OUTPUT when unwinding. E.g. '[~, a] = deal (error("qwe"), 1)'; * parse-tree/pt-bytecode-walk.cc: Set proper instruction offset in unwind table * parse-tree/pt-bytecode-walk.h: New field * test/compile/bytecode_multi_assign.m: Update tests
author Petter T.
date Wed, 09 Aug 2023 12:57:05 +0200
parents 5d9311556111
children 7bb3358d89ae
files libinterp/parse-tree/pt-bytecode-walk.cc libinterp/parse-tree/pt-bytecode-walk.h test/compile/bytecode_multi_assign.m
diffstat 3 files changed, 29 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-bytecode-walk.cc	Wed Aug 09 12:56:03 2023 +0200
+++ b/libinterp/parse-tree/pt-bytecode-walk.cc	Wed Aug 09 12:57:05 2023 +0200
@@ -2474,6 +2474,13 @@
 
   rhs->accept (*this); // Walks rhs for NARGOUT elements
 
+  if (m_pending_ignore_outputs)
+    {
+      // The outer expression in rhs should have set m_ignored_ip_start to its ip offset.
+      CHECK (m_ignored_ip_start);
+      UNWIND (D.m_idx_unwind).m_ip_start = m_ignored_ip_start;
+    }
+
   if (DEPTH () != 1)
     TODO ("Only root multi assignment supported now");
 
@@ -2512,6 +2519,7 @@
     {
       m_pending_ignore_outputs = 0;
       m_v_ignored.clear ();
+      m_ignored_ip_start = 0;
     }
 
   POP_NARGOUT ();
@@ -3669,6 +3677,7 @@
           PUSH_CODE (m_ignored_of_total);
           for (int i : m_v_ignored)
             PUSH_CODE (i);
+          m_ignored_ip_start = CODE_SIZE (); // visit_multi_assignment () need the code offset to set the proper range for the unwind protect
         }
 
       if (id.is_postfix_indexed ())
@@ -4308,6 +4317,7 @@
       PUSH_CODE (m_ignored_of_total);
       for (int i : m_v_ignored)
         PUSH_CODE (i);
+      m_ignored_ip_start = CODE_SIZE (); // visit_multi_assignment () need the code offset to set the proper range for the unwind protect
     }
 
   int loc_id = N_LOC ();
@@ -4574,6 +4584,7 @@
       PUSH_CODE (m_ignored_of_total);
       for (int i : m_v_ignored)
         PUSH_CODE (i);
+      m_ignored_ip_start = CODE_SIZE (); // visit_multi_assignment () need the code offset to set the proper range for the unwind protect        
     }
 
   int nargout = NARGOUT ();
--- a/libinterp/parse-tree/pt-bytecode-walk.h	Wed Aug 09 12:56:03 2023 +0200
+++ b/libinterp/parse-tree/pt-bytecode-walk.h	Wed Aug 09 12:57:05 2023 +0200
@@ -184,6 +184,7 @@
     bool m_pending_ignore_outputs = false;
     int m_ignored_of_total = 0;
     std::vector<int> m_v_ignored;
+    int m_ignored_ip_start = 0;
 
     //
     bool m_is_folding = false;
--- a/test/compile/bytecode_multi_assign.m	Wed Aug 09 12:56:03 2023 +0200
+++ b/test/compile/bytecode_multi_assign.m	Wed Aug 09 12:57:05 2023 +0200
@@ -46,6 +46,14 @@
   __printf_assert__ ("%d ", C{1});
   __printf_assert__ ("%d ", C{2});
   __printf_assert__ ("%d ", D);
+
+  % Check that opcodes SET_IGNORE_OUTPUTS and CLEAR_IGNORE_OUTPUTS
+  % does not mess up if a nested expression throws before SET_IGNORE_OUTPUTS
+  % is executed.
+  try
+    [~, b] = bar (baz_throws ());
+  catch
+  end
 end
 
 function [a,b,c,d] = foo ()
@@ -54,3 +62,12 @@
   c = 3;
   d = 4;
 end
+
+function [a b] = bar (c)
+  a = 1;
+  b = 0;
+end
+
+function a = baz_throws ()
+  error ("qwe");
+end
\ No newline at end of file