]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===---- llvm/TypeBuilder.h - Builder for LLVM types -----------*- 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 defines the TypeBuilder class, which is used as a convenient way to | |
11 | // create LLVM types with a consistent and simplified interface. | |
12 | // | |
13 | //===----------------------------------------------------------------------===// | |
14 | ||
970d7e83 LB |
15 | #ifndef LLVM_IR_TYPEBUILDER_H |
16 | #define LLVM_IR_TYPEBUILDER_H | |
223e47cc | 17 | |
970d7e83 LB |
18 | #include "llvm/IR/DerivedTypes.h" |
19 | #include "llvm/IR/LLVMContext.h" | |
1a4d82fc | 20 | #include <climits> |
223e47cc LB |
21 | |
22 | namespace llvm { | |
23 | ||
24 | /// TypeBuilder - This provides a uniform API for looking up types | |
25 | /// known at compile time. To support cross-compilation, we define a | |
26 | /// series of tag types in the llvm::types namespace, like i<N>, | |
27 | /// ieee_float, ppc_fp128, etc. TypeBuilder<T, false> allows T to be | |
28 | /// any of these, a native C type (whose size may depend on the host | |
29 | /// compiler), or a pointer, function, or struct type built out of | |
30 | /// these. TypeBuilder<T, true> removes native C types from this set | |
31 | /// to guarantee that its result is suitable for cross-compilation. | |
32 | /// We define the primitive types, pointer types, and functions up to | |
33 | /// 5 arguments here, but to use this class with your own types, | |
34 | /// you'll need to specialize it. For example, say you want to call a | |
35 | /// function defined externally as: | |
36 | /// | |
37 | /// struct MyType { | |
38 | /// int32 a; | |
39 | /// int32 *b; | |
40 | /// void *array[1]; // Intended as a flexible array. | |
41 | /// }; | |
42 | /// int8 AFunction(struct MyType *value); | |
43 | /// | |
44 | /// You'll want to use | |
45 | /// Function::Create(TypeBuilder<types::i<8>(MyType*), true>::get(), ...) | |
46 | /// to declare the function, but when you first try this, your compiler will | |
47 | /// complain that TypeBuilder<MyType, true>::get() doesn't exist. To fix this, | |
48 | /// write: | |
49 | /// | |
50 | /// namespace llvm { | |
51 | /// template<bool xcompile> class TypeBuilder<MyType, xcompile> { | |
52 | /// public: | |
53 | /// static StructType *get(LLVMContext &Context) { | |
54 | /// // If you cache this result, be sure to cache it separately | |
55 | /// // for each LLVMContext. | |
56 | /// return StructType::get( | |
57 | /// TypeBuilder<types::i<32>, xcompile>::get(Context), | |
58 | /// TypeBuilder<types::i<32>*, xcompile>::get(Context), | |
59 | /// TypeBuilder<types::i<8>*[], xcompile>::get(Context), | |
60 | /// NULL); | |
61 | /// } | |
62 | /// | |
63 | /// // You may find this a convenient place to put some constants | |
64 | /// // to help with getelementptr. They don't have any effect on | |
65 | /// // the operation of TypeBuilder. | |
66 | /// enum Fields { | |
67 | /// FIELD_A, | |
68 | /// FIELD_B, | |
69 | /// FIELD_ARRAY | |
70 | /// }; | |
71 | /// } | |
72 | /// } // namespace llvm | |
73 | /// | |
74 | /// TypeBuilder cannot handle recursive types or types you only know at runtime. | |
75 | /// If you try to give it a recursive type, it will deadlock, infinitely | |
76 | /// recurse, or do something similarly undesirable. | |
77 | template<typename T, bool cross_compilable> class TypeBuilder {}; | |
78 | ||
79 | // Types for use with cross-compilable TypeBuilders. These correspond | |
80 | // exactly with an LLVM-native type. | |
81 | namespace types { | |
82 | /// i<N> corresponds to the LLVM IntegerType with N bits. | |
83 | template<uint32_t num_bits> class i {}; | |
84 | ||
85 | // The following classes represent the LLVM floating types. | |
86 | class ieee_float {}; | |
87 | class ieee_double {}; | |
88 | class x86_fp80 {}; | |
89 | class fp128 {}; | |
90 | class ppc_fp128 {}; | |
91 | // X86 MMX. | |
92 | class x86_mmx {}; | |
93 | } // namespace types | |
94 | ||
95 | // LLVM doesn't have const or volatile types. | |
96 | template<typename T, bool cross> class TypeBuilder<const T, cross> | |
97 | : public TypeBuilder<T, cross> {}; | |
98 | template<typename T, bool cross> class TypeBuilder<volatile T, cross> | |
99 | : public TypeBuilder<T, cross> {}; | |
100 | template<typename T, bool cross> class TypeBuilder<const volatile T, cross> | |
101 | : public TypeBuilder<T, cross> {}; | |
102 | ||
103 | // Pointers | |
104 | template<typename T, bool cross> class TypeBuilder<T*, cross> { | |
105 | public: | |
106 | static PointerType *get(LLVMContext &Context) { | |
107 | return PointerType::getUnqual(TypeBuilder<T,cross>::get(Context)); | |
108 | } | |
109 | }; | |
110 | ||
111 | /// There is no support for references | |
112 | template<typename T, bool cross> class TypeBuilder<T&, cross> {}; | |
113 | ||
114 | // Arrays | |
115 | template<typename T, size_t N, bool cross> class TypeBuilder<T[N], cross> { | |
116 | public: | |
117 | static ArrayType *get(LLVMContext &Context) { | |
118 | return ArrayType::get(TypeBuilder<T, cross>::get(Context), N); | |
119 | } | |
120 | }; | |
121 | /// LLVM uses an array of length 0 to represent an unknown-length array. | |
122 | template<typename T, bool cross> class TypeBuilder<T[], cross> { | |
123 | public: | |
124 | static ArrayType *get(LLVMContext &Context) { | |
125 | return ArrayType::get(TypeBuilder<T, cross>::get(Context), 0); | |
126 | } | |
127 | }; | |
128 | ||
129 | // Define the C integral types only for TypeBuilder<T, false>. | |
130 | // | |
131 | // C integral types do not have a defined size. It would be nice to use the | |
132 | // stdint.h-defined typedefs that do have defined sizes, but we'd run into the | |
133 | // following problem: | |
134 | // | |
135 | // On an ILP32 machine, stdint.h might define: | |
136 | // | |
137 | // typedef int int32_t; | |
138 | // typedef long long int64_t; | |
139 | // typedef long size_t; | |
140 | // | |
141 | // If we defined TypeBuilder<int32_t> and TypeBuilder<int64_t>, then any use of | |
142 | // TypeBuilder<size_t> would fail. We couldn't define TypeBuilder<size_t> in | |
143 | // addition to the defined-size types because we'd get duplicate definitions on | |
144 | // platforms where stdint.h instead defines: | |
145 | // | |
146 | // typedef int int32_t; | |
147 | // typedef long long int64_t; | |
148 | // typedef int size_t; | |
149 | // | |
150 | // So we define all the primitive C types and nothing else. | |
151 | #define DEFINE_INTEGRAL_TYPEBUILDER(T) \ | |
152 | template<> class TypeBuilder<T, false> { \ | |
153 | public: \ | |
154 | static IntegerType *get(LLVMContext &Context) { \ | |
155 | return IntegerType::get(Context, sizeof(T) * CHAR_BIT); \ | |
156 | } \ | |
157 | }; \ | |
158 | template<> class TypeBuilder<T, true> { \ | |
159 | /* We provide a definition here so users don't accidentally */ \ | |
160 | /* define these types to work. */ \ | |
161 | } | |
162 | DEFINE_INTEGRAL_TYPEBUILDER(char); | |
163 | DEFINE_INTEGRAL_TYPEBUILDER(signed char); | |
164 | DEFINE_INTEGRAL_TYPEBUILDER(unsigned char); | |
165 | DEFINE_INTEGRAL_TYPEBUILDER(short); | |
166 | DEFINE_INTEGRAL_TYPEBUILDER(unsigned short); | |
167 | DEFINE_INTEGRAL_TYPEBUILDER(int); | |
168 | DEFINE_INTEGRAL_TYPEBUILDER(unsigned int); | |
169 | DEFINE_INTEGRAL_TYPEBUILDER(long); | |
170 | DEFINE_INTEGRAL_TYPEBUILDER(unsigned long); | |
171 | #ifdef _MSC_VER | |
172 | DEFINE_INTEGRAL_TYPEBUILDER(__int64); | |
173 | DEFINE_INTEGRAL_TYPEBUILDER(unsigned __int64); | |
174 | #else /* _MSC_VER */ | |
175 | DEFINE_INTEGRAL_TYPEBUILDER(long long); | |
176 | DEFINE_INTEGRAL_TYPEBUILDER(unsigned long long); | |
177 | #endif /* _MSC_VER */ | |
178 | #undef DEFINE_INTEGRAL_TYPEBUILDER | |
179 | ||
180 | template<uint32_t num_bits, bool cross> | |
181 | class TypeBuilder<types::i<num_bits>, cross> { | |
182 | public: | |
183 | static IntegerType *get(LLVMContext &C) { | |
184 | return IntegerType::get(C, num_bits); | |
185 | } | |
186 | }; | |
187 | ||
188 | template<> class TypeBuilder<float, false> { | |
189 | public: | |
190 | static Type *get(LLVMContext& C) { | |
191 | return Type::getFloatTy(C); | |
192 | } | |
193 | }; | |
194 | template<> class TypeBuilder<float, true> {}; | |
195 | ||
196 | template<> class TypeBuilder<double, false> { | |
197 | public: | |
198 | static Type *get(LLVMContext& C) { | |
199 | return Type::getDoubleTy(C); | |
200 | } | |
201 | }; | |
202 | template<> class TypeBuilder<double, true> {}; | |
203 | ||
204 | template<bool cross> class TypeBuilder<types::ieee_float, cross> { | |
205 | public: | |
206 | static Type *get(LLVMContext& C) { return Type::getFloatTy(C); } | |
207 | }; | |
208 | template<bool cross> class TypeBuilder<types::ieee_double, cross> { | |
209 | public: | |
210 | static Type *get(LLVMContext& C) { return Type::getDoubleTy(C); } | |
211 | }; | |
212 | template<bool cross> class TypeBuilder<types::x86_fp80, cross> { | |
213 | public: | |
214 | static Type *get(LLVMContext& C) { return Type::getX86_FP80Ty(C); } | |
215 | }; | |
216 | template<bool cross> class TypeBuilder<types::fp128, cross> { | |
217 | public: | |
218 | static Type *get(LLVMContext& C) { return Type::getFP128Ty(C); } | |
219 | }; | |
220 | template<bool cross> class TypeBuilder<types::ppc_fp128, cross> { | |
221 | public: | |
222 | static Type *get(LLVMContext& C) { return Type::getPPC_FP128Ty(C); } | |
223 | }; | |
224 | template<bool cross> class TypeBuilder<types::x86_mmx, cross> { | |
225 | public: | |
226 | static Type *get(LLVMContext& C) { return Type::getX86_MMXTy(C); } | |
227 | }; | |
228 | ||
229 | template<bool cross> class TypeBuilder<void, cross> { | |
230 | public: | |
231 | static Type *get(LLVMContext &C) { | |
232 | return Type::getVoidTy(C); | |
233 | } | |
234 | }; | |
235 | ||
236 | /// void* is disallowed in LLVM types, but it occurs often enough in C code that | |
237 | /// we special case it. | |
238 | template<> class TypeBuilder<void*, false> | |
239 | : public TypeBuilder<types::i<8>*, false> {}; | |
240 | template<> class TypeBuilder<const void*, false> | |
241 | : public TypeBuilder<types::i<8>*, false> {}; | |
242 | template<> class TypeBuilder<volatile void*, false> | |
243 | : public TypeBuilder<types::i<8>*, false> {}; | |
244 | template<> class TypeBuilder<const volatile void*, false> | |
245 | : public TypeBuilder<types::i<8>*, false> {}; | |
246 | ||
247 | template<typename R, bool cross> class TypeBuilder<R(), cross> { | |
248 | public: | |
249 | static FunctionType *get(LLVMContext &Context) { | |
250 | return FunctionType::get(TypeBuilder<R, cross>::get(Context), false); | |
251 | } | |
252 | }; | |
253 | template<typename R, typename A1, bool cross> class TypeBuilder<R(A1), cross> { | |
254 | public: | |
255 | static FunctionType *get(LLVMContext &Context) { | |
256 | Type *params[] = { | |
257 | TypeBuilder<A1, cross>::get(Context), | |
258 | }; | |
259 | return FunctionType::get(TypeBuilder<R, cross>::get(Context), | |
260 | params, false); | |
261 | } | |
262 | }; | |
263 | template<typename R, typename A1, typename A2, bool cross> | |
264 | class TypeBuilder<R(A1, A2), cross> { | |
265 | public: | |
266 | static FunctionType *get(LLVMContext &Context) { | |
267 | Type *params[] = { | |
268 | TypeBuilder<A1, cross>::get(Context), | |
269 | TypeBuilder<A2, cross>::get(Context), | |
270 | }; | |
271 | return FunctionType::get(TypeBuilder<R, cross>::get(Context), | |
272 | params, false); | |
273 | } | |
274 | }; | |
275 | template<typename R, typename A1, typename A2, typename A3, bool cross> | |
276 | class TypeBuilder<R(A1, A2, A3), cross> { | |
277 | public: | |
278 | static FunctionType *get(LLVMContext &Context) { | |
279 | Type *params[] = { | |
280 | TypeBuilder<A1, cross>::get(Context), | |
281 | TypeBuilder<A2, cross>::get(Context), | |
282 | TypeBuilder<A3, cross>::get(Context), | |
283 | }; | |
284 | return FunctionType::get(TypeBuilder<R, cross>::get(Context), | |
285 | params, false); | |
286 | } | |
287 | }; | |
288 | ||
289 | template<typename R, typename A1, typename A2, typename A3, typename A4, | |
290 | bool cross> | |
291 | class TypeBuilder<R(A1, A2, A3, A4), cross> { | |
292 | public: | |
293 | static FunctionType *get(LLVMContext &Context) { | |
294 | Type *params[] = { | |
295 | TypeBuilder<A1, cross>::get(Context), | |
296 | TypeBuilder<A2, cross>::get(Context), | |
297 | TypeBuilder<A3, cross>::get(Context), | |
298 | TypeBuilder<A4, cross>::get(Context), | |
299 | }; | |
300 | return FunctionType::get(TypeBuilder<R, cross>::get(Context), | |
301 | params, false); | |
302 | } | |
303 | }; | |
304 | ||
305 | template<typename R, typename A1, typename A2, typename A3, typename A4, | |
306 | typename A5, bool cross> | |
307 | class TypeBuilder<R(A1, A2, A3, A4, A5), cross> { | |
308 | public: | |
309 | static FunctionType *get(LLVMContext &Context) { | |
310 | Type *params[] = { | |
311 | TypeBuilder<A1, cross>::get(Context), | |
312 | TypeBuilder<A2, cross>::get(Context), | |
313 | TypeBuilder<A3, cross>::get(Context), | |
314 | TypeBuilder<A4, cross>::get(Context), | |
315 | TypeBuilder<A5, cross>::get(Context), | |
316 | }; | |
317 | return FunctionType::get(TypeBuilder<R, cross>::get(Context), | |
318 | params, false); | |
319 | } | |
320 | }; | |
321 | ||
322 | template<typename R, bool cross> class TypeBuilder<R(...), cross> { | |
323 | public: | |
324 | static FunctionType *get(LLVMContext &Context) { | |
325 | return FunctionType::get(TypeBuilder<R, cross>::get(Context), true); | |
326 | } | |
327 | }; | |
328 | template<typename R, typename A1, bool cross> | |
329 | class TypeBuilder<R(A1, ...), cross> { | |
330 | public: | |
331 | static FunctionType *get(LLVMContext &Context) { | |
332 | Type *params[] = { | |
333 | TypeBuilder<A1, cross>::get(Context), | |
334 | }; | |
335 | return FunctionType::get(TypeBuilder<R, cross>::get(Context), params, true); | |
336 | } | |
337 | }; | |
338 | template<typename R, typename A1, typename A2, bool cross> | |
339 | class TypeBuilder<R(A1, A2, ...), cross> { | |
340 | public: | |
341 | static FunctionType *get(LLVMContext &Context) { | |
342 | Type *params[] = { | |
343 | TypeBuilder<A1, cross>::get(Context), | |
344 | TypeBuilder<A2, cross>::get(Context), | |
345 | }; | |
346 | return FunctionType::get(TypeBuilder<R, cross>::get(Context), | |
347 | params, true); | |
348 | } | |
349 | }; | |
350 | template<typename R, typename A1, typename A2, typename A3, bool cross> | |
351 | class TypeBuilder<R(A1, A2, A3, ...), cross> { | |
352 | public: | |
353 | static FunctionType *get(LLVMContext &Context) { | |
354 | Type *params[] = { | |
355 | TypeBuilder<A1, cross>::get(Context), | |
356 | TypeBuilder<A2, cross>::get(Context), | |
357 | TypeBuilder<A3, cross>::get(Context), | |
358 | }; | |
359 | return FunctionType::get(TypeBuilder<R, cross>::get(Context), | |
360 | params, true); | |
361 | } | |
362 | }; | |
363 | ||
364 | template<typename R, typename A1, typename A2, typename A3, typename A4, | |
365 | bool cross> | |
366 | class TypeBuilder<R(A1, A2, A3, A4, ...), cross> { | |
367 | public: | |
368 | static FunctionType *get(LLVMContext &Context) { | |
369 | Type *params[] = { | |
370 | TypeBuilder<A1, cross>::get(Context), | |
371 | TypeBuilder<A2, cross>::get(Context), | |
372 | TypeBuilder<A3, cross>::get(Context), | |
373 | TypeBuilder<A4, cross>::get(Context), | |
374 | }; | |
375 | return FunctionType::get(TypeBuilder<R, cross>::get(Context), | |
376 | params, true); | |
377 | } | |
378 | }; | |
379 | ||
380 | template<typename R, typename A1, typename A2, typename A3, typename A4, | |
381 | typename A5, bool cross> | |
382 | class TypeBuilder<R(A1, A2, A3, A4, A5, ...), cross> { | |
383 | public: | |
384 | static FunctionType *get(LLVMContext &Context) { | |
385 | Type *params[] = { | |
386 | TypeBuilder<A1, cross>::get(Context), | |
387 | TypeBuilder<A2, cross>::get(Context), | |
388 | TypeBuilder<A3, cross>::get(Context), | |
389 | TypeBuilder<A4, cross>::get(Context), | |
390 | TypeBuilder<A5, cross>::get(Context), | |
391 | }; | |
392 | return FunctionType::get(TypeBuilder<R, cross>::get(Context), | |
393 | params, true); | |
394 | } | |
395 | }; | |
396 | ||
397 | } // namespace llvm | |
398 | ||
399 | #endif |