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