Path: blob/main/contrib/llvm-project/libc/src/__support/endian_internal.h
213766 views
//===-- Endianness support --------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIBC_SRC___SUPPORT_ENDIAN_INTERNAL_H9#define LLVM_LIBC_SRC___SUPPORT_ENDIAN_INTERNAL_H1011#include "common.h"12#include "src/__support/macros/config.h"1314#include <stdint.h>1516namespace LIBC_NAMESPACE_DECL {1718// We rely on compiler preprocessor defines to allow for cross compilation.19#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \20!defined(__ORDER_BIG_ENDIAN__)21#error "Missing preprocessor definitions for endianness detection."22#endif2324namespace internal {2526// Converts uint8_t, uint16_t, uint32_t, uint64_t to its big or little endian27// counterpart.28// We use explicit template specialization:29// - to prevent accidental integer promotion.30// - to prevent fallback in (unlikely) case of middle-endianness.3132template <unsigned ORDER> struct Endian {33static constexpr const bool IS_LITTLE = ORDER == __ORDER_LITTLE_ENDIAN__;34static constexpr const bool IS_BIG = ORDER == __ORDER_BIG_ENDIAN__;35template <typename T> LIBC_INLINE static T to_big_endian(T value);36template <typename T> LIBC_INLINE static T to_little_endian(T value);37};3839// Little Endian specializations40template <>41template <>42LIBC_INLINE uint8_t43Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint8_t>(uint8_t v) {44return v;45}46template <>47template <>48LIBC_INLINE uint8_t49Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint8_t>(uint8_t v) {50return v;51}52template <>53template <>54LIBC_INLINE uint16_t55Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint16_t>(uint16_t v) {56return __builtin_bswap16(v);57}58template <>59template <>60LIBC_INLINE uint16_t61Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint16_t>(uint16_t v) {62return v;63}64template <>65template <>66LIBC_INLINE uint32_t67Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint32_t>(uint32_t v) {68return __builtin_bswap32(v);69}70template <>71template <>72LIBC_INLINE uint32_t73Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint32_t>(uint32_t v) {74return v;75}76template <>77template <>78LIBC_INLINE uint64_t79Endian<__ORDER_LITTLE_ENDIAN__>::to_big_endian<uint64_t>(uint64_t v) {80return __builtin_bswap64(v);81}82template <>83template <>84LIBC_INLINE uint64_t85Endian<__ORDER_LITTLE_ENDIAN__>::to_little_endian<uint64_t>(uint64_t v) {86return v;87}8889// Big Endian specializations90template <>91template <>92LIBC_INLINE uint8_t93Endian<__ORDER_BIG_ENDIAN__>::to_big_endian<uint8_t>(uint8_t v) {94return v;95}96template <>97template <>98LIBC_INLINE uint8_t99Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint8_t>(uint8_t v) {100return v;101}102template <>103template <>104LIBC_INLINE uint16_t105Endian<__ORDER_BIG_ENDIAN__>::to_big_endian<uint16_t>(uint16_t v) {106return v;107}108template <>109template <>110LIBC_INLINE uint16_t111Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint16_t>(uint16_t v) {112return __builtin_bswap16(v);113}114template <>115template <>116LIBC_INLINE uint32_t117Endian<__ORDER_BIG_ENDIAN__>::to_big_endian<uint32_t>(uint32_t v) {118return v;119}120template <>121template <>122LIBC_INLINE uint32_t123Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint32_t>(uint32_t v) {124return __builtin_bswap32(v);125}126template <>127template <>128LIBC_INLINE uint64_t129Endian<__ORDER_BIG_ENDIAN__>::to_big_endian<uint64_t>(uint64_t v) {130return v;131}132template <>133template <>134LIBC_INLINE uint64_t135Endian<__ORDER_BIG_ENDIAN__>::to_little_endian<uint64_t>(uint64_t v) {136return __builtin_bswap64(v);137}138139} // namespace internal140141using Endian = internal::Endian<__BYTE_ORDER__>;142143} // namespace LIBC_NAMESPACE_DECL144145#endif // LLVM_LIBC_SRC___SUPPORT_ENDIAN_INTERNAL_H146147148