Home | History | Annotate | Download | only in IR
      1 //===- llvm/unittest/TypeBuilderTest.cpp - TypeBuilder tests --------------===//
      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 #include "llvm/IR/TypeBuilder.h"
     11 #include "llvm/IR/LLVMContext.h"
     12 #include "gtest/gtest.h"
     13 
     14 using namespace llvm;
     15 
     16 namespace {
     17 
     18 TEST(TypeBuilderTest, Void) {
     19   LLVMContext Context;
     20   EXPECT_EQ(Type::getVoidTy(Context), (TypeBuilder<void, true>::get(Context)));
     21   EXPECT_EQ(Type::getVoidTy(Context), (TypeBuilder<void, false>::get(Context)));
     22   // Special cases for C compatibility:
     23   EXPECT_EQ(Type::getInt8PtrTy(Context),
     24             (TypeBuilder<void *, false>::get(Context)));
     25   EXPECT_EQ(Type::getInt8PtrTy(Context),
     26             (TypeBuilder<const void *, false>::get(Context)));
     27   EXPECT_EQ(Type::getInt8PtrTy(Context),
     28             (TypeBuilder<volatile void *, false>::get(Context)));
     29   EXPECT_EQ(Type::getInt8PtrTy(Context),
     30             (TypeBuilder<const volatile void *, false>::get(Context)));
     31 }
     32 
     33 TEST(TypeBuilderTest, HostIntegers) {
     34   LLVMContext Context;
     35   EXPECT_EQ(Type::getInt8Ty(Context),
     36             (TypeBuilder<int8_t, false>::get(Context)));
     37   EXPECT_EQ(Type::getInt8Ty(Context),
     38             (TypeBuilder<uint8_t, false>::get(Context)));
     39   EXPECT_EQ(Type::getInt16Ty(Context),
     40             (TypeBuilder<int16_t, false>::get(Context)));
     41   EXPECT_EQ(Type::getInt16Ty(Context),
     42             (TypeBuilder<uint16_t, false>::get(Context)));
     43   EXPECT_EQ(Type::getInt32Ty(Context),
     44             (TypeBuilder<int32_t, false>::get(Context)));
     45   EXPECT_EQ(Type::getInt32Ty(Context),
     46             (TypeBuilder<uint32_t, false>::get(Context)));
     47   EXPECT_EQ(Type::getInt64Ty(Context),
     48             (TypeBuilder<int64_t, false>::get(Context)));
     49   EXPECT_EQ(Type::getInt64Ty(Context),
     50             (TypeBuilder<uint64_t, false>::get(Context)));
     51 
     52   EXPECT_EQ(IntegerType::get(Context, sizeof(size_t) * CHAR_BIT),
     53             (TypeBuilder<size_t, false>::get(Context)));
     54   EXPECT_EQ(IntegerType::get(Context, sizeof(ptrdiff_t) * CHAR_BIT),
     55             (TypeBuilder<ptrdiff_t, false>::get(Context)));
     56 }
     57 
     58 TEST(TypeBuilderTest, CrossCompilableIntegers) {
     59   LLVMContext Context;
     60   EXPECT_EQ(IntegerType::get(Context, 1),
     61             (TypeBuilder<types::i<1>, true>::get(Context)));
     62   EXPECT_EQ(IntegerType::get(Context, 1),
     63             (TypeBuilder<types::i<1>, false>::get(Context)));
     64   EXPECT_EQ(IntegerType::get(Context, 72),
     65             (TypeBuilder<types::i<72>, true>::get(Context)));
     66   EXPECT_EQ(IntegerType::get(Context, 72),
     67             (TypeBuilder<types::i<72>, false>::get(Context)));
     68 }
     69 
     70 TEST(TypeBuilderTest, Float) {
     71   LLVMContext Context;
     72   EXPECT_EQ(Type::getFloatTy(Context),
     73             (TypeBuilder<float, false>::get(Context)));
     74   EXPECT_EQ(Type::getDoubleTy(Context),
     75             (TypeBuilder<double, false>::get(Context)));
     76   // long double isn't supported yet.
     77   EXPECT_EQ(Type::getFloatTy(Context),
     78             (TypeBuilder<types::ieee_float, true>::get(Context)));
     79   EXPECT_EQ(Type::getFloatTy(Context),
     80             (TypeBuilder<types::ieee_float, false>::get(Context)));
     81   EXPECT_EQ(Type::getDoubleTy(Context),
     82             (TypeBuilder<types::ieee_double, true>::get(Context)));
     83   EXPECT_EQ(Type::getDoubleTy(Context),
     84             (TypeBuilder<types::ieee_double, false>::get(Context)));
     85   EXPECT_EQ(Type::getX86_FP80Ty(Context),
     86             (TypeBuilder<types::x86_fp80, true>::get(Context)));
     87   EXPECT_EQ(Type::getX86_FP80Ty(Context),
     88             (TypeBuilder<types::x86_fp80, false>::get(Context)));
     89   EXPECT_EQ(Type::getFP128Ty(Context),
     90             (TypeBuilder<types::fp128, true>::get(Context)));
     91   EXPECT_EQ(Type::getFP128Ty(Context),
     92             (TypeBuilder<types::fp128, false>::get(Context)));
     93   EXPECT_EQ(Type::getPPC_FP128Ty(Context),
     94             (TypeBuilder<types::ppc_fp128, true>::get(Context)));
     95   EXPECT_EQ(Type::getPPC_FP128Ty(Context),
     96             (TypeBuilder<types::ppc_fp128, false>::get(Context)));
     97 }
     98 
     99 TEST(TypeBuilderTest, Derived) {
    100   LLVMContext Context;
    101   EXPECT_EQ(PointerType::getUnqual(Type::getInt8PtrTy(Context)),
    102             (TypeBuilder<int8_t **, false>::get(Context)));
    103   EXPECT_EQ(ArrayType::get(Type::getInt8Ty(Context), 7),
    104             (TypeBuilder<int8_t[7], false>::get(Context)));
    105   EXPECT_EQ(ArrayType::get(Type::getInt8Ty(Context), 0),
    106             (TypeBuilder<int8_t[], false>::get(Context)));
    107 
    108   EXPECT_EQ(PointerType::getUnqual(Type::getInt8PtrTy(Context)),
    109             (TypeBuilder<types::i<8> **, false>::get(Context)));
    110   EXPECT_EQ(ArrayType::get(Type::getInt8Ty(Context), 7),
    111             (TypeBuilder<types::i<8>[7], false>::get(Context)));
    112   EXPECT_EQ(ArrayType::get(Type::getInt8Ty(Context), 0),
    113             (TypeBuilder<types::i<8>[], false>::get(Context)));
    114 
    115   EXPECT_EQ(PointerType::getUnqual(Type::getInt8PtrTy(Context)),
    116             (TypeBuilder<types::i<8> **, true>::get(Context)));
    117   EXPECT_EQ(ArrayType::get(Type::getInt8Ty(Context), 7),
    118             (TypeBuilder<types::i<8>[7], true>::get(Context)));
    119   EXPECT_EQ(ArrayType::get(Type::getInt8Ty(Context), 0),
    120             (TypeBuilder<types::i<8>[], true>::get(Context)));
    121 
    122   EXPECT_EQ(Type::getInt8Ty(Context),
    123             (TypeBuilder<const int8_t, false>::get(Context)));
    124   EXPECT_EQ(Type::getInt8Ty(Context),
    125             (TypeBuilder<volatile int8_t, false>::get(Context)));
    126   EXPECT_EQ(Type::getInt8Ty(Context),
    127             (TypeBuilder<const volatile int8_t, false>::get(Context)));
    128 
    129   EXPECT_EQ(Type::getInt8Ty(Context),
    130             (TypeBuilder<const types::i<8>, false>::get(Context)));
    131   EXPECT_EQ(Type::getInt8Ty(Context),
    132             (TypeBuilder<volatile types::i<8>, false>::get(Context)));
    133   EXPECT_EQ(Type::getInt8Ty(Context),
    134             (TypeBuilder<const volatile types::i<8>, false>::get(Context)));
    135 
    136   EXPECT_EQ(Type::getInt8Ty(Context),
    137             (TypeBuilder<const types::i<8>, true>::get(Context)));
    138   EXPECT_EQ(Type::getInt8Ty(Context),
    139             (TypeBuilder<volatile types::i<8>, true>::get(Context)));
    140   EXPECT_EQ(Type::getInt8Ty(Context),
    141             (TypeBuilder<const volatile types::i<8>, true>::get(Context)));
    142 
    143   EXPECT_EQ(Type::getInt8PtrTy(Context),
    144             (TypeBuilder<const volatile int8_t *const volatile, false>::get(
    145                 Context)));
    146 }
    147 
    148 TEST(TypeBuilderTest, Functions) {
    149   LLVMContext Context;
    150   std::vector<Type*> params;
    151   EXPECT_EQ(FunctionType::get(Type::getVoidTy(Context), params, false),
    152             (TypeBuilder<void(), true>::get(Context)));
    153   EXPECT_EQ(FunctionType::get(Type::getInt8Ty(Context), params, true),
    154             (TypeBuilder<int8_t(...), false>::get(Context)));
    155   params.push_back(TypeBuilder<int32_t *, false>::get(Context));
    156   EXPECT_EQ(FunctionType::get(Type::getInt8Ty(Context), params, false),
    157             (TypeBuilder<int8_t(const int32_t *), false>::get(Context)));
    158   EXPECT_EQ(FunctionType::get(Type::getInt8Ty(Context), params, true),
    159             (TypeBuilder<int8_t(const int32_t *, ...), false>::get(Context)));
    160   params.push_back(TypeBuilder<char *, false>::get(Context));
    161   EXPECT_EQ(FunctionType::get(Type::getInt8Ty(Context), params, false),
    162             (TypeBuilder<int8_t(int32_t *, void *), false>::get(Context)));
    163   EXPECT_EQ(FunctionType::get(Type::getInt8Ty(Context), params, true),
    164             (TypeBuilder<int8_t(int32_t *, char *, ...), false>::get(Context)));
    165   params.push_back(TypeBuilder<char, false>::get(Context));
    166   EXPECT_EQ(
    167       FunctionType::get(Type::getInt8Ty(Context), params, false),
    168       (TypeBuilder<int8_t(int32_t *, void *, char), false>::get(Context)));
    169   EXPECT_EQ(
    170       FunctionType::get(Type::getInt8Ty(Context), params, true),
    171       (TypeBuilder<int8_t(int32_t *, char *, char, ...), false>::get(Context)));
    172   params.push_back(TypeBuilder<char, false>::get(Context));
    173   EXPECT_EQ(FunctionType::get(Type::getInt8Ty(Context), params, false),
    174             (TypeBuilder<int8_t(int32_t *, void *, char, char), false>::get(
    175                 Context)));
    176   EXPECT_EQ(
    177       FunctionType::get(Type::getInt8Ty(Context), params, true),
    178       (TypeBuilder<int8_t(int32_t *, char *, char, char, ...), false>::get(
    179           Context)));
    180   params.push_back(TypeBuilder<char, false>::get(Context));
    181   EXPECT_EQ(
    182       FunctionType::get(Type::getInt8Ty(Context), params, false),
    183       (TypeBuilder<int8_t(int32_t *, void *, char, char, char), false>::get(
    184           Context)));
    185   EXPECT_EQ(FunctionType::get(Type::getInt8Ty(Context), params, true),
    186             (TypeBuilder<int8_t(int32_t *, char *, char, char, char, ...),
    187                          false>::get(Context)));
    188 }
    189 
    190 TEST(TypeBuilderTest, Context) {
    191   // We used to cache TypeBuilder results in static local variables.  This
    192   // produced the same type for different contexts, which of course broke
    193   // things.
    194   LLVMContext context1;
    195   EXPECT_EQ(&context1,
    196             &(TypeBuilder<types::i<1>, true>::get(context1))->getContext());
    197   LLVMContext context2;
    198   EXPECT_EQ(&context2,
    199             &(TypeBuilder<types::i<1>, true>::get(context2))->getContext());
    200 }
    201 
    202 struct MyType {
    203   int a;
    204   int *b;
    205   void *array[1];
    206 };
    207 
    208 struct MyPortableType {
    209   int32_t a;
    210   int32_t *b;
    211   void *array[1];
    212 };
    213 
    214 }  // anonymous namespace
    215 
    216 namespace llvm {
    217 template<bool cross> class TypeBuilder<MyType, cross> {
    218 public:
    219   static StructType *get(LLVMContext &Context) {
    220     // Using the static result variable ensures that the type is
    221     // only looked up once.
    222     std::vector<Type*> st;
    223     st.push_back(TypeBuilder<int, cross>::get(Context));
    224     st.push_back(TypeBuilder<int*, cross>::get(Context));
    225     st.push_back(TypeBuilder<void*[], cross>::get(Context));
    226     static StructType *const result = StructType::get(Context, st);
    227     return result;
    228   }
    229 
    230   // You may find this a convenient place to put some constants
    231   // to help with getelementptr.  They don't have any effect on
    232   // the operation of TypeBuilder.
    233   enum Fields {
    234     FIELD_A,
    235     FIELD_B,
    236     FIELD_ARRAY
    237   };
    238 };
    239 
    240 template<bool cross> class TypeBuilder<MyPortableType, cross> {
    241 public:
    242   static StructType *get(LLVMContext &Context) {
    243     // Using the static result variable ensures that the type is
    244     // only looked up once.
    245     std::vector<Type*> st;
    246     st.push_back(TypeBuilder<types::i<32>, cross>::get(Context));
    247     st.push_back(TypeBuilder<types::i<32>*, cross>::get(Context));
    248     st.push_back(TypeBuilder<types::i<8>*[], cross>::get(Context));
    249     static StructType *const result = StructType::get(Context, st);
    250     return result;
    251   }
    252 
    253   // You may find this a convenient place to put some constants
    254   // to help with getelementptr.  They don't have any effect on
    255   // the operation of TypeBuilder.
    256   enum Fields {
    257     FIELD_A,
    258     FIELD_B,
    259     FIELD_ARRAY
    260   };
    261 };
    262 }  // namespace llvm
    263 namespace {
    264 
    265 TEST(TypeBuilderTest, Extensions) {
    266   LLVMContext Context;
    267   EXPECT_EQ(PointerType::getUnqual(StructType::get(
    268                 TypeBuilder<int, false>::get(Context),
    269                 TypeBuilder<int *, false>::get(Context),
    270                 TypeBuilder<void *[], false>::get(Context), (void *)nullptr)),
    271             (TypeBuilder<MyType *, false>::get(Context)));
    272   EXPECT_EQ(
    273       PointerType::getUnqual(StructType::get(
    274           TypeBuilder<types::i<32>, false>::get(Context),
    275           TypeBuilder<types::i<32> *, false>::get(Context),
    276           TypeBuilder<types::i<8> *[], false>::get(Context), (void *)nullptr)),
    277       (TypeBuilder<MyPortableType *, false>::get(Context)));
    278   EXPECT_EQ(
    279       PointerType::getUnqual(StructType::get(
    280           TypeBuilder<types::i<32>, false>::get(Context),
    281           TypeBuilder<types::i<32> *, false>::get(Context),
    282           TypeBuilder<types::i<8> *[], false>::get(Context), (void *)nullptr)),
    283       (TypeBuilder<MyPortableType *, true>::get(Context)));
    284 }
    285 
    286 }  // anonymous namespace
    287