# HG changeset patch # User LYH # Date 1395428378 14400 # Node ID 3b7490456101ba450dbcf61f7ae2738fc1cb0693 # Parent c31fe3239c8b391ef5cc6ead76489ab4db229a29 Add switch statement support diff -r c31fe3239c8b -r 3b7490456101 libinterp/corefcn/pt-jit.cc --- 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 ("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 if_blocks (cond_blocks_num); + std::vector body_blocks (cond_blocks_num); + std::vector 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 ("if_cond"); + body_blocks[i] = factory.create ("if_body"); + else_blocks[i] = factory.create ("else"); + } + + jit_block *tail = factory.create ("switch_tail"); + + + // link & fullfil these blocks + block->append (factory.create (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 (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 (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 (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 (tail)); + blocks.push_back (tail); + block = tail; // switch_tail } void