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