GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
pt-jit.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2012-2013 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 #ifdef HAVE_LLVM
29 
30 #include "jit-ir.h"
31 #include "pt-walk.h"
32 #include "symtab.h"
33 
34 class octave_value_list;
35 
36 // Convert from the parse tree (AST) to the low level Octave IR.
37 class
38 jit_convert : public tree_walker
39 {
40 public:
41  typedef std::pair<jit_type *, std::string> type_bound;
42  typedef std::vector<type_bound> type_bound_vector;
43  typedef std::map<std::string, jit_variable *> variable_map;
44 
45  jit_convert (tree &tee, jit_type *for_bounds = 0);
46 
47  jit_convert (octave_user_function& fcn, const std::vector<jit_type *>& args);
48 
49 #define DECL_ARG(n) const ARG ## n& arg ## n
50 #define JIT_CREATE_CHECKED(N) \
51  template <OCT_MAKE_DECL_LIST (typename, ARG, N)> \
52  jit_call *create_checked (OCT_MAKE_LIST (DECL_ARG, N)) \
53  { \
54  jit_call *ret = factory.create<jit_call> (OCT_MAKE_ARG_LIST (arg, N)); \
55  return create_checked_impl (ret); \
56  }
57 
62 
63 #undef JIT_CREATE_CHECKED
64 #undef DECL_ARG
65 
66  jit_block_list& get_blocks (void) { return blocks; }
67 
68  const type_bound_vector& get_bounds (void) const { return bounds; }
69 
70  jit_factory& get_factory (void) { return factory; }
71 
72  llvm::Function *get_function (void) const { return function; }
73 
74  const variable_map &get_variable_map (void) const { return vmap; }
75 
76  void visit_anon_fcn_handle (tree_anon_fcn_handle&);
77 
78  void visit_argument_list (tree_argument_list&);
79 
80  void visit_binary_expression (tree_binary_expression&);
81 
82  void visit_break_command (tree_break_command&);
83 
84  void visit_colon_expression (tree_colon_expression&);
85 
86  void visit_continue_command (tree_continue_command&);
87 
88  void visit_global_command (tree_global_command&);
89 
90  void visit_persistent_command (tree_persistent_command&);
91 
92  void visit_decl_elt (tree_decl_elt&);
93 
94  void visit_decl_init_list (tree_decl_init_list&);
95 
96  void visit_simple_for_command (tree_simple_for_command&);
97 
98  void visit_complex_for_command (tree_complex_for_command&);
99 
100  void visit_octave_user_script (octave_user_script&);
101 
102  void visit_octave_user_function (octave_user_function&);
103 
104  void visit_octave_user_function_header (octave_user_function&);
105 
106  void visit_octave_user_function_trailer (octave_user_function&);
107 
108  void visit_function_def (tree_function_def&);
109 
110  void visit_identifier (tree_identifier&);
111 
112  void visit_if_clause (tree_if_clause&);
113 
114  void visit_if_command (tree_if_command&);
115 
116  void visit_if_command_list (tree_if_command_list&);
117 
118  void visit_index_expression (tree_index_expression&);
119 
120  void visit_matrix (tree_matrix&);
121 
122  void visit_cell (tree_cell&);
123 
124  void visit_multi_assignment (tree_multi_assignment&);
125 
126  void visit_no_op_command (tree_no_op_command&);
127 
128  void visit_constant (tree_constant&);
129 
130  void visit_fcn_handle (tree_fcn_handle&);
131 
132  void visit_parameter_list (tree_parameter_list&);
133 
134  void visit_postfix_expression (tree_postfix_expression&);
135 
136  void visit_prefix_expression (tree_prefix_expression&);
137 
138  void visit_return_command (tree_return_command&);
139 
140  void visit_return_list (tree_return_list&);
141 
142  void visit_simple_assignment (tree_simple_assignment&);
143 
144  void visit_statement (tree_statement&);
145 
146  void visit_statement_list (tree_statement_list&);
147 
148  void visit_switch_case (tree_switch_case&);
149 
150  void visit_switch_case_list (tree_switch_case_list&);
151 
152  void visit_switch_command (tree_switch_command&);
153 
154  void visit_try_catch_command (tree_try_catch_command&);
155 
156  void visit_unwind_protect_command (tree_unwind_protect_command&);
157 
158  void visit_while_command (tree_while_command&);
159 
160  void visit_do_until_command (tree_do_until_command&);
161 private:
162  std::vector<std::pair<std::string, bool> > arguments;
163  type_bound_vector bounds;
164 
166 
167  // the scope of the function we are converting, or the current scope
169 
171 
172  // used instead of return values from visit_* functions
174 
176 
178 
180 
181  llvm::Function *function;
182 
184 
185  std::vector<jit_magic_end::context> end_context;
186 
189  size_t short_count;
190 
191  variable_map vmap;
192 
194 
195  jit_call *create_checked_impl (jit_call *ret);
196 
197  // get an existing vairable. If the variable does not exist, it will not be
198  // created
199  jit_variable *find_variable (const std::string& vname) const;
200 
201  // get a variable, create it if it does not exist. The type will default to
202  // the variable's current type in the symbol table.
203  jit_variable *get_variable (const std::string& vname);
204 
205  // create a variable of the given name and given type. Will also insert an
206  // extract statement
207  jit_variable *create_variable (const std::string& vname, jit_type *type,
208  bool isarg = true);
209 
210  // The name of the next for loop iterator. If inc is false, then the iterator
211  // counter will not be incremented.
212  std::string next_iterator (bool inc = true)
213  { return next_name ("#iter", iterator_count, inc); }
214 
215  std::string next_for_bounds (bool inc = true)
216  { return next_name ("#for_bounds", for_bounds_count, inc); }
217 
218  std::string next_shortcircut_result (bool inc = true)
219  { return next_name ("#shortcircut_result", short_count, inc); }
220 
221  std::string next_name (const char *prefix, size_t& count, bool inc);
222 
223  jit_instruction *resolve (tree_index_expression& exp,
224  jit_value *extra_arg = 0, bool lhs = false);
225 
226  jit_value *do_assign (tree_expression *exp, jit_value *rhs,
227  bool artificial = false);
228 
229  jit_value *do_assign (const std::string& lhs, jit_value *rhs, bool print,
230  bool artificial = false);
231 
232  jit_value *visit (tree *tee) { return visit (*tee); }
233 
234  jit_value *visit (tree& tee);
235 
236  typedef std::list<jit_block *> block_list;
237  block_list breaks;
238  block_list continues;
239 
240  void finish_breaks (jit_block *dest, const block_list& lst);
241 };
242 
243 // Convert from the low level Octave IR to LLVM
244 class
246 {
247 public:
248  llvm::Function *convert_loop (llvm::Module *module,
249  const jit_block_list& blocks,
250  const std::list<jit_value *>& constants);
251 
252  jit_function convert_function (llvm::Module *module,
253  const jit_block_list& blocks,
254  const std::list<jit_value *>& constants,
256  const std::vector<jit_type *>& args);
257 
258  // arguments to the llvm::Function for loops
259  const std::vector<std::pair<std::string, bool> >& get_arguments(void) const
260  { return argument_vec; }
261 
262 #define JIT_METH(clname) \
263  virtual void visit (jit_ ## clname&);
264 
266 
267 #undef JIT_METH
268 private:
269  // name -> argument index (used for compiling functions)
270  std::map<std::string, int> argument_index;
271 
272  std::vector<std::pair<std::string, bool> > argument_vec;
273 
274  // name -> llvm argument (used for compiling loops)
275  std::map<std::string, llvm::Value *> arguments;
276 
278 
279  // only used if we are converting a function
281 
282  llvm::Function *function;
283  llvm::BasicBlock *prelude;
284 
285  void convert (const jit_block_list& blocks,
286  const std::list<jit_value *>& constants);
287 
288  void finish_phi (jit_phi *phi);
289 
290  void visit (jit_value *jvalue)
291  {
292  return visit (*jvalue);
293  }
294 
295  void visit (jit_value &jvalue)
296  {
297  jvalue.accept (*this);
298  }
299 };
300 
301 // type inference and SSA construction on the low level Octave IR
302 class
303 jit_infer
304 {
305 public:
307 
308  jit_infer (jit_factory& afactory, jit_block_list& ablocks,
309  const variable_map& avmap);
310 
311  jit_block_list& get_blocks (void) const { return blocks; }
312 
313  jit_factory& get_factory (void) const { return factory; }
314 
315  void infer (void);
316 private:
319  const variable_map& vmap;
320  std::list<jit_instruction *> worklist;
321 
322  void append_users (jit_value *v);
323 
324  void append_users_term (jit_terminator *term);
325 
326  void construct_ssa (void);
327 
328  void do_construct_ssa (jit_block& block, size_t avisit_count);
329 
330  jit_block& entry_block (void) { return *blocks.front (); }
331 
332  jit_block& final_block (void) { return *blocks.back (); }
333 
334  void place_releases (void);
335 
336  void push_worklist (jit_instruction *instr);
337 
338  void remove_dead ();
339 
340  void release_dead_phi (jit_block& ablock);
341 
342  void release_temp (jit_block& ablock, std::set<jit_value *>& temp);
343 
344  void simplify_phi (void);
345 
346  void simplify_phi (jit_phi& phi);
347 };
348 
349 class
350 tree_jit
351 {
352 public:
353  ~tree_jit (void);
354 
355  static bool execute (tree_simple_for_command& cmd,
356  const octave_value& bounds);
357 
358  static bool execute (tree_while_command& cmd);
359 
360  static bool execute (octave_user_function& fcn, const octave_value_list& args,
361  octave_value_list& retval);
362 
363  llvm::ExecutionEngine *get_engine (void) const { return engine; }
364 
365  llvm::Module *get_module (void) const { return module; }
366 
367  void optimize (llvm::Function *fn);
368 private:
369  tree_jit (void);
370 
371  static tree_jit& instance (void);
372 
373  bool initialize (void);
374 
375  bool do_execute (tree_simple_for_command& cmd, const octave_value& bounds);
376 
377  bool do_execute (tree_while_command& cmd);
378 
379  bool do_execute (octave_user_function& fcn, const octave_value_list& args,
380  octave_value_list& retval);
381 
382  bool enabled (void);
383 
384  size_t trip_count (const octave_value& bounds) const;
385 
386  llvm::Module *module;
387  llvm::PassManager *module_pass_manager;
388  llvm::FunctionPassManager *pass_manager;
389  llvm::ExecutionEngine *engine;
390 };
391 
392 class
394 {
395 public:
397  const octave_value_list& ov_args);
398 
399  bool execute (const octave_value_list& ov_args,
400  octave_value_list& retval) const;
401 
402  bool match (const octave_value_list& ov_args) const;
403 private:
404  typedef octave_base_value *(*jited_function)(octave_base_value**);
405 
406  std::vector<jit_type *> argument_types;
407  jited_function function;
408 };
409 
410 class
411 jit_info
412 {
413 public:
414  // we use a pointer here so we don't have to include ov.h
415  typedef std::map<std::string, const octave_value *> vmap;
416 
417  jit_info (tree_jit& tjit, tree& tee);
418 
419  jit_info (tree_jit& tjit, tree& tee, const octave_value& for_bounds);
420 
421  ~jit_info (void);
422 
423  bool execute (const vmap& extra_vars = vmap ()) const;
424 
425  bool match (const vmap& extra_vars = vmap ()) const;
426 private:
429  typedef void (*jited_function)(octave_base_value**);
430 
431  void compile (tree_jit& tjit, tree& tee, jit_type *for_bounds = 0);
432 
433  octave_value find (const vmap& extra_vars, const std::string& vname) const;
434 
435  llvm::ExecutionEngine *engine;
436  jited_function function;
437  llvm::Function *llvm_function;
438 
439  std::vector<std::pair<std::string, bool> > arguments;
440  type_bound_vector bounds;
441 };
442 
443 #endif
444 #endif