Mercurial > octave-nkf
comparison src/pt-jit.h @ 14980:bb1f3a9bb122
Reduce code duplication in JIT
* src/pt-jit.h (jit_function::overload::overload, jit_function::add_overload,
jit_typeinfo::create_function, jit_instruction::jit_instruction,
jit_terminator::jit_terminator, jit_call::jit_call, jit_convert::create,
jit_convert::create_checked): Define similar overloads with macros.
(jit_terminator::branch_llm): Remove dead function.
(jit_terminator::successor_llvm): Remove dead code.
* liboctave/lo-macros.h (OCT_MAKE_ARG_LIST): New macro.
author | Max Brister <max@2bass.com> |
---|---|
date | Thu, 05 Jul 2012 17:25:25 -0500 |
parents | f649b66ef1af |
children | a5f75de0dab1 |
comparison
equal
deleted
inserted
replaced
14979:8b4606e3be32 | 14980:bb1f3a9bb122 |
---|---|
318 struct | 318 struct |
319 overload | 319 overload |
320 { | 320 { |
321 overload (void) : function (0), can_error (false), result (0) {} | 321 overload (void) : function (0), can_error (false), result (0) {} |
322 | 322 |
323 overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0) : | 323 #define ASSIGN_ARG(i) arguments[i] = arg ## i; |
324 function (f), can_error (e), result (r), arguments (1) | 324 #define OVERLOAD_CTOR(N) \ |
325 { | 325 overload (llvm::Function *f, bool e, jit_type *ret, \ |
326 arguments[0] = arg0; | 326 OCT_MAKE_DECL_LIST (jit_type *, arg, N)) \ |
327 : function (f), can_error (e), result (ret), arguments (N) \ | |
328 { \ | |
329 OCT_ITERATE_MACRO (ASSIGN_ARG, N); \ | |
327 } | 330 } |
328 | 331 |
329 overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0, | 332 OVERLOAD_CTOR (1) |
330 jit_type *arg1) : function (f), can_error (e), | 333 OVERLOAD_CTOR (2) |
331 result (r), arguments (2) | 334 OVERLOAD_CTOR (3) |
332 { | 335 |
333 arguments[0] = arg0; | 336 #undef ASSIGN_ARG |
334 arguments[1] = arg1; | 337 #undef OVERLOAD_CTOR |
335 } | |
336 | |
337 overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0, | |
338 jit_type *arg1, jit_type *arg2) : function (f), can_error (e), | |
339 result (r), arguments (3) | |
340 { | |
341 arguments[0] = arg0; | |
342 arguments[1] = arg1; | |
343 arguments[2] = arg2; | |
344 } | |
345 | 338 |
346 overload (llvm::Function *f, bool e, jit_type *r, | 339 overload (llvm::Function *f, bool e, jit_type *r, |
347 const std::vector<jit_type *>& aarguments) | 340 const std::vector<jit_type *>& aarguments) |
348 : function (f), can_error (e), result (r), arguments (aarguments) | 341 : function (f), can_error (e), result (r), arguments (aarguments) |
349 {} | 342 {} |
357 void add_overload (const overload& func) | 350 void add_overload (const overload& func) |
358 { | 351 { |
359 add_overload (func, func.arguments); | 352 add_overload (func, func.arguments); |
360 } | 353 } |
361 | 354 |
362 void add_overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0) | 355 #define ADD_OVERLOAD(N) \ |
363 { | 356 void add_overload (llvm::Function *f, bool e, jit_type *ret, \ |
364 overload ol (f, e, r, arg0); | 357 OCT_MAKE_DECL_LIST (jit_type *, arg, N)) \ |
365 add_overload (ol); | 358 { \ |
366 } | 359 overload ol (f, e, ret, OCT_MAKE_ARG_LIST (arg, N)); \ |
367 | 360 add_overload (ol); \ |
368 void add_overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0, | 361 } |
369 jit_type *arg1) | 362 |
370 { | 363 ADD_OVERLOAD (1); |
371 overload ol (f, e, r, arg0, arg1); | 364 ADD_OVERLOAD (2); |
372 add_overload (ol); | 365 ADD_OVERLOAD (3); |
373 } | 366 |
374 | 367 #undef ADD_OVERLOAD |
375 void add_overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0, | |
376 jit_type *arg1, jit_type *arg2) | |
377 { | |
378 overload ol (f, e, r, arg0, arg1, arg2); | |
379 add_overload (ol); | |
380 } | |
381 | 368 |
382 void add_overload (llvm::Function *f, bool e, jit_type *r, | 369 void add_overload (llvm::Function *f, bool e, jit_type *r, |
383 const std::vector<jit_type *>& args) | 370 const std::vector<jit_type *>& args) |
384 { | 371 { |
385 overload ol (f, e, r, args); | 372 overload ol (f, e, r, args); |
618 | 605 |
619 void add_binary_icmp (jit_type *ty, int op, int llvm_op); | 606 void add_binary_icmp (jit_type *ty, int op, int llvm_op); |
620 | 607 |
621 void add_binary_fcmp (jit_type *ty, int op, int llvm_op); | 608 void add_binary_fcmp (jit_type *ty, int op, int llvm_op); |
622 | 609 |
610 | |
623 llvm::Function *create_function (const llvm::Twine& name, llvm::Type *ret) | 611 llvm::Function *create_function (const llvm::Twine& name, llvm::Type *ret) |
624 { | 612 { |
625 std::vector<llvm::Type *> args; | 613 std::vector<llvm::Type *> args; |
626 return create_function (name, ret, args); | 614 return create_function (name, ret, args); |
627 } | 615 } |
628 | 616 |
629 llvm::Function *create_function (const llvm::Twine& name, llvm::Type *ret, | 617 #define ASSIGN_ARG(i) args[i] = arg ## i; |
630 llvm::Type *arg0) | 618 #define CREATE_FUNCTIONT(TYPE, N) \ |
631 { | 619 llvm::Function *create_function (const llvm::Twine& name, TYPE *ret, \ |
632 std::vector<llvm::Type *> args (1, arg0); | 620 OCT_MAKE_DECL_LIST (TYPE *, arg, N)) \ |
633 return create_function (name, ret, args); | 621 { \ |
634 } | 622 std::vector<TYPE *> args (N); \ |
635 | 623 OCT_ITERATE_MACRO (ASSIGN_ARG, N); \ |
636 llvm::Function *create_function (const llvm::Twine& name, jit_type *ret, | 624 return create_function (name, ret, args); \ |
637 jit_type *arg0) | 625 } |
638 { | 626 |
639 return create_function (name, ret->to_llvm (), arg0->to_llvm ()); | 627 #define CREATE_FUNCTION(N) \ |
640 } | 628 CREATE_FUNCTIONT(llvm::Type, N) \ |
641 | 629 CREATE_FUNCTIONT(jit_type, N) |
642 llvm::Function *create_function (const llvm::Twine& name, llvm::Type *ret, | 630 |
643 llvm::Type *arg0, llvm::Type *arg1) | 631 CREATE_FUNCTION(1) |
644 { | 632 CREATE_FUNCTION(2) |
645 std::vector<llvm::Type *> args (2); | 633 CREATE_FUNCTION(3) |
646 args[0] = arg0; | 634 CREATE_FUNCTION(4) |
647 args[1] = arg1; | 635 |
648 return create_function (name, ret, args); | 636 #undef ASSIGN_ARG |
649 } | 637 #undef CREATE_FUNCTIONT |
650 | 638 #undef CREATE_FUNCTION |
651 llvm::Function *create_function (const llvm::Twine& name, jit_type *ret, | |
652 jit_type *arg0, jit_type *arg1) | |
653 { | |
654 return create_function (name, ret->to_llvm (), arg0->to_llvm (), | |
655 arg1->to_llvm ()); | |
656 } | |
657 | |
658 llvm::Function *create_function (const llvm::Twine& name, llvm::Type *ret, | |
659 llvm::Type *arg0, llvm::Type *arg1, | |
660 llvm::Type *arg2) | |
661 { | |
662 std::vector<llvm::Type *> args (3); | |
663 args[0] = arg0; | |
664 args[1] = arg1; | |
665 args[2] = arg2; | |
666 return create_function (name, ret, args); | |
667 } | |
668 | |
669 llvm::Function *create_function (const llvm::Twine& name, jit_type *ret, | |
670 jit_type *arg0, jit_type *arg1, | |
671 jit_type *arg2) | |
672 { | |
673 return create_function (name, ret->to_llvm (), arg0->to_llvm (), | |
674 arg1->to_llvm (), arg2->to_llvm ()); | |
675 } | |
676 | |
677 llvm::Function *create_function (const llvm::Twine& name, llvm::Type *ret, | |
678 llvm::Type *arg0, llvm::Type *arg1, | |
679 llvm::Type *arg2, llvm::Type *arg3) | |
680 { | |
681 std::vector<llvm::Type *> args (4); | |
682 args[0] = arg0; | |
683 args[1] = arg1; | |
684 args[2] = arg2; | |
685 args[3] = arg3; | |
686 return create_function (name, ret, args); | |
687 } | |
688 | 639 |
689 llvm::Function *create_function (const llvm::Twine& name, jit_type *ret, | 640 llvm::Function *create_function (const llvm::Twine& name, jit_type *ret, |
690 const std::vector<jit_type *>& args); | 641 const std::vector<jit_type *>& args); |
691 | 642 |
692 llvm::Function *create_function (const llvm::Twine& name, llvm::Type *ret, | 643 llvm::Function *create_function (const llvm::Twine& name, llvm::Type *ret, |
956 public: | 907 public: |
957 // FIXME: this code could be so much pretier with varadic templates... | 908 // FIXME: this code could be so much pretier with varadic templates... |
958 jit_instruction (void) : mid (next_id ()), mparent (0) | 909 jit_instruction (void) : mid (next_id ()), mparent (0) |
959 {} | 910 {} |
960 | 911 |
961 jit_instruction (size_t nargs) | 912 jit_instruction (size_t nargs) : mid (next_id ()), mparent (0) |
962 : already_infered (nargs, reinterpret_cast<jit_type *>(0)), | 913 { |
963 mid (next_id ()), mparent (0) | 914 already_infered.reserve (nargs); |
964 { | |
965 marguments.reserve (nargs); | 915 marguments.reserve (nargs); |
966 } | 916 } |
967 | 917 |
968 jit_instruction (jit_value *arg0) | 918 #define STASH_ARG(i) stash_argument (i, arg ## i); |
969 : already_infered (1, reinterpret_cast<jit_type *>(0)), marguments (1), | 919 #define JIT_INSTRUCTION_CTOR(N) \ |
970 mid (next_id ()), mparent (0) | 920 jit_instruction (OCT_MAKE_DECL_LIST (jit_value *, arg, N)) \ |
971 { | 921 : already_infered (N), marguments (N), mid (next_id ()), mparent (0) \ |
972 stash_argument (0, arg0); | 922 { \ |
973 } | 923 OCT_ITERATE_MACRO (STASH_ARG, N); \ |
974 | 924 } |
975 jit_instruction (jit_value *arg0, jit_value *arg1) | 925 |
976 : already_infered (2, reinterpret_cast<jit_type *>(0)), marguments (2), | 926 JIT_INSTRUCTION_CTOR(1) |
977 mid (next_id ()), mparent (0) | 927 JIT_INSTRUCTION_CTOR(2) |
978 { | 928 JIT_INSTRUCTION_CTOR(3) |
979 stash_argument (0, arg0); | 929 JIT_INSTRUCTION_CTOR(4) |
980 stash_argument (1, arg1); | 930 |
981 } | 931 #undef STASH_ARG |
982 | 932 #undef JIT_INSTRUCTION_CTOR |
983 jit_instruction (jit_value *arg0, jit_value *arg1, jit_value *arg2) | |
984 : already_infered (3, reinterpret_cast<jit_type *>(0)), marguments (3), | |
985 mid (next_id ()), mparent (0) | |
986 { | |
987 stash_argument (0, arg0); | |
988 stash_argument (1, arg1); | |
989 stash_argument (2, arg2); | |
990 } | |
991 | |
992 jit_instruction (jit_value *arg0, jit_value *arg1, jit_value *arg2, | |
993 jit_value *arg3) | |
994 : already_infered (3, reinterpret_cast<jit_type *>(0)), marguments (4), | |
995 mid (next_id ()), mparent (0) | |
996 { | |
997 stash_argument (0, arg0); | |
998 stash_argument (1, arg1); | |
999 stash_argument (2, arg2); | |
1000 stash_argument (3, arg3); | |
1001 } | |
1002 | 933 |
1003 static void reset_ids (void) | 934 static void reset_ids (void) |
1004 { | 935 { |
1005 next_id (true); | 936 next_id (true); |
1006 } | 937 } |
1682 | 1613 |
1683 class | 1614 class |
1684 jit_terminator : public jit_instruction | 1615 jit_terminator : public jit_instruction |
1685 { | 1616 { |
1686 public: | 1617 public: |
1687 jit_terminator (size_t asuccessor_count, jit_value *arg0) | 1618 #define JIT_TERMINATOR_CONST(N) \ |
1688 : jit_instruction (arg0), malive (asuccessor_count, false), | 1619 jit_terminator (size_t asuccessor_count, \ |
1689 mbranch_llvm (asuccessor_count, 0) {} | 1620 OCT_MAKE_DECL_LIST (jit_value *, arg, N)) \ |
1690 | 1621 : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), \ |
1691 jit_terminator (size_t asuccessor_count, jit_value *arg0, jit_value *arg1) | 1622 malive (asuccessor_count, false) {} |
1692 : jit_instruction (arg0, arg1), malive (asuccessor_count, false), | 1623 |
1693 mbranch_llvm (asuccessor_count, 0) {} | 1624 JIT_TERMINATOR_CONST (1) |
1694 | 1625 JIT_TERMINATOR_CONST (2) |
1695 jit_terminator (size_t asuccessor_count, jit_value *arg0, jit_value *arg1, | 1626 JIT_TERMINATOR_CONST (3) |
1696 jit_value *arg2) | 1627 |
1697 : jit_instruction (arg0, arg1, arg2), malive (asuccessor_count, false), | 1628 #undef JIT_TERMINATOR_CONST |
1698 mbranch_llvm (asuccessor_count, 0) {} | |
1699 | 1629 |
1700 jit_block *successor (size_t idx = 0) const | 1630 jit_block *successor (size_t idx = 0) const |
1701 { | 1631 { |
1702 return static_cast<jit_block *> (argument (idx)); | 1632 return static_cast<jit_block *> (argument (idx)); |
1703 } | 1633 } |
1704 | 1634 |
1705 // the llvm block between our parent and the given successor | |
1706 llvm::BasicBlock *branch_llvm (size_t idx = 0) const | |
1707 { | |
1708 return mbranch_llvm[idx] ? mbranch_llvm[idx] : parent ()->to_llvm (); | |
1709 } | |
1710 | |
1711 llvm::BasicBlock *branch_llvm (int idx) const | |
1712 { | |
1713 return branch_llvm (static_cast<size_t> (idx)); | |
1714 } | |
1715 | |
1716 llvm::BasicBlock *branch_llvm (const jit_block *asuccessor) const | |
1717 { | |
1718 return branch_llvm (successor_index (asuccessor)); | |
1719 } | |
1720 | |
1721 llvm::BasicBlock *successor_llvm (size_t idx = 0) const | 1635 llvm::BasicBlock *successor_llvm (size_t idx = 0) const |
1722 { | 1636 { |
1723 return mbranch_llvm[idx] ? mbranch_llvm[idx] : successor (idx)->to_llvm (); | 1637 return successor (idx)->to_llvm (); |
1724 } | 1638 } |
1725 | 1639 |
1726 size_t successor_index (const jit_block *asuccessor) const; | 1640 size_t successor_index (const jit_block *asuccessor) const; |
1727 | 1641 |
1728 std::ostream& print_successor (std::ostream& os, size_t idx = 0) const | 1642 std::ostream& print_successor (std::ostream& os, size_t idx = 0) const |
1752 llvm::TerminatorInst *to_llvm (void) const; | 1666 llvm::TerminatorInst *to_llvm (void) const; |
1753 protected: | 1667 protected: |
1754 virtual bool check_alive (size_t) const { return true; } | 1668 virtual bool check_alive (size_t) const { return true; } |
1755 private: | 1669 private: |
1756 std::vector<bool> malive; | 1670 std::vector<bool> malive; |
1757 std::vector<llvm::BasicBlock *> mbranch_llvm; | |
1758 }; | 1671 }; |
1759 | 1672 |
1760 class | 1673 class |
1761 jit_branch : public jit_terminator | 1674 jit_branch : public jit_terminator |
1762 { | 1675 { |
1808 | 1721 |
1809 class | 1722 class |
1810 jit_call : public jit_instruction | 1723 jit_call : public jit_instruction |
1811 { | 1724 { |
1812 public: | 1725 public: |
1813 jit_call (const jit_function& afunction, | 1726 #define JIT_CALL_CONST(N) \ |
1814 jit_value *arg0) : jit_instruction (arg0), mfunction (afunction) | 1727 jit_call (const jit_function& afunction, \ |
1815 {} | 1728 OCT_MAKE_DECL_LIST (jit_value *, arg, N)) \ |
1816 | 1729 : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), mfunction (afunction) {} \ |
1817 jit_call (const jit_function& (*afunction) (void), | 1730 \ |
1818 jit_value *arg0) : jit_instruction (arg0), | 1731 jit_call (const jit_function& (*afunction) (void), \ |
1819 mfunction (afunction ()) {} | 1732 OCT_MAKE_DECL_LIST (jit_value *, arg, N)) \ |
1820 | 1733 : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), mfunction (afunction ()) {} |
1821 jit_call (const jit_function& afunction, | 1734 |
1822 jit_value *arg0, jit_value *arg1) : jit_instruction (arg0, arg1), | 1735 JIT_CALL_CONST (1) |
1823 mfunction (afunction) {} | 1736 JIT_CALL_CONST (2) |
1824 | 1737 JIT_CALL_CONST (3) |
1825 jit_call (const jit_function& (*afunction) (void), | 1738 JIT_CALL_CONST (4) |
1826 jit_value *arg0, jit_value *arg1) : jit_instruction (arg0, arg1), | 1739 |
1827 mfunction (afunction ()) {} | 1740 #undef JIT_CALL_CONST |
1828 | |
1829 jit_call (const jit_function& (*afunction) (void), | |
1830 jit_value *arg0, jit_value *arg1, jit_value *arg2) | |
1831 : jit_instruction (arg0, arg1, arg2), mfunction (afunction ()) {} | |
1832 | |
1833 jit_call (const jit_function& (*afunction) (void), | |
1834 jit_value *arg0, jit_value *arg1, jit_value *arg2, jit_value *arg3) | |
1835 : jit_instruction (arg0, arg1, arg2, arg3), mfunction (afunction ()) {} | |
1836 | 1741 |
1837 | 1742 |
1838 const jit_function& function (void) const { return mfunction; } | 1743 const jit_function& function (void) const { return mfunction; } |
1839 | 1744 |
1840 bool can_error (void) const | 1745 bool can_error (void) const |
2124 T *ret = new T(); | 2029 T *ret = new T(); |
2125 track_value (ret); | 2030 track_value (ret); |
2126 return ret; | 2031 return ret; |
2127 } | 2032 } |
2128 | 2033 |
2129 template <typename T, typename ARG0> | 2034 #define DECL_ARG(n) const ARG ## n& arg ## n |
2130 T *create (const ARG0& arg0) | 2035 #define JIT_CREATE(N) \ |
2131 { | 2036 template <typename T, OCT_MAKE_DECL_LIST (typename, ARG, N)> \ |
2132 T *ret = new T(arg0); | 2037 T *create (OCT_MAKE_LIST (DECL_ARG, N)) \ |
2133 track_value (ret); | 2038 { \ |
2134 return ret; | 2039 T *ret = new T (OCT_MAKE_ARG_LIST (arg, N)); \ |
2135 } | 2040 track_value (ret); \ |
2136 | 2041 return ret; \ |
2137 template <typename T, typename ARG0, typename ARG1> | 2042 } |
2138 T *create (const ARG0& arg0, const ARG1& arg1) | 2043 |
2139 { | 2044 JIT_CREATE (1) |
2140 T *ret = new T(arg0, arg1); | 2045 JIT_CREATE (2) |
2141 track_value (ret); | 2046 JIT_CREATE (3) |
2142 return ret; | 2047 JIT_CREATE (4) |
2143 } | 2048 |
2144 | 2049 #undef JIT_CREATE |
2145 template <typename T, typename ARG0, typename ARG1, typename ARG2> | 2050 |
2146 T *create (const ARG0& arg0, const ARG1& arg1, const ARG2& arg2) | 2051 #define JIT_CREATE_CHECKED(N) \ |
2147 { | 2052 template <OCT_MAKE_DECL_LIST (typename, ARG, N)> \ |
2148 T *ret = new T(arg0, arg1, arg2); | 2053 jit_call *create_checked (OCT_MAKE_LIST (DECL_ARG, N)) \ |
2149 track_value (ret); | 2054 { \ |
2150 return ret; | 2055 jit_call *ret = create<jit_call> (OCT_MAKE_ARG_LIST (arg, N)); \ |
2151 } | 2056 return create_checked_impl (ret); \ |
2152 | 2057 } |
2153 template <typename T, typename ARG0, typename ARG1, typename ARG2, | 2058 |
2154 typename ARG3> | 2059 JIT_CREATE_CHECKED (1) |
2155 T *create (const ARG0& arg0, const ARG1& arg1, const ARG2& arg2, | 2060 JIT_CREATE_CHECKED (2) |
2156 const ARG3& arg3) | 2061 JIT_CREATE_CHECKED (3) |
2157 { | 2062 JIT_CREATE_CHECKED (4) |
2158 T *ret = new T(arg0, arg1, arg2, arg3); | 2063 |
2159 track_value (ret); | 2064 #undef JIT_CREATE_CHECKED |
2160 return ret; | 2065 #undef DECL_ARG |
2161 } | |
2162 | |
2163 template <typename ARG0, typename ARG1> | |
2164 jit_call *create_checked (const ARG0& arg0, const ARG1& arg1) | |
2165 { | |
2166 jit_call *ret = create<jit_call> (arg0, arg1); | |
2167 return create_checked_impl (ret); | |
2168 } | |
2169 | |
2170 template <typename ARG0, typename ARG1, typename ARG2> | |
2171 jit_call *create_checked (const ARG0& arg0, const ARG1& arg1, | |
2172 const ARG2& arg2) | |
2173 { | |
2174 jit_call *ret = create<jit_call> (arg0, arg1, arg2); | |
2175 return create_checked_impl (ret); | |
2176 } | |
2177 | |
2178 template <typename ARG0, typename ARG1, typename ARG2, typename ARG3> | |
2179 jit_call *create_checked (const ARG0& arg0, const ARG1& arg1, | |
2180 const ARG2& arg2, const ARG3& arg3) | |
2181 { | |
2182 jit_call *ret = create<jit_call> (arg0, arg1, arg2, arg3); | |
2183 return create_checked_impl (ret); | |
2184 } | |
2185 | 2066 |
2186 typedef std::list<jit_block *> block_list; | 2067 typedef std::list<jit_block *> block_list; |
2187 typedef block_list::iterator block_iterator; | 2068 typedef block_list::iterator block_iterator; |
2188 | 2069 |
2189 void append (jit_block *ablock); | 2070 void append (jit_block *ablock); |