[libc-commits] [libc] 4840895 - [libc] implement `memalignment` (#132493)

via libc-commits libc-commits at lists.llvm.org
Fri Mar 28 16:08:00 PDT 2025


Author: Mohamed Emad
Date: 2025-03-28T16:07:57-07:00
New Revision: 48408954670e1f564bd92eed6b54bf155238201c

URL: https://github.com/llvm/llvm-project/commit/48408954670e1f564bd92eed6b54bf155238201c
DIFF: https://github.com/llvm/llvm-project/commit/48408954670e1f564bd92eed6b54bf155238201c.diff

LOG: [libc] implement `memalignment` (#132493)

This patch adds the `memalignment` function to LLVM-libc, following its
description in [WG14 N3220,
ยง7.24.2.1](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#page=387).

- [x] Add the implementation of `memalignment` in
[`/src/stdlib`](https://github.com/llvm/llvm-project/tree/main/libc/src/stdlib)
- [x] Add tests for `memalignment` in
[`/test/src/stdlib`](https://github.com/llvm/llvm-project/tree/main/libc/test/src/stdlib)
- [x] Add `memalignment` to
[`entrypoints.txt`](https://github.com/llvm/llvm-project/blob/main/libc/config/linux/x86_64/entrypoints.txt)
for at least x86_64 and whatever you're building on
- [x] Add `memalignment` to
[`include/stdlib.yaml`](https://github.com/llvm/llvm-project/blob/main/libc/include/stdlib.yaml)




Closes #132300

---------

Co-authored-by: Joseph Huber <huberjn at outlook.com>

Added: 
    libc/src/stdlib/memalignment.cpp
    libc/src/stdlib/memalignment.h
    libc/test/src/stdlib/memalignment_test.cpp

Modified: 
    libc/config/baremetal/aarch64/entrypoints.txt
    libc/config/darwin/arm/entrypoints.txt
    libc/config/darwin/x86_64/entrypoints.txt
    libc/config/gpu/amdgpu/entrypoints.txt
    libc/config/gpu/nvptx/entrypoints.txt
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/arm/entrypoints.txt
    libc/config/linux/riscv/entrypoints.txt
    libc/config/linux/x86_64/entrypoints.txt
    libc/config/windows/entrypoints.txt
    libc/include/stdlib.yaml
    libc/src/stdlib/CMakeLists.txt
    libc/test/src/stdlib/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 8b51942d30fe8..9e9de9ed1569d 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -231,6 +231,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.llabs
     libc.src.stdlib.lldiv
     libc.src.stdlib.malloc
+    libc.src.stdlib.memalignment
     libc.src.stdlib.qsort
     libc.src.stdlib.rand
     libc.src.stdlib.realloc

diff  --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt
index 0170d18dceef7..38e585e43c776 100644
--- a/libc/config/darwin/arm/entrypoints.txt
+++ b/libc/config/darwin/arm/entrypoints.txt
@@ -82,6 +82,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.ldiv
     libc.src.stdlib.llabs
     libc.src.stdlib.lldiv
+    libc.src.stdlib.memalignment
     libc.src.stdlib.qsort
     libc.src.stdlib.rand
     libc.src.stdlib.srand

diff  --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index 19230cde47198..c55b6aa275690 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -78,6 +78,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.ldiv
     libc.src.stdlib.llabs
     libc.src.stdlib.lldiv
+    libc.src.stdlib.memalignment
     libc.src.stdlib.qsort
     libc.src.stdlib.strtod
     libc.src.stdlib.strtof

diff  --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index a5f8f82078f42..15c4b51cb2410 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -172,6 +172,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.ldiv
     libc.src.stdlib.llabs
     libc.src.stdlib.lldiv
+    libc.src.stdlib.memalignment
     libc.src.stdlib.qsort
     libc.src.stdlib.qsort_r
     libc.src.stdlib.rand

diff  --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index 7292ca3d6efca..36c5ce193a57c 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -172,6 +172,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.ldiv
     libc.src.stdlib.llabs
     libc.src.stdlib.lldiv
+    libc.src.stdlib.memalignment
     libc.src.stdlib.qsort
     libc.src.stdlib.qsort_r
     libc.src.stdlib.rand

diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index bca0b13feb1a0..27e4c7035165a 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -191,6 +191,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.ldiv
     libc.src.stdlib.llabs
     libc.src.stdlib.lldiv
+    libc.src.stdlib.memalignment
     libc.src.stdlib.qsort
     libc.src.stdlib.qsort_r
     libc.src.stdlib.rand

diff  --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 9b09cc583904c..05e8e9e308168 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -156,6 +156,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.ldiv
     libc.src.stdlib.llabs
     libc.src.stdlib.lldiv
+    libc.src.stdlib.memalignment
     libc.src.stdlib.qsort
     libc.src.stdlib.qsort_r
     libc.src.stdlib.strtod

diff  --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 9cf05ef6d5a61..b2329d30efb54 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -188,6 +188,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.ldiv
     libc.src.stdlib.llabs
     libc.src.stdlib.lldiv
+    libc.src.stdlib.memalignment
     libc.src.stdlib.qsort
     libc.src.stdlib.qsort_r
     libc.src.stdlib.rand

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index ac281e8d39066..5086315600ce6 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -193,6 +193,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.ldiv
     libc.src.stdlib.llabs
     libc.src.stdlib.lldiv
+    libc.src.stdlib.memalignment
     libc.src.stdlib.qsort
     libc.src.stdlib.qsort_r
     libc.src.stdlib.rand

diff  --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 319815e590425..8ec5760bef84e 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -79,6 +79,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.stdlib.ldiv
     libc.src.stdlib.llabs
     libc.src.stdlib.lldiv
+    libc.src.stdlib.memalignment
     libc.src.stdlib.qsort
     libc.src.stdlib.strtod
     libc.src.stdlib.strtof

diff  --git a/libc/include/stdlib.yaml b/libc/include/stdlib.yaml
index b308df98a6090..a6204ce3afee3 100644
--- a/libc/include/stdlib.yaml
+++ b/libc/include/stdlib.yaml
@@ -133,6 +133,12 @@ functions:
     arguments:
       - type: long long
       - type: long long
+  - name: memalignment
+    standards:
+      - stdc
+    return_type: size_t
+    arguments:
+      - type: const void *
   - name: posix_memalign
     standards:
       - posix

diff  --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index 63eb358717656..74ae864f72e23 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -345,6 +345,17 @@ add_entrypoint_object(
     .rand_util
 )
 
+add_entrypoint_object(
+  memalignment
+  SRCS
+    memalignment.cpp
+  HDRS
+    memalignment.h
+  DEPENDS
+    libc.src.__support.common
+    libc.hdr.types.size_t
+)
+
 if(NOT LIBC_TARGET_OS_IS_BAREMETAL AND NOT LIBC_TARGET_OS_IS_GPU)
   if(LLVM_LIBC_INCLUDE_SCUDO)
     set(SCUDO_DEPS "")

diff  --git a/libc/src/stdlib/memalignment.cpp b/libc/src/stdlib/memalignment.cpp
new file mode 100644
index 0000000000000..f06e7bf0f2d0d
--- /dev/null
+++ b/libc/src/stdlib/memalignment.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/stdlib/memalignment.h"
+#include "src/__support/CPP/bit.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(size_t, memalignment, (const void *p)) {
+  if (p == nullptr)
+    return 0;
+
+  uintptr_t addr = reinterpret_cast<uintptr_t>(p);
+
+  return size_t(1) << cpp::countr_zero(addr);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/stdlib/memalignment.h b/libc/src/stdlib/memalignment.h
new file mode 100644
index 0000000000000..b7c7430af8c8e
--- /dev/null
+++ b/libc/src/stdlib/memalignment.h
@@ -0,0 +1,21 @@
+//===-- 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 "hdr/types/size_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+size_t memalignment(const void *p);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDLIB_LDIV_H

diff  --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
index 90d7b7a55dbe6..302971a078c17 100644
--- a/libc/test/src/stdlib/CMakeLists.txt
+++ b/libc/test/src/stdlib/CMakeLists.txt
@@ -368,6 +368,17 @@ add_libc_test(
     libc.src.stdlib.srand
 )
 
+add_libc_test(
+  memalignment_test
+  SUITE
+    libc-stdlib-tests
+  SRCS
+    memalignment_test.cpp
+  DEPENDS
+    libc.include.stdlib
+    libc.src.stdlib.memalignment
+)
+
 if(LLVM_LIBC_FULL_BUILD)
 
   add_libc_test(

diff  --git a/libc/test/src/stdlib/memalignment_test.cpp b/libc/test/src/stdlib/memalignment_test.cpp
new file mode 100644
index 0000000000000..2ca1b79e69e36
--- /dev/null
+++ b/libc/test/src/stdlib/memalignment_test.cpp
@@ -0,0 +1,59 @@
+//===-- 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 "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, 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>(32));
+}
+
+TEST(LlvmLibcMemAlignmentTest, AlignasSpecifiedAlignment) {
+  alignas(16) static int aligned_16;
+  alignas(32) static int aligned_32;
+  alignas(64) static int aligned_64;
+  alignas(128) static int aligned_128;
+  alignas(256) static int aligned_256;
+
+  EXPECT_GE(LIBC_NAMESPACE::memalignment(&aligned_16), static_cast<size_t>(16));
+  EXPECT_GE(LIBC_NAMESPACE::memalignment(&aligned_32), static_cast<size_t>(32));
+  EXPECT_GE(LIBC_NAMESPACE::memalignment(&aligned_64), static_cast<size_t>(64));
+  EXPECT_GE(LIBC_NAMESPACE::memalignment(&aligned_128),
+            static_cast<size_t>(128));
+  EXPECT_GE(LIBC_NAMESPACE::memalignment(&aligned_256),
+            static_cast<size_t>(256));
+}


        


More information about the libc-commits mailing list