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 { operatorVariadicFunction107 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 { operatorVariadicFunction1154 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 { operatorVariadicFunction2201 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 { operatorVariadicFunction3250 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