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