changeset 18583:3b7490456101 draft

Add switch statement support
author LYH <lyh.kernel@gmail.com>
date Fri, 21 Mar 2014 14:59:38 -0400
parents c31fe3239c8b
children f00ef64486a2
files libinterp/corefcn/pt-jit.cc
diffstat 1 files changed, 118 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/pt-jit.cc	Fri Mar 21 14:59:38 2014 -0400
+++ b/libinterp/corefcn/pt-jit.cc	Fri Mar 21 14:59:38 2014 -0400
@@ -821,9 +821,125 @@
 }
 
 void
-jit_convert::visit_switch_command (tree_switch_command&)
+jit_convert::visit_switch_command (tree_switch_command& cmd)
 {
-  throw jit_fail_exception ();
+  // create blocks
+  jit_block *head = factory.create<jit_block> ("switch_head");
+
+  tree_switch_case_list *lst = cmd.case_list ();
+  tree_switch_case *last = lst->back ();
+
+  size_t cond_blocks_num;
+  if (lst->size() && last->is_default_case ())
+    cond_blocks_num = lst->size () - 1;
+  else
+    cond_blocks_num = lst->size ();
+
+  std::vector<jit_block *> if_blocks (cond_blocks_num);
+  std::vector<jit_block *> body_blocks (cond_blocks_num);
+  std::vector<jit_block *> else_blocks (cond_blocks_num);
+
+  //tree_switch_case_list::iterator iter = lst->begin ();
+  for (size_t i = 0; i < cond_blocks_num; ++i)
+    {
+      if_blocks[i] = factory.create<jit_block> ("if_cond");
+      body_blocks[i] = factory.create<jit_block> ("if_body");
+      else_blocks[i] = factory.create<jit_block> ("else");
+    }
+
+  jit_block *tail = factory.create<jit_block> ("switch_tail");
+
+
+  // link & fullfil these blocks
+  block->append (factory.create<jit_branch> (head));
+
+  blocks.push_back (head);
+  block = head; // switch_head
+  tree_expression *expr = cmd.switch_value ();
+  assert (expr && "Switch value can not be null");
+  jit_value *value = visit (expr);
+  assert (value);
+
+  // each branch in the if statement will have different breaks/continues
+  block_list current_breaks = breaks;
+  block_list current_continues = continues;
+  breaks.clear ();
+  continues.clear ();
+
+#if 0
+  size_t num_incomming = 0; // number of incomming blocks to our tail
+#endif
+  tree_switch_case_list::iterator iter = lst->begin ();
+  for (size_t i = 0; i < cond_blocks_num; ++iter, ++i)
+    {
+      block->append (factory.create<jit_branch> (if_blocks[i]));
+
+      blocks.push_back (if_blocks[i]);
+      block = if_blocks[i]; // if_cond
+      tree_switch_case *twc = *iter;
+      tree_expression *expr = twc->case_label ();
+      jit_value *label = visit (expr);
+      assert(label);
+
+      const jit_operation& fn = jit_typeinfo::binary_op (octave_value::op_eq);
+      jit_value *cond = create_checked (fn, value, label);
+      assert(cond);
+      jit_call *check = create_checked (&jit_typeinfo::logically_true,
+                                        cond);
+      block->append (factory.create<jit_cond_branch> (check, body_blocks[i],
+                                                      else_blocks[i]));
+
+      blocks.push_back (body_blocks[i]);
+      block = body_blocks[i]; // if_body
+      tree_statement_list *stmt_lst = twc->commands ();
+      assert(stmt_lst);
+#if 0
+      try
+        {
+#endif
+          stmt_lst->accept (*this);
+#if 0
+          num_incomming++;
+#endif
+          block->append (factory.create<jit_branch> (tail));
+#if 0
+        }
+      catch(const jit_break_exception&)
+        {}
+#endif
+
+#if 0
+      // each branch in the if statement will have different breaks/continues
+      current_breaks.splice (current_breaks.end (), breaks);
+      current_continues.splice (current_continues.end (), continues);
+#endif
+
+      blocks.push_back (else_blocks[i]);
+      block = else_blocks[i]; // else
+    }
+
+  if (lst->size() && last->is_default_case ())
+    {
+      tree_statement_list *stmt_lst = last->commands ();
+      assert(stmt_lst);
+      stmt_lst->accept (*this);
+
+#if 0
+      // each branch in the if statement will have different breaks/continues
+      current_breaks.splice (current_breaks.end (), breaks);
+      current_continues.splice (current_continues.end (), continues);
+#endif
+    }
+
+#if 0
+  // each branch in the if statement will have different breaks/continues
+  breaks.splice (breaks.end (), current_breaks);
+  continues.splice (continues.end (), current_continues);
+#endif
+
+  block->append (factory.create<jit_branch> (tail));
+  blocks.push_back (tail);
+  block = tail; // switch_tail
 }
 
 void