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