Mercurial > octave
annotate src/pt-jit.cc @ 14915:cba58541954c
Add if support and fix leak with any
author | Max Brister <max@2bass.com> |
---|---|
date | Mon, 21 May 2012 15:41:19 -0600 |
parents | c7071907a641 |
children | 232d8ab07932 |
rev | line source |
---|---|
14899 | 1 /* |
2 | |
14901
516b4a15b775
doc: Copyright fix in pt-jit.h and pt-jit.cc
Max Brister <max@2bass.com>
parents:
14899
diff
changeset
|
3 Copyright (C) 2012 Max Brister <max@2bass.com> |
14899 | 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 #define __STDC_LIMIT_MACROS | |
24 #define __STDC_CONSTANT_MACROS | |
25 | |
26 #ifdef HAVE_CONFIG_H | |
27 #include <config.h> | |
28 #endif | |
29 | |
30 #include "pt-jit.h" | |
31 | |
32 #include <typeinfo> | |
33 | |
34 #include <llvm/LLVMContext.h> | |
35 #include <llvm/Module.h> | |
36 #include <llvm/Function.h> | |
37 #include <llvm/BasicBlock.h> | |
38 #include <llvm/Support/IRBuilder.h> | |
39 #include <llvm/ExecutionEngine/ExecutionEngine.h> | |
40 #include <llvm/ExecutionEngine/JIT.h> | |
41 #include <llvm/PassManager.h> | |
42 #include <llvm/Analysis/Verifier.h> | |
14903 | 43 #include <llvm/Analysis/CallGraph.h> |
14899 | 44 #include <llvm/Analysis/Passes.h> |
45 #include <llvm/Target/TargetData.h> | |
46 #include <llvm/Transforms/Scalar.h> | |
14903 | 47 #include <llvm/Transforms/IPO.h> |
14899 | 48 #include <llvm/Support/TargetSelect.h> |
49 #include <llvm/Support/raw_os_ostream.h> | |
14903 | 50 #include <llvm/ExecutionEngine/GenericValue.h> |
14899 | 51 |
14903 | 52 #include "octave.h" |
14899 | 53 #include "ov-fcn-handle.h" |
54 #include "ov-usr-fcn.h" | |
55 #include "pt-all.h" | |
56 | |
14903 | 57 // FIXME: Remove eventually |
58 // For now we leave this in so people tell when JIT actually happens | |
59 static const bool debug_print = false; | |
14899 | 60 |
14903 | 61 static llvm::IRBuilder<> builder (llvm::getGlobalContext ()); |
62 | |
14906 | 63 // thrown when we should give up on JIT and interpret |
64 class jit_fail_exception : public std::exception {}; | |
65 | |
66 static void | |
67 fail (void) | |
68 { | |
69 throw jit_fail_exception (); | |
70 } | |
71 | |
14903 | 72 // function that jit code calls |
73 extern "C" void | |
74 octave_jit_print_any (const char *name, octave_base_value *obv) | |
75 { | |
76 obv->print_with_name (octave_stdout, name, true); | |
77 } | |
14899 | 78 |
79 extern "C" void | |
14903 | 80 octave_jit_print_double (const char *name, double value) |
14899 | 81 { |
82 // FIXME: We should avoid allocating a new octave_scalar each time | |
83 octave_value ov (value); | |
84 ov.print_with_name (octave_stdout, name); | |
85 } | |
86 | |
14903 | 87 extern "C" octave_base_value* |
88 octave_jit_binary_any_any (octave_value::binary_op op, octave_base_value *lhs, | |
89 octave_base_value *rhs) | |
90 { | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
91 octave_value olhs (lhs); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
92 octave_value orhs (rhs); |
14903 | 93 octave_value result = do_binary_op (op, olhs, orhs); |
94 octave_base_value *rep = result.internal_rep (); | |
95 rep->grab (); | |
96 return rep; | |
97 } | |
98 | |
99 extern "C" void | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
100 octave_jit_release_any (octave_base_value *obv) |
14903 | 101 { |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
102 obv->release (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
103 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
104 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
105 extern "C" void |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
106 octave_jit_grab_any (octave_base_value *obv) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
107 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
108 obv->grab (); |
14903 | 109 } |
110 | |
111 // -------------------- jit_type -------------------- | |
112 llvm::Type * | |
113 jit_type::to_llvm_arg (void) const | |
114 { | |
115 return llvm_type ? llvm_type->getPointerTo () : 0; | |
116 } | |
117 | |
118 // -------------------- jit_function -------------------- | |
119 void | |
120 jit_function::add_overload (const overload& func, | |
121 const std::vector<jit_type*>& args) | |
122 { | |
123 if (args.size () >= overloads.size ()) | |
124 overloads.resize (args.size () + 1); | |
125 | |
126 Array<overload>& over = overloads[args.size ()]; | |
127 dim_vector dv (over.dims ()); | |
128 Array<octave_idx_type> idx = to_idx (args); | |
129 bool must_resize = false; | |
130 | |
131 if (dv.length () != idx.numel ()) | |
132 { | |
133 dv.resize (idx.numel ()); | |
134 must_resize = true; | |
135 } | |
136 | |
137 for (octave_idx_type i = 0; i < dv.length (); ++i) | |
138 if (dv(i) <= idx(i)) | |
139 { | |
140 must_resize = true; | |
141 dv(i) = idx(i) + 1; | |
142 } | |
143 | |
144 if (must_resize) | |
145 over.resize (dv); | |
146 | |
147 over(idx) = func; | |
148 } | |
149 | |
150 const jit_function::overload& | |
151 jit_function::get_overload (const std::vector<jit_type*>& types) const | |
152 { | |
153 // FIXME: We should search for the next best overload on failure | |
154 static overload null_overload; | |
155 if (types.size () >= overloads.size ()) | |
156 return null_overload; | |
157 | |
158 const Array<overload>& over = overloads[types.size ()]; | |
159 dim_vector dv (over.dims ()); | |
160 Array<octave_idx_type> idx = to_idx (types); | |
161 for (octave_idx_type i = 0; i < dv.length (); ++i) | |
162 if (idx(i) >= dv(i)) | |
163 return null_overload; | |
164 | |
165 return over(idx); | |
166 } | |
167 | |
168 Array<octave_idx_type> | |
169 jit_function::to_idx (const std::vector<jit_type*>& types) const | |
170 { | |
171 octave_idx_type numel = types.size (); | |
172 if (numel == 1) | |
173 numel = 2; | |
174 | |
175 Array<octave_idx_type> idx (dim_vector (1, numel)); | |
176 for (octave_idx_type i = 0; i < static_cast<octave_idx_type> (types.size ()); | |
177 ++i) | |
178 idx(i) = types[i]->type_id (); | |
179 | |
180 if (types.size () == 1) | |
181 { | |
182 idx(1) = idx(0); | |
183 idx(0) = 0; | |
184 } | |
185 | |
186 return idx; | |
187 } | |
188 | |
189 // -------------------- jit_typeinfo -------------------- | |
14906 | 190 jit_typeinfo::jit_typeinfo (llvm::Module *m, llvm::ExecutionEngine *e) |
191 : module (m), engine (e), next_id (0) | |
14899 | 192 { |
14903 | 193 // FIXME: We should be registering types like in octave_value_typeinfo |
194 llvm::LLVMContext &ctx = m->getContext (); | |
195 | |
14906 | 196 ov_t = llvm::StructType::create (ctx, "octave_base_value"); |
197 ov_t = ov_t->getPointerTo (); | |
198 | |
199 llvm::Type *dbl = llvm::Type::getDoubleTy (ctx); | |
200 llvm::Type *bool_t = llvm::Type::getInt1Ty (ctx); | |
201 llvm::Type *index_t = 0; | |
202 switch (sizeof(octave_idx_type)) | |
203 { | |
204 case 4: | |
205 index_t = llvm::Type::getInt32Ty (ctx); | |
206 break; | |
207 case 8: | |
208 index_t = llvm::Type::getInt64Ty (ctx); | |
209 break; | |
210 default: | |
211 assert (false && "Unrecognized index type size"); | |
212 } | |
213 | |
214 llvm::StructType *range_t = llvm::StructType::create (ctx, "range"); | |
215 std::vector<llvm::Type *> range_contents (4, dbl); | |
216 range_contents[3] = index_t; | |
217 range_t->setBody (range_contents); | |
218 | |
14903 | 219 // create types |
220 any = new_type ("any", true, 0, ov_t); | |
14906 | 221 scalar = new_type ("scalar", false, any, dbl); |
222 range = new_type ("range", false, any, range_t); | |
223 boolean = new_type ("bool", false, any, bool_t); | |
224 index = new_type ("index", false, any, index_t); | |
14903 | 225 |
226 // any with anything is an any op | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
227 llvm::Function *fn; |
14903 | 228 llvm::Type *binary_op_type |
229 = llvm::Type::getIntNTy (ctx, sizeof (octave_value::binary_op)); | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
230 llvm::Function *any_binary = create_function ("octave_jit_binary_any_any", |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
231 any->to_llvm (), binary_op_type, |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
232 any->to_llvm (), any->to_llvm ()); |
14903 | 233 engine->addGlobalMapping (any_binary, |
234 reinterpret_cast<void*>(&octave_jit_binary_any_any)); | |
235 | |
236 binary_ops.resize (octave_value::num_binary_ops); | |
237 for (int op = 0; op < octave_value::num_binary_ops; ++op) | |
238 { | |
239 llvm::Twine fn_name ("octave_jit_binary_any_any_"); | |
240 fn_name = fn_name + llvm::Twine (op); | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
241 fn = create_function (fn_name, any, any, any); |
14903 | 242 llvm::BasicBlock *block = llvm::BasicBlock::Create (ctx, "body", fn); |
14906 | 243 builder.SetInsertPoint (block); |
14903 | 244 llvm::APInt op_int(sizeof (octave_value::binary_op), op, |
245 std::numeric_limits<octave_value::binary_op>::is_signed); | |
246 llvm::Value *op_as_llvm = llvm::ConstantInt::get (binary_op_type, op_int); | |
14906 | 247 llvm::Value *ret = builder.CreateCall3 (any_binary, |
14903 | 248 op_as_llvm, |
249 fn->arg_begin (), | |
250 ++fn->arg_begin ()); | |
14906 | 251 builder.CreateRet (ret); |
14903 | 252 |
253 jit_function::overload overload (fn, true, any, any, any); | |
254 for (octave_idx_type i = 0; i < next_id; ++i) | |
255 binary_ops[op].add_overload (overload); | |
256 } | |
257 | |
14906 | 258 llvm::Type *void_t = llvm::Type::getVoidTy (ctx); |
14903 | 259 |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
260 // grab any |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
261 fn = create_function ("octave_jit_grab_any", void_t, any->to_llvm ()); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
262 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
263 engine->addGlobalMapping (fn, reinterpret_cast<void*>(&octave_jit_grab_any)); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
264 grab_fn.add_overload (fn, false, 0, any); |
14903 | 265 |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
266 // release any |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
267 fn = create_function ("octave_jit_release_any", void_t, any->to_llvm ()); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
268 engine->addGlobalMapping (fn, reinterpret_cast<void*>(&octave_jit_release_any)); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
269 release_fn.add_overload (fn, false, 0, any); |
14903 | 270 |
271 // now for binary scalar operations | |
272 // FIXME: Finish all operations | |
273 add_binary_op (scalar, octave_value::op_add, llvm::Instruction::FAdd); | |
274 add_binary_op (scalar, octave_value::op_sub, llvm::Instruction::FSub); | |
275 add_binary_op (scalar, octave_value::op_mul, llvm::Instruction::FMul); | |
276 add_binary_op (scalar, octave_value::op_el_mul, llvm::Instruction::FMul); | |
277 | |
278 // FIXME: Warn if rhs is zero | |
279 add_binary_op (scalar, octave_value::op_div, llvm::Instruction::FDiv); | |
280 add_binary_op (scalar, octave_value::op_el_div, llvm::Instruction::FDiv); | |
281 | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
282 add_binary_fcmp (scalar, octave_value::op_lt, llvm::CmpInst::FCMP_ULT); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
283 add_binary_fcmp (scalar, octave_value::op_le, llvm::CmpInst::FCMP_ULE); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
284 add_binary_fcmp (scalar, octave_value::op_eq, llvm::CmpInst::FCMP_UEQ); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
285 add_binary_fcmp (scalar, octave_value::op_ge, llvm::CmpInst::FCMP_UGE); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
286 add_binary_fcmp (scalar, octave_value::op_gt, llvm::CmpInst::FCMP_UGT); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
287 add_binary_fcmp (scalar, octave_value::op_ne, llvm::CmpInst::FCMP_UNE); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
288 |
14903 | 289 // now for printing functions |
290 add_print (any, reinterpret_cast<void*> (&octave_jit_print_any)); | |
291 add_print (scalar, reinterpret_cast<void*> (&octave_jit_print_double)); | |
14906 | 292 |
293 // bounds check for for loop | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
294 fn = create_function ("octave_jit_simple_for_range", boolean, range, index); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
295 llvm::BasicBlock *body = llvm::BasicBlock::Create (ctx, "body", fn); |
14906 | 296 builder.SetInsertPoint (body); |
297 { | |
298 llvm::Value *nelem | |
299 = builder.CreateExtractValue (fn->arg_begin (), 3); | |
300 // llvm::Value *idx = builder.CreateLoad (++fn->arg_begin ()); | |
301 llvm::Value *idx = ++fn->arg_begin (); | |
302 llvm::Value *ret = builder.CreateICmpULT (idx, nelem); | |
303 builder.CreateRet (ret); | |
304 } | |
305 llvm::verifyFunction (*fn); | |
306 simple_for_check.add_overload (fn, false, boolean, range, index); | |
307 | |
308 // increment for for loop | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
309 fn = create_function ("octave_jit_imple_for_range_incr", index, index); |
14906 | 310 body = llvm::BasicBlock::Create (ctx, "body", fn); |
311 builder.SetInsertPoint (body); | |
312 { | |
313 llvm::Value *one = llvm::ConstantInt::get (index_t, 1); | |
314 llvm::Value *idx = fn->arg_begin (); | |
315 llvm::Value *ret = builder.CreateAdd (idx, one); | |
316 builder.CreateRet (ret); | |
317 } | |
318 llvm::verifyFunction (*fn); | |
319 simple_for_incr.add_overload (fn, false, index, index); | |
320 | |
321 // index variabe for for loop | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
322 fn = create_function ("octave_jit_simple_for_idx", scalar, range, index); |
14906 | 323 body = llvm::BasicBlock::Create (ctx, "body", fn); |
324 builder.SetInsertPoint (body); | |
325 { | |
326 llvm::Value *idx = ++fn->arg_begin (); | |
327 llvm::Value *didx = builder.CreateUIToFP (idx, dbl); | |
328 llvm::Value *rng = fn->arg_begin (); | |
329 llvm::Value *base = builder.CreateExtractValue (rng, 0); | |
330 llvm::Value *inc = builder.CreateExtractValue (rng, 2); | |
331 | |
332 llvm::Value *ret = builder.CreateFMul (didx, inc); | |
333 ret = builder.CreateFAdd (base, ret); | |
334 builder.CreateRet (ret); | |
335 } | |
336 llvm::verifyFunction (*fn); | |
337 simple_for_index.add_overload (fn, false, scalar, range, index); | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
338 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
339 // logically true |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
340 // FIXME: Check for NaN |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
341 fn = create_function ("octave_logically_true_scalar", boolean, scalar); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
342 body = llvm::BasicBlock::Create (ctx, "body", fn); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
343 builder.SetInsertPoint (body); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
344 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
345 llvm::Value *zero = llvm::ConstantFP::get (scalar->to_llvm (), 0); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
346 llvm::Value *ret = builder.CreateFCmpUNE (fn->arg_begin (), zero); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
347 builder.CreateRet (ret); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
348 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
349 llvm::verifyFunction (*fn); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
350 logically_true.add_overload (fn, true, boolean, scalar); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
351 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
352 fn = create_function ("octave_logically_true_bool", boolean, boolean); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
353 body = llvm::BasicBlock::Create (ctx, "body", fn); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
354 builder.SetInsertPoint (body); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
355 builder.CreateRet (fn->arg_begin ()); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
356 llvm::verifyFunction (*fn); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
357 logically_true.add_overload (fn, false, boolean, boolean); |
14903 | 358 } |
359 | |
360 void | |
361 jit_typeinfo::add_print (jit_type *ty, void *call) | |
362 { | |
363 std::stringstream name; | |
364 name << "octave_jit_print_" << ty->name (); | |
365 | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
366 llvm::LLVMContext &ctx = llvm::getGlobalContext (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
367 llvm::Type *void_t = llvm::Type::getVoidTy (ctx); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
368 llvm::Function *fn = create_function (name.str (), void_t, |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
369 llvm::Type::getInt8PtrTy (ctx), |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
370 ty->to_llvm ()); |
14903 | 371 engine->addGlobalMapping (fn, call); |
372 | |
373 jit_function::overload ol (fn, false, 0, ty); | |
374 print_fn.add_overload (ol); | |
375 } | |
376 | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
377 // FIXME: cp between add_binary_op, add_binary_icmp, and add_binary_fcmp |
14903 | 378 void |
379 jit_typeinfo::add_binary_op (jit_type *ty, int op, int llvm_op) | |
380 { | |
381 std::stringstream fname; | |
382 octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op); | |
383 fname << "octave_jit_" << octave_value::binary_op_as_string (ov_op) | |
384 << "_" << ty->name (); | |
14906 | 385 |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
386 llvm::LLVMContext &ctx = llvm::getGlobalContext (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
387 llvm::Function *fn = create_function (fname.str (), ty, ty, ty); |
14903 | 388 llvm::BasicBlock *block = llvm::BasicBlock::Create (ctx, "body", fn); |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
389 builder.SetInsertPoint (block); |
14903 | 390 llvm::Instruction::BinaryOps temp |
391 = static_cast<llvm::Instruction::BinaryOps>(llvm_op); | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
392 llvm::Value *ret = builder.CreateBinOp (temp, fn->arg_begin (), |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
393 ++fn->arg_begin ()); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
394 builder.CreateRet (ret); |
14903 | 395 llvm::verifyFunction (*fn); |
396 | |
397 jit_function::overload ol(fn, false, ty, ty, ty); | |
398 binary_ops[op].add_overload (ol); | |
399 } | |
400 | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
401 void |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
402 jit_typeinfo::add_binary_icmp (jit_type *ty, int op, int llvm_op) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
403 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
404 std::stringstream fname; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
405 octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
406 fname << "octave_jit" << octave_value::binary_op_as_string (ov_op) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
407 << "_" << ty->name (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
408 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
409 llvm::LLVMContext &ctx = llvm::getGlobalContext (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
410 llvm::Function *fn = create_function (fname.str (), boolean, ty, ty); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
411 llvm::BasicBlock *block = llvm::BasicBlock::Create (ctx, "body", fn); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
412 builder.SetInsertPoint (block); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
413 llvm::CmpInst::Predicate temp |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
414 = static_cast<llvm::CmpInst::Predicate>(llvm_op); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
415 llvm::Value *ret = builder.CreateICmp (temp, fn->arg_begin (), |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
416 ++fn->arg_begin ()); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
417 builder.CreateRet (ret); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
418 llvm::verifyFunction (*fn); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
419 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
420 jit_function::overload ol (fn, false, boolean, ty, ty); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
421 binary_ops[op].add_overload (ol); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
422 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
423 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
424 void |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
425 jit_typeinfo::add_binary_fcmp (jit_type *ty, int op, int llvm_op) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
426 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
427 std::stringstream fname; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
428 octave_value::binary_op ov_op = static_cast<octave_value::binary_op>(op); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
429 fname << "octave_jit" << octave_value::binary_op_as_string (ov_op) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
430 << "_" << ty->name (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
431 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
432 llvm::LLVMContext &ctx = llvm::getGlobalContext (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
433 llvm::Function *fn = create_function (fname.str (), boolean, ty, ty); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
434 llvm::BasicBlock *block = llvm::BasicBlock::Create (ctx, "body", fn); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
435 builder.SetInsertPoint (block); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
436 llvm::CmpInst::Predicate temp |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
437 = static_cast<llvm::CmpInst::Predicate>(llvm_op); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
438 llvm::Value *ret = builder.CreateFCmp (temp, fn->arg_begin (), |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
439 ++fn->arg_begin ()); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
440 builder.CreateRet (ret); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
441 llvm::verifyFunction (*fn); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
442 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
443 jit_function::overload ol (fn, false, boolean, ty, ty); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
444 binary_ops[op].add_overload (ol); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
445 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
446 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
447 llvm::Function * |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
448 jit_typeinfo::create_function (const llvm::Twine& name, llvm::Type *ret, |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
449 const std::vector<llvm::Type *>& args) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
450 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
451 llvm::FunctionType *ft = llvm::FunctionType::get (ret, args, false); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
452 llvm::Function *fn = llvm::Function::Create (ft, |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
453 llvm::Function::ExternalLinkage, |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
454 name, module); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
455 fn->addFnAttr (llvm::Attribute::AlwaysInline); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
456 return fn; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
457 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
458 |
14903 | 459 jit_type* |
460 jit_typeinfo::type_of (const octave_value &ov) const | |
461 { | |
462 if (ov.is_undefined () || ov.is_function ()) | |
463 return 0; | |
464 | |
465 if (ov.is_double_type () && ov.is_real_scalar ()) | |
466 return get_scalar (); | |
467 | |
14906 | 468 if (ov.is_range ()) |
469 return get_range (); | |
470 | |
14903 | 471 return get_any (); |
472 } | |
473 | |
474 const jit_function& | |
475 jit_typeinfo::binary_op (int op) const | |
476 { | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
477 assert (static_cast<size_t>(op) < binary_ops.size ()); |
14903 | 478 return binary_ops[op]; |
479 } | |
480 | |
481 const jit_function::overload& | |
482 jit_typeinfo::print_value (jit_type *to_print) const | |
483 { | |
484 return print_fn.get_overload (to_print); | |
485 } | |
486 | |
487 void | |
488 jit_typeinfo::to_generic (jit_type *type, llvm::GenericValue& gv) | |
489 { | |
490 if (type == any) | |
491 to_generic (type, gv, octave_value ()); | |
492 else if (type == scalar) | |
493 to_generic (type, gv, octave_value (0)); | |
14906 | 494 else if (type == range) |
495 to_generic (type, gv, octave_value (Range ())); | |
14903 | 496 else |
497 assert (false && "Type not supported yet"); | |
498 } | |
499 | |
500 void | |
501 jit_typeinfo::to_generic (jit_type *type, llvm::GenericValue& gv, octave_value ov) | |
502 { | |
503 if (type == any) | |
504 { | |
505 octave_base_value *obv = ov.internal_rep (); | |
506 obv->grab (); | |
14910
a8f1e08de8fc
Simplified llvm::GenericValue creation
Max Brister <max@2bass.com>
parents:
14906
diff
changeset
|
507 ov_out.push_back (obv); |
a8f1e08de8fc
Simplified llvm::GenericValue creation
Max Brister <max@2bass.com>
parents:
14906
diff
changeset
|
508 gv.PointerVal = &ov_out.back (); |
14906 | 509 } |
510 else if (type == scalar) | |
511 { | |
14910
a8f1e08de8fc
Simplified llvm::GenericValue creation
Max Brister <max@2bass.com>
parents:
14906
diff
changeset
|
512 scalar_out.push_back (ov.double_value ()); |
a8f1e08de8fc
Simplified llvm::GenericValue creation
Max Brister <max@2bass.com>
parents:
14906
diff
changeset
|
513 gv.PointerVal = &scalar_out.back (); |
14906 | 514 } |
515 else if (type == range) | |
516 { | |
14910
a8f1e08de8fc
Simplified llvm::GenericValue creation
Max Brister <max@2bass.com>
parents:
14906
diff
changeset
|
517 range_out.push_back (ov.range_value ()); |
a8f1e08de8fc
Simplified llvm::GenericValue creation
Max Brister <max@2bass.com>
parents:
14906
diff
changeset
|
518 gv.PointerVal = &range_out.back (); |
14903 | 519 } |
520 else | |
14906 | 521 assert (false && "Type not supported yet"); |
14903 | 522 } |
523 | |
524 octave_value | |
525 jit_typeinfo::to_octave_value (jit_type *type, llvm::GenericValue& gv) | |
526 { | |
527 if (type == any) | |
528 { | |
14906 | 529 octave_base_value **ptr = reinterpret_cast<octave_base_value **>(gv.PointerVal); |
14903 | 530 return octave_value (*ptr); |
531 } | |
532 else if (type == scalar) | |
533 { | |
14906 | 534 double *ptr = reinterpret_cast<double *>(gv.PointerVal); |
14903 | 535 return octave_value (*ptr); |
536 } | |
14906 | 537 else if (type == range) |
538 { | |
539 jit_range *ptr = reinterpret_cast<jit_range *>(gv.PointerVal); | |
540 Range rng = *ptr; | |
541 return octave_value (rng); | |
542 } | |
14903 | 543 else |
544 assert (false && "Type not supported yet"); | |
545 } | |
546 | |
547 void | |
14910
a8f1e08de8fc
Simplified llvm::GenericValue creation
Max Brister <max@2bass.com>
parents:
14906
diff
changeset
|
548 jit_typeinfo::reset_generic (void) |
14903 | 549 { |
14910
a8f1e08de8fc
Simplified llvm::GenericValue creation
Max Brister <max@2bass.com>
parents:
14906
diff
changeset
|
550 scalar_out.clear (); |
a8f1e08de8fc
Simplified llvm::GenericValue creation
Max Brister <max@2bass.com>
parents:
14906
diff
changeset
|
551 ov_out.clear (); |
a8f1e08de8fc
Simplified llvm::GenericValue creation
Max Brister <max@2bass.com>
parents:
14906
diff
changeset
|
552 range_out.clear (); |
14903 | 553 } |
554 | |
555 jit_type* | |
556 jit_typeinfo::new_type (const std::string& name, bool force_init, | |
557 jit_type *parent, llvm::Type *llvm_type) | |
558 { | |
559 jit_type *ret = new jit_type (name, force_init, parent, llvm_type, next_id++); | |
560 id_to_type.push_back (ret); | |
561 return ret; | |
562 } | |
563 | |
14906 | 564 // -------------------- jit_infer -------------------- |
565 void | |
566 jit_infer::infer (tree_simple_for_command& cmd, jit_type *bounds) | |
14899 | 567 { |
14906 | 568 infer_simple_for (cmd, bounds); |
14903 | 569 } |
570 | |
571 void | |
14906 | 572 jit_infer::visit_anon_fcn_handle (tree_anon_fcn_handle&) |
14903 | 573 { |
574 fail (); | |
575 } | |
576 | |
577 void | |
14906 | 578 jit_infer::visit_argument_list (tree_argument_list&) |
14903 | 579 { |
580 fail (); | |
581 } | |
582 | |
583 void | |
14906 | 584 jit_infer::visit_binary_expression (tree_binary_expression& be) |
14903 | 585 { |
586 if (is_lvalue) | |
587 fail (); | |
588 | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
589 if (be.op_type () >= octave_value::num_binary_ops) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
590 fail (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
591 |
14903 | 592 tree_expression *lhs = be.lhs (); |
593 lhs->accept (*this); | |
594 jit_type *tlhs = type_stack.back (); | |
595 type_stack.pop_back (); | |
596 | |
597 tree_expression *rhs = be.rhs (); | |
598 rhs->accept (*this); | |
599 jit_type *trhs = type_stack.back (); | |
600 | |
601 jit_type *result = tinfo->binary_op_result (be.op_type (), tlhs, trhs); | |
602 if (! result) | |
603 fail (); | |
604 | |
605 type_stack.push_back (result); | |
606 } | |
607 | |
608 void | |
14906 | 609 jit_infer::visit_break_command (tree_break_command&) |
14903 | 610 { |
611 fail (); | |
612 } | |
613 | |
614 void | |
14906 | 615 jit_infer::visit_colon_expression (tree_colon_expression&) |
14903 | 616 { |
617 fail (); | |
618 } | |
619 | |
620 void | |
14906 | 621 jit_infer::visit_continue_command (tree_continue_command&) |
14903 | 622 { |
623 fail (); | |
624 } | |
625 | |
626 void | |
14906 | 627 jit_infer::visit_global_command (tree_global_command&) |
14903 | 628 { |
629 fail (); | |
630 } | |
631 | |
632 void | |
14906 | 633 jit_infer::visit_persistent_command (tree_persistent_command&) |
14903 | 634 { |
635 fail (); | |
636 } | |
637 | |
638 void | |
14906 | 639 jit_infer::visit_decl_elt (tree_decl_elt&) |
14903 | 640 { |
641 fail (); | |
642 } | |
14899 | 643 |
14903 | 644 void |
14906 | 645 jit_infer::visit_decl_init_list (tree_decl_init_list&) |
14903 | 646 { |
647 fail (); | |
648 } | |
649 | |
650 void | |
14906 | 651 jit_infer::visit_simple_for_command (tree_simple_for_command& cmd) |
652 { | |
653 tree_expression *control = cmd.control_expr (); | |
654 control->accept (*this); | |
655 | |
656 jit_type *control_t = type_stack.back (); | |
657 type_stack.pop_back (); | |
658 | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
659 // FIXME: We should improve type inference so we don't have to do this |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
660 // to generate nested for loop code |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
661 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
662 // quick hack, check if the for loop bounds are const. If we |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
663 // run at least one, we don't have to merge types |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
664 bool atleast_once = false; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
665 if (control->is_constant ()) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
666 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
667 octave_value over = control->rvalue1 (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
668 if (over.is_range ()) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
669 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
670 Range rng = over.range_value (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
671 atleast_once = rng.nelem () > 0; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
672 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
673 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
674 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
675 if (atleast_once) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
676 infer_simple_for (cmd, control_t); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
677 else |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
678 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
679 type_map fallthrough = types; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
680 infer_simple_for (cmd, control_t); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
681 merge (types, fallthrough); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
682 } |
14906 | 683 } |
684 | |
685 void | |
686 jit_infer::visit_complex_for_command (tree_complex_for_command&) | |
14903 | 687 { |
688 fail (); | |
689 } | |
690 | |
691 void | |
14906 | 692 jit_infer::visit_octave_user_script (octave_user_script&) |
14903 | 693 { |
694 fail (); | |
695 } | |
696 | |
697 void | |
14906 | 698 jit_infer::visit_octave_user_function (octave_user_function&) |
14903 | 699 { |
700 fail (); | |
701 } | |
702 | |
703 void | |
14906 | 704 jit_infer::visit_octave_user_function_header (octave_user_function&) |
14903 | 705 { |
706 fail (); | |
707 } | |
708 | |
709 void | |
14906 | 710 jit_infer::visit_octave_user_function_trailer (octave_user_function&) |
14903 | 711 { |
712 fail (); | |
713 } | |
714 | |
715 void | |
14906 | 716 jit_infer::visit_function_def (tree_function_def&) |
14903 | 717 { |
718 fail (); | |
719 } | |
720 | |
721 void | |
14906 | 722 jit_infer::visit_identifier (tree_identifier& ti) |
14903 | 723 { |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
724 symbol_table::symbol_record_ref record = ti.symbol (); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
725 handle_identifier (record); |
14903 | 726 } |
14899 | 727 |
14903 | 728 void |
14906 | 729 jit_infer::visit_if_clause (tree_if_clause&) |
14903 | 730 { |
731 fail (); | |
732 } | |
733 | |
734 void | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
735 jit_infer::visit_if_command (tree_if_command& cmd) |
14903 | 736 { |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
737 if (is_lvalue) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
738 fail (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
739 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
740 tree_if_command_list *lst = cmd.cmd_list (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
741 assert (lst); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
742 lst->accept (*this); |
14903 | 743 } |
744 | |
745 void | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
746 jit_infer::visit_if_command_list (tree_if_command_list& lst) |
14903 | 747 { |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
748 // determine the types on each branch of the if seperatly, then merge |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
749 type_map fallthrough = types, last; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
750 bool first_time = true; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
751 for (tree_if_command_list::iterator p = lst.begin (); p != lst.end(); ++p) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
752 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
753 tree_if_clause *tic = *p; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
754 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
755 if (! first_time) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
756 types = fallthrough; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
757 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
758 if (! tic->is_else_clause ()) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
759 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
760 tree_expression *expr = tic->condition (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
761 expr->accept (*this); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
762 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
763 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
764 fallthrough = types; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
765 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
766 tree_statement_list *stmt_lst = tic->commands (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
767 assert (stmt_lst); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
768 stmt_lst->accept (*this); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
769 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
770 if (first_time) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
771 last = types; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
772 else |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
773 merge (last, types); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
774 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
775 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
776 types = last; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
777 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
778 tree_if_clause *last_clause = lst.back (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
779 if (! last_clause->is_else_clause ()) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
780 merge (types, fallthrough); |
14903 | 781 } |
782 | |
783 void | |
14906 | 784 jit_infer::visit_index_expression (tree_index_expression&) |
14903 | 785 { |
786 fail (); | |
787 } | |
788 | |
789 void | |
14906 | 790 jit_infer::visit_matrix (tree_matrix&) |
14903 | 791 { |
792 fail (); | |
793 } | |
794 | |
795 void | |
14906 | 796 jit_infer::visit_cell (tree_cell&) |
14903 | 797 { |
798 fail (); | |
799 } | |
800 | |
801 void | |
14906 | 802 jit_infer::visit_multi_assignment (tree_multi_assignment&) |
14903 | 803 { |
804 fail (); | |
805 } | |
806 | |
807 void | |
14906 | 808 jit_infer::visit_no_op_command (tree_no_op_command&) |
14903 | 809 { |
810 fail (); | |
811 } | |
812 | |
813 void | |
14906 | 814 jit_infer::visit_constant (tree_constant& tc) |
14903 | 815 { |
816 if (is_lvalue) | |
817 fail (); | |
818 | |
819 octave_value v = tc.rvalue1 (); | |
820 jit_type *type = tinfo->type_of (v); | |
821 if (! type) | |
822 fail (); | |
823 | |
824 type_stack.push_back (type); | |
14899 | 825 } |
826 | |
14903 | 827 void |
14906 | 828 jit_infer::visit_fcn_handle (tree_fcn_handle&) |
14903 | 829 { |
830 fail (); | |
831 } | |
832 | |
833 void | |
14906 | 834 jit_infer::visit_parameter_list (tree_parameter_list&) |
14903 | 835 { |
836 fail (); | |
837 } | |
838 | |
839 void | |
14906 | 840 jit_infer::visit_postfix_expression (tree_postfix_expression&) |
14903 | 841 { |
842 fail (); | |
843 } | |
844 | |
845 void | |
14906 | 846 jit_infer::visit_prefix_expression (tree_prefix_expression&) |
14903 | 847 { |
848 fail (); | |
849 } | |
850 | |
851 void | |
14906 | 852 jit_infer::visit_return_command (tree_return_command&) |
14903 | 853 { |
854 fail (); | |
855 } | |
856 | |
857 void | |
14906 | 858 jit_infer::visit_return_list (tree_return_list&) |
14903 | 859 { |
860 fail (); | |
861 } | |
862 | |
863 void | |
14906 | 864 jit_infer::visit_simple_assignment (tree_simple_assignment& tsa) |
14903 | 865 { |
866 if (is_lvalue) | |
867 fail (); | |
868 | |
869 // resolve rhs | |
870 is_lvalue = false; | |
871 tree_expression *rhs = tsa.right_hand_side (); | |
872 rhs->accept (*this); | |
873 | |
874 jit_type *trhs = type_stack.back (); | |
875 type_stack.pop_back (); | |
876 | |
877 // resolve lhs | |
878 is_lvalue = true; | |
879 rvalue_type = trhs; | |
880 tree_expression *lhs = tsa.left_hand_side (); | |
881 lhs->accept (*this); | |
882 | |
883 // we don't pop back here, as the resulting type should be the rhs type | |
884 // which is equal to the lhs type anways | |
885 jit_type *tlhs = type_stack.back (); | |
886 if (tlhs != trhs) | |
887 fail (); | |
888 | |
889 is_lvalue = false; | |
890 rvalue_type = 0; | |
891 } | |
892 | |
893 void | |
14906 | 894 jit_infer::visit_statement (tree_statement& stmt) |
14899 | 895 { |
14903 | 896 if (is_lvalue) |
897 fail (); | |
898 | |
899 tree_command *cmd = stmt.command (); | |
900 tree_expression *expr = stmt.expression (); | |
901 | |
902 if (cmd) | |
903 cmd->accept (*this); | |
904 else | |
905 { | |
906 // ok, this check for ans appears three times as cp | |
907 bool do_bind_ans = false; | |
908 | |
909 if (expr->is_identifier ()) | |
910 { | |
911 tree_identifier *id = dynamic_cast<tree_identifier *> (expr); | |
912 | |
913 do_bind_ans = (! id->is_variable ()); | |
914 } | |
915 else | |
916 do_bind_ans = (! expr->is_assignment_expression ()); | |
917 | |
918 expr->accept (*this); | |
919 | |
920 if (do_bind_ans) | |
921 { | |
922 is_lvalue = true; | |
923 rvalue_type = type_stack.back (); | |
924 type_stack.pop_back (); | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
925 |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
926 symbol_table::symbol_record_ref record (symbol_table::insert ("ans")); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
927 handle_identifier (record); |
14903 | 928 |
929 if (rvalue_type != type_stack.back ()) | |
930 fail (); | |
931 | |
932 is_lvalue = false; | |
933 rvalue_type = 0; | |
934 } | |
935 | |
936 type_stack.pop_back (); | |
937 } | |
938 } | |
939 | |
940 void | |
14906 | 941 jit_infer::visit_statement_list (tree_statement_list& lst) |
942 { | |
943 tree_statement_list::iterator iter; | |
944 for (iter = lst.begin (); iter != lst.end (); ++iter) | |
945 { | |
946 tree_statement *stmt = *iter; | |
947 assert (stmt); // FIXME: jwe can this be null? | |
948 stmt->accept (*this); | |
949 } | |
950 } | |
951 | |
952 void | |
953 jit_infer::visit_switch_case (tree_switch_case&) | |
14903 | 954 { |
955 fail (); | |
956 } | |
957 | |
958 void | |
14906 | 959 jit_infer::visit_switch_case_list (tree_switch_case_list&) |
14903 | 960 { |
961 fail (); | |
962 } | |
963 | |
964 void | |
14906 | 965 jit_infer::visit_switch_command (tree_switch_command&) |
14903 | 966 { |
967 fail (); | |
968 } | |
969 | |
970 void | |
14906 | 971 jit_infer::visit_try_catch_command (tree_try_catch_command&) |
14903 | 972 { |
973 fail (); | |
974 } | |
975 | |
976 void | |
14906 | 977 jit_infer::visit_unwind_protect_command (tree_unwind_protect_command&) |
14903 | 978 { |
979 fail (); | |
980 } | |
981 | |
982 void | |
14906 | 983 jit_infer::visit_while_command (tree_while_command&) |
984 { | |
985 fail (); | |
986 } | |
987 | |
988 void | |
989 jit_infer::visit_do_until_command (tree_do_until_command&) | |
14903 | 990 { |
991 fail (); | |
992 } | |
993 | |
994 void | |
14906 | 995 jit_infer::infer_simple_for (tree_simple_for_command& cmd, |
996 jit_type *bounds) | |
14903 | 997 { |
14906 | 998 if (is_lvalue) |
999 fail (); | |
1000 | |
1001 jit_type *iter = tinfo->get_simple_for_index_result (bounds); | |
1002 if (! iter) | |
1003 fail (); | |
1004 | |
1005 is_lvalue = true; | |
1006 rvalue_type = iter; | |
1007 tree_expression *lhs = cmd.left_hand_side (); | |
1008 lhs->accept (*this); | |
1009 if (type_stack.back () != iter) | |
1010 fail (); | |
1011 type_stack.pop_back (); | |
1012 is_lvalue = false; | |
1013 rvalue_type = 0; | |
1014 | |
1015 tree_statement_list *body = cmd.body (); | |
1016 body->accept (*this); | |
14903 | 1017 } |
1018 | |
1019 void | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1020 jit_infer::handle_identifier (const symbol_table::symbol_record_ref& record) |
14903 | 1021 { |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1022 type_map::iterator iter = types.find (record); |
14903 | 1023 if (iter == types.end ()) |
1024 { | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1025 jit_type *ty = tinfo->type_of (record->find ()); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1026 bool argin = false; |
14903 | 1027 if (is_lvalue) |
1028 { | |
1029 if (! ty) | |
1030 ty = rvalue_type; | |
1031 } | |
1032 else | |
1033 { | |
1034 if (! ty) | |
1035 fail (); | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1036 argin = true; |
14903 | 1037 } |
1038 | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1039 types[record] = type_entry (argin, ty); |
14903 | 1040 type_stack.push_back (ty); |
1041 } | |
1042 else | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1043 type_stack.push_back (iter->second.second); |
14903 | 1044 } |
1045 | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1046 void |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1047 jit_infer::merge (type_map& dest, const type_map& src) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1048 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1049 if (dest.size () != src.size ()) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1050 fail (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1051 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1052 type_map::iterator dest_iter; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1053 type_map::const_iterator src_iter; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1054 for (dest_iter = dest.begin (), src_iter = src.begin (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1055 dest_iter != dest.end (); ++dest_iter, ++src_iter) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1056 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1057 if (dest_iter->first.name () != src_iter->first.name () |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1058 || dest_iter->second.second != src_iter->second.second) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1059 fail (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1060 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1061 // require argin if one path requires argin |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1062 dest_iter->second.first = dest_iter->second.first |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1063 || src_iter->second.first; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1064 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1065 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1066 |
14906 | 1067 // -------------------- jit_generator -------------------- |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1068 jit_generator::jit_generator (jit_typeinfo *ti, llvm::Module *mod, |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1069 tree_simple_for_command& cmd, jit_type *bounds, |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1070 const type_map& infered_types) |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1071 : tinfo (ti), module (mod), is_lvalue (false) |
14903 | 1072 { |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1073 // create new vectors that include bounds |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1074 std::vector<std::string> names (infered_types.size () + 1); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1075 std::vector<bool> argin (infered_types.size () + 1); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1076 std::vector<jit_type *> types (infered_types.size () + 1); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1077 names[0] = "#bounds"; |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1078 argin[0] = true; |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1079 types[0] = bounds; |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1080 size_t i; |
14903 | 1081 type_map::const_iterator iter; |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1082 for (i = 1, iter = infered_types.begin (); iter != infered_types.end (); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1083 ++i, ++iter) |
14903 | 1084 { |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1085 names[i] = iter->first.name (); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1086 argin[i] = iter->second.first; |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1087 types[i] = iter->second.second; |
14903 | 1088 } |
1089 | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1090 initialize (names, argin, types); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1091 |
14899 | 1092 try |
1093 { | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1094 value var_bounds = variables["#bounds"]; |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1095 var_bounds.second = builder.CreateLoad (var_bounds.second); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1096 emit_simple_for (cmd, var_bounds, true); |
14899 | 1097 } |
1098 catch (const jit_fail_exception&) | |
1099 { | |
14903 | 1100 function->eraseFromParent (); |
1101 function = 0; | |
1102 return; | |
14899 | 1103 } |
1104 | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1105 finalize (names); |
14899 | 1106 } |
1107 | |
14903 | 1108 void |
14906 | 1109 jit_generator::visit_anon_fcn_handle (tree_anon_fcn_handle&) |
14899 | 1110 { |
14903 | 1111 fail (); |
1112 } | |
14899 | 1113 |
14903 | 1114 void |
14906 | 1115 jit_generator::visit_argument_list (tree_argument_list&) |
14903 | 1116 { |
1117 fail (); | |
14899 | 1118 } |
1119 | |
1120 void | |
14906 | 1121 jit_generator::visit_binary_expression (tree_binary_expression& be) |
14899 | 1122 { |
14903 | 1123 tree_expression *lhs = be.lhs (); |
1124 lhs->accept (*this); | |
1125 value lhsv = value_stack.back (); | |
1126 value_stack.pop_back (); | |
1127 | |
1128 tree_expression *rhs = be.rhs (); | |
1129 rhs->accept (*this); | |
1130 value rhsv = value_stack.back (); | |
1131 value_stack.pop_back (); | |
1132 | |
1133 const jit_function::overload& ol | |
1134 = tinfo->binary_op_overload (be.op_type (), lhsv.first, rhsv.first); | |
14899 | 1135 |
14903 | 1136 if (! ol.function) |
1137 fail (); | |
1138 | |
1139 llvm::Value *result = builder.CreateCall2 (ol.function, lhsv.second, | |
1140 rhsv.second); | |
1141 push_value (ol.result, result); | |
1142 } | |
1143 | |
1144 void | |
14906 | 1145 jit_generator::visit_break_command (tree_break_command&) |
14903 | 1146 { |
1147 fail (); | |
14899 | 1148 } |
1149 | |
1150 void | |
14906 | 1151 jit_generator::visit_colon_expression (tree_colon_expression&) |
14903 | 1152 { |
1153 fail (); | |
1154 } | |
1155 | |
1156 void | |
14906 | 1157 jit_generator::visit_continue_command (tree_continue_command&) |
14899 | 1158 { |
14903 | 1159 fail (); |
1160 } | |
1161 | |
1162 void | |
14906 | 1163 jit_generator::visit_global_command (tree_global_command&) |
14903 | 1164 { |
1165 fail (); | |
14899 | 1166 } |
1167 | |
1168 void | |
14906 | 1169 jit_generator::visit_persistent_command (tree_persistent_command&) |
14903 | 1170 { |
1171 fail (); | |
1172 } | |
1173 | |
1174 void | |
14906 | 1175 jit_generator::visit_decl_elt (tree_decl_elt&) |
14903 | 1176 { |
1177 fail (); | |
1178 } | |
1179 | |
1180 void | |
14906 | 1181 jit_generator::visit_decl_init_list (tree_decl_init_list&) |
14903 | 1182 { |
1183 fail (); | |
1184 } | |
1185 | |
1186 void | |
14906 | 1187 jit_generator::visit_simple_for_command (tree_simple_for_command& cmd) |
14899 | 1188 { |
14906 | 1189 if (is_lvalue) |
1190 fail (); | |
1191 | |
1192 tree_expression *control = cmd.control_expr (); | |
1193 assert (control); // FIXME: jwe, can this be null? | |
1194 | |
1195 control->accept (*this); | |
1196 value over = value_stack.back (); | |
1197 value_stack.pop_back (); | |
1198 | |
1199 emit_simple_for (cmd, over, false); | |
14899 | 1200 } |
1201 | |
1202 void | |
14906 | 1203 jit_generator::visit_complex_for_command (tree_complex_for_command&) |
14903 | 1204 { |
1205 fail (); | |
1206 } | |
1207 | |
1208 void | |
14906 | 1209 jit_generator::visit_octave_user_script (octave_user_script&) |
14903 | 1210 { |
1211 fail (); | |
1212 } | |
1213 | |
1214 void | |
14906 | 1215 jit_generator::visit_octave_user_function (octave_user_function&) |
14903 | 1216 { |
1217 fail (); | |
1218 } | |
1219 | |
1220 void | |
14906 | 1221 jit_generator::visit_octave_user_function_header (octave_user_function&) |
14903 | 1222 { |
1223 fail (); | |
1224 } | |
1225 | |
1226 void | |
14906 | 1227 jit_generator::visit_octave_user_function_trailer (octave_user_function&) |
14899 | 1228 { |
1229 fail (); | |
1230 } | |
1231 | |
1232 void | |
14906 | 1233 jit_generator::visit_function_def (tree_function_def&) |
1234 { | |
1235 fail (); | |
1236 } | |
1237 | |
1238 void | |
1239 jit_generator::visit_identifier (tree_identifier& ti) | |
14899 | 1240 { |
14903 | 1241 std::string name = ti.name (); |
1242 value variable = variables[name]; | |
1243 if (is_lvalue) | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1244 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1245 value_stack.push_back (variable); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1246 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1247 const jit_function::overload& ol = tinfo->release (variable.first); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1248 if (ol.function) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1249 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1250 llvm::Value *load = builder.CreateLoad (variable.second, name); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1251 builder.CreateCall (ol.function, load); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1252 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1253 } |
14903 | 1254 else |
14899 | 1255 { |
14903 | 1256 llvm::Value *load = builder.CreateLoad (variable.second, name); |
1257 push_value (variable.first, load); | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1258 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1259 const jit_function::overload& ol = tinfo->grab (variable.first); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1260 if (ol.function) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1261 builder.CreateCall (ol.function, load); |
14903 | 1262 } |
1263 } | |
1264 | |
1265 void | |
14906 | 1266 jit_generator::visit_if_clause (tree_if_clause&) |
1267 { | |
1268 fail (); | |
1269 } | |
1270 | |
1271 void | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1272 jit_generator::visit_if_command (tree_if_command& cmd) |
14903 | 1273 { |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1274 tree_if_command_list *lst = cmd.cmd_list (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1275 assert (lst); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1276 lst->accept (*this); |
14903 | 1277 } |
14899 | 1278 |
14903 | 1279 void |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1280 jit_generator::visit_if_command_list (tree_if_command_list& lst) |
14903 | 1281 { |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1282 llvm::LLVMContext &ctx = llvm::getGlobalContext (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1283 llvm::BasicBlock *tail = llvm::BasicBlock::Create (ctx, "if_tail", function); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1284 std::vector<llvm::BasicBlock *> clause_entry (lst.size ()); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1285 tree_if_command_list::iterator p; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1286 size_t i; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1287 for (p = lst.begin (), i = 0; p != lst.end (); ++p, ++i) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1288 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1289 tree_if_clause *tic = *p; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1290 if (tic->is_else_clause ()) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1291 clause_entry[i] = llvm::BasicBlock::Create (ctx, "else_body", function, |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1292 tail); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1293 else |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1294 clause_entry[i] = llvm::BasicBlock::Create (ctx, "if_cond", function, |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1295 tail); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1296 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1297 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1298 builder.CreateBr (clause_entry[0]); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1299 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1300 for (p = lst.begin (), i = 0; p != lst.end (); ++p, ++i) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1301 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1302 tree_if_clause *tic = *p; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1303 llvm::BasicBlock *body; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1304 if (tic->is_else_clause ()) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1305 body = clause_entry[i]; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1306 else |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1307 { |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1308 llvm::BasicBlock *cond = clause_entry[i]; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1309 builder.SetInsertPoint (cond); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1310 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1311 tree_expression *expr = tic->condition (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1312 expr->accept (*this); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1313 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1314 // FIXME: Handle undefined case |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1315 value condv = value_stack.back (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1316 value_stack.pop_back (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1317 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1318 const jit_function::overload& ol = tinfo->get_logically_true (condv.first); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1319 if (! ol.function) |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1320 fail (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1321 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1322 bool last = i + 1 == clause_entry.size (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1323 llvm::BasicBlock *next = last ? tail : clause_entry[i + 1]; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1324 body = llvm::BasicBlock::Create (ctx, "if_body", function, tail); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1325 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1326 llvm::Value *is_true = builder.CreateCall (ol.function, condv.second); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1327 builder.CreateCondBr (is_true, body, next); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1328 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1329 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1330 tree_statement_list *stmt_lst = tic->commands (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1331 builder.SetInsertPoint (body); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1332 stmt_lst->accept (*this); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1333 builder.CreateBr (tail); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1334 } |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1335 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1336 builder.SetInsertPoint (tail); |
14903 | 1337 } |
14899 | 1338 |
14903 | 1339 void |
14906 | 1340 jit_generator::visit_index_expression (tree_index_expression&) |
14903 | 1341 { |
1342 fail (); | |
1343 } | |
14899 | 1344 |
14903 | 1345 void |
14906 | 1346 jit_generator::visit_matrix (tree_matrix&) |
1347 { | |
1348 fail (); | |
1349 } | |
1350 | |
1351 void | |
1352 jit_generator::visit_cell (tree_cell&) | |
14903 | 1353 { |
1354 fail (); | |
1355 } | |
1356 | |
1357 void | |
14906 | 1358 jit_generator::visit_multi_assignment (tree_multi_assignment&) |
14903 | 1359 { |
1360 fail (); | |
1361 } | |
1362 | |
1363 void | |
14906 | 1364 jit_generator::visit_no_op_command (tree_no_op_command&) |
14903 | 1365 { |
1366 fail (); | |
1367 } | |
14899 | 1368 |
14903 | 1369 void |
14906 | 1370 jit_generator::visit_constant (tree_constant& tc) |
14903 | 1371 { |
1372 octave_value v = tc.rvalue1 (); | |
14906 | 1373 llvm::LLVMContext& ctx = llvm::getGlobalContext (); |
14903 | 1374 if (v.is_real_scalar () && v.is_double_type ()) |
1375 { | |
1376 double dv = v.double_value (); | |
1377 llvm::Value *lv = llvm::ConstantFP::get (ctx, llvm::APFloat (dv)); | |
1378 push_value (tinfo->get_scalar (), lv); | |
14899 | 1379 } |
14906 | 1380 else if (v.is_range ()) |
1381 { | |
1382 Range rng = v.range_value (); | |
1383 llvm::Type *range = tinfo->get_range_llvm (); | |
1384 llvm::Type *scalar = tinfo->get_scalar_llvm (); | |
1385 llvm::Type *index = tinfo->get_index_llvm (); | |
1386 | |
1387 std::vector<llvm::Constant *> values (4); | |
1388 values[0] = llvm::ConstantFP::get (scalar, rng.base ()); | |
1389 values[1] = llvm::ConstantFP::get (scalar, rng.limit ()); | |
1390 values[2] = llvm::ConstantFP::get (scalar, rng.inc ()); | |
1391 values[3] = llvm::ConstantInt::get (index, rng.nelem ()); | |
1392 | |
1393 llvm::StructType *llvm_range = llvm::cast<llvm::StructType>(range); | |
1394 llvm::Value *lv = llvm::ConstantStruct::get (llvm_range, values); | |
1395 push_value (tinfo->get_range (), lv); | |
1396 } | |
14899 | 1397 else |
1398 fail (); | |
1399 } | |
1400 | |
1401 void | |
14906 | 1402 jit_generator::visit_fcn_handle (tree_fcn_handle&) |
14899 | 1403 { |
1404 fail (); | |
1405 } | |
1406 | |
1407 void | |
14906 | 1408 jit_generator::visit_parameter_list (tree_parameter_list&) |
14899 | 1409 { |
1410 fail (); | |
1411 } | |
1412 | |
1413 void | |
14906 | 1414 jit_generator::visit_postfix_expression (tree_postfix_expression&) |
14899 | 1415 { |
1416 fail (); | |
1417 } | |
1418 | |
1419 void | |
14906 | 1420 jit_generator::visit_prefix_expression (tree_prefix_expression&) |
14899 | 1421 { |
1422 fail (); | |
1423 } | |
1424 | |
1425 void | |
14906 | 1426 jit_generator::visit_return_command (tree_return_command&) |
14899 | 1427 { |
1428 fail (); | |
1429 } | |
1430 | |
1431 void | |
14906 | 1432 jit_generator::visit_return_list (tree_return_list&) |
14899 | 1433 { |
1434 fail (); | |
1435 } | |
1436 | |
1437 void | |
14906 | 1438 jit_generator::visit_simple_assignment (tree_simple_assignment& tsa) |
14899 | 1439 { |
14903 | 1440 if (is_lvalue) |
14899 | 1441 fail (); |
14903 | 1442 |
1443 // resolve rhs | |
1444 tree_expression *rhs = tsa.right_hand_side (); | |
1445 rhs->accept (*this); | |
1446 | |
1447 value rhsv = value_stack.back (); | |
1448 value_stack.pop_back (); | |
14899 | 1449 |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1450 // resolve lhs |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1451 is_lvalue = true; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1452 tree_expression *lhs = tsa.left_hand_side (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1453 lhs->accept (*this); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1454 is_lvalue = false; |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1455 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1456 value lhsv = value_stack.back (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1457 value_stack.pop_back (); |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1458 |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1459 // do assign, then keep rhs as the result |
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1460 builder.CreateStore (rhsv.second, lhsv.second); |
14899 | 1461 |
14903 | 1462 if (tsa.print_result ()) |
1463 emit_print (lhs->name (), rhsv); | |
1464 | |
1465 value_stack.push_back (rhsv); | |
14899 | 1466 } |
1467 | |
1468 void | |
14906 | 1469 jit_generator::visit_statement (tree_statement& stmt) |
14899 | 1470 { |
1471 tree_command *cmd = stmt.command (); | |
1472 tree_expression *expr = stmt.expression (); | |
1473 | |
1474 if (cmd) | |
1475 cmd->accept (*this); | |
1476 else | |
1477 { | |
1478 // stolen from tree_evaluator::visit_statement | |
1479 bool do_bind_ans = false; | |
1480 | |
1481 if (expr->is_identifier ()) | |
1482 { | |
1483 tree_identifier *id = dynamic_cast<tree_identifier *> (expr); | |
1484 | |
1485 do_bind_ans = (! id->is_variable ()); | |
1486 } | |
1487 else | |
1488 do_bind_ans = (! expr->is_assignment_expression ()); | |
1489 | |
1490 expr->accept (*this); | |
1491 | |
1492 if (do_bind_ans) | |
1493 { | |
14903 | 1494 value rhs = value_stack.back (); |
1495 value ans = variables["ans"]; | |
1496 if (ans.first != rhs.first) | |
1497 fail (); | |
14899 | 1498 |
14903 | 1499 builder.CreateStore (rhs.second, ans.second); |
1500 | |
1501 if (expr->print_result ()) | |
1502 emit_print ("ans", rhs); | |
14899 | 1503 } |
1504 else if (expr->is_identifier () && expr->print_result ()) | |
1505 { | |
1506 // FIXME: ugly hack, we need to come up with a way to pass | |
1507 // nargout to visit_identifier | |
1508 emit_print (expr->name (), value_stack.back ()); | |
1509 } | |
1510 | |
1511 | |
1512 value_stack.pop_back (); | |
1513 } | |
1514 } | |
1515 | |
1516 void | |
14906 | 1517 jit_generator::visit_statement_list (tree_statement_list& lst) |
1518 { | |
1519 tree_statement_list::iterator iter; | |
1520 for (iter = lst.begin (); iter != lst.end (); ++iter) | |
1521 { | |
1522 tree_statement *stmt = *iter; | |
1523 assert (stmt); // FIXME: jwe can this be null? | |
1524 stmt->accept (*this); | |
1525 } | |
1526 } | |
1527 | |
1528 void | |
1529 jit_generator::visit_switch_case (tree_switch_case&) | |
1530 { | |
1531 fail (); | |
1532 } | |
1533 | |
1534 void | |
1535 jit_generator::visit_switch_case_list (tree_switch_case_list&) | |
14899 | 1536 { |
1537 fail (); | |
1538 } | |
1539 | |
1540 void | |
14906 | 1541 jit_generator::visit_switch_command (tree_switch_command&) |
1542 { | |
1543 fail (); | |
1544 } | |
1545 | |
1546 void | |
1547 jit_generator::visit_try_catch_command (tree_try_catch_command&) | |
14899 | 1548 { |
1549 fail (); | |
1550 } | |
1551 | |
1552 void | |
14906 | 1553 jit_generator::visit_unwind_protect_command (tree_unwind_protect_command&) |
14899 | 1554 { |
1555 fail (); | |
1556 } | |
1557 | |
1558 void | |
14906 | 1559 jit_generator::visit_while_command (tree_while_command&) |
1560 { | |
1561 fail (); | |
1562 } | |
1563 | |
1564 void | |
1565 jit_generator::visit_do_until_command (tree_do_until_command&) | |
14899 | 1566 { |
1567 fail (); | |
1568 } | |
1569 | |
1570 void | |
14906 | 1571 jit_generator::emit_simple_for (tree_simple_for_command& cmd, value over, |
1572 bool atleast_once) | |
14899 | 1573 { |
14906 | 1574 if (is_lvalue) |
1575 fail (); | |
1576 | |
1577 jit_type *index = tinfo->get_index (); | |
1578 llvm::Value *init_index = 0; | |
1579 if (over.first == tinfo->get_range ()) | |
1580 init_index = llvm::ConstantInt::get (index->to_llvm (), 0); | |
1581 else | |
1582 fail (); | |
1583 | |
1584 llvm::Value *llvm_index = builder.CreateAlloca (index->to_llvm (), 0, "index"); | |
1585 builder.CreateStore (init_index, llvm_index); | |
1586 | |
1587 // FIXME: Support break | |
1588 llvm::LLVMContext &ctx = llvm::getGlobalContext (); | |
1589 llvm::BasicBlock *body = llvm::BasicBlock::Create (ctx, "for_body", function); | |
1590 llvm::BasicBlock *cond_check = llvm::BasicBlock::Create (ctx, "for_check", function); | |
1591 llvm::BasicBlock *tail = llvm::BasicBlock::Create (ctx, "for_tail", function); | |
1592 | |
1593 // initialize the iter from the index | |
1594 if (atleast_once) | |
1595 builder.CreateBr (body); | |
1596 else | |
1597 builder.CreateBr (cond_check); | |
1598 | |
1599 builder.SetInsertPoint (body); | |
14899 | 1600 |
14906 | 1601 is_lvalue = true; |
1602 tree_expression *lhs = cmd.left_hand_side (); | |
1603 lhs->accept (*this); | |
1604 is_lvalue = false; | |
1605 | |
1606 value lhsv = value_stack.back (); | |
1607 value_stack.pop_back (); | |
1608 | |
1609 const jit_function::overload& index_ol = tinfo->get_simple_for_index (over.first); | |
1610 llvm::Value *lindex = builder.CreateLoad (llvm_index); | |
1611 llvm::Value *llvm_iter = builder.CreateCall2 (index_ol.function, over.second, lindex); | |
1612 value iter(index_ol.result, llvm_iter); | |
14915
cba58541954c
Add if support and fix leak with any
Max Brister <max@2bass.com>
parents:
14913
diff
changeset
|
1613 builder.CreateStore (iter.second, lhsv.second); |
14906 | 1614 |
1615 tree_statement_list *lst = cmd.body (); | |
1616 lst->accept (*this); | |
1617 | |
1618 llvm::Value *one = llvm::ConstantInt::get (index->to_llvm (), 1); | |
1619 lindex = builder.CreateLoad (llvm_index); | |
1620 lindex = builder.CreateAdd (lindex, one); | |
1621 builder.CreateStore (lindex, llvm_index); | |
1622 builder.CreateBr (cond_check); | |
1623 | |
1624 builder.SetInsertPoint (cond_check); | |
1625 lindex = builder.CreateLoad (llvm_index); | |
1626 const jit_function::overload& check_ol = tinfo->get_simple_for_check (over.first); | |
1627 llvm::Value *cond = builder.CreateCall2 (check_ol.function, over.second, lindex); | |
1628 builder.CreateCondBr (cond, body, tail); | |
1629 | |
1630 builder.SetInsertPoint (tail); | |
14899 | 1631 } |
1632 | |
1633 void | |
14906 | 1634 jit_generator::emit_print (const std::string& name, const value& v) |
14899 | 1635 { |
14903 | 1636 const jit_function::overload& ol = tinfo->print_value (v.first); |
1637 if (! ol.function) | |
1638 fail (); | |
1639 | |
1640 llvm::Value *str = builder.CreateGlobalStringPtr (name); | |
1641 builder.CreateCall2 (ol.function, str, v.second); | |
14899 | 1642 } |
1643 | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1644 void |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1645 jit_generator::initialize (const std::vector<std::string>& names, |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1646 const std::vector<bool>& argin, |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1647 const std::vector<jit_type *> types) |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1648 { |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1649 std::vector<llvm::Type *> arg_types (names.size ()); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1650 for (size_t i = 0; i < types.size (); ++i) |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1651 arg_types[i] = types[i]->to_llvm_arg (); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1652 |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1653 llvm::LLVMContext &ctx = llvm::getGlobalContext (); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1654 llvm::Type *tvoid = llvm::Type::getVoidTy (ctx); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1655 llvm::FunctionType *ft = llvm::FunctionType::get (tvoid, arg_types, false); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1656 function = llvm::Function::Create (ft, llvm::Function::ExternalLinkage, |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1657 "foobar", module); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1658 |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1659 // create variables and copy initial values |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1660 llvm::BasicBlock *body = llvm::BasicBlock::Create (ctx, "body", function); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1661 builder.SetInsertPoint (body); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1662 llvm::Function::arg_iterator arg_iter = function->arg_begin(); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1663 for (size_t i = 0; i < names.size (); ++i, ++arg_iter) |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1664 { |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1665 llvm::Type *vartype = types[i]->to_llvm (); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1666 const std::string& name = names[i]; |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1667 llvm::Value *var = builder.CreateAlloca (vartype, 0, name); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1668 variables[name] = value (types[i], var); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1669 |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1670 if (argin[i] || types[i]->force_init ()) |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1671 { |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1672 llvm::Value *loaded_arg = builder.CreateLoad (arg_iter); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1673 builder.CreateStore (loaded_arg, var); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1674 } |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1675 } |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1676 } |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1677 |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1678 void |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1679 jit_generator::finalize (const std::vector<std::string>& names) |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1680 { |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1681 // copy computed values back into arguments |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1682 // we use names instead of looping through variables because order is |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1683 // important |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1684 llvm::Function::arg_iterator arg_iter = function->arg_begin(); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1685 for (size_t i = 0; i < names.size (); ++i, ++arg_iter) |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1686 { |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1687 llvm::Value *var = variables[names[i]].second; |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1688 llvm::Value *loaded_var = builder.CreateLoad (var); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1689 builder.CreateStore (loaded_var, arg_iter); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1690 } |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1691 builder.CreateRetVoid (); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1692 } |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1693 |
14906 | 1694 // -------------------- tree_jit -------------------- |
1695 | |
1696 tree_jit::tree_jit (void) : context (llvm::getGlobalContext ()), engine (0) | |
1697 { | |
1698 llvm::InitializeNativeTarget (); | |
1699 module = new llvm::Module ("octave", context); | |
1700 } | |
1701 | |
1702 tree_jit::~tree_jit (void) | |
1703 { | |
1704 delete tinfo; | |
1705 } | |
1706 | |
1707 bool | |
1708 tree_jit::execute (tree_simple_for_command& cmd, const octave_value& bounds) | |
1709 { | |
1710 if (! initialize ()) | |
1711 return false; | |
1712 | |
1713 jit_type *bounds_t = tinfo->type_of (bounds); | |
1714 jit_info *jinfo = cmd.get_info (bounds_t); | |
1715 if (! jinfo) | |
1716 { | |
1717 jinfo = new jit_info (*this, cmd, bounds_t); | |
1718 cmd.stash_info (bounds_t, jinfo); | |
1719 } | |
1720 | |
1721 return jinfo->execute (bounds); | |
1722 } | |
1723 | |
1724 bool | |
1725 tree_jit::initialize (void) | |
14903 | 1726 { |
14906 | 1727 if (engine) |
1728 return true; | |
1729 | |
1730 // sometimes this fails pre main | |
1731 engine = llvm::ExecutionEngine::createJIT (module); | |
1732 | |
1733 if (! engine) | |
1734 return false; | |
1735 | |
1736 module_pass_manager = new llvm::PassManager (); | |
1737 module_pass_manager->add (llvm::createAlwaysInlinerPass ()); | |
1738 | |
1739 pass_manager = new llvm::FunctionPassManager (module); | |
1740 pass_manager->add (new llvm::TargetData(*engine->getTargetData ())); | |
1741 pass_manager->add (llvm::createBasicAliasAnalysisPass ()); | |
1742 pass_manager->add (llvm::createPromoteMemoryToRegisterPass ()); | |
1743 pass_manager->add (llvm::createInstructionCombiningPass ()); | |
1744 pass_manager->add (llvm::createReassociatePass ()); | |
1745 pass_manager->add (llvm::createGVNPass ()); | |
1746 pass_manager->add (llvm::createCFGSimplificationPass ()); | |
1747 pass_manager->doInitialization (); | |
1748 | |
1749 tinfo = new jit_typeinfo (module, engine); | |
1750 | |
1751 return true; | |
1752 } | |
1753 | |
1754 | |
1755 void | |
1756 tree_jit::optimize (llvm::Function *fn) | |
1757 { | |
1758 module_pass_manager->run (*module); | |
1759 pass_manager->run (*fn); | |
1760 } | |
1761 | |
1762 // -------------------- jit_info -------------------- | |
1763 jit_info::jit_info (tree_jit& tjit, tree_simple_for_command& cmd, | |
1764 jit_type *bounds) : tinfo (tjit.get_typeinfo ()), | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1765 engine (tjit.get_engine ()), |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1766 bounds_t (bounds) |
14906 | 1767 { |
1768 jit_infer infer(tinfo); | |
14903 | 1769 |
1770 try | |
1771 { | |
14906 | 1772 infer.infer (cmd, bounds); |
14903 | 1773 } |
1774 catch (const jit_fail_exception&) | |
1775 { | |
1776 function = 0; | |
1777 return; | |
1778 } | |
1779 | |
1780 types = infer.get_types (); | |
1781 | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1782 jit_generator gen(tinfo, tjit.get_module (), cmd, bounds, types); |
14903 | 1783 function = gen.get_function (); |
14899 | 1784 |
14903 | 1785 if (function) |
1786 { | |
14906 | 1787 if (debug_print) |
1788 { | |
1789 std::cout << "Compiled code:\n"; | |
1790 std::cout << cmd.str_print_code () << std::endl; | |
1791 | |
1792 std::cout << "Before optimization:\n"; | |
1793 | |
1794 llvm::raw_os_ostream os (std::cout); | |
1795 function->print (os); | |
1796 } | |
14903 | 1797 llvm::verifyFunction (*function); |
14906 | 1798 tjit.optimize (function); |
14903 | 1799 |
1800 if (debug_print) | |
1801 { | |
14906 | 1802 std::cout << "After optimization:\n"; |
14903 | 1803 |
1804 llvm::raw_os_ostream os (std::cout); | |
1805 function->print (os); | |
1806 } | |
1807 } | |
1808 } | |
1809 | |
1810 bool | |
14906 | 1811 jit_info::execute (const octave_value& bounds) const |
14899 | 1812 { |
1813 if (! function) | |
1814 return false; | |
1815 | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1816 std::vector<llvm::GenericValue> args (types.size () + 1); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1817 tinfo->to_generic (bounds_t, args[0], bounds); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1818 |
14903 | 1819 size_t idx; |
1820 type_map::const_iterator iter; | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1821 for (idx = 1, iter = types.begin (); iter != types.end (); ++iter, ++idx) |
14899 | 1822 { |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1823 if (iter->second.first) // argin? |
14899 | 1824 { |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1825 octave_value ov = iter->first->varval (); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1826 tinfo->to_generic (iter->second.second, args[idx], ov); |
14899 | 1827 } |
1828 else | |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1829 tinfo->to_generic (iter->second.second, args[idx]); |
14899 | 1830 } |
1831 | |
14903 | 1832 engine->runFunction (function, args); |
14899 | 1833 |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1834 for (idx = 1, iter = types.begin (); iter != types.end (); ++iter, ++idx) |
14903 | 1835 { |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1836 octave_value result = tinfo->to_octave_value (iter->second.second, args[idx]); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1837 octave_value &ref = iter->first->varref (); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1838 ref = result; |
14903 | 1839 } |
14899 | 1840 |
14910
a8f1e08de8fc
Simplified llvm::GenericValue creation
Max Brister <max@2bass.com>
parents:
14906
diff
changeset
|
1841 tinfo->reset_generic (); |
a8f1e08de8fc
Simplified llvm::GenericValue creation
Max Brister <max@2bass.com>
parents:
14906
diff
changeset
|
1842 |
14899 | 1843 return true; |
1844 } | |
14903 | 1845 |
1846 bool | |
14906 | 1847 jit_info::match () const |
14903 | 1848 { |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1849 for (type_map::const_iterator iter = types.begin (); iter != types.end (); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1850 ++iter) |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1851 |
14903 | 1852 { |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1853 if (iter->second.first) // argin? |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1854 { |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1855 jit_type *required_type = iter->second.second; |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1856 octave_value val = iter->first->varval (); |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1857 jit_type *current_type = tinfo->type_of (val); |
14906 | 1858 |
14913
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1859 // FIXME: should be: ! required_type->is_parent (current_type) |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1860 if (required_type != current_type) |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1861 return false; |
c7071907a641
Use symbol_record_ref instead of names in JIT
Max Brister <max@2bass.com>
parents:
14911
diff
changeset
|
1862 } |
14903 | 1863 } |
1864 | |
1865 return true; | |
1866 } |