changeset 18325:2a8243d8327a

jit compiler: Add support for the do_until statement * libinterp/corefcn/pt-jit.cc (jit_convert::visit_do_until_command): Compile do_until loop. * libinterp/corefcn/pt-eval.cc (tree_evaluator::visit_do_until_command): Use jit compiler if available. * test/jit.tst: do until tests added
author LYH <lyh.kernel@gmail.com>
date Fri, 27 Dec 2013 13:01:39 +0100
parents 7e425ca58e9c
children 421bed6994f0
files libinterp/corefcn/pt-jit.cc libinterp/parse-tree/pt-eval.cc test/jit.tst
diffstat 3 files changed, 90 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/pt-jit.cc	Fri Aug 23 11:33:21 2013 +0800
+++ b/libinterp/corefcn/pt-jit.cc	Fri Dec 27 13:01:39 2013 +0100
@@ -903,9 +903,66 @@
 }
 
 void
-jit_convert::visit_do_until_command (tree_do_until_command&)
+jit_convert::visit_do_until_command (tree_do_until_command& duc)
 {
-  throw jit_fail_exception ();
+  unwind_protect prot;
+  prot.protect_var (breaks);
+  prot.protect_var (continues);
+  breaks.clear ();
+  continues.clear ();
+
+  jit_block *body = factory.create<jit_block> ("do_until_body");
+  jit_block *cond_check = factory.create<jit_block> ("do_until_cond_check");
+  jit_block *tail = factory.create<jit_block> ("do_until_tail");
+
+  block->append (factory.create<jit_branch> (body));
+  blocks.push_back (body);
+  block = body;
+
+  tree_statement_list *loop_body = duc.body ();
+  bool all_breaking = false;
+  if (loop_body)
+    {
+      try
+        {
+          loop_body->accept (*this);
+        }
+      catch (const jit_break_exception&)
+        {
+          all_breaking = true;
+        }
+    }
+
+  finish_breaks (tail, breaks);
+
+  if (! all_breaking || continues.size ())
+    {
+      jit_block *interrupt_check
+        = factory.create<jit_block> ("interrupt_check");
+      blocks.push_back (interrupt_check);
+      finish_breaks (interrupt_check, continues);
+      if (! all_breaking)
+        block->append (factory.create<jit_branch> (interrupt_check));
+
+      block = interrupt_check;
+      jit_error_check *ec
+        = factory.create<jit_error_check> (jit_error_check::var_interrupt,
+                                           cond_check, final_block);
+      block->append (ec);
+
+      blocks.push_back (cond_check);
+      block = cond_check;
+
+      tree_expression *expr = duc.condition ();
+      assert (expr && "Do-Until expression can not be null");
+      jit_value *check = visit (expr);
+      check = create_checked (&jit_typeinfo::logically_true, check);
+
+      block->append (factory.create<jit_cond_branch> (check, tail, body));
+    }
+
+  blocks.push_back (tail);
+  block = tail;
 }
 
 void
--- a/libinterp/parse-tree/pt-eval.cc	Fri Aug 23 11:33:21 2013 +0800
+++ b/libinterp/parse-tree/pt-eval.cc	Fri Dec 27 13:01:39 2013 +0100
@@ -1121,6 +1121,11 @@
   if (error_state)
     return;
 
+#if HAVE_LLVM
+  if (tree_jit::execute (cmd))
+    return;
+#endif
+
   unwind_protect frame;
 
   frame.protect_var (in_loop_command);
--- a/test/jit.tst	Fri Aug 23 11:33:21 2013 +0800
+++ b/test/jit.tst	Fri Dec 27 13:01:39 2013 +0100
@@ -52,6 +52,32 @@
 
 %!testif HAVE_LLVM
 %! jit_failure_count (0)
+%! do
+%!   break;
+%! until (0)
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   if (1)
+%!     break;
+%!   end;
+%! until (0)
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! i=1;
+%! do
+%!   continue;
+%!   i=i+1;
+%! until (1)
+%! assert (i, 1);
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! for i=1:1e6
 %!   if (i == 100)
 %!     break;