123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- //===--- VariadicFunctions.h - Variadic Functions ---------------*- C++ -*-===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file implements compile-time type-safe variadic functions.
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_ADT_VARIADICFUNCTION_H
- #define LLVM_ADT_VARIADICFUNCTION_H
- #include "llvm/ADT/ArrayRef.h"
- namespace llvm {
- // Define macros to aid in expanding a comma separated series with the index of
- // the series pasted onto the last token.
- #define LLVM_COMMA_JOIN1(x) x ## 0
- #define LLVM_COMMA_JOIN2(x) LLVM_COMMA_JOIN1(x), x ## 1
- #define LLVM_COMMA_JOIN3(x) LLVM_COMMA_JOIN2(x), x ## 2
- #define LLVM_COMMA_JOIN4(x) LLVM_COMMA_JOIN3(x), x ## 3
- #define LLVM_COMMA_JOIN5(x) LLVM_COMMA_JOIN4(x), x ## 4
- #define LLVM_COMMA_JOIN6(x) LLVM_COMMA_JOIN5(x), x ## 5
- #define LLVM_COMMA_JOIN7(x) LLVM_COMMA_JOIN6(x), x ## 6
- #define LLVM_COMMA_JOIN8(x) LLVM_COMMA_JOIN7(x), x ## 7
- #define LLVM_COMMA_JOIN9(x) LLVM_COMMA_JOIN8(x), x ## 8
- #define LLVM_COMMA_JOIN10(x) LLVM_COMMA_JOIN9(x), x ## 9
- #define LLVM_COMMA_JOIN11(x) LLVM_COMMA_JOIN10(x), x ## 10
- #define LLVM_COMMA_JOIN12(x) LLVM_COMMA_JOIN11(x), x ## 11
- #define LLVM_COMMA_JOIN13(x) LLVM_COMMA_JOIN12(x), x ## 12
- #define LLVM_COMMA_JOIN14(x) LLVM_COMMA_JOIN13(x), x ## 13
- #define LLVM_COMMA_JOIN15(x) LLVM_COMMA_JOIN14(x), x ## 14
- #define LLVM_COMMA_JOIN16(x) LLVM_COMMA_JOIN15(x), x ## 15
- #define LLVM_COMMA_JOIN17(x) LLVM_COMMA_JOIN16(x), x ## 16
- #define LLVM_COMMA_JOIN18(x) LLVM_COMMA_JOIN17(x), x ## 17
- #define LLVM_COMMA_JOIN19(x) LLVM_COMMA_JOIN18(x), x ## 18
- #define LLVM_COMMA_JOIN20(x) LLVM_COMMA_JOIN19(x), x ## 19
- #define LLVM_COMMA_JOIN21(x) LLVM_COMMA_JOIN20(x), x ## 20
- #define LLVM_COMMA_JOIN22(x) LLVM_COMMA_JOIN21(x), x ## 21
- #define LLVM_COMMA_JOIN23(x) LLVM_COMMA_JOIN22(x), x ## 22
- #define LLVM_COMMA_JOIN24(x) LLVM_COMMA_JOIN23(x), x ## 23
- #define LLVM_COMMA_JOIN25(x) LLVM_COMMA_JOIN24(x), x ## 24
- #define LLVM_COMMA_JOIN26(x) LLVM_COMMA_JOIN25(x), x ## 25
- #define LLVM_COMMA_JOIN27(x) LLVM_COMMA_JOIN26(x), x ## 26
- #define LLVM_COMMA_JOIN28(x) LLVM_COMMA_JOIN27(x), x ## 27
- #define LLVM_COMMA_JOIN29(x) LLVM_COMMA_JOIN28(x), x ## 28
- #define LLVM_COMMA_JOIN30(x) LLVM_COMMA_JOIN29(x), x ## 29
- #define LLVM_COMMA_JOIN31(x) LLVM_COMMA_JOIN30(x), x ## 30
- #define LLVM_COMMA_JOIN32(x) LLVM_COMMA_JOIN31(x), x ## 31
- /// \brief Class which can simulate a type-safe variadic function.
- ///
- /// The VariadicFunction class template makes it easy to define
- /// type-safe variadic functions where all arguments have the same
- /// type.
- ///
- /// Suppose we need a variadic function like this:
- ///
- /// ResultT Foo(const ArgT &A_0, const ArgT &A_1, ..., const ArgT &A_N);
- ///
- /// Instead of many overloads of Foo(), we only need to define a helper
- /// function that takes an array of arguments:
- ///
- /// ResultT FooImpl(ArrayRef<const ArgT *> Args) {
- /// // 'Args[i]' is a pointer to the i-th argument passed to Foo().
- /// ...
- /// }
- ///
- /// and then define Foo() like this:
- ///
- /// const VariadicFunction<ResultT, ArgT, FooImpl> Foo;
- ///
- /// VariadicFunction takes care of defining the overloads of Foo().
- ///
- /// Actually, Foo is a function object (i.e. functor) instead of a plain
- /// function. This object is stateless and its constructor/destructor
- /// does nothing, so it's safe to create global objects and call Foo(...) at
- /// any time.
- ///
- /// Sometimes we need a variadic function to have some fixed leading
- /// arguments whose types may be different from that of the optional
- /// arguments. For example:
- ///
- /// bool FullMatch(const StringRef &S, const RE &Regex,
- /// const ArgT &A_0, ..., const ArgT &A_N);
- ///
- /// VariadicFunctionN is for such cases, where N is the number of fixed
- /// arguments. It is like VariadicFunction, except that it takes N more
- /// template arguments for the types of the fixed arguments:
- ///
- /// bool FullMatchImpl(const StringRef &S, const RE &Regex,
- /// ArrayRef<const ArgT *> Args) { ... }
- /// const VariadicFunction2<bool, const StringRef&,
- /// const RE&, ArgT, FullMatchImpl>
- /// FullMatch;
- ///
- /// Currently VariadicFunction and friends support up-to 3
- /// fixed leading arguments and up-to 32 optional arguments.
- template <typename ResultT, typename ArgT,
- ResultT (*Func)(ArrayRef<const ArgT *>)>
- struct VariadicFunction {
- ResultT operator()() const {
- return Func(None);
- }
- #define LLVM_DEFINE_OVERLOAD(N) \
- ResultT operator()(LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
- const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
- return Func(makeArrayRef(Args)); \
- }
- LLVM_DEFINE_OVERLOAD(1)
- LLVM_DEFINE_OVERLOAD(2)
- LLVM_DEFINE_OVERLOAD(3)
- LLVM_DEFINE_OVERLOAD(4)
- LLVM_DEFINE_OVERLOAD(5)
- LLVM_DEFINE_OVERLOAD(6)
- LLVM_DEFINE_OVERLOAD(7)
- LLVM_DEFINE_OVERLOAD(8)
- LLVM_DEFINE_OVERLOAD(9)
- LLVM_DEFINE_OVERLOAD(10)
- LLVM_DEFINE_OVERLOAD(11)
- LLVM_DEFINE_OVERLOAD(12)
- LLVM_DEFINE_OVERLOAD(13)
- LLVM_DEFINE_OVERLOAD(14)
- LLVM_DEFINE_OVERLOAD(15)
- LLVM_DEFINE_OVERLOAD(16)
- LLVM_DEFINE_OVERLOAD(17)
- LLVM_DEFINE_OVERLOAD(18)
- LLVM_DEFINE_OVERLOAD(19)
- LLVM_DEFINE_OVERLOAD(20)
- LLVM_DEFINE_OVERLOAD(21)
- LLVM_DEFINE_OVERLOAD(22)
- LLVM_DEFINE_OVERLOAD(23)
- LLVM_DEFINE_OVERLOAD(24)
- LLVM_DEFINE_OVERLOAD(25)
- LLVM_DEFINE_OVERLOAD(26)
- LLVM_DEFINE_OVERLOAD(27)
- LLVM_DEFINE_OVERLOAD(28)
- LLVM_DEFINE_OVERLOAD(29)
- LLVM_DEFINE_OVERLOAD(30)
- LLVM_DEFINE_OVERLOAD(31)
- LLVM_DEFINE_OVERLOAD(32)
- #undef LLVM_DEFINE_OVERLOAD
- };
- template <typename ResultT, typename Param0T, typename ArgT,
- ResultT (*Func)(Param0T, ArrayRef<const ArgT *>)>
- struct VariadicFunction1 {
- ResultT operator()(Param0T P0) const {
- return Func(P0, None);
- }
- #define LLVM_DEFINE_OVERLOAD(N) \
- ResultT operator()(Param0T P0, LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
- const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
- return Func(P0, makeArrayRef(Args)); \
- }
- LLVM_DEFINE_OVERLOAD(1)
- LLVM_DEFINE_OVERLOAD(2)
- LLVM_DEFINE_OVERLOAD(3)
- LLVM_DEFINE_OVERLOAD(4)
- LLVM_DEFINE_OVERLOAD(5)
- LLVM_DEFINE_OVERLOAD(6)
- LLVM_DEFINE_OVERLOAD(7)
- LLVM_DEFINE_OVERLOAD(8)
- LLVM_DEFINE_OVERLOAD(9)
- LLVM_DEFINE_OVERLOAD(10)
- LLVM_DEFINE_OVERLOAD(11)
- LLVM_DEFINE_OVERLOAD(12)
- LLVM_DEFINE_OVERLOAD(13)
- LLVM_DEFINE_OVERLOAD(14)
- LLVM_DEFINE_OVERLOAD(15)
- LLVM_DEFINE_OVERLOAD(16)
- LLVM_DEFINE_OVERLOAD(17)
- LLVM_DEFINE_OVERLOAD(18)
- LLVM_DEFINE_OVERLOAD(19)
- LLVM_DEFINE_OVERLOAD(20)
- LLVM_DEFINE_OVERLOAD(21)
- LLVM_DEFINE_OVERLOAD(22)
- LLVM_DEFINE_OVERLOAD(23)
- LLVM_DEFINE_OVERLOAD(24)
- LLVM_DEFINE_OVERLOAD(25)
- LLVM_DEFINE_OVERLOAD(26)
- LLVM_DEFINE_OVERLOAD(27)
- LLVM_DEFINE_OVERLOAD(28)
- LLVM_DEFINE_OVERLOAD(29)
- LLVM_DEFINE_OVERLOAD(30)
- LLVM_DEFINE_OVERLOAD(31)
- LLVM_DEFINE_OVERLOAD(32)
- #undef LLVM_DEFINE_OVERLOAD
- };
- template <typename ResultT, typename Param0T, typename Param1T, typename ArgT,
- ResultT (*Func)(Param0T, Param1T, ArrayRef<const ArgT *>)>
- struct VariadicFunction2 {
- ResultT operator()(Param0T P0, Param1T P1) const {
- return Func(P0, P1, None);
- }
- #define LLVM_DEFINE_OVERLOAD(N) \
- ResultT operator()(Param0T P0, Param1T P1, \
- LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
- const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
- return Func(P0, P1, makeArrayRef(Args)); \
- }
- LLVM_DEFINE_OVERLOAD(1)
- LLVM_DEFINE_OVERLOAD(2)
- LLVM_DEFINE_OVERLOAD(3)
- LLVM_DEFINE_OVERLOAD(4)
- LLVM_DEFINE_OVERLOAD(5)
- LLVM_DEFINE_OVERLOAD(6)
- LLVM_DEFINE_OVERLOAD(7)
- LLVM_DEFINE_OVERLOAD(8)
- LLVM_DEFINE_OVERLOAD(9)
- LLVM_DEFINE_OVERLOAD(10)
- LLVM_DEFINE_OVERLOAD(11)
- LLVM_DEFINE_OVERLOAD(12)
- LLVM_DEFINE_OVERLOAD(13)
- LLVM_DEFINE_OVERLOAD(14)
- LLVM_DEFINE_OVERLOAD(15)
- LLVM_DEFINE_OVERLOAD(16)
- LLVM_DEFINE_OVERLOAD(17)
- LLVM_DEFINE_OVERLOAD(18)
- LLVM_DEFINE_OVERLOAD(19)
- LLVM_DEFINE_OVERLOAD(20)
- LLVM_DEFINE_OVERLOAD(21)
- LLVM_DEFINE_OVERLOAD(22)
- LLVM_DEFINE_OVERLOAD(23)
- LLVM_DEFINE_OVERLOAD(24)
- LLVM_DEFINE_OVERLOAD(25)
- LLVM_DEFINE_OVERLOAD(26)
- LLVM_DEFINE_OVERLOAD(27)
- LLVM_DEFINE_OVERLOAD(28)
- LLVM_DEFINE_OVERLOAD(29)
- LLVM_DEFINE_OVERLOAD(30)
- LLVM_DEFINE_OVERLOAD(31)
- LLVM_DEFINE_OVERLOAD(32)
- #undef LLVM_DEFINE_OVERLOAD
- };
- template <typename ResultT, typename Param0T, typename Param1T,
- typename Param2T, typename ArgT,
- ResultT (*Func)(Param0T, Param1T, Param2T, ArrayRef<const ArgT *>)>
- struct VariadicFunction3 {
- ResultT operator()(Param0T P0, Param1T P1, Param2T P2) const {
- return Func(P0, P1, P2, None);
- }
- #define LLVM_DEFINE_OVERLOAD(N) \
- ResultT operator()(Param0T P0, Param1T P1, Param2T P2, \
- LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
- const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
- return Func(P0, P1, P2, makeArrayRef(Args)); \
- }
- LLVM_DEFINE_OVERLOAD(1)
- LLVM_DEFINE_OVERLOAD(2)
- LLVM_DEFINE_OVERLOAD(3)
- LLVM_DEFINE_OVERLOAD(4)
- LLVM_DEFINE_OVERLOAD(5)
- LLVM_DEFINE_OVERLOAD(6)
- LLVM_DEFINE_OVERLOAD(7)
- LLVM_DEFINE_OVERLOAD(8)
- LLVM_DEFINE_OVERLOAD(9)
- LLVM_DEFINE_OVERLOAD(10)
- LLVM_DEFINE_OVERLOAD(11)
- LLVM_DEFINE_OVERLOAD(12)
- LLVM_DEFINE_OVERLOAD(13)
- LLVM_DEFINE_OVERLOAD(14)
- LLVM_DEFINE_OVERLOAD(15)
- LLVM_DEFINE_OVERLOAD(16)
- LLVM_DEFINE_OVERLOAD(17)
- LLVM_DEFINE_OVERLOAD(18)
- LLVM_DEFINE_OVERLOAD(19)
- LLVM_DEFINE_OVERLOAD(20)
- LLVM_DEFINE_OVERLOAD(21)
- LLVM_DEFINE_OVERLOAD(22)
- LLVM_DEFINE_OVERLOAD(23)
- LLVM_DEFINE_OVERLOAD(24)
- LLVM_DEFINE_OVERLOAD(25)
- LLVM_DEFINE_OVERLOAD(26)
- LLVM_DEFINE_OVERLOAD(27)
- LLVM_DEFINE_OVERLOAD(28)
- LLVM_DEFINE_OVERLOAD(29)
- LLVM_DEFINE_OVERLOAD(30)
- LLVM_DEFINE_OVERLOAD(31)
- LLVM_DEFINE_OVERLOAD(32)
- #undef LLVM_DEFINE_OVERLOAD
- };
- // Cleanup the macro namespace.
- #undef LLVM_COMMA_JOIN1
- #undef LLVM_COMMA_JOIN2
- #undef LLVM_COMMA_JOIN3
- #undef LLVM_COMMA_JOIN4
- #undef LLVM_COMMA_JOIN5
- #undef LLVM_COMMA_JOIN6
- #undef LLVM_COMMA_JOIN7
- #undef LLVM_COMMA_JOIN8
- #undef LLVM_COMMA_JOIN9
- #undef LLVM_COMMA_JOIN10
- #undef LLVM_COMMA_JOIN11
- #undef LLVM_COMMA_JOIN12
- #undef LLVM_COMMA_JOIN13
- #undef LLVM_COMMA_JOIN14
- #undef LLVM_COMMA_JOIN15
- #undef LLVM_COMMA_JOIN16
- #undef LLVM_COMMA_JOIN17
- #undef LLVM_COMMA_JOIN18
- #undef LLVM_COMMA_JOIN19
- #undef LLVM_COMMA_JOIN20
- #undef LLVM_COMMA_JOIN21
- #undef LLVM_COMMA_JOIN22
- #undef LLVM_COMMA_JOIN23
- #undef LLVM_COMMA_JOIN24
- #undef LLVM_COMMA_JOIN25
- #undef LLVM_COMMA_JOIN26
- #undef LLVM_COMMA_JOIN27
- #undef LLVM_COMMA_JOIN28
- #undef LLVM_COMMA_JOIN29
- #undef LLVM_COMMA_JOIN30
- #undef LLVM_COMMA_JOIN31
- #undef LLVM_COMMA_JOIN32
- } // end namespace llvm
- #endif // LLVM_ADT_VARIADICFUNCTION_H
|