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