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 19namespace 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. 104template <typename ResultT, typename ArgT, 105 ResultT (*Func)(ArrayRef<const ArgT *>)> 106struct VariadicFunction { 107 ResultT operator()() const { 108 return Func(ArrayRef<const ArgT *>()); 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 151template <typename ResultT, typename Param0T, typename ArgT, 152 ResultT (*Func)(Param0T, ArrayRef<const ArgT *>)> 153struct VariadicFunction1 { 154 ResultT operator()(Param0T P0) const { 155 return Func(P0, ArrayRef<const ArgT *>()); 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 198template <typename ResultT, typename Param0T, typename Param1T, typename ArgT, 199 ResultT (*Func)(Param0T, Param1T, ArrayRef<const ArgT *>)> 200struct VariadicFunction2 { 201 ResultT operator()(Param0T P0, Param1T P1) const { 202 return Func(P0, P1, ArrayRef<const ArgT *>()); 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 246template <typename ResultT, typename Param0T, typename Param1T, 247 typename Param2T, typename ArgT, 248 ResultT (*Func)(Param0T, Param1T, Param2T, ArrayRef<const ArgT *>)> 249struct VariadicFunction3 { 250 ResultT operator()(Param0T P0, Param1T P1, Param2T P2) const { 251 return Func(P0, P1, P2, ArrayRef<const ArgT *>()); 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