Home | History | Annotate | Download | only in Support
      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 "llvm/LLVMContext.h"
     20 #include <limits.h>
     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
    400