GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
jit-ir.cc
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 // defines required by llvm
27 #define __STDC_LIMIT_MACROS
28 #define __STDC_CONSTANT_MACROS
29 
30 #if defined (HAVE_CONFIG_H)
31 # include "config.h"
32 #endif
33 
34 #if defined (HAVE_LLVM)
35 
36 #include "jit-ir.h"
37 
38 #if defined (HAVE_LLVM_IR_FUNCTION_H)
39 # include <llvm/IR/BasicBlock.h>
40 # include <llvm/IR/Instructions.h>
41 #else
42 # include <llvm/BasicBlock.h>
43 # include <llvm/Instructions.h>
44 #endif
45 
46 #include "error.h"
47 
48 namespace octave
49 {
50 
51  // -------------------- jit_factory --------------------
53  {
54  for (auto iter = m_all_values.begin ();
55  iter != m_all_values.end (); ++iter)
56  delete *iter;
57  }
58 
59  void
61  {
62  if (value->type ())
63  m_constants.push_back (value);
64  m_all_values.push_back (value);
65  }
66 
67  // -------------------- jit_block_list --------------------
68  void
70  {
71  ++iter;
72  insert_before (iter, ablock);
73  }
74 
75  void
77  {
78  insert_after (loc->location (), ablock);
79  }
80 
81  void
83  {
84  iter = m_list.insert (iter, ablock);
85  ablock->stash_location (iter);
86  }
87 
88  void
90  {
91  insert_before (loc->location (), ablock);
92  }
93 
94  void
96  {
97  if (m_list.size ())
98  {
99  jit_block *block = m_list.back ();
100  block->label ();
101  }
102  }
103 
104  std::ostream&
105  jit_block_list::print (std::ostream& os, const std::string& header) const
106  {
107  os << "-------------------- " << header << " --------------------\n";
108  return os << *this;
109  }
110 
111  std::ostream&
112  jit_block_list::print_dom (std::ostream& os) const
113  {
114  os << "-------------------- dom info --------------------\n";
115  for (auto iter = begin (); iter != end (); ++iter)
116  {
117  assert (*iter);
118  (*iter)->print_dom (os);
119  }
120  os << std::endl;
121 
122  return os;
123  }
124 
125  void
127  {
128  m_list.push_back (b);
129  auto iter = m_list.end ();
130  b->stash_location (--iter);
131  }
132 
133  std::ostream&
134  operator<<(std::ostream& os, const jit_block_list& blocks)
135  {
136  for (auto iter = blocks.begin (); iter != blocks.end (); ++iter)
137  {
138  assert (*iter);
139  (*iter)->print (os, 0);
140  }
141  return os << std::endl;
142  }
143 
144  // -------------------- jit_use --------------------
145  jit_block *
146  jit_use::user_parent (void) const
147  {
148  return m_user->parent ();
149  }
150 
151  // -------------------- jit_value --------------------
153  { }
154 
155  jit_block *
157  {
158  jit_use *use = first_use ();
159  while (use)
160  {
161  if (! isa<jit_error_check> (use->user ()))
162  return use->user_parent ();
163 
164  use = use->next ();
165  }
166 
167  return 0;
168  }
169 
170  void
172  {
173  while (first_use ())
174  {
175  jit_instruction *user = first_use ()->user ();
176  size_t idx = first_use ()->index ();
177  user->stash_argument (idx, value);
178  }
179  }
180 
181 #define JIT_METH(clname) \
182  void \
183  jit_ ## clname::accept (jit_ir_walker& walker) \
184  { \
185  walker.visit (*this); \
186  }
187 
189 #undef JIT_METH
190 
191  std::ostream&
192  operator<< (std::ostream& os, const jit_value& value)
193  {
194  return value.short_print (os);
195  }
196 
197  std::ostream&
198  jit_print (std::ostream& os, jit_value *avalue)
199  {
200  if (avalue)
201  return avalue->print (os);
202  return os << "NULL";
203  }
204 
205  // -------------------- jit_instruction --------------------
206  void
208  {
209  if (m_parent)
211  resize_arguments (0);
212  }
213 
214  llvm::BasicBlock *
216  {
217  return m_parent->to_llvm ();
218  }
219 
220  std::ostream&
221  jit_instruction::short_print (std::ostream& os) const
222  {
223  if (type ())
224  jit_print (os, type ()) << ": ";
225  return os << '#' << m_id;
226  }
227 
228  void
229  jit_instruction::do_construct_ssa (size_t start, size_t end)
230  {
231  for (size_t i = start; i < end; ++i)
232  {
233  jit_value *arg = argument (i);
234  jit_variable *var = dynamic_cast<jit_variable *> (arg);
235  if (var && var->has_top ())
236  stash_argument (i, var->top ());
237  }
238  }
239 
240  // -------------------- jit_block --------------------
241  void
243  {
244  assert (isa<jit_block> (value));
245  jit_block *block = static_cast<jit_block *> (value);
246 
247  jit_value::replace_with (block);
248 
249  while (ILIST_T::first_use ())
250  {
251  jit_phi_incoming *incoming = ILIST_T::first_use ();
252  incoming->stash_value (block);
253  }
254  }
255 
256  void
258  {
260  while (node)
261  {
262  jit_phi_incoming *prev = node;
263  node = node->next ();
264 
265  if (prev->user_parent () == ablock)
266  prev->stash_value (with);
267  }
268  }
269 
270  jit_block *
272  {
273  if (successor_count () == 1 && successor (0) != this
274  && (successor (0)->use_count () == 1 || m_instructions.size () == 1))
275  {
276  jit_block *to_merge = successor (0);
277  merge (*to_merge);
278  return to_merge;
279  }
280 
281  return 0;
282  }
283 
284  void
286  {
287  // the merge block will contain a new terminator
288  jit_terminator *old_term = terminator ();
289  if (old_term)
290  old_term->remove ();
291 
292  bool was_empty = end () == begin ();
293  auto merge_begin = end ();
294  if (! was_empty)
295  --merge_begin;
296 
297  m_instructions.splice (end (), block.m_instructions);
298  if (was_empty)
299  merge_begin = begin ();
300  else
301  ++merge_begin;
302 
303  // now merge_begin points to the start of the new instructions, we must
304  // update their parent information
305  for (auto iter = merge_begin; iter != end (); ++iter)
306  {
307  jit_instruction *instr = *iter;
308  instr->stash_parent (this, iter);
309  }
310 
311  block.replace_with (this);
312  }
313 
316  {
317  m_instructions.push_front (instr);
318  instr->stash_parent (this, m_instructions.begin ());
319  return instr;
320  }
321 
324  {
325  // FIXME: Make this O(1)
326  for (auto iter = begin (); iter != end (); ++iter)
327  {
328  jit_instruction *temp = *iter;
329  if (! isa<jit_phi> (temp))
330  {
331  insert_before (iter, instr);
332  return instr;
333  }
334  }
335 
336  return append (instr);
337  }
338 
339  void
341  {
342  m_instructions.push_back (instr);
343  instr->stash_parent (this, --m_instructions.end ());
344  }
345 
348  {
349  auto iloc = m_instructions.insert (loc, instr);
350  instr->stash_parent (this, iloc);
351  return instr;
352  }
353 
356  {
357  ++loc;
358  auto iloc = m_instructions.insert (loc, instr);
359  instr->stash_parent (this, iloc);
360  return instr;
361  }
362 
365  {
366  if (m_instructions.empty ())
367  return nullptr;
368 
369  jit_instruction *last = m_instructions.back ();
370  return dynamic_cast<jit_terminator *> (last);
371  }
372 
373  bool
375  {
376  return terminator ()->alive (asucc);
377  }
378 
379  jit_block *
380  jit_block::successor (size_t i) const
381  {
382  jit_terminator *term = terminator ();
383  return term->successor (i);
384  }
385 
386  size_t
388  {
389  jit_terminator *term = terminator ();
390  return term ? term->successor_count () : 0;
391  }
392 
393  llvm::BasicBlock *
394  jit_block::to_llvm (void) const
395  {
396  return llvm::cast<llvm::BasicBlock> (m_llvm_value);
397  }
398 
399  std::ostream&
400  jit_block::print_dom (std::ostream& os) const
401  {
402  short_print (os);
403  os << ":\n";
404  os << " m_id: " << m_id << std::endl;
405  os << " predecessors: ";
406  for (jit_use *use = first_use (); use; use = use->next ())
407  os << *use->user_parent () << ' ';
408  os << std::endl;
409 
410  os << " successors: ";
411  for (size_t i = 0; i < successor_count (); ++i)
412  os << *successor (i) << ' ';
413  os << std::endl;
414 
415  os << " m_idom: ";
416  if (m_idom)
417  os << *m_idom;
418  else
419  os << "NULL";
420  os << std::endl;
421  os << " df: ";
422  for (auto iter = df_begin (); iter != df_end (); ++iter)
423  os << **iter << ' ';
424  os << std::endl;
425 
426  os << " m_dom_succ: ";
427  for (size_t i = 0; i < m_dom_succ.size (); ++i)
428  os << *m_dom_succ[i] << ' ';
429 
430  return os << std::endl;
431  }
432 
433  void
434  jit_block::compute_df (size_t avisit_count)
435  {
436  if (visited (avisit_count))
437  return;
438 
439  if (use_count () >= 2)
440  {
441  for (jit_use *use = first_use (); use; use = use->next ())
442  {
443  jit_block *runner = use->user_parent ();
444  while (runner != m_idom)
445  {
446  runner->m_df.insert (this);
447  runner = runner->m_idom;
448  }
449  }
450  }
451 
452  for (size_t i = 0; i < successor_count (); ++i)
453  successor (i)->compute_df (avisit_count);
454  }
455 
456  bool
457  jit_block::update_idom (size_t avisit_count)
458  {
459  if (visited (avisit_count) || ! use_count ())
460  return false;
461 
462  bool changed = false;
463  for (jit_use *use = first_use (); use; use = use->next ())
464  {
465  jit_block *pred = use->user_parent ();
466  changed = pred->update_idom (avisit_count) || changed;
467  }
468 
469  jit_use *use = first_use ();
470  jit_block *new_idom = use->user_parent ();
471  use = use->next ();
472 
473  for (; use; use = use->next ())
474  {
475  jit_block *pred = use->user_parent ();
476  jit_block *pidom = pred->m_idom;
477  if (pidom)
478  new_idom = idom_intersect (pidom, new_idom);
479  }
480 
481  if (m_idom != new_idom)
482  {
483  m_idom = new_idom;
484  return true;
485  }
486 
487  return changed;
488  }
489 
490  void
491  jit_block::label (size_t avisit_count, size_t& number)
492  {
493  if (visited (avisit_count))
494  return;
495 
496  for (jit_use *use = first_use (); use; use = use->next ())
497  {
498  jit_block *pred = use->user_parent ();
499  pred->label (avisit_count, number);
500  }
501 
502  m_id = number++;
503  }
504 
505  void
507  {
508  for (auto iter = begin (); iter != end (); ++iter)
509  {
510  jit_instruction *instr = *iter;
511  instr->pop_variable ();
512  }
513  }
514 
515  std::ostream&
516  jit_block::print (std::ostream& os, size_t indent) const
517  {
518  print_indent (os, indent);
519  short_print (os) << ": %pred = ";
520  for (jit_use *use = first_use (); use; use = use->next ())
521  {
522  jit_block *pred = use->user_parent ();
523  os << *pred;
524  if (use->next ())
525  os << ", ";
526  }
527  os << std::endl;
528 
529  for (auto iter = begin (); iter != end (); ++iter)
530  {
531  jit_instruction *instr = *iter;
532  instr->print (os, indent + 1) << std::endl;
533  }
534  return os;
535  }
536 
537  jit_block *
539  jit_block *asuccessor)
540  {
541  if (successor_count () > 1)
542  {
543  jit_terminator *term = terminator ();
544  size_t idx = term->successor_index (asuccessor);
545  jit_block *split = factory.create<jit_block> ("phi_split", m_visit_count);
546 
547  // place after this to ensure define before use in the blocks list
548  blocks.insert_after (this, split);
549 
550  term->stash_argument (idx, split);
551  jit_branch *br = split->append (factory.create<jit_branch> (asuccessor));
552  replace_in_phi (asuccessor, split);
553 
554  if (alive ())
555  {
556  split->mark_alive ();
557  br->infer ();
558  }
559 
560  return split;
561  }
562 
563  return this;
564  }
565 
566  void
567  jit_block::create_dom_tree (size_t avisit_count)
568  {
569  if (visited (avisit_count))
570  return;
571 
572  if (m_idom != this)
573  m_idom->m_dom_succ.push_back (this);
574 
575  for (size_t i = 0; i < successor_count (); ++i)
576  successor (i)->create_dom_tree (avisit_count);
577  }
578 
579  jit_block *
581  {
582  while (i && j && i != j)
583  {
584  while (i && i->id () > j->id ())
585  i = i->m_idom;
586 
587  while (i && j && j->id () > i->id ())
588  j = j->m_idom;
589  }
590 
591  return i ? i : j;
592  }
593 
594  // -------------------- jit_phi_incoming --------------------
595 
596  jit_block *
598  { return m_user->parent (); }
599 
600  // -------------------- jit_phi --------------------
601  bool
603  {
604  jit_block *p = parent ();
605  size_t new_idx = 0;
606  jit_value *unique = argument (1);
607 
608  for (size_t i = 0; i < argument_count (); ++i)
609  {
610  jit_block *inc = incoming (i);
611  if (inc->branch_alive (p))
612  {
613  if (unique != argument (i))
614  unique = 0;
615 
616  if (new_idx != i)
617  {
618  stash_argument (new_idx, argument (i));
619  m_incoming[new_idx].stash_value (inc);
620  }
621 
622  ++new_idx;
623  }
624  }
625 
626  if (new_idx != argument_count ())
627  {
628  resize_arguments (new_idx);
629  m_incoming.resize (new_idx);
630  }
631 
632  assert (argument_count () > 0);
633  if (unique)
634  {
635  replace_with (unique);
636  return true;
637  }
638 
639  return false;
640  }
641 
642  bool
644  {
645  jit_block *p = parent ();
646  if (! p->alive ())
647  return false;
648 
649  jit_type *infered = nullptr;
650  for (size_t i = 0; i < argument_count (); ++i)
651  {
652  jit_block *inc = incoming (i);
653  if (inc->branch_alive (p))
654  infered = jit_type_join (infered, argument_type (i));
655  }
656 
657  if (infered != type ())
658  {
659  stash_type (infered);
660  return true;
661  }
662 
663  return false;
664  }
665 
666  llvm::PHINode *
667  jit_phi::to_llvm (void) const
668  {
669  return llvm::cast<llvm::PHINode> (jit_value::to_llvm ());
670  }
671 
672  // -------------------- jit_terminator --------------------
673  size_t
674  jit_terminator::successor_index (const jit_block *asuccessor) const
675  {
676  size_t scount = successor_count ();
677  for (size_t i = 0; i < scount; ++i)
678  if (successor (i) == asuccessor)
679  return i;
680 
681  panic_impossible ();
682  }
683 
684  bool
686  {
687  if (! parent ()->alive ())
688  return false;
689 
690  bool changed = false;
691  for (size_t i = 0; i < m_alive.size (); ++i)
692  if (! m_alive[i] && check_alive (i))
693  {
694  changed = true;
695  m_alive[i] = true;
696  successor (i)->mark_alive ();
697  }
698 
699  return changed;
700  }
701 
702  llvm::TerminatorInst *
704  {
705  return llvm::cast<llvm::TerminatorInst> (jit_value::to_llvm ());
706  }
707 
708  // -------------------- jit_call --------------------
709  bool
711  {
712  if (type () && jit_typeinfo::get_release (type ()).valid ())
713  {
714  for (jit_use *use = first_use (); use; use = use->next ())
715  {
716  jit_assign *assign = dynamic_cast<jit_assign *> (use->user ());
717  if (assign && assign->artificial ())
718  return false;
719  }
720 
721  return true;
722  }
723  return false;
724  }
725 
726  bool
728  {
729  // FIXME: explain algorithm
730  for (size_t i = 0; i < argument_count (); ++i)
731  {
733  if (! m_already_infered[i])
734  return false;
735  }
736 
738  if (! infered && use_count ())
739  {
740  std::stringstream ss;
741  ss << "Missing overload in type inference for ";
742  print (ss, 0);
743  throw jit_fail_exception (ss.str ());
744  }
745 
746  if (infered != type ())
747  {
748  stash_type (infered);
749  return true;
750  }
751 
752  return false;
753  }
754 
755  // -------------------- jit_error_check --------------------
756  std::string
758  {
759  switch (v)
760  {
761  case var_error_state:
762  return "error_state";
763  case var_interrupt:
764  return "interrupt";
765  default:
766  panic_impossible ();
767  }
768  }
769 
770  std::ostream&
771  jit_error_check::print (std::ostream& os, size_t indent) const
772  {
773  print_indent (os, indent) << "error_check " << variable_to_string (m_variable)
774  << ", ";
775 
776  if (has_check_for ())
777  os << "<for> " << *check_for () << ", ";
778  print_successor (os << "<normal> ", 1) << ", ";
779  return print_successor (os << "<error> ", 0);
780  }
781 
782  // -------------------- jit_magic_end --------------------
784  size_t aindex, size_t acount)
785  : m_value (avalue), m_index (factory.create<jit_const_index> (aindex)),
786  m_count (factory.create<jit_const_index> (acount))
787  { }
788 
789  jit_magic_end::jit_magic_end (const std::vector<context>& full_context)
790  : m_contexts (full_context)
791  {
792  resize_arguments (m_contexts.size ());
793 
794  size_t i;
795  std::vector<context>::const_iterator iter;
796  for (iter = m_contexts.begin (), i = 0; iter != m_contexts.end (); ++iter, ++i)
797  stash_argument (i, iter->m_value);
798  }
799 
802  {
803  size_t idx;
804  for (idx = 0; idx < m_contexts.size (); ++idx)
805  {
806  jit_type *ctx_type = m_contexts[idx].m_value->type ();
807  if (! ctx_type || ctx_type->skip_paren ())
808  break;
809  }
810 
811  if (idx >= m_contexts.size ())
812  idx = 0;
813 
814  context ret = m_contexts[idx];
815  ret.m_value = argument (idx);
816  return ret;
817  }
818 
819  bool
821  {
822  jit_type *new_type = overload ().result ();
823  if (new_type != type ())
824  {
825  stash_type (new_type);
826  return true;
827  }
828 
829  return false;
830  }
831 
832  std::ostream&
833  jit_magic_end::print (std::ostream& os, size_t indent) const
834  {
835  context ctx = resolve_context ();
836  short_print (print_indent (os, indent)) << " (" << *ctx.m_value << ", ";
837  return os << *ctx.m_index << ", " << *ctx.m_count << ')';
838  }
839 
840  const jit_function&
842  {
843  const context& ctx = resolve_context ();
844  return jit_typeinfo::end (ctx.m_value, ctx.m_index, ctx.m_count);
845  }
846 
847 }
848 
849 #endif
#define loc(X, Y)
Definition: Screen.cpp:56
bool artificial(void) const
Definition: jit-ir.h:957
void insert_before(iterator iter, jit_block *ablock)
Definition: jit-ir.cc:82
void label(void)
Definition: jit-ir.cc:95
iterator end(void)
Definition: jit-ir.h:152
void push_back(jit_block *b)
Definition: jit-ir.cc:126
std::list< jit_block * > m_list
Definition: jit-ir.h:178
iterator begin(void)
Definition: jit-ir.h:148
void insert_after(iterator iter, jit_block *ablock)
Definition: jit-ir.cc:69
std::list< jit_block * >::iterator iterator
Definition: jit-ir.h:143
std::ostream & print(std::ostream &os, const std::string &header) const
Definition: jit-ir.cc:105
std::ostream & print_dom(std::ostream &os) const
Definition: jit-ir.cc:112
llvm::BasicBlock * to_llvm(void) const
Definition: jit-ir.cc:394
jit_block * m_idom
Definition: jit-ir.h:782
T * append(T *instr)
Definition: jit-ir.h:608
jit_block * maybe_merge()
Definition: jit-ir.cc:271
void create_dom_tree(void)
Definition: jit-ir.h:696
void replace_in_phi(jit_block *ablock, jit_block *with)
Definition: jit-ir.cc:257
void internal_append(jit_instruction *instr)
Definition: jit-ir.cc:340
void merge(jit_block &merge)
Definition: jit-ir.cc:285
jit_instruction * prepend_after_phi(jit_instruction *instr)
Definition: jit-ir.cc:323
bool update_idom(size_t avisit_count)
Definition: jit-ir.cc:457
instruction_list m_instructions
Definition: jit-ir.h:786
size_t id(void) const
Definition: jit-ir.h:660
bool branch_alive(jit_block *asucc) const
Definition: jit-ir.cc:374
instruction_list::iterator iterator
Definition: jit-ir.h:568
iterator remove(iterator iter)
Definition: jit-ir.h:628
jit_instruction * insert_after(iterator loc, jit_instruction *instr)
Definition: jit-ir.cc:355
virtual void replace_with(jit_value *value)
Definition: jit-ir.cc:242
virtual std::ostream & short_print(std::ostream &os) const
Definition: jit-ir.h:728
size_t successor_count(void) const
Definition: jit-ir.cc:387
iterator end(void)
Definition: jit-ir.h:649
void label(void)
Definition: jit-ir.h:670
jit_block * maybe_split(jit_factory &factory, jit_block_list &blocks, jit_block *asuccessor)
Definition: jit-ir.cc:538
jit_block * successor(size_t i) const
Definition: jit-ir.cc:380
bool visited(size_t avisit_count)
Definition: jit-ir.h:751
bool alive(void) const
Definition: jit-ir.h:591
std::ostream & print_dom(std::ostream &os) const
Definition: jit-ir.cc:400
iterator begin(void)
Definition: jit-ir.h:645
jit_instruction * prepend(jit_instruction *instr)
Definition: jit-ir.cc:315
jit_terminator * terminator(void) const
Definition: jit-ir.cc:364
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
size_t m_visit_count
Definition: jit-ir.h:780
jit_use * first_use(void) const
Definition: jit-ir.h:586
void pop_all(void)
Definition: jit-ir.cc:506
size_t use_count(void) const
Definition: jit-ir.h:588
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
static jit_block * idom_intersect(jit_block *i, jit_block *j)
Definition: jit-ir.cc:580
jit_instruction * insert_before(iterator loc, jit_instruction *instr)
Definition: jit-ir.cc:347
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.cc:516
void compute_df(void)
Definition: jit-ir.h:691
virtual bool needs_release(void) const
Definition: jit-ir.cc:710
virtual bool infer(void)
Definition: jit-ir.cc:727
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
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.cc:771
static std::string variable_to_string(variable v)
Definition: jit-ir.cc:757
bool has_check_for(void) const
Definition: jit-ir.h:1270
jit_call * check_for(void) const
Definition: jit-ir.h:1275
~jit_factory(void)
Definition: jit-ir.cc:52
value_list m_constants
Definition: jit-ir.h:131
value_list m_all_values
Definition: jit-ir.h:129
T * create(const Args &... args)
Definition: jit-ir.h:118
void track_value(jit_value *v)
Definition: jit-ir.cc:60
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
void do_construct_ssa(size_t start, size_t end)
Definition: jit-ir.cc:229
jit_block * m_parent
Definition: jit-ir.h:494
void stash_argument(size_t i, jit_value *arg)
Definition: jit-ir.h:399
llvm::BasicBlock * parent_llvm(void) const
Definition: jit-ir.cc:215
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
jit_block * parent(void) const
Definition: jit-ir.h:455
virtual void pop_variable(void)
Definition: jit-ir.h:442
jit_value * argument(size_t i) const
Definition: jit-ir.h:369
virtual std::ostream & short_print(std::ostream &os) const
Definition: jit-ir.cc:221
NODE_T * next(void) const
Definition: jit-util.h:196
void stash_value(LIST_T *avalue)
Definition: jit-util.h:173
jit_const_index * m_index
Definition: jit-ir.h:1316
jit_const_index * m_count
Definition: jit-ir.h:1317
jit_magic_end(const std::vector< context > &full_context)
Definition: jit-ir.cc:789
const jit_function & overload() const
Definition: jit-ir.cc:841
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.cc:833
std::vector< context > m_contexts
Definition: jit-ir.h:1335
virtual std::ostream & short_print(std::ostream &os) const
Definition: jit-ir.h:1330
context resolve_context(void) const
Definition: jit-ir.cc:801
virtual bool infer(void)
Definition: jit-ir.cc:820
jit_type * result(const signature_vec &types) const
Definition: jit-typeinfo.h:390
jit_block * user_parent(void) const
Definition: jit-ir.cc:597
std::vector< jit_phi_incoming > m_incoming
Definition: jit-ir.h:1052
llvm::PHINode * to_llvm(void) const
Definition: jit-ir.cc:667
virtual bool infer(void)
Definition: jit-ir.cc:643
bool prune(void)
Definition: jit-ir.cc:602
jit_block * incoming(size_t i) const
Definition: jit-ir.h:1011
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_block * successor(size_t idx=0) const
Definition: jit-ir.h:1069
std::vector< bool > m_alive
Definition: jit-ir.h:1113
size_t successor_index(const jit_block *asuccessor) const
Definition: jit-ir.cc:674
virtual bool infer(void)
Definition: jit-ir.cc:685
llvm::TerminatorInst * to_llvm(void) const
Definition: jit-ir.cc:703
bool skip_paren(void) const
Definition: jit-typeinfo.h:167
static const jit_function & get_release(jit_type *type)
Definition: jit-typeinfo.h:663
static const jit_operation & end(void)
Definition: jit-typeinfo.h:723
jit_block * user_parent(void) const
Definition: jit-ir.cc:146
jit_instruction * user(void) const
Definition: jit-ir.h:310
size_t index(void) const
Definition: jit-ir.h:308
jit_instruction * m_user
Definition: jit-ir.h:326
virtual void replace_with(jit_value *m_value)
Definition: jit-ir.cc:171
virtual ~jit_value(void)
Definition: jit-ir.cc:152
jit_type * type(void) const
Definition: jit-ir.h:211
void stash_type(jit_type *new_type)
Definition: jit-ir.h:223
jit_block * first_use_block(void)
Definition: jit-ir.cc:156
virtual std::ostream & print(std::ostream &os, size_t indent=0) const =0
llvm::Value * to_llvm(void) const
Definition: jit-ir.h:253
llvm::Value * m_llvm_value
Definition: jit-ir.h:273
virtual std::ostream & short_print(std::ostream &os) const
Definition: jit-ir.h:243
std::ostream & print_indent(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:266
bool has_top(void) const
Definition: jit-ir.h:834
jit_value * top(void) const
Definition: jit-ir.h:839
#define panic_impossible()
Definition: error.h:380
#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_type * jit_type_join(jit_type *lhs, jit_type *rhs)
std::ostream & jit_print(std::ostream &os, jit_value *avalue)
Definition: jit-ir.cc:198