# HG changeset patch
# User Gene Harvey <gharveymn@gmail.com>
# Date 1559676749 18000
#      Tue Jun 04 14:32:29 2019 -0500
# Branch jitwork
# Node ID 1f78cc5c749e61d16a13339ad86dabad4ffc0abf
# Parent  ef06683d1c224b57abdaf9e9678286cb3dd075d1
 update jit build for use with the stack_frame refactor and LLVM-8.0

* configure.ac: Call new macro.

* jit-ir.cc: Remove LLVM macros definitions.

* jit-ir.cc, jit-ir.h (jit_terminator::to_llvm): Remove function.

* jit-typeinfo.cc: Remove LLVM macros definitions.
(jit_typeinfo::jit_typeinfo): Use llvm::ArrayRef instead of va_args.

* jit-util.cc: Remove LLVM macro definitions.

* jit-util.h: Remove llvm::TerminatorInst forward declaration.

* pt-eval.cc (tree_evaluator::visit_simple_for_command,
tree_evaluator::execute_user_function,
tree_evaluator::visit_unwind_protect_command,
tree_evaluator::visit_do_until_command): Pass self-reference
to tree_jit::execute.

* pt-eval.h: Forward declare symbol_table.

* pt-eval.cc, pt-eval.h (tree_evaluator::is_global): New overload.
(tree_evaluator::is_persistent, tree_evaluator::lookup_symbol,
tree_evaluator::insert_symbol, tree_evaluator::get_symbol_table):
New functions.

* pt-jit.cc: Remove LLVM macro definitions.
(llvm/Transforms/InstCombine/InstCombine.h, llvm/Transforms/Utils.h):
New includes.
(jit_convert::jit_convert): Initialize tree_evaluator member variable.
Call jit_convert::initialize without symbol_scope argument.
(jit_convert::visit_statement): Use tree_evaluator::is_variable.
(jit_convert::initialize): Remove symbol_scope usage.
(jit_convert::get_variable): Use tree_evaluator to query variables.
(tree_jit::do_execute): Pass tree_evaluator to jit_info::jit_info.
(jit_module::optimize): Use new macro.
(jit_function_info::jit_function_info): Initialize tree_evaluator member
variable. Use tree_evaluator in jit_convert constructor.
(jit_info::jit_info): Initialize tree_evaluator member variable.
(jit_info::execute): Use tree_evaluator.
(jit_info::compile): Use tree_evaluator in jit_convert constructor.
(jit_info::find): Use tree_evaluator instaed of symbol_scope.

pt-jit.h: Forward declare tree_evaluator.
(jit_convert::jit_convert, jit_info::execute, jit_info::do_execute,
jit_info::jit_info, jit_function_info::jit_function_info):
New tree_evaluator& parameter.
(jit_convert::m_evaluator, jit_info::m_evaluator,
jit_function_info::m_evaluator): New member variable.
(jit_convert::initialize): Remove symbol_scope parameter.

acinclude.m4 (OCTAVE_LLVM_WRITEBITCODETOFILE_API): New macro.

diff -r ef06683d1c22 -r 1f78cc5c749e configure.ac
--- a/configure.ac	Mon Jun 03 15:23:56 2019 -0500
+++ b/configure.ac	Tue Jun 04 14:32:29 2019 -0500
@@ -1447,6 +1447,7 @@
     OCTAVE_LLVM_IRBUILDER_API
     OCTAVE_LLVM_HAS_CREATEALWAYSINLINERPASS
     OCTAVE_LLVM_IRBUILDER_CREATECONSTINBOUNDSGEP1_32_API
+    OCTAVE_LLVM_WRITEBITCODETOFILE_API
 
     AC_LANG_POP(C++)
     CPPFLAGS="$save_CPPFLAGS"
diff -r ef06683d1c22 -r 1f78cc5c749e libinterp/parse-tree/jit-ir.cc
--- a/libinterp/parse-tree/jit-ir.cc	Mon Jun 03 15:23:56 2019 -0500
+++ b/libinterp/parse-tree/jit-ir.cc	Tue Jun 04 14:32:29 2019 -0500
@@ -22,10 +22,6 @@
 
 // Author: Max Brister <max@2bass.com>
 
-// defines required by llvm
-#define __STDC_LIMIT_MACROS
-#define __STDC_CONSTANT_MACROS
-
 #if defined (HAVE_CONFIG_H)
 #  include "config.h"
 #endif
@@ -698,12 +694,6 @@
     return changed;
   }
 
-  llvm::TerminatorInst *
-  jit_terminator::to_llvm (void) const
-  {
-    return llvm::cast<llvm::TerminatorInst> (jit_value::to_llvm ());
-  }
-
   // -------------------- jit_call --------------------
   bool
   jit_call::needs_release (void) const
diff -r ef06683d1c22 -r 1f78cc5c749e libinterp/parse-tree/jit-ir.h
--- a/libinterp/parse-tree/jit-ir.h	Mon Jun 03 15:23:56 2019 -0500
+++ b/libinterp/parse-tree/jit-ir.h	Tue Jun 04 14:32:29 2019 -0500
@@ -1100,8 +1100,6 @@
 
     virtual bool infer (void);
 
-    llvm::TerminatorInst * to_llvm (void) const;
-
   protected:
 
     virtual bool check_alive (size_t) const { return true; }
diff -r ef06683d1c22 -r 1f78cc5c749e libinterp/parse-tree/jit-typeinfo.cc
--- a/libinterp/parse-tree/jit-typeinfo.cc	Mon Jun 03 15:23:56 2019 -0500
+++ b/libinterp/parse-tree/jit-typeinfo.cc	Tue Jun 04 14:32:29 2019 -0500
@@ -23,8 +23,6 @@
 // Author: Max Brister <max@2bass.com>
 
 // defines required by llvm
-#define __STDC_LIMIT_MACROS
-#define __STDC_CONSTANT_MACROS
 
 #if defined (HAVE_CONFIG_H)
 #  include "config.h"
@@ -1661,13 +1659,13 @@
       llvm::Value *inc = fn.argument (m_builder, 2);
       llvm::Value *nelem = compute_nelem.call (m_builder, base, limit, inc);
 
-      llvm::Value *dzero = llvm::ConstantFP::get (m_scalar_t, 0);
-      llvm::Value *izero = llvm::ConstantInt::get (m_index_t, 0);
-      llvm::Value *rng = llvm::ConstantStruct::get (m_range_t, dzero, dzero,
-                                                    dzero, izero, NULL);
-      rng = m_builder.CreateInsertValue (rng, base, 0);
+      llvm::Constant *dzero = llvm::ConstantFP::get (m_scalar_t, 0);
+      llvm::Constant *izero = llvm::ConstantInt::get (m_index_t, 0);
+      llvm::Value *rng = llvm::ConstantStruct::get (m_range_t,
+                                                {dzero, dzero, dzero, izero});
+      rng = m_builder.CreateInsertValue (rng, base,  0);
       rng = m_builder.CreateInsertValue (rng, limit, 1);
-      rng = m_builder.CreateInsertValue (rng, inc, 2);
+      rng = m_builder.CreateInsertValue (rng, inc,   2);
       rng = m_builder.CreateInsertValue (rng, nelem, 3);
       fn.do_return (m_builder, rng);
     }
diff -r ef06683d1c22 -r 1f78cc5c749e libinterp/parse-tree/jit-util.cc
--- a/libinterp/parse-tree/jit-util.cc	Mon Jun 03 15:23:56 2019 -0500
+++ b/libinterp/parse-tree/jit-util.cc	Tue Jun 04 14:32:29 2019 -0500
@@ -22,10 +22,6 @@
 
 // Author: Max Brister <max@2bass.com>
 
-// defines required by llvm
-#define __STDC_LIMIT_MACROS
-#define __STDC_CONSTANT_MACROS
-
 #if defined (HAVE_CONFIG_H)
 #  include "config.h"
 #endif
diff -r ef06683d1c22 -r 1f78cc5c749e libinterp/parse-tree/jit-util.h
--- a/libinterp/parse-tree/jit-util.h	Mon Jun 03 15:23:56 2019 -0500
+++ b/libinterp/parse-tree/jit-util.h	Tue Jun 04 14:32:29 2019 -0500
@@ -54,7 +54,6 @@
   class Twine;
   class GlobalValue;
   class GlobalVariable;
-  class TerminatorInst;
   class PHINode;
   class TargetMachine;
 
diff -r ef06683d1c22 -r 1f78cc5c749e libinterp/parse-tree/pt-eval.cc
--- a/libinterp/parse-tree/pt-eval.cc	Mon Jun 03 15:23:56 2019 -0500
+++ b/libinterp/parse-tree/pt-eval.cc	Tue Jun 04 14:32:29 2019 -0500
@@ -1293,13 +1293,54 @@
     return frame.is_defined (sym);
   }
 
-  bool tree_evaluator::is_global (const std::string& name) const
+  bool
+  tree_evaluator::is_global (const std::string& name) const
   {
     const stack_frame& frame = m_call_stack.get_current_stack_frame ();
 
     return frame.is_global (name);
   }
 
+  bool
+  tree_evaluator::is_global (const symbol_record& sym) const
+  {
+    const stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.is_global (sym);
+  }
+
+  bool
+  tree_evaluator::is_persistent (const std::string& name) const
+  {
+    const stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.is_persistent (name);
+  }
+
+  bool
+  tree_evaluator::is_persistent (const symbol_record& sym) const
+  {
+    const stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.is_persistent (sym);
+  }
+
+  symbol_record
+  tree_evaluator::lookup_symbol (const std::string& name) const
+  {
+    const stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.lookup_symbol (name);
+  }
+
+  symbol_record
+  tree_evaluator::insert_symbol (const std::string& name)
+  {
+    stack_frame& frame = m_call_stack.get_current_stack_frame ();
+
+    return frame.insert_symbol (name);
+  }
+
   octave_value
   tree_evaluator::varval (const symbol_record& sym) const
   {
@@ -1855,6 +1896,11 @@
     return false;
   }
 
+  symbol_table& tree_evaluator::get_symbol_table (void)
+  {
+    return m_interpreter.get_symbol_table ();
+  }
+
   void tree_evaluator::push_dummy_scope (const std::string& name)
   {
     symbol_scope dummy_scope (name + "$dummy");
@@ -2187,7 +2233,7 @@
     octave_value rhs = evaluate (expr);
 
 #if defined (HAVE_LLVM)
-    if (tree_jit::execute (cmd, rhs))
+    if (tree_jit::execute (*this, cmd, rhs))
       return;
 #endif
 
@@ -2474,7 +2520,7 @@
 
 #if defined (HAVE_LLVM)
     if (user_function.is_special_expr ()
-        && tree_jit::execute (user_function, args, retval))
+        && tree_jit::execute (*this, user_function, args, retval))
       return retval;
 #endif
 
@@ -4027,7 +4073,7 @@
       }
 
 #if defined (HAVE_LLVM)
-    if (tree_jit::execute (cmd))
+    if (tree_jit::execute (*this, cmd))
       return;
 #endif
 
@@ -4077,7 +4123,7 @@
       }
 
 #if defined (HAVE_LLVM)
-    if (tree_jit::execute (cmd))
+    if (tree_jit::execute (*this, cmd))
       return;
 #endif
 
diff -r ef06683d1c22 -r 1f78cc5c749e libinterp/parse-tree/pt-eval.h
--- a/libinterp/parse-tree/pt-eval.h	Mon Jun 03 15:23:56 2019 -0500
+++ b/libinterp/parse-tree/pt-eval.h	Tue Jun 04 14:32:29 2019 -0500
@@ -43,6 +43,7 @@
 namespace octave
 {
   class symbol_scope;
+  class symbol_table;
   class tree_decl_elt;
   class tree_expression;
 
@@ -418,10 +419,20 @@
 
     bool is_global (const std::string& name) const;
 
+    bool is_global (const symbol_record& sym) const;
+
+    bool is_persistent (const std::string& name) const;
+
+    bool is_persistent (const symbol_record& sym) const;
+
     octave_value varval (const symbol_record& sym) const;
 
     octave_value varval (const std::string& name) const;
 
+    symbol_record lookup_symbol (const std::string& name) const;
+
+    symbol_record insert_symbol (const std::string& name);
+
     void assign (const std::string& name,
                  const octave_value& val = octave_value ());
 
@@ -458,6 +469,8 @@
 
     interpreter& get_interpreter (void) { return m_interpreter; }
 
+    symbol_table& get_symbol_table (void);
+
     bp_table& get_bp_table (void) { return m_bp_table; }
 
     profiler& get_profiler (void) { return m_profiler; }
diff -r ef06683d1c22 -r 1f78cc5c749e libinterp/parse-tree/pt-jit.cc
--- a/libinterp/parse-tree/pt-jit.cc	Mon Jun 03 15:23:56 2019 -0500
+++ b/libinterp/parse-tree/pt-jit.cc	Tue Jun 04 14:32:29 2019 -0500
@@ -22,9 +22,6 @@
 
 // Author: Max Brister <max@2bass.com>
 
-#define __STDC_LIMIT_MACROS
-#define __STDC_CONSTANT_MACROS
-
 #if defined (HAVE_CONFIG_H)
 #  include "config.h"
 #endif
@@ -126,6 +123,9 @@
 #  include <llvm/Transforms/Scalar/GVN.h>
 #endif
 
+#include <llvm/Transforms/InstCombine/InstCombine.h>
+#include <llvm/Transforms/Utils.h>
+
 static bool Vdebug_jit = false;
 
 static bool Vjit_enable = false;
@@ -160,10 +160,12 @@
   { };
 
   // -------------------- jit_convert --------------------
-  jit_convert::jit_convert (tree& tee, jit_type *for_bounds)
-    : m_converting_function (false)
+  jit_convert::jit_convert (tree_evaluator& tr_eval, tree& tee,
+                            jit_type *for_bounds)
+    : m_evaluator (tr_eval),
+      m_converting_function (false)
   {
-    initialize (__get_current_scope__ ("jit_convert::jit_convert"));
+    initialize ();
 
     if (for_bounds)
       create_variable (next_for_bounds (false), for_bounds);
@@ -193,11 +195,13 @@
     m_final_block->append (m_factory.create<jit_return> ());
   }
 
-  jit_convert::jit_convert (octave_user_function& fcn,
+  jit_convert::jit_convert (tree_evaluator& tr_eval,
+                            octave_user_function& fcn,
                             const std::vector<jit_type *>& args)
-    : m_converting_function (true)
+    : m_evaluator (tr_eval),
+      m_converting_function (true)
   {
-    initialize (fcn.scope ());
+    initialize ();
 
     tree_parameter_list *plist = fcn.parameter_list ();
     tree_parameter_list *rlist = fcn.return_list ();
@@ -820,13 +824,11 @@
     else
       {
         // stolen from tree_evaluator::visit_statement
-        bool do_bind_ans = false;
+        bool do_bind_ans;
 
         if (expr->is_identifier ())
           {
-            tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
-
-            do_bind_ans = (! id->is_variable (m_scope.current_context ()));
+            do_bind_ans = ! m_evaluator.is_variable (expr);
           }
         else
           do_bind_ans = (! expr->is_assignment_expression ());
@@ -1119,9 +1121,8 @@
   }
 
   void
-  jit_convert::initialize (const symbol_scope& s)
+  jit_convert::initialize ()
   {
-    m_scope = s;
     m_iterator_count = 0;
     m_for_bounds_count = 0;
     m_short_count = 0;
@@ -1165,17 +1166,16 @@
     if (ret)
       return ret;
 
-    symbol_table& symtab = __get_symbol_table__ ("jit_convert::find_variable");
-
-    symbol_record record = m_scope.find_symbol (vname);
-    if (record.is_persistent () || record.is_global ())
+    symbol_table& symtab = m_evaluator.get_symbol_table ();
+    symbol_record record = m_evaluator.insert_symbol (vname);
+    if (m_evaluator.is_persistent (record) || m_evaluator.is_global (record))
       throw jit_fail_exception ("Persistent and global not yet supported");
 
     if (m_converting_function)
       return create_variable (vname, jit_typeinfo::get_any (), false);
     else
       {
-        octave_value val = record.varval (m_scope.current_context ());
+        octave_value val = m_evaluator.varval (record);
         if (val.is_undefined ())
           val = symtab.find_function (vname);
 
@@ -2259,7 +2259,7 @@
   }
 
   bool
-  tree_jit::do_execute (tree_simple_for_command& cmd,
+  tree_jit::do_execute (tree_evaluator& tr_eval, tree_simple_for_command& cmd,
                         const octave_value& bounds)
   {
     size_t tc = trip_count (bounds);
@@ -2278,7 +2278,7 @@
 
         delete info;
 
-        info = new jit_info (cmd, bounds);
+        info = new jit_info (tr_eval, cmd, bounds);
 
         cmd.stash_info (info);
       }
@@ -2287,7 +2287,7 @@
   }
 
   bool
-  tree_jit::do_execute (tree_while_command& cmd)
+  tree_jit::do_execute (tree_evaluator& tr_eval, tree_while_command& cmd)
   {
     if (! initialized || ! enabled ())
       return false;
@@ -2296,7 +2296,7 @@
     if (! info || ! info->match ())
       {
         delete info;
-        info = new jit_info (cmd);
+        info = new jit_info (tr_eval, cmd);
         cmd.stash_info (info);
       }
 
@@ -2304,7 +2304,8 @@
   }
 
   bool
-  tree_jit::do_execute (octave_user_function& fcn,
+  tree_jit::do_execute (tree_evaluator& tr_eval,
+                        octave_user_function& fcn,
                         const octave_value_list& args,
                         octave_value_list& retval)
   {
@@ -2315,7 +2316,7 @@
     if (! info || ! info->match (args))
       {
         delete info;
-        info = new jit_function_info (fcn, args);
+        info = new jit_function_info (tr_eval, fcn, args);
         fcn.stash_info (info);
       }
 
@@ -2492,7 +2493,11 @@
         //      llvm::raw_fd_ostream fout ("test.bc", error, llvm::raw_fd_ostream::F_Binary);
         //#endif
 
+#if defined(LLVM_WRITEBITCODETOFILE_HAS_PTR_ARG)
         llvm::WriteBitcodeToFile (m_module, fout);
+#else
+        llvm::WriteBitcodeToFile (*m_module, fout);
+#endif
       }
   }
 
@@ -2504,9 +2509,11 @@
 
 
   // -------------------- jit_function_info --------------------
-  jit_function_info::jit_function_info (octave_user_function& fcn,
+  jit_function_info::jit_function_info (tree_evaluator& tr_eval,
+                                        octave_user_function& fcn,
                                         const octave_value_list& ov_args)
-    : m_llvm_function_name (""),
+    : m_evaluator (tr_eval),
+      m_llvm_function_name (""),
       m_function (nullptr),
       m_argument_types (ov_args.length ())
   {
@@ -2519,7 +2526,7 @@
 
     try
       {
-        jit_convert conv (fcn, m_argument_types);
+        jit_convert conv (tr_eval, fcn, m_argument_types);
         jit_infer infer (conv.get_factory (), conv.get_blocks (),
                          conv.get_variable_map ());
         infer.infer ();
@@ -2684,23 +2691,26 @@
 
 
   // -------------------- jit_info --------------------
-  jit_info::jit_info (tree& tee)
-    : m_llvm_function_name (tree_jit::generate_unique_function_name ()),
+  jit_info::jit_info (tree_evaluator& tr_eval, tree& tee)
+    : m_evaluator (tr_eval),
+      m_llvm_function_name (tree_jit::generate_unique_function_name ()),
       m_function (nullptr)
   {
     compile (tee);
   }
 
-  jit_info::jit_info (tree& tee, const octave_value& for_bounds)
-    : m_llvm_function_name (tree_jit::generate_unique_function_name ()),
+  jit_info::jit_info (tree_evaluator& tr_eval, tree& tee, const octave_value& for_bounds)
+    : m_evaluator (tr_eval),
+      m_llvm_function_name (tree_jit::generate_unique_function_name ()),
       m_function (nullptr)
   {
     compile (tee, jit_typeinfo::type_of (for_bounds));
   }
 
-  jit_info::jit_info (tree_simple_for_command& tee,
+  jit_info::jit_info (tree_evaluator& tr_eval, tree_simple_for_command& tee,
                       const octave_value& for_bounds)
-    : m_llvm_function_name (tree_jit::generate_unique_forloop_name ()),
+    : m_evaluator (tr_eval),
+      m_llvm_function_name (tree_jit::generate_unique_forloop_name ()),
       m_function (nullptr)
   {
     compile (tee, jit_typeinfo::type_of (for_bounds));
@@ -2728,15 +2738,13 @@
 
     m_function (&real_arguments[0]);
 
-    symbol_scope scope = __require_current_scope__ ("jit_info::execute");
-
     for (size_t i = 0; i < m_arguments.size (); ++i)
       {
         const std::string& name = m_arguments[i].first;
 
         // do not store for loop bounds temporary
         if (name.size () && name[0] != '#')
-          scope.assign (m_arguments[i].first, real_arguments[i]);
+          m_evaluator.assign (m_arguments[i].first, real_arguments[i]);
       }
 
     octave_quit ();
@@ -2771,7 +2779,7 @@
 
     try
       {
-        jit_convert conv (tee, for_bounds);
+        jit_convert conv (m_evaluator, tee, for_bounds);
         jit_infer infer (conv.get_factory (), conv.get_blocks (),
                          conv.get_variable_map ());
 
@@ -2851,9 +2859,7 @@
 
     if (iter == extra_vars.end ())
       {
-        symbol_scope scope = __require_current_scope__ ("jit_convert::find");
-
-        return scope.varval (vname);
+        return m_evaluator.varval (vname);
       }
     else
       return *iter->second;
diff -r ef06683d1c22 -r 1f78cc5c749e libinterp/parse-tree/pt-jit.h
--- a/libinterp/parse-tree/pt-jit.h	Mon Jun 03 15:23:56 2019 -0500
+++ b/libinterp/parse-tree/pt-jit.h	Tue Jun 04 14:32:29 2019 -0500
@@ -38,6 +38,8 @@
 // octave_value_list is not (yet) in the octave namespace
 class octave_value_list;
 
+class tree_evaluator;
+
 namespace octave
 {
   namespace jit
@@ -56,9 +58,11 @@
     typedef std::vector<type_bound> type_bound_vector;
     typedef std::map<std::string, jit_variable *> variable_map;
 
-    jit_convert (tree& tee, jit_type *for_bounds = nullptr);
+    jit_convert (tree_evaluator& tr_eval, tree& tee,
+                 jit_type *for_bounds = nullptr);
 
-    jit_convert (octave_user_function& fcn, const std::vector<jit_type *>& args);
+    jit_convert (tree_evaluator& tr_eval, octave_user_function& fcn,
+                 const std::vector<jit_type *>& args);
 
     template <typename ...Args>
     jit_call * create_checked (const Args&... args)
@@ -168,10 +172,10 @@
     std::vector<std::pair<std::string, bool>> m_arguments;
     type_bound_vector m_bounds;
 
-    bool m_converting_function;
+    // the evaluator
+    tree_evaluator& m_evaluator;
 
-    // the scope of the function we are converting, or the current scope
-    symbol_scope m_scope;
+    bool m_converting_function;
 
     jit_factory m_factory;
 
@@ -196,7 +200,7 @@
 
     variable_map m_vmap;
 
-    void initialize (const symbol_scope& s);
+    void initialize ();
 
     jit_call * create_checked_impl (jit_call *ret);
 
@@ -484,26 +488,31 @@
 
   public:
 
-    static bool execute (tree_simple_for_command& cmd,
+    static bool execute (tree_evaluator& tr_eval,
+                         tree_simple_for_command& cmd,
                          const octave_value& bounds)
-    { return instance ().do_execute (cmd, bounds); }
+    { return instance ().do_execute (tr_eval, cmd, bounds); }
 
-    static bool execute (tree_while_command& cmd)
-    { return instance ().do_execute (cmd); }
+    static bool execute (tree_evaluator& tr_eval,
+                         tree_while_command& cmd)
+    { return instance ().do_execute (tr_eval, cmd); }
 
-    static bool execute (octave_user_function& fcn,
+    static bool execute (tree_evaluator& tr_eval,
+                         octave_user_function& fcn,
                          const octave_value_list& args,
                          octave_value_list& retval)
-    { return instance ().do_execute (fcn, args, retval); }
+    { return instance ().do_execute (tr_eval, fcn, args, retval); }
 
   private:
 
-    bool do_execute (tree_simple_for_command& cmd,
+    bool do_execute (tree_evaluator& tr_eval,
+                     tree_simple_for_command& cmd,
                      const octave_value& bounds);
 
-    bool do_execute (tree_while_command& cmd);
+    bool do_execute (tree_evaluator& tr_eval, tree_while_command& cmd);
 
-    bool do_execute (octave_user_function& fcn,
+    bool do_execute (tree_evaluator& tr_eval,
+                     octave_user_function& fcn,
                      const octave_value_list& args,
                      octave_value_list& retval);
 
@@ -587,11 +596,13 @@
     // we use a pointer here so we don't have to include ov.h
     typedef std::map<std::string, const octave_value *> vmap;
 
-    jit_info (tree& tee);
+    jit_info (tree_evaluator& tr_eval, tree& tee);
 
-    jit_info (tree& tee, const octave_value& for_bounds);
+    jit_info (tree_evaluator& tr_eval, tree& tee,
+              const octave_value& for_bounds);
 
-    jit_info (tree_simple_for_command& tee, const octave_value& for_bounds);
+    jit_info (tree_evaluator& tr_eval, tree_simple_for_command& tee,
+              const octave_value& for_bounds);
 
     bool execute (const vmap& extra_vars = vmap ()) const;
 
@@ -607,6 +618,8 @@
 
     octave_value find (const vmap& extra_vars, const std::string& vname) const;
 
+    tree_evaluator& m_evaluator;
+
     // LLVM function associated to this jit_info object
     std::string m_llvm_function_name;
     jited_function m_function;
@@ -621,7 +634,8 @@
   {
   public:
 
-    jit_function_info (octave_user_function& fcn,
+    jit_function_info (tree_evaluator& tr_eval,
+                       octave_user_function& fcn,
                        const octave_value_list& ov_args);
 
     bool execute (const octave_value_list& ov_args,
@@ -633,6 +647,8 @@
 
     typedef octave_base_value *(*jited_function)(octave_base_value**);
 
+    tree_evaluator& m_evaluator;
+
     // LLVM function associated to this jit_info object
     std::string m_llvm_function_name;
     jited_function m_function;
diff -r ef06683d1c22 -r 1f78cc5c749e m4/acinclude.m4
--- a/m4/acinclude.m4	Mon Jun 03 15:23:56 2019 -0500
+++ b/m4/acinclude.m4	Tue Jun 04 14:32:29 2019 -0500
@@ -2874,6 +2874,45 @@
   fi
 ])
 dnl
+dnl Check llvm::WriteBitcodeToFile API
+dnl
+AC_DEFUN([OCTAVE_LLVM_WRITEBITCODETOFILE_API], [
+  AC_CACHE_CHECK([if llvm::WriteBitcodeToFile requires a pointer or a reference argument],
+    [octave_cv_llvm_writebitcodetofile_has_ptr_arg],
+    [AC_LANG_PUSH(C++)
+      AC_COMPILE_IFELSE(
+        [AC_LANG_PROGRAM([[
+#if defined (HAVE_LLVM_BITCODE_READERWRITER_H)
+#  include <llvm/Bitcode/ReaderWriter.h>
+#else
+#  include <llvm/Bitcode/BitcodeWriter.h>
+#endif
+#if defined (HAVE_LLVM_IR_FUNCTION_H)
+#  include <llvm/IR/LLVMContext.h>
+#  include <llvm/IR/Module.h>
+#else
+#  include <llvm/LLVMContext.h>
+#  include <llvm/Module.h>
+#endif
+#include <llvm/Support/FileSystem.h>
+#include <llvm/Support/raw_ostream.h>
+          ]], [[
+          std::error_code ec;
+          llvm::LLVMContext c;
+          llvm::Module* m = new llvm::Module ("test", c);
+          llvm::raw_fd_ostream fout ("test.bc", ec, llvm::sys::fs::F_None);
+          llvm::WriteBitcodeToFile (m, fout);
+        ]])],
+        octave_cv_llvm_writebitcodetofile_has_ptr_arg=pointer,
+        octave_cv_llvm_writebitcodetofile_has_ptr_arg=reference)
+    AC_LANG_POP(C++)
+  ])
+  if test $octave_cv_llvm_writebitcodetofile_has_ptr_arg = pointer; then
+    AC_DEFINE(LLVM_WRITEBITCODETOFILE_HAS_PTR_ARG, 1,
+      [Define to 1 if llvm::WriteBitcodeToFile requires a pointer argument.])
+  fi
+])
+dnl
 dnl OCTAVE_CHECK_SEARCH_PATH
 dnl
 dnl Check if the specified path is already in the system search path
