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