comparison src/pt-jit.cc @ 14906:3f81e8b42955

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