Line data Source code
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 : /// 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 0 : ResultT operator()() const {
108 1 : return Func(None);
109 : }
110 0 :
111 0 : #define LLVM_DEFINE_OVERLOAD(N) \
112 : ResultT operator()(LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
113 0 : const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
114 0 : 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 1 : LLVM_DEFINE_OVERLOAD(7)
123 2 : 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 1 : 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 1 : 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 0 : const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
161 1 : 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 1 : LLVM_DEFINE_OVERLOAD(7)
170 : LLVM_DEFINE_OVERLOAD(8)
171 : LLVM_DEFINE_OVERLOAD(9)
172 1 : 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 0 : LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
257 0 : 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 0 : LLVM_DEFINE_OVERLOAD(7)
267 : LLVM_DEFINE_OVERLOAD(8)
268 : LLVM_DEFINE_OVERLOAD(9)
269 1 : 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
|