GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
pt-jit.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2012-2017 Max Brister
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 // Author: Max Brister <max@2bass.com>
24 
25 #if ! defined (octave_pt_jit_h)
26 #define octave_pt_jit_h 1
27 
28 #include "octave-config.h"
29 
30 #if defined (HAVE_LLVM)
31 
32 #include "jit-ir.h"
33 #include "pt-walk.h"
34 #include "symtab.h"
35 
36 class octave_value_list;
37 
38 // Convert from the parse tree (AST) to the low level Octave IR.
39 class
40 jit_convert : public tree_walker
41 {
42 public:
43  typedef std::pair<jit_type *, std::string> type_bound;
44  typedef std::vector<type_bound> type_bound_vector;
45  typedef std::map<std::string, jit_variable *> variable_map;
46 
47  jit_convert (tree &tee, jit_type *for_bounds = 0);
48 
49  jit_convert (octave_user_function& fcn, const std::vector<jit_type *>& args);
50 
51 #define DECL_ARG(n) const ARG ## n& arg ## n
52 #define JIT_CREATE_CHECKED(N) \
53  template <OCT_MAKE_DECL_LIST (typename, ARG, N)> \
54  jit_call *create_checked (OCT_MAKE_LIST (DECL_ARG, N)) \
55  { \
56  jit_call *ret = factory.create<jit_call> (OCT_MAKE_ARG_LIST (arg, N)); \
57  return create_checked_impl (ret); \
58  }
59 
64 
65 #undef JIT_CREATE_CHECKED
66 #undef DECL_ARG
67 
68  jit_block_list& get_blocks (void) { return blocks; }
69 
70  const type_bound_vector& get_bounds (void) const { return bounds; }
71 
72  jit_factory& get_factory (void) { return factory; }
73 
74  llvm::Function *get_function (void) const { return function; }
75 
76  const variable_map &get_variable_map (void) const { return vmap; }
77 
78  void visit_anon_fcn_handle (tree_anon_fcn_handle&);
79 
80  void visit_argument_list (tree_argument_list&);
81 
82  void visit_binary_expression (tree_binary_expression&);
83 
84  void visit_break_command (tree_break_command&);
85 
86  void visit_colon_expression (tree_colon_expression&);
87 
88  void visit_continue_command (tree_continue_command&);
89 
90  void visit_global_command (tree_global_command&);
91 
92  void visit_persistent_command (tree_persistent_command&);
93 
94  void visit_decl_elt (tree_decl_elt&);
95 
96  void visit_decl_init_list (tree_decl_init_list&);
97 
98  void visit_simple_for_command (tree_simple_for_command&);
99 
100  void visit_complex_for_command (tree_complex_for_command&);
101 
102  void visit_octave_user_script (octave_user_script&);
103 
104  void visit_octave_user_function (octave_user_function&);
105 
106  void visit_octave_user_function_header (octave_user_function&);
107 
108  void visit_octave_user_function_trailer (octave_user_function&);
109 
110  void visit_function_def (tree_function_def&);
111 
112  void visit_identifier (tree_identifier&);
113 
114  void visit_if_clause (tree_if_clause&);
115 
116  void visit_if_command (tree_if_command&);
117 
118  void visit_if_command_list (tree_if_command_list&);
119 
120  void visit_index_expression (tree_index_expression&);
121 
122  void visit_matrix (tree_matrix&);
123 
124  void visit_cell (tree_cell&);
125 
126  void visit_multi_assignment (tree_multi_assignment&);
127 
128  void visit_no_op_command (tree_no_op_command&);
129 
130  void visit_constant (tree_constant&);
131 
132  void visit_fcn_handle (tree_fcn_handle&);
133 
134  void visit_funcall (tree_funcall&);
135 
136  void visit_parameter_list (tree_parameter_list&);
137 
138  void visit_postfix_expression (tree_postfix_expression&);
139 
140  void visit_prefix_expression (tree_prefix_expression&);
141 
142  void visit_return_command (tree_return_command&);
143 
144  void visit_return_list (tree_return_list&);
145 
146  void visit_simple_assignment (tree_simple_assignment&);
147 
148  void visit_statement (tree_statement&);
149 
150  void visit_statement_list (tree_statement_list&);
151 
152  void visit_switch_case (tree_switch_case&);
153 
154  void visit_switch_case_list (tree_switch_case_list&);
155 
156  void visit_switch_command (tree_switch_command&);
157 
158  void visit_try_catch_command (tree_try_catch_command&);
159 
160  void visit_unwind_protect_command (tree_unwind_protect_command&);
162  void visit_while_command (tree_while_command&);
163 
164  void visit_do_until_command (tree_do_until_command&);
165 private:
166  std::vector<std::pair<std::string, bool> > arguments;
167  type_bound_vector bounds;
168 
169  bool converting_function;
170 
171  // the scope of the function we are converting, or the current scope
173 
174  jit_factory factory;
175 
176  // used instead of return values from visit_* functions
177  jit_value *result;
179  jit_block *entry_block;
181  jit_block *final_block;
183  jit_block *block;
185  llvm::Function *function;
189  std::vector<jit_magic_end::context> end_context;
191  size_t iterator_count;
192  size_t for_bounds_count;
193  size_t short_count;
194 
195  variable_map vmap;
196 
198 
199  jit_call *create_checked_impl (jit_call *ret);
200 
201  // get an existing vairable. If the variable does not exist, it will not be
202  // created
203  jit_variable *find_variable (const std::string& vname) const;
204 
205  // get a variable, create it if it does not exist. The type will default to
206  // the variable's current type in the symbol table.
207  jit_variable *get_variable (const std::string& vname);
208 
209  // create a variable of the given name and given type. Will also insert an
210  // extract statement
211  jit_variable *create_variable (const std::string& vname, jit_type *type,
212  bool isarg = true);
213 
214  // The name of the next for loop iterator. If inc is false, then the
215  // iterator counter will not be incremented.
216  std::string next_iterator (bool inc = true)
217  { return next_name ("#iter", iterator_count, inc); }
218 
219  std::string next_for_bounds (bool inc = true)
220  { return next_name ("#for_bounds", for_bounds_count, inc); }
221 
222  std::string next_shortcircut_result (bool inc = true)
223  { return next_name ("#shortcircut_result", short_count, inc); }
224 
225  std::string next_name (const char *prefix, size_t& count, bool inc);
226 
227  jit_instruction *resolve (tree_index_expression& exp,
228  jit_value *extra_arg = 0, bool lhs = false);
229 
230  jit_value *do_assign (tree_expression *exp, jit_value *rhs,
231  bool artificial = false);
232 
233  jit_value *do_assign (const std::string& lhs, jit_value *rhs, bool print,
234  bool artificial = false);
236  jit_value *visit (tree *tee) { return visit (*tee); }
238  jit_value *visit (tree& tee);
239 
240  typedef std::list<jit_block *> block_list;
241  block_list breaks;
242  block_list continues;
244  void finish_breaks (jit_block *dest, const block_list& lst);
245 };
246 
247 // Convert from the low level Octave IR to LLVM
248 class
250 {
251 public:
252  llvm::Function *convert_loop (llvm::Module *module,
253  const jit_block_list& blocks,
254  const std::list<jit_value *>& constants);
255 
256  jit_function convert_function (llvm::Module *module,
257  const jit_block_list& blocks,
258  const std::list<jit_value *>& constants,
260  const std::vector<jit_type *>& args);
262  // arguments to the llvm::Function for loops
263  const std::vector<std::pair<std::string, bool> >& get_arguments(void) const
264  { return argument_vec; }
265 
266 #define JIT_METH(clname) \
267  virtual void visit (jit_ ## clname&);
268 
270 
271 #undef JIT_METH
272 private:
273  // name -> argument index (used for compiling functions)
274  std::map<std::string, int> argument_index;
275 
276  std::vector<std::pair<std::string, bool> > argument_vec;
277 
278  // name -> llvm argument (used for compiling loops)
279  std::map<std::string, llvm::Value *> arguments;
280 
281  bool converting_function;
283  // only used if we are converting a function
284  jit_function creating;
285 
286  llvm::Function *function;
287  llvm::BasicBlock *prelude;
288 
289  void convert (const jit_block_list& blocks,
290  const std::list<jit_value *>& constants);
291 
292  void finish_phi (jit_phi *phi);
293 
294  void visit (jit_value *jvalue)
295  {
296  return visit (*jvalue);
297  }
298 
299  void visit (jit_value &jvalue)
300  {
301  jvalue.accept (*this);
302  }
303 };
304 
305 // type inference and SSA construction on the low level Octave IR
306 class
307 jit_infer
308 {
309 public:
310  typedef jit_convert::variable_map variable_map;
311 
312  jit_infer (jit_factory& afactory, jit_block_list& ablocks,
313  const variable_map& avmap);
314 
315  jit_block_list& get_blocks (void) const { return blocks; }
317  jit_factory& get_factory (void) const { return factory; }
319  void infer (void);
320 private:
321  jit_block_list& blocks;
322  jit_factory& factory;
323  const variable_map& vmap;
324  std::list<jit_instruction *> worklist;
325 
326  void append_users (jit_value *v);
327 
328  void append_users_term (jit_terminator *term);
330  void construct_ssa (void);
332  void do_construct_ssa (jit_block& block, size_t avisit_count);
333 
334  jit_block& entry_block (void) { return *blocks.front (); }
335 
336  jit_block& final_block (void) { return *blocks.back (); }
337 
338  void place_releases (void);
339 
340  void push_worklist (jit_instruction *instr);
341 
342  void remove_dead ();
343 
344  void release_dead_phi (jit_block& ablock);
345 
346  void release_temp (jit_block& ablock, std::set<jit_value *>& temp);
347 
348  void simplify_phi (void);
349 
350  void simplify_phi (jit_phi& phi);
351 };
352 
353 class
354 tree_jit
355 {
356 public:
357  ~tree_jit (void);
358 
359  static bool execute (tree_simple_for_command& cmd,
360  const octave_value& bounds);
361 
362  static bool execute (tree_while_command& cmd);
363 
364  static bool execute (octave_user_function& fcn, const octave_value_list& args,
366 
367  llvm::ExecutionEngine *get_engine (void) const { return engine; }
368 
369  llvm::Module *get_module (void) const { return module; }
370 
371  void optimize (llvm::Function *fn);
372 private:
373  tree_jit (void);
374 
375  static tree_jit& instance (void);
376 
377  bool initialize (void);
378 
379  bool do_execute (tree_simple_for_command& cmd, const octave_value& bounds);
380 
381  bool do_execute (tree_while_command& cmd);
382 
383  bool do_execute (octave_user_function& fcn, const octave_value_list& args,
386  bool enabled (void);
387 
388  size_t trip_count (const octave_value& bounds) const;
389 
390  llvm::Module *module;
391 #if defined (LEGACY_PASSMANAGER)
392  llvm::legacy::PassManager *module_pass_manager;
393  llvm::legacy::FunctionPassManager *pass_manager;
394 #else
395  llvm::PassManager *module_pass_manager;
396  llvm::FunctionPassManager *pass_manager;
397 #endif
398  llvm::ExecutionEngine *engine;
399 };
400 
401 class
403 {
404 public:
406  const octave_value_list& ov_args);
407 
408  bool execute (const octave_value_list& ov_args,
409  octave_value_list& retval) const;
411  bool match (const octave_value_list& ov_args) const;
412 private:
413  typedef octave_base_value *(*jited_function)(octave_base_value**);
415  std::vector<jit_type *> argument_types;
416  jited_function function;
417 };
418 
419 class
420 jit_info
421 {
422 public:
423  // we use a pointer here so we don't have to include ov.h
424  typedef std::map<std::string, const octave_value *> vmap;
425 
426  jit_info (tree_jit& tjit, tree& tee);
427 
428  jit_info (tree_jit& tjit, tree& tee, const octave_value& for_bounds);
429 
430  ~jit_info (void);
432  bool execute (const vmap& extra_vars = vmap ()) const;
434  bool match (const vmap& extra_vars = vmap ()) const;
435 private:
436  typedef jit_convert::type_bound type_bound;
437  typedef jit_convert::type_bound_vector type_bound_vector;
438  typedef void (*jited_function)(octave_base_value**);
440  void compile (tree_jit& tjit, tree& tee, jit_type *for_bounds = 0);
442  octave_value find (const vmap& extra_vars, const std::string& vname) const;
444  llvm::ExecutionEngine *engine;
445  jited_function function;
446  llvm::Function *llvm_function;
447 
448  std::vector<std::pair<std::string, bool> > arguments;
449  type_bound_vector bounds;
450 };
451 
452 #endif
453 #endif
#define JIT_VISIT_IR_CLASSES
Definition: jit-ir.h:65
virtual void accept(jit_ir_walker &walker)=0
s
Definition: file-io.cc:2682
octave_function * fcn
Definition: ov-class.cc:1743
JNIEnv void * args
Definition: ov-java.cc:67
jit_block * back(void) const
Definition: jit-ir.h:154
jit_factory & factory
Definition: pt-jit.h:317
std::list< jit_block * > block_list
Definition: pt-jit.h:235
jit_block * front(void) const
Definition: jit-ir.h:166
static std::string get_variable(const char *name, const std::string &defval)
Definition: mkoctfile.cc:104
octave_value retval
Definition: data.cc:6294
idx type
Definition: ov.cc:3129
With real return the complex result
Definition: data.cc:3375
static octave_idx_type find(octave_idx_type i, octave_idx_type *pp)
Definition: colamd.cc:112
std::pair< jit_type *, std::string > type_bound
Definition: pt-jit.h:43
Definition: pt.h:39
std::map< std::string, jit_variable * > variable_map
Definition: pt-jit.h:45
static void initialize(void)
Definition: mkoctfile.cc:123
#define JIT_CREATE_CHECKED(N)
Definition: pt-jit.h:52
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
With real arguments
Definition: data.cc:3375
void visit(jit_value &jvalue)
Definition: pt-jit.h:294
std::vector< type_bound > type_bound_vector
Definition: pt-jit.h:44