GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
pt-jit.h
Go to the documentation of this file.
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 #if ! defined (octave_pt_jit_h)
27 #define octave_pt_jit_h 1
28 
29 #include "octave-config.h"
30 
31 #if defined (HAVE_LLVM)
32 
33 #include "jit-util.h"
34 #include "jit-typeinfo.h"
35 #include "jit-ir.h"
36 #include "pt-walk.h"
37 #include "symscope.h"
38 
39 // octave_value_list is not (yet) in the octave namespace
40 class octave_value_list;
41 
42 namespace octave
43 {
44  namespace jit
45  {
46  typedef std::unique_ptr<llvm::Module> ModuleOwner;
47  typedef std::unique_ptr<llvm::ExecutionEngine> EngineOwner;
48  }
49 
50  // Convert from the parse tree (AST) to the low level Octave IR.
51  class
52  jit_convert : public tree_walker
53  {
54  public:
55 
56  typedef std::pair<jit_type *, std::string> type_bound;
57  typedef std::vector<type_bound> type_bound_vector;
58  typedef std::map<std::string, jit_variable *> variable_map;
59 
60  jit_convert (tree& tee, jit_type *for_bounds = nullptr);
61 
62  jit_convert (octave_user_function& fcn, const std::vector<jit_type *>& args);
63 
64  template <typename ...Args>
65  jit_call * create_checked (const Args&... args)
66  {
67  jit_call *ret = m_factory.create<jit_call> (args...);
68  return create_checked_impl (ret);
69  }
70 
71  jit_block_list& get_blocks (void) { return m_blocks; }
72 
73  const type_bound_vector& get_bounds (void) const { return m_bounds; }
74 
75  jit_factory& get_factory (void) { return m_factory; }
76 
77  llvm::Function *get_function (void) const { return m_function; }
78 
79  const variable_map& get_variable_map (void) const { return m_vmap; }
80 
81  void visit_anon_fcn_handle (tree_anon_fcn_handle&);
82 
83  void visit_argument_list (tree_argument_list&);
84 
85  void visit_binary_expression (tree_binary_expression&);
86 
87  void visit_boolean_expression (tree_boolean_expression&);
88 
89  void visit_break_command (tree_break_command&);
90 
91  void visit_colon_expression (tree_colon_expression&);
92 
93  void visit_continue_command (tree_continue_command&);
94 
95  void visit_decl_command (tree_decl_command&);
96 
97  void visit_decl_init_list (tree_decl_init_list&);
98 
99  void visit_decl_elt (tree_decl_elt&);
100 
101  void visit_simple_for_command (tree_simple_for_command&);
102 
103  void visit_complex_for_command (tree_complex_for_command&);
104 
105  void visit_octave_user_script (octave_user_script&);
106 
107  void visit_octave_user_function (octave_user_function&);
108 
109  void visit_octave_user_function_header (octave_user_function&);
110 
111  void visit_octave_user_function_trailer (octave_user_function&);
112 
113  void visit_function_def (tree_function_def&);
114 
115  void visit_identifier (tree_identifier&);
116 
117  void visit_if_clause (tree_if_clause&);
118 
120 
121  void visit_if_command_list (tree_if_command_list&);
122 
123  void visit_index_expression (tree_index_expression&);
124 
125  void visit_matrix (tree_matrix&);
126 
127  void visit_cell (tree_cell&);
128 
129  void visit_multi_assignment (tree_multi_assignment&);
130 
131  void visit_no_op_command (tree_no_op_command&);
132 
133  void visit_constant (tree_constant&);
134 
135  void visit_fcn_handle (tree_fcn_handle&);
136 
137  void visit_parameter_list (tree_parameter_list&);
138 
139  void visit_postfix_expression (tree_postfix_expression&);
140 
141  void visit_prefix_expression (tree_prefix_expression&);
142 
143  void visit_return_command (tree_return_command&);
144 
145  void visit_simple_assignment (tree_simple_assignment&);
146 
147  void visit_statement (tree_statement&);
148 
150 
151  void visit_switch_case (tree_switch_case&);
152 
153  void visit_switch_case_list (tree_switch_case_list&);
154 
155  void visit_switch_command (tree_switch_command&);
156 
157  void visit_try_catch_command (tree_try_catch_command&);
158 
159  void visit_unwind_protect_command (tree_unwind_protect_command&);
160 
161  void visit_while_command (tree_while_command&);
162 
163  void visit_do_until_command (tree_do_until_command&);
164 
165  private:
166 
167  std::vector<std::pair<std::string, bool>> m_arguments;
169 
171 
172  // the scope of the function we are converting, or the current scope
174 
176 
177  // used instead of return values from visit_* functions
179 
181 
183 
185 
186  llvm::Function *m_function;
187 
189 
190  std::vector<jit_magic_end::context> m_end_context;
191 
195 
197 
198  void initialize (const symbol_scope& s);
199 
200  jit_call * create_checked_impl (jit_call *ret);
201 
202  // get an existing vairable. If the variable does not exist, it will not be
203  // created
204  jit_variable * find_variable (const std::string& vname) const;
205 
206  // get a variable, create it if it does not exist. The type will default to
207  // the variable's current type in the symbol table.
208  jit_variable * get_variable (const std::string& vname);
209 
210  // create a variable of the given name and given type. Will also insert an
211  // extract statement
212  jit_variable * create_variable (const std::string& vname, jit_type *type,
213  bool isarg = true);
214 
215  // The name of the next for loop iterator. If inc is false, then the
216  // iterator counter will not be incremented.
217  std::string next_iterator (bool inc = true)
218  { return next_name ("#iter", m_iterator_count, inc); }
219 
220  std::string next_for_bounds (bool inc = true)
221  { return next_name ("#for_bounds", m_for_bounds_count, inc); }
222 
223  std::string next_shortcircut_result (bool inc = true)
224  { return next_name ("#shortcircut_result", m_short_count, inc); }
225 
226  std::string next_name (const char *prefix, size_t& count, bool inc);
227 
228  jit_instruction * resolve (tree_index_expression& exp,
229  jit_value *extra_arg = nullptr, bool lhs = false);
230 
231  jit_value * do_assign (tree_expression *exp, jit_value *rhs,
232  bool artificial = false);
233 
234  jit_value * do_assign (const std::string& lhs, jit_value *rhs, bool print,
235  bool artificial = false);
236 
237  jit_value * visit (tree *tee) { return visit (*tee); }
238 
239  jit_value * visit (tree& tee);
240 
241  typedef std::list<jit_block *> block_list;
244 
245  void finish_breaks (jit_block *dest, const block_list& lst);
246  };
247 
248  // Convert from the low level Octave IR to LLVM
249  class
251  {
252  public:
253 
254  llvm::Function * convert_loop (const jit_module& module,
255  const jit_block_list& blocks,
256  const std::list<jit_value *>& constants,
257  const std::string& llvm_function_name);
258 
259  jit_function convert_function (const jit_module& module,
260  const jit_block_list& blocks,
261  const std::list<jit_value *>& constants,
263  const std::vector<jit_type *>& args);
264 
265  // arguments to the llvm::Function for loops
266  const std::vector<std::pair<std::string, bool>>& get_arguments(void) const
267  { return m_argument_vec; }
268 
269 #define JIT_METH(clname) \
270  virtual void visit (jit_ ## clname&);
271 
273 
274 #undef JIT_METH
275 
276  private:
277 
278  // name -> argument index (used for compiling functions)
279  std::map<std::string, int> m_argument_index;
280 
281  std::vector<std::pair<std::string, bool>> m_argument_vec;
282 
283  // name -> llvm argument (used for compiling loops)
284  std::map<std::string, llvm::Value *> m_arguments;
285 
287 
288  // only used if we are converting a function
290 
291  llvm::Function *m_function;
292  llvm::BasicBlock *m_prelude;
293 
294  void convert (const jit_block_list& blocks,
295  const std::list<jit_value *>& constants);
296 
297  void finish_phi (jit_phi *phi);
298 
299  void visit (jit_value *jvalue)
300  {
301  return visit (*jvalue);
302  }
303 
304  void visit (jit_value& jvalue)
305  {
306  jvalue.accept (*this);
307  }
308  };
309 
310  // type inference and SSA construction on the low level Octave IR
311  class
312  jit_infer
313  {
314  public:
315 
317 
318  jit_infer (jit_factory& afactory, jit_block_list& ablocks,
319  const variable_map& avmap);
320 
321  jit_block_list& get_blocks (void) const { return m_blocks; }
322 
323  jit_factory& get_factory (void) const { return m_factory; }
324 
325  void infer (void);
326 
327  private:
328 
332  std::list<jit_instruction *> m_worklist;
333 
334  void append_users (jit_value *v);
335 
336  void append_users_term (jit_terminator *term);
337 
338  void construct_ssa (void);
339 
340  void do_construct_ssa (jit_block& block, size_t avisit_count);
341 
342  jit_block& entry_block (void) { return *m_blocks.front (); }
343 
344  jit_block& final_block (void) { return *m_blocks.back (); }
345 
346  void place_releases (void);
347 
348  void push_worklist (jit_instruction *instr);
349 
350  void remove_dead ();
351 
352  void release_dead_phi (jit_block& ablock);
353 
354  void release_temp (jit_block& ablock, std::set<jit_value *>& temp);
355 
356  void simplify_phi (void);
357 
358  void simplify_phi (jit_phi& phi);
359  };
360 
361 
362  class jit_module;
363 
364  class
365  tree_jit
366  {
367  // ----- Constructor/destructor (singleton pattern) -----
368 
369  public:
370 
371  ~tree_jit (void);
372 
373  private:
374 
375  tree_jit (void);
376  static tree_jit& instance (void);
377 
378  // ----- Initialization -----
379 
380  private:
381 
382  static bool initialized;
383  bool do_initialize (void);
384 
385  // ----- LLVM context -----
386 
387  public:
388 
389  static llvm::LLVMContext llvm_context;
390 
391  // ----- Target machine ----
392 
393  public:
394 
395  static const llvm::TargetMachine* get_target_machine (void)
396  { return instance ().target_machine; }
397 
398  private:
399 
400  llvm::TargetMachine *target_machine;
401 
402  // ----- Create LLVM modules and engines -----
403 
404  public:
405 
406  static jit::ModuleOwner
407  open_new_module (const std::string& module_name = generate_unique_module_name ());
408 
409  static jit::EngineOwner
410  create_new_engine (jit::ModuleOwner module_owner);
411 
412  private:
413 
415  do_open_new_module (const std::string& module_name) const;
416 
417  // ----- Registering JIT modules (module+engine pairs) -----
418 
419  public:
420 
421  static void register_jit_module (jit_module* jm)
422  { instance ().do_register_jit_module (jm); }
423 
425  { instance ().do_unregister_jit_module (jm); }
426 
427  private:
428 
429  // List of all currently registered jit modules
430  std::list<jit_module*> jm_list;
431  void do_register_jit_module (jit_module* jm);
432  void do_unregister_jit_module (jit_module* jm);
433  void do_dump_all_modules (void) const;
434 
435  // ----- Symbol resolution -----
436 
437  public:
438 
439  static void* getPointerToNamedFunction (const std::string &name)
440  { return instance ().do_getPointerToNamedFunction (name); }
441 
442  static uint64_t getSymbolAddress (const std::string &name)
443  { return instance ().do_getSymbolAddress (name); }
444 
445  private:
446 
447  void* do_getPointerToNamedFunction (const std::string &Name) const;
448 
449  uint64_t do_getSymbolAddress (const std::string &name) const;
450 
451  // ----- Generate unique identifiers -----
452 
453  public:
454 
455  static std::string generate_unique_forloop_name (void)
456  {
457  return std::string ("jittedForLoop")
458  + std::to_string (next_forloop_number ++);
459  }
460  // FIXME: Check that the identifier does not exist
461 
462  static std::string generate_unique_function_name (void)
463  {
464  return std::string ("jittedFunction")
465  + std::to_string (next_function_number ++);
466  }
467  // FIXME: Check that the identifier does not exist
468 
469  static std::string generate_unique_module_name (void)
470  {
471  return std::string ("octaveJITModule")
472  + std::to_string (next_module_number ++);
473  }
474  // FIXME: Check that the identifier does not exist
475 
476  private:
477 
480  static int next_module_number;
481 
482  // ----- JIT and execute ASTs -----
483 
484  public:
485 
486  static bool execute (tree_simple_for_command& cmd,
487  const octave_value& bounds)
488  { return instance ().do_execute (cmd, bounds); }
489 
490  static bool execute (tree_while_command& cmd)
491  { return instance ().do_execute (cmd); }
492 
493  static bool execute (octave_user_function& fcn,
494  const octave_value_list& args,
496  { return instance ().do_execute (fcn, args, retval); }
497 
498  private:
499 
500  bool do_execute (tree_simple_for_command& cmd,
501  const octave_value& bounds);
502 
503  bool do_execute (tree_while_command& cmd);
504 
505  bool do_execute (octave_user_function& fcn,
506  const octave_value_list& args,
508 
509  // ----- Miscellaneous -----
510 
511  bool enabled (void);
512 
513  size_t trip_count (const octave_value& bounds) const;
514  };
515 
516 
517  class
518  jit_module
519  {
520  // TODO: Encapsulate all operations that can modify the module,
521  // and prevent them if the module has been finalized
522 
523  // TODO: Consider creating the engine at the end only?
524  // I have read somewhere that this is more efficient (nor sure)
525 
526  public:
527 
528  // Create an open module and associated JIT engine
529  jit_module (const std::string& module_name
531 
532  // Delete the underlying JIT engine
533  ~jit_module ();
534 
535  // Create an LLVM function in the module, with external linkage
536  llvm::Function*
537  create_llvm_function (llvm::FunctionType *ftype,
538  const llvm::Twine &name) const;
539 
540  // Create a global in the module, with external linkage
541  llvm::GlobalVariable*
542  create_global_variable (llvm::Type *type, bool is_constant,
543  const llvm::Twine& name) const;
544 
545  // Create or insert an LLVM Function declaration for an intrinsic,
546  // and return it
547  llvm::Function*
548  get_intrinsic_declaration (size_t id,
549  std::vector<llvm::Type*> types) const;
550 
551  // Underlying type of enums defined in yet-inconplete types
552  typedef unsigned llvm_gv_linkage; // FIXME: autoconf this
553 
554  // add_global_mapping tells the execution engine where a specified
555  // global value (variable or function) is
556  template <typename ptr_type>
557  void add_global_mapping (const llvm::GlobalValue* gv, ptr_type p) const
558  {
559  do_add_global_mapping (gv, reinterpret_cast<void *> (p));
560  }
561 
562  // Return the address of the specified function.
563  uint64_t getFunctionAddress (const std::string &name) const;
564 
565  // Optimize a function in the LLVM module
566  void optimize (llvm::Function *fn) const;
567 
568  // FIXME: Once this has been called, we should not be able
569  // to change anything in the module...
570  void finalizeObject (void);
571 
572  private:
573 
574  void do_add_global_mapping (const llvm::GlobalValue* gv, void* p) const;
575 
576  llvm::Module *m_module;
577  llvm::ExecutionEngine *m_engine;
578  };
579 
580 
581  class
582  jit_info : public jit_module
583  {
584  public:
585 
586  // we use a pointer here so we don't have to include ov.h
587  typedef std::map<std::string, const octave_value *> vmap;
588 
589  jit_info (tree& tee);
590 
591  jit_info (tree& tee, const octave_value& for_bounds);
592 
593  jit_info (tree_simple_for_command& tee, const octave_value& for_bounds);
594 
595  bool execute (const vmap& extra_vars = vmap ()) const;
596 
597  bool match (const vmap& extra_vars = vmap ()) const;
598 
599  private:
600 
603  typedef void (*jited_function)(octave_base_value**);
604 
605  void compile (tree& tee, jit_type *for_bounds = 0);
606 
607  octave_value find (const vmap& extra_vars, const std::string& vname) const;
608 
609  // LLVM function associated to this jit_info object
610  std::string m_llvm_function_name;
611  jited_function m_function;
612 
613  std::vector<std::pair<std::string, bool>> m_arguments;
615  };
616 
617 
618  class
620  {
621  public:
622 
624  const octave_value_list& ov_args);
625 
626  bool execute (const octave_value_list& ov_args,
627  octave_value_list& retval) const;
628 
629  bool match (const octave_value_list& ov_args) const;
630 
631  private:
632 
633  typedef octave_base_value *(*jited_function)(octave_base_value**);
634 
635  // LLVM function associated to this jit_info object
636  std::string m_llvm_function_name;
637  jited_function m_function;
638 
639  std::vector<jit_type *> m_argument_types;
640  };
641 }
642 
643 #endif
644 
645 #endif
jit_block * front(void) const
Definition: jit-ir.h:158
jit_block * back(void) const
Definition: jit-ir.h:146
llvm::Function * m_function
Definition: pt-jit.h:291
std::map< std::string, llvm::Value * > m_arguments
Definition: pt-jit.h:284
void visit(jit_value *jvalue)
Definition: pt-jit.h:299
const std::vector< std::pair< std::string, bool > > & get_arguments(void) const
Definition: pt-jit.h:266
llvm::BasicBlock * m_prelude
Definition: pt-jit.h:292
jit_function m_creating
Definition: pt-jit.h:289
std::vector< std::pair< std::string, bool > > m_argument_vec
Definition: pt-jit.h:281
void visit(jit_value &jvalue)
Definition: pt-jit.h:304
std::map< std::string, int > m_argument_index
Definition: pt-jit.h:272
size_t m_iterator_count
Definition: pt-jit.h:192
llvm::Function * m_function
Definition: pt-jit.h:186
symbol_scope m_scope
Definition: pt-jit.h:173
bool m_converting_function
Definition: pt-jit.h:170
std::string next_for_bounds(bool inc=true)
Definition: pt-jit.h:220
void visit_if_command(tree_if_command &)
void visit_statement_list(tree_statement_list &)
block_list m_continues
Definition: pt-jit.h:243
jit_factory & get_factory(void)
Definition: pt-jit.h:75
variable_map m_vmap
Definition: pt-jit.h:196
jit_factory m_factory
Definition: pt-jit.h:175
jit_block_list & get_blocks(void)
Definition: pt-jit.h:71
llvm::Function * get_function(void) const
Definition: pt-jit.h:77
std::vector< type_bound > type_bound_vector
Definition: pt-jit.h:57
size_t m_short_count
Definition: pt-jit.h:194
jit_block_list m_blocks
Definition: pt-jit.h:188
jit_block * m_entry_block
Definition: pt-jit.h:180
jit_block * m_final_block
Definition: pt-jit.h:182
std::vector< std::pair< std::string, bool > > m_arguments
Definition: pt-jit.h:167
jit_value * visit(tree *tee)
Definition: pt-jit.h:237
block_list m_breaks
Definition: pt-jit.h:242
const variable_map & get_variable_map(void) const
Definition: pt-jit.h:79
jit_block * m_block
Definition: pt-jit.h:184
std::string next_shortcircut_result(bool inc=true)
Definition: pt-jit.h:223
std::pair< jit_type *, std::string > type_bound
Definition: pt-jit.h:56
std::vector< jit_magic_end::context > m_end_context
Definition: pt-jit.h:190
size_t m_for_bounds_count
Definition: pt-jit.h:193
std::string next_iterator(bool inc=true)
Definition: pt-jit.h:217
type_bound_vector m_bounds
Definition: pt-jit.h:168
std::list< jit_block * > block_list
Definition: pt-jit.h:241
jit_call * create_checked(const Args &... args)
Definition: pt-jit.h:65
std::map< std::string, jit_variable * > variable_map
Definition: pt-jit.h:58
const type_bound_vector & get_bounds(void) const
Definition: pt-jit.h:73
jit_value * m_result
Definition: pt-jit.h:178
jited_function m_function
Definition: pt-jit.h:637
std::string m_llvm_function_name
Definition: pt-jit.h:636
std::vector< jit_type * > m_argument_types
Definition: pt-jit.h:639
std::list< jit_instruction * > m_worklist
Definition: pt-jit.h:332
jit_block_list & get_blocks(void) const
Definition: pt-jit.h:321
jit_block_list & m_blocks
Definition: pt-jit.h:329
jit_convert::variable_map variable_map
Definition: pt-jit.h:316
jit_factory & get_factory(void) const
Definition: pt-jit.h:323
jit_block & entry_block(void)
Definition: pt-jit.h:342
const variable_map & m_vmap
Definition: pt-jit.h:331
jit_block & final_block(void)
Definition: pt-jit.h:344
jit_factory & m_factory
Definition: pt-jit.h:330
type_bound_vector m_bounds
Definition: pt-jit.h:614
std::vector< std::pair< std::string, bool > > m_arguments
Definition: pt-jit.h:613
jited_function m_function
Definition: pt-jit.h:611
jit_convert::type_bound type_bound
Definition: pt-jit.h:601
std::map< std::string, const octave_value * > vmap
Definition: pt-jit.h:587
std::string m_llvm_function_name
Definition: pt-jit.h:610
jit_convert::type_bound_vector type_bound_vector
Definition: pt-jit.h:602
llvm::ExecutionEngine * m_engine
Definition: pt-jit.h:577
void add_global_mapping(const llvm::GlobalValue *gv, ptr_type p) const
Definition: pt-jit.h:557
llvm::Module * m_module
Definition: pt-jit.h:576
unsigned llvm_gv_linkage
Definition: pt-jit.h:552
virtual void accept(jit_ir_walker &walker)=0
static int next_module_number
Definition: pt-jit.h:480
void * do_getPointerToNamedFunction(const std::string &Name) const
Definition: pt-jit.cc:2163
uint64_t do_getSymbolAddress(const std::string &name) const
Definition: pt-jit.cc:2179
static const llvm::TargetMachine * get_target_machine(void)
Definition: pt-jit.h:395
void do_register_jit_module(jit_module *jm)
Definition: pt-jit.cc:2151
static llvm::LLVMContext llvm_context
Definition: pt-jit.h:389
void do_unregister_jit_module(jit_module *jm)
Definition: pt-jit.cc:2157
static void * getPointerToNamedFunction(const std::string &name)
Definition: pt-jit.h:439
static bool initialized
Definition: pt-jit.h:382
std::list< jit_module * > jm_list
Definition: pt-jit.h:430
static uint64_t getSymbolAddress(const std::string &name)
Definition: pt-jit.h:442
static bool execute(tree_while_command &cmd)
Definition: pt-jit.h:490
static int next_function_number
Definition: pt-jit.h:479
static void unregister_jit_module(jit_module *jm)
Definition: pt-jit.h:424
static bool execute(tree_simple_for_command &cmd, const octave_value &bounds)
Definition: pt-jit.h:486
static void register_jit_module(jit_module *jm)
Definition: pt-jit.h:421
static int next_forloop_number
Definition: pt-jit.h:478
llvm::TargetMachine * target_machine
Definition: pt-jit.h:400
static std::string generate_unique_module_name(void)
Definition: pt-jit.h:469
static std::string generate_unique_forloop_name(void)
Definition: pt-jit.h:455
bool do_execute(tree_simple_for_command &cmd, const octave_value &bounds)
Definition: pt-jit.cc:2237
static bool execute(octave_user_function &fcn, const octave_value_list &args, octave_value_list &retval)
Definition: pt-jit.h:493
void do_dump_all_modules(void) const
static std::string generate_unique_function_name(void)
Definition: pt-jit.h:462
static octave_idx_type find(octave_idx_type i, octave_idx_type *pp)
Definition: colamd.cc:104
static int convert(int x, int ibase, int obase)
Definition: file-io.cc:3032
QString name
#define JIT_VISIT_IR_CLASSES
Definition: jit-ir.h:69
static void initialize(void)
static std::string get_variable(const char *name, const std::string &defval)
std::unique_ptr< llvm::ExecutionEngine > EngineOwner
Definition: pt-jit.h:47
std::unique_ptr< llvm::Module > ModuleOwner
Definition: pt-jit.h:46
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811