Home | History | Annotate | Download | only in ADT
      1 //===--- VariadicFunctions.h - Variadic Functions ---------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  This file implements compile-time type-safe variadic functions.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_ADT_VARIADICFUNCTION_H
     15 #define LLVM_ADT_VARIADICFUNCTION_H
     16 
     17 #include "llvm/ADT/ArrayRef.h"
     18 
     19 namespace llvm {
     20 
     21 // Define macros to aid in expanding a comma separated series with the index of
     22 // the series pasted onto the last token.
     23 #define LLVM_COMMA_JOIN1(x) x ## 0
     24 #define LLVM_COMMA_JOIN2(x) LLVM_COMMA_JOIN1(x), x ## 1
     25 #define LLVM_COMMA_JOIN3(x) LLVM_COMMA_JOIN2(x), x ## 2
     26 #define LLVM_COMMA_JOIN4(x) LLVM_COMMA_JOIN3(x), x ## 3
     27 #define LLVM_COMMA_JOIN5(x) LLVM_COMMA_JOIN4(x), x ## 4
     28 #define LLVM_COMMA_JOIN6(x) LLVM_COMMA_JOIN5(x), x ## 5
     29 #define LLVM_COMMA_JOIN7(x) LLVM_COMMA_JOIN6(x), x ## 6
     30 #define LLVM_COMMA_JOIN8(x) LLVM_COMMA_JOIN7(x), x ## 7
     31 #define LLVM_COMMA_JOIN9(x) LLVM_COMMA_JOIN8(x), x ## 8
     32 #define LLVM_COMMA_JOIN10(x) LLVM_COMMA_JOIN9(x), x ## 9
     33 #define LLVM_COMMA_JOIN11(x) LLVM_COMMA_JOIN10(x), x ## 10
     34 #define LLVM_COMMA_JOIN12(x) LLVM_COMMA_JOIN11(x), x ## 11
     35 #define LLVM_COMMA_JOIN13(x) LLVM_COMMA_JOIN12(x), x ## 12
     36 #define LLVM_COMMA_JOIN14(x) LLVM_COMMA_JOIN13(x), x ## 13
     37 #define LLVM_COMMA_JOIN15(x) LLVM_COMMA_JOIN14(x), x ## 14
     38 #define LLVM_COMMA_JOIN16(x) LLVM_COMMA_JOIN15(x), x ## 15
     39 #define LLVM_COMMA_JOIN17(x) LLVM_COMMA_JOIN16(x), x ## 16
     40 #define LLVM_COMMA_JOIN18(x) LLVM_COMMA_JOIN17(x), x ## 17
     41 #define LLVM_COMMA_JOIN19(x) LLVM_COMMA_JOIN18(x), x ## 18
     42 #define LLVM_COMMA_JOIN20(x) LLVM_COMMA_JOIN19(x), x ## 19
     43 #define LLVM_COMMA_JOIN21(x) LLVM_COMMA_JOIN20(x), x ## 20
     44 #define LLVM_COMMA_JOIN22(x) LLVM_COMMA_JOIN21(x), x ## 21
     45 #define LLVM_COMMA_JOIN23(x) LLVM_COMMA_JOIN22(x), x ## 22
     46 #define LLVM_COMMA_JOIN24(x) LLVM_COMMA_JOIN23(x), x ## 23
     47 #define LLVM_COMMA_JOIN25(x) LLVM_COMMA_JOIN24(x), x ## 24
     48 #define LLVM_COMMA_JOIN26(x) LLVM_COMMA_JOIN25(x), x ## 25
     49 #define LLVM_COMMA_JOIN27(x) LLVM_COMMA_JOIN26(x), x ## 26
     50 #define LLVM_COMMA_JOIN28(x) LLVM_COMMA_JOIN27(x), x ## 27
     51 #define LLVM_COMMA_JOIN29(x) LLVM_COMMA_JOIN28(x), x ## 28
     52 #define LLVM_COMMA_JOIN30(x) LLVM_COMMA_JOIN29(x), x ## 29
     53 #define LLVM_COMMA_JOIN31(x) LLVM_COMMA_JOIN30(x), x ## 30
     54 #define LLVM_COMMA_JOIN32(x) LLVM_COMMA_JOIN31(x), x ## 31
     55 
     56 /// \brief Class which can simulate a type-safe variadic function.
     57 ///
     58 /// The VariadicFunction class template makes it easy to define
     59 /// type-safe variadic functions where all arguments have the same
     60 /// type.
     61 ///
     62 /// Suppose we need a variadic function like this:
     63 ///
     64 ///   ResultT Foo(const ArgT &A_0, const ArgT &A_1, ..., const ArgT &A_N);
     65 ///
     66 /// Instead of many overloads of Foo(), we only need to define a helper
     67 /// function that takes an array of arguments:
     68 ///
     69 ///   ResultT FooImpl(ArrayRef<const ArgT *> Args) {
     70 ///     // 'Args[i]' is a pointer to the i-th argument passed to Foo().
     71 ///     ...
     72 ///   }
     73 ///
     74 /// and then define Foo() like this:
     75 ///
     76 ///   const VariadicFunction<ResultT, ArgT, FooImpl> Foo;
     77 ///
     78 /// VariadicFunction takes care of defining the overloads of Foo().
     79 ///
     80 /// Actually, Foo is a function object (i.e. functor) instead of a plain
     81 /// function.  This object is stateless and its constructor/destructor
     82 /// does nothing, so it's safe to create global objects and call Foo(...) at
     83 /// any time.
     84 ///
     85 /// Sometimes we need a variadic function to have some fixed leading
     86 /// arguments whose types may be different from that of the optional
     87 /// arguments.  For example:
     88 ///
     89 ///   bool FullMatch(const StringRef &S, const RE &Regex,
     90 ///                  const ArgT &A_0, ..., const ArgT &A_N);
     91 ///
     92 /// VariadicFunctionN is for such cases, where N is the number of fixed
     93 /// arguments.  It is like VariadicFunction, except that it takes N more
     94 /// template arguments for the types of the fixed arguments:
     95 ///
     96 ///   bool FullMatchImpl(const StringRef &S, const RE &Regex,
     97 ///                      ArrayRef<const ArgT *> Args) { ... }
     98 ///   const VariadicFunction2<bool, const StringRef&,
     99 ///                           const RE&, ArgT, FullMatchImpl>
    100 ///       FullMatch;
    101 ///
    102 /// Currently VariadicFunction and friends support up-to 3
    103 /// fixed leading arguments and up-to 32 optional arguments.
    104 template <typename ResultT, typename ArgT,
    105           ResultT (*Func)(ArrayRef<const ArgT *>)>
    106 struct VariadicFunction {
    107   ResultT operator()() const {
    108     return Func(None);
    109   }
    110 
    111 #define LLVM_DEFINE_OVERLOAD(N) \
    112   ResultT operator()(LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
    113     const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
    114     return Func(makeArrayRef(Args)); \
    115   }
    116   LLVM_DEFINE_OVERLOAD(1)
    117   LLVM_DEFINE_OVERLOAD(2)
    118   LLVM_DEFINE_OVERLOAD(3)
    119   LLVM_DEFINE_OVERLOAD(4)
    120   LLVM_DEFINE_OVERLOAD(5)
    121   LLVM_DEFINE_OVERLOAD(6)
    122   LLVM_DEFINE_OVERLOAD(7)
    123   LLVM_DEFINE_OVERLOAD(8)
    124   LLVM_DEFINE_OVERLOAD(9)
    125   LLVM_DEFINE_OVERLOAD(10)
    126   LLVM_DEFINE_OVERLOAD(11)
    127   LLVM_DEFINE_OVERLOAD(12)
    128   LLVM_DEFINE_OVERLOAD(13)
    129   LLVM_DEFINE_OVERLOAD(14)
    130   LLVM_DEFINE_OVERLOAD(15)
    131   LLVM_DEFINE_OVERLOAD(16)
    132   LLVM_DEFINE_OVERLOAD(17)
    133   LLVM_DEFINE_OVERLOAD(18)
    134   LLVM_DEFINE_OVERLOAD(19)
    135   LLVM_DEFINE_OVERLOAD(20)
    136   LLVM_DEFINE_OVERLOAD(21)
    137   LLVM_DEFINE_OVERLOAD(22)
    138   LLVM_DEFINE_OVERLOAD(23)
    139   LLVM_DEFINE_OVERLOAD(24)
    140   LLVM_DEFINE_OVERLOAD(25)
    141   LLVM_DEFINE_OVERLOAD(26)
    142   LLVM_DEFINE_OVERLOAD(27)
    143   LLVM_DEFINE_OVERLOAD(28)
    144   LLVM_DEFINE_OVERLOAD(29)
    145   LLVM_DEFINE_OVERLOAD(30)
    146   LLVM_DEFINE_OVERLOAD(31)
    147   LLVM_DEFINE_OVERLOAD(32)
    148 #undef LLVM_DEFINE_OVERLOAD
    149 };
    150 
    151 template <typename ResultT, typename Param0T, typename ArgT,
    152           ResultT (*Func)(Param0T, ArrayRef<const ArgT *>)>
    153 struct VariadicFunction1 {
    154   ResultT operator()(Param0T P0) const {
    155     return Func(P0, None);
    156   }
    157 
    158 #define LLVM_DEFINE_OVERLOAD(N) \
    159   ResultT operator()(Param0T P0, LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
    160     const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
    161     return Func(P0, makeArrayRef(Args)); \
    162   }
    163   LLVM_DEFINE_OVERLOAD(1)
    164   LLVM_DEFINE_OVERLOAD(2)
    165   LLVM_DEFINE_OVERLOAD(3)
    166   LLVM_DEFINE_OVERLOAD(4)
    167   LLVM_DEFINE_OVERLOAD(5)
    168   LLVM_DEFINE_OVERLOAD(6)
    169   LLVM_DEFINE_OVERLOAD(7)
    170   LLVM_DEFINE_OVERLOAD(8)
    171   LLVM_DEFINE_OVERLOAD(9)
    172   LLVM_DEFINE_OVERLOAD(10)
    173   LLVM_DEFINE_OVERLOAD(11)
    174   LLVM_DEFINE_OVERLOAD(12)
    175   LLVM_DEFINE_OVERLOAD(13)
    176   LLVM_DEFINE_OVERLOAD(14)
    177   LLVM_DEFINE_OVERLOAD(15)
    178   LLVM_DEFINE_OVERLOAD(16)
    179   LLVM_DEFINE_OVERLOAD(17)
    180   LLVM_DEFINE_OVERLOAD(18)
    181   LLVM_DEFINE_OVERLOAD(19)
    182   LLVM_DEFINE_OVERLOAD(20)
    183   LLVM_DEFINE_OVERLOAD(21)
    184   LLVM_DEFINE_OVERLOAD(22)
    185   LLVM_DEFINE_OVERLOAD(23)
    186   LLVM_DEFINE_OVERLOAD(24)
    187   LLVM_DEFINE_OVERLOAD(25)
    188   LLVM_DEFINE_OVERLOAD(26)
    189   LLVM_DEFINE_OVERLOAD(27)
    190   LLVM_DEFINE_OVERLOAD(28)
    191   LLVM_DEFINE_OVERLOAD(29)
    192   LLVM_DEFINE_OVERLOAD(30)
    193   LLVM_DEFINE_OVERLOAD(31)
    194   LLVM_DEFINE_OVERLOAD(32)
    195 #undef LLVM_DEFINE_OVERLOAD
    196 };
    197 
    198 template <typename ResultT, typename Param0T, typename Param1T, typename ArgT,
    199           ResultT (*Func)(Param0T, Param1T, ArrayRef<const ArgT *>)>
    200 struct VariadicFunction2 {
    201   ResultT operator()(Param0T P0, Param1T P1) const {
    202     return Func(P0, P1, None);
    203   }
    204 
    205 #define LLVM_DEFINE_OVERLOAD(N) \
    206   ResultT operator()(Param0T P0, Param1T P1, \
    207                      LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
    208     const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
    209     return Func(P0, P1, makeArrayRef(Args)); \
    210   }
    211   LLVM_DEFINE_OVERLOAD(1)
    212   LLVM_DEFINE_OVERLOAD(2)
    213   LLVM_DEFINE_OVERLOAD(3)
    214   LLVM_DEFINE_OVERLOAD(4)
    215   LLVM_DEFINE_OVERLOAD(5)
    216   LLVM_DEFINE_OVERLOAD(6)
    217   LLVM_DEFINE_OVERLOAD(7)
    218   LLVM_DEFINE_OVERLOAD(8)
    219   LLVM_DEFINE_OVERLOAD(9)
    220   LLVM_DEFINE_OVERLOAD(10)
    221   LLVM_DEFINE_OVERLOAD(11)
    222   LLVM_DEFINE_OVERLOAD(12)
    223   LLVM_DEFINE_OVERLOAD(13)
    224   LLVM_DEFINE_OVERLOAD(14)
    225   LLVM_DEFINE_OVERLOAD(15)
    226   LLVM_DEFINE_OVERLOAD(16)
    227   LLVM_DEFINE_OVERLOAD(17)
    228   LLVM_DEFINE_OVERLOAD(18)
    229   LLVM_DEFINE_OVERLOAD(19)
    230   LLVM_DEFINE_OVERLOAD(20)
    231   LLVM_DEFINE_OVERLOAD(21)
    232   LLVM_DEFINE_OVERLOAD(22)
    233   LLVM_DEFINE_OVERLOAD(23)
    234   LLVM_DEFINE_OVERLOAD(24)
    235   LLVM_DEFINE_OVERLOAD(25)
    236   LLVM_DEFINE_OVERLOAD(26)
    237   LLVM_DEFINE_OVERLOAD(27)
    238   LLVM_DEFINE_OVERLOAD(28)
    239   LLVM_DEFINE_OVERLOAD(29)
    240   LLVM_DEFINE_OVERLOAD(30)
    241   LLVM_DEFINE_OVERLOAD(31)
    242   LLVM_DEFINE_OVERLOAD(32)
    243 #undef LLVM_DEFINE_OVERLOAD
    244 };
    245 
    246 template <typename ResultT, typename Param0T, typename Param1T,
    247           typename Param2T, typename ArgT,
    248           ResultT (*Func)(Param0T, Param1T, Param2T, ArrayRef<const ArgT *>)>
    249 struct VariadicFunction3 {
    250   ResultT operator()(Param0T P0, Param1T P1, Param2T P2) const {
    251     return Func(P0, P1, P2, None);
    252   }
    253 
    254 #define LLVM_DEFINE_OVERLOAD(N) \
    255   ResultT operator()(Param0T P0, Param1T P1, Param2T P2, \
    256                      LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
    257     const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
    258     return Func(P0, P1, P2, makeArrayRef(Args)); \
    259   }
    260   LLVM_DEFINE_OVERLOAD(1)
    261   LLVM_DEFINE_OVERLOAD(2)
    262   LLVM_DEFINE_OVERLOAD(3)
    263   LLVM_DEFINE_OVERLOAD(4)
    264   LLVM_DEFINE_OVERLOAD(5)
    265   LLVM_DEFINE_OVERLOAD(6)
    266   LLVM_DEFINE_OVERLOAD(7)
    267   LLVM_DEFINE_OVERLOAD(8)
    268   LLVM_DEFINE_OVERLOAD(9)
    269   LLVM_DEFINE_OVERLOAD(10)
    270   LLVM_DEFINE_OVERLOAD(11)
    271   LLVM_DEFINE_OVERLOAD(12)
    272   LLVM_DEFINE_OVERLOAD(13)
    273   LLVM_DEFINE_OVERLOAD(14)
    274   LLVM_DEFINE_OVERLOAD(15)
    275   LLVM_DEFINE_OVERLOAD(16)
    276   LLVM_DEFINE_OVERLOAD(17)
    277   LLVM_DEFINE_OVERLOAD(18)
    278   LLVM_DEFINE_OVERLOAD(19)
    279   LLVM_DEFINE_OVERLOAD(20)
    280   LLVM_DEFINE_OVERLOAD(21)
    281   LLVM_DEFINE_OVERLOAD(22)
    282   LLVM_DEFINE_OVERLOAD(23)
    283   LLVM_DEFINE_OVERLOAD(24)
    284   LLVM_DEFINE_OVERLOAD(25)
    285   LLVM_DEFINE_OVERLOAD(26)
    286   LLVM_DEFINE_OVERLOAD(27)
    287   LLVM_DEFINE_OVERLOAD(28)
    288   LLVM_DEFINE_OVERLOAD(29)
    289   LLVM_DEFINE_OVERLOAD(30)
    290   LLVM_DEFINE_OVERLOAD(31)
    291   LLVM_DEFINE_OVERLOAD(32)
    292 #undef LLVM_DEFINE_OVERLOAD
    293 };
    294 
    295 // Cleanup the macro namespace.
    296 #undef LLVM_COMMA_JOIN1
    297 #undef LLVM_COMMA_JOIN2
    298 #undef LLVM_COMMA_JOIN3
    299 #undef LLVM_COMMA_JOIN4
    300 #undef LLVM_COMMA_JOIN5
    301 #undef LLVM_COMMA_JOIN6
    302 #undef LLVM_COMMA_JOIN7
    303 #undef LLVM_COMMA_JOIN8
    304 #undef LLVM_COMMA_JOIN9
    305 #undef LLVM_COMMA_JOIN10
    306 #undef LLVM_COMMA_JOIN11
    307 #undef LLVM_COMMA_JOIN12
    308 #undef LLVM_COMMA_JOIN13
    309 #undef LLVM_COMMA_JOIN14
    310 #undef LLVM_COMMA_JOIN15
    311 #undef LLVM_COMMA_JOIN16
    312 #undef LLVM_COMMA_JOIN17
    313 #undef LLVM_COMMA_JOIN18
    314 #undef LLVM_COMMA_JOIN19
    315 #undef LLVM_COMMA_JOIN20
    316 #undef LLVM_COMMA_JOIN21
    317 #undef LLVM_COMMA_JOIN22
    318 #undef LLVM_COMMA_JOIN23
    319 #undef LLVM_COMMA_JOIN24
    320 #undef LLVM_COMMA_JOIN25
    321 #undef LLVM_COMMA_JOIN26
    322 #undef LLVM_COMMA_JOIN27
    323 #undef LLVM_COMMA_JOIN28
    324 #undef LLVM_COMMA_JOIN29
    325 #undef LLVM_COMMA_JOIN30
    326 #undef LLVM_COMMA_JOIN31
    327 #undef LLVM_COMMA_JOIN32
    328 
    329 } // end namespace llvm
    330 
    331 #endif  // LLVM_ADT_VARIADICFUNCTION_H
    332