GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
jit-ir.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_jit_ir_h)
27 #define octave_jit_ir_h 1
28 
29 #include "octave-config.h"
30 
31 #if defined (HAVE_LLVM)
32 
33 #include <list>
34 #include <stack>
35 #include <set>
36 
37 #include "jit-typeinfo.h"
38 
39 namespace octave
40 {
41 
42  // The low level octave JIT IR. This ir is close to llvm, but
43  // contains information for doing type inference. We convert the
44  // octave parse tree to this IR directly.
45 
46 #define JIT_VISIT_IR_NOTEMPLATE \
47  JIT_METH (block); \
48  JIT_METH (branch); \
49  JIT_METH (cond_branch); \
50  JIT_METH (call); \
51  JIT_METH (extract_argument); \
52  JIT_METH (store_argument); \
53  JIT_METH (return); \
54  JIT_METH (phi); \
55  JIT_METH (variable); \
56  JIT_METH (error_check); \
57  JIT_METH (assign) \
58  JIT_METH (argument) \
59  JIT_METH (magic_end)
60 
61 #define JIT_VISIT_IR_CONST \
62  JIT_METH (const_bool); \
63  JIT_METH (const_scalar); \
64  JIT_METH (const_complex); \
65  JIT_METH (const_index); \
66  JIT_METH (const_string); \
67  JIT_METH (const_range)
68 
69 #define JIT_VISIT_IR_CLASSES \
70  JIT_VISIT_IR_NOTEMPLATE \
71  JIT_VISIT_IR_CONST
72 
73  // forward declare all ir classes
74 #define JIT_METH(cname) \
75  class jit_ ## cname;
76 
78 
79 #undef JIT_METH
80 
81  // ABCs which aren't included in JIT_VISIT_IR_ALL
82  class jit_instruction;
83  class jit_terminator;
84 
85  template <typename T, jit_type *(*EXTRACT_T)(void), typename PASS_T = T,
86  bool QUOTE=false>
87  class jit_const;
88 
93 
94  typedef jit_const<std::string, jit_typeinfo::get_string,
95  const std::string&, true>
99 
100  class jit_ir_walker;
101  class jit_use;
102 
103  // Creates and tracks memory for jit_value and subclasses.
104  // Memory management is simple, all values that are created live as
105  // long as the factory.
106  class
108  {
109  typedef std::list<jit_value *> value_list;
110 
111  public:
112 
113  ~jit_factory (void);
114 
115  const value_list& constants (void) const { return m_constants; }
116 
117  template <typename T, typename ...Args>
118  T * create (const Args&... args)
119  {
120  T *ret = new T (args...);
121  track_value (ret);
122  return ret;
123  }
124 
125  private:
126 
127  void track_value (jit_value *v);
128 
130 
132  };
133 
134  // A list of basic blocks (jit_block) which form some body of code.
135  //
136  // We do not directly inherit from std::list because we need to update the
137  // blocks stashed location in push_back and insert.
138  class
140  {
141  public:
142 
143  typedef std::list<jit_block *>::iterator iterator;
144  typedef std::list<jit_block *>::const_iterator const_iterator;
145 
146  jit_block * back (void) const { return m_list.back (); }
147 
148  iterator begin (void) { return m_list.begin (); }
149 
150  const_iterator begin (void) const { return m_list.begin (); }
151 
152  iterator end (void) { return m_list.end (); }
153 
154  const_iterator end (void) const { return m_list.end (); }
155 
156  iterator erase (iterator iter) { return m_list.erase (iter); }
157 
158  jit_block * front (void) const { return m_list.front (); }
159 
160  void insert_after (iterator iter, jit_block *ablock);
161 
162  void insert_after (jit_block *loc, jit_block *ablock);
163 
164  void insert_before (iterator iter, jit_block *ablock);
165 
166  void insert_before (jit_block *loc, jit_block *ablock);
167 
168  void label (void);
169 
170  std::ostream& print (std::ostream& os, const std::string& header) const;
171 
172  std::ostream& print_dom (std::ostream& os) const;
173 
174  void push_back (jit_block *b);
175 
176  private:
177 
178  std::list<jit_block *> m_list;
179  };
180 
181  std::ostream& operator<<(std::ostream& os, const jit_block_list& blocks);
182 
183  class
185  {
186  public:
187 
188  jit_value (void)
189  : m_llvm_value (0), m_type (0), m_last_use (0), m_in_worklist (false)
190  { }
191 
192  virtual ~jit_value (void);
193 
194  bool in_worklist (void) const
195  {
196  return m_in_worklist;
197  }
198 
199  void stash_in_worklist (bool ain_worklist)
200  {
201  m_in_worklist = ain_worklist;
202  }
203 
204  // The block of the first use which is not a jit_error_check
205  // So this is not necessarily first_use ()->parent ().
206  jit_block * first_use_block (void);
207 
208  // replace all uses with
209  virtual void replace_with (jit_value *m_value);
210 
211  jit_type * type (void) const { return m_type; }
212 
213  llvm::Type * type_llvm (void) const
214  {
215  return m_type ? m_type->to_llvm () : nullptr;
216  }
217 
218  const std::string& type_name (void) const
219  {
220  return m_type->name ();
221  }
222 
223  void stash_type (jit_type *new_type) { m_type = new_type; }
224 
225  std::string print_string (void)
226  {
227  std::stringstream ss;
228  print (ss);
229  return ss.str ();
230  }
231 
232  jit_instruction * last_use (void) const { return m_last_use; }
233 
234  void stash_last_use (jit_instruction *alast_use)
235  {
236  m_last_use = alast_use;
237  }
238 
239  virtual bool needs_release (void) const { return false; }
240 
241  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const = 0;
242 
243  virtual std::ostream& short_print (std::ostream& os) const
244  { return print (os); }
245 
246  virtual void accept (jit_ir_walker& walker) = 0;
247 
248  bool has_llvm (void) const
249  {
250  return m_llvm_value;
251  }
252 
253  llvm::Value * to_llvm (void) const
254  {
255  assert (m_llvm_value);
256  return m_llvm_value;
257  }
258 
259  void stash_llvm (llvm::Value *compiled)
260  {
261  m_llvm_value = compiled;
262  }
263 
264  protected:
265 
266  std::ostream& print_indent (std::ostream& os, size_t indent = 0) const
267  {
268  for (size_t i = 0; i < indent * 8; ++i)
269  os << ' ';
270  return os;
271  }
272 
273  llvm::Value *m_llvm_value;
274 
275  private:
276 
280  };
281 
282  std::ostream& operator<< (std::ostream& os, const jit_value& value);
283  std::ostream& jit_print (std::ostream& os, jit_value *avalue);
284 
285  class
287  {
288  public:
289 
290  // some compilers don't allow us to use jit_internal_node without template
291  // parameters
293 
294  jit_use (void) : m_user (0), m_index (0) { }
295 
296  // we should really have a move operator, but not until c++11 :(
297  jit_use (const jit_use& use) : m_user (0), m_index (0)
298  {
299  *this = use;
300  }
301 
302  jit_use& operator= (const jit_use& use)
303  {
304  stash_value (use.value (), use.user (), use.index ());
305  return *this;
306  }
307 
308  size_t index (void) const { return m_index; }
309 
310  jit_instruction * user (void) const { return m_user; }
311 
312  jit_block * user_parent (void) const;
313 
314  std::list<jit_block *> user_parent_location (void) const;
315 
316  void stash_value (jit_value *avalue, jit_instruction *auser = nullptr,
317  size_t aindex = -1)
318  {
319  PARENT_T::stash_value (avalue);
320  m_index = aindex;
321  m_user = auser;
322  }
323 
324  private:
325 
327  size_t m_index;
328  };
329 
330  class
331  jit_instruction : public jit_value
332  {
333  public:
334 
335  // FIXME: this code could be so much pretier with varadic templates...
337  : m_id (next_id ()), m_parent (0)
338  { }
339 
340  jit_instruction (size_t nargs)
341  : m_id (next_id ()), m_parent (0)
342  {
343  m_already_infered.reserve (nargs);
344  m_arguments.reserve (nargs);
345  }
346 
347  template <typename ...Args>
348  jit_instruction (jit_value * arg1, Args... other_args)
349  : m_already_infered (1 + sizeof... (other_args)),
350  m_arguments (1 + sizeof... (other_args)),
351  m_id (next_id ()), m_parent (nullptr)
352  {
353  stash_argument (0, arg1, other_args...);
354  }
355 
356  jit_instruction (const std::vector<jit_value *>& aarguments)
357  : m_already_infered (aarguments.size ()), m_arguments (aarguments.size ()),
358  m_id (next_id ()), m_parent (0)
359  {
360  for (size_t i = 0; i < aarguments.size (); ++i)
361  stash_argument (i, aarguments[i]);
362  }
363 
364  static void reset_ids (void)
365  {
366  next_id (true);
367  }
368 
369  jit_value * argument (size_t i) const
370  {
371  return m_arguments[i].value ();
372  }
373 
374  llvm::Value * argument_llvm (size_t i) const
375  {
376  assert (argument (i));
377  return argument (i)->to_llvm ();
378  }
379 
380  jit_type * argument_type (size_t i) const
381  {
382  return argument (i)->type ();
383  }
384 
385  llvm::Type * argument_type_llvm (size_t i) const
386  {
387  assert (argument (i));
388  return argument_type (i)->to_llvm ();
389  }
390 
391  std::ostream& print_argument (std::ostream& os, size_t i) const
392  {
393  if (argument (i))
394  return argument (i)->short_print (os);
395  else
396  return os << "NULL";
397  }
398 
399  void stash_argument (size_t i, jit_value * arg)
400  {
401  m_arguments[i].stash_value (arg, this, i);
402  }
403 
404  template <typename ...Args>
405  void stash_argument (size_t i, jit_value * arg1, Args... aargs)
406  {
407  m_arguments[i].stash_value (arg1, this, i);
408  stash_argument (++i, aargs...);
409  }
410 
412  {
413  m_arguments.push_back (jit_use ());
414  stash_argument (m_arguments.size () - 1, arg);
415  m_already_infered.push_back (0);
416  }
417 
418  size_t argument_count (void) const
419  {
420  return m_arguments.size ();
421  }
422 
423  void resize_arguments (size_t acount, jit_value *adefault = nullptr)
424  {
425  size_t old = m_arguments.size ();
426  m_arguments.resize (acount);
427  m_already_infered.resize (acount);
428 
429  if (adefault)
430  for (size_t i = old; i < acount; ++i)
431  stash_argument (i, adefault);
432  }
433 
434  const std::vector<jit_use>& arguments (void) const { return m_arguments; }
435 
436  // argument types which have been infered already
437  const std::vector<jit_type *>& argument_types (void) const
438  { return m_already_infered; }
439 
440  virtual void push_variable (void) { }
441 
442  virtual void pop_variable (void) { }
443 
444  virtual void construct_ssa (void)
445  {
446  do_construct_ssa (0, argument_count ());
447  }
448 
449  virtual bool infer (void) { return false; }
450 
451  void remove (void);
452 
453  virtual std::ostream& short_print (std::ostream& os) const;
454 
455  jit_block * parent (void) const { return m_parent; }
456 
457  std::list<jit_instruction *>::iterator location (void) const
458  {
459  return m_location;
460  }
461 
462  llvm::BasicBlock * parent_llvm (void) const;
463 
464  void stash_parent (jit_block *aparent,
465  std::list<jit_instruction *>::iterator alocation)
466  {
467  m_parent = aparent;
468  m_location = alocation;
469  }
470 
471  size_t id (void) const { return m_id; }
472 
473  protected:
474 
475  // Do SSA replacement on arguments in [start, end)
476  void do_construct_ssa (size_t start, size_t end);
477 
478  std::vector<jit_type *> m_already_infered;
479 
480  private:
481 
482  static size_t next_id (bool reset = false)
483  {
484  static size_t ret = 0;
485  if (reset)
486  return ret = 0;
487 
488  return ret++;
489  }
490 
491  std::vector<jit_use> m_arguments;
492 
493  size_t m_id;
495  std::list<jit_instruction *>::iterator m_location;
496  };
497 
498  // defnie accept methods for subclasses
499 #define JIT_VALUE_ACCEPT \
500  virtual void accept (jit_ir_walker& walker);
501 
502  // for use as a dummy argument during conversion to LLVM
503  class
504  jit_argument : public jit_value
505  {
506  public:
507 
508  jit_argument (jit_type *atype, llvm::Value *avalue)
509  {
510  stash_type (atype);
511  stash_llvm (avalue);
512  }
513 
514  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
515  {
516  print_indent (os, indent);
517  return jit_print (os, type ()) << ": DUMMY";
518  }
519 
521  };
522 
523  template <typename T, jit_type *(*EXTRACT_T)(void), typename PASS_T, bool QUOTE>
524  class
525  jit_const : public jit_value
526  {
527  public:
528 
529  typedef PASS_T pass_t;
530 
531  jit_const (PASS_T avalue) : m_value (avalue)
532  {
533  stash_type (EXTRACT_T ());
534  }
535 
536  PASS_T value (void) const { return m_value; }
537 
538  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
539  {
540  print_indent (os, indent);
541  jit_print (os, type ()) << ": ";
542  if (QUOTE)
543  os << '"';
544  os << m_value;
545  if (QUOTE)
546  os << '"';
547  return os;
548  }
549 
551 
552  private:
553 
555  };
556 
557  class jit_phi_incoming;
558 
559  class
562  {
564 
565  public:
566 
567  typedef std::list<jit_instruction *> instruction_list;
568  typedef instruction_list::iterator iterator;
569  typedef instruction_list::const_iterator const_iterator;
570 
571  typedef std::set<jit_block *> df_set;
572  typedef df_set::const_iterator df_iterator;
573 
574  static const size_t NO_ID = static_cast<size_t> (-1);
575 
576  jit_block (const std::string& aname, size_t avisit_count = 0)
577  : m_visit_count (avisit_count), m_id (NO_ID), m_idom (0), m_name (aname),
578  m_alive (false)
579  { }
580 
581  virtual void replace_with (jit_value *value);
582 
583  void replace_in_phi (jit_block *ablock, jit_block *with);
584 
585  // we have a new internal list, but we want to stay compatible with jit_value
586  jit_use * first_use (void) const { return jit_value::first_use (); }
587 
588  size_t use_count (void) const { return jit_value::use_count (); }
589 
590  // if a block is alive, then it might be visited during execution
591  bool alive (void) const { return m_alive; }
592 
593  void mark_alive (void) { m_alive = true; }
594 
595  // If we can merge with a successor, do so and return the now empty block
596  jit_block * maybe_merge ();
597 
598  // merge another block into this block, leaving the merge block empty
599  void merge (jit_block& merge);
600 
601  const std::string& name (void) const { return m_name; }
602 
603  jit_instruction * prepend (jit_instruction *instr);
604 
605  jit_instruction * prepend_after_phi (jit_instruction *instr);
606 
607  template <typename T>
608  T * append (T *instr)
609  {
610  internal_append (instr);
611  return instr;
612  }
613 
614  jit_instruction * insert_before (iterator loc, jit_instruction *instr);
615 
617  {
618  return insert_before (loc->location (), instr);
619  }
620 
621  jit_instruction * insert_after (iterator loc, jit_instruction *instr);
622 
624  {
625  return insert_after (loc->location (), instr);
626  }
627 
629  {
630  jit_instruction *instr = *iter;
631  iter = m_instructions.erase (iter);
632  instr->stash_parent (0, m_instructions.end ());
633  return iter;
634  }
635 
636  jit_terminator * terminator (void) const;
637 
638  // is the jump from pred alive?
639  bool branch_alive (jit_block *asucc) const;
640 
641  jit_block * successor (size_t i) const;
642 
643  size_t successor_count (void) const;
644 
645  iterator begin (void) { return m_instructions.begin (); }
646 
647  const_iterator begin (void) const { return m_instructions.begin (); }
648 
649  iterator end (void) { return m_instructions.end (); }
650 
651  const_iterator end (void) const { return m_instructions.end (); }
652 
654 
656 
658 
659  // must label before id is valid
660  size_t id (void) const { return m_id; }
661 
662  // dominance frontier
663  const df_set& df (void) const { return m_df; }
664 
665  df_iterator df_begin (void) const { return m_df.begin (); }
666 
667  df_iterator df_end (void) const { return m_df.end (); }
668 
669  // label with a RPO walk
670  void label (void)
671  {
672  size_t number = 0;
673  label (m_visit_count, number);
674  }
675 
676  void label (size_t avisit_count, size_t& number);
677 
678  // See for idom computation algorithm
679  // Cooper, Keith D.; Harvey, Timothy J; and Kennedy, Ken (2001).
680  // "A Simple, Fast Dominance Algorithm"
681  void compute_idom (jit_block& entry_block)
682  {
683  bool changed;
684  entry_block.m_idom = &entry_block;
685  do
686  changed = update_idom (m_visit_count);
687  while (changed);
688  }
689 
690  // compute dominance frontier
691  void compute_df (void)
692  {
693  compute_df (m_visit_count);
694  }
695 
696  void create_dom_tree (void)
697  {
698  create_dom_tree (m_visit_count);
699  }
700 
701  jit_block * dom_successor (size_t idx) const
702  {
703  return m_dom_succ[idx];
704  }
705 
706  size_t dom_successor_count (void) const
707  {
708  return m_dom_succ.size ();
709  }
710 
711  // call pop_variable on all instructions
712  void pop_all (void);
713 
714  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const;
715 
716  jit_block * maybe_split (jit_factory& factory, jit_block_list& blocks,
717  jit_block *asuccessor);
718 
720  jit_block& asuccessor)
721  {
722  return maybe_split (factory, blocks, &asuccessor);
723  }
724 
725  // print dominator infomration
726  std::ostream& print_dom (std::ostream& os) const;
727 
728  virtual std::ostream& short_print (std::ostream& os) const
729  {
730  os << m_name;
731  if (m_id != NO_ID)
732  os << m_id;
733  else
734  os << '!';
735  return os;
736  }
737 
738  llvm::BasicBlock * to_llvm (void) const;
739 
740  std::list<jit_block *>::iterator location (void) const
741  { return m_location; }
742 
743  void stash_location (std::list<jit_block *>::iterator alocation)
744  { m_location = alocation; }
745 
746  // used to prevent visiting the same node twice in the graph
747  size_t visit_count (void) const { return m_visit_count; }
748 
749  // check if this node has been visited yet at the given visit count.
750  // If we have not been visited yet, mark us as visited.
751  bool visited (size_t avisit_count)
752  {
753  if (m_visit_count <= avisit_count)
754  {
755  m_visit_count = avisit_count + 1;
756  return false;
757  }
758 
759  return true;
760  }
761 
762  jit_instruction * front (void) { return m_instructions.front (); }
763 
764  jit_instruction * back (void) { return m_instructions.back (); }
765 
767 
768  private:
769 
770  void internal_append (jit_instruction *instr);
771 
772  void compute_df (size_t avisit_count);
773 
774  bool update_idom (size_t avisit_count);
775 
776  void create_dom_tree (size_t avisit_count);
777 
778  static jit_block * idom_intersect (jit_block *i, jit_block *j);
779 
781  size_t m_id;
784  std::vector<jit_block *> m_dom_succ;
785  std::string m_name;
787  bool m_alive;
788  std::list<jit_block *>::iterator m_location;
789  };
790 
791  // keeps track of phi functions that use a block on incoming edges
792  class
794  {
795  public:
796 
797  jit_phi_incoming (void) : m_user (0) { }
798 
799  jit_phi_incoming (jit_phi *auser) : m_user (auser) { }
800 
802  {
803  *this = use;
804  }
805 
806  jit_phi_incoming& operator= (const jit_phi_incoming& use)
807  {
808  stash_value (use.value ());
809  m_user = use.m_user;
810  return *this;
811  }
812 
813  jit_phi * user (void) const { return m_user; }
814 
815  jit_block * user_parent (void) const;
816 
817  private:
818 
820  };
821 
822  // A non-ssa variable
823  class
824  jit_variable : public jit_value
825  {
826  public:
827 
828  jit_variable (const std::string& aname) : m_name (aname), m_last_use (0) { }
829 
830  const std::string& name (void) const { return m_name; }
831 
832  // manipulate the value_stack, for use during SSA construction. The top of
833  // the value stack represents the current value for this variable
834  bool has_top (void) const
835  {
836  return ! value_stack.empty ();
837  }
838 
839  jit_value * top (void) const
840  {
841  return value_stack.top ();
842  }
843 
845  {
846  value_stack.push (v);
847  m_last_use = v;
848  }
849 
850  void pop (void)
851  {
852  value_stack.pop ();
853  }
854 
855  jit_instruction * last_use (void) const
856  {
857  return m_last_use;
858  }
859 
861  {
862  m_last_use = instr;
863  }
864 
865  // blocks in which we are used
867  {
868  jit_use *use = first_use ();
869  while (use)
870  {
871  result.insert (use->user_parent ());
872  use = use->next ();
873  }
874  }
875 
876  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
877  {
878  return print_indent (os, indent) << m_name;
879  }
880 
882 
883  private:
884 
885  std::string m_name;
886  std::stack<jit_value *> value_stack;
888  };
889 
890  class
892  {
893  public:
894 
896  : jit_instruction (), m_dest (adest)
897  { }
898 
899  jit_assign_base (jit_variable *adest, size_t npred)
900  : jit_instruction (npred), m_dest (adest)
901  { }
902 
904  : jit_instruction (arg0, arg1), m_dest (adest)
905  { }
906 
907  jit_variable * dest (void) const { return m_dest; }
908 
909  virtual void push_variable (void)
910  {
911  m_dest->push (this);
912  }
913 
914  virtual void pop_variable (void)
915  {
916  m_dest->pop ();
917  }
918 
919  virtual std::ostream& short_print (std::ostream& os) const
920  {
921  if (type ())
922  jit_print (os, type ()) << ": ";
923 
924  dest ()->short_print (os);
925  return os << '#' << id ();
926  }
927 
928  private:
929 
931  };
932 
933  class
934  jit_assign : public jit_assign_base
935  {
936  public:
937 
939  : jit_assign_base (adest, adest, asrc), m_artificial (false)
940  { }
941 
942  jit_value * overwrite (void) const
943  {
944  return argument (0);
945  }
946 
947  jit_value * src (void) const
948  {
949  return argument (1);
950  }
951 
952  // Variables don't get modified in an SSA, but COW requires we
953  // modify variables. An artificial assign is for when a variable
954  // gets modified. We need an assign in the SSA, but the reference
955  // counts shouldn't be updated.
956 
957  bool artificial (void) const { return m_artificial; }
958 
959  void mark_artificial (void) { m_artificial = true; }
960 
961  virtual bool infer (void)
962  {
963  jit_type *stype = src ()->type ();
964  if (stype != type())
965  {
966  stash_type (stype);
967  return true;
968  }
969 
970  return false;
971  }
972 
973  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
974  {
975  print_indent (os, indent) << *this << " = " << *src ();
976 
977  if (artificial ())
978  os << " [artificial]";
979 
980  return os;
981  }
982 
984 
985  private:
986 
988  };
989 
990  class
991  jit_phi : public jit_assign_base
992  {
993  public:
994 
995  jit_phi (jit_variable *adest, size_t npred)
996  : jit_assign_base (adest, npred)
997  {
998  m_incoming.reserve (npred);
999  }
1000 
1001  // removes arguments form dead incoming jumps
1002  bool prune (void);
1003 
1004  void add_incoming (jit_block *from, jit_value *value)
1005  {
1006  push_argument (value);
1007  m_incoming.push_back (jit_phi_incoming (this));
1008  m_incoming[m_incoming.size () - 1].stash_value (from);
1009  }
1010 
1011  jit_block * incoming (size_t i) const
1012  {
1013  return m_incoming[i].value ();
1014  }
1015 
1016  llvm::BasicBlock * incoming_llvm (size_t i) const
1017  {
1018  return incoming (i)->to_llvm ();
1019  }
1020 
1021  virtual void construct_ssa (void) { }
1022 
1023  virtual bool infer (void);
1024 
1025  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
1026  {
1027  std::stringstream ss;
1028  print_indent (ss, indent);
1029  short_print (ss) << " phi ";
1030  std::string ss_str = ss.str ();
1031  std::string indent_str (ss_str.size (), ' ');
1032  os << ss_str;
1033 
1034  for (size_t i = 0; i < argument_count (); ++i)
1035  {
1036  if (i > 0)
1037  os << indent_str;
1038  os << "| ";
1039 
1040  os << *incoming (i) << " -> ";
1041  os << *argument (i);
1042 
1043  if (i + 1 < argument_count ())
1044  os << std::endl;
1045  }
1046 
1047  return os;
1048  }
1049 
1050  llvm::PHINode * to_llvm (void) const;
1051 
1053 
1054  private:
1055 
1056  std::vector<jit_phi_incoming> m_incoming;
1057  };
1058 
1059  class
1061  {
1062  public:
1063 
1064  template <typename ...Args>
1065  jit_terminator (size_t asuccessor_count, Args... args)
1066  : jit_instruction (args...),
1067  m_alive (asuccessor_count, false) { }
1068 
1069  jit_block * successor (size_t idx = 0) const
1070  {
1071  return static_cast<jit_block *> (argument (idx));
1072  }
1073 
1074  llvm::BasicBlock * successor_llvm (size_t idx = 0) const
1075  {
1076  return successor (idx)->to_llvm ();
1077  }
1078 
1079  size_t successor_index (const jit_block *asuccessor) const;
1080 
1081  std::ostream& print_successor (std::ostream& os, size_t idx = 0) const
1082  {
1083  if (alive (idx))
1084  os << "[live] ";
1085  else
1086  os << "[dead] ";
1087 
1088  return successor (idx)->short_print (os);
1089  }
1090 
1091  // Check if the jump to successor is live
1092  bool alive (const jit_block *asuccessor) const
1093  {
1094  return alive (successor_index (asuccessor));
1095  }
1096 
1097  bool alive (size_t idx) const { return m_alive[idx]; }
1098 
1099  bool alive (int idx) const { return m_alive[idx]; }
1100 
1101  size_t successor_count (void) const { return m_alive.size (); }
1102 
1103  virtual bool infer (void);
1104 
1105  llvm::TerminatorInst * to_llvm (void) const;
1106 
1107  protected:
1108 
1109  virtual bool check_alive (size_t) const { return true; }
1110 
1111  private:
1112 
1113  std::vector<bool> m_alive;
1114  };
1115 
1116  class
1117  jit_branch : public jit_terminator
1118  {
1119  public:
1120 
1121  jit_branch (jit_block *succ) : jit_terminator (1, succ) { }
1122 
1123  virtual size_t successor_count (void) const { return 1; }
1124 
1125  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
1126  {
1127  print_indent (os, indent) << "branch: ";
1128  return print_successor (os);
1129  }
1130 
1132  };
1133 
1134  class
1136  {
1137  public:
1138 
1140  : jit_terminator (2, ctrue, cfalse, c) { }
1141 
1142  jit_value * cond (void) const { return argument (2); }
1143 
1144  std::ostream& print_cond (std::ostream& os) const
1145  {
1146  return cond ()->short_print (os);
1147  }
1148 
1149  llvm::Value * cond_llvm (void) const
1150  {
1151  return cond ()->to_llvm ();
1152  }
1153 
1154  virtual size_t successor_count (void) const { return 2; }
1155 
1156  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
1157  {
1158  print_indent (os, indent) << "cond_branch: ";
1159  print_cond (os) << ", ";
1160  print_successor (os, 0) << ", ";
1161  return print_successor (os, 1);
1162  }
1163 
1165  };
1166 
1167  class
1168  jit_call : public jit_instruction
1169  {
1170  public:
1171 
1172  jit_call (const jit_operation& (*aoperation) (void))
1173  : m_operation (aoperation ())
1174  {
1175  const jit_function& ol = overload ();
1176  if (ol.valid ())
1177  stash_type (ol.result ());
1178  }
1179 
1180  jit_call (const jit_operation& aoperation) : m_operation (aoperation)
1181  {
1182  const jit_function& ol = overload ();
1183  if (ol.valid ())
1184  stash_type (ol.result ());
1185  }
1186 
1187  template <typename ...Args>
1188  jit_call (const jit_operation& aoperation,
1189  jit_value * arg1, Args... other_args)
1190  : jit_instruction (arg1, other_args...), m_operation (aoperation)
1191  { }
1192 
1193  template <typename ...Args>
1194  jit_call (const jit_operation& (*aoperation) (void),
1195  jit_value * arg1, Args... other_args)
1196  : jit_instruction (arg1, other_args...), m_operation (aoperation ())
1197  { }
1198 
1199  jit_call (const jit_operation& aoperation,
1200  const std::vector<jit_value *>& args)
1201  : jit_instruction (args), m_operation (aoperation)
1202  { }
1203 
1204  const jit_operation& operation (void) const { return m_operation; }
1205 
1206  bool can_error (void) const
1207  {
1208  return overload ().can_error ();
1209  }
1210 
1211  const jit_function& overload (void) const
1212  {
1213  return m_operation.overload (argument_types ());
1214  }
1215 
1216  virtual bool needs_release (void) const;
1217 
1218  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
1219  {
1220  print_indent (os, indent);
1221 
1222  if (use_count ())
1223  short_print (os) << " = ";
1224  os << "call " << m_operation.name () << " (";
1225 
1226  for (size_t i = 0; i < argument_count (); ++i)
1227  {
1228  print_argument (os, i);
1229  if (i + 1 < argument_count ())
1230  os << ", ";
1231  }
1232  return os << ')';
1233  }
1234 
1235  virtual bool infer (void);
1236 
1238 
1239  private:
1240 
1242  };
1243 
1244  // FIXME: This is just ugly...
1245  // checks error_state, if error_state is false then goto the normal branch,
1246  // otherwise goto the error branch
1247  class
1249  {
1250  public:
1251 
1252  // Which variable is the error check for?
1254  {
1256  var_interrupt
1257  };
1258 
1259  static std::string variable_to_string (variable v);
1260 
1261  jit_error_check (variable var, jit_call *acheck_for, jit_block *normal,
1262  jit_block *error)
1263  : jit_terminator (2, error, normal, acheck_for), m_variable (var) { }
1264 
1266  : jit_terminator (2, error, normal), m_variable (var) { }
1267 
1268  variable check_variable (void) const { return m_variable; }
1269 
1270  bool has_check_for (void) const
1271  {
1272  return argument_count () == 3;
1273  }
1274 
1275  jit_call * check_for (void) const
1276  {
1277  assert (has_check_for ());
1278  return static_cast<jit_call *> (argument (2));
1279  }
1280 
1281  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const;
1282 
1284 
1285  protected:
1286 
1287  virtual bool check_alive (size_t idx) const
1288  {
1289  if (! has_check_for ())
1290  return true;
1291  return idx == 1 ? true : check_for ()->can_error ();
1292  }
1293 
1294  private:
1295 
1297  };
1298 
1299  // for now only handles the 1D case
1300  class
1302  {
1303  public:
1304 
1305  class
1306  context
1307  {
1308  public:
1309 
1310  context (void) : m_value (0), m_index (0), m_count (0) { }
1311 
1312  context (jit_factory& factory, jit_value *avalue, size_t aindex,
1313  size_t acount);
1314 
1318  };
1319 
1320  jit_magic_end (const std::vector<context>& full_context);
1321 
1322  virtual bool infer (void);
1323 
1324  const jit_function& overload () const;
1325 
1326  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const;
1327 
1328  context resolve_context (void) const;
1329 
1330  virtual std::ostream& short_print (std::ostream& os) const
1331  {
1332  return os << "magic_end" << '#' << id ();
1333  }
1334 
1336 
1337  private:
1338 
1339  std::vector<context> m_contexts;
1340  };
1341 
1342  class
1344  {
1345  public:
1346 
1348  : jit_assign_base (adest)
1349  {
1350  stash_type (atype);
1351  }
1352 
1353  const std::string& name (void) const
1354  {
1355  return dest ()->name ();
1356  }
1357 
1358  const jit_function& overload (void) const
1359  {
1361  }
1362 
1363  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
1364  {
1365  print_indent (os, indent);
1366 
1367  return short_print (os) << " = extract " << name ();
1368  }
1369 
1371  };
1372 
1373  class
1375  {
1376  public:
1377 
1379  : jit_instruction (var), m_dest (var)
1380  { }
1381 
1382  const std::string& name (void) const
1383  {
1384  return m_dest->name ();
1385  }
1386 
1387  const jit_function& overload (void) const
1388  {
1389  return jit_typeinfo::cast (jit_typeinfo::get_any (), result_type ());
1390  }
1391 
1392  jit_value * result (void) const
1393  {
1394  return argument (0);
1395  }
1396 
1397  jit_type * result_type (void) const
1398  {
1399  return result ()->type ();
1400  }
1401 
1402  llvm::Value * result_llvm (void) const
1403  {
1404  return result ()->to_llvm ();
1405  }
1406 
1407  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
1408  {
1409  jit_value *res = result ();
1410  print_indent (os, indent) << "store ";
1411  m_dest->short_print (os);
1412 
1413  if (! isa<jit_variable> (res))
1414  {
1415  os << " = ";
1416  res->short_print (os);
1417  }
1418 
1419  return os;
1420  }
1421 
1423 
1424  private:
1425 
1427  };
1428 
1429  class
1430  jit_return : public jit_instruction
1431  {
1432  public:
1433 
1434  jit_return (void) { }
1435 
1437 
1438  jit_value * result (void) const
1439  {
1440  return argument_count () ? argument (0) : nullptr;
1441  }
1442 
1443  jit_type * result_type (void) const
1444  {
1445  jit_value *res = result ();
1446  return res ? res->type () : nullptr;
1447  }
1448 
1449  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
1450  {
1451  print_indent (os, indent) << "return";
1452 
1453  if (result ())
1454  os << ' ' << *result ();
1455 
1456  return os;
1457  }
1458 
1460  };
1461 
1462  class
1464  {
1465  public:
1466 
1467  virtual ~jit_ir_walker (void) { }
1468 
1469 #define JIT_METH(clname) \
1470  virtual void visit (jit_ ## clname&) = 0;
1471 
1473 
1474 #undef JIT_METH
1475  };
1476 
1477  template <typename T, jit_type *(*EXTRACT_T)(void), typename PASS_T, bool QUOTE>
1478  void
1480  {
1481  walker.visit (*this);
1482  }
1483 
1484 #undef JIT_VALUE_ACCEPT
1485 }
1486 
1487 #endif
1488 
1489 #endif
#define loc(X, Y)
Definition: Screen.cpp:56
jit_argument(jit_type *atype, llvm::Value *avalue)
Definition: jit-ir.h:508
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:514
jit_variable * dest(void) const
Definition: jit-ir.h:907
jit_variable * m_dest
Definition: jit-ir.h:930
virtual void pop_variable(void)
Definition: jit-ir.h:914
virtual void push_variable(void)
Definition: jit-ir.h:909
jit_assign_base(jit_variable *adest)
Definition: jit-ir.h:895
virtual std::ostream & short_print(std::ostream &os) const
Definition: jit-ir.h:919
jit_assign_base(jit_variable *adest, size_t npred)
Definition: jit-ir.h:899
jit_assign_base(jit_variable *adest, jit_value *arg0, jit_value *arg1)
Definition: jit-ir.h:903
jit_value * src(void) const
Definition: jit-ir.h:947
void mark_artificial(void)
Definition: jit-ir.h:959
jit_value * overwrite(void) const
Definition: jit-ir.h:942
virtual bool infer(void)
Definition: jit-ir.h:961
bool artificial(void) const
Definition: jit-ir.h:957
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:973
jit_assign(jit_variable *adest, jit_value *asrc)
Definition: jit-ir.h:938
iterator erase(iterator iter)
Definition: jit-ir.h:156
jit_block * front(void) const
Definition: jit-ir.h:158
const_iterator end(void) const
Definition: jit-ir.h:154
iterator end(void)
Definition: jit-ir.h:152
std::list< jit_block * >::const_iterator const_iterator
Definition: jit-ir.h:144
jit_block * back(void) const
Definition: jit-ir.h:146
std::list< jit_block * > m_list
Definition: jit-ir.h:178
iterator begin(void)
Definition: jit-ir.h:148
std::list< jit_block * >::iterator iterator
Definition: jit-ir.h:143
const_iterator begin(void) const
Definition: jit-ir.h:150
jit_block * m_idom
Definition: jit-ir.h:782
T * append(T *instr)
Definition: jit-ir.h:608
void create_dom_tree(void)
Definition: jit-ir.h:696
instruction_list::const_iterator const_iterator
Definition: jit-ir.h:569
iterator phi_begin(void)
iterator nonphi_begin(void)
jit_instruction * back(void)
Definition: jit-ir.h:764
jit_instruction * insert_after(jit_instruction *loc, jit_instruction *instr)
Definition: jit-ir.h:623
instruction_list m_instructions
Definition: jit-ir.h:786
df_set::const_iterator df_iterator
Definition: jit-ir.h:572
size_t id(void) const
Definition: jit-ir.h:660
size_t dom_successor_count(void) const
Definition: jit-ir.h:706
jit_block * maybe_split(jit_factory &factory, jit_block_list &blocks, jit_block &asuccessor)
Definition: jit-ir.h:719
instruction_list::iterator iterator
Definition: jit-ir.h:568
const df_set & df(void) const
Definition: jit-ir.h:663
std::string m_name
Definition: jit-ir.h:785
iterator remove(iterator iter)
Definition: jit-ir.h:628
const_iterator begin(void) const
Definition: jit-ir.h:647
size_t visit_count(void) const
Definition: jit-ir.h:747
virtual std::ostream & short_print(std::ostream &os) const
Definition: jit-ir.h:728
iterator end(void)
Definition: jit-ir.h:649
void label(void)
Definition: jit-ir.h:670
std::list< jit_instruction * > instruction_list
Definition: jit-ir.h:567
bool visited(size_t avisit_count)
Definition: jit-ir.h:751
bool alive(void) const
Definition: jit-ir.h:591
jit_instruction * insert_before(jit_instruction *loc, jit_instruction *instr)
Definition: jit-ir.h:616
std::set< jit_block * > df_set
Definition: jit-ir.h:571
jit_internal_list< jit_block, jit_phi_incoming > ILIST_T
Definition: jit-ir.h:563
iterator begin(void)
Definition: jit-ir.h:645
iterator phi_end(void)
void stash_location(std::list< jit_block * >::iterator alocation)
Definition: jit-ir.h:743
df_iterator df_begin(void) const
Definition: jit-ir.h:665
void compute_idom(jit_block &entry_block)
Definition: jit-ir.h:681
size_t m_visit_count
Definition: jit-ir.h:780
std::list< jit_block * >::iterator m_location
Definition: jit-ir.h:788
const std::string & name(void) const
Definition: jit-ir.h:601
jit_use * first_use(void) const
Definition: jit-ir.h:586
size_t use_count(void) const
Definition: jit-ir.h:588
jit_instruction * front(void)
Definition: jit-ir.h:762
jit_block * dom_successor(size_t idx) const
Definition: jit-ir.h:701
jit_block(const std::string &aname, size_t avisit_count=0)
Definition: jit-ir.h:576
std::vector< jit_block * > m_dom_succ
Definition: jit-ir.h:784
df_iterator df_end(void) const
Definition: jit-ir.h:667
void mark_alive(void)
Definition: jit-ir.h:593
const_iterator end(void) const
Definition: jit-ir.h:651
std::list< jit_block * >::iterator location(void) const
Definition: jit-ir.h:740
void compute_df(void)
Definition: jit-ir.h:691
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:1125
jit_branch(jit_block *succ)
Definition: jit-ir.h:1121
virtual size_t successor_count(void) const
Definition: jit-ir.h:1123
jit_call(const jit_operation &aoperation)
Definition: jit-ir.h:1180
jit_call(const jit_operation &aoperation, jit_value *arg1, Args... other_args)
Definition: jit-ir.h:1188
const jit_function & overload(void) const
Definition: jit-ir.h:1211
jit_call(const jit_operation &(*aoperation)(void), jit_value *arg1, Args... other_args)
Definition: jit-ir.h:1194
jit_call(const jit_operation &(*aoperation)(void))
Definition: jit-ir.h:1172
bool can_error(void) const
Definition: jit-ir.h:1206
const jit_operation & m_operation
Definition: jit-ir.h:1237
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:1218
const jit_operation & operation(void) const
Definition: jit-ir.h:1204
jit_call(const jit_operation &aoperation, const std::vector< jit_value * > &args)
Definition: jit-ir.h:1199
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:1156
jit_value * cond(void) const
Definition: jit-ir.h:1142
std::ostream & print_cond(std::ostream &os) const
Definition: jit-ir.h:1144
jit_cond_branch(jit_value *c, jit_block *ctrue, jit_block *cfalse)
Definition: jit-ir.h:1139
llvm::Value * cond_llvm(void) const
Definition: jit-ir.h:1149
virtual size_t successor_count(void) const
Definition: jit-ir.h:1154
jit_const(PASS_T avalue)
Definition: jit-ir.h:531
PASS_T value(void) const
Definition: jit-ir.h:536
PASS_T pass_t
Definition: jit-ir.h:529
virtual void accept(jit_ir_walker &walker)
Definition: jit-ir.h:1479
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:538
virtual bool check_alive(size_t idx) const
Definition: jit-ir.h:1287
jit_error_check(variable var, jit_block *normal, jit_block *error)
Definition: jit-ir.h:1265
variable check_variable(void) const
Definition: jit-ir.h:1268
bool has_check_for(void) const
Definition: jit-ir.h:1270
jit_error_check(variable var, jit_call *acheck_for, jit_block *normal, jit_block *error)
Definition: jit-ir.h:1261
jit_call * check_for(void) const
Definition: jit-ir.h:1275
const std::string & name(void) const
Definition: jit-ir.h:1353
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:1363
jit_extract_argument(jit_type *atype, jit_variable *adest)
Definition: jit-ir.h:1347
const jit_function & overload(void) const
Definition: jit-ir.h:1358
value_list m_constants
Definition: jit-ir.h:131
const value_list & constants(void) const
Definition: jit-ir.h:115
value_list m_all_values
Definition: jit-ir.h:129
T * create(const Args &... args)
Definition: jit-ir.h:118
std::list< jit_value * > value_list
Definition: jit-ir.h:109
bool valid(void) const
Definition: jit-typeinfo.h:262
jit_type * result(void) const
Definition: jit-typeinfo.h:327
void stash_parent(jit_block *aparent, std::list< jit_instruction * >::iterator alocation)
Definition: jit-ir.h:464
jit_type * argument_type(size_t i) const
Definition: jit-ir.h:380
llvm::Value * argument_llvm(size_t i) const
Definition: jit-ir.h:374
jit_block * m_parent
Definition: jit-ir.h:494
const std::vector< jit_use > & arguments(void) const
Definition: jit-ir.h:434
jit_instruction(size_t nargs)
Definition: jit-ir.h:340
jit_instruction(jit_value *arg1, Args... other_args)
Definition: jit-ir.h:348
virtual void push_variable(void)
Definition: jit-ir.h:440
llvm::Type * argument_type_llvm(size_t i) const
Definition: jit-ir.h:385
void stash_argument(size_t i, jit_value *arg)
Definition: jit-ir.h:399
std::ostream & print_argument(std::ostream &os, size_t i) const
Definition: jit-ir.h:391
void resize_arguments(size_t acount, jit_value *adefault=nullptr)
Definition: jit-ir.h:423
std::vector< jit_type * > m_already_infered
Definition: jit-ir.h:478
std::list< jit_instruction * >::iterator m_location
Definition: jit-ir.h:495
size_t argument_count(void) const
Definition: jit-ir.h:418
std::list< jit_instruction * >::iterator location(void) const
Definition: jit-ir.h:457
size_t id(void) const
Definition: jit-ir.h:471
void stash_argument(size_t i, jit_value *arg1, Args... aargs)
Definition: jit-ir.h:405
std::vector< jit_use > m_arguments
Definition: jit-ir.h:491
const std::vector< jit_type * > & argument_types(void) const
Definition: jit-ir.h:437
jit_block * parent(void) const
Definition: jit-ir.h:455
virtual bool infer(void)
Definition: jit-ir.h:449
virtual void pop_variable(void)
Definition: jit-ir.h:442
void push_argument(jit_value *arg)
Definition: jit-ir.h:411
jit_value * argument(size_t i) const
Definition: jit-ir.h:369
jit_instruction(const std::vector< jit_value * > &aarguments)
Definition: jit-ir.h:356
static void reset_ids(void)
Definition: jit-ir.h:364
virtual void construct_ssa(void)
Definition: jit-ir.h:444
static size_t next_id(bool reset=false)
Definition: jit-ir.h:482
LIST_T * value(void) const
Definition: jit-util.h:171
NODE_T * next(void) const
Definition: jit-util.h:196
virtual ~jit_ir_walker(void)
Definition: jit-ir.h:1467
virtual void visit(jit_block &)=0
jit_const_index * m_index
Definition: jit-ir.h:1316
jit_const_index * m_count
Definition: jit-ir.h:1317
std::vector< context > m_contexts
Definition: jit-ir.h:1335
virtual std::ostream & short_print(std::ostream &os) const
Definition: jit-ir.h:1330
jit_phi_incoming(jit_phi *auser)
Definition: jit-ir.h:799
jit_phi * user(void) const
Definition: jit-ir.h:813
jit_phi_incoming(const jit_phi_incoming &use)
Definition: jit-ir.h:801
std::vector< jit_phi_incoming > m_incoming
Definition: jit-ir.h:1052
llvm::BasicBlock * incoming_llvm(size_t i) const
Definition: jit-ir.h:1016
jit_phi(jit_variable *adest, size_t npred)
Definition: jit-ir.h:995
void add_incoming(jit_block *from, jit_value *value)
Definition: jit-ir.h:1004
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:1025
virtual void construct_ssa(void)
Definition: jit-ir.h:1021
jit_block * incoming(size_t i) const
Definition: jit-ir.h:1011
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:1449
jit_return(jit_value *retval)
Definition: jit-ir.h:1436
jit_value * result(void) const
Definition: jit-ir.h:1438
jit_type * result_type(void) const
Definition: jit-ir.h:1443
const jit_function & overload(void) const
Definition: jit-ir.h:1387
const std::string & name(void) const
Definition: jit-ir.h:1382
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:1407
jit_value * result(void) const
Definition: jit-ir.h:1392
jit_store_argument(jit_variable *var)
Definition: jit-ir.h:1378
jit_type * result_type(void) const
Definition: jit-ir.h:1397
llvm::Value * result_llvm(void) const
Definition: jit-ir.h:1402
jit_variable * m_dest
Definition: jit-ir.h:1422
llvm::BasicBlock * successor_llvm(size_t idx=0) const
Definition: jit-ir.h:1074
bool alive(int idx) const
Definition: jit-ir.h:1099
std::ostream & print_successor(std::ostream &os, size_t idx=0) const
Definition: jit-ir.h:1081
bool alive(const jit_block *asuccessor) const
Definition: jit-ir.h:1092
size_t successor_count(void) const
Definition: jit-ir.h:1101
virtual bool check_alive(size_t) const
Definition: jit-ir.h:1109
jit_terminator(size_t asuccessor_count, Args... args)
Definition: jit-ir.h:1065
jit_block * successor(size_t idx=0) const
Definition: jit-ir.h:1069
std::vector< bool > m_alive
Definition: jit-ir.h:1113
bool alive(size_t idx) const
Definition: jit-ir.h:1097
static const jit_operation & cast(jit_type *result)
Definition: jit-typeinfo.h:703
static jit_type * get_any(void)
Definition: jit-typeinfo.h:544
static jit_type * get_string(void)
Definition: jit-typeinfo.h:556
jit_block * user_parent(void) const
Definition: jit-ir.cc:146
jit_use(const jit_use &use)
Definition: jit-ir.h:297
jit_use(void)
Definition: jit-ir.h:294
jit_instruction * user(void) const
Definition: jit-ir.h:310
size_t index(void) const
Definition: jit-ir.h:308
void stash_value(jit_value *avalue, jit_instruction *auser=nullptr, size_t aindex=-1)
Definition: jit-ir.h:316
std::list< jit_block * > user_parent_location(void) const
size_t m_index
Definition: jit-ir.h:327
jit_instruction * m_user
Definition: jit-ir.h:326
jit_internal_node< jit_value, jit_use > PARENT_T
Definition: jit-ir.h:292
void stash_llvm(llvm::Value *compiled)
Definition: jit-ir.h:259
virtual bool needs_release(void) const
Definition: jit-ir.h:239
bool has_llvm(void) const
Definition: jit-ir.h:248
virtual void accept(jit_ir_walker &walker)=0
bool in_worklist(void) const
Definition: jit-ir.h:194
jit_type * type(void) const
Definition: jit-ir.h:211
void stash_type(jit_type *new_type)
Definition: jit-ir.h:223
jit_instruction * last_use(void) const
Definition: jit-ir.h:232
void stash_in_worklist(bool ain_worklist)
Definition: jit-ir.h:199
virtual std::ostream & print(std::ostream &os, size_t indent=0) const =0
void stash_last_use(jit_instruction *alast_use)
Definition: jit-ir.h:234
llvm::Value * to_llvm(void) const
Definition: jit-ir.h:253
llvm::Value * m_llvm_value
Definition: jit-ir.h:273
bool m_in_worklist
Definition: jit-ir.h:279
llvm::Type * type_llvm(void) const
Definition: jit-ir.h:213
std::string print_string(void)
Definition: jit-ir.h:225
const std::string & type_name(void) const
Definition: jit-ir.h:218
virtual std::ostream & short_print(std::ostream &os) const
Definition: jit-ir.h:243
jit_instruction * m_last_use
Definition: jit-ir.h:278
jit_value(void)
Definition: jit-ir.h:188
std::ostream & print_indent(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:266
jit_type * m_type
Definition: jit-ir.h:277
bool has_top(void) const
Definition: jit-ir.h:834
jit_instruction * last_use(void) const
Definition: jit-ir.h:855
void push(jit_instruction *v)
Definition: jit-ir.h:844
void stash_last_use(jit_instruction *instr)
Definition: jit-ir.h:860
jit_instruction * m_last_use
Definition: jit-ir.h:887
void use_blocks(jit_block::df_set &result)
Definition: jit-ir.h:866
void pop(void)
Definition: jit-ir.h:850
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:876
const std::string & name(void) const
Definition: jit-ir.h:830
std::string m_name
Definition: jit-ir.h:881
jit_variable(const std::string &aname)
Definition: jit-ir.h:828
jit_value * top(void) const
Definition: jit-ir.h:839
std::stack< jit_value * > value_stack
Definition: jit-ir.h:886
void error(const char *fmt,...)
Definition: error.cc:968
QString name
#define JIT_VALUE_ACCEPT
Definition: jit-ir.h:499
#define JIT_VISIT_IR_CLASSES
Definition: jit-ir.h:69
#define JIT_VISIT_IR_NOTEMPLATE
Definition: jit-ir.h:46
std::ostream & operator<<(std::ostream &os, const jit_block_list &blocks)
Definition: jit-ir.cc:134
jit_const< double, jit_typeinfo::get_scalar > jit_const_scalar
Definition: jit-ir.h:90
jit_const< octave_idx_type, jit_typeinfo::get_index > jit_const_index
Definition: jit-ir.h:92
static llvm::LLVMContext & context
Definition: jit-typeinfo.cc:80
jit_const< bool, jit_typeinfo::get_bool > jit_const_bool
Definition: jit-ir.h:87
std::ostream & jit_print(std::ostream &os, jit_value *avalue)
Definition: jit-ir.cc:198
jit_const< Complex, jit_typeinfo::get_complex > jit_const_complex
Definition: jit-ir.h:91
jit_const< std::string, jit_typeinfo::get_string, const std::string &, true > jit_const_string
Definition: jit-ir.h:96
jit_const< jit_range, jit_typeinfo::get_range, const jit_range & > jit_const_range
Definition: jit-ir.h:98
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811