Skip to content

Commit 4840895

Browse files
hulxvjhuber6
andauthored
[libc] implement memalignment (llvm#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 llvm#132300 --------- Co-authored-by: Joseph Huber <[email protected]>
1 parent 5bdce30 commit 4840895

File tree

16 files changed

+143
-0
lines changed

16 files changed

+143
-0
lines changed

libc/config/baremetal/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ set(TARGET_LIBC_ENTRYPOINTS
231231
libc.src.stdlib.llabs
232232
libc.src.stdlib.lldiv
233233
libc.src.stdlib.malloc
234+
libc.src.stdlib.memalignment
234235
libc.src.stdlib.qsort
235236
libc.src.stdlib.rand
236237
libc.src.stdlib.realloc

libc/config/darwin/arm/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ set(TARGET_LIBC_ENTRYPOINTS
8282
libc.src.stdlib.ldiv
8383
libc.src.stdlib.llabs
8484
libc.src.stdlib.lldiv
85+
libc.src.stdlib.memalignment
8586
libc.src.stdlib.qsort
8687
libc.src.stdlib.rand
8788
libc.src.stdlib.srand

libc/config/darwin/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ set(TARGET_LIBC_ENTRYPOINTS
7878
libc.src.stdlib.ldiv
7979
libc.src.stdlib.llabs
8080
libc.src.stdlib.lldiv
81+
libc.src.stdlib.memalignment
8182
libc.src.stdlib.qsort
8283
libc.src.stdlib.strtod
8384
libc.src.stdlib.strtof

libc/config/gpu/amdgpu/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ set(TARGET_LIBC_ENTRYPOINTS
172172
libc.src.stdlib.ldiv
173173
libc.src.stdlib.llabs
174174
libc.src.stdlib.lldiv
175+
libc.src.stdlib.memalignment
175176
libc.src.stdlib.qsort
176177
libc.src.stdlib.qsort_r
177178
libc.src.stdlib.rand

libc/config/gpu/nvptx/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ set(TARGET_LIBC_ENTRYPOINTS
172172
libc.src.stdlib.ldiv
173173
libc.src.stdlib.llabs
174174
libc.src.stdlib.lldiv
175+
libc.src.stdlib.memalignment
175176
libc.src.stdlib.qsort
176177
libc.src.stdlib.qsort_r
177178
libc.src.stdlib.rand

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ set(TARGET_LIBC_ENTRYPOINTS
191191
libc.src.stdlib.ldiv
192192
libc.src.stdlib.llabs
193193
libc.src.stdlib.lldiv
194+
libc.src.stdlib.memalignment
194195
libc.src.stdlib.qsort
195196
libc.src.stdlib.qsort_r
196197
libc.src.stdlib.rand

libc/config/linux/arm/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ set(TARGET_LIBC_ENTRYPOINTS
156156
libc.src.stdlib.ldiv
157157
libc.src.stdlib.llabs
158158
libc.src.stdlib.lldiv
159+
libc.src.stdlib.memalignment
159160
libc.src.stdlib.qsort
160161
libc.src.stdlib.qsort_r
161162
libc.src.stdlib.strtod

libc/config/linux/riscv/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ set(TARGET_LIBC_ENTRYPOINTS
188188
libc.src.stdlib.ldiv
189189
libc.src.stdlib.llabs
190190
libc.src.stdlib.lldiv
191+
libc.src.stdlib.memalignment
191192
libc.src.stdlib.qsort
192193
libc.src.stdlib.qsort_r
193194
libc.src.stdlib.rand

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ set(TARGET_LIBC_ENTRYPOINTS
193193
libc.src.stdlib.ldiv
194194
libc.src.stdlib.llabs
195195
libc.src.stdlib.lldiv
196+
libc.src.stdlib.memalignment
196197
libc.src.stdlib.qsort
197198
libc.src.stdlib.qsort_r
198199
libc.src.stdlib.rand

libc/config/windows/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ set(TARGET_LIBC_ENTRYPOINTS
7979
libc.src.stdlib.ldiv
8080
libc.src.stdlib.llabs
8181
libc.src.stdlib.lldiv
82+
libc.src.stdlib.memalignment
8283
libc.src.stdlib.qsort
8384
libc.src.stdlib.strtod
8485
libc.src.stdlib.strtof

libc/include/stdlib.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ functions:
133133
arguments:
134134
- type: long long
135135
- type: long long
136+
- name: memalignment
137+
standards:
138+
- stdc
139+
return_type: size_t
140+
arguments:
141+
- type: const void *
136142
- name: posix_memalign
137143
standards:
138144
- posix

libc/src/stdlib/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,17 @@ add_entrypoint_object(
345345
.rand_util
346346
)
347347

348+
add_entrypoint_object(
349+
memalignment
350+
SRCS
351+
memalignment.cpp
352+
HDRS
353+
memalignment.h
354+
DEPENDS
355+
libc.src.__support.common
356+
libc.hdr.types.size_t
357+
)
358+
348359
if(NOT LIBC_TARGET_OS_IS_BAREMETAL AND NOT LIBC_TARGET_OS_IS_GPU)
349360
if(LLVM_LIBC_INCLUDE_SCUDO)
350361
set(SCUDO_DEPS "")

libc/src/stdlib/memalignment.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//===-- Implementation for memalignment -------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/stdlib/memalignment.h"
10+
#include "src/__support/CPP/bit.h"
11+
#include "src/__support/common.h"
12+
#include "src/__support/macros/config.h"
13+
14+
namespace LIBC_NAMESPACE_DECL {
15+
16+
LLVM_LIBC_FUNCTION(size_t, memalignment, (const void *p)) {
17+
if (p == nullptr)
18+
return 0;
19+
20+
uintptr_t addr = reinterpret_cast<uintptr_t>(p);
21+
22+
return size_t(1) << cpp::countr_zero(addr);
23+
}
24+
25+
} // namespace LIBC_NAMESPACE_DECL

libc/src/stdlib/memalignment.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation header for memalignment ------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_STDLIB_MEM_ALIGNMENT_H
10+
#define LLVM_LIBC_SRC_STDLIB_MEM_ALIGNMENT_H
11+
12+
#include "hdr/types/size_t.h"
13+
#include "src/__support/macros/config.h"
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
size_t memalignment(const void *p);
18+
19+
} // namespace LIBC_NAMESPACE_DECL
20+
21+
#endif // LLVM_LIBC_SRC_STDLIB_LDIV_H

libc/test/src/stdlib/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,17 @@ add_libc_test(
368368
libc.src.stdlib.srand
369369
)
370370

371+
add_libc_test(
372+
memalignment_test
373+
SUITE
374+
libc-stdlib-tests
375+
SRCS
376+
memalignment_test.cpp
377+
DEPENDS
378+
libc.include.stdlib
379+
libc.src.stdlib.memalignment
380+
)
381+
371382
if(LLVM_LIBC_FULL_BUILD)
372383

373384
add_libc_test(
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//===-- Unittests for memalignment ----------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/stdlib/memalignment.h"
10+
#include "test/UnitTest/Test.h"
11+
12+
#include <stdint.h>
13+
14+
TEST(LlvmLibcMemAlignmentTest, NullPointer) {
15+
void *ptr = nullptr;
16+
EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr), static_cast<size_t>(0));
17+
}
18+
19+
TEST(LlvmLibcMemAlignmentTest, SpecificAlignment) {
20+
21+
// These addresses have known alignment patterns - if we can construct them
22+
uintptr_t addr_align2 = 0x2; // 2-byte aligned
23+
uintptr_t addr_align4 = 0x4; // 4-byte aligned
24+
uintptr_t addr_align8 = 0x8; // 8-byte aligned
25+
uintptr_t addr_align16 = 0x10; // 16-byte aligned
26+
uintptr_t addr_align32 = 0x20; // 32-byte aligned
27+
28+
void *ptr_align2 = reinterpret_cast<void *>(addr_align2);
29+
void *ptr_align4 = reinterpret_cast<void *>(addr_align4);
30+
void *ptr_align8 = reinterpret_cast<void *>(addr_align8);
31+
void *ptr_align16 = reinterpret_cast<void *>(addr_align16);
32+
void *ptr_align32 = reinterpret_cast<void *>(addr_align32);
33+
34+
EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr_align2), static_cast<size_t>(2));
35+
EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr_align4), static_cast<size_t>(4));
36+
EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr_align8), static_cast<size_t>(8));
37+
EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr_align16), static_cast<size_t>(16));
38+
EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr_align32), static_cast<size_t>(32));
39+
40+
uintptr_t addr_complex = 0x1234560; // 16-byte aligned (ends in 0)
41+
void *ptr_complex = reinterpret_cast<void *>(addr_complex);
42+
EXPECT_EQ(LIBC_NAMESPACE::memalignment(ptr_complex), static_cast<size_t>(32));
43+
}
44+
45+
TEST(LlvmLibcMemAlignmentTest, AlignasSpecifiedAlignment) {
46+
alignas(16) static int aligned_16;
47+
alignas(32) static int aligned_32;
48+
alignas(64) static int aligned_64;
49+
alignas(128) static int aligned_128;
50+
alignas(256) static int aligned_256;
51+
52+
EXPECT_GE(LIBC_NAMESPACE::memalignment(&aligned_16), static_cast<size_t>(16));
53+
EXPECT_GE(LIBC_NAMESPACE::memalignment(&aligned_32), static_cast<size_t>(32));
54+
EXPECT_GE(LIBC_NAMESPACE::memalignment(&aligned_64), static_cast<size_t>(64));
55+
EXPECT_GE(LIBC_NAMESPACE::memalignment(&aligned_128),
56+
static_cast<size_t>(128));
57+
EXPECT_GE(LIBC_NAMESPACE::memalignment(&aligned_256),
58+
static_cast<size_t>(256));
59+
}

0 commit comments

Comments
 (0)