TypeBuilder.h revision 894018228b0e0bdbd7aa7e8f47d4a9458789ca82
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 22namespace 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 const 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 throw a recursive_init exception. 77template<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. 81namespace types { 82/// i<N> corresponds to the LLVM IntegerType with N bits. 83template<uint32_t num_bits> class i {}; 84 85// The following classes represent the LLVM floating types. 86class ieee_float {}; 87class ieee_double {}; 88class x86_fp80 {}; 89class fp128 {}; 90class ppc_fp128 {}; 91} // namespace types 92 93// LLVM doesn't have const or volatile types. 94template<typename T, bool cross> class TypeBuilder<const T, cross> 95 : public TypeBuilder<T, cross> {}; 96template<typename T, bool cross> class TypeBuilder<volatile T, cross> 97 : public TypeBuilder<T, cross> {}; 98template<typename T, bool cross> class TypeBuilder<const volatile T, cross> 99 : public TypeBuilder<T, cross> {}; 100 101// Pointers 102template<typename T, bool cross> class TypeBuilder<T*, cross> { 103public: 104 static const PointerType *get(LLVMContext &Context) { 105 return PointerType::getUnqual(TypeBuilder<T,cross>::get(Context)); 106 } 107}; 108 109/// There is no support for references 110template<typename T, bool cross> class TypeBuilder<T&, cross> {}; 111 112// Arrays 113template<typename T, size_t N, bool cross> class TypeBuilder<T[N], cross> { 114public: 115 static const ArrayType *get(LLVMContext &Context) { 116 return ArrayType::get(TypeBuilder<T, cross>::get(Context), N); 117 } 118}; 119/// LLVM uses an array of length 0 to represent an unknown-length array. 120template<typename T, bool cross> class TypeBuilder<T[], cross> { 121public: 122 static const ArrayType *get(LLVMContext &Context) { 123 return ArrayType::get(TypeBuilder<T, cross>::get(Context), 0); 124 } 125}; 126 127// Define the C integral types only for TypeBuilder<T, false>. 128// 129// C integral types do not have a defined size. It would be nice to use the 130// stdint.h-defined typedefs that do have defined sizes, but we'd run into the 131// following problem: 132// 133// On an ILP32 machine, stdint.h might define: 134// 135// typedef int int32_t; 136// typedef long long int64_t; 137// typedef long size_t; 138// 139// If we defined TypeBuilder<int32_t> and TypeBuilder<int64_t>, then any use of 140// TypeBuilder<size_t> would fail. We couldn't define TypeBuilder<size_t> in 141// addition to the defined-size types because we'd get duplicate definitions on 142// platforms where stdint.h instead defines: 143// 144// typedef int int32_t; 145// typedef long long int64_t; 146// typedef int size_t; 147// 148// So we define all the primitive C types and nothing else. 149#define DEFINE_INTEGRAL_TYPEBUILDER(T) \ 150template<> class TypeBuilder<T, false> { \ 151public: \ 152 static const IntegerType *get(LLVMContext &Context) { \ 153 return IntegerType::get(Context, sizeof(T) * CHAR_BIT); \ 154 } \ 155}; \ 156template<> class TypeBuilder<T, true> { \ 157 /* We provide a definition here so users don't accidentally */ \ 158 /* define these types to work. */ \ 159} 160DEFINE_INTEGRAL_TYPEBUILDER(char); 161DEFINE_INTEGRAL_TYPEBUILDER(signed char); 162DEFINE_INTEGRAL_TYPEBUILDER(unsigned char); 163DEFINE_INTEGRAL_TYPEBUILDER(short); 164DEFINE_INTEGRAL_TYPEBUILDER(unsigned short); 165DEFINE_INTEGRAL_TYPEBUILDER(int); 166DEFINE_INTEGRAL_TYPEBUILDER(unsigned int); 167DEFINE_INTEGRAL_TYPEBUILDER(long); 168DEFINE_INTEGRAL_TYPEBUILDER(unsigned long); 169#ifdef _MSC_VER 170DEFINE_INTEGRAL_TYPEBUILDER(__int64); 171DEFINE_INTEGRAL_TYPEBUILDER(unsigned __int64); 172#else /* _MSC_VER */ 173DEFINE_INTEGRAL_TYPEBUILDER(long long); 174DEFINE_INTEGRAL_TYPEBUILDER(unsigned long long); 175#endif /* _MSC_VER */ 176#undef DEFINE_INTEGRAL_TYPEBUILDER 177 178template<uint32_t num_bits, bool cross> 179class TypeBuilder<types::i<num_bits>, cross> { 180public: 181 static const IntegerType *get(LLVMContext &C) { 182 return IntegerType::get(C, num_bits); 183 } 184}; 185 186template<> class TypeBuilder<float, false> { 187public: 188 static const Type *get(LLVMContext& C) { 189 return Type::getFloatTy(C); 190 } 191}; 192template<> class TypeBuilder<float, true> {}; 193 194template<> class TypeBuilder<double, false> { 195public: 196 static const Type *get(LLVMContext& C) { 197 return Type::getDoubleTy(C); 198 } 199}; 200template<> class TypeBuilder<double, true> {}; 201 202template<bool cross> class TypeBuilder<types::ieee_float, cross> { 203public: 204 static const Type *get(LLVMContext& C) { return Type::getFloatTy(C); } 205}; 206template<bool cross> class TypeBuilder<types::ieee_double, cross> { 207public: 208 static const Type *get(LLVMContext& C) { return Type::getDoubleTy(C); } 209}; 210template<bool cross> class TypeBuilder<types::x86_fp80, cross> { 211public: 212 static const Type *get(LLVMContext& C) { return Type::getX86_FP80Ty(C); } 213}; 214template<bool cross> class TypeBuilder<types::fp128, cross> { 215public: 216 static const Type *get(LLVMContext& C) { return Type::getFP128Ty(C); } 217}; 218template<bool cross> class TypeBuilder<types::ppc_fp128, cross> { 219public: 220 static const Type *get(LLVMContext& C) { return Type::getPPC_FP128Ty(C); } 221}; 222 223template<bool cross> class TypeBuilder<void, cross> { 224public: 225 static const Type *get(LLVMContext &C) { 226 return Type::getVoidTy(C); 227 } 228}; 229 230/// void* is disallowed in LLVM types, but it occurs often enough in C code that 231/// we special case it. 232template<> class TypeBuilder<void*, false> 233 : public TypeBuilder<types::i<8>*, false> {}; 234template<> class TypeBuilder<const void*, false> 235 : public TypeBuilder<types::i<8>*, false> {}; 236template<> class TypeBuilder<volatile void*, false> 237 : public TypeBuilder<types::i<8>*, false> {}; 238template<> class TypeBuilder<const volatile void*, false> 239 : public TypeBuilder<types::i<8>*, false> {}; 240 241template<typename R, bool cross> class TypeBuilder<R(), cross> { 242public: 243 static const FunctionType *get(LLVMContext &Context) { 244 return FunctionType::get(TypeBuilder<R, cross>::get(Context), false); 245 } 246}; 247template<typename R, typename A1, bool cross> class TypeBuilder<R(A1), cross> { 248public: 249 static const FunctionType *get(LLVMContext &Context) { 250 std::vector<const Type*> params; 251 params.reserve(1); 252 params.push_back(TypeBuilder<A1, cross>::get(Context)); 253 return FunctionType::get(TypeBuilder<R, cross>::get(Context), 254 params, false); 255 } 256}; 257template<typename R, typename A1, typename A2, bool cross> 258class TypeBuilder<R(A1, A2), cross> { 259public: 260 static const FunctionType *get(LLVMContext &Context) { 261 std::vector<const Type*> params; 262 params.reserve(2); 263 params.push_back(TypeBuilder<A1, cross>::get(Context)); 264 params.push_back(TypeBuilder<A2, cross>::get(Context)); 265 return FunctionType::get(TypeBuilder<R, cross>::get(Context), 266 params, false); 267 } 268}; 269template<typename R, typename A1, typename A2, typename A3, bool cross> 270class TypeBuilder<R(A1, A2, A3), cross> { 271public: 272 static const FunctionType *get(LLVMContext &Context) { 273 std::vector<const Type*> params; 274 params.reserve(3); 275 params.push_back(TypeBuilder<A1, cross>::get(Context)); 276 params.push_back(TypeBuilder<A2, cross>::get(Context)); 277 params.push_back(TypeBuilder<A3, cross>::get(Context)); 278 return FunctionType::get(TypeBuilder<R, cross>::get(Context), 279 params, false); 280 } 281}; 282 283template<typename R, typename A1, typename A2, typename A3, typename A4, 284 bool cross> 285class TypeBuilder<R(A1, A2, A3, A4), cross> { 286public: 287 static const FunctionType *get(LLVMContext &Context) { 288 std::vector<const Type*> params; 289 params.reserve(4); 290 params.push_back(TypeBuilder<A1, cross>::get(Context)); 291 params.push_back(TypeBuilder<A2, cross>::get(Context)); 292 params.push_back(TypeBuilder<A3, cross>::get(Context)); 293 params.push_back(TypeBuilder<A4, cross>::get(Context)); 294 return FunctionType::get(TypeBuilder<R, cross>::get(Context), 295 params, false); 296 } 297}; 298 299template<typename R, typename A1, typename A2, typename A3, typename A4, 300 typename A5, bool cross> 301class TypeBuilder<R(A1, A2, A3, A4, A5), cross> { 302public: 303 static const FunctionType *get(LLVMContext &Context) { 304 std::vector<const Type*> params; 305 params.reserve(5); 306 params.push_back(TypeBuilder<A1, cross>::get(Context)); 307 params.push_back(TypeBuilder<A2, cross>::get(Context)); 308 params.push_back(TypeBuilder<A3, cross>::get(Context)); 309 params.push_back(TypeBuilder<A4, cross>::get(Context)); 310 params.push_back(TypeBuilder<A5, cross>::get(Context)); 311 return FunctionType::get(TypeBuilder<R, cross>::get(Context), 312 params, false); 313 } 314}; 315 316template<typename R, bool cross> class TypeBuilder<R(...), cross> { 317public: 318 static const FunctionType *get(LLVMContext &Context) { 319 return FunctionType::get(TypeBuilder<R, cross>::get(Context), true); 320 } 321}; 322template<typename R, typename A1, bool cross> 323class TypeBuilder<R(A1, ...), cross> { 324public: 325 static const FunctionType *get(LLVMContext &Context) { 326 std::vector<const Type*> params; 327 params.reserve(1); 328 params.push_back(TypeBuilder<A1, cross>::get(Context)); 329 return FunctionType::get(TypeBuilder<R, cross>::get(Context), params, true); 330 } 331}; 332template<typename R, typename A1, typename A2, bool cross> 333class TypeBuilder<R(A1, A2, ...), cross> { 334public: 335 static const FunctionType *get(LLVMContext &Context) { 336 std::vector<const Type*> params; 337 params.reserve(2); 338 params.push_back(TypeBuilder<A1, cross>::get(Context)); 339 params.push_back(TypeBuilder<A2, cross>::get(Context)); 340 return FunctionType::get(TypeBuilder<R, cross>::get(Context), 341 params, true); 342 } 343}; 344template<typename R, typename A1, typename A2, typename A3, bool cross> 345class TypeBuilder<R(A1, A2, A3, ...), cross> { 346public: 347 static const FunctionType *get(LLVMContext &Context) { 348 std::vector<const Type*> params; 349 params.reserve(3); 350 params.push_back(TypeBuilder<A1, cross>::get(Context)); 351 params.push_back(TypeBuilder<A2, cross>::get(Context)); 352 params.push_back(TypeBuilder<A3, cross>::get(Context)); 353 return FunctionType::get(TypeBuilder<R, cross>::get(Context), 354 params, true); 355 } 356}; 357 358template<typename R, typename A1, typename A2, typename A3, typename A4, 359 bool cross> 360class TypeBuilder<R(A1, A2, A3, A4, ...), cross> { 361public: 362 static const FunctionType *get(LLVMContext &Context) { 363 std::vector<const Type*> params; 364 params.reserve(4); 365 params.push_back(TypeBuilder<A1, cross>::get(Context)); 366 params.push_back(TypeBuilder<A2, cross>::get(Context)); 367 params.push_back(TypeBuilder<A3, cross>::get(Context)); 368 params.push_back(TypeBuilder<A4, cross>::get(Context)); 369 return FunctionType::get(TypeBuilder<R, cross>::get(Context), 370 params, true); 371 } 372}; 373 374template<typename R, typename A1, typename A2, typename A3, typename A4, 375 typename A5, bool cross> 376class TypeBuilder<R(A1, A2, A3, A4, A5, ...), cross> { 377public: 378 static const FunctionType *get(LLVMContext &Context) { 379 std::vector<const Type*> params; 380 params.reserve(5); 381 params.push_back(TypeBuilder<A1, cross>::get(Context)); 382 params.push_back(TypeBuilder<A2, cross>::get(Context)); 383 params.push_back(TypeBuilder<A3, cross>::get(Context)); 384 params.push_back(TypeBuilder<A4, cross>::get(Context)); 385 params.push_back(TypeBuilder<A5, cross>::get(Context)); 386 return FunctionType::get(TypeBuilder<R, cross>::get(Context), 387 params, true); 388 } 389}; 390 391} // namespace llvm 392 393#endif 394