diff --git a/libc/src/__support/endian.h b/libc/src/__support/endian.h new file mode 100644 --- /dev/null +++ b/libc/src/__support/endian.h @@ -0,0 +1,67 @@ +//===-- Endianness support ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_SUPPORT_ENDIAN_H +#define LLVM_LIBC_SRC_SUPPORT_ENDIAN_H + +#include + +namespace __llvm_libc { + +#if defined(LLVM_LIBC_IS_BIG_ENDIAN) +#error "LLVM_LIBC_IS_BIG_ENDIAN cannot be defined directly." +#endif +#if defined(LLVM_LIBC_IS_LITTLE_ENDIAN) +#error "LLVM_LIBC_IS_LITTLE_ENDIAN cannot be defined directly." +#endif + +// We rely on compiler preprocessor defines to allow for cross compilation. +#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \ + !defined(__ORDER_BIG_ENDIAN__) +#error "Missing preprocessor definitions for endianness detection." +#endif + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define LLVM_LIBC_IS_LITTLE_ENDIAN 1 +#else +#define LLVM_LIBC_IS_LITTLE_ENDIAN 0 +#endif + +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define LLVM_LIBC_IS_BIG_ENDIAN 1 +#else +#define LLVM_LIBC_IS_BIG_ENDIAN 0 +#endif + +// Converts the value to big endian representation. This is a no-op on big +// endian architecture. We use template specialization to prevent accidental +// integer promotion. +template static inline T ToBigEndian(T value); + +#if LLVM_LIBC_IS_LITTLE_ENDIAN +template <> inline uint8_t ToBigEndian(uint8_t value) { return value; } +template <> inline uint16_t ToBigEndian(uint16_t value) { + return __builtin_bswap16(value); +} +template <> inline uint32_t ToBigEndian(uint32_t value) { + return __builtin_bswap32(value); +} +template <> inline uint64_t ToBigEndian(uint64_t value) { + return __builtin_bswap64(value); +} +#endif +#if LLVM_LIBC_IS_BIG_ENDIAN +template <> inline uint8_t ToBigEndian(uint8_t value) { return value; } +template <> inline uint16_t ToBigEndian(uint16_t value) { return value; } +template <> inline uint32_t ToBigEndian(uint32_t value) { return value; } +template <> inline uint64_t ToBigEndian(uint64_t value) { return value; } +#endif + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_SUPPORT_ENDIAN_H