LCOV - code coverage report
Current view: top level - include/llvm/IR - TypeBuilder.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 97 97 100.0 %
Date: 2017-09-14 15:23:50 Functions: 33 34 97.1 %
Legend: Lines: hit not hit

          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          51 :   static PointerType *get(LLVMContext &Context) {
     115         136 :     return PointerType::getUnqual(TypeBuilder<T,cross>::get(Context));
     116             :   }
     117             : };
     118             : 
     119             : /// There is no support for references
     120             : template<typename T, bool cross> class TypeBuilder<T&, cross> {};
     121             : 
     122             : // Arrays
     123             : template<typename T, size_t N, bool cross> class TypeBuilder<T[N], cross> {
     124             : public:
     125           5 :   static ArrayType *get(LLVMContext &Context) {
     126           5 :     return ArrayType::get(TypeBuilder<T, cross>::get(Context), N);
     127             :   }
     128             : };
     129             : /// LLVM uses an array of length 0 to represent an unknown-length array.
     130             : template<typename T, bool cross> class TypeBuilder<T[], cross> {
     131             : public:
     132           3 :   static ArrayType *get(LLVMContext &Context) {
     133           9 :     return ArrayType::get(TypeBuilder<T, cross>::get(Context), 0);
     134             :   }
     135             : };
     136             : 
     137             : // Define the C integral types only for TypeBuilder<T, false>.
     138             : //
     139             : // 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             : // following problem:
     142             : //
     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             : // platforms where stdint.h instead defines:
     153             : //
     154             : //   typedef int int32_t;
     155             : //   typedef long long int64_t;
     156             : //   typedef int size_t;
     157             : //
     158             : // So we define all the primitive C types and nothing else.
     159             : #define DEFINE_INTEGRAL_TYPEBUILDER(T) \
     160             : template<> class TypeBuilder<T, false> { \
     161             : public: \
     162             :   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             :   /* define these types to work. */ \
     169             : }
     170          31 : DEFINE_INTEGRAL_TYPEBUILDER(char);
     171          19 : DEFINE_INTEGRAL_TYPEBUILDER(signed char);
     172           1 : DEFINE_INTEGRAL_TYPEBUILDER(unsigned char);
     173           1 : DEFINE_INTEGRAL_TYPEBUILDER(short);
     174           1 : DEFINE_INTEGRAL_TYPEBUILDER(unsigned short);
     175         173 : DEFINE_INTEGRAL_TYPEBUILDER(int);
     176           1 : DEFINE_INTEGRAL_TYPEBUILDER(unsigned int);
     177           2 : DEFINE_INTEGRAL_TYPEBUILDER(long);
     178           2 : 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          47 :     return IntegerType::get(C, num_bits);
     193             :   }
     194             : };
     195             : 
     196             : template<> class TypeBuilder<float, false> {
     197             : public:
     198             :   static Type *get(LLVMContext& C) {
     199           1 :     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           1 :     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           2 :   static Type *get(LLVMContext& C) { return Type::getFloatTy(C); }
     215             : };
     216             : template<bool cross> class TypeBuilder<types::ieee_double, cross> {
     217             : public:
     218           2 :   static Type *get(LLVMContext& C) { return Type::getDoubleTy(C); }
     219             : };
     220             : template<bool cross> class TypeBuilder<types::x86_fp80, cross> {
     221             : public:
     222           2 :   static Type *get(LLVMContext& C) { return Type::getX86_FP80Ty(C); }
     223             : };
     224             : template<bool cross> class TypeBuilder<types::fp128, cross> {
     225             : public:
     226           2 :   static Type *get(LLVMContext& C) { return Type::getFP128Ty(C); }
     227             : };
     228             : template<bool cross> class TypeBuilder<types::ppc_fp128, cross> {
     229             : public:
     230           2 :   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             : template<bool cross> class TypeBuilder<void, cross> {
     238             : public:
     239             :   static Type *get(LLVMContext &C) {
     240          66 :     return Type::getVoidTy(C);
     241             :   }
     242             : };
     243             : 
     244             : /// 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             : 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          47 :   static FunctionType *get(LLVMContext &Context) {
     258         102 :     return FunctionType::get(TypeBuilder<R, cross>::get(Context), false);
     259             :   }
     260             : };
     261             : template<typename R, typename A1, bool cross> class TypeBuilder<R(A1), cross> {
     262             : public:
     263          13 :   static FunctionType *get(LLVMContext &Context) {
     264          13 :     Type *params[] = {
     265          13 :       TypeBuilder<A1, cross>::get(Context),
     266             :     };
     267          39 :     return FunctionType::get(TypeBuilder<R, cross>::get(Context),
     268          26 :                              params, false);
     269             :   }
     270             : };
     271             : 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          74 :     Type *params[] = {
     276          37 :       TypeBuilder<A1, cross>::get(Context),
     277          37 :       TypeBuilder<A2, cross>::get(Context),
     278             :     };
     279         111 :     return FunctionType::get(TypeBuilder<R, cross>::get(Context),
     280          74 :                              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             : public:
     286           1 :   static FunctionType *get(LLVMContext &Context) {
     287           3 :     Type *params[] = {
     288           1 :       TypeBuilder<A1, cross>::get(Context),
     289           1 :       TypeBuilder<A2, cross>::get(Context),
     290           1 :       TypeBuilder<A3, cross>::get(Context),
     291             :     };
     292           3 :     return FunctionType::get(TypeBuilder<R, cross>::get(Context),
     293           2 :                              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           1 :   static FunctionType *get(LLVMContext &Context) {
     302           4 :     Type *params[] = {
     303           1 :       TypeBuilder<A1, cross>::get(Context),
     304           1 :       TypeBuilder<A2, cross>::get(Context),
     305           1 :       TypeBuilder<A3, cross>::get(Context),
     306           1 :       TypeBuilder<A4, cross>::get(Context),
     307             :     };
     308           3 :     return FunctionType::get(TypeBuilder<R, cross>::get(Context),
     309           2 :                              params, false);
     310             :   }
     311             : };
     312             : 
     313             : 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           1 :   static FunctionType *get(LLVMContext &Context) {
     318           5 :     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           1 :       TypeBuilder<A5, cross>::get(Context),
     324             :     };
     325           3 :     return FunctionType::get(TypeBuilder<R, cross>::get(Context),
     326           2 :                              params, false);
     327             :   }
     328             : };
     329             : 
     330             : template<typename R, bool cross> class TypeBuilder<R(...), cross> {
     331             : public:
     332           1 :   static FunctionType *get(LLVMContext &Context) {
     333           1 :     return FunctionType::get(TypeBuilder<R, cross>::get(Context), true);
     334             :   }
     335             : };
     336             : template<typename R, typename A1, bool cross>
     337             : class TypeBuilder<R(A1, ...), cross> {
     338             : public:
     339           1 :   static FunctionType *get(LLVMContext &Context) {
     340           1 :     Type *params[] = {
     341           1 :       TypeBuilder<A1, cross>::get(Context),
     342             :     };
     343           2 :     return FunctionType::get(TypeBuilder<R, cross>::get(Context), params, true);
     344             :   }
     345             : };
     346             : template<typename R, typename A1, typename A2, bool cross>
     347             : class TypeBuilder<R(A1, A2, ...), cross> {
     348             : public:
     349           1 :   static FunctionType *get(LLVMContext &Context) {
     350           2 :     Type *params[] = {
     351           1 :       TypeBuilder<A1, cross>::get(Context),
     352           1 :       TypeBuilder<A2, cross>::get(Context),
     353             :     };
     354           3 :     return FunctionType::get(TypeBuilder<R, cross>::get(Context),
     355           2 :                                    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           1 :   static FunctionType *get(LLVMContext &Context) {
     362           3 :     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           3 :     return FunctionType::get(TypeBuilder<R, cross>::get(Context),
     368           2 :                                    params, true);
     369             :   }
     370             : };
     371             : 
     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           1 :   static FunctionType *get(LLVMContext &Context) {
     377           4 :     Type *params[] = {
     378           1 :       TypeBuilder<A1, cross>::get(Context),
     379           1 :       TypeBuilder<A2, cross>::get(Context),
     380           1 :       TypeBuilder<A3, cross>::get(Context),
     381           1 :       TypeBuilder<A4, cross>::get(Context),
     382             :     };
     383           3 :     return FunctionType::get(TypeBuilder<R, cross>::get(Context),
     384           2 :                              params, true);
     385             :   }
     386             : };
     387             : 
     388             : 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           1 :   static FunctionType *get(LLVMContext &Context) {
     393           5 :     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           1 :       TypeBuilder<A5, cross>::get(Context),
     399             :     };
     400           3 :     return FunctionType::get(TypeBuilder<R, cross>::get(Context),
     401           2 :                                    params, true);
     402             :   }
     403             : };
     404             : 
     405             : }  // namespace llvm
     406             : 
     407             : #endif

Generated by: LCOV version 1.13