1 //===-- Freestanding version of bit_cast -----------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
10 #define LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
12 #include "src/__support/CPP/type_traits.h"
13 #include "src/__support/macros/attributes.h"
14 #include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN
15 #include "src/__support/macros/sanitizer.h"
17 namespace LIBC_NAMESPACE::cpp
{
19 #if LIBC_HAS_BUILTIN(__builtin_bit_cast)
20 #define LLVM_LIBC_HAS_BUILTIN_BIT_CAST
23 #if LIBC_HAS_BUILTIN(__builtin_memcpy_inline)
24 #define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE
27 // This function guarantees the bitcast to be optimized away by the compiler for
28 // GCC >= 8 and Clang >= 6.
29 template <class To
, class From
>
30 LIBC_INLINE
constexpr To
bit_cast(const From
&from
) {
31 static_assert(sizeof(To
) == sizeof(From
), "To and From must be of same size");
32 static_assert(cpp::is_trivially_copyable
<To
>::value
&&
33 cpp::is_trivially_copyable
<From
>::value
,
34 "Cannot bit-cast instances of non-trivially copyable classes.");
35 MSAN_UNPOISON(&from
, sizeof(From
));
36 #if defined(LLVM_LIBC_HAS_BUILTIN_BIT_CAST)
37 return __builtin_bit_cast(To
, from
);
39 static_assert(cpp::is_trivially_constructible
<To
>::value
,
40 "This implementation additionally requires destination type to "
41 "be trivially constructible");
43 char *dst
= reinterpret_cast<char *>(&to
);
44 const char *src
= reinterpret_cast<const char *>(&from
);
45 #if defined(LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE)
46 __builtin_memcpy_inline(dst
, src
, sizeof(To
));
48 for (unsigned i
= 0; i
< sizeof(To
); ++i
)
50 #endif // defined(LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE)
52 #endif // defined(LLVM_LIBC_HAS_BUILTIN_BIT_CAST)
55 template <class To
, class From
>
56 LIBC_INLINE
constexpr To
bit_or_static_cast(const From
&from
) {
57 if constexpr (sizeof(To
) == sizeof(From
)) {
58 return bit_cast
<To
>(from
);
60 return static_cast<To
>(from
);
64 } // namespace LIBC_NAMESPACE::cpp
66 #endif // LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H