Mercurial > octave-nkf
comparison libinterp/corefcn/pt-jit.cc @ 20654:b65888ec820e draft default tip gccjit
dmalcom gcc jit import
author | Stefan Mahr <dac922@gmx.de> |
---|---|
date | Fri, 27 Feb 2015 16:59:36 +0100 |
parents | d35201e5ce5d |
children |
comparison
equal
deleted
inserted
replaced
20653:9cef0a1207e4 | 20654:b65888ec820e |
---|---|
36 #include "pt-jit.h" | 36 #include "pt-jit.h" |
37 #include "sighandlers.h" | 37 #include "sighandlers.h" |
38 #include "symtab.h" | 38 #include "symtab.h" |
39 #include "variables.h" | 39 #include "variables.h" |
40 | 40 |
41 #ifdef HAVE_JIT | |
42 | |
43 static bool Vdebug_jit = false; | |
44 | |
45 static bool Vjit_enable = false; | |
46 | |
47 static int Vjit_startcnt = 1000; | |
48 | |
49 static int Vjit_failcnt = 0; | |
50 | |
41 #ifdef HAVE_LLVM | 51 #ifdef HAVE_LLVM |
42 | |
43 static bool Vdebug_jit = false; | |
44 | |
45 static bool Vjit_enable = false; | |
46 | |
47 static int Vjit_startcnt = 1000; | |
48 | |
49 static int Vjit_failcnt = 0; | |
50 | |
51 #include <llvm/Analysis/CallGraph.h> | 52 #include <llvm/Analysis/CallGraph.h> |
52 #include <llvm/Analysis/Passes.h> | 53 #include <llvm/Analysis/Passes.h> |
53 | 54 |
54 #ifdef HAVE_LLVM_IR_VERIFIER_H | 55 #ifdef HAVE_LLVM_IR_VERIFIER_H |
55 #include <llvm/IR/Verifier.h> | 56 #include <llvm/IR/Verifier.h> |
98 #include <llvm/Transforms/Scalar.h> | 99 #include <llvm/Transforms/Scalar.h> |
99 | 100 |
100 static llvm::IRBuilder<> builder (llvm::getGlobalContext ()); | 101 static llvm::IRBuilder<> builder (llvm::getGlobalContext ()); |
101 | 102 |
102 static llvm::LLVMContext& context = llvm::getGlobalContext (); | 103 static llvm::LLVMContext& context = llvm::getGlobalContext (); |
104 | |
105 #endif /* ifdef HAVE_LLVM */ | |
103 | 106 |
104 // -------------------- jit_break_exception -------------------- | 107 // -------------------- jit_break_exception -------------------- |
105 | 108 |
106 // jit_break is thrown whenever a branch we are converting has only breaks or | 109 // jit_break is thrown whenever a branch we are converting has only breaks or |
107 // continues. This is because all code that follows a break or continue is dead. | 110 // continues. This is because all code that follows a break or continue is dead. |
1293 jit_block *b = *iter; | 1296 jit_block *b = *iter; |
1294 b->append (factory.create<jit_branch> (dest)); | 1297 b->append (factory.create<jit_branch> (dest)); |
1295 } | 1298 } |
1296 } | 1299 } |
1297 | 1300 |
1301 // -------------------- jit_convert_gcc -------------------- | |
1302 #ifdef HAVE_GCCJIT | |
1303 jit_convert_gcc::jit_convert_gcc () | |
1304 : m_blocks (NULL), | |
1305 m_constants (NULL), | |
1306 m_ctxt (jit_typeinfo::create_gccjit_child_context ()), | |
1307 m_func (), | |
1308 m_extracted_params (), | |
1309 m_block_map (), | |
1310 m_locals_for_insns (), | |
1311 m_block_stack (), | |
1312 m_log_visits (false) | |
1313 { | |
1314 // FIXME: error-handling | |
1315 | |
1316 m_ctxt.set_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, | |
1317 3); | |
1318 | |
1319 // Diagnostics, debugging etc: | |
1320 if (1) | |
1321 { | |
1322 m_ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, | |
1323 1); | |
1324 m_ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE, | |
1325 0); | |
1326 m_ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, | |
1327 1); | |
1328 m_ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_SUMMARY, | |
1329 1); | |
1330 m_ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, | |
1331 0); | |
1332 m_ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING, | |
1333 1); | |
1334 m_ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_SELFCHECK_GC, | |
1335 0); | |
1336 m_ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES, | |
1337 1); | |
1338 } | |
1339 } | |
1340 | |
1341 jit_convert_gcc::~jit_convert_gcc () | |
1342 { | |
1343 m_ctxt.release (); | |
1344 } | |
1345 | |
1346 gcc_jit_result * | |
1347 jit_convert_gcc::convert_loop (const jit_block_list& blocks, | |
1348 const std::list<jit_value *>& constants) | |
1349 { | |
1350 converting_function = false; | |
1351 | |
1352 m_blocks = &blocks; | |
1353 m_constants = &constants; | |
1354 | |
1355 jit_type *any = jit_typeinfo::get_any (); | |
1356 // argument is an array of octave_base_value*, or octave_base_value** | |
1357 gccjit::type arg_type = any->to_gccjit (); // this is octave_base_value* | |
1358 arg_type = arg_type.get_pointer (); | |
1359 | |
1360 // for now just init arguments from entry, later we will have to do something | |
1361 // more interesting | |
1362 jit_block *entry_block = m_blocks->front (); | |
1363 for (jit_block::iterator iter = entry_block->begin (); | |
1364 iter != entry_block->end (); ++iter) | |
1365 if (jit_extract_argument *extract | |
1366 = dynamic_cast<jit_extract_argument *> (*iter)) | |
1367 { | |
1368 m_argument_index[extract->name ()] = m_argument_vec.size (); | |
1369 m_argument_vec.push_back (std::make_pair (extract->name (), true)); | |
1370 } | |
1371 | |
1372 /* We have a single param, confusingly named "params" (an array). */ | |
1373 params = m_ctxt.new_param (arg_type, "params"); | |
1374 | |
1375 std::vector<gccjit::param> params_of_fn (1, params); | |
1376 | |
1377 m_func = m_ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, | |
1378 m_ctxt.get_type (GCC_JIT_TYPE_VOID), | |
1379 "loop", | |
1380 params_of_fn, | |
1381 0); | |
1382 | |
1383 gccjit::block initial_block = m_func.new_block ("initial"); | |
1384 | |
1385 /* Create gccjit::blocks for each jit_block, and for each edge. | |
1386 | |
1387 We're converting from an SSA representation back to a non-SSA | |
1388 representation, hence we need to convert phi nodes into regular | |
1389 assignments. To do this, introduce a gccjit::block for each edge, to | |
1390 handle the phis along each edges. Jumps to blocks in the JIT-IR | |
1391 will become jumps to edge-handling gccjit::blocks in our CFG; each | |
1392 such "edge" block will end with a jump to the "real" gccjit::block. */ | |
1393 std::list<jit_block *>::const_iterator block_iter; | |
1394 for (block_iter = m_blocks->begin (); | |
1395 block_iter != m_blocks->end (); | |
1396 ++block_iter) | |
1397 { | |
1398 jit_block *jblock = *block_iter; | |
1399 | |
1400 // Find predecessor blocks | |
1401 for (jit_use *use = jblock->first_use (); use; use = use->next ()) | |
1402 { | |
1403 jit_block *pred = use->user_parent (); | |
1404 | |
1405 /* Create edge-handling gccjit::block. */ | |
1406 m_blocks_for_edges[std::make_pair(pred, jblock)] = | |
1407 m_func.new_block (std::string ("edge_from_") | |
1408 + pred->name_and_id () | |
1409 + std::string ("_to_") | |
1410 + jblock->name_and_id ()); | |
1411 } | |
1412 | |
1413 /* The "real" gccjit::block. */ | |
1414 m_block_map[jblock] = | |
1415 m_func.new_block (jblock->name_and_id ()); | |
1416 } | |
1417 | |
1418 /* It's an SSA representation, so we have another pass here that | |
1419 creates a local for every statement. */ | |
1420 for (block_iter = m_blocks->begin (); | |
1421 block_iter != m_blocks->end (); | |
1422 ++block_iter) | |
1423 for (jit_block::iterator insn_iter = (*block_iter)->begin (); | |
1424 insn_iter != (*block_iter)->end (); | |
1425 ++insn_iter) | |
1426 { | |
1427 jit_instruction *insn = *insn_iter; | |
1428 | |
1429 /* Some insns have NULL type e.g. conditional branches; it only | |
1430 makes sense to create a local for those with actual types. */ | |
1431 if (insn->type ()) | |
1432 { | |
1433 std::stringstream ss; | |
1434 // FIXME: perhaps make these identifiers look less weird? | |
1435 // that said, the short_print vfunc conveys more information | |
1436 ss << "("; | |
1437 insn->short_print (ss); | |
1438 ss << ")"; | |
1439 | |
1440 m_locals_for_insns[insn] = | |
1441 m_func.new_local (insn->type_gccjit (), | |
1442 ss.str ().c_str ()); | |
1443 | |
1444 insn->stash_rvalue (m_locals_for_insns[insn]); | |
1445 } | |
1446 } | |
1447 | |
1448 // constants aren't in the IR, we visit those first | |
1449 for (std::list<jit_value *>::const_iterator iter = m_constants->begin (); | |
1450 iter != m_constants->end (); ++iter) | |
1451 if (! isa<jit_instruction> (*iter)) | |
1452 visit (*iter); | |
1453 | |
1454 /* Prelude: extract params from the "params" array. */ | |
1455 if (m_with_comments) | |
1456 initial_block.add_comment ("prelude"); | |
1457 for (int i = 0; i < m_argument_vec.size (); ++i) | |
1458 { | |
1459 gccjit::lvalue extracted_param = | |
1460 m_func.new_local (any->to_gccjit (), | |
1461 "extracted_param_" + m_argument_vec[i].first); | |
1462 m_extracted_params.push_back (extracted_param); | |
1463 initial_block.add_assignment ( | |
1464 extracted_param, | |
1465 m_ctxt.new_array_access ( | |
1466 params, | |
1467 m_ctxt.new_rvalue (m_ctxt.get_type (GCC_JIT_TYPE_INT), | |
1468 i))); | |
1469 } | |
1470 initial_block.end_with_jump (m_block_map[*m_blocks->begin ()]); | |
1471 | |
1472 // convert all instructions | |
1473 for (block_iter = m_blocks->begin (); block_iter != m_blocks->end (); ++block_iter) | |
1474 visit (**block_iter); | |
1475 | |
1476 m_ctxt.dump_to_file ("/tmp/loop-dump.c", true); | |
1477 | |
1478 m_func.dump_to_dot ("/tmp/loop.dot"); | |
1479 | |
1480 return m_ctxt.compile (); | |
1481 } | |
1482 | |
1483 #if 0 | |
1484 gccjit::lvalue | |
1485 jit_convert_gcc::as_lvalue (jit_value *jval) | |
1486 { | |
1487 if (m_log_visits) | |
1488 std::cerr << "jit_convert_gcc::as_lvalue (jit_value *jval): " << *jval << "\n"; | |
1489 | |
1490 if (!jval->has_lvalue ()) | |
1491 { | |
1492 gccjit::lvalue local = | |
1493 m_func.new_local (/* FIXME: */ | |
1494 m_ctxt.get_type (GCC_JIT_TYPE_INT), | |
1495 jval->print_string ().c_str ()); | |
1496 jval->stash_lvalue (local); | |
1497 } | |
1498 | |
1499 return jval->as_lvalue (); | |
1500 } | |
1501 #endif | |
1502 | |
1503 gccjit::rvalue | |
1504 jit_convert_gcc::as_rvalue (jit_value *jval) | |
1505 { | |
1506 if (m_log_visits) | |
1507 std::cerr << "jit_convert_gcc::as_rvalue (jit_value *jval): " << *jval << "\n"; | |
1508 //std::map<jit_value *, gcc_jit_rvalue *> m_rvalues; | |
1509 | |
1510 if (jit_instruction *insn = dynamic_cast<jit_instruction *> (jval)) | |
1511 { | |
1512 return m_locals_for_insns[insn]; | |
1513 } | |
1514 | |
1515 // return gcc_jit_lvalue_as_rvalue (as_lvalue (jval)); | |
1516 return jval->as_rvalue (); | |
1517 } | |
1518 | |
1519 void | |
1520 jit_convert_gcc::add_assignment_for_insn (jit_instruction &insn, | |
1521 gccjit::rvalue val) | |
1522 { | |
1523 //insn.stash_rvalue (val); | |
1524 if (insn.type ()) | |
1525 get_current_block ().add_assignment (m_locals_for_insns[&insn], | |
1526 val); | |
1527 //TODO: use location of insn | |
1528 } | |
1529 | |
1530 gccjit::block | |
1531 jit_convert_gcc::get_block_for_edge (jit_block *src, jit_block *dest) | |
1532 { | |
1533 return m_blocks_for_edges[std::make_pair (src, dest)]; | |
1534 } | |
1535 | |
1536 gccjit::block | |
1537 jit_convert_gcc::get_current_block () | |
1538 { | |
1539 assert (!m_block_stack.empty ()); | |
1540 return m_block_stack.top (); | |
1541 } | |
1542 | |
1543 void | |
1544 jit_convert_gcc::push_block (gccjit::block block) | |
1545 { | |
1546 m_block_stack.push (block); | |
1547 } | |
1548 | |
1549 void | |
1550 jit_convert_gcc::pop_block () | |
1551 { | |
1552 m_block_stack.pop (); | |
1553 } | |
1554 | |
1555 //std::vector<gccjit::block> m_current_block_stack; | |
1556 | |
1557 | |
1558 void | |
1559 jit_convert_gcc::visit (jit_const_string& cs) | |
1560 { | |
1561 if (m_log_visits) | |
1562 std::cerr << "jit_convert_gcc::visit (jit_const_string& cs): " << cs << "\n"; | |
1563 gccjit::rvalue rvalue = m_ctxt.new_rvalue (cs.value ()); | |
1564 cs.stash_rvalue (rvalue); | |
1565 } | |
1566 | |
1567 void | |
1568 jit_convert_gcc::visit (jit_const_bool& cb) | |
1569 { | |
1570 if (m_log_visits) | |
1571 std::cerr << "jit_convert_gcc::visit (jit_const_bool& cb): " << cb << "\n"; | |
1572 gccjit::rvalue rvalue = m_ctxt.new_rvalue (cb.type_gccjit (), | |
1573 cb.value ()); | |
1574 cb.stash_rvalue (rvalue); | |
1575 } | |
1576 | |
1577 void | |
1578 jit_convert_gcc::visit (jit_const_scalar& cs) | |
1579 { | |
1580 if (m_log_visits) | |
1581 std::cerr << "jit_convert_gcc::visit (jit_const_scalar& cs): " << cs << "\n"; | |
1582 gccjit::rvalue rvalue = m_ctxt.new_rvalue (cs.type_gccjit (), | |
1583 cs.value ()); | |
1584 cs.stash_rvalue (rvalue); | |
1585 } | |
1586 | |
1587 void | |
1588 jit_convert_gcc::visit (jit_const_complex& cc) | |
1589 { | |
1590 if (m_log_visits) | |
1591 std::cerr << "jit_convert_gcc::visit (jit_const_complex& cc): " << cc << "\n"; | |
1592 #if 0 | |
1593 gccjit::rvalue rvalue = m_ctxt.new_rvalue (cc.type_gccjit (), | |
1594 cc.value ()); | |
1595 cc.stash_rvalue (rvalue); | |
1596 #else | |
1597 throw jit_fail_exception ("TODO"); | |
1598 #endif | |
1599 } | |
1600 | |
1601 void jit_convert_gcc::visit (jit_const_index& ci) | |
1602 { | |
1603 if (m_log_visits) | |
1604 std::cerr << "jit_convert_gcc::visit (jit_const_index& ci): " << ci << "\n"; | |
1605 gccjit::rvalue rvalue = m_ctxt.new_rvalue (ci.type_gccjit (), | |
1606 ci.value ()); | |
1607 ci.stash_rvalue (rvalue); | |
1608 } | |
1609 | |
1610 void | |
1611 jit_convert_gcc::visit (jit_const_range& cr) | |
1612 { | |
1613 if (m_log_visits) | |
1614 std::cerr << "jit_convert_gcc::visit (jit_const_range& cr): " << cr << "\n"; | |
1615 #if 0 | |
1616 gccjit::rvalue rvalue = m_ctxt.new_rvalue (cr.type_gccjit (), | |
1617 cr.value ()); | |
1618 cr.stash_rvalue (rvalue); | |
1619 #else | |
1620 throw jit_fail_exception ("TODO"); | |
1621 #endif | |
1622 } | |
1623 | |
1624 void | |
1625 jit_convert_gcc::visit (jit_block& b) | |
1626 { | |
1627 /* First, handle the phi nodes by populating the edge-handling blocks | |
1628 with assignments that set up the phi nodes's lvalues based on the incoming | |
1629 edge, then jumping to the "real" block for this block. */ | |
1630 for (jit_block::iterator insn_iter = b.begin (); | |
1631 insn_iter != b.end (); | |
1632 ++insn_iter) | |
1633 if (jit_phi *phi = dynamic_cast<jit_phi *> (*insn_iter)) | |
1634 { | |
1635 for (size_t i = 0; i < phi->argument_count (); ++i) | |
1636 { | |
1637 jit_block *pred = phi->incomming (i); | |
1638 push_block (m_blocks_for_edges[std::make_pair(pred, &b)]); | |
1639 if (m_with_comments) | |
1640 { | |
1641 std::ostringstream os; | |
1642 os << "incoming edge " << i << " for: "; | |
1643 phi->print (os); | |
1644 get_current_block ().add_comment (os.str ()); | |
1645 } | |
1646 get_current_block ().add_assignment ( | |
1647 m_locals_for_insns[phi], | |
1648 m_locals_for_insns[static_cast <jit_instruction *> (phi->argument (i))]); | |
1649 pop_block (); | |
1650 } | |
1651 } | |
1652 | |
1653 /* Terminate the blocks for edges leading to this block. */ | |
1654 jit_use *use; | |
1655 for (use = b.first_use (); use; use = use->next ()) | |
1656 { | |
1657 jit_block *pred = use->user_parent (); | |
1658 gccjit::block block_for_edge = | |
1659 m_blocks_for_edges[std::make_pair(pred, &b)]; | |
1660 block_for_edge.end_with_jump (m_block_map[&b]); | |
1661 } | |
1662 | |
1663 /* Now generate a block for all of the non-phi instructions. */ | |
1664 push_block (m_block_map[&b]); | |
1665 for (jit_block::iterator insn_iter = b.begin (); | |
1666 insn_iter != b.end (); | |
1667 ++insn_iter) | |
1668 { | |
1669 // We've handled phi nodes above; skip them: | |
1670 if (dynamic_cast<jit_phi *> (*insn_iter)) | |
1671 continue; | |
1672 | |
1673 if (m_with_comments) | |
1674 get_current_block ().add_comment (std::string ("jit_instruction: ") | |
1675 + (*insn_iter)->print_string ()); | |
1676 visit (*insn_iter); | |
1677 } | |
1678 pop_block (); | |
1679 } | |
1680 | |
1681 void | |
1682 jit_convert_gcc::visit (jit_branch& b) | |
1683 { | |
1684 if (m_log_visits) | |
1685 std::cerr << "jit_convert_gcc::visit (jit_branch& b): " << b << "\n"; | |
1686 | |
1687 jit_block *this_block = b.parent (); | |
1688 jit_block *next = b.successor (); | |
1689 | |
1690 get_current_block ().end_with_jump (get_block_for_edge (this_block, next)); | |
1691 } | |
1692 | |
1693 void | |
1694 jit_convert_gcc::visit (jit_cond_branch& cb) | |
1695 { | |
1696 if (m_log_visits) | |
1697 std::cerr << "jit_convert_gcc::visit (jit_cond_branch& cb): " << cb << "\n"; | |
1698 | |
1699 gccjit::rvalue boolval = as_rvalue (cb.cond ()); | |
1700 | |
1701 jit_block *this_block = cb.parent (); | |
1702 get_current_block ().end_with_conditional ( | |
1703 boolval, | |
1704 get_block_for_edge (this_block, cb.successor (0)), | |
1705 get_block_for_edge (this_block, cb.successor (1))); | |
1706 } | |
1707 | |
1708 void | |
1709 jit_convert_gcc::visit (jit_call& call) | |
1710 { | |
1711 if (m_log_visits) | |
1712 std::cerr << "jit_convert_gcc::visit (jit_call& call): " << call << "\n"; | |
1713 | |
1714 const jit_function& ol = call.overload (); | |
1715 | |
1716 std::vector<jit_value *> args (call.arguments ().size ()); | |
1717 for (size_t i = 0; i < args.size (); ++i) | |
1718 args[i] = call.argument (i); | |
1719 | |
1720 gccjit::rvalue ret = ol.call (m_ctxt, get_current_block (), args); | |
1721 add_assignment_for_insn (call, ret); | |
1722 } | |
1723 | |
1724 void | |
1725 jit_convert_gcc::visit (jit_extract_argument& extract) | |
1726 { | |
1727 if (m_log_visits) | |
1728 std::cerr << "jit_convert_gcc::visit (jit_extract_argument& extract): " << extract << "\n"; | |
1729 | |
1730 const std::string& argname = extract.name (); | |
1731 | |
1732 // Get the stored (octave_base_value *) | |
1733 gccjit::lvalue param = m_extracted_params[m_argument_index[argname]]; | |
1734 | |
1735 // Convert it to a more specialized type: | |
1736 const jit_function& ol = extract.overload (); | |
1737 std::vector<gccjit::rvalue> args (1, param); | |
1738 gccjit::rvalue extracted = ol.call (m_ctxt, get_current_block (), args); | |
1739 add_assignment_for_insn (extract, | |
1740 extracted); | |
1741 } | |
1742 | |
1743 void | |
1744 jit_convert_gcc::visit (jit_store_argument& store) | |
1745 { | |
1746 if (m_log_visits) | |
1747 std::cerr << "jit_convert_gcc::visit (jit_store_argument& store): " << store << "\n"; | |
1748 | |
1749 const jit_function& ol = store.overload (); | |
1750 | |
1751 std::vector<jit_value *> args (1); | |
1752 args[0] = store.result (); | |
1753 | |
1754 gccjit::rvalue ret = ol.call (m_ctxt, get_current_block (), args); | |
1755 int index = m_argument_index[store.name ()]; | |
1756 get_current_block ().add_assignment ( | |
1757 // "params[index] = ..." | |
1758 m_ctxt.new_array_access ( | |
1759 params, | |
1760 m_ctxt.new_rvalue (m_ctxt.get_type (GCC_JIT_TYPE_INT), | |
1761 index)), | |
1762 // "... = ret;" | |
1763 ret); | |
1764 } | |
1765 | |
1766 void | |
1767 jit_convert_gcc::visit (jit_return& ret) | |
1768 { | |
1769 if (m_log_visits) | |
1770 std::cerr << "jit_convert_gcc::visit (jit_return& ret): " << ret << "\n"; | |
1771 jit_value *res = ret.result (); | |
1772 | |
1773 if (converting_function) | |
1774 throw jit_fail_exception ("TODO"); | |
1775 else | |
1776 { | |
1777 if (res) | |
1778 get_current_block ().end_with_return (res->as_rvalue ()); | |
1779 else | |
1780 get_current_block ().end_with_return (); | |
1781 } | |
1782 } | |
1783 | |
1784 void | |
1785 jit_convert_gcc::visit (jit_phi& phi) | |
1786 { | |
1787 if (m_log_visits) | |
1788 std::cerr << "jit_convert_gcc::visit (jit_phi& phi): " << phi << "\n"; | |
1789 throw jit_fail_exception ("TODO"); | |
1790 } | |
1791 | |
1792 void | |
1793 jit_convert_gcc::visit (jit_variable& var) | |
1794 { | |
1795 if (m_log_visits) | |
1796 std::cerr << "jit_convert_gcc::visit (jit_variable&): " << var << "\n"; | |
1797 throw jit_fail_exception ("TODO"); | |
1798 } | |
1799 | |
1800 void | |
1801 jit_convert_gcc::visit (jit_error_check& check) | |
1802 { | |
1803 if (m_log_visits) | |
1804 std::cerr << "jit_convert_gcc::visit (jit_error_check& check): " << check << "\n"; | |
1805 | |
1806 gccjit::rvalue cond; | |
1807 | |
1808 switch (check.check_variable ()) | |
1809 { | |
1810 case jit_error_check::var_error_state: | |
1811 cond = jit_typeinfo::insert_error_check (m_func); | |
1812 break; | |
1813 case jit_error_check::var_interrupt: | |
1814 cond = jit_typeinfo::insert_interrupt_check (m_func); | |
1815 break; | |
1816 default: | |
1817 panic_impossible (); | |
1818 } | |
1819 | |
1820 jit_block *this_block = check.parent (); | |
1821 get_current_block ().end_with_conditional ( | |
1822 cond, | |
1823 get_block_for_edge (this_block, check.successor (0)), | |
1824 get_block_for_edge (this_block, check.successor (1))); | |
1825 } | |
1826 | |
1827 void | |
1828 jit_convert_gcc::visit (jit_assign& assign) | |
1829 { | |
1830 if (m_log_visits) | |
1831 std::cerr << "jit_convert_gcc::visit (jit_assign& assign): " << assign << "\n"; | |
1832 | |
1833 jit_value *jsrc = assign.src (); | |
1834 | |
1835 add_assignment_for_insn (assign, | |
1836 as_rvalue (jsrc)); | |
1837 } | |
1838 | |
1839 void | |
1840 jit_convert_gcc::visit (jit_argument& arg) | |
1841 { | |
1842 if (m_log_visits) | |
1843 std::cerr << "jit_convert_gcc::visit (jit_argument&): " << arg << "\n"; | |
1844 throw jit_fail_exception ("TODO"); | |
1845 } | |
1846 | |
1847 void | |
1848 jit_convert_gcc::visit (jit_magic_end& me) | |
1849 { | |
1850 if (m_log_visits) | |
1851 std::cerr << "jit_convert_gcc::visit (jit_magic_end& me): " << me << "\n"; | |
1852 throw jit_fail_exception ("TODO"); | |
1853 } | |
1854 #endif /* HAVE_GCCJIT */ | |
1855 | |
1298 // -------------------- jit_convert_llvm -------------------- | 1856 // -------------------- jit_convert_llvm -------------------- |
1857 | |
1858 #ifdef HAVE_LLVM | |
1859 | |
1299 llvm::Function * | 1860 llvm::Function * |
1300 jit_convert_llvm::convert_loop (llvm::Module *module, | 1861 jit_convert_llvm::convert_loop (llvm::Module *module, |
1301 const jit_block_list& blocks, | 1862 const jit_block_list& blocks, |
1302 const std::list<jit_value *>& constants) | 1863 const std::list<jit_value *>& constants) |
1303 { | 1864 { |
1359 | 1920 |
1360 jit_block *final_block = blocks.back (); | 1921 jit_block *final_block = blocks.back (); |
1361 jit_return *ret = dynamic_cast<jit_return *> (final_block->back ()); | 1922 jit_return *ret = dynamic_cast<jit_return *> (final_block->back ()); |
1362 assert (ret); | 1923 assert (ret); |
1363 | 1924 |
1364 creating = jit_function (module, jit_convention::internal, | 1925 creating = jit_function (module, |
1926 #ifdef HAVE_GCCJIT | |
1927 gccjit::context (), // FIXME? | |
1928 #endif | |
1929 jit_convention::internal, | |
1365 "foobar", ret->result_type (), args); | 1930 "foobar", ret->result_type (), args); |
1366 function = creating.to_llvm (); | 1931 function = creating.to_llvm (); |
1367 | 1932 |
1368 try | 1933 try |
1369 { | 1934 { |
1646 | 2211 |
1647 jit_magic_end::context ctx = me.resolve_context (); | 2212 jit_magic_end::context ctx = me.resolve_context (); |
1648 llvm::Value *ret = ol.call (builder, ctx.value, ctx.index, ctx.count); | 2213 llvm::Value *ret = ol.call (builder, ctx.value, ctx.index, ctx.count); |
1649 me.stash_llvm (ret); | 2214 me.stash_llvm (ret); |
1650 } | 2215 } |
2216 | |
2217 #endif /* ifdef HAVE_LLVM */ | |
1651 | 2218 |
1652 // -------------------- jit_infer -------------------- | 2219 // -------------------- jit_infer -------------------- |
1653 jit_infer::jit_infer (jit_factory& afactory, jit_block_list& ablocks, | 2220 jit_infer::jit_infer (jit_factory& afactory, jit_block_list& ablocks, |
1654 const variable_map& avmap) | 2221 const variable_map& avmap) |
1655 : blocks (ablocks), factory (afactory), vmap (avmap) { } | 2222 : blocks (ablocks), factory (afactory), vmap (avmap) { } |
2050 } | 2617 } |
2051 | 2618 |
2052 bool | 2619 bool |
2053 tree_jit::initialize (void) | 2620 tree_jit::initialize (void) |
2054 { | 2621 { |
2622 #ifdef HAVE_LLVM | |
2055 if (engine) | 2623 if (engine) |
2056 return true; | 2624 return true; |
2057 | 2625 |
2058 if (! module) | 2626 if (! module) |
2059 { | 2627 { |
2087 pass_manager->add (llvm::createInstructionCombiningPass ()); | 2655 pass_manager->add (llvm::createInstructionCombiningPass ()); |
2088 pass_manager->add (llvm::createReassociatePass ()); | 2656 pass_manager->add (llvm::createReassociatePass ()); |
2089 pass_manager->add (llvm::createGVNPass ()); | 2657 pass_manager->add (llvm::createGVNPass ()); |
2090 pass_manager->add (llvm::createCFGSimplificationPass ()); | 2658 pass_manager->add (llvm::createCFGSimplificationPass ()); |
2091 pass_manager->doInitialization (); | 2659 pass_manager->doInitialization (); |
2092 | 2660 #endif /* ifdef HAVE_LLVM */ |
2093 jit_typeinfo::initialize (module, engine); | 2661 |
2662 jit_typeinfo::initialize ( | |
2663 #ifdef HAVE_LLVM | |
2664 module, engine | |
2665 #endif | |
2666 ); | |
2094 | 2667 |
2095 return true; | 2668 return true; |
2096 } | 2669 } |
2097 | 2670 |
2098 bool | 2671 bool |
2175 | 2748 |
2176 // unsupported type | 2749 // unsupported type |
2177 return 0; | 2750 return 0; |
2178 } | 2751 } |
2179 | 2752 |
2180 | 2753 #ifdef HAVE_LLVM |
2181 void | 2754 void |
2182 tree_jit::optimize (llvm::Function *fn) | 2755 tree_jit::optimize (llvm::Function *fn) |
2183 { | 2756 { |
2184 if (Vdebug_jit) | 2757 if (Vdebug_jit) |
2185 llvm::verifyModule (*module); | 2758 llvm::verifyModule (*module); |
2198 llvm::raw_fd_ostream::F_Binary); | 2771 llvm::raw_fd_ostream::F_Binary); |
2199 #endif | 2772 #endif |
2200 llvm::WriteBitcodeToFile (module, fout); | 2773 llvm::WriteBitcodeToFile (module, fout); |
2201 } | 2774 } |
2202 } | 2775 } |
2776 #endif /* ifdef HAVE_LLVM */ | |
2203 | 2777 |
2204 // -------------------- jit_function_info -------------------- | 2778 // -------------------- jit_function_info -------------------- |
2779 #ifdef HAVE_JIT | |
2205 jit_function_info::jit_function_info (tree_jit& tjit, | 2780 jit_function_info::jit_function_info (tree_jit& tjit, |
2206 octave_user_function& fcn, | 2781 octave_user_function& fcn, |
2207 const octave_value_list& ov_args) | 2782 const octave_value_list& ov_args) |
2208 : argument_types (ov_args.length ()), function (0) | 2783 : argument_types (ov_args.length ()), function (0) |
2209 { | 2784 { |
2215 jit_function wrapper; | 2790 jit_function wrapper; |
2216 | 2791 |
2217 try | 2792 try |
2218 { | 2793 { |
2219 jit_convert conv (fcn, argument_types); | 2794 jit_convert conv (fcn, argument_types); |
2795 | |
2796 if (Vdebug_jit) | |
2797 { | |
2798 jit_block_list& blocks = conv.get_blocks (); | |
2799 blocks.label (); | |
2800 std::cout << "-------------------- Compiling function "; | |
2801 std::cout << "--------------------\n"; | |
2802 | |
2803 tree_print_code tpc (std::cout); | |
2804 tpc.visit_octave_user_function_header (fcn); | |
2805 tpc.visit_statement_list (*fcn.body ()); | |
2806 tpc.visit_octave_user_function_trailer (fcn); | |
2807 blocks.print (std::cout, "octave jit ir"); | |
2808 } | |
2809 | |
2220 jit_infer infer (conv.get_factory (), conv.get_blocks (), | 2810 jit_infer infer (conv.get_factory (), conv.get_blocks (), |
2221 conv.get_variable_map ()); | 2811 conv.get_variable_map ()); |
2222 infer.infer (); | 2812 infer.infer (); |
2223 | 2813 |
2224 if (Vdebug_jit) | 2814 if (Vdebug_jit) |
2251 } | 2841 } |
2252 | 2842 |
2253 std::string wrapper_name = fcn.name () + "_wrapper"; | 2843 std::string wrapper_name = fcn.name () + "_wrapper"; |
2254 jit_type *any_t = jit_typeinfo::get_any (); | 2844 jit_type *any_t = jit_typeinfo::get_any (); |
2255 std::vector<jit_type *> wrapper_args (1, jit_typeinfo::get_any_ptr ()); | 2845 std::vector<jit_type *> wrapper_args (1, jit_typeinfo::get_any_ptr ()); |
2256 wrapper = jit_function (module, jit_convention::internal, wrapper_name, | 2846 wrapper = jit_function (module, |
2847 #ifdef HAVE_GCCJIT | |
2848 gccjit::context (), // FIXME | |
2849 #endif | |
2850 jit_convention::internal, wrapper_name, | |
2257 any_t, wrapper_args); | 2851 any_t, wrapper_args); |
2258 | 2852 |
2259 llvm::BasicBlock *wrapper_body = wrapper.new_block (); | 2853 llvm::BasicBlock *wrapper_body = wrapper.new_block (); |
2260 builder.SetInsertPoint (wrapper_body); | 2854 builder.SetInsertPoint (wrapper_body); |
2261 | 2855 |
2316 | 2910 |
2317 wrapper.erase (); | 2911 wrapper.erase (); |
2318 raw_fn.erase (); | 2912 raw_fn.erase (); |
2319 } | 2913 } |
2320 } | 2914 } |
2915 #endif /* ifdef HAVE_JIT */ | |
2321 | 2916 |
2322 bool | 2917 bool |
2323 jit_function_info::execute (const octave_value_list& ov_args, | 2918 jit_function_info::execute (const octave_value_list& ov_args, |
2324 octave_value_list& retval) const | 2919 octave_value_list& retval) const |
2325 { | 2920 { |
2361 | 2956 |
2362 return true; | 2957 return true; |
2363 } | 2958 } |
2364 | 2959 |
2365 // -------------------- jit_info -------------------- | 2960 // -------------------- jit_info -------------------- |
2961 #ifdef HAVE_LLVM | |
2366 jit_info::jit_info (tree_jit& tjit, tree& tee) | 2962 jit_info::jit_info (tree_jit& tjit, tree& tee) |
2367 : engine (tjit.get_engine ()), function (0), llvm_function (0) | 2963 : engine (tjit.get_engine ()), function (0), llvm_function (0) |
2964 #ifdef HAVE_GCCJIT | |
2965 , gccjit_result (NULL) | |
2966 #endif | |
2368 { | 2967 { |
2369 compile (tjit, tee); | 2968 compile (tjit, tee); |
2370 } | 2969 } |
2371 | 2970 |
2372 jit_info::jit_info (tree_jit& tjit, tree& tee, const octave_value& for_bounds) | 2971 jit_info::jit_info (tree_jit& tjit, tree& tee, const octave_value& for_bounds) |
2373 : engine (tjit.get_engine ()), function (0), llvm_function (0) | 2972 : engine (tjit.get_engine ()), function (0), llvm_function (0) |
2973 #ifdef HAVE_GCCJIT | |
2974 , gccjit_result (NULL) | |
2975 #endif | |
2374 { | 2976 { |
2375 compile (tjit, tee, jit_typeinfo::type_of (for_bounds)); | 2977 compile (tjit, tee, jit_typeinfo::type_of (for_bounds)); |
2376 } | 2978 } |
2377 | 2979 |
2378 jit_info::~jit_info (void) | 2980 jit_info::~jit_info (void) |
2379 { | 2981 { |
2380 if (llvm_function) | 2982 if (llvm_function) |
2381 llvm_function->eraseFromParent (); | 2983 llvm_function->eraseFromParent (); |
2382 } | 2984 #ifdef HAVE_GCCJIT |
2985 if (gccjit_result) | |
2986 gcc_jit_result_release (gccjit_result); | |
2987 #endif | |
2988 } | |
2989 #endif | |
2383 | 2990 |
2384 bool | 2991 bool |
2385 jit_info::execute (const vmap& extra_vars) const | 2992 jit_info::execute (const vmap& extra_vars) const |
2386 { | 2993 { |
2387 if (! function) | 2994 if (! function) |
2433 } | 3040 } |
2434 | 3041 |
2435 return true; | 3042 return true; |
2436 } | 3043 } |
2437 | 3044 |
3045 #ifdef HAVE_LLVM | |
2438 void | 3046 void |
2439 jit_info::compile (tree_jit& tjit, tree& tee, jit_type *for_bounds) | 3047 jit_info::compile (tree_jit& tjit, tree& tee, jit_type *for_bounds) |
2440 { | 3048 { |
2441 try | 3049 try |
2442 { | 3050 { |
2443 jit_convert conv (tee, for_bounds); | 3051 jit_convert conv (tee, for_bounds); |
3052 | |
3053 if (Vdebug_jit) | |
3054 { | |
3055 jit_block_list& blocks = conv.get_blocks (); | |
3056 blocks.label (); | |
3057 std::cout << "-------------------- Compiling tree --------------------\n"; | |
3058 std::cout << tee.str_print_code () << std::endl; | |
3059 blocks.print (std::cout, "octave jit ir"); | |
3060 } | |
3061 | |
2444 jit_infer infer (conv.get_factory (), conv.get_blocks (), | 3062 jit_infer infer (conv.get_factory (), conv.get_blocks (), |
2445 conv.get_variable_map ()); | 3063 conv.get_variable_map ()); |
2446 | 3064 |
2447 infer.infer (); | 3065 infer.infer (); |
2448 | 3066 |
2454 std::cout << tee.str_print_code () << std::endl; | 3072 std::cout << tee.str_print_code () << std::endl; |
2455 blocks.print (std::cout, "octave jit ir"); | 3073 blocks.print (std::cout, "octave jit ir"); |
2456 } | 3074 } |
2457 | 3075 |
2458 jit_factory& factory = conv.get_factory (); | 3076 jit_factory& factory = conv.get_factory (); |
3077 | |
3078 #ifdef HAVE_GCCJIT | |
3079 jit_convert_gcc to_gcc; | |
3080 gccjit_result = to_gcc.convert_loop (infer.get_blocks (), | |
3081 factory.constants ()); | |
3082 #endif | |
3083 | |
2459 jit_convert_llvm to_llvm; | 3084 jit_convert_llvm to_llvm; |
2460 llvm_function = to_llvm.convert_loop (tjit.get_module (), | 3085 llvm_function = to_llvm.convert_loop (tjit.get_module (), |
2461 infer.get_blocks (), | 3086 infer.get_blocks (), |
2462 factory.constants ()); | 3087 factory.constants ()); |
2463 arguments = to_llvm.get_arguments (); | 3088 arguments = to_llvm.get_arguments (); |
2472 } | 3097 } |
2473 | 3098 |
2474 Vjit_failcnt++; | 3099 Vjit_failcnt++; |
2475 | 3100 |
2476 } | 3101 } |
2477 | 3102 #ifdef HAVE_GCCJIT |
3103 if (gccjit_result) | |
3104 { | |
3105 if (Vdebug_jit) | |
3106 { | |
3107 std::cout << "-------------------- gccjit --------------------"; | |
3108 void *void_fn = gcc_jit_result_get_code (gccjit_result, "loop"); | |
3109 function = reinterpret_cast<jited_function> (void_fn); | |
3110 } | |
3111 printf ("using gccjit function\n"); | |
3112 } | |
3113 else | |
3114 #endif | |
2478 if (llvm_function) | 3115 if (llvm_function) |
2479 { | 3116 { |
2480 if (Vdebug_jit) | 3117 if (Vdebug_jit) |
2481 { | 3118 { |
2482 std::cout << "-------------------- llvm ir --------------------"; | 3119 std::cout << "-------------------- llvm ir --------------------"; |
2495 | 3132 |
2496 void *void_fn = engine->getPointerToFunction (llvm_function); | 3133 void *void_fn = engine->getPointerToFunction (llvm_function); |
2497 function = reinterpret_cast<jited_function> (void_fn); | 3134 function = reinterpret_cast<jited_function> (void_fn); |
2498 } | 3135 } |
2499 } | 3136 } |
3137 #endif | |
2500 | 3138 |
2501 octave_value | 3139 octave_value |
2502 jit_info::find (const vmap& extra_vars, const std::string& vname) const | 3140 jit_info::find (const vmap& extra_vars, const std::string& vname) const |
2503 { | 3141 { |
2504 vmap::const_iterator iter = extra_vars.find (vname); | 3142 vmap::const_iterator iter = extra_vars.find (vname); |
2505 return iter == extra_vars.end () ? symbol_table::varval (vname) | 3143 return iter == extra_vars.end () ? symbol_table::varval (vname) |
2506 : *iter->second; | 3144 : *iter->second; |
2507 } | 3145 } |
2508 | 3146 |
3147 #endif /* if HAVE_JIT */ | |
3148 | |
3149 #if defined (HAVE_JIT) | |
3150 #define UNUSED_WITHOUT_JIT(x) x | |
3151 #else | |
3152 #define UNUSED_WITHOUT_JIT(x) x GCC_ATTR_UNUSED | |
2509 #endif | 3153 #endif |
2510 | 3154 |
2511 #if defined (HAVE_LLVM) | 3155 DEFUN (jit_failcnt, UNUSED_WITHOUT_JIT (args), |
2512 #define UNUSED_WITHOUT_LLVM(x) x | 3156 UNUSED_WITHOUT_JIT (nargout), |
2513 #else | |
2514 #define UNUSED_WITHOUT_LLVM(x) x GCC_ATTR_UNUSED | |
2515 #endif | |
2516 | |
2517 DEFUN (jit_failcnt, UNUSED_WITHOUT_LLVM (args), | |
2518 UNUSED_WITHOUT_LLVM (nargout), | |
2519 "-*- texinfo -*-\n\ | 3157 "-*- texinfo -*-\n\ |
2520 @deftypefn {Built-in Function} {@var{val} =} jit_failcnt ()\n\ | 3158 @deftypefn {Built-in Function} {@var{val} =} jit_failcnt ()\n\ |
2521 @deftypefnx {Built-in Function} {@var{old_val} =} jit_failcnt (@var{new_val})\n\ | 3159 @deftypefnx {Built-in Function} {@var{old_val} =} jit_failcnt (@var{new_val})\n\ |
2522 @deftypefnx {Built-in Function} {} jit_failcnt (@var{new_val}, \"local\")\n\ | 3160 @deftypefnx {Built-in Function} {} jit_failcnt (@var{new_val}, \"local\")\n\ |
2523 Query or set the internal variable that counts the number of JIT fail\n\ | 3161 Query or set the internal variable that counts the number of JIT fail\n\ |
2527 variable is changed locally for the function and any subroutines it calls.\n\ | 3165 variable is changed locally for the function and any subroutines it calls.\n\ |
2528 The original variable value is restored when exiting the function.\n\ | 3166 The original variable value is restored when exiting the function.\n\ |
2529 @seealso{jit_enable, jit_startcnt, debug_jit}\n\ | 3167 @seealso{jit_enable, jit_startcnt, debug_jit}\n\ |
2530 @end deftypefn") | 3168 @end deftypefn") |
2531 { | 3169 { |
2532 #if defined (HAVE_LLVM) | 3170 #if defined (HAVE_JIT) |
2533 return SET_INTERNAL_VARIABLE (jit_failcnt); | 3171 return SET_INTERNAL_VARIABLE (jit_failcnt); |
2534 #else | 3172 #else |
2535 warning ("jit_failcnt: JIT compiling not available in this version of Octave"); | 3173 warning ("jit_failcnt: JIT compiling not available in this version of Octave"); |
2536 return octave_value (); | 3174 return octave_value (); |
2537 #endif | 3175 #endif |
2538 } | 3176 } |
2539 | 3177 |
2540 DEFUN (debug_jit, UNUSED_WITHOUT_LLVM (args), | 3178 DEFUN (debug_jit, UNUSED_WITHOUT_JIT (args), |
2541 UNUSED_WITHOUT_LLVM (nargout), | 3179 UNUSED_WITHOUT_JIT (nargout), |
2542 "-*- texinfo -*-\n\ | 3180 "-*- texinfo -*-\n\ |
2543 @deftypefn {Built-in Function} {@var{val} =} debug_jit ()\n\ | 3181 @deftypefn {Built-in Function} {@var{val} =} debug_jit ()\n\ |
2544 @deftypefnx {Built-in Function} {@var{old_val} =} debug_jit (@var{new_val})\n\ | 3182 @deftypefnx {Built-in Function} {@var{old_val} =} debug_jit (@var{new_val})\n\ |
2545 @deftypefnx {Built-in Function} {} debug_jit (@var{new_val}, \"local\")\n\ | 3183 @deftypefnx {Built-in Function} {} debug_jit (@var{new_val}, \"local\")\n\ |
2546 Query or set the internal variable that determines whether\n\ | 3184 Query or set the internal variable that determines whether\n\ |
2550 variable is changed locally for the function and any subroutines it calls.\n\ | 3188 variable is changed locally for the function and any subroutines it calls.\n\ |
2551 The original variable value is restored when exiting the function.\n\ | 3189 The original variable value is restored when exiting the function.\n\ |
2552 @seealso{jit_enable, jit_startcnt}\n\ | 3190 @seealso{jit_enable, jit_startcnt}\n\ |
2553 @end deftypefn") | 3191 @end deftypefn") |
2554 { | 3192 { |
2555 #if defined (HAVE_LLVM) | 3193 #if defined (HAVE_JIT) |
2556 return SET_INTERNAL_VARIABLE (debug_jit); | 3194 return SET_INTERNAL_VARIABLE (debug_jit); |
2557 #else | 3195 #else |
2558 warning ("debug_jit: JIT compiling not available in this version of Octave"); | 3196 warning ("debug_jit: JIT compiling not available in this version of Octave"); |
2559 return octave_value (); | 3197 return octave_value (); |
2560 #endif | 3198 #endif |
2561 } | 3199 } |
2562 | 3200 |
2563 DEFUN (jit_enable, UNUSED_WITHOUT_LLVM (args), | 3201 DEFUN (jit_enable, UNUSED_WITHOUT_JIT (args), |
2564 UNUSED_WITHOUT_LLVM (nargout), | 3202 UNUSED_WITHOUT_JIT (nargout), |
2565 "-*- texinfo -*-\n\ | 3203 "-*- texinfo -*-\n\ |
2566 @deftypefn {Built-in Function} {@var{val} =} jit_enable ()\n\ | 3204 @deftypefn {Built-in Function} {@var{val} =} jit_enable ()\n\ |
2567 @deftypefnx {Built-in Function} {@var{old_val} =} jit_enable (@var{new_val})\n\ | 3205 @deftypefnx {Built-in Function} {@var{old_val} =} jit_enable (@var{new_val})\n\ |
2568 @deftypefnx {Built-in Function} {} jit_enable (@var{new_val}, \"local\")\n\ | 3206 @deftypefnx {Built-in Function} {} jit_enable (@var{new_val}, \"local\")\n\ |
2569 Query or set the internal variable that enables Octave's JIT compiler.\n\ | 3207 Query or set the internal variable that enables Octave's JIT compiler.\n\ |
2572 variable is changed locally for the function and any subroutines it calls.\n\ | 3210 variable is changed locally for the function and any subroutines it calls.\n\ |
2573 The original variable value is restored when exiting the function.\n\ | 3211 The original variable value is restored when exiting the function.\n\ |
2574 @seealso{jit_startcnt, debug_jit}\n\ | 3212 @seealso{jit_startcnt, debug_jit}\n\ |
2575 @end deftypefn") | 3213 @end deftypefn") |
2576 { | 3214 { |
2577 #if defined (HAVE_LLVM) | 3215 #if defined (HAVE_JIT) |
2578 return SET_INTERNAL_VARIABLE (jit_enable); | 3216 return SET_INTERNAL_VARIABLE (jit_enable); |
2579 #else | 3217 #else |
2580 warning ("jit_enable: JIT compiling not available in this version of Octave"); | 3218 warning ("jit_enable: JIT compiling not available in this version of Octave"); |
2581 return octave_value (); | 3219 return octave_value (); |
2582 #endif | 3220 #endif |
2583 } | 3221 } |
2584 | 3222 |
2585 DEFUN (jit_startcnt, UNUSED_WITHOUT_LLVM (args), | 3223 DEFUN (jit_startcnt, UNUSED_WITHOUT_JIT (args), |
2586 UNUSED_WITHOUT_LLVM (nargout), | 3224 UNUSED_WITHOUT_JIT (nargout), |
2587 "-*- texinfo -*-\n\ | 3225 "-*- texinfo -*-\n\ |
2588 @deftypefn {Built-in Function} {@var{val} =} jit_startcnt ()\n\ | 3226 @deftypefn {Built-in Function} {@var{val} =} jit_startcnt ()\n\ |
2589 @deftypefnx {Built-in Function} {@var{old_val} =} jit_startcnt (@var{new_val})\n\ | 3227 @deftypefnx {Built-in Function} {@var{old_val} =} jit_startcnt (@var{new_val})\n\ |
2590 @deftypefnx {Built-in Function} {} jit_startcnt (@var{new_val}, \"local\")\n\ | 3228 @deftypefnx {Built-in Function} {} jit_startcnt (@var{new_val}, \"local\")\n\ |
2591 Query or set the internal variable that determines whether JIT compilation\n\ | 3229 Query or set the internal variable that determines whether JIT compilation\n\ |
2599 variable is changed locally for the function and any subroutines it calls.\n\ | 3237 variable is changed locally for the function and any subroutines it calls.\n\ |
2600 The original variable value is restored when exiting the function.\n\ | 3238 The original variable value is restored when exiting the function.\n\ |
2601 @seealso{jit_enable, jit_failcnt, debug_jit}\n\ | 3239 @seealso{jit_enable, jit_failcnt, debug_jit}\n\ |
2602 @end deftypefn") | 3240 @end deftypefn") |
2603 { | 3241 { |
2604 #if defined (HAVE_LLVM) | 3242 #if defined (HAVE_JIT) |
2605 return SET_INTERNAL_VARIABLE_WITH_LIMITS (jit_startcnt, 1, | 3243 return SET_INTERNAL_VARIABLE_WITH_LIMITS (jit_startcnt, 1, |
2606 std::numeric_limits<int>::max ()); | 3244 std::numeric_limits<int>::max ()); |
2607 #else | 3245 #else |
2608 warning ("jit_enable: JIT compiling not available in this version of Octave"); | 3246 warning ("jit_enable: JIT compiling not available in this version of Octave"); |
2609 return octave_value (); | 3247 return octave_value (); |