https://github.com/daltenty created 
https://github.com/llvm/llvm-project/pull/186032

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.

>From 7701606ef879fd6283e097a0171b505edfa7887b Mon Sep 17 00:00:00 2001
From: David Tenty <[email protected]>
Date: Wed, 11 Mar 2026 12:02:23 -0400
Subject: [PATCH] [clang][Headers] add endian.h

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.
---
 clang/lib/Headers/CMakeLists.txt |  1 +
 clang/lib/Headers/endian.h       | 62 ++++++++++++++++++++++++++++++++
 clang/test/Headers/endian.c      | 40 +++++++++++++++++++++
 3 files changed, 103 insertions(+)
 create mode 100644 clang/lib/Headers/endian.h
 create mode 100644 clang/test/Headers/endian.c

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

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to