]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
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 | ||
970d7e83 LB |
14 | #ifndef LLVM_ADT_VARIADICFUNCTION_H |
15 | #define LLVM_ADT_VARIADICFUNCTION_H | |
223e47cc LB |
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 { | |
1a4d82fc | 108 | return Func(None); |
223e47cc LB |
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 { | |
1a4d82fc | 155 | return Func(P0, None); |
223e47cc LB |
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 { | |
1a4d82fc | 202 | return Func(P0, P1, None); |
223e47cc LB |
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 { | |
1a4d82fc | 251 | return Func(P0, P1, P2, None); |
223e47cc LB |
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 | ||
970d7e83 | 331 | #endif // LLVM_ADT_VARIADICFUNCTION_H |