aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Support/PointerLikeTypeTraits.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Support/PointerLikeTypeTraits.h')
-rw-r--r--include/llvm/Support/PointerLikeTypeTraits.h34
1 files changed, 34 insertions, 0 deletions
diff --git a/include/llvm/Support/PointerLikeTypeTraits.h b/include/llvm/Support/PointerLikeTypeTraits.h
index 794230d606a4..1710b57131d1 100644
--- a/include/llvm/Support/PointerLikeTypeTraits.h
+++ b/include/llvm/Support/PointerLikeTypeTraits.h
@@ -16,6 +16,7 @@
#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
#include "llvm/Support/DataTypes.h"
+#include <assert.h>
#include <type_traits>
namespace llvm {
@@ -111,6 +112,39 @@ template <> struct PointerLikeTypeTraits<uintptr_t> {
enum { NumLowBitsAvailable = 0 };
};
+/// Provide suitable custom traits struct for function pointers.
+///
+/// Function pointers can't be directly given these traits as functions can't
+/// have their alignment computed with `alignof` and we need different casting.
+///
+/// To rely on higher alignment for a specialized use, you can provide a
+/// customized form of this template explicitly with higher alignment, and
+/// potentially use alignment attributes on functions to satisfy that.
+template <int Alignment, typename FunctionPointerT>
+struct FunctionPointerLikeTypeTraits {
+ enum { NumLowBitsAvailable = detail::ConstantLog2<Alignment>::value };
+ static inline void *getAsVoidPointer(FunctionPointerT P) {
+ assert((reinterpret_cast<uintptr_t>(P) &
+ ~((uintptr_t)-1 << NumLowBitsAvailable)) == 0 &&
+ "Alignment not satisfied for an actual function pointer!");
+ return reinterpret_cast<void *>(P);
+ }
+ static inline FunctionPointerT getFromVoidPointer(void *P) {
+ return reinterpret_cast<FunctionPointerT>(P);
+ }
+};
+
+/// Provide a default specialization for function pointers that assumes 4-byte
+/// alignment.
+///
+/// We assume here that functions used with this are always at least 4-byte
+/// aligned. This means that, for example, thumb functions won't work or systems
+/// with weird unaligned function pointers won't work. But all practical systems
+/// we support satisfy this requirement.
+template <typename ReturnT, typename... ParamTs>
+struct PointerLikeTypeTraits<ReturnT (*)(ParamTs...)>
+ : FunctionPointerLikeTypeTraits<4, ReturnT (*)(ParamTs...)> {};
+
} // end namespace llvm
#endif