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

Reply via email to