Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:33

0001 //===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines the PointerLikeTypeTraits class.  This allows data
0010 // structures to reason about pointers and other things that are pointer sized.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
0015 #define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
0016 
0017 #include "llvm/Support/DataTypes.h"
0018 #include <cassert>
0019 #include <type_traits>
0020 
0021 namespace llvm {
0022 
0023 /// A traits type that is used to handle pointer types and things that are just
0024 /// wrappers for pointers as a uniform entity.
0025 template <typename T> struct PointerLikeTypeTraits;
0026 
0027 namespace detail {
0028 /// A tiny meta function to compute the log2 of a compile time constant.
0029 template <size_t N>
0030 struct ConstantLog2
0031     : std::integral_constant<size_t, ConstantLog2<N / 2>::value + 1> {};
0032 template <> struct ConstantLog2<1> : std::integral_constant<size_t, 0> {};
0033 
0034 // Provide a trait to check if T is pointer-like.
0035 template <typename T, typename U = void> struct HasPointerLikeTypeTraits {
0036   static const bool value = false;
0037 };
0038 
0039 // sizeof(T) is valid only for a complete T.
0040 template <typename T>
0041 struct HasPointerLikeTypeTraits<
0042     T, decltype((sizeof(PointerLikeTypeTraits<T>) + sizeof(T)), void())> {
0043   static const bool value = true;
0044 };
0045 
0046 template <typename T> struct IsPointerLike {
0047   static const bool value = HasPointerLikeTypeTraits<T>::value;
0048 };
0049 
0050 template <typename T> struct IsPointerLike<T *> {
0051   static const bool value = true;
0052 };
0053 } // namespace detail
0054 
0055 // Provide PointerLikeTypeTraits for non-cvr pointers.
0056 template <typename T> struct PointerLikeTypeTraits<T *> {
0057   static inline void *getAsVoidPointer(T *P) { return P; }
0058   static inline T *getFromVoidPointer(void *P) { return static_cast<T *>(P); }
0059 
0060   static constexpr int NumLowBitsAvailable =
0061       detail::ConstantLog2<alignof(T)>::value;
0062 };
0063 
0064 template <> struct PointerLikeTypeTraits<void *> {
0065   static inline void *getAsVoidPointer(void *P) { return P; }
0066   static inline void *getFromVoidPointer(void *P) { return P; }
0067 
0068   /// Note, we assume here that void* is related to raw malloc'ed memory and
0069   /// that malloc returns objects at least 4-byte aligned. However, this may be
0070   /// wrong, or pointers may be from something other than malloc. In this case,
0071   /// you should specify a real typed pointer or avoid this template.
0072   ///
0073   /// All clients should use assertions to do a run-time check to ensure that
0074   /// this is actually true.
0075   static constexpr int NumLowBitsAvailable = 2;
0076 };
0077 
0078 // Provide PointerLikeTypeTraits for const things.
0079 template <typename T> struct PointerLikeTypeTraits<const T> {
0080   typedef PointerLikeTypeTraits<T> NonConst;
0081 
0082   static inline const void *getAsVoidPointer(const T P) {
0083     return NonConst::getAsVoidPointer(P);
0084   }
0085   static inline const T getFromVoidPointer(const void *P) {
0086     return NonConst::getFromVoidPointer(const_cast<void *>(P));
0087   }
0088   static constexpr int NumLowBitsAvailable = NonConst::NumLowBitsAvailable;
0089 };
0090 
0091 // Provide PointerLikeTypeTraits for const pointers.
0092 template <typename T> struct PointerLikeTypeTraits<const T *> {
0093   typedef PointerLikeTypeTraits<T *> NonConst;
0094 
0095   static inline const void *getAsVoidPointer(const T *P) {
0096     return NonConst::getAsVoidPointer(const_cast<T *>(P));
0097   }
0098   static inline const T *getFromVoidPointer(const void *P) {
0099     return NonConst::getFromVoidPointer(const_cast<void *>(P));
0100   }
0101   static constexpr int NumLowBitsAvailable = NonConst::NumLowBitsAvailable;
0102 };
0103 
0104 // Provide PointerLikeTypeTraits for uintptr_t.
0105 template <> struct PointerLikeTypeTraits<uintptr_t> {
0106   static inline void *getAsVoidPointer(uintptr_t P) {
0107     return reinterpret_cast<void *>(P);
0108   }
0109   static inline uintptr_t getFromVoidPointer(void *P) {
0110     return reinterpret_cast<uintptr_t>(P);
0111   }
0112   // No bits are available!
0113   static constexpr int NumLowBitsAvailable = 0;
0114 };
0115 
0116 /// Provide suitable custom traits struct for function pointers.
0117 ///
0118 /// Function pointers can't be directly given these traits as functions can't
0119 /// have their alignment computed with `alignof` and we need different casting.
0120 ///
0121 /// To rely on higher alignment for a specialized use, you can provide a
0122 /// customized form of this template explicitly with higher alignment, and
0123 /// potentially use alignment attributes on functions to satisfy that.
0124 template <int Alignment, typename FunctionPointerT>
0125 struct FunctionPointerLikeTypeTraits {
0126   static constexpr int NumLowBitsAvailable =
0127       detail::ConstantLog2<Alignment>::value;
0128   static inline void *getAsVoidPointer(FunctionPointerT P) {
0129     assert((reinterpret_cast<uintptr_t>(P) &
0130             ~((uintptr_t)-1 << NumLowBitsAvailable)) == 0 &&
0131            "Alignment not satisfied for an actual function pointer!");
0132     return reinterpret_cast<void *>(P);
0133   }
0134   static inline FunctionPointerT getFromVoidPointer(void *P) {
0135     return reinterpret_cast<FunctionPointerT>(P);
0136   }
0137 };
0138 
0139 /// Provide a default specialization for function pointers that assumes 4-byte
0140 /// alignment.
0141 ///
0142 /// We assume here that functions used with this are always at least 4-byte
0143 /// aligned. This means that, for example, thumb functions won't work or systems
0144 /// with weird unaligned function pointers won't work. But all practical systems
0145 /// we support satisfy this requirement.
0146 template <typename ReturnT, typename... ParamTs>
0147 struct PointerLikeTypeTraits<ReturnT (*)(ParamTs...)>
0148     : FunctionPointerLikeTypeTraits<4, ReturnT (*)(ParamTs...)> {};
0149 
0150 } // end namespace llvm
0151 
0152 #endif