llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-x86 Author: David Tenty (daltenty) <details> <summary>Changes</summary> POSIX.1-2024 defines a header called `endian.h`` which contains macros and helpers for handling byte order conversions. Unfortunately it is not available on all platforms, however LLVM libc has a useful endian.h implementation that is essentially only casts and builtins. This PR draws on that implementation to add a clang header so applications on platforms without it can make use of this header. The clang header forwards to the system header if available, so existing usages are not affected. --- Full diff: https://github.com/llvm/llvm-project/pull/186032.diff 3 Files Affected: - (modified) clang/lib/Headers/CMakeLists.txt (+1) - (added) clang/lib/Headers/endian.h (+62) - (added) clang/test/Headers/endian.c (+40) ``````````diff diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index 89e582564050b..c6c299bb61af3 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -3,6 +3,7 @@ # to platform specific lists below. set(core_files builtins.h + endian.h float.h __float_float.h __float_header_macro.h diff --git a/clang/lib/Headers/endian.h b/clang/lib/Headers/endian.h new file mode 100644 index 0000000000000..6225baf1127b1 --- /dev/null +++ b/clang/lib/Headers/endian.h @@ -0,0 +1,62 @@ +//===-- Definition of macros from endian.h --------------------------------===// +// +// 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 __CLANG_ENDIAN_H +#define __CLANG_ENDIAN_H + +// If the system has an endian.h, let's use that instead. +#if __STDC_HOSTED__ && __has_include_next(<endian.h>) +# include_next <endian.h> +#else + +#include <stdint.h> + +// Implementation taken from llvm libc endian-macros.h. +#ifdef __cplusplus +#define __CLANG_ENDIAN_CAST(cast, type, value) (cast<type>(value)) +#else +#define __CLANG_ENDIAN_CAST(cast, type, value) ((type)(value)) +#endif + +#define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ +#define BIG_ENDIAN __ORDER_BIG_ENDIAN__ +#define BYTE_ORDER __BYTE_ORDER__ + +#if BYTE_ORDER == LITTLE_ENDIAN + +#define htobe16(x) __builtin_bswap16((x)) +#define htobe32(x) __builtin_bswap32((x)) +#define htobe64(x) __builtin_bswap64((x)) +#define htole16(x) __CLANG_ENDIAN_CAST(static_cast, uint16_t, x) +#define htole32(x) __CLANG_ENDIAN_CAST(static_cast, uint32_t, x) +#define htole64(x) __CLANG_ENDIAN_CAST(static_cast, uint64_t, x) +#define be16toh(x) __builtin_bswap16((x)) +#define be32toh(x) __builtin_bswap32((x)) +#define be64toh(x) __builtin_bswap64((x)) +#define le16toh(x) __CLANG_ENDIAN_CAST(static_cast, uint16_t, x) +#define le32toh(x) __CLANG_ENDIAN_CAST(static_cast, uint32_t, x) +#define le64toh(x) __CLANG_ENDIAN_CAST(static_cast, uint64_t, x) + +#else + +#define htobe16(x) __CLANG_ENDIAN_CAST(static_cast, uint16_t, x) +#define htobe32(x) __CLANG_ENDIAN_CAST(static_cast, uint32_t, x) +#define htobe64(x) __CLANG_ENDIAN_CAST(static_cast, uint64_t, x) +#define htole16(x) __builtin_bswap16((x)) +#define htole32(x) __builtin_bswap32((x)) +#define htole64(x) __builtin_bswap64((x)) +#define be16toh(x) __CLANG_ENDIAN_CAST(static_cast, uint16_t, x) +#define be32toh(x) __CLANG_ENDIAN_CAST(static_cast, uint32_t, x) +#define be64toh(x) __CLANG_ENDIAN_CAST(static_cast, uint64_t, x) +#define le16toh(x) __builtin_bswap16((x)) +#define le32toh(x) __builtin_bswap32((x)) +#define le64toh(x) __builtin_bswap64((x)) + +#endif +#endif // __has_include_next +#endif // __CLANG_ENDIAN_H \ No newline at end of file diff --git a/clang/test/Headers/endian.c b/clang/test/Headers/endian.c new file mode 100644 index 0000000000000..c6fc4e82c6d8d --- /dev/null +++ b/clang/test/Headers/endian.c @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -triple powerpc64-unknown -fsyntax-only -verify -ffreestanding %s +// RUN: %clang_cc1 -triple ppc64le-unknown -fsyntax-only -verify -xc++ -ffreestanding %s +// expected-no-diagnostics + +#include <endian.h> + + +#if BYTE_ORDER == BIG_ENDIAN + +_Static_assert(htobe16(0xBEEF) == 0xBEEF, ""); +_Static_assert(htobe32(0xDEADBEEF) == 0xDEADBEEF, ""); +_Static_assert(htobe64(0xDEADBEEFDEADBEEF) == 0xDEADBEEFDEADBEEF, ""); +_Static_assert(htole16(0xBEEF) == 0xEFBE, ""); +_Static_assert(htole32(0xDEADBEEF) == 0xEFBEADDE, ""); +_Static_assert(htole64(0xDEADBEEFDEADBEEF) == 0xEFBEADDEEFBEADDE, ""); +_Static_assert(be16toh(0xBEEF) == 0xBEEF, ""); +_Static_assert(be32toh(0xDEADBEEF) == 0xDEADBEEF, ""); +_Static_assert(be64toh(0xDEADBEEFDEADBEEF) == 0xDEADBEEFDEADBEEF, ""); +_Static_assert(le16toh(0xBEEF) == 0xEFBE, ""); +_Static_assert(le32toh(0xDEADBEEF) == 0xEFBEADDE, ""); +_Static_assert(le64toh(0xDEADBEEFDEADBEEF) == 0xEFBEADDEEFBEADDE, ""); + +#elif BYTE_ORDER == LITTLE_ENDIAN + +_Static_assert(htobe16(0xBEEF) == 0xEFBE, ""); +_Static_assert(htobe32(0xDEADBEEF) == 0xEFBEADDE, ""); +_Static_assert(htobe64(0xDEADBEEFDEADBEEF) == 0xEFBEADDEEFBEADDE, ""); +_Static_assert(htole16(0xBEEF) == 0xBEEF, ""); +_Static_assert(htole32(0xDEADBEEF) == 0xDEADBEEF, ""); +_Static_assert(htole64(0xDEADBEEFDEADBEEF) == 0xDEADBEEFDEADBEEF, ""); +_Static_assert(be16toh(0xBEEF) == 0xEFBE, ""); +_Static_assert(be32toh(0xDEADBEEF) == 0xEFBEADDE, ""); +_Static_assert(be64toh(0xDEADBEEFDEADBEEF) == 0xEFBEADDEEFBEADDE, ""); +_Static_assert(le16toh(0xBEEF) == 0xBEEF, ""); +_Static_assert(le32toh(0xDEADBEEF) == 0xDEADBEEF, ""); +_Static_assert(le64toh(0xDEADBEEFDEADBEEF) == 0xDEADBEEFDEADBEEF, ""); + +#else +#error "Invalid byte order" +#endif `````````` </details> https://github.com/llvm/llvm-project/pull/186032 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
