Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines the PointerLikeTypeTraits class.  This allows data
  10. // structures to reason about pointers and other things that are pointer sized.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
  15. #define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
  16.  
  17. #include "llvm/Support/DataTypes.h"
  18. #include <cassert>
  19. #include <type_traits>
  20.  
  21. namespace llvm {
  22.  
  23. /// A traits type that is used to handle pointer types and things that are just
  24. /// wrappers for pointers as a uniform entity.
  25. template <typename T> struct PointerLikeTypeTraits;
  26.  
  27. namespace detail {
  28. /// A tiny meta function to compute the log2 of a compile time constant.
  29. template <size_t N>
  30. struct ConstantLog2
  31.     : std::integral_constant<size_t, ConstantLog2<N / 2>::value + 1> {};
  32. template <> struct ConstantLog2<1> : std::integral_constant<size_t, 0> {};
  33.  
  34. // Provide a trait to check if T is pointer-like.
  35. template <typename T, typename U = void> struct HasPointerLikeTypeTraits {
  36.   static const bool value = false;
  37. };
  38.  
  39. // sizeof(T) is valid only for a complete T.
  40. template <typename T>
  41. struct HasPointerLikeTypeTraits<
  42.     T, decltype((sizeof(PointerLikeTypeTraits<T>) + sizeof(T)), void())> {
  43.   static const bool value = true;
  44. };
  45.  
  46. template <typename T> struct IsPointerLike {
  47.   static const bool value = HasPointerLikeTypeTraits<T>::value;
  48. };
  49.  
  50. template <typename T> struct IsPointerLike<T *> {
  51.   static const bool value = true;
  52. };
  53. } // namespace detail
  54.  
  55. // Provide PointerLikeTypeTraits for non-cvr pointers.
  56. template <typename T> struct PointerLikeTypeTraits<T *> {
  57.   static inline void *getAsVoidPointer(T *P) { return P; }
  58.   static inline T *getFromVoidPointer(void *P) { return static_cast<T *>(P); }
  59.  
  60.   static constexpr int NumLowBitsAvailable =
  61.       detail::ConstantLog2<alignof(T)>::value;
  62. };
  63.  
  64. template <> struct PointerLikeTypeTraits<void *> {
  65.   static inline void *getAsVoidPointer(void *P) { return P; }
  66.   static inline void *getFromVoidPointer(void *P) { return P; }
  67.  
  68.   /// Note, we assume here that void* is related to raw malloc'ed memory and
  69.   /// that malloc returns objects at least 4-byte aligned. However, this may be
  70.   /// wrong, or pointers may be from something other than malloc. In this case,
  71.   /// you should specify a real typed pointer or avoid this template.
  72.   ///
  73.   /// All clients should use assertions to do a run-time check to ensure that
  74.   /// this is actually true.
  75.   static constexpr int NumLowBitsAvailable = 2;
  76. };
  77.  
  78. // Provide PointerLikeTypeTraits for const things.
  79. template <typename T> struct PointerLikeTypeTraits<const T> {
  80.   typedef PointerLikeTypeTraits<T> NonConst;
  81.  
  82.   static inline const void *getAsVoidPointer(const T P) {
  83.     return NonConst::getAsVoidPointer(P);
  84.   }
  85.   static inline const T getFromVoidPointer(const void *P) {
  86.     return NonConst::getFromVoidPointer(const_cast<void *>(P));
  87.   }
  88.   static constexpr int NumLowBitsAvailable = NonConst::NumLowBitsAvailable;
  89. };
  90.  
  91. // Provide PointerLikeTypeTraits for const pointers.
  92. template <typename T> struct PointerLikeTypeTraits<const T *> {
  93.   typedef PointerLikeTypeTraits<T *> NonConst;
  94.  
  95.   static inline const void *getAsVoidPointer(const T *P) {
  96.     return NonConst::getAsVoidPointer(const_cast<T *>(P));
  97.   }
  98.   static inline const T *getFromVoidPointer(const void *P) {
  99.     return NonConst::getFromVoidPointer(const_cast<void *>(P));
  100.   }
  101.   static constexpr int NumLowBitsAvailable = NonConst::NumLowBitsAvailable;
  102. };
  103.  
  104. // Provide PointerLikeTypeTraits for uintptr_t.
  105. template <> struct PointerLikeTypeTraits<uintptr_t> {
  106.   static inline void *getAsVoidPointer(uintptr_t P) {
  107.     return reinterpret_cast<void *>(P);
  108.   }
  109.   static inline uintptr_t getFromVoidPointer(void *P) {
  110.     return reinterpret_cast<uintptr_t>(P);
  111.   }
  112.   // No bits are available!
  113.   static constexpr int NumLowBitsAvailable = 0;
  114. };
  115.  
  116. /// Provide suitable custom traits struct for function pointers.
  117. ///
  118. /// Function pointers can't be directly given these traits as functions can't
  119. /// have their alignment computed with `alignof` and we need different casting.
  120. ///
  121. /// To rely on higher alignment for a specialized use, you can provide a
  122. /// customized form of this template explicitly with higher alignment, and
  123. /// potentially use alignment attributes on functions to satisfy that.
  124. template <int Alignment, typename FunctionPointerT>
  125. struct FunctionPointerLikeTypeTraits {
  126.   static constexpr int NumLowBitsAvailable =
  127.       detail::ConstantLog2<Alignment>::value;
  128.   static inline void *getAsVoidPointer(FunctionPointerT P) {
  129.     assert((reinterpret_cast<uintptr_t>(P) &
  130.             ~((uintptr_t)-1 << NumLowBitsAvailable)) == 0 &&
  131.            "Alignment not satisfied for an actual function pointer!");
  132.     return reinterpret_cast<void *>(P);
  133.   }
  134.   static inline FunctionPointerT getFromVoidPointer(void *P) {
  135.     return reinterpret_cast<FunctionPointerT>(P);
  136.   }
  137. };
  138.  
  139. /// Provide a default specialization for function pointers that assumes 4-byte
  140. /// alignment.
  141. ///
  142. /// We assume here that functions used with this are always at least 4-byte
  143. /// aligned. This means that, for example, thumb functions won't work or systems
  144. /// with weird unaligned function pointers won't work. But all practical systems
  145. /// we support satisfy this requirement.
  146. template <typename ReturnT, typename... ParamTs>
  147. struct PointerLikeTypeTraits<ReturnT (*)(ParamTs...)>
  148.     : FunctionPointerLikeTypeTraits<4, ReturnT (*)(ParamTs...)> {};
  149.  
  150. } // end namespace llvm
  151.  
  152. #endif
  153.