Mercurial > hg > octave-lyh
changeset 17142:c3cb55d917a9
Add switch statement support
author | LYH <lyh.kernel@gmail.com> |
---|---|
date | Fri, 02 Aug 2013 20:04:01 +0800 |
parents | 2a4a83b5b317 |
children | 73afa852a898 |
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 +++ b/libinterp/corefcn/pt-jit.cc @@ -798,9 +798,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