Mercurial > hg > octave-nkf
diff src/pt-jit.cc @ 14928:39d52aa37a08
Use standard SSA construction algorithm, and support break/continue
author | Max Brister <max@2bass.com> |
---|---|
date | Fri, 01 Jun 2012 19:08:43 -0500 |
parents | 8697e3e9d77a |
children | 1f914446157d |
line wrap: on
line diff
--- a/src/pt-jit.cc +++ b/src/pt-jit.cc @@ -90,6 +90,13 @@ throw jit_fail_exception (reason); } +std::ostream& jit_print (std::ostream& os, jit_type *atype) +{ + if (! atype) + return os << "null"; + return os << atype->name (); +} + // function that jit code calls extern "C" void octave_jit_print_any (const char *name, octave_base_value *obv) @@ -618,11 +625,20 @@ // -------------------- jit_value -------------------- jit_value::~jit_value (void) { + replace_with (0); +} + +void +jit_value::replace_with (jit_value *value) +{ while (use_head) { jit_instruction *user = use_head->user (); size_t idx = use_head->index (); - user->stash_argument (idx, 0); + if (idx < user->argument_count ()) + user->stash_argument (idx, value); + else + user->stash_tag (0); } } @@ -636,13 +652,58 @@ JIT_VISIT_IR_NOTEMPLATE #undef JIT_METH +std::ostream& +operator<< (std::ostream& os, const jit_value& value) +{ + return value.short_print (os); +} + // -------------------- jit_instruction -------------------- +void +jit_instruction::push_variable (void) +{ + if (tag ()) + tag ()->push (this); +} + +void +jit_instruction::pop_variable (void) +{ + if (tag ()) + tag ()->pop (); +} + llvm::BasicBlock * jit_instruction::parent_llvm (void) const { return mparent->to_llvm (); } +std::ostream& +jit_instruction::short_print (std::ostream& os) const +{ + if (type ()) + jit_print (os, type ()) << ": "; + + if (tag ()) + os << tag ()->name () << "." << id; + else + os << "#" << id; + return os; +} + +jit_variable * +jit_instruction::tag (void) const +{ + return reinterpret_cast<jit_variable *> (mtag.value ()); +} + +void +jit_instruction::stash_tag (jit_variable *atag) +{ + mtag.stash_value (atag, this); +} + // -------------------- jit_block -------------------- jit_instruction * jit_block::prepend (jit_instruction *instr) @@ -660,6 +721,23 @@ return instr; } +jit_instruction * +jit_block::insert_before (iterator loc, jit_instruction *instr) +{ + instructions.insert (loc, instr); + instr->stash_parent (this); + return instr; +} + +jit_instruction * +jit_block::insert_after (iterator loc, jit_instruction *instr) +{ + ++loc; + instructions.insert (loc, instr); + instr->stash_parent (this); + return instr; +} + jit_terminator * jit_block::terminator (void) const { @@ -687,13 +765,6 @@ return use->user_parent (); } -llvm::Value * -jit_block::pred_terminator_llvm (size_t idx) const -{ - jit_terminator *term = pred_terminator (idx); - return term ? term->to_llvm () : 0; -} - size_t jit_block::pred_index (jit_block *apred) const { @@ -718,9 +789,10 @@ to_llvm ()); // fix the predecessor jump if it has been created - llvm::Value *term = pred_terminator_llvm (pred_idx); - if (term) + jit_terminator *jterm = pred_terminator (pred_idx); + if (jterm->has_llvm ()) { + llvm::Value *term = jterm->to_llvm (); llvm::TerminatorInst *branch = llvm::cast<llvm::TerminatorInst> (term); for (size_t i = 0; i < branch->getNumSuccessors (); ++i) { @@ -735,6 +807,13 @@ } } +jit_block * +jit_block::succ (size_t i) const +{ + jit_terminator *term = terminator (); + return term->sucessor (i); +} + size_t jit_block::succ_count (void) const { @@ -742,24 +821,198 @@ return term ? term->sucessor_count () : 0; } -jit_phi * -jit_block::search_phi (const std::string& tag_name) -{ - jit_phi *ret = 0; - for (iterator iter = begin (); iter != end () - && (ret = dynamic_cast<jit_phi *> (*iter)); ++iter) - if (ret->tag () == tag_name) - return ret; - - return 0; -} - llvm::BasicBlock * jit_block::to_llvm (void) const { return llvm::cast<llvm::BasicBlock> (llvm_value); } +std::ostream& +jit_block::print_dom (std::ostream& os) const +{ + short_print (os); + os << ":\n"; + os << " mid: " << mid << std::endl; + os << " pred: "; + for (size_t i = 0; i < pred_count (); ++i) + os << *pred (i) << " "; + os << std::endl; + + os << " succ: "; + for (size_t i = 0; i < succ_count (); ++i) + os << *succ (i) << " "; + os << std::endl; + + os << " idom: "; + if (idom) + os << *idom; + else + os << "NULL"; + os << std::endl; + os << " df: "; + for (df_iterator iter = df_begin (); iter != df_end (); ++iter) + os << **iter << " "; + os << std::endl; + + os << " dom_succ: "; + for (size_t i = 0; i < dom_succ.size (); ++i) + os << *dom_succ[i] << " "; + + return os << std::endl; +} + +void +jit_block::compute_df (size_t visit_count) +{ + if (mvisit_count > visit_count) + return; + ++mvisit_count; + + if (pred_count () >= 2) + { + for (size_t i = 0; i < pred_count (); ++i) + { + jit_block *runner = pred (i); + while (runner != idom) + { + runner->mdf.insert (this); + runner = runner->idom; + } + } + } + + for (size_t i = 0; i < succ_count (); ++i) + succ (i)->compute_df (visit_count); +} + +bool +jit_block::update_idom (size_t visit_count) +{ + if (mvisit_count > visit_count) + return false; + ++mvisit_count; + + if (! pred_count ()) + return false; + + bool changed = false; + for (size_t i = 0; i < pred_count (); ++i) + changed = pred (i)->update_idom (visit_count) || changed; + + jit_block *new_idom = pred (0); + for (size_t i = 1; i < pred_count (); ++i) + { + jit_block *pidom = pred (i)->idom; + if (! new_idom) + new_idom = pidom; + else if (pidom) + new_idom = pidom->idom_intersect (new_idom); + } + + if (idom != new_idom) + { + idom = new_idom; + return true; + } + + return changed; +} + +void +jit_block::finish_phi (jit_block *apred) +{ + size_t pred_idx = pred_index (apred); + for (iterator iter = begin (); iter != end () + && dynamic_cast<jit_phi *> (*iter); ++iter) + { + jit_instruction *phi = *iter; + jit_variable *var = phi->tag (); + phi->stash_argument (pred_idx, var->top ()); + } +} + +void +jit_block::do_construct_ssa (jit_convert& convert, size_t visit_count) +{ + if (mvisit_count > visit_count) + return; + ++mvisit_count; + + for (iterator iter = begin (); iter != end (); ++iter) + { + jit_instruction *instr = *iter; + bool isphi = dynamic_cast<jit_phi *> (instr); + + if (! isphi) + { + for (size_t i = 0; i < instr->argument_count (); ++i) + { + jit_variable *var; + var = dynamic_cast<jit_variable *> (instr->argument (i)); + if (var) + instr->stash_argument (i, var->top ()); + } + + // FIXME: Remove need for jit_store_argument dynamic cast + jit_variable *tag = instr->tag (); + if (tag && tag->has_top () + && ! dynamic_cast<jit_store_argument *> (instr)) + { + jit_call *rel = convert.create<jit_call> (jit_typeinfo::release, + tag->top ()); + insert_after (iter, rel); + ++iter; + } + } + + instr->push_variable (); + } + + for (size_t i = 0; i < succ_count (); ++i) + succ (i)->finish_phi (this); + + for (size_t i = 0; i < dom_succ.size (); ++i) + dom_succ[i]->do_construct_ssa (convert, visit_count); + + for (iterator iter = begin (); iter != end (); ++iter) + { + jit_instruction *instr = *iter; + instr->pop_variable (); + } +} + +void +jit_block::create_dom_tree (size_t visit_count) +{ + if (mvisit_count > visit_count) + return; + ++mvisit_count; + + if (idom != this) + idom->dom_succ.push_back (this); + + for (size_t i = 0; i < succ_count (); ++i) + succ (i)->create_dom_tree (visit_count); +} + +jit_block * +jit_block::idom_intersect (jit_block *b) +{ + jit_block *i = this; + jit_block *j = b; + + while (i != j) + { + while (i->id () > j->id ()) + i = i->idom; + + while (j->id () > i->id ()) + j = j->idom; + } + + return i; +} + // -------------------- jit_call -------------------- bool jit_call::infer (void) @@ -792,45 +1045,39 @@ // -------------------- jit_convert -------------------- jit_convert::jit_convert (llvm::Module *module, tree &tee) + : iterator_count (0), breaking (false) { jit_instruction::reset_ids (); - jit_block *entry_block = create<jit_block> ("body"); + entry_block = create<jit_block> ("body"); + blocks.push_back (entry_block); block = entry_block; - blocks.push_back (block); - - toplevel_map tlevel (*this, block); - variables = &tlevel; - final_block = create<jit_block> ("final"); visit (tee); - blocks.push_back (final_block); - block->append (create<jit_break> (final_block)); + // FIXME: Remove if we no longer only compile loops + assert (! breaking); + assert (breaks.empty ()); + assert (continues.empty ()); - for (variable_map::iterator iter = variables->begin (); - iter != variables->end (); ++iter) - final_block->append (create<jit_store_argument> (iter->first, iter->second)); + jit_block *final_block = block; + for (vmap_t::iterator iter = vmap.begin (); iter != vmap.end (); ++iter) + + { + jit_variable *var = iter->second; + const std::string& name = var->name (); + if (name.size () && name[0] != '#') + final_block->append (create<jit_store_argument> (var)); + } - // FIXME: Maybe we should remove dead code here? + construct_ssa (final_block); // initialize the worklist to instructions derived from constants for (std::list<jit_value *>::iterator iter = constants.begin (); iter != constants.end (); ++iter) append_users (*iter); - // also get anything from jit_extract_argument, as these have constant types - for (jit_block::iterator iter = entry_block->begin (); - iter != entry_block->end (); ++iter) - { - jit_instruction *instr = *iter; - if (jit_extract_argument *extract = dynamic_cast<jit_extract_argument *>(instr)) - { - if (! extract->type ()) - // we depend on an unknown type - fail ("Unknown initial type: \"" + extract->tag () + "\""); - append_users (extract); - } - } + if (debug_print) + print_blocks ("octave jit ir"); // FIXME: Describe algorithm here while (worklist.size ()) @@ -846,11 +1093,7 @@ { std::cout << "-------------------- Compiling tree --------------------\n"; std::cout << tee.str_print_code () << std::endl; - std::cout << "-------------------- octave jit ir --------------------\n"; - for (std::list<jit_block *>::iterator iter = blocks.begin (); - iter != blocks.end (); ++iter) - (*iter)->print (std::cout, 0); - std::cout << std::endl; + print_blocks ("octave jit ir"); } // for now just init arguments from entry, later we will have to do something @@ -859,11 +1102,11 @@ iter != entry_block->end (); ++iter) { if (jit_extract_argument *extract = dynamic_cast<jit_extract_argument *> (*iter)) - arguments.push_back (std::make_pair (extract->tag (), true)); + arguments.push_back (std::make_pair (extract->name (), true)); } convert_llvm to_llvm; - function = to_llvm.convert (module, arguments, blocks, constants); + function = to_llvm.convert (module, arguments, blocks); if (debug_print) { @@ -914,7 +1157,8 @@ void jit_convert::visit_break_command (tree_break_command&) { - fail (); + breaks.push_back (block); + breaking = true; } void @@ -926,7 +1170,8 @@ void jit_convert::visit_continue_command (tree_continue_command&) { - fail (); + continues.push_back (block); + breaking = true; } void @@ -961,29 +1206,13 @@ // better type inference bounds on variables defined and used only // inside the for loop (e.g. the index variable) - // prev_block: % pred = ? - // #control.0 = % compute_control (note this will just be a temp) - // #iter.0 = call for_init (#control.0) % Let type of control decide iter - // % initial value and type - // #temp.0 = call for_check (control.0, #iter.0) - // cond_break #temp.0, for_body, for_tail - // for_body: % pred = for_init, for_cond - // idxvar.2 = phi | for_init -> idxvar.1 - // | for_body -> idxvar.3 - // #iter.1 = phi | for_init -> #iter.0 - // | for_body -> #iter.2 - // idxvar.3 = call for_index (#control.0, #iter.1) - // % do loop body - // #iter.2 = #iter.1 + 1 % release is implicit in iter reuse - // #check = call for_check (#control.0, iter.2) - // cond_break #check for_body, for_tail - // for_tail: % pred = prev_block, for_body - // #iter.3 = phi | prev_block -> #iter.0 - // | for_body -> #iter.2 - // idxvar.4 = phi | prev_block -> idxvar.0 - // | for_body -> idxvar.3 - // call release (#iter.3) - // % rest of code + // If we are a nested for loop we need to store the previous breaks + assert (! breaking); + unwind_protect prot; + prot.protect_var (breaks); + prot.protect_var (continues); + prot.protect_var (breaking); + breaks.clear (); // FIXME: one of these days we will introduce proper lvalues... tree_identifier *lhs = dynamic_cast<tree_identifier *>(cmd.left_hand_side ()); @@ -991,6 +1220,13 @@ fail (); std::string lhs_name = lhs->name (); + // we need a variable for our iterator, because it is used in multiple blocks + std::stringstream ss; + ss << "#iter" << iterator_count++; + std::string iter_name = ss.str (); + jit_variable *iterator = create<jit_variable> (iter_name); + vmap[iter_name] = iterator; + jit_block *body = create<jit_block> ("for_body"); blocks.push_back (body); @@ -999,55 +1235,57 @@ // do control expression, iter init, and condition check in prev_block (block) jit_value *control = visit (cmd.control_expr ()); jit_call *init_iter = create<jit_call> (jit_typeinfo::for_init, control); - init_iter->stash_tag ("#iter"); + init_iter->stash_tag (iterator); block->append (init_iter); + jit_value *check = block->append (create<jit_call> (jit_typeinfo::for_check, - control, init_iter)); + control, iterator)); block->append (create<jit_cond_break> (check, body, tail)); - - // we need to do iter phi manually, for_map handles the rest - jit_phi *iter_phi = create<jit_phi> (2); - iter_phi->stash_tag ("#iter"); - iter_phi->stash_argument (0, init_iter); - body->append (iter_phi); - - variable_map *merge_vars = variables; - for_map body_vars (variables, body); - variables = &body_vars; block = body; - // first thing we do in the for loop is bind our index from our itertor - jit_call *idx_rhs = create<jit_call> (jit_typeinfo::for_index, control, iter_phi); + // compute the syntactical iterator + jit_call *idx_rhs = create<jit_call> (jit_typeinfo::for_index, control, iterator); block->append (idx_rhs); - idx_rhs->stash_tag (lhs_name); do_assign (lhs_name, idx_rhs, false); + // do loop tree_statement_list *pt_body = cmd.body (); pt_body->accept (*this); - // increment iterator, check conditional, and repeat + if (breaking && continues.empty ()) + { + // WTF are you doing user? Every branch was a continue, why did you have + // a loop??? Users are silly people... + finish_breaks (tail, breaks); + blocks.push_back (tail); + block = tail; + return; + } + + // check our condition, continues jump to this block + jit_block *check_block = create<jit_block> ("for_check"); + blocks.push_back (check_block); + + if (! breaking) + block->append (create<jit_break> (check_block)); + finish_breaks (check_block, continues); + + block = check_block; const jit_function& add_fn = jit_typeinfo::binary_op (octave_value::op_add); - jit_call *iter_inc = create<jit_call> (add_fn, iter_phi, - create<jit_const_index> (1)); - iter_inc->stash_tag ("#iter"); + jit_instruction *one = create<jit_const_index> (1); + block->append (one); + + jit_call *iter_inc = create<jit_call> (add_fn, iterator, one); + iter_inc->stash_tag (iterator); block->append (iter_inc); check = block->append (create<jit_call> (jit_typeinfo::for_check, control, - iter_inc)); + iterator)); block->append (create<jit_cond_break> (check, body, tail)); - iter_phi->stash_argument (1, iter_inc); - body_vars.finish_phi (*variables); - merge (tail, *merge_vars, block, body_vars); + // breaks will go to our tail blocks.push_back (tail); + finish_breaks (tail, breaks); block = tail; - variables = merge_vars; - - iter_phi = create<jit_phi> (2); - iter_phi->stash_tag ("#iter"); - iter_phi->stash_argument (0, init_iter); - iter_phi->stash_argument (1, iter_inc); - block->append (iter_phi); - block->append (create<jit_call> (jit_typeinfo::release, iter_phi)); } void @@ -1090,8 +1328,8 @@ jit_convert::visit_identifier (tree_identifier& ti) { const jit_function& fn = jit_typeinfo::grab (); - jit_value *var = variables->get (ti.name ()); - result = block->append (create<jit_call> (fn, var)); + jit_value *decl = get_variable (ti.name ()); + result = block->append (create<jit_call> (fn, decl)); } void @@ -1120,6 +1358,10 @@ // c = c + 3; // endif + // ******************** + // FIXME: Documentation no longer reflects current version + // ******************** + // Generates: // prev_block0: % pred - ? // #temp.0 = call binary== (a.0, 1) @@ -1149,7 +1391,6 @@ // the condition check for the ith clause. For the else, it is simple the // else body. If there is no else body, then it is padded with the tail std::vector<jit_block *> entry_blocks (lst.size () + 1 - last_else); - std::vector<variable_map *> branch_variables (lst.size (), 0); std::vector<jit_block *> branch_blocks (lst.size (), 0); // final blocks entry_blocks[0] = block; @@ -1169,16 +1410,13 @@ if (! last_else) entry_blocks[entry_blocks.size () - 1] = tail; - // actually fill out the contents of our blocks. We store the variable maps - // at the end of each branch, this allows us to merge them in the tail - variable_map *prev_map = variables; + size_t num_incomming = 0; // number of incomming blocks to our tail iter = lst.begin (); for (size_t i = 0; iter != lst.end (); ++iter, ++i) { tree_if_clause *tic = *iter; block = entry_blocks[i]; assert (block); - variables = prev_map; if (i) // the first block is prev_block, so it has already been added blocks.push_back (entry_blocks[i]); @@ -1195,31 +1433,29 @@ entry_blocks[i + 1]); block->append (br); block = body; - - variables = new compound_map (variables); - branch_variables[i] = variables; } tree_statement_list *stmt_lst = tic->commands (); assert (stmt_lst); // jwe: Can this be null? stmt_lst->accept (*this); - branch_variables[i] = variables; - branch_blocks[i] = block; - block->append (create<jit_break> (tail)); + if (breaking) + breaking = false; + else + { + ++num_incomming; + block->append (create<jit_break> (tail)); + } } - blocks.push_back (tail); - - // We create phi nodes in the tail to merge blocks - for (size_t i = 0; i < branch_variables.size () - last_else; ++i) + if (num_incomming || ! last_else) { - merge (tail, *prev_map, branch_blocks[i], *branch_variables[i]); - delete branch_variables[i]; + blocks.push_back (tail); + block = tail; } - - variables = prev_map; - block = tail; + else + // every branch broke, so we don't have a tail + breaking = true; } void @@ -1267,7 +1503,9 @@ result = create<jit_const_range> (rv); } else - fail (); + fail ("Unknown constant"); + + block->append (result); } void @@ -1311,7 +1549,7 @@ { // resolve rhs tree_expression *rhs = tsa.right_hand_side (); - jit_value *rhsv = visit (rhs); + jit_instruction *rhsv = visit (rhs); // resolve lhs tree_expression *lhs = tsa.left_hand_side (); @@ -1319,11 +1557,7 @@ fail (); std::string lhs_name = lhs->name (); - do_assign (lhs_name, rhsv, tsa.print_result ()); - result = rhsv; - - if (jit_instruction *instr = dynamic_cast<jit_instruction *>(rhsv)) - instr->stash_tag (lhs_name); + result = do_assign (lhs_name, rhsv, tsa.print_result ()); } void @@ -1348,7 +1582,7 @@ else do_bind_ans = (! expr->is_assignment_expression ()); - jit_value *expr_result = visit (expr); + jit_instruction *expr_result = visit (expr); if (do_bind_ans) do_assign ("ans", expr_result, expr->print_result ()); @@ -1373,6 +1607,9 @@ // jwe: Can this ever be null? assert (elt); elt->accept (*this); + + if (breaking) + break; } } @@ -1418,86 +1655,113 @@ fail (); } -void -jit_convert::do_assign (const std::string& lhs, jit_value *rhs, bool print) +jit_variable * +jit_convert::get_variable (const std::string& vname) { - const jit_function& release = jit_typeinfo::release (); - jit_value *current = variables->get (lhs); - block->append (create<jit_call> (release, current)); - variables->set (lhs, rhs); + vmap_t::iterator iter; + iter = vmap.find (vname); + if (iter != vmap.end ()) + return iter->second; + + jit_variable *var = create<jit_variable> (vname); + octave_value val = symbol_table::find (vname); + jit_type *type = jit_typeinfo::type_of (val); + jit_extract_argument *extract; + extract = create<jit_extract_argument> (type, var); + entry_block->prepend (extract); + + return vmap[vname] = var; +} + +jit_instruction * +jit_convert::do_assign (const std::string& lhs, jit_instruction *rhs, + bool print) +{ + jit_variable *var = get_variable (lhs); + rhs->stash_tag (var); if (print) { const jit_function& print_fn = jit_typeinfo::print_value (); jit_const_string *name = create<jit_const_string> (lhs); - block->append (create<jit_call> (print_fn, name, rhs)); + block->append (create<jit_call> (print_fn, name, var)); } + + return rhs; } -jit_value * +jit_instruction * jit_convert::visit (tree& tee) { result = 0; tee.accept (*this); - jit_value *ret = result; + jit_instruction *ret = result; result = 0; return ret; } void -jit_convert::merge (jit_block *merge_block, variable_map& merge_vars, - jit_block *incomming_block, - const variable_map& incomming_vars) +jit_convert::construct_ssa (jit_block *final_block) { - size_t pred_count = merge_block->pred_count (); - size_t merge_idx = merge_block->pred_index (incomming_block); - for (variable_map::const_iterator iter = incomming_vars.begin (); - iter != incomming_vars.end (); ++iter) + final_block->label (); + entry_block->compute_idom (final_block); + entry_block->compute_df (); + entry_block->create_dom_tree (); + + // insert phi nodes where needed + for (vmap_t::iterator iter = vmap.begin (); iter != vmap.end (); ++iter) { - const std::string& vname = iter->first; - jit_value *merge_val = merge_vars.get (vname); - jit_value *inc_val = iter->second; + jit_block::df_set visited, added_phi; + std::list<jit_block *> ssa_worklist; + iter->second->use_blocks (visited); + ssa_worklist.insert (ssa_worklist.begin (), visited.begin (), visited.end ()); - if (merge_val != inc_val) + while (ssa_worklist.size ()) { - jit_phi *phi = dynamic_cast<jit_phi *> (merge_val); - if (! (phi && phi->parent () == merge_block)) + jit_block *b = ssa_worklist.front (); + ssa_worklist.pop_front (); + + for (jit_block::df_iterator diter = b->df_begin (); + diter != b->df_end (); ++diter) { - phi = merge_block->search_phi (vname); - if (! phi) + jit_block *dblock = *diter; + if (! added_phi.count (dblock)) { - phi = create<jit_phi> (pred_count, merge_val); - merge_block->prepend (phi); + jit_phi *phi = create<jit_phi> (iter->second, + dblock->pred_count ()); + dblock->prepend (phi); + added_phi.insert (dblock); } - merge_vars.set (vname, phi); + if (! visited.count (dblock)) + { + ssa_worklist.push_back (dblock); + visited.insert (dblock); + } } - - phi->stash_argument (merge_idx, inc_val); } } + + entry_block->construct_ssa (*this); } -// -------------------- jit_convert::toplevel_map -------------------- -jit_value * -jit_convert::toplevel_map::insert (const std::string& name, jit_value *pval) +void +jit_convert::finish_breaks (jit_block *dest, const break_list& lst) { - assert (pval == 0); // we have no parent - - jit_block *entry = block (); - octave_value val = symbol_table::find (name); - jit_type *type = jit_typeinfo::type_of (val); - jit_instruction *ret = convert.create<jit_extract_argument> (type, name); - return vars[name] = entry->prepend (ret); + for (break_list::const_iterator iter = lst.begin (); iter != lst.end (); + ++iter) + { + jit_block *b = *iter; + b->append (create<jit_break> (dest)); + } } // -------------------- jit_convert::convert_llvm -------------------- llvm::Function * jit_convert::convert_llvm::convert (llvm::Module *module, const std::vector<std::pair< std::string, bool> >& args, - const std::list<jit_block *>& blocks, - const std::list<jit_value *>& constants) + const std::list<jit_block *>& blocks) { jit_type *any = jit_typeinfo::get_any (); @@ -1522,12 +1786,6 @@ arguments[args[i].first] = loaded_arg; } - // we need to generate llvm values for constants, as these don't appear in - // a block - for (std::list<jit_value *>::const_iterator iter = constants.begin (); - iter != constants.end (); ++iter) - visit (*iter); - std::list<jit_block *>::const_iterator biter; for (biter = blocks.begin (); biter != blocks.end (); ++biter) { @@ -1667,12 +1925,12 @@ const jit_function::overload& ol = call.overload (); if (! ol.function) fail ("No overload for: " + call.print_string ()); - + std::vector<llvm::Value *> args (call.argument_count ()); for (size_t i = 0; i < call.argument_count (); ++i) args[i] = call.argument_llvm (i); - call.stash_llvm (builder.CreateCall (ol.function, args, call.tag ())); + call.stash_llvm (builder.CreateCall (ol.function, args)); } void @@ -1682,10 +1940,10 @@ if (! ol.function) fail (); - llvm::Value *arg = arguments[extract.tag ()]; + llvm::Value *arg = arguments[extract.name ()]; assert (arg); arg = builder.CreateLoad (arg); - extract.stash_llvm (builder.CreateCall (ol.function, arg, extract.tag ())); + extract.stash_llvm (builder.CreateCall (ol.function, arg, extract.name ())); } void @@ -1698,7 +1956,7 @@ arg_value = builder.CreateCall (ol.function, arg_value); - llvm::Value *arg = arguments[store.tag ()]; + llvm::Value *arg = arguments[store.name ()]; store.stash_llvm (builder.CreateStore (arg_value, arg)); } @@ -1708,8 +1966,7 @@ // we might not have converted all incoming branches, so we don't // set incomming branches now llvm::PHINode *node = llvm::PHINode::Create (phi.type_llvm (), - phi.argument_count (), - phi.tag ()); + phi.argument_count ()); builder.Insert (node); phi.stash_llvm (node); @@ -1719,6 +1976,12 @@ parent->create_merge (function, i); } +void +jit_convert::convert_llvm::visit (jit_variable&) +{ + fail ("ERROR: SSA construction should remove all variables"); +} + // -------------------- tree_jit -------------------- tree_jit::tree_jit (void) : module (0), engine (0)