TypeBuilder.h revision 0fd38069cb6699ce21eb159f22d3f23c012c9e81
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 <limits.h> 20 21namespace llvm { 22 23/// TypeBuilder - This provides a uniform API for looking up types 24/// known at compile time. To support cross-compilation, we define a 25/// series of tag types in the llvm::types namespace, like i<N>, 26/// ieee_float, ppc_fp128, etc. TypeBuilder<T, false> allows T to be 27/// any of these, a native C type (whose size may depend on the host 28/// compiler), or a pointer, function, or struct type built out of 29/// these. TypeBuilder<T, true> removes native C types from this set 30/// to guarantee that its result is suitable for cross-compilation. 31/// We define the primitive types, pointer types, and functions up to 32/// 5 arguments here, but to use this class with your own types, 33/// you'll need to specialize it. For example, say you want to call a 34/// function defined externally as: 35/// 36/// struct MyType { 37/// int32 a; 38/// int32 *b; 39/// void *array[1]; // Intended as a flexible array. 40/// }; 41/// int8 AFunction(struct MyType *value); 42/// 43/// You'll want to use 44/// Function::Create(TypeBuilder<types::i<8>(MyType*), true>::get(), ...) 45/// to declare the function, but when you first try this, your compiler will 46/// complain that TypeBuilder<MyType, true>::get() doesn't exist. To fix this, 47/// write: 48/// 49/// namespace llvm { 50/// template<bool xcompile> class TypeBuilder<MyType, xcompile> { 51/// public: 52/// static const StructType *get() { 53/// // Using the static result variable ensures that the type is 54/// // only looked up once. 55/// static const StructType *const result = StructType::get( 56/// TypeBuilder<types::i<32>, xcompile>::get(), 57/// TypeBuilder<types::i<32>*, xcompile>::get(), 58/// TypeBuilder<types::i<8>*[], xcompile>::get(), 59/// NULL); 60/// return result; 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/// Using the static result variable ensures that the type is only looked up 75/// once. 76/// 77/// TypeBuilder cannot handle recursive types or types you only know at runtime. 78/// If you try to give it a recursive type, it will deadlock, infinitely 79/// recurse, or throw a recursive_init exception. 80template<typename T, bool cross_compilable> class TypeBuilder {}; 81 82// Types for use with cross-compilable TypeBuilders. These correspond 83// exactly with an LLVM-native type. 84namespace types { 85/// i<N> corresponds to the LLVM IntegerType with N bits. 86template<uint32_t num_bits> class i {}; 87 88// The following classes represent the LLVM floating types. 89class ieee_float {}; 90class ieee_double {}; 91class x86_fp80 {}; 92class fp128 {}; 93class ppc_fp128 {}; 94} // namespace types 95 96// LLVM doesn't have const or volatile types. 97template<typename T, bool cross> class TypeBuilder<const T, cross> 98 : public TypeBuilder<T, cross> {}; 99template<typename T, bool cross> class TypeBuilder<volatile T, cross> 100 : public TypeBuilder<T, cross> {}; 101template<typename T, bool cross> class TypeBuilder<const volatile T, cross> 102 : public TypeBuilder<T, cross> {}; 103 104// Pointers 105template<typename T, bool cross> class TypeBuilder<T*, cross> { 106public: 107 static const PointerType *get() { 108 static const PointerType *const result = 109 PointerType::getUnqual(TypeBuilder<T,cross>::get()); 110 return result; 111 } 112}; 113 114/// There is no support for references 115template<typename T, bool cross> class TypeBuilder<T&, cross> {}; 116 117// Arrays 118template<typename T, size_t N, bool cross> class TypeBuilder<T[N], cross> { 119public: 120 static const ArrayType *get() { 121 static const ArrayType *const result = 122 ArrayType::get(TypeBuilder<T, cross>::get(), N); 123 return result; 124 } 125}; 126/// LLVM uses an array of length 0 to represent an unknown-length array. 127template<typename T, bool cross> class TypeBuilder<T[], cross> { 128public: 129 static const ArrayType *get() { 130 static const ArrayType *const result = 131 ArrayType::get(TypeBuilder<T, cross>::get(), 0); 132 return result; 133 } 134}; 135 136// Define the C integral types only for TypeBuilder<T, false>. 137// 138// C integral types do not have a defined size. It would be nice to use the 139// stdint.h-defined typedefs that do have defined sizes, but we'd run into the 140// following problem: 141// 142// On an ILP32 machine, stdint.h might define: 143// 144// typedef int int32_t; 145// typedef long long int64_t; 146// typedef long size_t; 147// 148// If we defined TypeBuilder<int32_t> and TypeBuilder<int64_t>, then any use of 149// TypeBuilder<size_t> would fail. We couldn't define TypeBuilder<size_t> in 150// addition to the defined-size types because we'd get duplicate definitions on 151// platforms where stdint.h instead defines: 152// 153// typedef int int32_t; 154// typedef long long int64_t; 155// typedef int size_t; 156// 157// So we define all the primitive C types and nothing else. 158#define DEFINE_INTEGRAL_TYPEBUILDER(T) \ 159template<> class TypeBuilder<T, false> { \ 160public: \ 161 static const IntegerType *get() { \ 162 static const IntegerType *const result = \ 163 IntegerType::get(sizeof(T) * CHAR_BIT); \ 164 return result; \ 165 } \ 166}; \ 167template<> class TypeBuilder<T, true> { \ 168 /* We provide a definition here so users don't accidentally */ \ 169 /* define these types to work. */ \ 170} 171DEFINE_INTEGRAL_TYPEBUILDER(char); 172DEFINE_INTEGRAL_TYPEBUILDER(signed char); 173DEFINE_INTEGRAL_TYPEBUILDER(unsigned char); 174DEFINE_INTEGRAL_TYPEBUILDER(short); 175DEFINE_INTEGRAL_TYPEBUILDER(unsigned short); 176DEFINE_INTEGRAL_TYPEBUILDER(int); 177DEFINE_INTEGRAL_TYPEBUILDER(unsigned int); 178DEFINE_INTEGRAL_TYPEBUILDER(long); 179DEFINE_INTEGRAL_TYPEBUILDER(unsigned long); 180#ifdef _MSC_VER 181DEFINE_INTEGRAL_TYPEBUILDER(__int64); 182DEFINE_INTEGRAL_TYPEBUILDER(unsigned __int64); 183#else /* _MSC_VER */ 184DEFINE_INTEGRAL_TYPEBUILDER(long long); 185DEFINE_INTEGRAL_TYPEBUILDER(unsigned long long); 186#endif /* _MSC_VER */ 187#undef DEFINE_INTEGRAL_TYPEBUILDER 188 189template<uint32_t num_bits, bool cross> 190class TypeBuilder<types::i<num_bits>, cross> { 191public: 192 static const IntegerType *get() { 193 static const IntegerType *const result = IntegerType::get(num_bits); 194 return result; 195 } 196}; 197 198template<> class TypeBuilder<float, false> { 199public: 200 static const Type *get() { 201 return Type::FloatTy; 202 } 203}; 204template<> class TypeBuilder<float, true> {}; 205 206template<> class TypeBuilder<double, false> { 207public: 208 static const Type *get() { 209 return Type::DoubleTy; 210 } 211}; 212template<> class TypeBuilder<double, true> {}; 213 214template<bool cross> class TypeBuilder<types::ieee_float, cross> { 215public: 216 static const Type *get() { return Type::FloatTy; } 217}; 218template<bool cross> class TypeBuilder<types::ieee_double, cross> { 219public: 220 static const Type *get() { return Type::DoubleTy; } 221}; 222template<bool cross> class TypeBuilder<types::x86_fp80, cross> { 223public: 224 static const Type *get() { return Type::X86_FP80Ty; } 225}; 226template<bool cross> class TypeBuilder<types::fp128, cross> { 227public: 228 static const Type *get() { return Type::FP128Ty; } 229}; 230template<bool cross> class TypeBuilder<types::ppc_fp128, cross> { 231public: 232 static const Type *get() { return Type::PPC_FP128Ty; } 233}; 234 235template<bool cross> class TypeBuilder<void, cross> { 236public: 237 static const Type *get() { 238 return Type::VoidTy; 239 } 240}; 241 242/// void* is disallowed in LLVM types, but it occurs often enough in C code that 243/// we special case it. 244template<> class TypeBuilder<void*, false> 245 : public TypeBuilder<types::i<8>*, false> {}; 246 247template<typename R, bool cross> class TypeBuilder<R(), cross> { 248public: 249 static const FunctionType *get() { 250 static const FunctionType *const result = create(); 251 return result; 252 } 253 254private: 255 static const FunctionType *create() { 256 return FunctionType::get(TypeBuilder<R, cross>::get(), false); 257 } 258}; 259template<typename R, typename A1, bool cross> class TypeBuilder<R(A1), cross> { 260public: 261 static const FunctionType *get() { 262 static const FunctionType *const result = create(); 263 return result; 264 } 265 266private: 267 static const FunctionType *create() { 268 std::vector<const Type*> params; 269 params.reserve(1); 270 params.push_back(TypeBuilder<A1, cross>::get()); 271 return FunctionType::get(TypeBuilder<R, cross>::get(), params, false); 272 } 273}; 274template<typename R, typename A1, typename A2, bool cross> 275class TypeBuilder<R(A1, A2), cross> { 276public: 277 static const FunctionType *get() { 278 static const FunctionType *const result = create(); 279 return result; 280 } 281 282private: 283 static const FunctionType *create() { 284 std::vector<const Type*> params; 285 params.reserve(2); 286 params.push_back(TypeBuilder<A1, cross>::get()); 287 params.push_back(TypeBuilder<A2, cross>::get()); 288 return FunctionType::get(TypeBuilder<R, cross>::get(), params, false); 289 } 290}; 291template<typename R, typename A1, typename A2, typename A3, bool cross> 292class TypeBuilder<R(A1, A2, A3), cross> { 293public: 294 static const FunctionType *get() { 295 static const FunctionType *const result = create(); 296 return result; 297 } 298 299private: 300 static const FunctionType *create() { 301 std::vector<const Type*> params; 302 params.reserve(3); 303 params.push_back(TypeBuilder<A1, cross>::get()); 304 params.push_back(TypeBuilder<A2, cross>::get()); 305 params.push_back(TypeBuilder<A3, cross>::get()); 306 return FunctionType::get(TypeBuilder<R, cross>::get(), params, false); 307 } 308}; 309 310template<typename R, typename A1, typename A2, typename A3, typename A4, 311 bool cross> 312class TypeBuilder<R(A1, A2, A3, A4), cross> { 313public: 314 static const FunctionType *get() { 315 static const FunctionType *const result = create(); 316 return result; 317 } 318 319private: 320 static const FunctionType *create() { 321 std::vector<const Type*> params; 322 params.reserve(4); 323 params.push_back(TypeBuilder<A1, cross>::get()); 324 params.push_back(TypeBuilder<A2, cross>::get()); 325 params.push_back(TypeBuilder<A3, cross>::get()); 326 params.push_back(TypeBuilder<A4, cross>::get()); 327 return FunctionType::get(TypeBuilder<R, cross>::get(), params, false); 328 } 329}; 330 331template<typename R, typename A1, typename A2, typename A3, typename A4, 332 typename A5, bool cross> 333class TypeBuilder<R(A1, A2, A3, A4, A5), cross> { 334public: 335 static const FunctionType *get() { 336 static const FunctionType *const result = create(); 337 return result; 338 } 339 340private: 341 static const FunctionType *create() { 342 std::vector<const Type*> params; 343 params.reserve(5); 344 params.push_back(TypeBuilder<A1, cross>::get()); 345 params.push_back(TypeBuilder<A2, cross>::get()); 346 params.push_back(TypeBuilder<A3, cross>::get()); 347 params.push_back(TypeBuilder<A4, cross>::get()); 348 params.push_back(TypeBuilder<A5, cross>::get()); 349 return FunctionType::get(TypeBuilder<R, cross>::get(), params, false); 350 } 351}; 352 353template<typename R, bool cross> class TypeBuilder<R(...), cross> { 354public: 355 static const FunctionType *get() { 356 static const FunctionType *const result = create(); 357 return result; 358 } 359 360private: 361 static const FunctionType *create() { 362 return FunctionType::get(TypeBuilder<R, cross>::get(), true); 363 } 364}; 365template<typename R, typename A1, bool cross> 366class TypeBuilder<R(A1, ...), cross> { 367public: 368 static const FunctionType *get() { 369 static const FunctionType *const result = create(); 370 return result; 371 } 372 373private: 374 static const FunctionType *create() { 375 std::vector<const Type*> params; 376 params.reserve(1); 377 params.push_back(TypeBuilder<A1, cross>::get()); 378 return FunctionType::get(TypeBuilder<R, cross>::get(), params, true); 379 } 380}; 381template<typename R, typename A1, typename A2, bool cross> 382class TypeBuilder<R(A1, A2, ...), cross> { 383public: 384 static const FunctionType *get() { 385 static const FunctionType *const result = create(); 386 return result; 387 } 388 389private: 390 static const FunctionType *create() { 391 std::vector<const Type*> params; 392 params.reserve(2); 393 params.push_back(TypeBuilder<A1, cross>::get()); 394 params.push_back(TypeBuilder<A2, cross>::get()); 395 return FunctionType::get(TypeBuilder<R, cross>::get(), params, true); 396 } 397}; 398template<typename R, typename A1, typename A2, typename A3, bool cross> 399class TypeBuilder<R(A1, A2, A3, ...), cross> { 400public: 401 static const FunctionType *get() { 402 static const FunctionType *const result = create(); 403 return result; 404 } 405 406private: 407 static const FunctionType *create() { 408 std::vector<const Type*> params; 409 params.reserve(3); 410 params.push_back(TypeBuilder<A1, cross>::get()); 411 params.push_back(TypeBuilder<A2, cross>::get()); 412 params.push_back(TypeBuilder<A3, cross>::get()); 413 return FunctionType::get(TypeBuilder<R, cross>::get(), params, true); 414 } 415}; 416 417template<typename R, typename A1, typename A2, typename A3, typename A4, 418 bool cross> 419class TypeBuilder<R(A1, A2, A3, A4, ...), cross> { 420public: 421 static const FunctionType *get() { 422 static const FunctionType *const result = create(); 423 return result; 424 } 425 426private: 427 static const FunctionType *create() { 428 std::vector<const Type*> params; 429 params.reserve(4); 430 params.push_back(TypeBuilder<A1, cross>::get()); 431 params.push_back(TypeBuilder<A2, cross>::get()); 432 params.push_back(TypeBuilder<A3, cross>::get()); 433 params.push_back(TypeBuilder<A4, cross>::get()); 434 return FunctionType::get(TypeBuilder<R, cross>::get(), params, true); 435 } 436}; 437 438template<typename R, typename A1, typename A2, typename A3, typename A4, 439 typename A5, bool cross> 440class TypeBuilder<R(A1, A2, A3, A4, A5, ...), cross> { 441public: 442 static const FunctionType *get() { 443 static const FunctionType *const result = create(); 444 return result; 445 } 446 447private: 448 static const FunctionType *create() { 449 std::vector<const Type*> params; 450 params.reserve(5); 451 params.push_back(TypeBuilder<A1, cross>::get()); 452 params.push_back(TypeBuilder<A2, cross>::get()); 453 params.push_back(TypeBuilder<A3, cross>::get()); 454 params.push_back(TypeBuilder<A4, cross>::get()); 455 params.push_back(TypeBuilder<A5, cross>::get()); 456 return FunctionType::get(TypeBuilder<R, cross>::get(), params, true); 457 } 458}; 459 460} // namespace llvm 461 462#endif 463