GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
pt-jit.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2012-2015 Max Brister
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 // Author: Max Brister <max@2bass.com>
24 
25 #define __STDC_LIMIT_MACROS
26 #define __STDC_CONSTANT_MACROS
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 #include "debug.h"
33 #include "defun.h"
34 #include "ov.h"
35 #include "pt-all.h"
36 #include "pt-jit.h"
37 #include "sighandlers.h"
38 #include "symtab.h"
39 #include "variables.h"
40 
41 #ifdef HAVE_LLVM
42 
43 static bool Vdebug_jit = false;
44 
45 static bool Vjit_enable = false;
46 
47 static int Vjit_startcnt = 1000;
48 
49 static int Vjit_failcnt = 0;
50 
51 #include <llvm/Analysis/CallGraph.h>
52 #include <llvm/Analysis/Passes.h>
53 
54 #ifdef HAVE_LLVM_IR_VERIFIER_H
55 #include <llvm/IR/Verifier.h>
56 #else
57 #include <llvm/Analysis/Verifier.h>
58 #endif
59 
60 #include <llvm/Bitcode/ReaderWriter.h>
61 #include <llvm/ExecutionEngine/ExecutionEngine.h>
62 #include <llvm/ExecutionEngine/JIT.h>
63 
64 #ifdef LEGACY_PASSMANAGER
65 #include <llvm/IR/LegacyPassManager.h>
66 #else
67 #include <llvm/PassManager.h>
68 #endif
69 
70 #ifdef HAVE_LLVM_IR_FUNCTION_H
71 #include <llvm/IR/LLVMContext.h>
72 #include <llvm/IR/Module.h>
73 #else
74 #include <llvm/LLVMContext.h>
75 #include <llvm/Module.h>
76 #endif
77 
78 #ifdef HAVE_LLVM_SUPPORT_IRBUILDER_H
79 #include <llvm/Support/IRBuilder.h>
80 #elif defined(HAVE_LLVM_IR_IRBUILDER_H)
81 #include <llvm/IR/IRBuilder.h>
82 #else
83 #include <llvm/IRBuilder.h>
84 #endif
85 
86 #include <llvm/Support/raw_os_ostream.h>
87 #include <llvm/Support/TargetSelect.h>
88 
89 #ifdef HAVE_LLVM_IR_DATALAYOUT_H
90 #include <llvm/IR/DataLayout.h>
91 #elif defined(HAVE_LLVM_DATALAYOUT_H)
92 #include <llvm/DataLayout.h>
93 #else
94 #include <llvm/Target/TargetData.h>
95 #endif
96 
97 #include <llvm/Transforms/IPO.h>
98 #include <llvm/Transforms/Scalar.h>
99 
100 static llvm::IRBuilder<> builder (llvm::getGlobalContext ());
101 
102 static llvm::LLVMContext& context = llvm::getGlobalContext ();
103 
104 // -------------------- jit_break_exception --------------------
105 
106 // jit_break is thrown whenever a branch we are converting has only breaks or
107 // continues. This is because all code that follows a break or continue is dead.
108 class jit_break_exception : public std::exception {};
109 
110 // -------------------- jit_convert --------------------
112  : converting_function (false)
113 {
115 
116  if (for_bounds)
117  create_variable (next_for_bounds (false), for_bounds);
118 
119  try
120  {
121  visit (tee);
122  }
123  catch (const jit_break_exception&)
124  { }
125 
126  // breaks must have been handled by the top level loop
127  assert (breaks.empty ());
128  assert (continues.empty ());
129 
132 
133  for (variable_map::iterator iter = vmap.begin (); iter != vmap.end (); ++iter)
134  {
135  jit_variable *var = iter->second;
136  const std::string& name = var->name ();
137  if (name.size () && name[0] != '#')
139  }
140 
142 }
143 
145  const std::vector<jit_type *>& args)
146  : converting_function (true)
147 {
148  initialize (fcn.scope ());
149 
150  tree_parameter_list *plist = fcn.parameter_list ();
151  tree_parameter_list *rlist = fcn.return_list ();
152  if (plist && plist->takes_varargs ())
153  throw jit_fail_exception ("varags not supported");
154 
155  if (rlist && (rlist->size () > 1 || rlist->takes_varargs ()))
156  throw jit_fail_exception ("multiple returns not supported");
157 
158  if (plist)
159  {
160  tree_parameter_list::iterator piter = plist->begin ();
161  for (size_t i = 0; i < args.size (); ++i, ++piter)
162  {
163  if (piter == plist->end ())
164  throw jit_fail_exception ("Too many parameter to function");
165 
166  tree_decl_elt *elt = *piter;
167  std::string name = elt->name ();
168  create_variable (name, args[i]);
169  }
170  }
171 
172  jit_value *return_value = 0;
173  bool all_breaking = false;
174  if (fcn.is_special_expr ())
175  {
176  tree_expression *expr = fcn.special_expr ();
177  if (expr)
178  {
179  jit_variable *retvar = get_variable ("#return");
180  jit_value *retval = 0;
181  try
182  {
183  retval = visit (expr);
184  }
185  catch (const jit_break_exception&)
186  { }
187 
188  if (breaks.size () || continues.size ())
189  throw jit_fail_exception ("break/continue not supported in "
190  "anonymous functions");
191 
192  block->append (factory.create<jit_assign> (retvar, retval));
193  return_value = retvar;
194  }
195  }
196  else
197  {
198  try
199  {
200  visit_statement_list (*fcn.body ());
201  }
202  catch (const jit_break_exception&)
203  {
204  all_breaking = true;
205  }
206 
207  // the user may use break or continue to exit the function
210  }
211 
212  if (! all_breaking)
214 
216  block = final_block;
217 
218  if (! return_value && rlist && rlist->size () == 1)
219  {
220  tree_decl_elt *elt = rlist->front ();
221  return_value = get_variable (elt->name ());
222  }
223 
224  // FIXME: We should use live range analysis to delete variables where needed.
225  // For now we just delete everything at the end of the function.
226  for (variable_map::iterator iter = vmap.begin (); iter != vmap.end (); ++iter)
227  {
228  if (iter->second != return_value)
229  {
230  jit_call *call;
232  iter->second);
233  final_block->append (call);
234  }
235  }
236 
237  if (return_value)
238  final_block->append (factory.create<jit_return> (return_value));
239  else
241 }
242 
243 void
245 {
246  throw jit_fail_exception ("No visit_anon_fcn_handle implementation");
247 }
248 
249 void
251 {
252  throw jit_fail_exception ("No visit_argument_list implementation");
253 }
254 
255 void
257 {
259  {
261  boole = dynamic_cast<tree_boolean_expression *> (&be);
262  assert (boole);
263  bool is_and = boole->op_type () == tree_boolean_expression::bool_and;
264 
265  std::string short_name = next_shortcircut_result ();
266  jit_variable *short_result = factory.create<jit_variable> (short_name);
267  vmap[short_name] = short_result;
268 
269  jit_block *done = factory.create<jit_block> (block->name ());
270  tree_expression *lhs = be.lhs ();
271  jit_value *lhsv = visit (lhs);
273 
274  jit_block *short_early = factory.create<jit_block> ("short_early");
275  blocks.push_back (short_early);
276 
277  jit_block *short_cont = factory.create<jit_block> ("short_cont");
278 
279  if (is_and)
280  block->append (factory.create<jit_cond_branch> (lhsv, short_cont,
281  short_early));
282  else
283  block->append (factory.create<jit_cond_branch> (lhsv, short_early,
284  short_cont));
285 
286  block = short_early;
287 
288  jit_value *early_result = factory.create<jit_const_bool> (! is_and);
289  block->append (factory.create<jit_assign> (short_result, early_result));
290  block->append (factory.create<jit_branch> (done));
291 
292  blocks.push_back (short_cont);
293  block = short_cont;
294 
295  tree_expression *rhs = be.rhs ();
296  jit_value *rhsv = visit (rhs);
298  block->append (factory.create<jit_assign> (short_result, rhsv));
299  block->append (factory.create<jit_branch> (done));
300 
301  blocks.push_back (done);
302  block = done;
303  result = short_result;
304  }
305  else
306  {
307  tree_expression *lhs = be.lhs ();
308  jit_value *lhsv = visit (lhs);
309 
310  tree_expression *rhs = be.rhs ();
311  jit_value *rhsv = visit (rhs);
312 
313  const jit_operation& fn = jit_typeinfo::binary_op (be.op_type ());
314  result = create_checked (fn, lhsv, rhsv);
315  }
316 }
317 
318 void
320 {
321  breaks.push_back (block);
322  throw jit_break_exception ();
323 }
324 
325 void
327 {
328  // in the futher we need to add support for classes and deal with rvalues
329  jit_value *base = visit (expr.base ());
330  jit_value *limit = visit (expr.limit ());
331  jit_value *increment;
332  tree_expression *tinc = expr.increment ();
333 
334  if (tinc)
335  increment = visit (tinc);
336  else
337  increment = factory.create<jit_const_scalar> (1);
338 
340  base, limit, increment));
341 }
342 
343 void
345 {
346  continues.push_back (block);
347  throw jit_break_exception ();
348 }
349 
350 void
352 {
353  throw jit_fail_exception ("No visit_global_command implemenation");
354 }
355 
356 void
358 {
359  throw jit_fail_exception ("No visit_persistent_command implementation");
360 }
361 
362 void
364 {
365  throw jit_fail_exception ("No visit_decl_elt implementation");
366 }
367 
368 void
370 {
371  throw jit_fail_exception ("No visit_decl_init_list implementation");
372 }
373 
374 void
376 {
377  // Note we do an initial check to see if the loop will run atleast once.
378  // This allows us to get better type inference bounds on variables defined
379  // and used only inside the for loop (e.g. the index variable)
380 
381  // If we are a nested for loop we need to store the previous breaks
382  unwind_protect prot;
383  prot.protect_var (breaks);
384  prot.protect_var (continues);
385  breaks.clear ();
386  continues.clear ();
387 
388  // we need a variable for our iterator, because it is used in multiple blocks
389  std::string iter_name = next_iterator ();
390  jit_variable *iterator = factory.create<jit_variable> (iter_name);
391  factory.create<jit_variable> (iter_name);
392  vmap[iter_name] = iterator;
393 
394  jit_block *body = factory.create<jit_block> ("for_body");
395  jit_block *tail = factory.create<jit_block> ("for_tail");
396 
397  // do control expression, iter init, and condition check in prev_block (block)
398  // if we are the top level for loop, the bounds is an input argument.
399  jit_value *control = find_variable (next_for_bounds ());
400  if (! control)
401  control = visit (cmd.control_expr ());
403  control);
404  block->append (init_iter);
405  block->append (factory.create<jit_assign> (iterator, init_iter));
406 
408  iterator);
409  block->append (check);
410  block->append (factory.create<jit_cond_branch> (check, body, tail));
411 
412  blocks.push_back (body);
413  block = body;
414 
415  // compute the syntactical iterator
417  control, iterator);
418  block->append (idx_rhs);
419  do_assign (cmd.left_hand_side (), idx_rhs);
420 
421  // do loop
422  tree_statement_list *pt_body = cmd.body ();
423  bool all_breaking = false;
424  try
425  {
426  pt_body->accept (*this);
427  }
428  catch (const jit_break_exception&)
429  {
430  if (continues.empty ())
431  {
432  // WTF are you doing user? Every branch was a break, why did you have
433  // a loop??? Users are silly people...
434  finish_breaks (tail, breaks);
435  blocks.push_back (tail);
436  block = tail;
437  return;
438  }
439 
440  all_breaking = true;
441  }
442 
443  // check our condition, continues jump to this block
444  jit_block *check_block = factory.create<jit_block> ("for_check");
445  blocks.push_back (check_block);
446 
447  jit_block *interrupt_check = factory.create<jit_block> ("for_interrupt");
448  blocks.push_back (interrupt_check);
449 
450  if (! all_breaking)
451  block->append (factory.create<jit_branch> (check_block));
452  finish_breaks (check_block, continues);
453 
454  block = check_block;
457  jit_call *iter_inc = factory.create<jit_call> (add_fn, iterator, one);
458  block->append (iter_inc);
459  block->append (factory.create<jit_assign> (iterator, iter_inc));
460  check = block->append (factory.create<jit_call> (jit_typeinfo::for_check,
461  control, iterator));
462  block->append (factory.create<jit_cond_branch> (check, interrupt_check,
463  tail));
464 
465  block = interrupt_check;
466  jit_error_check *ec
468  body, final_block);
469  block->append (ec);
470 
471  // breaks will go to our tail
472  blocks.push_back (tail);
473  finish_breaks (tail, breaks);
474  block = tail;
475 }
476 
477 void
479 {
480  throw jit_fail_exception ("No visit_complex_for_command implementation");
481 }
482 
483 void
485 {
486  throw jit_fail_exception ("No visit_octave_user_script implementation");
487 }
488 
489 void
491 {
492  throw jit_fail_exception ("No visit_octave_user_function implementation");
493 }
494 
495 void
497 {
498  throw jit_fail_exception ("No visit_octave_user_function_header implementation");
499 }
500 
501 void
503 {
504  throw jit_fail_exception ("No visit_octave_user_function_trailer implementation");
505 }
506 
507 void
509 {
510  throw jit_fail_exception ("No visit_function_def implementation");
511 }
512 
513 void
515 {
516  if (ti.has_magic_end ())
517  {
518  if (!end_context.size ())
519  throw jit_fail_exception ("Illegal end");
521  }
522  else
523  {
524  jit_variable *var = get_variable (ti.name ());
525  jit_instruction *instr;
526  instr = factory.create<jit_call> (&jit_typeinfo::grab, var);
527  result = block->append (instr);
528  }
529 }
530 
531 void
533 {
534  throw jit_fail_exception ("No visit_if_clause implementation");
535 }
536 
537 void
539 {
540  tree_if_command_list *lst = cmd.cmd_list ();
541  assert (lst); // jwe: Can this be null?
542  lst->accept (*this);
543 }
544 
545 void
547 {
548  tree_if_clause *last = lst.back ();
549  size_t last_else = static_cast<size_t> (last->is_else_clause ());
550 
551  // entry_blocks represents the block you need to enter in order to execute
552  // the condition check for the ith clause. For the else, it is simple the
553  // else body. If there is no else body, then it is padded with the tail
554  std::vector<jit_block *> entry_blocks (lst.size () + 1 - last_else);
555  entry_blocks[0] = block;
556 
557  // we need to construct blocks first, because they have jumps to eachother
559  ++iter;
560  for (size_t i = 1; iter != lst.end (); ++iter, ++i)
561  {
562  tree_if_clause *tic = *iter;
563  if (tic->is_else_clause ())
564  entry_blocks[i] = factory.create<jit_block> ("else");
565  else
566  entry_blocks[i] = factory.create<jit_block> ("ifelse_cond");
567  }
568 
569  jit_block *tail = factory.create<jit_block> ("if_tail");
570  if (! last_else)
571  entry_blocks[entry_blocks.size () - 1] = tail;
572 
573 
574  // each branch in the if statement will have different breaks/continues
575  block_list current_breaks = breaks;
576  block_list current_continues = continues;
577  breaks.clear ();
578  continues.clear ();
579 
580  size_t num_incomming = 0; // number of incomming blocks to our tail
581  iter = lst.begin ();
582  for (size_t i = 0; iter != lst.end (); ++iter, ++i)
583  {
584  tree_if_clause *tic = *iter;
585  block = entry_blocks[i];
586  assert (block);
587 
588  if (i) // the first block is prev_block, so it has already been added
589  blocks.push_back (entry_blocks[i]);
590 
591  if (! tic->is_else_clause ())
592  {
593  tree_expression *expr = tic->condition ();
594  jit_value *cond = visit (expr);
596  cond);
597  jit_block *body = factory.create<jit_block> (i == 0 ? "if_body"
598  : "ifelse_body");
599  blocks.push_back (body);
600 
601  jit_instruction *br = factory.create<jit_cond_branch> (check, body,
602  entry_blocks[i + 1]);
603  block->append (br);
604  block = body;
605  }
606 
607  tree_statement_list *stmt_lst = tic->commands ();
608  assert (stmt_lst); // jwe: Can this be null?
609 
610  try
611  {
612  stmt_lst->accept (*this);
613  ++num_incomming;
614  block->append (factory.create<jit_branch> (tail));
615  }
616  catch (const jit_break_exception&)
617  { }
618 
619  current_breaks.splice (current_breaks.end (), breaks);
620  current_continues.splice (current_continues.end (), continues);
621  }
622 
623  breaks.splice (breaks.end (), current_breaks);
624  continues.splice (continues.end (), current_continues);
625 
626  if (num_incomming || ! last_else)
627  {
628  blocks.push_back (tail);
629  block = tail;
630  }
631  else
632  // every branch broke, so we don't have a tail
633  throw jit_break_exception ();
634 }
635 
636 void
638 {
639  result = resolve (exp);
640 }
641 
642 void
644 {
645  throw jit_fail_exception ("No visit_matrix implementation");
646 }
647 
648 void
650 {
651  throw jit_fail_exception ("No visit_cell implementation");
652 }
653 
654 void
656 {
657  throw jit_fail_exception ("No visit_multi_assignment implementation");
658 }
659 
660 void
662 {
663  throw jit_fail_exception ("No visit_no_op_command implementation");
664 }
665 
666 void
668 {
669  octave_value v = tc.rvalue1 ();
671 
672  if (ty == jit_typeinfo::get_scalar ())
673  {
674  double dv = v.double_value ();
676  }
677  else if (ty == jit_typeinfo::get_range ())
678  {
679  Range rv = v.range_value ();
681  }
682  else if (ty == jit_typeinfo::get_complex ())
683  {
684  Complex cv = v.complex_value ();
686  }
687  else
688  throw jit_fail_exception ("Unknown constant");
689 }
690 
691 void
693 {
694  throw jit_fail_exception ("No visit_fcn_handle implementation");
695 }
696 
697 void
699 {
700  throw jit_fail_exception ();
701 }
702 
703 void
705 {
706  throw jit_fail_exception ("No visit_parameter_list implementation");
707 }
708 
709 void
711 {
712  octave_value::unary_op etype = tpe.op_type ();
713  tree_expression *operand = tpe.operand ();
714  jit_value *operandv = visit (operand);
715 
716  const jit_operation& fn = jit_typeinfo::unary_op (etype);
717  result = create_checked (fn, operandv);
718 
719  if (etype == octave_value::op_incr || etype == octave_value::op_decr)
720  {
721  jit_value *ret = create_checked (&jit_typeinfo::grab, operandv);
722  do_assign (operand, result);
723  result = ret;
724  }
725 }
726 
727 void
729 {
730  octave_value::unary_op etype = tpe.op_type ();
731  tree_expression *operand = tpe.operand ();
732  const jit_operation& fn = jit_typeinfo::unary_op (etype);
733  result = create_checked (fn, visit (operand));
734 
735  if (etype == octave_value::op_incr || etype == octave_value::op_decr)
736  do_assign (operand, result);
737 }
738 
739 void
741 {
742  throw jit_fail_exception ("No visit_return_command implementation");
743 }
744 
745 void
747 {
748  throw jit_fail_exception ("No visit_return_list implementation");
749 }
750 
751 void
753 {
754  tree_expression *rhs = tsa.right_hand_side ();
755  jit_value *rhsv = visit (rhs);
756  octave_value::assign_op op = tsa.op_type ();
757 
758  if (op != octave_value::op_asn_eq)
759  {
760  // do the equivlent binary operation, then assign. This is always correct,
761  // but isn't always optimal.
762  tree_expression *lhs = tsa.left_hand_side ();
763  jit_value *lhsv = visit (lhs);
765  const jit_operation& fn = jit_typeinfo::binary_op (bop);
766  rhsv = create_checked (fn, lhsv, rhsv);
767  }
768 
769  result = do_assign (tsa.left_hand_side (), rhsv);
770 }
771 
772 void
774 {
775  tree_command *cmd = stmt.command ();
776  tree_expression *expr = stmt.expression ();
777 
778  if (cmd)
779  visit (cmd);
780  else
781  {
782  // stolen from tree_evaluator::visit_statement
783  bool do_bind_ans = false;
784 
785  if (expr->is_identifier ())
786  {
787  tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
788 
789  do_bind_ans = (! id->is_variable ());
790  }
791  else
792  do_bind_ans = (! expr->is_assignment_expression ());
793 
794  jit_value *expr_result = visit (expr);
795 
796  if (do_bind_ans)
797  do_assign ("ans", expr_result, expr->print_result ());
798  else if (expr->is_identifier () && expr->print_result ())
799  {
800  // FIXME: ugly hack, we need to come up with a way to pass
801  // nargout to visit_identifier
804  (expr->name ());
805  block->append (factory.create<jit_call> (fn, name, expr_result));
806  }
807  }
808 }
809 
810 void
812 {
813  for (tree_statement_list::iterator iter = lst.begin (); iter != lst.end();
814  ++iter)
815  {
816  tree_statement *elt = *iter;
817  // jwe: Can this ever be null?
818  assert (elt);
819  elt->accept (*this);
820  }
821 }
822 
823 void
825 {
826  throw jit_fail_exception ("No visit_switch_case implementation");
827 }
828 
829 void
831 {
832  throw jit_fail_exception ("No visit_switch_case_list implementation");
833 }
834 
835 void
837 {
838  tree_switch_case_list *lst = cmd.case_list ();
839 
840  // always visit switch expression
841  tree_expression *expr = cmd.switch_value ();
842  assert (expr && "Switch value can not be null");
843  jit_value *value = visit (expr);
844  assert (value);
845 
846  size_t case_blocks_num = lst->size ();
847 
848  if (! case_blocks_num) // there's nothing to do
849  return;
850 
851  // check for otherwise, it's interpreted as last 'else' condition
852  size_t has_otherwise = 0;
853  tree_switch_case *last = lst->back ();
854  if (last->is_default_case ())
855  has_otherwise = 1;
856 
857  std::vector<jit_block *> entry_blocks (case_blocks_num + 1 - has_otherwise);
858 
859  // the first entry point is always the actual block. afterward new blocks
860  // are created for every case and the otherwise branch
861  entry_blocks[0] = block;
862  for (size_t i = 1; i < case_blocks_num; ++i)
863  entry_blocks[i] = factory.create<jit_block> ("case_cond");
864 
865  jit_block *tail = factory.create<jit_block> ("switch_tail");
866 
867  // if there's no otherwise branch, the the 'else' of the last branch
868  // has to point to the tail
869  if (! has_otherwise)
870  entry_blocks[entry_blocks.size()-1] = tail;
871 
872  // each branch in the case statement will have different breaks/continues
873  block_list current_breaks = breaks;
874  block_list current_continues = continues;
875  breaks.clear ();
876  continues.clear ();
877 
878  size_t num_incomming = 0; // number of incomming blocks to our tail
879 
880  tree_switch_case_list::iterator iter = lst->begin ();
881  for (size_t i = 0; i < case_blocks_num; ++iter, ++i)
882  {
883  tree_switch_case *twc = *iter;
884  block = entry_blocks[i]; // case_cond
885  assert (block);
886 
887  if (i)
888  blocks.push_back (entry_blocks[i]); // first block already pushed
889 
890  if (! twc->is_default_case ())
891  {
892  // compare result of switch expression with actual case label
893  tree_expression *te = twc->case_label ();
894  jit_value *label = visit (te);
895  assert(label);
896 
898  jit_value *cond = create_checked (fn, value, label);
899  assert(cond);
900 
902  cond);
903 
904  jit_block *body = factory.create<jit_block> ("case_body");
905  blocks.push_back (body);
906 
907  block->append (factory.create<jit_cond_branch> (check, body,
908  entry_blocks[i+1]));
909  block = body; // case_body
910  }
911 
912  tree_statement_list *stmt_lst = twc->commands ();
913  assert(stmt_lst);
914 
915  try
916  {
917  stmt_lst->accept (*this);
918  num_incomming++;
919  block->append (factory.create<jit_branch> (tail));
920  }
921  catch (const jit_break_exception&)
922  { }
923 
924  // each branch in the case statement will have different breaks/continues
925  current_breaks.splice (current_breaks.end (), breaks);
926  current_continues.splice (current_continues.end (), continues);
927  }
928 
929  // each branch in the case statement will have different breaks/continues
930  breaks.splice (breaks.end (), current_breaks);
931  continues.splice (continues.end (), current_continues);
932 
933  if (num_incomming || ! has_otherwise)
934  {
935  blocks.push_back (tail);
936  block = tail; // switch_tail
937  }
938  else
939  throw jit_break_exception (); // every branch broke
940 }
941 
942 void
944 {
945  throw jit_fail_exception ("No visit_try_catch_command implementation");
946 }
947 
948 void
950 {
951  throw jit_fail_exception ("No visit_unwind_protect_command implementation");
952 }
953 
954 void
956 {
957  unwind_protect prot;
958  prot.protect_var (breaks);
959  prot.protect_var (continues);
960  breaks.clear ();
961  continues.clear ();
962 
963  jit_block *cond_check = factory.create<jit_block> ("while_cond_check");
964  block->append (factory.create<jit_branch> (cond_check));
965  blocks.push_back (cond_check);
966  block = cond_check;
967 
968  tree_expression *expr = wc.condition ();
969  assert (expr && "While expression can not be null");
970  jit_value *check = visit (expr);
972 
973  jit_block *body = factory.create<jit_block> ("while_body");
974  blocks.push_back (body);
975 
976  jit_block *tail = factory.create<jit_block> ("while_tail");
977  block->append (factory.create<jit_cond_branch> (check, body, tail));
978  block = body;
979 
980  tree_statement_list *loop_body = wc.body ();
981  bool all_breaking = false;
982  if (loop_body)
983  {
984  try
985  {
986  loop_body->accept (*this);
987  }
988  catch (const jit_break_exception&)
989  {
990  all_breaking = true;
991  }
992  }
993 
994  finish_breaks (tail, breaks);
995 
996  if (! all_breaking || continues.size ())
997  {
998  jit_block *interrupt_check
999  = factory.create<jit_block> ("interrupt_check");
1000  blocks.push_back (interrupt_check);
1001  finish_breaks (interrupt_check, continues);
1002  if (! all_breaking)
1003  block->append (factory.create<jit_branch> (interrupt_check));
1004 
1005  block = interrupt_check;
1006  jit_error_check *ec
1008  cond_check, final_block);
1009  block->append (ec);
1010  }
1011 
1012  blocks.push_back (tail);
1013  block = tail;
1014 }
1015 
1016 void
1018 {
1019  unwind_protect prot;
1020  prot.protect_var (breaks);
1021  prot.protect_var (continues);
1022  breaks.clear ();
1023  continues.clear ();
1024 
1025  jit_block *body = factory.create<jit_block> ("do_until_body");
1026  jit_block *cond_check = factory.create<jit_block> ("do_until_cond_check");
1027  jit_block *tail = factory.create<jit_block> ("do_until_tail");
1028 
1029  block->append (factory.create<jit_branch> (body));
1030  blocks.push_back (body);
1031  block = body;
1032 
1033  tree_statement_list *loop_body = duc.body ();
1034  bool all_breaking = false;
1035  if (loop_body)
1036  {
1037  try
1038  {
1039  loop_body->accept (*this);
1040  }
1041  catch (const jit_break_exception&)
1042  {
1043  all_breaking = true;
1044  }
1045  }
1046 
1047  finish_breaks (tail, breaks);
1048 
1049  if (! all_breaking || continues.size ())
1050  {
1051  jit_block *interrupt_check
1052  = factory.create<jit_block> ("interrupt_check");
1053  blocks.push_back (interrupt_check);
1054  finish_breaks (interrupt_check, continues);
1055  if (! all_breaking)
1056  block->append (factory.create<jit_branch> (interrupt_check));
1057 
1058  block = interrupt_check;
1059  jit_error_check *ec
1061  cond_check, final_block);
1062  block->append (ec);
1063 
1064  blocks.push_back (cond_check);
1065  block = cond_check;
1066 
1067  tree_expression *expr = duc.condition ();
1068  assert (expr && "Do-Until expression can not be null");
1069  jit_value *check = visit (expr);
1070  check = create_checked (&jit_typeinfo::logically_true, check);
1071 
1072  block->append (factory.create<jit_cond_branch> (check, tail, body));
1073  }
1074 
1075  blocks.push_back (tail);
1076  block = tail;
1077 }
1078 
1079 void
1081 {
1082  scope = s;
1083  iterator_count = 0;
1084  for_bounds_count = 0;
1085  short_count = 0;
1087 
1088  entry_block = factory.create<jit_block> ("body");
1089  final_block = factory.create<jit_block> ("final");
1091  entry_block->mark_alive ();
1092  block = entry_block;
1093 }
1094 
1095 jit_call *
1097 {
1098  block->append (ret);
1099 
1100  jit_block *normal = factory.create<jit_block> (block->name ());
1101  jit_error_check *check
1103  normal, final_block);
1104  block->append (check);
1105  blocks.push_back (normal);
1106  block = normal;
1107 
1108  return ret;
1109 }
1110 
1111 jit_variable *
1112 jit_convert::find_variable (const std::string& vname) const
1113 {
1114  variable_map::const_iterator iter;
1115  iter = vmap.find (vname);
1116  return iter != vmap.end () ? iter->second : 0;
1117 }
1118 
1119 jit_variable *
1120 jit_convert::get_variable (const std::string& vname)
1121 {
1122  jit_variable *ret = find_variable (vname);
1123  if (ret)
1124  return ret;
1125 
1127  if (record.is_persistent () || record.is_global ())
1128  throw jit_fail_exception ("Persistent and global not yet supported");
1129 
1130  if (converting_function)
1131  return create_variable (vname, jit_typeinfo::get_any (), false);
1132  else
1133  {
1134  octave_value val = record.varval ();
1135  if (val.is_undefined ())
1136  val = symbol_table::find_function (vname);
1137 
1139  bounds.push_back (type_bound (type, vname));
1140 
1141  return create_variable (vname, type);
1142  }
1143 }
1144 
1145 jit_variable *
1146 jit_convert::create_variable (const std::string& vname, jit_type *type,
1147  bool isarg)
1148 {
1149  jit_variable *var = factory.create<jit_variable> (vname);
1150 
1151  if (isarg)
1152  {
1153  jit_extract_argument *extract;
1154  extract = factory.create<jit_extract_argument> (type, var);
1155  entry_block->prepend (extract);
1156  }
1157  else
1158  {
1160  jit_assign *assign = factory.create<jit_assign> (var, init);
1161  entry_block->prepend (assign);
1162  entry_block->prepend (init);
1163  }
1164 
1165  return vmap[vname] = var;
1166 }
1167 
1168 std::string
1169 jit_convert::next_name (const char *prefix, size_t& count, bool inc)
1170 {
1171  std::stringstream ss;
1172  ss << prefix << count;
1173  if (inc)
1174  ++count;
1175  return ss.str ();
1176 }
1177 
1180  bool lhs)
1181 {
1182  std::string type = exp.type_tags ();
1183  if (! (type.size () == 1 && type[0] == '('))
1184  throw jit_fail_exception ("Unsupported index operation");
1185 
1186  std::list<tree_argument_list *> args = exp.arg_lists ();
1187  if (args.size () != 1)
1188  throw jit_fail_exception ("Bad number of arguments in "
1189  "tree_index_expression");
1190 
1191  tree_argument_list *arg_list = args.front ();
1192  if (! arg_list)
1193  throw jit_fail_exception ("null argument list");
1194 
1195  if (arg_list->size () < 1)
1196  throw jit_fail_exception ("Empty arg_list");
1197 
1198  tree_expression *tree_object = exp.expression ();
1199  jit_value *object;
1200  if (lhs)
1201  {
1202  tree_identifier *id = dynamic_cast<tree_identifier *> (tree_object);
1203  if (! id)
1204  throw jit_fail_exception ("expected identifier");
1205  object = get_variable (id->name ());
1206  }
1207  else
1208  object = visit (tree_object);
1209 
1210  size_t narg = arg_list->size ();
1211  tree_argument_list::iterator iter = arg_list->begin ();
1212  bool have_extra = extra_arg;
1213  std::vector<jit_value *> call_args (narg + 1 + have_extra);
1214  call_args[0] = object;
1215 
1216  for (size_t idx = 0; iter != arg_list->end (); ++idx, ++iter)
1217  {
1218  unwind_protect prot;
1219  prot.add_method (&end_context,
1220  &std::vector<jit_magic_end::context>::pop_back);
1221 
1222  jit_magic_end::context ctx (factory, object, idx, narg);
1223  end_context.push_back (ctx);
1224  call_args[idx + 1] = visit (*iter);
1225  }
1226 
1227  if (extra_arg)
1228  call_args[call_args.size () - 1] = extra_arg;
1229 
1230  const jit_operation& fres = lhs ? jit_typeinfo::paren_subsasgn ()
1232 
1233  return create_checked (fres, call_args);
1234 }
1235 
1236 jit_value *
1237 jit_convert::do_assign (tree_expression *exp, jit_value *rhs, bool artificial)
1238 {
1239  if (! exp)
1240  throw jit_fail_exception ("NULL lhs in assign");
1241 
1242  if (isa<tree_identifier> (exp))
1243  return do_assign (exp->name (), rhs, exp->print_result (), artificial);
1244  else if (tree_index_expression *idx
1245  = dynamic_cast<tree_index_expression *> (exp))
1246  {
1247  jit_value *new_object = resolve (*idx, rhs, true);
1248  do_assign (idx->expression (), new_object, true);
1249 
1250  // FIXME: Will not work for values that must be release/grabed
1251  return rhs;
1252  }
1253  else
1254  throw jit_fail_exception ("Unsupported assignment");
1255 }
1256 
1257 jit_value *
1258 jit_convert::do_assign (const std::string& lhs, jit_value *rhs,
1259  bool print, bool artificial)
1260 {
1261  jit_variable *var = get_variable (lhs);
1262  jit_assign *assign = block->append (factory.create<jit_assign> (var, rhs));
1263 
1264  if (artificial)
1265  assign->mark_artificial ();
1266 
1267  if (print)
1268  {
1269  const jit_operation& print_fn = jit_typeinfo::print_value ();
1271  block->append (factory.create<jit_call> (print_fn, name, var));
1272  }
1273 
1274  return var;
1275 }
1276 
1277 jit_value *
1279 {
1280  unwind_protect prot;
1281  prot.protect_var (result);
1282 
1283  tee.accept (*this);
1284  return result;
1285 }
1286 
1287 void
1289 {
1290  for (block_list::const_iterator iter = lst.begin (); iter != lst.end ();
1291  ++iter)
1292  {
1293  jit_block *b = *iter;
1294  b->append (factory.create<jit_branch> (dest));
1295  }
1296 }
1297 
1298 // -------------------- jit_convert_llvm --------------------
1299 llvm::Function *
1300 jit_convert_llvm::convert_loop (llvm::Module *module,
1301  const jit_block_list& blocks,
1302  const std::list<jit_value *>& constants)
1303 {
1304  converting_function = false;
1305 
1306  // for now just init arguments from entry, later we will have to do something
1307  // more interesting
1308  jit_block *entry_block = blocks.front ();
1309  for (jit_block::iterator iter = entry_block->begin ();
1310  iter != entry_block->end (); ++iter)
1311  if (jit_extract_argument *extract
1312  = dynamic_cast<jit_extract_argument *> (*iter))
1313  argument_vec.push_back (std::make_pair (extract->name (), true));
1314 
1315 
1316  jit_type *any = jit_typeinfo::get_any ();
1317 
1318  // argument is an array of octave_base_value*, or octave_base_value**
1319  llvm::Type *arg_type = any->to_llvm (); // this is octave_base_value*
1320  arg_type = arg_type->getPointerTo ();
1321  llvm::FunctionType *ft;
1322  ft = llvm::FunctionType::get (llvm::Type::getVoidTy (context), arg_type,
1323  false);
1324  function = llvm::Function::Create (ft, llvm::Function::ExternalLinkage,
1325  "foobar", module);
1326 
1327  try
1328  {
1329  prelude = llvm::BasicBlock::Create (context, "prelude", function);
1330  builder.SetInsertPoint (prelude);
1331 
1332  llvm::Value *arg = function->arg_begin ();
1333  for (size_t i = 0; i < argument_vec.size (); ++i)
1334  {
1335  llvm::Value *loaded_arg = builder.CreateConstInBoundsGEP1_32 (arg, i);
1336  arguments[argument_vec[i].first] = loaded_arg;
1337  }
1338 
1339  convert (blocks, constants);
1340  }
1341  catch (const jit_fail_exception& e)
1342  {
1343  function->eraseFromParent ();
1344  throw;
1345  }
1346 
1347  return function;
1348 }
1349 
1350 
1353  const jit_block_list& blocks,
1354  const std::list<jit_value *>& constants,
1355  octave_user_function& fcn,
1356  const std::vector<jit_type *>& args)
1357 {
1358  converting_function = true;
1359 
1360  jit_block *final_block = blocks.back ();
1361  jit_return *ret = dynamic_cast<jit_return *> (final_block->back ());
1362  assert (ret);
1363 
1365  "foobar", ret->result_type (), args);
1366  function = creating.to_llvm ();
1367 
1368  try
1369  {
1370  prelude = creating.new_block ("prelude");
1371  builder.SetInsertPoint (prelude);
1372 
1373  tree_parameter_list *plist = fcn.parameter_list ();
1374  if (plist)
1375  {
1376  tree_parameter_list::iterator piter = plist->begin ();
1377  tree_parameter_list::iterator pend = plist->end ();
1378  for (size_t i = 0; i < args.size () && piter != pend; ++i, ++piter)
1379  {
1380  tree_decl_elt *elt = *piter;
1381  std::string arg_name = elt->name ();
1382  arguments[arg_name] = creating.argument (builder, i);
1383  }
1384  }
1385 
1386  convert (blocks, constants);
1387  }
1388  catch (const jit_fail_exception& e)
1389  {
1390  function->eraseFromParent ();
1391  throw;
1392  }
1393 
1394  return creating;
1395 }
1396 
1397 void
1399  const std::list<jit_value *>& constants)
1400 {
1401  std::list<jit_block *>::const_iterator biter;
1402  for (biter = blocks.begin (); biter != blocks.end (); ++biter)
1403  {
1404  jit_block *jblock = *biter;
1405  llvm::BasicBlock *block = llvm::BasicBlock::Create (context,
1406  jblock->name (),
1407  function);
1408  jblock->stash_llvm (block);
1409  }
1410 
1411  jit_block *first = *blocks.begin ();
1412  builder.CreateBr (first->to_llvm ());
1413 
1414  // constants aren't in the IR, we visit those first
1415  for (std::list<jit_value *>::const_iterator iter = constants.begin ();
1416  iter != constants.end (); ++iter)
1417  if (! isa<jit_instruction> (*iter))
1418  visit (*iter);
1419 
1420  // convert all instructions
1421  for (biter = blocks.begin (); biter != blocks.end (); ++biter)
1422  visit (*biter);
1423 
1424  // now finish phi nodes
1425  for (biter = blocks.begin (); biter != blocks.end (); ++biter)
1426  {
1427  jit_block& block = **biter;
1428  for (jit_block::iterator piter = block.begin ();
1429  piter != block.end () && isa<jit_phi> (*piter); ++piter)
1430  {
1431  jit_instruction *phi = *piter;
1432  finish_phi (static_cast<jit_phi *> (phi));
1433  }
1434  }
1435 }
1436 
1437 void
1439 {
1440  llvm::PHINode *llvm_phi = phi->to_llvm ();
1441  for (size_t i = 0; i < phi->argument_count (); ++i)
1442  {
1443  llvm::BasicBlock *pred = phi->incomming_llvm (i);
1444  llvm_phi->addIncoming (phi->argument_llvm (i), pred);
1445  }
1446 }
1447 
1448 void
1450 {
1451  cs.stash_llvm (builder.CreateGlobalStringPtr (cs.value ()));
1452 }
1453 
1454 void
1456 {
1457  cb.stash_llvm (llvm::ConstantInt::get (cb.type_llvm (), cb.value ()));
1458 }
1459 
1460 void
1462 {
1463  cs.stash_llvm (llvm::ConstantFP::get (cs.type_llvm (), cs.value ()));
1464 }
1465 
1466 void
1468 {
1469  llvm::Type *scalar_t = jit_typeinfo::get_scalar_llvm ();
1470  Complex value = cc.value ();
1471  llvm::Value *real = llvm::ConstantFP::get (scalar_t, value.real ());
1472  llvm::Value *imag = llvm::ConstantFP::get (scalar_t, value.imag ());
1473  cc.stash_llvm (jit_typeinfo::create_complex (real, imag));
1474 }
1475 
1477 {
1478  ci.stash_llvm (llvm::ConstantInt::get (ci.type_llvm (), ci.value ()));
1479 }
1480 
1481 void
1483 {
1484  llvm::StructType *stype = llvm::cast<llvm::StructType>(cr.type_llvm ());
1485  llvm::Type *scalar_t = jit_typeinfo::get_scalar_llvm ();
1486  llvm::Type *idx = jit_typeinfo::get_index_llvm ();
1487  const jit_range& rng = cr.value ();
1488 
1489  llvm::Constant *constants[4];
1490  constants[0] = llvm::ConstantFP::get (scalar_t, rng.base);
1491  constants[1] = llvm::ConstantFP::get (scalar_t, rng.limit);
1492  constants[2] = llvm::ConstantFP::get (scalar_t, rng.inc);
1493  constants[3] = llvm::ConstantInt::get (idx, rng.nelem);
1494 
1495  llvm::Value *as_llvm;
1496  as_llvm = llvm::ConstantStruct::get (stype,
1497  llvm::makeArrayRef (constants, 4));
1498  cr.stash_llvm (as_llvm);
1499 }
1500 
1501 void
1503 {
1504  llvm::BasicBlock *block = b.to_llvm ();
1505  builder.SetInsertPoint (block);
1506  for (jit_block::iterator iter = b.begin (); iter != b.end (); ++iter)
1507  visit (*iter);
1508 }
1509 
1510 void
1512 {
1513  b.stash_llvm (builder.CreateBr (b.successor_llvm ()));
1514 }
1515 
1516 void
1518 {
1519  llvm::Value *cond = cb.cond_llvm ();
1520  llvm::Value *br;
1521  br = builder.CreateCondBr (cond, cb.successor_llvm (0),
1522  cb.successor_llvm (1));
1523  cb.stash_llvm (br);
1524 }
1525 
1526 void
1528 {
1529  const jit_function& ol = call.overload ();
1530 
1531  std::vector<jit_value *> args (call.arguments ().size ());
1532  for (size_t i = 0; i < args.size (); ++i)
1533  args[i] = call.argument (i);
1534 
1535  llvm::Value *ret = ol.call (builder, args);
1536  call.stash_llvm (ret);
1537 }
1538 
1539 void
1541 {
1542  llvm::Value *arg = arguments[extract.name ()];
1543  assert (arg);
1544 
1545  if (converting_function)
1546  extract.stash_llvm (arg);
1547  else
1548  {
1549  arg = builder.CreateLoad (arg);
1550 
1551  const jit_function& ol = extract.overload ();
1552  extract.stash_llvm (ol.call (builder, arg));
1553  }
1554 }
1555 
1556 void
1558 {
1559  const jit_function& ol = store.overload ();
1560  llvm::Value *arg_value = ol.call (builder, store.result ());
1561  llvm::Value *arg = arguments[store.name ()];
1562  store.stash_llvm (builder.CreateStore (arg_value, arg));
1563 }
1564 
1565 void
1567 {
1568  jit_value *res = ret.result ();
1569 
1570  if (converting_function)
1571  creating.do_return (builder, res->to_llvm (), false);
1572  else
1573  {
1574  if (res)
1575  builder.CreateRet (res->to_llvm ());
1576  else
1577  builder.CreateRetVoid ();
1578  }
1579 }
1580 
1581 void
1583 {
1584  // we might not have converted all incoming branches, so we don't
1585  // set incomming branches now
1586  llvm::PHINode *node = llvm::PHINode::Create (phi.type_llvm (),
1587  phi.argument_count ());
1588  builder.Insert (node);
1589  phi.stash_llvm (node);
1590 }
1591 
1592 void
1594 {
1595  throw jit_fail_exception ("ERROR: SSA construction should remove all variables");
1596 }
1597 
1598 void
1600 {
1601  llvm::Value *cond;
1602 
1603  switch (check.check_variable ())
1604  {
1607  break;
1610  break;
1611  default:
1612  panic_impossible ();
1613  }
1614 
1615  llvm::Value *br = builder.CreateCondBr (cond, check.successor_llvm (0),
1616  check.successor_llvm (1));
1617  check.stash_llvm (br);
1618 }
1619 
1620 void
1622 {
1623  jit_value *new_value = assign.src ();
1624  assign.stash_llvm (new_value->to_llvm ());
1625 
1626  if (assign.artificial ())
1627  return;
1628 
1629  jit_value *overwrite = assign.overwrite ();
1630  if (isa<jit_assign_base> (overwrite))
1631  {
1632  const jit_function& ol = jit_typeinfo::get_release (overwrite->type ());
1633  if (ol.valid ())
1634  ol.call (builder, overwrite);
1635  }
1636 }
1637 
1638 void
1640 {}
1641 
1642 void
1644 {
1645  const jit_function& ol = me.overload ();
1646 
1648  llvm::Value *ret = ol.call (builder, ctx.value, ctx.index, ctx.count);
1649  me.stash_llvm (ret);
1650 }
1651 
1652 // -------------------- jit_infer --------------------
1654  const variable_map& avmap)
1655  : blocks (ablocks), factory (afactory), vmap (avmap) { }
1656 
1657 void
1659 {
1660  construct_ssa ();
1661 
1662  // initialize the worklist to instructions derived from constants
1663  const std::list<jit_value *>& constants = factory.constants ();
1664  for (std::list<jit_value *>::const_iterator iter = constants.begin ();
1665  iter != constants.end (); ++iter)
1666  append_users (*iter);
1667 
1668  // the entry block terminator may be a regular branch statement
1669  if (entry_block ().terminator ())
1671 
1672  // FIXME: Describe algorithm here
1673  while (worklist.size ())
1674  {
1675  jit_instruction *next = worklist.front ();
1676  worklist.pop_front ();
1677  next->stash_in_worklist (false);
1678 
1679  if (next->infer ())
1680  {
1681  // terminators need to be handles specially
1682  if (jit_terminator *term = dynamic_cast<jit_terminator *> (next))
1683  append_users_term (term);
1684  else
1685  append_users (next);
1686  }
1687  }
1688 
1689  remove_dead ();
1690  blocks.label ();
1691  place_releases ();
1692  simplify_phi ();
1693 }
1694 
1695 void
1697 {
1698  for (jit_use *use = v->first_use (); use; use = use->next ())
1699  push_worklist (use->user ());
1700 }
1701 
1702 void
1704 {
1705  for (size_t i = 0; i < term->successor_count (); ++i)
1706  {
1707  if (term->alive (i))
1708  {
1709  jit_block *succ = term->successor (i);
1710  for (jit_block::iterator iter = succ->begin ();
1711  iter != succ->end () && isa<jit_phi> (*iter); ++iter)
1712  push_worklist (*iter);
1713 
1714  jit_terminator *sterm = succ->terminator ();
1715  if (sterm)
1716  push_worklist (sterm);
1717  }
1718  }
1719 }
1720 
1721 void
1723 {
1724  blocks.label ();
1726  entry_block ().compute_df ();
1728 
1729  // insert phi nodes where needed, this is done on a per variable basis
1730  for (variable_map::const_iterator iter = vmap.begin (); iter != vmap.end ();
1731  ++iter)
1732  {
1733  jit_block::df_set visited, added_phi;
1734  std::list<jit_block *> ssa_worklist;
1735  iter->second->use_blocks (visited);
1736  ssa_worklist.insert (ssa_worklist.begin (), visited.begin (),
1737  visited.end ());
1738 
1739  while (ssa_worklist.size ())
1740  {
1741  jit_block *b = ssa_worklist.front ();
1742  ssa_worklist.pop_front ();
1743 
1744  for (jit_block::df_iterator diter = b->df_begin ();
1745  diter != b->df_end (); ++diter)
1746  {
1747  jit_block *dblock = *diter;
1748  if (! added_phi.count (dblock))
1749  {
1750  jit_phi *phi = factory.create<jit_phi> (iter->second,
1751  dblock->use_count ());
1752  dblock->prepend (phi);
1753  added_phi.insert (dblock);
1754  }
1755 
1756  if (! visited.count (dblock))
1757  {
1758  ssa_worklist.push_back (dblock);
1759  visited.insert (dblock);
1760  }
1761  }
1762  }
1763  }
1764 
1765  do_construct_ssa (entry_block (), entry_block ().visit_count ());
1766 }
1767 
1768 void
1769 jit_infer::do_construct_ssa (jit_block& ablock, size_t avisit_count)
1770 {
1771  if (ablock.visited (avisit_count))
1772  return;
1773 
1774  // replace variables with their current SSA value
1775  for (jit_block::iterator iter = ablock.begin (); iter != ablock.end ();
1776  ++iter)
1777  {
1778  jit_instruction *instr = *iter;
1779  instr->construct_ssa ();
1780  instr->push_variable ();
1781  }
1782 
1783  // finish phi nodes of successors
1784  for (size_t i = 0; i < ablock.successor_count (); ++i)
1785  {
1786  jit_block *finish = ablock.successor (i);
1787 
1788  for (jit_block::iterator iter = finish->begin ();
1789  iter != finish->end () && isa<jit_phi> (*iter);)
1790  {
1791  jit_phi *phi = static_cast<jit_phi *> (*iter);
1792  jit_variable *var = phi->dest ();
1793  ++iter;
1794 
1795  if (var->has_top ())
1796  phi->add_incomming (&ablock, var->top ());
1797  else
1798  {
1799  // temporaries may have extranious phi nodes which can be removed
1800  assert (! phi->use_count ());
1801  assert (var->name ().size () && var->name ()[0] == '#');
1802  phi->remove ();
1803  }
1804  }
1805  }
1806 
1807  for (size_t i = 0; i < ablock.dom_successor_count (); ++i)
1808  do_construct_ssa (*ablock.dom_successor (i), avisit_count);
1809 
1810  ablock.pop_all ();
1811 }
1812 
1813 void
1815 {
1816  std::set<jit_value *> temporaries;
1817  for (jit_block_list::iterator iter = blocks.begin (); iter != blocks.end ();
1818  ++iter)
1819  {
1820  jit_block& ablock = **iter;
1821  if (ablock.id () != jit_block::NO_ID)
1822  {
1823  release_temp (ablock, temporaries);
1824  release_dead_phi (ablock);
1825  }
1826  }
1827 }
1828 
1829 void
1831 {
1832  if (! instr->in_worklist ())
1833  {
1834  instr->stash_in_worklist (true);
1835  worklist.push_back (instr);
1836  }
1837 }
1838 
1839 void
1841 {
1843  for (biter = blocks.begin (); biter != blocks.end (); ++biter)
1844  {
1845  jit_block *b = *biter;
1846  if (b->alive ())
1847  {
1848  for (jit_block::iterator iter = b->begin ();
1849  iter != b->end () && isa<jit_phi> (*iter);)
1850  {
1851  jit_phi *phi = static_cast<jit_phi *> (*iter);
1852  if (phi->prune ())
1853  iter = b->remove (iter);
1854  else
1855  ++iter;
1856  }
1857  }
1858  }
1859 
1860  for (biter = blocks.begin (); biter != blocks.end ();)
1861  {
1862  jit_block *b = *biter;
1863  if (b->alive ())
1864  {
1865  // FIXME: A special case for jit_error_check, if we generalize to
1866  // we will need to change!
1867  jit_terminator *term = b->terminator ();
1868  if (term && term->successor_count () == 2 && ! term->alive (0))
1869  {
1870  jit_block *succ = term->successor (1);
1871  term->remove ();
1872  jit_branch *abreak = factory.create<jit_branch> (succ);
1873  b->append (abreak);
1874  abreak->infer ();
1875  }
1876 
1877  ++biter;
1878  }
1879  else
1880  {
1881  jit_terminator *term = b->terminator ();
1882  if (term)
1883  term->remove ();
1884  biter = blocks.erase (biter);
1885  }
1886  }
1887 }
1888 
1889 void
1891 {
1892  jit_block::iterator iter = ablock.begin ();
1893  while (iter != ablock.end () && isa<jit_phi> (*iter))
1894  {
1895  jit_phi *phi = static_cast<jit_phi *> (*iter);
1896  ++iter;
1897 
1898  jit_use *use = phi->first_use ();
1899  if (phi->use_count () == 1 && isa<jit_assign> (use->user ()))
1900  {
1901  // instead of releasing on assign, release on all incomming branches,
1902  // this can get rid of casts inside loops
1903  for (size_t i = 0; i < phi->argument_count (); ++i)
1904  {
1905  jit_value *arg = phi->argument (i);
1906  if (! arg->needs_release ())
1907  continue;
1908 
1909  jit_block *inc = phi->incomming (i);
1910  jit_block *split = inc->maybe_split (factory, blocks, ablock);
1911  jit_terminator *term = split->terminator ();
1912  jit_call *release
1914  release->infer ();
1915  split->insert_before (term, release);
1916  }
1917 
1918  phi->replace_with (0);
1919  phi->remove ();
1920  }
1921  }
1922 }
1923 
1924 void
1925 jit_infer::release_temp (jit_block& ablock, std::set<jit_value *>& temp)
1926 {
1927  for (jit_block::iterator iter = ablock.begin (); iter != ablock.end ();
1928  ++iter)
1929  {
1930  jit_instruction *instr = *iter;
1931 
1932  // check for temporaries that require release and live across
1933  // multiple blocks
1934  if (instr->needs_release ())
1935  {
1936  jit_block *fu_block = instr->first_use_block ();
1937  if (fu_block && fu_block != &ablock && instr->needs_release ())
1938  temp.insert (instr);
1939  }
1940 
1941  if (isa<jit_call> (instr))
1942  {
1943  // place releases for temporary arguments
1944  for (size_t i = 0; i < instr->argument_count (); ++i)
1945  {
1946  jit_value *arg = instr->argument (i);
1947  if (! arg->needs_release ())
1948  continue;
1949 
1950  jit_call *release
1952  release->infer ();
1953  ablock.insert_after (iter, release);
1954  ++iter;
1955  temp.erase (arg);
1956  }
1957  }
1958  }
1959 
1960  if (! temp.size () || ! isa<jit_error_check> (ablock.terminator ()))
1961  return;
1962 
1963  // FIXME: If we support try/catch or unwind_protect final_block
1964  // may not be the destination
1965  jit_block *split = ablock.maybe_split (factory, blocks, final_block ());
1966  jit_terminator *term = split->terminator ();
1967  for (std::set<jit_value *>::const_iterator iter = temp.begin ();
1968  iter != temp.end (); ++iter)
1969  {
1970  jit_value *value = *iter;
1971  jit_call *release
1973  split->insert_before (term, release);
1974  release->infer ();
1975  }
1976 }
1977 
1978 void
1980 {
1981  for (jit_block_list::iterator biter = blocks.begin (); biter != blocks.end ();
1982  ++biter)
1983  {
1984  jit_block &ablock = **biter;
1985  for (jit_block::iterator iter = ablock.begin ();
1986  iter != ablock.end () && isa<jit_phi> (*iter); ++iter)
1987  simplify_phi (*static_cast<jit_phi *> (*iter));
1988  }
1989 }
1990 
1991 void
1993 {
1994  jit_block& pblock = *phi.parent ();
1995  const jit_operation& cast_fn = jit_typeinfo::cast (phi.type ());
1996  jit_variable *dest = phi.dest ();
1997  for (size_t i = 0; i < phi.argument_count (); ++i)
1998  {
1999  jit_value *arg = phi.argument (i);
2000  if (arg->type () != phi.type ())
2001  {
2002  jit_block *pred = phi.incomming (i);
2003  jit_block *split = pred->maybe_split (factory, blocks, pblock);
2004  jit_terminator *term = split->terminator ();
2005  jit_instruction *cast = factory.create<jit_call> (cast_fn, arg);
2006  jit_assign *assign = factory.create<jit_assign> (dest, cast);
2007 
2008  split->insert_before (term, cast);
2009  split->insert_before (term, assign);
2010  cast->infer ();
2011  assign->infer ();
2012  phi.stash_argument (i, assign);
2013  }
2014  }
2015 }
2016 
2017 // -------------------- tree_jit --------------------
2018 
2019 tree_jit::tree_jit (void) : module (0), engine (0)
2020 {
2021 }
2022 
2024 {}
2025 
2026 bool
2028 {
2029  return instance ().do_execute (cmd, bounds);
2030 }
2031 
2032 bool
2034 {
2035  return instance ().do_execute (cmd);
2036 }
2037 
2038 bool
2040  octave_value_list& retval)
2041 {
2042  return instance ().do_execute (fcn, args, retval);
2043 }
2044 
2045 tree_jit&
2047 {
2048  static tree_jit ret;
2049  return ret;
2050 }
2051 
2052 bool
2054 {
2055  if (engine)
2056  return true;
2057 
2058  if (! module)
2059  {
2060  llvm::InitializeNativeTarget ();
2061  module = new llvm::Module ("octave", context);
2062  }
2063 
2064  // sometimes this fails pre main
2065  engine = llvm::ExecutionEngine::createJIT (module);
2066 
2067  if (! engine)
2068  return false;
2069 
2070 #ifdef LEGACY_PASSMANAGER
2071  module_pass_manager = new llvm::legacy::PassManager ();
2072  pass_manager = new llvm::legacy::FunctionPassManager (module);
2073 #else
2074  module_pass_manager = new llvm::PassManager ();
2075  pass_manager = new llvm::FunctionPassManager (module);
2076 #endif
2077  module_pass_manager->add (llvm::createAlwaysInlinerPass ());
2078 
2079 #ifdef HAVE_LLVM_DATALAYOUT
2080  pass_manager->add (new llvm::DataLayout (*engine->getDataLayout ()));
2081 #else
2082  pass_manager->add (new llvm::TargetData (*engine->getTargetData ()));
2083 #endif
2084  pass_manager->add (llvm::createCFGSimplificationPass ());
2085  pass_manager->add (llvm::createBasicAliasAnalysisPass ());
2086  pass_manager->add (llvm::createPromoteMemoryToRegisterPass ());
2087  pass_manager->add (llvm::createInstructionCombiningPass ());
2088  pass_manager->add (llvm::createReassociatePass ());
2089  pass_manager->add (llvm::createGVNPass ());
2090  pass_manager->add (llvm::createCFGSimplificationPass ());
2091  pass_manager->doInitialization ();
2092 
2094 
2095  return true;
2096 }
2097 
2098 bool
2100 {
2101  size_t tc = trip_count (bounds);
2102  if (! tc || ! initialize () || ! enabled ())
2103  return false;
2104 
2105  jit_info::vmap extra_vars;
2106  extra_vars["#for_bounds0"] = &bounds;
2107 
2108  jit_info *info = cmd.get_info ();
2109  if (! info || ! info->match (extra_vars))
2110  {
2111  if (tc < static_cast<size_t> (Vjit_startcnt))
2112  return false;
2113 
2114  delete info;
2115  info = new jit_info (*this, cmd, bounds);
2116  cmd.stash_info (info);
2117  }
2118 
2119  return info->execute (extra_vars);
2120 }
2121 
2122 bool
2124 {
2125  if (! initialize () || ! enabled ())
2126  return false;
2127 
2128  jit_info *info = cmd.get_info ();
2129  if (! info || ! info->match ())
2130  {
2131  delete info;
2132  info = new jit_info (*this, cmd);
2133  cmd.stash_info (info);
2134  }
2135 
2136  return info->execute ();
2137 }
2138 
2139 bool
2141  octave_value_list& retval)
2142 {
2143  if (! initialize () || ! enabled ())
2144  return false;
2145 
2146  jit_function_info *info = fcn.get_info ();
2147  if (! info || ! info->match (args))
2148  {
2149  delete info;
2150  info = new jit_function_info (*this, fcn, args);
2151  fcn.stash_info (info);
2152  }
2153 
2154  return info->execute (args, retval);
2155 }
2156 
2157 bool
2159 {
2160  // Ideally, we should only disable JIT if there is a breakpoint in the code we
2161  // are about to run. However, we can't figure this out in O(1) time, so we
2162  // conservatively check for the existence of any breakpoints.
2165 }
2166 
2167 size_t
2168 tree_jit::trip_count (const octave_value& bounds) const
2169 {
2170  if (bounds.is_range ())
2171  {
2172  Range rng = bounds.range_value ();
2173  return rng.nelem ();
2174  }
2175 
2176  // unsupported type
2177  return 0;
2178 }
2179 
2180 
2181 void
2182 tree_jit::optimize (llvm::Function *fn)
2183 {
2184  if (Vdebug_jit)
2185  llvm::verifyModule (*module);
2186 
2187  module_pass_manager->run (*module);
2188  pass_manager->run (*fn);
2189 
2190  if (Vdebug_jit)
2191  {
2192  std::string error;
2193 #ifdef RAW_FD_OSTREAM_ARG_IS_LLVM_SYS_FS
2194  llvm::raw_fd_ostream fout ("test.bc", error,
2195  llvm::sys::fs::F_Binary);
2196 #else
2197  llvm::raw_fd_ostream fout ("test.bc", error,
2198  llvm::raw_fd_ostream::F_Binary);
2199 #endif
2200  llvm::WriteBitcodeToFile (module, fout);
2201  }
2202 }
2203 
2204 // -------------------- jit_function_info --------------------
2206  octave_user_function& fcn,
2207  const octave_value_list& ov_args)
2208  : argument_types (ov_args.length ()), function (0)
2209 {
2210  size_t nargs = ov_args.length ();
2211  for (size_t i = 0; i < nargs; ++i)
2212  argument_types[i] = jit_typeinfo::type_of (ov_args(i));
2213 
2214  jit_function raw_fn;
2215  jit_function wrapper;
2216 
2217  try
2218  {
2219  jit_convert conv (fcn, argument_types);
2220  jit_infer infer (conv.get_factory (), conv.get_blocks (),
2221  conv.get_variable_map ());
2222  infer.infer ();
2223 
2224  if (Vdebug_jit)
2225  {
2226  jit_block_list& blocks = infer.get_blocks ();
2227  blocks.label ();
2228  std::cout << "-------------------- Compiling function ";
2229  std::cout << "--------------------\n";
2230 
2231  tree_print_code tpc (std::cout);
2233  tpc.visit_statement_list (*fcn.body ());
2235  blocks.print (std::cout, "octave jit ir");
2236  }
2237 
2238  jit_factory& factory = conv.get_factory ();
2239  llvm::Module *module = tjit.get_module ();
2240  jit_convert_llvm to_llvm;
2241  raw_fn = to_llvm.convert_function (module, infer.get_blocks (),
2242  factory.constants (), fcn,
2243  argument_types);
2244 
2245  if (Vdebug_jit)
2246  {
2247  std::cout << "-------------------- raw function ";
2248  std::cout << "--------------------\n";
2249  std::cout << *raw_fn.to_llvm () << std::endl;
2250  llvm::verifyFunction (*raw_fn.to_llvm ());
2251  }
2252 
2253  std::string wrapper_name = fcn.name () + "_wrapper";
2254  jit_type *any_t = jit_typeinfo::get_any ();
2255  std::vector<jit_type *> wrapper_args (1, jit_typeinfo::get_any_ptr ());
2256  wrapper = jit_function (module, jit_convention::internal, wrapper_name,
2257  any_t, wrapper_args);
2258 
2259  llvm::BasicBlock *wrapper_body = wrapper.new_block ();
2260  builder.SetInsertPoint (wrapper_body);
2261 
2262  llvm::Value *wrapper_arg = wrapper.argument (builder, 0);
2263  std::vector<llvm::Value *> raw_args (nargs);
2264  for (size_t i = 0; i < nargs; ++i)
2265  {
2266  llvm::Value *arg;
2267  arg = builder.CreateConstInBoundsGEP1_32 (wrapper_arg, i);
2268  arg = builder.CreateLoad (arg);
2269 
2270  jit_type *arg_type = argument_types[i];
2271  const jit_function& cast = jit_typeinfo::cast (arg_type, any_t);
2272  raw_args[i] = cast.call (builder, arg);
2273  }
2274 
2275  llvm::Value *result = raw_fn.call (builder, raw_args);
2276  if (raw_fn.result ())
2277  {
2278  jit_type *raw_result_t = raw_fn.result ();
2279  const jit_function& cast = jit_typeinfo::cast (any_t, raw_result_t);
2280  result = cast.call (builder, result);
2281  }
2282  else
2283  {
2284  llvm::Value *zero = builder.getInt32 (0);
2285  result = builder.CreateBitCast (zero, any_t->to_llvm ());
2286  }
2287 
2288  wrapper.do_return (builder, result);
2289 
2290  llvm::Function *llvm_function = wrapper.to_llvm ();
2291  tjit.optimize (llvm_function);
2292 
2293  if (Vdebug_jit)
2294  {
2295  std::cout << "-------------------- optimized and wrapped ";
2296  std::cout << "--------------------\n";
2297  std::cout << *llvm_function << std::endl;
2298  llvm::verifyFunction (*llvm_function);
2299  }
2300 
2301  llvm::ExecutionEngine* engine = tjit.get_engine ();
2302  void *void_fn = engine->getPointerToFunction (llvm_function);
2303  function = reinterpret_cast<jited_function> (void_fn);
2304  }
2305  catch (const jit_fail_exception& e)
2306  {
2307  argument_types.clear ();
2308 
2309  if (Vdebug_jit)
2310  {
2311  if (e.known ())
2312  std::cout << "jit fail: " << e.what () << std::endl;
2313  }
2314 
2315  Vjit_failcnt++;
2316 
2317  wrapper.erase ();
2318  raw_fn.erase ();
2319  }
2320 }
2321 
2322 bool
2324  octave_value_list& retval) const
2325 {
2326  if (! function)
2327  return false;
2328 
2329  // TODO figure out a way to delete ov_args so we avoid duplicating refcount
2330  size_t nargs = ov_args.length ();
2331  std::vector<octave_base_value *> args (nargs);
2332  for (size_t i = 0; i < nargs; ++i)
2333  {
2334  octave_base_value *obv = ov_args(i).internal_rep ();
2335  obv->grab ();
2336  args[i] = obv;
2337  }
2338 
2339  octave_base_value *ret = function (&args[0]);
2340  if (ret)
2341  retval(0) = octave_value (ret);
2342 
2343  octave_quit ();
2344 
2345  return true;
2346 }
2347 
2348 bool
2350 {
2351  if (! function)
2352  return true;
2353 
2354  size_t nargs = ov_args.length ();
2355  if (nargs != argument_types.size ())
2356  return false;
2357 
2358  for (size_t i = 0; i < nargs; ++i)
2359  if (jit_typeinfo::type_of (ov_args(i)) != argument_types[i])
2360  return false;
2361 
2362  return true;
2363 }
2364 
2365 // -------------------- jit_info --------------------
2367  : engine (tjit.get_engine ()), function (0), llvm_function (0)
2368 {
2369  compile (tjit, tee);
2370 }
2371 
2372 jit_info::jit_info (tree_jit& tjit, tree& tee, const octave_value& for_bounds)
2373  : engine (tjit.get_engine ()), function (0), llvm_function (0)
2374 {
2375  compile (tjit, tee, jit_typeinfo::type_of (for_bounds));
2376 }
2377 
2379 {
2380  if (llvm_function)
2381  llvm_function->eraseFromParent ();
2382 }
2383 
2384 bool
2385 jit_info::execute (const vmap& extra_vars) const
2386 {
2387  if (! function)
2388  return false;
2389 
2390  std::vector<octave_base_value *> real_arguments (arguments.size ());
2391  for (size_t i = 0; i < arguments.size (); ++i)
2392  {
2393  if (arguments[i].second)
2394  {
2395  octave_value current = find (extra_vars, arguments[i].first);
2396  octave_base_value *obv = current.internal_rep ();
2397  obv->grab ();
2398  real_arguments[i] = obv;
2399  }
2400  }
2401 
2402  function (&real_arguments[0]);
2403 
2404  for (size_t i = 0; i < arguments.size (); ++i)
2405  {
2406  const std::string& name = arguments[i].first;
2407 
2408  // do not store for loop bounds temporary
2409  if (name.size () && name[0] != '#')
2410  symbol_table::assign (arguments[i].first, real_arguments[i]);
2411  }
2412 
2413  octave_quit ();
2414 
2415  return true;
2416 }
2417 
2418 bool
2419 jit_info::match (const vmap& extra_vars) const
2420 {
2421  if (! function)
2422  return true;
2423 
2424  for (size_t i = 0; i < bounds.size (); ++i)
2425  {
2426  const std::string& arg_name = bounds[i].second;
2427  octave_value value = find (extra_vars, arg_name);
2428  jit_type *type = jit_typeinfo::type_of (value);
2429 
2430  // FIXME: Check for a parent relationship
2431  if (type != bounds[i].first)
2432  return false;
2433  }
2434 
2435  return true;
2436 }
2437 
2438 void
2439 jit_info::compile (tree_jit& tjit, tree& tee, jit_type *for_bounds)
2440 {
2441  try
2442  {
2443  jit_convert conv (tee, for_bounds);
2444  jit_infer infer (conv.get_factory (), conv.get_blocks (),
2445  conv.get_variable_map ());
2446 
2447  infer.infer ();
2448 
2449  if (Vdebug_jit)
2450  {
2451  jit_block_list& blocks = infer.get_blocks ();
2452  blocks.label ();
2453  std::cout << "-------------------- Compiling tree --------------------\n";
2454  std::cout << tee.str_print_code () << std::endl;
2455  blocks.print (std::cout, "octave jit ir");
2456  }
2457 
2458  jit_factory& factory = conv.get_factory ();
2459  jit_convert_llvm to_llvm;
2460  llvm_function = to_llvm.convert_loop (tjit.get_module (),
2461  infer.get_blocks (),
2462  factory.constants ());
2463  arguments = to_llvm.get_arguments ();
2464  bounds = conv.get_bounds ();
2465  }
2466  catch (const jit_fail_exception& e)
2467  {
2468  if (Vdebug_jit)
2469  {
2470  if (e.known ())
2471  std::cout << "jit fail: " << e.what () << std::endl;
2472  }
2473 
2474  Vjit_failcnt++;
2475 
2476  }
2477 
2478  if (llvm_function)
2479  {
2480  if (Vdebug_jit)
2481  {
2482  std::cout << "-------------------- llvm ir --------------------";
2483  std::cout << *llvm_function << std::endl;
2484  llvm::verifyFunction (*llvm_function);
2485  }
2486 
2487  tjit.optimize (llvm_function);
2488 
2489  if (Vdebug_jit)
2490  {
2491  std::cout << "-------------------- optimized llvm ir "
2492  << "--------------------\n";
2493  std::cout << *llvm_function << std::endl;
2494  }
2495 
2496  void *void_fn = engine->getPointerToFunction (llvm_function);
2497  function = reinterpret_cast<jited_function> (void_fn);
2498  }
2499 }
2500 
2502 jit_info::find (const vmap& extra_vars, const std::string& vname) const
2503 {
2504  vmap::const_iterator iter = extra_vars.find (vname);
2505  return iter == extra_vars.end () ? symbol_table::varval (vname)
2506  : *iter->second;
2507 }
2508 
2509 #endif
2510 
2511 #if defined (HAVE_LLVM)
2512 #define UNUSED_WITHOUT_LLVM(x) x
2513 #else
2514 #define UNUSED_WITHOUT_LLVM(x) x GCC_ATTR_UNUSED
2515 #endif
2516 
2517 DEFUN (jit_failcnt, UNUSED_WITHOUT_LLVM (args),
2518  UNUSED_WITHOUT_LLVM (nargout),
2519  "-*- texinfo -*-\n\
2520 @deftypefn {Built-in Function} {@var{val} =} jit_failcnt ()\n\
2521 @deftypefnx {Built-in Function} {@var{old_val} =} jit_failcnt (@var{new_val})\n\
2522 @deftypefnx {Built-in Function} {} jit_failcnt (@var{new_val}, \"local\")\n\
2523 Query or set the internal variable that counts the number of JIT fail\n\
2524 exceptions for Octave's JIT compiler.\n\
2525 \n\
2526 When called from inside a function with the @qcode{\"local\"} option, the\n\
2527 variable is changed locally for the function and any subroutines it calls.\n\
2528 The original variable value is restored when exiting the function.\n\
2529 @seealso{jit_enable, jit_startcnt, debug_jit}\n\
2530 @end deftypefn")
2531 {
2532 #if defined (HAVE_LLVM)
2533  return SET_INTERNAL_VARIABLE (jit_failcnt);
2534 #else
2535  warning ("jit_failcnt: JIT compiling not available in this version of Octave");
2536  return octave_value ();
2537 #endif
2538 }
2539 
2540 DEFUN (debug_jit, UNUSED_WITHOUT_LLVM (args),
2541  UNUSED_WITHOUT_LLVM (nargout),
2542  "-*- texinfo -*-\n\
2543 @deftypefn {Built-in Function} {@var{val} =} debug_jit ()\n\
2544 @deftypefnx {Built-in Function} {@var{old_val} =} debug_jit (@var{new_val})\n\
2545 @deftypefnx {Built-in Function} {} debug_jit (@var{new_val}, \"local\")\n\
2546 Query or set the internal variable that determines whether\n\
2547 debugging/tracing is enabled for Octave's JIT compiler.\n\
2548 \n\
2549 When called from inside a function with the @qcode{\"local\"} option, the\n\
2550 variable is changed locally for the function and any subroutines it calls.\n\
2551 The original variable value is restored when exiting the function.\n\
2552 @seealso{jit_enable, jit_startcnt}\n\
2553 @end deftypefn")
2554 {
2555 #if defined (HAVE_LLVM)
2556  return SET_INTERNAL_VARIABLE (debug_jit);
2557 #else
2558  warning ("debug_jit: JIT compiling not available in this version of Octave");
2559  return octave_value ();
2560 #endif
2561 }
2562 
2563 DEFUN (jit_enable, UNUSED_WITHOUT_LLVM (args),
2564  UNUSED_WITHOUT_LLVM (nargout),
2565  "-*- texinfo -*-\n\
2566 @deftypefn {Built-in Function} {@var{val} =} jit_enable ()\n\
2567 @deftypefnx {Built-in Function} {@var{old_val} =} jit_enable (@var{new_val})\n\
2568 @deftypefnx {Built-in Function} {} jit_enable (@var{new_val}, \"local\")\n\
2569 Query or set the internal variable that enables Octave's JIT compiler.\n\
2570 \n\
2571 When called from inside a function with the @qcode{\"local\"} option, the\n\
2572 variable is changed locally for the function and any subroutines it calls.\n\
2573 The original variable value is restored when exiting the function.\n\
2574 @seealso{jit_startcnt, debug_jit}\n\
2575 @end deftypefn")
2576 {
2577 #if defined (HAVE_LLVM)
2578  return SET_INTERNAL_VARIABLE (jit_enable);
2579 #else
2580  warning ("jit_enable: JIT compiling not available in this version of Octave");
2581  return octave_value ();
2582 #endif
2583 }
2584 
2585 DEFUN (jit_startcnt, UNUSED_WITHOUT_LLVM (args),
2586  UNUSED_WITHOUT_LLVM (nargout),
2587  "-*- texinfo -*-\n\
2588 @deftypefn {Built-in Function} {@var{val} =} jit_startcnt ()\n\
2589 @deftypefnx {Built-in Function} {@var{old_val} =} jit_startcnt (@var{new_val})\n\
2590 @deftypefnx {Built-in Function} {} jit_startcnt (@var{new_val}, \"local\")\n\
2591 Query or set the internal variable that determines whether JIT compilation\n\
2592 will take place for a specific loop.\n\
2593 \n\
2594 Because compilation is a costly operation it does not make sense to employ\n\
2595 JIT when the loop count is low. By default only loops with greater than\n\
2596 1000 iterations will be accelerated.\n\
2597 \n\
2598 When called from inside a function with the @qcode{\"local\"} option, the\n\
2599 variable is changed locally for the function and any subroutines it calls.\n\
2600 The original variable value is restored when exiting the function.\n\
2601 @seealso{jit_enable, jit_failcnt, debug_jit}\n\
2602 @end deftypefn")
2603 {
2604 #if defined (HAVE_LLVM)
2605  return SET_INTERNAL_VARIABLE_WITH_LIMITS (jit_startcnt, 1,
2607 #else
2608  warning ("jit_enable: JIT compiling not available in this version of Octave");
2609  return octave_value ();
2610 #endif
2611 }
virtual void visit(jit_block &)
Definition: pt-jit.cc:1502
jit_type * result(void) const
Definition: jit-typeinfo.h:294
bool Vdebug_on_error
Definition: error.cc:58
void do_return(llvm::IRBuilderD &builder, llvm::Value *rval=0, bool verify=true)
octave_base_value *(* jited_function)(octave_base_value **)
Definition: pt-jit.h:406
size_t iterator_count
Definition: pt-jit.h:184
tree_expression * operand(void)
Definition: pt-unop.h:60
void visit_colon_expression(tree_colon_expression &)
Definition: pt-jit.cc:326
const type_bound_vector & get_bounds(void) const
Definition: pt-jit.h:63
static bool Vjit_enable
Definition: pt-jit.cc:45
octave_value::assign_op op_type(void) const
Definition: pt-assign.h:79
jit_instruction * insert_after(iterator loc, jit_instruction *instr)
Definition: jit-ir.cc:352
static llvm::Value * insert_interrupt_check(llvm::IRBuilderD &bld)
Definition: jit-typeinfo.h:565
static const jit_operation & paren_subsasgn(void)
Definition: jit-typeinfo.h:540
instruction_list::iterator iterator
Definition: jit-ir.h:542
#define SET_INTERNAL_VARIABLE_WITH_LIMITS(NM, MINVAL, MAXVAL)
Definition: variables.h:126
jit_instruction * insert_before(iterator loc, jit_instruction *instr)
Definition: jit-ir.cc:344
const std::vector< std::pair< std::string, bool > > & get_arguments(void) const
Definition: pt-jit.h:256
void stash_llvm(llvm::Value *compiled)
Definition: jit-ir.h:256
bool is_range(void) const
Definition: ov.h:571
std::string next_shortcircut_result(bool inc=true)
Definition: pt-jit.h:215
std::map< std::string, llvm::Value * > arguments
Definition: pt-jit.h:272
jit_variable * dest(void) const
Definition: jit-ir.h:868
jit_value * result(void) const
Definition: jit-ir.h:1325
void simplify_phi(void)
Definition: pt-jit.cc:1979
virtual void replace_with(jit_value *value)
Definition: jit-ir.cc:168
void release_dead_phi(jit_block &ablock)
Definition: pt-jit.cc:1890
void construct_ssa(void)
Definition: pt-jit.cc:1722
jit_block * incomming(size_t i) const
Definition: jit-ir.h:963
void visit_if_command(tree_if_command &)
Definition: pt-jit.cc:538
jit_type * result_type(void) const
Definition: jit-ir.h:1373
octave_value rvalue1(int=1)
Definition: pt-const.h:71
df_iterator df_end(void) const
Definition: jit-ir.h:641
octave_value::unary_op op_type(void) const
Definition: pt-unop.h:64
assign_op
Definition: ov.h:131
iterator end(void)
Definition: jit-ir.h:153
bool valid(void) const
Definition: jit-typeinfo.h:250
bool converting_function
Definition: pt-jit.h:274
void visit_simple_for_command(tree_simple_for_command &)
Definition: pt-jit.cc:375
static jit_type * get_any_ptr(void)
Definition: jit-typeinfo.h:457
void stash_info(jit_info *jinfo)
Definition: pt-loop.h:100
size_t use_count(void) const
Definition: jit-ir.h:562
jit_value * value
Definition: jit-ir.h:1252
void visit_simple_assignment(tree_simple_assignment &)
Definition: pt-jit.cc:752
void visit_matrix(tree_matrix &)
Definition: pt-jit.cc:643
jit_terminator * terminator(void) const
Definition: jit-ir.cc:361
const std::string & name(void) const
Definition: jit-ir.h:798
tree_expression * left_hand_side(void)
Definition: pt-assign.h:70
df_iterator df_begin(void) const
Definition: jit-ir.h:639
jit_block_list blocks
Definition: pt-jit.h:180
void push_worklist(jit_instruction *instr)
Definition: pt-jit.cc:1830
jit_call * create_checked_impl(jit_call *ret)
Definition: pt-jit.cc:1096
type op_type(void) const
Definition: pt-binop.h:167
tree_expression * switch_value(void)
Definition: pt-select.h:268
block_list breaks
Definition: pt-jit.h:234
tree_parameter_list * parameter_list(void)
Definition: ov-usr-fcn.h:376
void visit_if_clause(tree_if_clause &)
Definition: pt-jit.cc:532
llvm::Type * to_llvm(void) const
Definition: jit-typeinfo.h:151
void place_releases(void)
Definition: pt-jit.cc:1814
std::string name(void)
Definition: pt-decl.h:87
void visit_complex_for_command(tree_complex_for_command &)
Definition: pt-jit.cc:478
void visit_octave_user_function_header(octave_user_function &)
Definition: pt-pr-code.cc:339
std::vector< jit_type * > argument_types
Definition: pt-jit.h:408
void visit_fcn_handle(tree_fcn_handle &)
Definition: pt-jit.cc:692
static void initialize(llvm::Module *m, llvm::ExecutionEngine *e)
jit_function_info(tree_jit &tjit, octave_user_function &fcn, const octave_value_list &ov_args)
Definition: pt-jit.cc:2205
void visit_return_list(tree_return_list &)
Definition: pt-jit.cc:746
jit_info(tree_jit &tjit, tree &tee)
Definition: pt-jit.cc:2366
const jit_function & overload() const
Definition: jit-ir.cc:839
octave_idx_type length(void) const
Definition: oct-obj.h:89
jit_block * parent(void) const
Definition: jit-ir.h:438
llvm::Function * convert_loop(llvm::Module *module, const jit_block_list &blocks, const std::list< jit_value * > &constants)
Definition: pt-jit.cc:1300
void accept(tree_walker &tw)
Definition: pt-stmt.cc:289
octave_idx_type nelem(void) const
Definition: Range.h:64
static bool have_breakpoints(void)
Definition: debug.h:102
llvm::Value * to_llvm(void) const
Definition: jit-ir.h:250
jit_instruction * prepend(jit_instruction *instr)
Definition: jit-ir.cc:312
jit_block * block
Definition: pt-jit.h:176
llvm::Type * type_llvm(void) const
Definition: jit-ir.h:210
llvm::Module * module
Definition: pt-jit.h:383
void visit_statement_list(tree_statement_list &)
Definition: pt-pr-code.cc:904
jit_function convert_function(llvm::Module *module, const jit_block_list &blocks, const std::list< jit_value * > &constants, octave_user_function &fcn, const std::vector< jit_type * > &args)
Definition: pt-jit.cc:1352
void release_temp(jit_block &ablock, std::set< jit_value * > &temp)
Definition: pt-jit.cc:1925
type_bound_vector bounds
Definition: pt-jit.h:160
void visit_constant(tree_constant &)
Definition: pt-jit.cc:667
jit_instruction * resolve(tree_index_expression &exp, jit_value *extra_arg=0, bool lhs=false)
Definition: pt-jit.cc:1179
llvm::PassManager * module_pass_manager
Definition: pt-jit.h:388
bool is_default_case(void)
Definition: pt-select.h:185
static bool execute(tree_simple_for_command &cmd, const octave_value &bounds)
Definition: pt-jit.cc:2027
void remove(void)
Definition: jit-ir.cc:204
tree_command * command(void)
Definition: pt-stmt.h:81
Definition: Range.h:31
void visit_if_command_list(tree_if_command_list &)
Definition: pt-jit.cc:546
binary_op
Definition: ov.h:87
llvm::BasicBlock * prelude
Definition: pt-jit.h:280
static const jit_operation & for_init(void)
Definition: jit-typeinfo.h:515
void protect_var(T &var)
T * append(T *instr)
Definition: jit-ir.h:582
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
size_t trip_count(const octave_value &bounds) const
Definition: pt-jit.cc:2168
void error(const char *fmt,...)
Definition: error.cc:476
symbol_table::scope_id scope(void)
Definition: ov-usr-fcn.h:248
iterator end(void)
Definition: jit-ir.h:623
static const jit_operation & release(void)
Definition: jit-typeinfo.h:495
std::string name(void) const
Definition: ov-fcn.h:161
#define SET_INTERNAL_VARIABLE(NM)
Definition: variables.h:120
bool prune(void)
Definition: jit-ir.cc:600
bool is_special_expr(void) const
Definition: ov-usr-fcn.h:320
octave_value varval(context_id context=xdefault_context) const
Definition: symtab.h:574
jit_type * type(void) const
Definition: jit-ir.h:208
tree_switch_case_list * case_list(void)
Definition: pt-select.h:270
llvm::Module * get_module(void) const
Definition: pt-jit.h:362
elt_type & back(void)
Definition: base-list.h:93
bool known(void) const
Definition: jit-util.h:92
jit_block * first_use_block(void)
Definition: jit-ir.cc:153
static binary_op assign_op_to_binary_op(assign_op)
Definition: ov.cc:502
std::vector< jit_magic_end::context > end_context
Definition: pt-jit.h:182
std::vector< std::pair< std::string, bool > > arguments
Definition: pt-jit.h:441
jit_block * dom_successor(size_t idx) const
Definition: jit-ir.h:675
void stash_info(jit_function_info *info)
Definition: ov-usr-fcn.h:409
iterator begin(void)
Definition: jit-ir.h:149
iterator erase(iterator iter)
Definition: jit-ir.h:157
void visit_argument_list(tree_argument_list &)
Definition: pt-jit.cc:250
const jit_function & overload(void) const
Definition: jit-ir.h:1292
bool execute(const octave_value_list &ov_args, octave_value_list &retval) const
Definition: pt-jit.cc:2323
octave_idx_type nelem
Definition: jit-typeinfo.h:61
tree_statement_list * commands(void)
Definition: pt-select.h:61
void add_incomming(jit_block *from, jit_value *value)
Definition: jit-ir.h:956
bool do_execute(tree_simple_for_command &cmd, const octave_value &bounds)
Definition: pt-jit.cc:2099
void visit_global_command(tree_global_command &)
Definition: pt-jit.cc:351
void visit_postfix_expression(tree_postfix_expression &)
Definition: pt-jit.cc:710
void erase(void)
static const jit_operation & for_check(void)
Definition: jit-typeinfo.h:520
static const jit_operation & paren_subsref(void)
Definition: jit-typeinfo.h:535
void compute_df(void)
Definition: jit-ir.h:665
elt_type & front(void)
Definition: base-list.h:92
tree_expression * expression(void)
Definition: pt-idx.h:72
tree_expression * case_label(void)
Definition: pt-select.h:189
void visit_anon_fcn_handle(tree_anon_fcn_handle &)
Definition: pt-jit.cc:244
static llvm::IRBuilder builder(llvm::getGlobalContext())
void stash_info(jit_info *jinfo)
Definition: pt-loop.h:230
bool visited(size_t avisit_count)
Definition: jit-ir.h:725
void visit_parameter_list(tree_parameter_list &)
Definition: pt-jit.cc:704
static llvm::Type * get_scalar_llvm(void)
Definition: jit-typeinfo.h:452
void add_method(T *obj, void(T::*method)(void))
bool Vdebug_on_interrupt
Definition: sighandlers.cc:64
const std::string & name(void) const
Definition: jit-ir.h:1287
std::map< std::string, const octave_value * > vmap
Definition: pt-jit.h:417
void create_dom_tree(void)
Definition: jit-ir.h:670
jit_block_list & get_blocks(void)
Definition: pt-jit.h:61
static octave_value find_function(const std::string &name, const octave_value_list &args=octave_value_list(), bool local_funcs=true)
Definition: symtab.cc:1271
std::string next_for_bounds(bool inc=true)
Definition: pt-jit.h:212
std::string type_tags(void)
Definition: pt-idx.h:76
double base
Definition: jit-typeinfo.h:58
jit_value * overwrite(void) const
Definition: jit-ir.h:899
static tree_jit & instance(void)
Definition: pt-jit.cc:2046
static octave_value varval(const std::string &name, scope_id scope=xcurrent_scope, context_id context=xdefault_context)
Definition: symtab.h:1385
void convert(const jit_block_list &blocks, const std::list< jit_value * > &constants)
Definition: pt-jit.cc:1398
void visit_prefix_expression(tree_prefix_expression &)
Definition: pt-jit.cc:728
void visit_switch_case(tree_switch_case &)
Definition: pt-jit.cc:824
bool initialize(void)
Definition: pt-jit.cc:2053
virtual bool needs_release(void) const
Definition: jit-ir.h:236
void do_construct_ssa(jit_block &block, size_t avisit_count)
Definition: pt-jit.cc:1769
const jit_function & overload(void) const
Definition: jit-ir.h:1320
jit_info * get_info(void) const
Definition: pt-loop.h:95
static jit_type * get_range(void)
Definition: jit-typeinfo.h:459
void visit_cell(tree_cell &)
Definition: pt-jit.cc:649
void visit_statement(tree_statement &)
Definition: pt-jit.cc:773
void push_back(jit_block *b)
Definition: jit-ir.cc:122
jit_value * src(void) const
Definition: jit-ir.h:904
void visit_octave_user_function_trailer(octave_user_function &)
Definition: pt-jit.cc:502
llvm::Value * call(llvm::IRBuilderD &builder, const std::vector< jit_value * > &in_args) const
tree_expression * increment(void)
Definition: pt-colon.h:89
void visit_index_expression(tree_index_expression &)
Definition: pt-jit.cc:637
static const size_t NO_ID
Definition: jit-ir.h:548
tree_if_command_list * cmd_list(void)
Definition: pt-select.h:135
std::list< jit_instruction * > worklist
Definition: pt-jit.h:317
bool execute(const vmap &extra_vars=vmap()) const
Definition: pt-jit.cc:2385
static llvm::LLVMContext & context
Definition: pt-jit.cc:102
static symbol_record find_symbol(const std::string &name, scope_id scope=xcurrent_scope)
Definition: symtab.h:1281
jit_block_list & blocks
Definition: pt-jit.h:314
tree_statement_list * body(void)
Definition: pt-loop.h:212
jit_value * result
Definition: pt-jit.h:170
bool has_magic_end(void) const
Definition: pt-id.h:59
tree_jit(void)
Definition: pt-jit.cc:2019
std::list< tree_decl_elt * >::iterator iterator
Definition: base-list.h:36
static const jit_operation & cast(jit_type *result)
Definition: jit-typeinfo.h:550
void visit_octave_user_script(octave_user_script &)
Definition: pt-jit.cc:484
static jit_type * get_complex(void)
Definition: jit-typeinfo.h:470
void finish_breaks(jit_block *dest, const block_list &lst)
Definition: pt-jit.cc:1288
iterator remove(iterator iter)
Definition: jit-ir.h:602
bool alive(const jit_block *asuccessor) const
Definition: jit-ir.h:1044
iterator end(void)
Definition: base-list.h:81
bool print_result(void) const
Definition: pt-exp.h:97
size_t short_count
Definition: pt-jit.h:186
jit_block * back(void) const
Definition: jit-ir.h:147
static int Vjit_failcnt
Definition: pt-jit.cc:49
tree_expression * right_hand_side(void)
Definition: pt-assign.h:72
jit_factory & factory
Definition: pt-jit.h:315
std::list< tree_argument_list * > arg_lists(void)
Definition: pt-idx.h:74
tree_expression * condition(void)
Definition: pt-select.h:59
void visit_persistent_command(tree_persistent_command &)
Definition: pt-jit.cc:357
bool is_persistent(void) const
Definition: symtab.h:613
jit_block & entry_block(void)
Definition: pt-jit.h:327
void visit_identifier(tree_identifier &)
Definition: pt-jit.cc:514
const jit_function & overload(void) const
Definition: jit-ir.h:1156
static const jit_operation & make_range(void)
Definition: jit-typeinfo.h:530
block_list continues
Definition: pt-jit.h:235
symbol_table::scope_id scope
Definition: pt-jit.h:165
static uint32_t * next
Definition: randmtzig.c:187
type_bound_vector bounds
Definition: pt-jit.h:442
tree_expression * control_expr(void)
Definition: pt-loop.h:208
variable check_variable(void) const
Definition: jit-ir.h:1210
bool is_global(void) const
Definition: symtab.h:610
jit_infer(jit_factory &afactory, jit_block_list &ablocks, const variable_map &avmap)
Definition: pt-jit.cc:1653
virtual void construct_ssa(void)
Definition: jit-ir.h:427
tree_parameter_list * return_list(void)
Definition: ov-usr-fcn.h:378
void accept(tree_walker &tw)
Definition: pt-stmt.cc:176
jit_const_index * index
Definition: jit-ir.h:1253
bool converting_function
Definition: pt-jit.h:162
std::list< jit_block * > block_list
Definition: pt-jit.h:233
std::string name(void) const
Definition: pt-id.h:65
Range range_value(void) const
Definition: ov.h:903
void append_users(jit_value *v)
Definition: pt-jit.cc:1696
jit_convert::variable_map variable_map
Definition: pt-jit.h:303
jit_factory factory
Definition: pt-jit.h:167
void visit_do_until_command(tree_do_until_command &)
Definition: pt-jit.cc:1017
jit_block * front(void) const
Definition: jit-ir.h:159
jit_block * successor(size_t idx=0) const
Definition: jit-ir.h:1021
bool match(const octave_value_list &ov_args) const
Definition: pt-jit.cc:2349
void visit_octave_user_function_header(octave_user_function &)
Definition: pt-jit.cc:496
bool in_worklist(void) const
Definition: jit-ir.h:191
llvm::ExecutionEngine * engine
Definition: pt-jit.h:391
void append_users_term(jit_terminator *term)
Definition: pt-jit.cc:1703
std::vector< std::pair< std::string, bool > > argument_vec
Definition: pt-jit.h:269
void infer(void)
Definition: pt-jit.cc:1658
bool artificial(void) const
Definition: jit-ir.h:912
static const jit_operation & binary_op(int op)
Definition: jit-typeinfo.h:478
context resolve_context(void) const
Definition: jit-ir.cc:799
tree_expression * limit(void)
Definition: pt-colon.h:87
void visit_unwind_protect_command(tree_unwind_protect_command &)
Definition: pt-jit.cc:949
std::ostream & print(std::ostream &os, const std::string &header) const
Definition: jit-ir.cc:101
virtual bool infer(void)
Definition: jit-ir.cc:725
#define panic_impossible()
Definition: error.h:33
static jit_type * get_scalar(void)
Definition: jit-typeinfo.h:450
jit_convert(tree &tee, jit_type *for_bounds=0)
Definition: pt-jit.cc:111
~jit_info(void)
Definition: pt-jit.cc:2378
void visit_funcall(tree_funcall &)
Definition: pt-jit.cc:698
void label(void)
Definition: jit-ir.cc:91
tree_expression * lhs(void)
Definition: pt-binop.h:95
tree_expression * left_hand_side(void)
Definition: pt-loop.h:206
void remove_dead()
Definition: pt-jit.cc:1840
jit_value * visit(tree *tee)
Definition: pt-jit.h:229
jit_value * argument(size_t i) const
Definition: jit-ir.h:359
static void assign(const std::string &name, const octave_value &value=octave_value(), scope_id scope=xcurrent_scope, context_id context=xdefault_context, bool force_add=false)
Definition: symtab.h:1335
static const jit_operation & create_undef(void)
Definition: jit-typeinfo.h:581
llvm::Value * cond_llvm(void) const
Definition: jit-ir.h:1095
llvm::PHINode * to_llvm(void) const
Definition: jit-ir.cc:665
jit_const_index * count
Definition: jit-ir.h:1254
static llvm::Value * insert_error_check(llvm::IRBuilderD &bld)
Definition: jit-typeinfo.h:560
void visit_switch_case_list(tree_switch_case_list &)
Definition: pt-jit.cc:830
jit_function_info * get_info(void)
Definition: ov-usr-fcn.h:407
size_t argument_count(void) const
Definition: jit-ir.h:401
tree_statement_list * commands(void)
Definition: pt-select.h:191
octave_value::binary_op op_type(void) const
Definition: pt-binop.h:93
void visit_return_command(tree_return_command &)
Definition: pt-jit.cc:740
tree_expression * special_expr(void)
Definition: ov-usr-fcn.cc:677
void stash_argument(size_t i, jit_value *arg)
Definition: jit-ir.h:389
jit_value * do_assign(tree_expression *exp, jit_value *rhs, bool artificial=false)
Definition: pt-jit.cc:1237
iterator begin(void)
Definition: base-list.h:78
bool has_top(void) const
Definition: jit-ir.h:802
void visit_switch_command(tree_switch_command &)
Definition: pt-jit.cc:836
void finish_phi(jit_phi *phi)
Definition: pt-jit.cc:1438
jit_factory & get_factory(void)
Definition: pt-jit.h:65
void stash_in_worklist(bool ain_worklist)
Definition: jit-ir.h:196
llvm::BasicBlock * to_llvm(void) const
Definition: jit-ir.cc:392
variable_map vmap
Definition: pt-jit.h:188
df_set::const_iterator df_iterator
Definition: jit-ir.h:546
double arg(double x)
Definition: lo-mappers.h:37
bool takes_varargs(void) const
Definition: pt-misc.h:71
size_t for_bounds_count
Definition: pt-jit.h:185
static bool Vdebug_jit
Definition: pt-jit.cc:43
void visit_multi_assignment(tree_multi_assignment &)
Definition: pt-jit.cc:655
static llvm::Type * get_index_llvm(void)
Definition: jit-typeinfo.h:467
std::string next_iterator(bool inc=true)
Definition: pt-jit.h:209
virtual bool infer(void)
Definition: jit-ir.cc:683
void warning(const char *fmt,...)
Definition: error.cc:681
bool enabled(void)
Definition: pt-jit.cc:2158
virtual std::string name(void) const
Definition: pt-exp.h:101
void grab(void)
Definition: ov-base.h:775
std::string str_print_code(void)
Definition: pt.cc:39
static octave_idx_type fout(const octave_idx_type &lsize, const double &alpha, const double &beta, const double &, const double &p)
Definition: qz.cc:282
virtual bool infer(void)
Definition: jit-ir.h:432
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:233
size_t use_count(void) const
Definition: jit-util.h:122
static const jit_operation & unary_op(int op)
Definition: jit-typeinfo.h:483
void compile(tree_jit &tjit, tree &tee, jit_type *for_bounds=0)
Definition: pt-jit.cc:2439
void visit_octave_user_function_trailer(octave_user_function &)
Definition: pt-pr-code.cc:429
static const jit_function & get_release(jit_type *type)
Definition: jit-typeinfo.h:500
llvm::BasicBlock * incomming_llvm(size_t i) const
Definition: jit-ir.h:968
jit_info * get_info(void) const
Definition: pt-loop.h:225
std::pair< jit_type *, std::string > type_bound
Definition: pt-jit.h:41
const variable_map & vmap
Definition: pt-jit.h:316
void visit_no_op_command(tree_no_op_command &)
Definition: pt-jit.cc:661
tree_expression * rhs(void)
Definition: pt-binop.h:96
NODE_T * first_use(void) const
Definition: jit-util.h:120
static int Vjit_startcnt
Definition: pt-jit.cc:47
bool is_else_clause(void)
Definition: pt-select.h:57
std::set< jit_block * > df_set
Definition: jit-ir.h:545
jit_value * result(void) const
Definition: jit-ir.h:1368
void visit_decl_elt(tree_decl_elt &)
Definition: pt-jit.cc:363
size_t successor_count(void) const
Definition: jit-ir.h:1053
static const jit_operation & print_value(void)
Definition: jit-typeinfo.h:510
void pop_all(void)
Definition: jit-ir.cc:504
tree_expression * expression(void)
Definition: pt-stmt.h:83
double inc
Definition: jit-typeinfo.h:60
Definition: pt.h:35
void visit_break_command(tree_break_command &)
Definition: pt-jit.cc:319
void compute_idom(jit_block &entry_block)
Definition: jit-ir.h:655
Complex complex_value(bool frc_str_conv=false) const
Definition: ov.h:785
const value_list & constants(void) const
Definition: jit-ir.h:106
bool match(const vmap &extra_vars=vmap()) const
Definition: pt-jit.cc:2419
void optimize(llvm::Function *fn)
Definition: pt-jit.cc:2182
#define UNUSED_WITHOUT_LLVM(x)
Definition: pt-jit.cc:2512
PASS_T value(void) const
Definition: jit-ir.h:514
void accept(tree_walker &tw)
Definition: pt-select.cc:81
size_t id(void) const
Definition: jit-ir.h:634
llvm::Value * argument_llvm(size_t i) const
Definition: jit-ir.h:364
void visit_continue_command(tree_continue_command &)
Definition: pt-jit.cc:344
bool is_undefined(void) const
Definition: ov.h:523
std::list< jit_block * >::iterator iterator
Definition: jit-ir.h:144
static void reset_ids(void)
Definition: jit-ir.h:354
llvm::BasicBlock * new_block(const std::string &aname="body", llvm::BasicBlock *insert_before=0)
void visit_binary_expression(tree_binary_expression &)
Definition: pt-jit.cc:256
iterator begin(void)
Definition: jit-ir.h:619
void visit_decl_init_list(tree_decl_init_list &)
Definition: pt-jit.cc:369
void visit_octave_user_function(octave_user_function &)
Definition: pt-jit.cc:490
virtual bool is_assignment_expression(void) const
Definition: pt-exp.h:63
jit_block * successor(size_t i) const
Definition: jit-ir.cc:378
llvm::ExecutionEngine * engine
Definition: pt-jit.h:437
llvm::FunctionPassManager * pass_manager
Definition: pt-jit.h:389
static const jit_operation & grab(void)
Definition: jit-typeinfo.h:488
ColumnVector imag(const ComplexColumnVector &a)
Definition: dColVector.cc:162
const std::string & name(void) const
Definition: jit-ir.h:575
jit_block & final_block(void)
Definition: pt-jit.h:329
std::string next_name(const char *prefix, size_t &count, bool inc)
Definition: pt-jit.cc:1169
jit_block * entry_block
Definition: pt-jit.h:172
llvm::ExecutionEngine * get_engine(void) const
Definition: pt-jit.h:360
jit_block * maybe_split(jit_factory &factory, jit_block_list &blocks, jit_block *asuccessor)
Definition: jit-ir.cc:536
double limit
Definition: jit-typeinfo.h:59
const std::string & name(void) const
Definition: jit-ir.h:1315
static jit_type * get_any(void)
Definition: jit-typeinfo.h:446
llvm::Value * argument(llvm::IRBuilderD &builder, size_t idx) const
tree_expression * base(void)
Definition: pt-colon.h:85
tree_statement_list * body(void)
Definition: pt-loop.h:82
jit_instruction * back(void)
Definition: jit-ir.h:738
void visit_while_command(tree_while_command &)
Definition: pt-jit.cc:955
std::complex< double > Complex
Definition: oct-cmplx.h:29
void(* jited_function)(octave_base_value **)
Definition: pt-jit.h:431
void initialize(symbol_table::scope_id s)
Definition: pt-jit.cc:1080
llvm::Function * llvm_function
Definition: pt-jit.h:439
static jit_type * type_of(const octave_value &ov)
Definition: jit-typeinfo.h:473
octave_base_value * internal_rep(void) const
Definition: ov.h:1114
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:156
double double_value(bool frc_str_conv=false) const
Definition: ov.h:759
virtual void push_variable(void)
Definition: jit-ir.h:423
void mark_alive(void)
Definition: jit-ir.h:567
jit_function creating
Definition: pt-jit.h:277
T * create(void)
Definition: jit-ir.h:109
static llvm::Value * create_complex(llvm::Value *real, llvm::Value *imag)
Definition: jit-typeinfo.h:586
llvm::Function * to_llvm(void) const
Definition: jit-typeinfo.h:285
NODE_T * next(void) const
Definition: jit-util.h:166
tree_statement_list * body(void)
Definition: ov-usr-fcn.h:380
jit_instruction * user(void) const
Definition: jit-ir.h:303
void visit_function_def(tree_function_def &)
Definition: pt-jit.cc:508
jit_value * top(void) const
Definition: jit-ir.h:807
llvm::BasicBlock * successor_llvm(size_t idx=0) const
Definition: jit-ir.h:1026
unary_op
Definition: ov.h:74
void visit_statement_list(tree_statement_list &)
Definition: pt-jit.cc:811
octave_value find(const vmap &extra_vars, const std::string &vname) const
Definition: pt-jit.cc:2502
virtual void accept(tree_walker &tw)=0
size_t successor_count(void) const
Definition: jit-ir.cc:385
const variable_map & get_variable_map(void) const
Definition: pt-jit.h:69
void visit_try_catch_command(tree_try_catch_command &)
Definition: pt-jit.cc:943
static const jit_operation & for_index(void)
Definition: jit-typeinfo.h:525
virtual bool is_identifier(void) const
Definition: pt-exp.h:59
bool alive(void) const
Definition: jit-ir.h:565
jit_variable * find_variable(const std::string &vname) const
Definition: pt-jit.cc:1112
size_t dom_successor_count(void) const
Definition: jit-ir.h:680
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
jit_variable * get_variable(const std::string &vname)
Definition: pt-jit.cc:1120
static const jit_operation & logically_true(void)
Definition: jit-typeinfo.h:545
void mark_artificial(void)
Definition: jit-ir.h:914
static scope_id current_scope(void)
Definition: symtab.h:1163
jit_call * create_checked(const ARG0 &arg0)
Definition: pt-jit.h:58
jit_block * final_block
Definition: pt-jit.h:174
size_t size(void) const
Definition: base-list.h:44
const std::vector< jit_use > & arguments(void) const
Definition: jit-ir.h:417
tree_expression * condition(void)
Definition: pt-loop.h:80
static const jit_operation & destroy(void)
Definition: jit-typeinfo.h:505
~tree_jit(void)
Definition: pt-jit.cc:2023
jit_variable * create_variable(const std::string &vname, jit_type *type, bool isarg=true)
Definition: pt-jit.cc:1146