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