comparison libinterp/corefcn/jit-ir.h @ 16892:68fc671a9339

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