[libc-commits] [libc] [libc] implement `memalignment` (PR #132493)
Mohamed Emad via libc-commits
libc-commits at lists.llvm.org
Fri Mar 21 16:48:25 PDT 2025
https://github.com/hulxv updated https://github.com/llvm/llvm-project/pull/132493
>From 152894ee1076d18efed7730bed774e0f2b5aa9f9 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 22 Mar 2025 01:33:30 +0200
Subject: [PATCH 1/3] [libc] implement `memalignment`
---
libc/src/stdlib/memalignment.c | 19 +++++++++++++++++++
libc/src/stdlib/memalignment.h | 22 ++++++++++++++++++++++
2 files changed, 41 insertions(+)
create mode 100644 libc/src/stdlib/memalignment.c
create mode 100644 libc/src/stdlib/memalignment.h
diff --git a/libc/src/stdlib/memalignment.c b/libc/src/stdlib/memalignment.c
new file mode 100644
index 0000000000000..bf182f16ea138
--- /dev/null
+++ b/libc/src/stdlib/memalignment.c
@@ -0,0 +1,19 @@
+#include "src/stdlib/memalignment.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(size_t, memalignment, (const void *p)) {
+ if (p == NULL) {
+ return 0;
+ }
+
+ uintptr_t addr = (uintptr_t)p;
+
+ // Find the rightmost set bit, which represents the maximum alignment
+ // The alignment is a power of two, so we need to find the largest
+ // power of two that divides the address
+ return addr & (~addr + 1);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdlib/memalignment.h b/libc/src/stdlib/memalignment.h
new file mode 100644
index 0000000000000..8ed900122a153
--- /dev/null
+++ b/libc/src/stdlib/memalignment.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for memalignment --------------------------*- C++ -*-===//
+//
+// 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_STDLIB_MEM_ALIGNMENT_H
+#define LLVM_LIBC_SRC_STDLIB_MEM_ALIGNMENT_H
+
+#include "src/__support/macros/config.h"
+#include <stddef.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+size_t memalignment(const void* p);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDLIB_LDIV_H
+
>From 000e4e2a874dcd5faeb2df5f6544b02bd9215b10 Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 22 Mar 2025 01:44:12 +0200
Subject: [PATCH 2/3] chore: fix formatting of `memalignment.h`
---
libc/src/stdlib/memalignment.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libc/src/stdlib/memalignment.h b/libc/src/stdlib/memalignment.h
index 8ed900122a153..b50aa02d5050e 100644
--- a/libc/src/stdlib/memalignment.h
+++ b/libc/src/stdlib/memalignment.h
@@ -1,4 +1,5 @@
-//===-- Implementation header for memalignment --------------------------*- C++ -*-===//
+//===-- Implementation header for memalignment --------------------------*- C++
+//-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -14,9 +15,8 @@
namespace LIBC_NAMESPACE_DECL {
-size_t memalignment(const void* p);
+size_t memalignment(const void *p);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_STDLIB_LDIV_H
-
>From 845184e4b21c3d52f7c127b2aa6d7688cc29745e Mon Sep 17 00:00:00 2001
From: hulxv <hulxxv at gmail.com>
Date: Sat, 22 Mar 2025 01:47:15 +0200
Subject: [PATCH 3/3] test: adding tests for `memalignment`
---
libc/test/src/stdlib/CMakeLists.txt | 12 ++++
libc/test/src/stdlib/memalignment_test.cpp | 67 ++++++++++++++++++++++
2 files changed, 79 insertions(+)
create mode 100644 libc/test/src/stdlib/memalignment_test.cpp
diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
index 90d7b7a55dbe6..93324a836f555 100644
--- a/libc/test/src/stdlib/CMakeLists.txt
+++ b/libc/test/src/stdlib/CMakeLists.txt
@@ -457,4 +457,16 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.stdlib.free
)
endif()
+ add_libc_test(
+ memalignment_test
+ # The EXPECT_EXITS test is only availible for unit tests.
+ UNIT_TEST_ONLY
+ SUITE
+ libc-stdlib-tests
+ SRCS
+ memalignment_test.cpp
+ DEPENDS
+ libc.include.stdlib
+ libc.src.stdlib.memalignment
+ )
endif()
diff --git a/libc/test/src/stdlib/memalignment_test.cpp b/libc/test/src/stdlib/memalignment_test.cpp
new file mode 100644
index 0000000000000..d0405a4cb5e11
--- /dev/null
+++ b/libc/test/src/stdlib/memalignment_test.cpp
@@ -0,0 +1,67 @@
+//===-- Unittests for memalignment ---------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/memalignment.h"
+#include "src/stdlib/malloc.h"
+#include "src/stdlib/free.h"
+#include "test/UnitTest/Test.h"
+
+#include <stdint.h>
+
+TEST(LlvmLibcMemAlignmentTest, NullPointer) {
+ void *ptr = nullptr;
+ EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr), static_cast<size_t>(0));
+}
+
+TEST(LlvmLibcMemAlignmentTest, MallocedPointers) {
+ int *int_ptr = reinterpret_cast<int *>(LIBC_NAMESPACE::malloc(sizeof(int)));
+ EXPECT_NE(reinterpret_cast<void *>(int_ptr), static_cast<void *>(nullptr));
+
+ size_t int_alignment = LIBC_NAMESPACE::memalignment(int_ptr);
+ EXPECT_GE(int_alignment, alignof(int));
+
+
+ LIBC_NAMESPACE::free(int_ptr);
+
+ // Allocate a double (typically 8-byte aligned)
+ double *double_ptr = reinterpret_cast<double *>(LIBC_NAMESPACE::malloc(sizeof(double)));
+ EXPECT_NE(reinterpret_cast<void *>(double_ptr), static_cast<void *>(nullptr));
+
+ size_t double_alignment = LIBC_NAMESPACE::memalignment(double_ptr);
+ EXPECT_GE(double_alignment, alignof(double));
+
+ EXPECT_EQ(double_alignment & (double_alignment - 1), static_cast<size_t>(0));
+
+ LIBC_NAMESPACE::free(double_ptr);
+}
+
+TEST(LlvmLibcMemAlignmentTest, SpecificAlignment) {
+
+ // These addresses have known alignment patterns - if we can construct them
+ uintptr_t addr_align2 = 0x2; // 2-byte aligned
+ uintptr_t addr_align4 = 0x4; // 4-byte aligned
+ uintptr_t addr_align8 = 0x8; // 8-byte aligned
+ uintptr_t addr_align16 = 0x10; // 16-byte aligned
+ uintptr_t addr_align32 = 0x20; // 32-byte aligned
+
+ void *ptr_align2 = reinterpret_cast<void *>(addr_align2);
+ void *ptr_align4 = reinterpret_cast<void *>(addr_align4);
+ void *ptr_align8 = reinterpret_cast<void *>(addr_align8);
+ void *ptr_align16 = reinterpret_cast<void *>(addr_align16);
+ void *ptr_align32 = reinterpret_cast<void *>(addr_align32);
+
+ EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr_align2), static_cast<size_t>(2));
+ EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr_align4), static_cast<size_t>(4));
+ EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr_align8), static_cast<size_t>(8));
+ EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr_align16), static_cast<size_t>(16));
+ EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr_align32), static_cast<size_t>(32));
+
+ uintptr_t addr_complex = 0x1234560; // 16-byte aligned (ends in 0)
+ void *ptr_complex = reinterpret_cast<void *>(addr_complex);
+ EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr_complex), static_cast<size_t>(16));
+}
\ No newline at end of file
More information about the libc-commits
mailing list