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
jit-util.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 // Some utility classes and functions used throughout jit
26 
27 #if !defined (octave_jit_util_h)
28 #define octave_jit_util_h 1
29 
30 #ifdef HAVE_LLVM
31 
32 #include <stdexcept>
33 
34 #if defined(HAVE_LLVM_IR_DATALAYOUT_H) || defined(HAVE_LLVM_DATALAYOUT_H)
35 #define HAVE_LLVM_DATALAYOUT
36 #endif
37 
38 // we don't want to include llvm headers here, as they require
39 // __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS be defined in the entire
40 // compilation unit
41 namespace llvm
42 {
43  class Value;
44  class Module;
45  class FunctionPassManager;
46  class PassManager;
47  class ExecutionEngine;
48  class Function;
49  class BasicBlock;
50  class LLVMContext;
51  class Type;
52  class StructType;
53  class Twine;
54  class GlobalVariable;
55  class TerminatorInst;
56  class PHINode;
57 
58  class ConstantFolder;
59 
60  template <bool preserveNames>
61  class IRBuilderDefaultInserter;
62 
63  template <bool preserveNames, typename T, typename Inserter>
64  class IRBuilder;
65 
66 typedef IRBuilder<true, ConstantFolder, IRBuilderDefaultInserter<true> >
68 }
69 
70 class octave_base_value;
71 class octave_builtin;
72 class octave_value;
73 class tree;
74 class tree_expression;
75 
76 // thrown when we should give up on JIT and interpret
77 class jit_fail_exception : public std::runtime_error
78 {
79 public:
80  jit_fail_exception (void) : std::runtime_error ("unknown"), mknown (false) { }
81  jit_fail_exception (const std::string& reason) : std::runtime_error (reason),
82  mknown (true)
83  { }
84 
85  bool known (void) const { return mknown; }
86 private:
87  bool mknown;
88 };
89 
90 // llvm doesn't provide this, and it's really useful for debugging
91 std::ostream& operator<< (std::ostream& os, const llvm::Value& v);
92 
93 template <typename HOLDER_T, typename SUB_T>
94 class jit_internal_node;
95 
96 // jit_internal_list and jit_internal_node implement generic embedded doubly
97 // linked lists. List items extend from jit_internal_list, and can be placed
98 // in nodes of type jit_internal_node. We use CRTP twice.
99 template <typename LIST_T, typename NODE_T>
100 class
102 {
103  friend class jit_internal_node<LIST_T, NODE_T>;
104 public:
105  jit_internal_list (void) : use_head (0), use_tail (0), muse_count (0) { }
106 
107  virtual ~jit_internal_list (void)
108  {
109  while (use_head)
110  use_head->stash_value (0);
111  }
112 
113  NODE_T *first_use (void) const { return use_head; }
114 
115  size_t use_count (void) const { return muse_count; }
116 private:
117  NODE_T *use_head;
118  NODE_T *use_tail;
119  size_t muse_count;
120 };
121 
122 // a node for internal linked lists
123 template <typename LIST_T, typename NODE_T>
124 class
126 {
127 public:
129 
130  jit_internal_node (void) : mvalue (0), mnext (0), mprev (0) { }
131 
132  ~jit_internal_node (void) { remove (); }
133 
134  LIST_T *value (void) const { return mvalue; }
135 
136  void stash_value (LIST_T *avalue)
137  {
138  remove ();
139 
140  mvalue = avalue;
141 
142  if (mvalue)
143  {
144  jit_ilist *ilist = mvalue;
145  NODE_T *sthis = static_cast<NODE_T *> (this);
146  if (ilist->use_head)
147  {
148  ilist->use_tail->mnext = sthis;
149  mprev = ilist->use_tail;
150  }
151  else
152  ilist->use_head = sthis;
153 
154  ilist->use_tail = sthis;
155  ++ilist->muse_count;
156  }
157  }
158 
159  NODE_T *next (void) const { return mnext; }
160 
161  NODE_T *prev (void) const { return mprev; }
162 private:
163  void remove ()
164  {
165  if (mvalue)
166  {
167  jit_ilist *ilist = mvalue;
168  if (mprev)
169  mprev->mnext = mnext;
170  else
171  // we are the use_head
172  ilist->use_head = mnext;
173 
174  if (mnext)
175  mnext->mprev = mprev;
176  else
177  // we are the use tail
178  ilist->use_tail = mprev;
179 
180  mnext = mprev = 0;
181  --ilist->muse_count;
182  mvalue = 0;
183  }
184  }
185 
186  LIST_T *mvalue;
187  NODE_T *mnext;
188  NODE_T *mprev;
189 };
190 
191 // Use like: isa<jit_phi> (value)
192 // basically just a short cut type typing dyanmic_cast.
193 template <typename T, typename U>
194 bool isa (U *value)
195 {
196  return dynamic_cast<T *> (value);
197 }
198 
199 #define JIT_ASSIGN_ARG(i) the_args[i] = arg ## i;
200 #define JIT_EXPAND(ret, fname, type, isconst, N) \
201  ret fname (JIT_PARAM_ARGS OCT_MAKE_DECL_LIST (type, arg, N)) isconst \
202  { \
203  std::vector<type> the_args (N); \
204  OCT_ITERATE_MACRO (JIT_ASSIGN_ARG, N); \
205  return fname (JIT_PARAMS the_args); \
206  }
207 
208 #endif
209 #endif