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