127 changes: 127 additions & 0 deletions libc/src/unistd/linux/pathconf_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
//===-- Linux implementation of pathconf_utils ----------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// This header must go before limits_macros.h otherwise libc header may choose
// to undefine LINK_MAX.
#include <linux/limits.h> // For LINK_MAX and other limits

#include "hdr/limits_macros.h"
#include "hdr/unistd_macros.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/errno/libc_errno.h"
#include "src/sys/statvfs/linux/statfs_utils.h"

// other linux specific includes
#include <linux/bfs_fs.h>
#if __has_include(<linux/ufs_fs.h>)
#include <linux/ufs_fs.h>
#else
// from https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/
#define UFS_MAGIC 0x00011954
#endif
#include <linux/magic.h> // For common FS magics

namespace LIBC_NAMESPACE {

long filesizebits(const statfs_utils::LinuxStatFs &s) {
switch (s.f_type) {
case JFFS2_SUPER_MAGIC:
case MSDOS_SUPER_MAGIC:
case NCP_SUPER_MAGIC:
return 32;
}
return 64;
}

long link_max(const statfs_utils::LinuxStatFs &s) {
switch (s.f_type) {
case EXT2_SUPER_MAGIC:
return 32000;
case MINIX_SUPER_MAGIC:
return 250;
case MINIX2_SUPER_MAGIC:
return 65530;
case REISERFS_SUPER_MAGIC:
return 0xffff - 1000;
case UFS_MAGIC:
return 32000;
}
return LINK_MAX;
}

long symlinks(const statfs_utils::LinuxStatFs &s) {
switch (s.f_type) {
case ADFS_SUPER_MAGIC:
case BFS_MAGIC:
case CRAMFS_MAGIC:
case EFS_SUPER_MAGIC:
case MSDOS_SUPER_MAGIC:
case QNX4_SUPER_MAGIC:
return 0;
}
return 1;
}

long pathconfig(const statfs_utils::LinuxStatFs &s, int name) {
switch (name) {
case _PC_LINK_MAX:
return link_max(s);

case _PC_FILESIZEBITS:
return filesizebits(s);

case _PC_2_SYMLINKS:
return symlinks(s);

case _PC_REC_MIN_XFER_SIZE:
return s.f_bsize;

case _PC_ALLOC_SIZE_MIN:
case _PC_REC_XFER_ALIGN:
return s.f_frsize;

case _PC_MAX_CANON:
return _POSIX_MAX_CANON;

case _PC_MAX_INPUT:
return _POSIX_MAX_INPUT;

case _PC_NAME_MAX:
return s.f_namelen;

case _PC_PATH_MAX:
return _POSIX_PATH_MAX;

case _PC_PIPE_BUF:
return _POSIX_PIPE_BUF;

case _PC_CHOWN_RESTRICTED:
return _POSIX_CHOWN_RESTRICTED;

case _PC_NO_TRUNC:
return _POSIX_NO_TRUNC;

case _PC_VDISABLE:
return _POSIX_VDISABLE;

case _PC_ASYNC_IO:
case _PC_PRIO_IO:
case _PC_REC_INCR_XFER_SIZE:
case _PC_REC_MAX_XFER_SIZE:
case _PC_SYMLINK_MAX:
case _PC_SYNC_IO:
return -1;

default:
libc_errno = EINVAL;
return -1;
}
}

} // namespace LIBC_NAMESPACE
20 changes: 20 additions & 0 deletions libc/src/unistd/linux/pathconf_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for pathconf_utils ----------------*- 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_UNISTD_PATHCONF_UTILS_H
#define LLVM_LIBC_SRC_UNISTD_PATHCONF_UTILS_H

#include "src/sys/statvfs/linux/statfs_utils.h"

namespace LIBC_NAMESPACE {

long pathconfig(const statfs_utils::LinuxStatFs &s, int name);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_UNISTD_PREAD_H
18 changes: 18 additions & 0 deletions libc/src/unistd/pathconf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for pathconf ----------------------*- 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_UNISTD_PATHCONF_H
#define LLVM_LIBC_SRC_UNISTD_PATHCONF_H

namespace LIBC_NAMESPACE {

long pathconf(const char *path, int name);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_UNISTD_PREAD_H
13 changes: 12 additions & 1 deletion libc/startup/linux/aarch64/tls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,18 @@ void cleanup_tls(uintptr_t addr, uintptr_t size) {
}

bool set_thread_ptr(uintptr_t val) {
__arm_wsr64("tpidr_el0", val);
// The PR for __arm_wsr64 support in GCC was merged on Dec 6, 2023, and it is
// not yet usable in 13.3.0
// https://github.com/gcc-mirror/gcc/commit/fc42900d21abd5eacb7537c3c8ffc5278d510195
#if __has_builtin(__builtin_arm_wsr64)
__builtin_arm_wsr64("tpidr_el0", val);
#elif __has_builtin(__builtin_aarch64_wsr)
__builtin_aarch64_wsr("tpidr_el0", val);
#elif defined(__GNUC__)
asm volatile("msr tpidr_el0, %0" ::"r"(val));
#else
#error "Unsupported compiler"
#endif
return true;
}
} // namespace LIBC_NAMESPACE
16 changes: 16 additions & 0 deletions libc/test/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)

add_fp_unittest(
cospif_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
cospif_test.cpp
HDRS
sdcomp26094.h
DEPENDS
libc.src.errno.errno
libc.src.math.cospif
libc.src.__support.CPP.array
libc.src.__support.FPUtil.fp_bits
)

add_fp_unittest(
sinf_test
NEED_MPFR
Expand Down
120 changes: 120 additions & 0 deletions libc/test/src/math/cospif_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//===-- Unittests for cospif ----------------------------------------------===//
//
// 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/errno/libc_errno.h"
#include "src/math/cospif.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/src/math/sdcomp26094.h"
#include "utils/MPFRWrapper/MPFRUtils.h"

using LlvmLibcCospifTest = LIBC_NAMESPACE::testing::FPTest<float>;

using LIBC_NAMESPACE::testing::SDCOMP26094_VALUES;

namespace mpfr = LIBC_NAMESPACE::testing::mpfr;

TEST_F(LlvmLibcCospifTest, SpecialNumbers) {
LIBC_NAMESPACE::libc_errno = 0;

EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(aNaN));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::cospif(0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::cospif(-0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(inf));
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(neg_inf));
EXPECT_MATH_ERRNO(EDOM);
}

TEST_F(LlvmLibcCospifTest, SpecificBitPatterns) {
constexpr int N = 36;
constexpr uint32_t INPUTS[N] = {
0x3f06'0a92U, // x = pi/6
0x3f3a'dc51U, // x = 0x1.75b8a2p-1f
0x3f49'0fdbU, // x = pi/4
0x3f86'0a92U, // x = pi/3
0x3fa7'832aU, // x = 0x1.4f0654p+0f
0x3fc9'0fdbU, // x = pi/2
0x4017'1973U, // x = 0x1.2e32e6p+1f
0x4049'0fdbU, // x = pi
0x4096'cbe4U, // x = 0x1.2d97c8p+2f
0x40c9'0fdbU, // x = 2*pi
0x433b'7490U, // x = 0x1.76e92p+7f
0x437c'e5f1U, // x = 0x1.f9cbe2p+7f
0x4619'9998U, // x = 0x1.33333p+13f
0x474d'246fU, // x = 0x1.9a48dep+15f
0x4afd'ece4U, // x = 0x1.fbd9c8p+22f
0x4c23'32e9U, // x = 0x1.4665d2p+25f
0x50a3'e87fU, // x = 0x1.47d0fep+34f
0x5239'47f6U, // x = 0x1.728fecp+37f
0x53b1'46a6U, // x = 0x1.628d4cp+40f
0x55ca'fb2aU, // x = 0x1.95f654p+44f
0x588e'f060U, // x = 0x1.1de0cp+50f
0x5c07'bcd0U, // x = 0x1.0f79ap+57f
0x5ebc'fddeU, // x = 0x1.79fbbcp+62f
0x5fa6'eba7U, // x = 0x1.4dd74ep+64f
0x61a4'0b40U, // x = 0x1.48168p+68f
0x6386'134eU, // x = 0x1.0c269cp+72f
0x6589'8498U, // x = 0x1.13093p+76f
0x6600'0001U, // x = 0x1.000002p+77f
0x664e'46e4U, // x = 0x1.9c8dc8p+77f
0x66b0'14aaU, // x = 0x1.602954p+78f
0x67a9'242bU, // x = 0x1.524856p+80f
0x6a19'76f1U, // x = 0x1.32ede2p+85f
0x6c55'da58U, // x = 0x1.abb4bp+89f
0x6f79'be45U, // x = 0x1.f37c8ap+95f
0x7276'69d4U, // x = 0x1.ecd3a8p+101f
0x7758'4625U, // x = 0x1.b08c4ap+111f
};

for (int i = 0; i < N; ++i) {
float x = FPBits(INPUTS[i]).get_val();
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cospi, x,
LIBC_NAMESPACE::cospif(x), 0.5);
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cospi, -x,
LIBC_NAMESPACE::cospif(-x), 0.5);
}
}

// For small values, sinpi(x) is pi * x.
TEST_F(LlvmLibcCospifTest, SmallValues) {
float x = FPBits(0x1780'0000U).get_val();
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cospi, x,
LIBC_NAMESPACE::cospif(x), 0.5);

x = FPBits(0x0040'0000U).get_val();
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cospi, x,
LIBC_NAMESPACE::cospif(x), 0.5);
}

// SDCOMP-26094: check sinfpi in the cases for which the range reducer
// returns values furthest beyond its nominal upper bound of pi/4.
TEST_F(LlvmLibcCospifTest, SDCOMP_26094) {
for (uint32_t v : SDCOMP26094_VALUES) {
float x = FPBits((v)).get_val();
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Cospi, x,
LIBC_NAMESPACE::cospif(x), 0.5);
}
}

// sinpi(-n) = -0.0
// sinpi(+n) = +0.0
TEST_F(LlvmLibcCospifTest, SignedZeros) {
EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::cospif(100.5f));
EXPECT_FP_EQ(-0.0, LIBC_NAMESPACE::cospif(-100.5f));
EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::cospif(45678.5f));
EXPECT_FP_EQ(-0.0, LIBC_NAMESPACE::cospif(-45678.5f));
EXPECT_FP_EQ(0.0, LIBC_NAMESPACE::cospif(8000000.5f));
EXPECT_FP_EQ(-0.0, LIBC_NAMESPACE::cospif(-8000000.5f));
}
16 changes: 16 additions & 0 deletions libc/test/src/math/exhaustive/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,22 @@ add_fp_unittest(
-lpthread
)

add_fp_unittest(
cospif_test
NO_RUN_POSTBUILD
NEED_MPFR
SUITE
libc_math_exhaustive_tests
SRCS
cospif_test.cpp
DEPENDS
.exhaustive_test
libc.src.math.cospif
libc.src.__support.FPUtil.fp_bits
LINK_LIBRARIES
-lpthread
)

add_fp_unittest(
sincosf_test
NO_RUN_POSTBUILD
Expand Down
33 changes: 33 additions & 0 deletions libc/test/src/math/exhaustive/cospif_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===-- Exhaustive test for cospif ----------------------------------------===//
//
// 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 "exhaustive_test.h"
#include "src/math/cospif.h"
#include "utils/MPFRWrapper/MPFRUtils.h"

namespace mpfr = LIBC_NAMESPACE::testing::mpfr;

using LlvmLibcCospifExhaustiveTest =
LlvmLibcUnaryOpExhaustiveMathTest<float, mpfr::Operation::Cospi,
LIBC_NAMESPACE::cospif>;

static constexpr uint32_t POS_START = 0x0000'0000U;
static constexpr uint32_t POS_STOP = 0x7f80'0000U;

// Range: [0, Inf]
TEST_F(LlvmLibcCospifExhaustiveTest, PostiveRange) {
test_full_range_all_roundings(POS_START, POS_STOP);
}

// Range: [-Inf, 0]
static constexpr uint32_t NEG_START = 0xb000'0000U;
static constexpr uint32_t NEG_STOP = 0xff80'0000U;

TEST_F(LlvmLibcCospifExhaustiveTest, NegativeRange) {
test_full_range_all_roundings(NEG_START, NEG_STOP);
}
11 changes: 11 additions & 0 deletions libc/test/src/math/smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ add_fp_unittest(
DEPENDS
libc.src.errno.errno
libc.src.math.cosf
)

add_fp_unittest(
cospif_test
SUITE
libc-math-smoke-tests
SRCS
cospif_test.cpp
DEPENDS
libc.src.errno.errno
libc.src.math.cospif
libc.src.__support.CPP.array
libc.src.__support.FPUtil.fp_bits
)
Expand Down
34 changes: 34 additions & 0 deletions libc/test/src/math/smoke/cospif_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===-- Unittests for cospif ----------------------------------------------===//
//
// 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/errno/libc_errno.h"
#include "src/math/cospif.h"
#include "test/UnitTest/FPMatcher.h"

#include <stdint.h>

using LlvmLibcCospifTest = LIBC_NAMESPACE::testing::FPTest<float>;

TEST_F(LlvmLibcCospifTest, SpecialNumbers) {
LIBC_NAMESPACE::libc_errno = 0;

EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(aNaN));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::cospif(0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ(1.0f, LIBC_NAMESPACE::cospif(-0.0f));
EXPECT_MATH_ERRNO(0);

EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(inf));
EXPECT_MATH_ERRNO(EDOM);

EXPECT_FP_EQ(aNaN, LIBC_NAMESPACE::cospif(neg_inf));
EXPECT_MATH_ERRNO(EDOM);
}
30 changes: 30 additions & 0 deletions libc/test/src/unistd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,36 @@ add_libc_unittest(
libc.src.unistd.sysconf
)

add_libc_unittest(
fpathconf_test
SUITE
libc_unistd_unittests
SRCS
fpathconf_test.cpp
DEPENDS
libc.hdr.limits_macros
libc.hdr.unistd_macros
libc.hdr.sys_stat_macros
libc.src.unistd.fpathconf
libc.src.fcntl.open
libc.src.unistd.close
)

add_libc_unittest(
pathconf_test
SUITE
libc_unistd_unittests
SRCS
pathconf_test.cpp
DEPENDS
libc.hdr.limits_macros
libc.hdr.unistd_macros
libc.hdr.sys_stat_macros
libc.src.unistd.pathconf
libc.src.fcntl.open
libc.src.unistd.close
)

add_libc_test(
getopt_test
HERMETIC_TEST_ONLY # Uses libc's own stderr
Expand Down
30 changes: 30 additions & 0 deletions libc/test/src/unistd/fpathconf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===-- Unittests for fpathconf -------------------------------------------===//
//
// 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 "hdr/fcntl_macros.h"
#include "hdr/limits_macros.h"
#include "hdr/sys_stat_macros.h"
#include "hdr/unistd_macros.h"
#include "src/fcntl/open.h"
#include "src/unistd/close.h"
#include "src/unistd/fpathconf.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"

using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;

TEST(LlvmLibcPipeTest, SmokeTest) {
constexpr const char *FILENAME = "fpathconf.test";
auto TEST_FILE = libc_make_test_file_path(FILENAME);
int fd = LIBC_NAMESPACE::open(TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
EXPECT_EQ(LIBC_NAMESPACE::fpathconf(fd, _PC_SYNC_IO), -1l);
EXPECT_EQ(LIBC_NAMESPACE::fpathconf(fd, _PC_PATH_MAX),
static_cast<long>(_POSIX_PATH_MAX));
LIBC_NAMESPACE::close(fd);
}

// TODO: Functionality tests
30 changes: 30 additions & 0 deletions libc/test/src/unistd/pathconf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===-- Unittests for pathconf --------------------------------------------===//
//
// 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 "hdr/fcntl_macros.h"
#include "hdr/limits_macros.h"
#include "hdr/sys_stat_macros.h"
#include "hdr/unistd_macros.h"
#include "src/fcntl/open.h"
#include "src/unistd/close.h"
#include "src/unistd/pathconf.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"

using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;

TEST(LlvmLibcPipeTest, SmokeTest) {
constexpr const char *FILENAME = "pathconf.test";
auto TEST_FILE = libc_make_test_file_path(FILENAME);
int fd = LIBC_NAMESPACE::open(TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
EXPECT_EQ(LIBC_NAMESPACE::pathconf(FILENAME, _PC_SYNC_IO), -1l);
EXPECT_EQ(LIBC_NAMESPACE::pathconf(FILENAME, _PC_PATH_MAX),
static_cast<long>(_POSIX_PATH_MAX));
LIBC_NAMESPACE::close(fd);
}

// TODO: Functionality tests
4 changes: 2 additions & 2 deletions libc/test/src/unistd/readlink_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ namespace cpp = LIBC_NAMESPACE::cpp;

TEST(LlvmLibcReadlinkTest, CreateAndUnlink) {
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
constexpr const char *FILENAME = "readlink_test_value";
constexpr const char *FILENAME = "readlink_test_file";
auto LINK_VAL = libc_make_test_file_path(FILENAME);
constexpr const char *FILENAME2 = "readlink.test.link";
constexpr const char *FILENAME2 = "readlink_test_file.link";
auto LINK = libc_make_test_file_path(FILENAME2);
LIBC_NAMESPACE::libc_errno = 0;

Expand Down
4 changes: 2 additions & 2 deletions libc/test/src/unistd/readlinkat_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ namespace cpp = LIBC_NAMESPACE::cpp;

TEST(LlvmLibcReadlinkatTest, CreateAndUnlink) {
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
constexpr const char *FILENAME = "readlinkat_test_value";
constexpr const char *FILENAME = "readlinkat_test_file";
auto LINK_VAL = libc_make_test_file_path(FILENAME);
constexpr const char *FILENAME2 = "readlinkat.test.link";
constexpr const char *FILENAME2 = "readlinkat_test_file.link";
auto LINK = libc_make_test_file_path(FILENAME2);
LIBC_NAMESPACE::libc_errno = 0;

Expand Down
4 changes: 3 additions & 1 deletion libc/utils/HdrGen/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
include(TableGen)

set(LLVM_LINK_COMPONENTS Support)
if (NOT LLVM_LINK_LLVM_DYLIB)
set(LLVM_LINK_COMPONENTS Support)
endif()

add_tablegen(libc-hdrgen LIBC
Command.h
Expand Down
8 changes: 6 additions & 2 deletions libc/utils/LibcTableGenUtil/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
if (NOT LLVM_LINK_LLVM_DYLIB)
set(flags "DISABLE_LLVM_LINK_LLVM_DYLIB;LINK_COMPONENTS;Support;TableGen")
else()
set(flags "LINK_COMPONENTS;TableGen")
endif()
add_llvm_library(
LibcTableGenUtil
APIIndexer.cpp
APIIndexer.h
DISABLE_LLVM_LINK_LLVM_DYLIB
LINK_COMPONENTS Support TableGen
${flags}
)
target_include_directories(LibcTableGenUtil PUBLIC ${LIBC_SOURCE_DIR})
target_include_directories(LibcTableGenUtil PRIVATE ${LLVM_INCLUDE_DIR} ${LLVM_MAIN_INCLUDE_DIR})
35 changes: 35 additions & 0 deletions libc/utils/MPFRWrapper/MPFRUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,39 @@ class MPFRNumber {
return result;
}

MPFRNumber cospi() const {
MPFRNumber result(*this);

#if MPFR_VERSION_MAJOR > 4 || \
(MPFR_VERSION_MAJOR == 4 && MPFR_VERSION_MINOR >= 2)
mpfr_cospi(result.value, value, mpfr_rounding);
return result;
#else
MPFRNumber value_frac(*this);
mpfr_frac(value_frac.value, value, MPFR_RNDN);

if (mpfr_cmp_si(value_frac.value, 0.0) == 0) {
mpz_t integer_part;
mpz_init(integer_part);
mpfr_get_z(integer_part, value, MPFR_RNDN);

if (mpz_tstbit(integer_part, 0)) {
mpfr_set_si(result.value, -1.0, MPFR_RNDN); // odd
} else {
mpfr_set_si(result.value, 1.0, MPFR_RNDN); // even
}
return result;
}

MPFRNumber value_pi(0.0, 1280);
mpfr_const_pi(value_pi.value, MPFR_RNDN);
mpfr_mul(value_pi.value, value_pi.value, value, MPFR_RNDN);
mpfr_cos(result.value, value_pi.value, mpfr_rounding);

return result;
#endif
}

MPFRNumber erf() const {
MPFRNumber result(*this);
mpfr_erf(result.value, value, mpfr_rounding);
Expand Down Expand Up @@ -675,6 +708,8 @@ unary_operation(Operation op, InputType input, unsigned int precision,
return mpfrInput.cos();
case Operation::Cosh:
return mpfrInput.cosh();
case Operation::Cospi:
return mpfrInput.cospi();
case Operation::Erf:
return mpfrInput.erf();
case Operation::Exp:
Expand Down
1 change: 1 addition & 0 deletions libc/utils/MPFRWrapper/MPFRUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ enum class Operation : int {
Ceil,
Cos,
Cosh,
Cospi,
Erf,
Exp,
Exp2,
Expand Down
4 changes: 2 additions & 2 deletions libcxx/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ iOS, watchOS, and tvOS, Google Search, the Android operating system, and FreeBSD
user base of over 1 billion daily active users.

Since its inception, libc++ has focused on delivering high performance, standards-conformance, and portability. It has
been extensively tested and optimized, making it robust and production ready. libc++ fully implements C++11 and C++14,
been extensively tested and optimized, making it robust and production ready. libc++ fully implements C++11 and C++14,
with C++17, C++20, C++23, and C++26 features being actively developed and making steady progress.

libc++ is continuously integrated and tested on a wide range of platforms and configurations, ensuring its reliability
Expand Down Expand Up @@ -137,7 +137,7 @@ Compiler Versions Restrictions Support policy
Clang 17, 18, 19-git latest two stable releases per `LLVM's release page <https://releases.llvm.org>`_ and the development version
AppleClang 15 latest stable release per `Xcode's release page <https://developer.apple.com/documentation/xcode-release-notes>`_
Open XL 17.1 (AIX) latest stable release per `Open XL's documentation page <https://www.ibm.com/docs/en/openxl-c-and-cpp-aix>`_
GCC 13 In C++11 or later only latest stable release per `GCC's release page <https://gcc.gnu.org/releases.html>`_
GCC 14 In C++11 or later only latest stable release per `GCC's release page <https://gcc.gnu.org/releases.html>`_
============ =============== ========================== =====================

Libc++ also supports common platforms and architectures:
Expand Down
9 changes: 2 additions & 7 deletions libcxx/include/__compare/synth_three_way.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD

// [expos.only.func]

// TODO MODULES restore the lamba to match the Standard.
// See https://github.com/llvm/llvm-project/issues/57222
//_LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way =
// []<class _Tp, class _Up>(const _Tp& __t, const _Up& __u)
template <class _Tp, class _Up>
_LIBCPP_HIDE_FROM_ABI constexpr auto __synth_three_way(const _Tp& __t, const _Up& __u)
_LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way = []<class _Tp, class _Up>(const _Tp& __t, const _Up& __u)
requires requires {
{ __t < __u } -> __boolean_testable;
{ __u < __t } -> __boolean_testable;
Expand All @@ -45,7 +40,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __synth_three_way(const _Tp& __t, const _Up
return weak_ordering::greater;
return weak_ordering::equivalent;
}
}
};

template <class _Tp, class _Up = _Tp>
using __synth_three_way_result = decltype(std::__synth_three_way(std::declval<_Tp&>(), std::declval<_Up&>()));
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__configuration/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
# warning "Libc++ only supports AppleClang 15 and later"
# endif
# elif defined(_LIBCPP_GCC_VER)
# if _LIBCPP_GCC_VER < 1300
# warning "Libc++ only supports GCC 13 and later"
# if _LIBCPP_GCC_VER < 1400
# warning "Libc++ only supports GCC 14 and later"
# endif
# endif

Expand Down
14 changes: 0 additions & 14 deletions libcxx/include/__locale_dir/locale_base_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,4 @@ except that locale_t is used instead of the current global locale.
The variadic functions may be implemented as templates with a parameter pack instead of variadic functions.
*/

/*
// TODO: These symbols are never actually used, but defined by one or more implementations. They should be removed.
long strtol_l(const char* str, char** str_end, locale_t);
unsigned long strtoul_l(const char* str, char** str_end, locale_t);
long long wcstoll_l(const wchar_t* str, wchar_t** str_end, int base, locale_t);
unsigned long long wcstoull_l(const wchar_t* str, wchar_t** str_end, int base, locale_t);
long double wcstold_l(const wchar_t* str, wchar_t** str_end, int base, locale_t);
int sprintf_l(char* str, const char* format, locale_t, ...);
int vsprintf_l(char* str, const char* format, locale_t, va_list);
int vsnprintf_l(char* str, size_t size, const char* format, locale_t, va_list);
int isblank_l(int ch, locale_t);
*/

#endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_H
46 changes: 16 additions & 30 deletions libcxx/include/__locale_dir/locale_base_api/android.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,29 @@
#ifndef _LIBCPP___LOCALE_LOCALE_BASE_API_ANDROID_H
#define _LIBCPP___LOCALE_LOCALE_BASE_API_ANDROID_H

#if defined(__BIONIC__)
#include <stdlib.h>

# ifdef __cplusplus
// FIXME: Is this actually required?
extern "C" {
# endif

# include <stdlib.h>
# include <xlocale.h>

# ifdef __cplusplus
#include <xlocale.h>
}
# endif

# if defined(__ANDROID__)

# include <android/api-level.h>
# if __ANDROID_API__ < 21
# include <__support/xlocale/__posix_l_fallback.h>
# endif
#include <android/api-level.h>
#if __ANDROID_API__ < 21
# include <__support/xlocale/__posix_l_fallback.h>
#endif

// If we do not have this header, we are in a platform build rather than an NDK
// build, which will always be at least as new as the ToT NDK, in which case we
// don't need any of the inlines below since libc provides them.
# if __has_include(<android/ndk-version.h>)
# include <android/ndk-version.h>
#if __has_include(<android/ndk-version.h>)
# include <android/ndk-version.h>
// In NDK versions later than 16, locale-aware functions are provided by
// legacy_stdlib_inlines.h
# if __NDK_MAJOR__ <= 16
# if __ANDROID_API__ < 21
# include <__support/xlocale/__strtonum_fallback.h>
# elif __ANDROID_API__ < 26
# if __NDK_MAJOR__ <= 16
# if __ANDROID_API__ < 21
# include <__support/xlocale/__strtonum_fallback.h>
# elif __ANDROID_API__ < 26

inline _LIBCPP_HIDE_FROM_ABI float strtof_l(const char* __nptr, char** __endptr, locale_t) {
return ::strtof(__nptr, __endptr);
Expand All @@ -50,15 +42,9 @@ inline _LIBCPP_HIDE_FROM_ABI double strtod_l(const char* __nptr, char** __endptr
return ::strtod(__nptr, __endptr);
}

inline _LIBCPP_HIDE_FROM_ABI long strtol_l(const char* __nptr, char** __endptr, int __base, locale_t) {
return ::strtol(__nptr, __endptr, __base);
}

# endif // __ANDROID_API__ < 26
# endif // __ANDROID_API__ < 26

# endif // __NDK_MAJOR__ <= 16
# endif // __has_include(<android/ndk-version.h>)
# endif // defined(__ANDROID__)
# endif // __NDK_MAJOR__ <= 16
#endif // __has_include(<android/ndk-version.h>)

#endif // defined(__BIONIC__)
#endif // _LIBCPP___LOCALE_LOCALE_BASE_API_ANDROID_H
12 changes: 4 additions & 8 deletions libcxx/include/__locale_dir/locale_base_api/fuchsia.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,9 @@
#ifndef _LIBCPP___LOCALE_LOCALE_BASE_API_FUCHSIA_H
#define _LIBCPP___LOCALE_LOCALE_BASE_API_FUCHSIA_H

#if defined(__Fuchsia__)

# include <__support/xlocale/__posix_l_fallback.h>
# include <__support/xlocale/__strtonum_fallback.h>
# include <cstdlib>
# include <cwchar>

#endif // defined(__Fuchsia__)
#include <__support/xlocale/__posix_l_fallback.h>
#include <__support/xlocale/__strtonum_fallback.h>
#include <cstdlib>
#include <cwchar>

#endif // _LIBCPP___LOCALE_LOCALE_BASE_API_FUCHSIA_H
10 changes: 0 additions & 10 deletions libcxx/include/__locale_dir/locale_base_api/ibm.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,6 @@ inline _LIBCPP_HIDE_FROM_ABI long long strtoll_l(const char* __nptr, char** __en
return ::strtoll(__nptr, __endptr, __base);
}

inline _LIBCPP_HIDE_FROM_ABI long strtol_l(const char* __nptr, char** __endptr, int __base, locale_t locale) {
__setAndRestore __newloc(locale);
return ::strtol(__nptr, __endptr, __base);
}

inline _LIBCPP_HIDE_FROM_ABI double strtod_l(const char* __nptr, char** __endptr, locale_t locale) {
__setAndRestore __newloc(locale);
return ::strtod(__nptr, __endptr);
Expand All @@ -84,11 +79,6 @@ strtoull_l(const char* __nptr, char** __endptr, int __base, locale_t locale) {
return ::strtoull(__nptr, __endptr, __base);
}

inline _LIBCPP_HIDE_FROM_ABI unsigned long strtoul_l(const char* __nptr, char** __endptr, int __base, locale_t locale) {
__setAndRestore __newloc(locale);
return ::strtoul(__nptr, __endptr, __base);
}

inline _LIBCPP_HIDE_FROM_ABI
_LIBCPP_ATTRIBUTE_FORMAT(__printf__, 2, 0) int vasprintf(char** strp, const char* fmt, va_list ap) {
const size_t buff_size = 256;
Expand Down
13 changes: 0 additions & 13 deletions libcxx/include/__locale_dir/locale_base_api/musl.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,4 @@ inline _LIBCPP_HIDE_FROM_ABI unsigned long long strtoull_l(const char* __nptr, c
return ::strtoull(__nptr, __endptr, __base);
}

inline _LIBCPP_HIDE_FROM_ABI long long wcstoll_l(const wchar_t* __nptr, wchar_t** __endptr, int __base, locale_t) {
return ::wcstoll(__nptr, __endptr, __base);
}

inline _LIBCPP_HIDE_FROM_ABI unsigned long long
wcstoull_l(const wchar_t* __nptr, wchar_t** __endptr, int __base, locale_t) {
return ::wcstoull(__nptr, __endptr, __base);
}

inline _LIBCPP_HIDE_FROM_ABI long double wcstold_l(const wchar_t* __nptr, wchar_t** __endptr, locale_t) {
return ::wcstold(__nptr, __endptr);
}

#endif // _LIBCPP___LOCALE_LOCALE_BASE_API_MUSL_H
10 changes: 0 additions & 10 deletions libcxx/include/__locale_dir/locale_base_api/newlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,4 @@
#ifndef _LIBCPP___LOCALE_LOCALE_BASE_API_NEWLIB_H
#define _LIBCPP___LOCALE_LOCALE_BASE_API_NEWLIB_H

#if defined(_NEWLIB_VERSION)

# if !defined(__NEWLIB__) || __NEWLIB__ < 2 || __NEWLIB__ == 2 && __NEWLIB_MINOR__ < 5
# include <__support/xlocale/__nop_locale_mgmt.h>
# include <__support/xlocale/__posix_l_fallback.h>
# include <__support/xlocale/__strtonum_fallback.h>
# endif

#endif // _NEWLIB_VERSION

#endif // _LIBCPP___LOCALE_LOCALE_BASE_API_NEWLIB_H
8 changes: 0 additions & 8 deletions libcxx/include/__locale_dir/locale_base_api/openbsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,4 @@
#include <ctype.h>
#include <cwctype>

inline _LIBCPP_HIDE_FROM_ABI long strtol_l(const char* __nptr, char** __endptr, int __base, locale_t) {
return ::strtol(__nptr, __endptr, __base);
}

inline _LIBCPP_HIDE_FROM_ABI unsigned long strtoul_l(const char* __nptr, char** __endptr, int __base, locale_t) {
return ::strtoul(__nptr, __endptr, __base);
}

#endif // _LIBCPP___LOCALE_LOCALE_BASE_API_OPENBSD_H
4 changes: 0 additions & 4 deletions libcxx/include/__locale_dir/locale_base_api/win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,15 +225,11 @@ _LIBCPP_EXPORTED_FROM_ABI size_t strftime_l(char* ret, size_t n, const char* for
# define strftime_l _strftime_l
#endif
#define sscanf_l(__s, __l, __f, ...) _sscanf_l(__s, __f, __l, __VA_ARGS__)
#define sprintf_l(__s, __l, __f, ...) _sprintf_l(__s, __f, __l, __VA_ARGS__)
#define vsprintf_l(__s, __l, __f, ...) _vsprintf_l(__s, __f, __l, __VA_ARGS__)
#define vsnprintf_l(__s, __n, __l, __f, ...) _vsnprintf_l(__s, __n, __f, __l, __VA_ARGS__)
_LIBCPP_EXPORTED_FROM_ABI int snprintf_l(char* __ret, size_t __n, locale_t __loc, const char* __format, ...);
_LIBCPP_EXPORTED_FROM_ABI int asprintf_l(char** __ret, locale_t __loc, const char* __format, ...);
_LIBCPP_EXPORTED_FROM_ABI int vasprintf_l(char** __ret, locale_t __loc, const char* __format, va_list __ap);

// not-so-pressing FIXME: use locale to determine blank characters
inline int isblank_l(int __c, locale_t /*loc*/) { return (__c == ' ' || __c == '\t'); }
inline int iswblank_l(wint_t __c, locale_t /*loc*/) { return (__c == L' ' || __c == L'\t'); }

#endif // _LIBCPP___LOCALE_LOCALE_BASE_API_WIN32_H
266 changes: 64 additions & 202 deletions libcxx/include/__string/char_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,31 +170,72 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char> {
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return int_type(EOF); }
};

// char_traits<wchar_t>

#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
template <>
struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t> {
using char_type = wchar_t;
using int_type = wint_t;
template <class _CharT, class _IntT, _IntT _EOFVal>
struct __char_traits_base {
using char_type = _CharT;
using int_type = _IntT;
using off_type = streamoff;
using pos_type = streampos;
using state_type = mbstate_t;
# if _LIBCPP_STD_VER >= 20
#if _LIBCPP_STD_VER >= 20
using comparison_category = strong_ordering;
# endif
#endif

static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void
assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {
__c1 = __c2;
// There are different aliases for the different char types, but they are all aliases to this type
using pos_type = fpos<mbstate_t>;

_LIBCPP_HIDE_FROM_ABI static inline _LIBCPP_CONSTEXPR_SINCE_CXX17 void
assign(char_type& __lhs, const char_type& __rhs) _NOEXCEPT {
__lhs = __rhs;
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {
return __c1 == __c2;

_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool eq(char_type __lhs, char_type __rhs) _NOEXCEPT {
return __lhs == __rhs;
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {
return __c1 < __c2;

_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool lt(char_type __lhs, char_type __rhs) _NOEXCEPT {
return __lhs < __rhs;
}

_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
move(char_type* __dest, const char_type* __src, size_t __n) _NOEXCEPT {
return std::__constexpr_memmove(__dest, __src, __element_count(__n));
}

_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
copy(char_type* __dest, const char_type* __src, size_t __n) _NOEXCEPT {
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__dest, __dest + __n, __src),
"char_traits::copy: source and destination ranges overlap");
return std::__constexpr_memmove(__dest, __src, __element_count(__n));
}

_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
assign(char_type* __str, size_t __n, char_type __fill_char) _NOEXCEPT {
std::fill_n(__str, __n, __fill_char);
return __str;
}

_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {
return char_type(__c);
}

_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT { return int_type(__c); }

_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool eq_int_type(int_type __lhs, int_type __rhs) _NOEXCEPT {
return __lhs == __rhs;
}

_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return _EOFVal; }

_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
return eq_int_type(__c, eof()) ? static_cast<int_type>(~eof()) : __c;
}
};

// char_traits<wchar_t>

#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
template <>
struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t> : __char_traits_base<wchar_t, wint_t, static_cast<wint_t>(WEOF)> {
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
if (__n == 0)
Expand All @@ -212,63 +253,14 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t> {
return nullptr;
return std::__constexpr_wmemchr(__s, __a, __n);
}

static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
return std::__constexpr_memmove(__s1, __s2, __element_count(__n));
}

static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2),
"char_traits::copy: source and destination ranges overlap");
std::__constexpr_memmove(__s1, __s2, __element_count(__n));
return __s1;
}

static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
std::fill_n(__s, __n, __a);
return __s;
}

static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
return eq_int_type(__c, eof()) ? ~eof() : __c;
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {
return char_type(__c);
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {
return int_type(__c);
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {
return __c1 == __c2;
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return int_type(WEOF); }
};
#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS

#ifndef _LIBCPP_HAS_NO_CHAR8_T

template <>
struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t> {
using char_type = char8_t;
using int_type = unsigned int;
using off_type = streamoff;
using pos_type = u8streampos;
using state_type = mbstate_t;
# if _LIBCPP_STD_VER >= 20
using comparison_category = strong_ordering;
# endif

static inline _LIBCPP_HIDE_FROM_ABI constexpr void assign(char_type& __c1, const char_type& __c2) noexcept {
__c1 = __c2;
}
static inline _LIBCPP_HIDE_FROM_ABI constexpr bool eq(char_type __c1, char_type __c2) noexcept {
return __c1 == __c2;
}
static inline _LIBCPP_HIDE_FROM_ABI constexpr bool lt(char_type __c1, char_type __c2) noexcept { return __c1 < __c2; }

struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
: __char_traits_base<char8_t, unsigned int, static_cast<unsigned int>(EOF)> {
static _LIBCPP_HIDE_FROM_ABI constexpr int
compare(const char_type* __s1, const char_type* __s2, size_t __n) noexcept {
return std::__constexpr_memcmp(__s1, __s2, __element_count(__n));
Expand All @@ -282,61 +274,13 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t> {
find(const char_type* __s, size_t __n, const char_type& __a) noexcept {
return std::__constexpr_memchr(__s, __a, __n);
}

static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
move(char_type* __s1, const char_type* __s2, size_t __n) noexcept {
return std::__constexpr_memmove(__s1, __s2, __element_count(__n));
}

static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
copy(char_type* __s1, const char_type* __s2, size_t __n) noexcept {
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2),
"char_traits::copy: source and destination ranges overlap");
std::__constexpr_memmove(__s1, __s2, __element_count(__n));
return __s1;
}

static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
assign(char_type* __s, size_t __n, char_type __a) noexcept {
std::fill_n(__s, __n, __a);
return __s;
}

static inline _LIBCPP_HIDE_FROM_ABI constexpr int_type not_eof(int_type __c) noexcept {
return eq_int_type(__c, eof()) ? ~eof() : __c;
}
static inline _LIBCPP_HIDE_FROM_ABI constexpr char_type to_char_type(int_type __c) noexcept { return char_type(__c); }
static inline _LIBCPP_HIDE_FROM_ABI constexpr int_type to_int_type(char_type __c) noexcept { return int_type(__c); }
static inline _LIBCPP_HIDE_FROM_ABI constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept {
return __c1 == __c2;
}
static inline _LIBCPP_HIDE_FROM_ABI constexpr int_type eof() noexcept { return int_type(EOF); }
};

#endif // _LIBCPP_HAS_NO_CHAR8_T

template <>
struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t> {
using char_type = char16_t;
using int_type = uint_least16_t;
using off_type = streamoff;
using pos_type = u16streampos;
using state_type = mbstate_t;
#if _LIBCPP_STD_VER >= 20
using comparison_category = strong_ordering;
#endif

static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void
assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {
__c1 = __c2;
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {
return __c1 == __c2;
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {
return __c1 < __c2;
}

struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
: __char_traits_base<char16_t, uint_least16_t, static_cast<uint_least16_t>(0xFFFF)> {
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT;
Expand All @@ -349,38 +293,6 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t> {
return nullptr;
return __match;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type*
move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
return std::__constexpr_memmove(__s1, __s2, __element_count(__n));
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type*
copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2),
"char_traits::copy: source and destination ranges overlap");
std::__constexpr_memmove(__s1, __s2, __element_count(__n));
return __s1;
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type*
assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
std::fill_n(__s, __n, __a);
return __s;
}

static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
return eq_int_type(__c, eof()) ? ~eof() : __c;
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {
return char_type(__c);
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {
return int_type(__c);
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {
return __c1 == __c2;
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return int_type(0xFFFF); }
};

inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
Expand All @@ -402,27 +314,8 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits<char16_t>::length(const
}

template <>
struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t> {
using char_type = char32_t;
using int_type = uint_least32_t;
using off_type = streamoff;
using pos_type = u32streampos;
using state_type = mbstate_t;
#if _LIBCPP_STD_VER >= 20
using comparison_category = strong_ordering;
#endif

static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void
assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {
__c1 = __c2;
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {
return __c1 == __c2;
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {
return __c1 < __c2;
}

struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
: __char_traits_base<char32_t, uint_least32_t, static_cast<uint_least32_t>(0xFFFFFFFF)> {
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT;
Expand All @@ -435,37 +328,6 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t> {
return nullptr;
return __match;
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type*
move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
return std::__constexpr_memmove(__s1, __s2, __element_count(__n));
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type*
copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
std::__constexpr_memmove(__s1, __s2, __element_count(__n));
return __s1;
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type*
assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
std::fill_n(__s, __n, __a);
return __s;
}

static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
return eq_int_type(__c, eof()) ? ~eof() : __c;
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {
return char_type(__c);
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {
return int_type(__c);
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {
return __c1 == __c2;
}
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return int_type(0xFFFFFFFF); }
};

inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
Expand Down
2 changes: 0 additions & 2 deletions libcxx/include/__support/xlocale/__posix_l_fallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ inline _LIBCPP_HIDE_FROM_ABI int isalnum_l(int __c, locale_t) { return ::isalnum

inline _LIBCPP_HIDE_FROM_ABI int isalpha_l(int __c, locale_t) { return ::isalpha(__c); }

inline _LIBCPP_HIDE_FROM_ABI int isblank_l(int __c, locale_t) { return ::isblank(__c); }

inline _LIBCPP_HIDE_FROM_ABI int iscntrl_l(int __c, locale_t) { return ::iscntrl(__c); }

inline _LIBCPP_HIDE_FROM_ABI int isdigit_l(int __c, locale_t) { return ::isdigit(__c); }
Expand Down
15 changes: 0 additions & 15 deletions libcxx/include/__support/xlocale/__strtonum_fallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,4 @@ inline _LIBCPP_HIDE_FROM_ABI unsigned long long strtoull_l(const char* __nptr, c
return ::strtoull(__nptr, __endptr, __base);
}

#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
inline _LIBCPP_HIDE_FROM_ABI long long wcstoll_l(const wchar_t* __nptr, wchar_t** __endptr, int __base, locale_t) {
return ::wcstoll(__nptr, __endptr, __base);
}

inline _LIBCPP_HIDE_FROM_ABI unsigned long long
wcstoull_l(const wchar_t* __nptr, wchar_t** __endptr, int __base, locale_t) {
return ::wcstoull(__nptr, __endptr, __base);
}

inline _LIBCPP_HIDE_FROM_ABI long double wcstold_l(const wchar_t* __nptr, wchar_t** __endptr, locale_t) {
return ::wcstold(__nptr, __endptr);
}
#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS

#endif // _LIBCPP___SUPPORT_XLOCALE_STRTONUM_FALLBACK_H
5 changes: 2 additions & 3 deletions libcxx/include/__type_traits/is_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@

_LIBCPP_BEGIN_NAMESPACE_STD

// TODO: Clang incorrectly reports that __is_array is true for T[0].
// Re-enable the branch once https://llvm.org/PR54705 is fixed.
#if __has_builtin(__is_array) && 0
#if __has_builtin(__is_array) && \
(!defined(_LIBCPP_COMPILER_CLANG_BASED) || (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1900))

template <class _Tp>
struct _LIBCPP_TEMPLATE_VIS is_array : _BoolConstant<__is_array(_Tp)> {};
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/array
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ template <class _Tp, size_t _Size>
_LIBCPP_HIDE_FROM_ABI constexpr __synth_three_way_result<_Tp>
operator<=>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
return std::lexicographical_compare_three_way(
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>);
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
}

#endif // _LIBCPP_STD_VER <= 17
Expand Down
4 changes: 3 additions & 1 deletion libcxx/include/chrono
Original file line number Diff line number Diff line change
Expand Up @@ -996,7 +996,9 @@ constexpr chrono::year operator ""y(unsigned lo

#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER == 20
# include <charconv>
# include <locale>
# if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <locale>
# endif
# include <ostream>
#endif

Expand Down
1 change: 1 addition & 0 deletions libcxx/include/complex
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ template<class T> complex<T> tanh (const complex<T>&);
#include <__fwd/tuple.h>
#include <__tuple/tuple_element.h>
#include <__tuple/tuple_size.h>
#include <__type_traits/conditional.h>
#include <__utility/move.h>
#include <cmath>
#include <version>
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/deque
Original file line number Diff line number Diff line change
Expand Up @@ -2531,7 +2531,7 @@ template <class _Tp, class _Allocator>
_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Tp>
operator<=>(const deque<_Tp, _Allocator>& __x, const deque<_Tp, _Allocator>& __y) {
return std::lexicographical_compare_three_way(
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>);
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
}

#endif // _LIBCPP_STD_VER <= 17
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/forward_list
Original file line number Diff line number Diff line change
Expand Up @@ -1518,7 +1518,7 @@ template <class _Tp, class _Allocator>
_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Tp>
operator<=>(const forward_list<_Tp, _Allocator>& __x, const forward_list<_Tp, _Allocator>& __y) {
return std::lexicographical_compare_three_way(
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>);
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
}

#endif // #if _LIBCPP_STD_VER <= 17
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/list
Original file line number Diff line number Diff line change
Expand Up @@ -1680,7 +1680,7 @@ template <class _Tp, class _Allocator>
_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Tp>
operator<=>(const list<_Tp, _Allocator>& __x, const list<_Tp, _Allocator>& __y) {
return std::lexicographical_compare_three_way(
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>);
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
}

#endif // _LIBCPP_STD_VER <= 17
Expand Down
14 changes: 2 additions & 12 deletions libcxx/include/map
Original file line number Diff line number Diff line change
Expand Up @@ -1617,12 +1617,7 @@ operator<=(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp,
template <class _Key, class _Tp, class _Compare, class _Allocator>
_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<pair<const _Key, _Tp>>
operator<=>(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) {
return std::lexicographical_compare_three_way(
__x.begin(),
__x.end(),
__y.begin(),
__y.end(),
std::__synth_three_way<pair<const _Key, _Tp>, pair<const _Key, _Tp>>);
return std::lexicographical_compare_three_way(__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
}

#endif // #if _LIBCPP_STD_VER <= 17
Expand Down Expand Up @@ -2136,12 +2131,7 @@ template <class _Key, class _Tp, class _Compare, class _Allocator>
_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<pair<const _Key, _Tp>>
operator<=>(const multimap<_Key, _Tp, _Compare, _Allocator>& __x,
const multimap<_Key, _Tp, _Compare, _Allocator>& __y) {
return std::lexicographical_compare_three_way(
__x.begin(),
__x.end(),
__y.begin(),
__y.end(),
std::__synth_three_way<pair<const _Key, _Tp>, pair<const _Key, _Tp>>);
return std::lexicographical_compare_three_way(__x.begin(), __x.end(), __y.begin(), __y.end(), __synth_three_way);
}

#endif // #if _LIBCPP_STD_VER <= 17
Expand Down
5 changes: 2 additions & 3 deletions libcxx/include/set
Original file line number Diff line number Diff line change
Expand Up @@ -993,8 +993,7 @@ operator<=(const set<_Key, _Compare, _Allocator>& __x, const set<_Key, _Compare,
template <class _Key, class _Allocator>
_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Key>
operator<=>(const set<_Key, _Allocator>& __x, const set<_Key, _Allocator>& __y) {
return std::lexicographical_compare_three_way(
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Key, _Key>);
return std::lexicographical_compare_three_way(__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
}

#endif // _LIBCPP_STD_VER <= 17
Expand Down Expand Up @@ -1454,7 +1453,7 @@ template <class _Key, class _Allocator>
_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Key>
operator<=>(const multiset<_Key, _Allocator>& __x, const multiset<_Key, _Allocator>& __y) {
return std::lexicographical_compare_three_way(
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Key, _Key>);
__x.begin(), __x.end(), __y.begin(), __y.end(), __synth_three_way);
}

#endif // _LIBCPP_STD_VER <= 17
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/vector
Original file line number Diff line number Diff line change
Expand Up @@ -2903,7 +2903,7 @@ template <class _Tp, class _Allocator>
_LIBCPP_HIDE_FROM_ABI constexpr __synth_three_way_result<_Tp>
operator<=>(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) {
return std::lexicographical_compare_three_way(
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>);
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
}

#endif // _LIBCPP_STD_VER <= 17
Expand Down
16 changes: 8 additions & 8 deletions libcxx/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -342,16 +342,16 @@ endif()

if (LIBCXX_ENABLE_LOCALIZATION AND LIBCXX_ENABLE_FILESYSTEM AND LIBCXX_ENABLE_TIME_ZONE_DATABASE)
list(APPEND LIBCXX_EXPERIMENTAL_SOURCES
include/tzdb/time_zone_private.h
include/tzdb/types_private.h
include/tzdb/tzdb_list_private.h
include/tzdb/tzdb_private.h
experimental/include/tzdb/time_zone_private.h
experimental/include/tzdb/types_private.h
experimental/include/tzdb/tzdb_list_private.h
experimental/include/tzdb/tzdb_private.h
# TODO TZDB The exception could be moved in chrono once the TZDB library
# is no longer experimental.
chrono_exception.cpp
time_zone.cpp
tzdb.cpp
tzdb_list.cpp
experimental/chrono_exception.cpp
experimental/time_zone.cpp
experimental/tzdb.cpp
experimental/tzdb_list.cpp
)
endif()

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
10 changes: 5 additions & 5 deletions libcxx/src/tzdb.cpp → libcxx/src/experimental/tzdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -677,9 +677,9 @@ void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {

__tzdb.version = chrono::__parse_version(__tzdata);
chrono::__parse_tzdata(__tzdb, __rules, __tzdata);
std::ranges::sort(__tzdb.zones);
std::ranges::sort(__tzdb.links);
std::ranges::sort(__rules, {}, [](const auto& p) { return p.first; });
ranges::sort(__tzdb.zones);
ranges::sort(__tzdb.links);
ranges::sort(__rules, {}, [](const auto& p) { return p.first; });

// There are two files with the leap second information
// - leapseconds as specified by zic
Expand Down Expand Up @@ -724,10 +724,10 @@ void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
return __result;

filesystem::path __path = "/etc/localtime";
if (!std::filesystem::exists(__path))
if (!filesystem::exists(__path))
std::__throw_runtime_error("tzdb: the symlink '/etc/localtime' does not exist");

if (!std::filesystem::is_symlink(__path))
if (!filesystem::is_symlink(__path))
std::__throw_runtime_error("tzdb: the path '/etc/localtime' is not a symlink");

filesystem::path __tz = filesystem::read_symlink(__path);
Expand Down
File renamed without changes.
3 changes: 0 additions & 3 deletions libcxx/test/libcxx/gdb/gdb_pretty_printer_test.sh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
// TODO: Investigate these failures which break the CI.
// UNSUPPORTED: clang-17, clang-18, clang-19

// TODO: Investigate this failure on GCC 13 (in Ubuntu Jammy)
// UNSUPPORTED: gcc-13

// The Android libc++ tests are run on a non-Android host, connected to an
// Android device over adb. gdb needs special support to make this work (e.g.
// gdbclient.py, ndk-gdb.py, gdbserver), and the Android organization doesn't
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
// GCC doesn't support the aligned-allocation flags.
// XFAIL: gcc

// TODO(mordante) fix this test after updating clang in Docker
// UNSUPPORTED: clang-15, clang-16, clang-17, clang-18, clang-19
// These compiler versions do not have proper sized deallocation support.
// UNSUPPORTED: clang-17, clang-18

// RUN: %{build} -faligned-allocation -fsized-deallocation
// RUN: %{run}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// Tests the IANA database rules parsing and operations.
// This is not part of the public tzdb interface.
// The test uses private implementation headers.
// ADDITIONAL_COMPILE_FLAGS: -I %{libcxx-dir}/src/include
// ADDITIONAL_COMPILE_FLAGS: -I %{libcxx-dir}/src/experimental/include

#include <chrono>
#include <fstream>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// Tests the IANA database zones parsing and operations.
// This is not part of the public tzdb interface.
// The test uses private implementation headers.
// ADDITIONAL_COMPILE_FLAGS: -I %{libcxx-dir}/src/include
// ADDITIONAL_COMPILE_FLAGS: -I %{libcxx-dir}/src/experimental/include

#include <cassert>
#include <chrono>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@

// <algorithm>

// https://buildkite.com/llvm-project/libcxx-ci/builds/15823#0184fc0b-d56b-4774-9e1d-35fe24e09e37
// It seems like the CI gcc version is buggy. I can't reproduce the failure on my system or on
// godbolt (https://godbolt.org/z/rsPv8e8fn).
// UNSUPPORTED: gcc-13

#include <algorithm>
#include <cstddef>
#include <functional>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ constexpr void test_layout() {
test_iteration(construct_mapping(Layout(), std::extents<unsigned, 7, 8>()));
test_iteration(construct_mapping(Layout(), std::extents<signed char, D, D, D, D>(1, 1, 1, 1)));

// TODO enable for GCC 13, when the CI pipeline is switched, doesn't work with GCC 12
#if defined(__clang_major__) && __clang_major__ >= 17
// TODO(LLVM 20): Enable this once AppleClang is upgraded
#ifndef TEST_COMPILER_APPLE_CLANG
int data[1];
// Check operator constraint for number of arguments
static_assert(check_operator_constraints(std::mdspan(data, construct_mapping(Layout(), std::extents<int, D>(1))), 0));
Expand Down Expand Up @@ -216,7 +216,7 @@ constexpr void test_layout() {
assert(!check_operator_constraints(std::mdspan(data, construct_mapping(Layout(), std::extents<int, D>(1))), s));
}
}
#endif
#endif // TEST_COMPILER_APPLE_CLANG
}

template <class Layout>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@

// test sized operator delete[] replacement.

// TODO(mordante) fix this test after updating clang in Docker
// UNSUPPORTED: clang-15, clang-16, clang-17, clang-18, clang-19
// These compiler versions do not have proper sized deallocation support.
// UNSUPPORTED: clang-17, clang-18

// UNSUPPORTED: sanitizer-new-delete, c++03, c++11
// XFAIL: apple-clang
// XFAIL: using-built-library-before-llvm-11
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@

// test sized operator delete replacement.

// TODO(mordante) fix this test after updating clang in Docker
// UNSUPPORTED: clang-15, clang-16, clang-17, clang-18, clang-19
// These compiler versions do not have proper sized deallocation support.
// UNSUPPORTED: clang-17, clang-18

// UNSUPPORTED: sanitizer-new-delete, c++03, c++11
// XFAIL: apple-clang
// XFAIL: using-built-library-before-llvm-11
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb

// TODO TZDB investigate why this fails with GCC
// UNSUPPORTED: gcc-13, gcc-14
// UNSUPPORTED: gcc-14

// XFAIL: libcpp-has-no-experimental-tzdb
// XFAIL: availability-tzdb-missing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

// GCC has a issue for `Guaranteed copy elision for potentially-overlapping non-static data members`,
// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333
// XFAIL: gcc-13, gcc-14
// XFAIL: gcc-14

// <expected>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

// GCC has a issue for `Guaranteed copy elision for potentially-overlapping non-static data members`,
// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333.
// XFAIL: gcc-13, gcc-14
// XFAIL: gcc-14

// <expected>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

// GCC has a issue for `Guaranteed copy elision for potentially-overlapping non-static data members`,
// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333
// XFAIL: gcc-13, gcc-14
// XFAIL: gcc-14

// <expected>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

// UNSUPPORTED: c++03, c++11, c++14, c++17
// TODO FMT __builtin_memcpy isn't constexpr in GCC
// UNSUPPORTED: gcc-13, gcc-14
// UNSUPPORTED: gcc-14

// <format>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,28 @@ int main(int, char**)
test_pair_rv<CopyOnly, CopyOnly&>();
test_pair_rv<CopyOnly, CopyOnly&&>();

test_pair_rv<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly>();
/* For ExplicitTypes::CopyOnly, two of the viable candidates for initializing from a non-const xvalue are:
* pair(const pair&); // (defaulted copy constructor)
* template<class U1, class U2> explicit pair(const pair<U1, U2>&&); [U1 = ExplicitTypes::CopyOnly, U2 = int]
*
* This results in diverging behavior for test_convertible which uses copy-list-initialization.
* Prior to CWG2137, this would have selected the first (non-explicit) ctor as explicit ctors
* would not be considered. Afterwards, it should select the second since it is a better match,
* and then failed because it is explicit.
*
* This may change with future defect reports, and some compilers only have partial support
* for CWG2137, so use std::is_convertible directly to avoid a copy-list-initialization
*/
{
using P1 = std::pair<ExplicitTypes::CopyOnly, int>;
using P2 = std::pair<int, ExplicitTypes::CopyOnly>;
using UP1 = std::pair<ExplicitTypes::CopyOnly, int>&&;
using UP2 = std::pair<int, ExplicitTypes::CopyOnly>&&;
static_assert(std::is_constructible<P1, UP1>::value, "");
static_assert(std::is_convertible<P1, UP1>::value, "");
static_assert(std::is_constructible<P2, UP2>::value, "");
static_assert(std::is_convertible<P2, UP2>::value, "");
}
test_pair_rv<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&, true, false>();
test_pair_rv<ExplicitTypes::CopyOnly, ExplicitTypes::CopyOnly&&, true, false>();

Expand Down
2 changes: 1 addition & 1 deletion libcxx/utils/libcxx/test/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ def check_gdb(cfg):
Feature(
name="_target-has-llvm-17",
when=lambda cfg: BooleanExpression.evaluate(
"target={{.+}}-apple-macosx{{14.[4-9](.0)?}}",
"target={{.+}}-apple-macosx{{14.[4-9](.0)?}} || target={{.+}}-apple-macosx{{1[5-9]([.].+)?}}",
cfg.available_features,
),
),
Expand Down
4 changes: 2 additions & 2 deletions libcxxabi/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ set_target_properties(cxxabi_shared_objects
if (CMAKE_POSITION_INDEPENDENT_CODE OR NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
set_target_properties(cxxabi_shared_objects PROPERTIES POSITION_INDEPENDENT_CODE ON) # must set manually because it's an object library
endif()
target_compile_options(cxxabi_shared_objects PUBLIC "${LIBCXXABI_ADDITIONAL_COMPILE_FLAGS}")
target_compile_options(cxxabi_shared_objects PRIVATE "${LIBCXXABI_ADDITIONAL_COMPILE_FLAGS}")

if (LIBCXXABI_ENABLE_SHARED)
add_library(cxxabi_shared SHARED)
Expand Down Expand Up @@ -262,7 +262,7 @@ set_target_properties(cxxabi_static_objects
CXX_STANDARD_REQUIRED OFF # TODO: Make this REQUIRED once we don't need to accommodate the LLVM documentation builders using an ancient CMake
COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}"
)
target_compile_options(cxxabi_static_objects PUBLIC "${LIBCXXABI_ADDITIONAL_COMPILE_FLAGS}")
target_compile_options(cxxabi_static_objects PRIVATE "${LIBCXXABI_ADDITIONAL_COMPILE_FLAGS}")

if(LIBCXXABI_HERMETIC_STATIC_LIBRARY)
target_add_compile_flags_if_supported(cxxabi_static_objects PRIVATE -fvisibility=hidden)
Expand Down
2 changes: 1 addition & 1 deletion libcxxabi/test/catch_member_function_pointer_02.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

// GCC supports noexcept function types but this test still fails.
// This is likely a bug in their implementation. Investigation needed.
// XFAIL: gcc-13, gcc-14
// XFAIL: gcc-14

#include <cassert>

Expand Down
2 changes: 1 addition & 1 deletion lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
// of Libtool. We cannot convince every software developer to migrate to
// the latest version and re-generate scripts. So we have this hack.
if (args.hasArg(OPT_v) || args.hasArg(OPT_version))
message(getLLDVersion() + ", compatible with GNU linkers");
message(getLLDVersion() + " (compatible with GNU linkers)");

if (const char *path = getReproduceOption(args)) {
// Note that --reproduce is a debug option so you can ignore it
Expand Down
4 changes: 4 additions & 0 deletions lld/ELF/InputSection.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,17 @@ class SectionBase {

Kind kind() const { return (Kind)sectionKind; }

LLVM_PREFERRED_TYPE(Kind)
uint8_t sectionKind : 3;

// The next two bit fields are only used by InputSectionBase, but we
// put them here so the struct packs better.

LLVM_PREFERRED_TYPE(bool)
uint8_t bss : 1;

// Set for sections that should not be folded by ICF.
LLVM_PREFERRED_TYPE(bool)
uint8_t keepUnique : 1;

uint8_t partition = 1;
Expand Down Expand Up @@ -282,6 +285,7 @@ struct SectionPiece {
: inputOff(off), live(live), hash(hash >> 1) {}

uint32_t inputOff;
LLVM_PREFERRED_TYPE(bool)
uint32_t live : 1;
uint32_t hash : 31;
uint64_t outputOff = 0;
Expand Down
18 changes: 18 additions & 0 deletions lld/ELF/Symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,21 @@ class Symbol {
uint8_t partition;

// True if this symbol is preemptible at load time.
LLVM_PREFERRED_TYPE(bool)
uint8_t isPreemptible : 1;

// True if the symbol was used for linking and thus need to be added to the
// output file's symbol table. This is true for all symbols except for
// unreferenced DSO symbols, lazy (archive) symbols, and bitcode symbols that
// are unreferenced except by other bitcode objects.
LLVM_PREFERRED_TYPE(bool)
uint8_t isUsedInRegularObj : 1;

// True if an undefined or shared symbol is used from a live section.
//
// NOTE: In Writer.cpp the field is used to mark local defined symbols
// which are referenced by relocations when -r or --emit-relocs is given.
LLVM_PREFERRED_TYPE(bool)
uint8_t used : 1;

// Used by a Defined symbol with protected or default visibility, to record
Expand All @@ -138,27 +141,33 @@ class Symbol {
// - If -shared or --export-dynamic is specified, any symbol in an object
// file/bitcode sets this property, unless suppressed by LTO
// canBeOmittedFromSymbolTable().
LLVM_PREFERRED_TYPE(bool)
uint8_t exportDynamic : 1;

// True if the symbol is in the --dynamic-list file. A Defined symbol with
// protected or default visibility with this property is required to be
// exported into .dynsym.
LLVM_PREFERRED_TYPE(bool)
uint8_t inDynamicList : 1;

// Used to track if there has been at least one undefined reference to the
// symbol. For Undefined and SharedSymbol, the binding may change to STB_WEAK
// if the first undefined reference from a non-shared object is weak.
LLVM_PREFERRED_TYPE(bool)
uint8_t referenced : 1;

// Used to track if this symbol will be referenced after wrapping is performed
// (i.e. this will be true for foo if __real_foo is referenced, and will be
// true for __wrap_foo if foo is referenced).
LLVM_PREFERRED_TYPE(bool)
uint8_t referencedAfterWrap : 1;

// True if this symbol is specified by --trace-symbol option.
LLVM_PREFERRED_TYPE(bool)
uint8_t traced : 1;

// True if the name contains '@'.
LLVM_PREFERRED_TYPE(bool)
uint8_t hasVersionSuffix : 1;

// Symbol visibility. This is the computed minimum visibility of all
Expand Down Expand Up @@ -270,20 +279,24 @@ class Symbol {
public:
// True if this symbol is in the Iplt sub-section of the Plt and the Igot
// sub-section of the .got.plt or .got.
LLVM_PREFERRED_TYPE(bool)
uint8_t isInIplt : 1;

// True if this symbol needs a GOT entry and its GOT entry is actually in
// Igot. This will be true only for certain non-preemptible ifuncs.
LLVM_PREFERRED_TYPE(bool)
uint8_t gotInIgot : 1;

// True if defined relative to a section discarded by ICF.
LLVM_PREFERRED_TYPE(bool)
uint8_t folded : 1;

// Allow reuse of a bit between architecture-exclusive symbol flags.
// - needsTocRestore(): On PPC64, true if a call to this symbol needs to be
// followed by a restore of the toc pointer.
// - isTagged(): On AArch64, true if the symbol needs special relocation and
// metadata semantics because it's tagged, under the AArch64 MemtagABI.
LLVM_PREFERRED_TYPE(bool)
uint8_t archSpecificBit : 1;
bool needsTocRestore() const { return archSpecificBit; }
bool isTagged() const { return archSpecificBit; }
Expand All @@ -296,13 +309,16 @@ class Symbol {
//
// LTO shouldn't inline the symbol because it doesn't know the final content
// of the symbol.
LLVM_PREFERRED_TYPE(bool)
uint8_t scriptDefined : 1;

// True if defined in a DSO. There may also be a definition in a relocatable
// object file.
LLVM_PREFERRED_TYPE(bool)
uint8_t dsoDefined : 1;

// True if defined in a DSO as protected visibility.
LLVM_PREFERRED_TYPE(bool)
uint8_t dsoProtected : 1;

// Temporary flags used to communicate which symbol entries need PLT and GOT
Expand All @@ -319,9 +335,11 @@ class Symbol {
// to a Verneed index in the output. Otherwise, this represents the Verdef
// index (VER_NDX_LOCAL, VER_NDX_GLOBAL, or a named version).
uint16_t versionId;
LLVM_PREFERRED_TYPE(bool)
uint8_t versionScriptAssigned : 1;

// True if targeted by a range extension thunk.
LLVM_PREFERRED_TYPE(bool)
uint8_t thunkAccessed : 1;

void setFlags(uint16_t bits) {
Expand Down
11 changes: 11 additions & 0 deletions lld/MachO/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1393,6 +1393,12 @@ static void handleExplicitExports() {
}
}

static void eraseInitializerSymbols() {
for (ConcatInputSection *isec : in.initOffsets->inputs())
for (Defined *sym : isec->symbols)
sym->used = false;
}

namespace lld {
namespace macho {
bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
Expand Down Expand Up @@ -1971,6 +1977,11 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
if (config->deadStrip)
markLive();

// Ensure that no symbols point inside __mod_init_func sections if they are
// removed due to -init_offsets. This must run after dead stripping.
if (config->emitInitOffsets)
eraseInitializerSymbols();

// Categories are not subject to dead-strip. The __objc_catlist section is
// marked as NO_DEAD_STRIP and that propagates into all category data.
if (args.hasArg(OPT_check_category_conflicts))
Expand Down
12 changes: 11 additions & 1 deletion lld/MachO/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,17 @@ void Writer::treatSpecialUndefineds() {

static void prepareSymbolRelocation(Symbol *sym, const InputSection *isec,
const lld::macho::Reloc &r) {
assert(sym->isLive());
if (!sym->isLive()) {
if (Defined *defined = dyn_cast<Defined>(sym)) {
if (config->emitInitOffsets &&
defined->isec()->getName() == section_names::moduleInitFunc)
fatal(isec->getLocation(r.offset) + ": cannot reference " +
sym->getName() +
" defined in __mod_init_func when -init_offsets is used");
}
assert(false && "referenced symbol must be live");
}

const RelocAttrs &relocAttrs = target->getRelocAttrs(r.type);

if (relocAttrs.hasAttr(RelocAttrBits::BRANCH)) {
Expand Down
33 changes: 33 additions & 0 deletions lld/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,21 @@ Non-comprehensive list of changes in this release
ELF Improvements
----------------

* ``EI_OSABI`` in the output is now inferred from input object files.
(`#97144 <https://github.com/llvm/llvm-project/pull/97144>`_)
* ``--compress-sections <section-glib>={none,zlib,zstd}[:level]`` is added to compress
matched output sections without the ``SHF_ALLOC`` flag.
(`#84855 <https://github.com/llvm/llvm-project/pull/84855>`_)
(`#90567 <https://github.com/llvm/llvm-project/pull/90567>`_)
* The default compression level for zlib is now independent of linker
optimization level (``Z_BEST_SPEED``).
* zstd compression parallelism no longer requires ``ZSTD_MULITHREAD`` build.
* ``GNU_PROPERTY_AARCH64_FEATURE_PAUTH`` notes, ``R_AARCH64_AUTH_ABS64`` and
``R_AARCH64_AUTH_RELATIVE`` relocations are now supported.
(`#72714 <https://github.com/llvm/llvm-project/pull/72714>`_)
* ``--no-allow-shlib-undefined`` now rejects non-exported definitions in the
``def-hidden.so ref.so`` case.
(`#86777 <https://github.com/llvm/llvm-project/issues/86777>`_)
* ``--debug-names`` is added to create a merged ``.debug_names`` index
from input ``.debug_names`` sections. Type units are not handled yet.
(`#86508 <https://github.com/llvm/llvm-project/pull/86508>`_)
Expand All @@ -44,13 +50,40 @@ ELF Improvements
(typical for embedded). It also makes full LTO feasible in such cases, since
IR merging currently prevents the linker script from referring to input
files. (`#90007 <https://github.com/llvm/llvm-project/pull/90007>`_)
* ``--default-script`/``-dT`` is implemented to specify a default script that is processed
if ``--script``/``-T`` is not specified.
(`#89327 <https://github.com/llvm/llvm-project/pull/89327>`_)
* ``--force-group-allocation`` is implemented to discard ``SHT_GROUP`` sections
and combine relocation sections if their relocated section group members are
placed to the same output section.
(`#94704 <https://github.com/llvm/llvm-project/pull/94704>`_)
* ``--build-id`` now defaults to generating a 20-byte digest ("sha1") instead
of 8-byte ("fast"). This improves compatibility with RPM packaging tools.
(`#93943 <https://github.com/llvm/llvm-project/pull/93943>`_)
* ``-z lrodata-after-bss`` is implemented to place ``.lrodata`` after ``.bss``.
(`#81224 <https://github.com/llvm/llvm-project/pull/81224>`_)
* ``--export-dynamic`` no longer creates dynamic sections for ``-no-pie`` static linking.
* ``--lto-emit-asm`` is now added as the canonical spelling of ``--plugin-opt=emit-llvm``.
* ``--lto-emit-llvm`` now uses the pre-codegen module.
(`#97480 <https://github.com/llvm/llvm-project/pull/97480>`_)
* When AArch64 PAuth is enabled, ``-z pack-relative-relocs`` now encodes ``R_AARCH64_AUTH_RELATIVE`` relocations in ``.rela.auth.dyn``.
(`#96496 <https://github.com/llvm/llvm-project/pull/96496>`_)
* ``-z gcs`` and ``-z gcs-report`` are now supported for AArch64 Guarded Control Stack extension.
* ``-r`` now forces ``-Bstatic``.
* Thumb2 PLT is now supported for Cortex-M processors.
(`#93644 <https://github.com/llvm/llvm-project/pull/93644>`_)
* ``DW_EH_sdata4`` of addresses larger than 0x80000000 is now supported for MIPS32.
(`#92438 <https://github.com/llvm/llvm-project/pull/92438>`_)
* Certain unknown section types are rejected.
(`#85173 <https://github.com/llvm/llvm-project/pull/85173>`_)
* ``PROVIDE(lhs = rhs) PROVIDE(rhs = ...)``, ``lhs`` is now defined only if ``rhs`` is needed.
(`#74771 <https://github.com/llvm/llvm-project/issues/74771>`_)
(`#87530 <https://github.com/llvm/llvm-project/pull/87530>`_)
* Orphan placement is refined to prefer the last similar section when its rank <= orphan's rank.
(`#94099 <https://github.com/llvm/llvm-project/pull/94099>`_)
Non-alloc orphan sections are now placed at the end.
(`#94519 <https://github.com/llvm/llvm-project/pull/94519>`_)
* R_X86_64_REX_GOTPCRELX of the addq form is no longer incorrectly optimized when the address is larger than 0x80000000.

Breaking changes
----------------
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/version.test
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
# RUN: ld.lld -V 2>&1 | FileCheck %s
# RUN: not ld.lld -V %t/not-exist 2>&1 | FileCheck %s

# CHECK: LLD {{.*}}, compatible with GNU linkers
# CHECK: LLD {{.+}} (compatible with GNU linkers)
6 changes: 5 additions & 1 deletion lld/test/MachO/init-offsets.s
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# RUN: llvm-objcopy --dump-section=__TEXT,__init_offsets=%t/section.bin %t/out
# RUN: echo "__TEXT,__init_offsets contents:" >> %t/dump.txt
# RUN: od -An -txI %t/section.bin >> %t/dump.txt
# RUN: FileCheck --check-prefix=CONTENT %s < %t/dump.txt
# RUN: FileCheck --check-prefix=CONTENT --implicit-check-not=_init_ptr %s < %t/dump.txt

## This test checks that:
## - __mod_init_func is replaced by __init_offsets.
Expand All @@ -21,6 +21,7 @@
## command line, and in the order they show up within __mod_init_func.
## - for undefined and dylib symbols, stubs are created, and the offsets point to those.
## - offsets are relative to __TEXT's address, they aren't an absolute virtual address.
## - symbols defined within __mod_init_func are ignored.

# FLAGS: sectname __init_offsets
# FLAGS-NEXT: segname __TEXT
Expand Down Expand Up @@ -48,13 +49,15 @@

#--- first.s
.globl _first_init, ___isnan, _main
.globl _init_ptr_1
.text
_first_init:
ret
_main:
ret

.section __DATA,__mod_init_func,mod_init_funcs
_init_ptr_1:
.quad _first_init
.quad ___isnan

Expand All @@ -68,6 +71,7 @@ _second_init:

.section __DATA,__mod_init_func,mod_init_funcs
.quad _undefined
_init_ptr_2:
.quad _second_init

.subsections_via_symbols
16 changes: 16 additions & 0 deletions lld/test/MachO/invalid/init-offsets.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# REQUIRES: x86

# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
# RUN: not %lld -lSystem -init_offsets %t.o -o /dev/null 2>&1 | FileCheck %s

# CHECK: error: {{.*}}init-offsets.s.tmp.o:(symbol _main+0x3): cannot reference _init_slot defined in __mod_init_func when -init_offsets is used

.globl _main
.text
_main:
leaq _init_slot(%rip), %rax

.section __DATA,__mod_init_func,mod_init_funcs
_init_slot:
.quad _main

10 changes: 7 additions & 3 deletions lldb/include/lldb/Target/Language.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,9 +363,13 @@ class Language : public PluginInterface {
return false;
}

/// Returns true if this Language supports exception breakpoints via a
/// corresponding LanguageRuntime plugin.
virtual bool SupportsExceptionBreakpoints() const { return false; }
/// Returns true if this Language supports exception breakpoints on throw via
/// a corresponding LanguageRuntime plugin.
virtual bool SupportsExceptionBreakpointsOnThrow() const { return false; }

/// Returns true if this Language supports exception breakpoints on catch via
/// a corresponding LanguageRuntime plugin.
virtual bool SupportsExceptionBreakpointsOnCatch() const { return false; }

protected:
// Classes that inherit from Language can see and modify these
Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/Utility/Listener.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class Listener : public std::enable_shared_from_this<Listener> {

std::string m_name;
broadcaster_collection m_broadcasters;
std::recursive_mutex m_broadcasters_mutex; // Protects m_broadcasters
std::mutex m_broadcasters_mutex; // Protects m_broadcasters
event_collection m_events;
std::mutex m_events_mutex; // Protects m_broadcasters and m_events
std::condition_variable m_events_condition;
Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Commands/CommandObjectBreakpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,8 @@ class CommandObjectBreakpointSet : public CommandObjectParsed {
break;
default:
if (Language *languagePlugin = Language::FindPlugin(language)) {
if (languagePlugin->SupportsExceptionBreakpoints()) {
if (languagePlugin->SupportsExceptionBreakpointsOnThrow() ||
languagePlugin->SupportsExceptionBreakpointsOnCatch()) {
m_exception_language = language;
break;
}
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ class ObjCLanguage : public Language {

llvm::StringRef GetInstanceVariableName() override { return "self"; }

bool SupportsExceptionBreakpoints() const override { return true; }
bool SupportsExceptionBreakpointsOnThrow() const override { return true; }

// PluginInterface protocol
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
Expand Down
21 changes: 8 additions & 13 deletions lldb/source/Utility/Listener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ Listener::~Listener() {

void Listener::Clear() {
Log *log = GetLog(LLDBLog::Object);
std::lock_guard<std::recursive_mutex> broadcasters_guard(
m_broadcasters_mutex);
std::lock_guard<std::mutex> broadcasters_guard(m_broadcasters_mutex);
broadcaster_collection::iterator pos, end = m_broadcasters.end();
for (pos = m_broadcasters.begin(); pos != end; ++pos) {
Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock());
Expand Down Expand Up @@ -68,8 +67,7 @@ uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
// Scope for "locker"
// Tell the broadcaster to add this object as a listener
{
std::lock_guard<std::recursive_mutex> broadcasters_guard(
m_broadcasters_mutex);
std::lock_guard<std::mutex> broadcasters_guard(m_broadcasters_mutex);
Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
m_broadcasters.insert(
std::make_pair(impl_wp, BroadcasterInfo(event_mask)));
Expand Down Expand Up @@ -99,8 +97,7 @@ uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster,
// Scope for "locker"
// Tell the broadcaster to add this object as a listener
{
std::lock_guard<std::recursive_mutex> broadcasters_guard(
m_broadcasters_mutex);
std::lock_guard<std::mutex> broadcasters_guard(m_broadcasters_mutex);
Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl());
m_broadcasters.insert(std::make_pair(
impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data)));
Expand Down Expand Up @@ -131,8 +128,7 @@ bool Listener::StopListeningForEvents(Broadcaster *broadcaster,
if (broadcaster) {
// Scope for "locker"
{
std::lock_guard<std::recursive_mutex> broadcasters_guard(
m_broadcasters_mutex);
std::lock_guard<std::mutex> broadcasters_guard(m_broadcasters_mutex);
m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
}
// Remove the broadcaster from our set of broadcasters
Expand All @@ -147,8 +143,7 @@ bool Listener::StopListeningForEvents(Broadcaster *broadcaster,
void Listener::BroadcasterWillDestruct(Broadcaster *broadcaster) {
// Scope for "broadcasters_locker"
{
std::lock_guard<std::recursive_mutex> broadcasters_guard(
m_broadcasters_mutex);
std::lock_guard<std::mutex> broadcasters_guard(m_broadcasters_mutex);
m_broadcasters.erase(broadcaster->GetBroadcasterImpl());
}

Expand Down Expand Up @@ -322,7 +317,7 @@ bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) {

size_t Listener::HandleBroadcastEvent(EventSP &event_sp) {
size_t num_handled = 0;
std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
std::lock_guard<std::mutex> guard(m_broadcasters_mutex);
Broadcaster *broadcaster = event_sp->GetBroadcaster();
if (!broadcaster)
return 0;
Expand Down Expand Up @@ -357,7 +352,7 @@ Listener::StartListeningForEventSpec(const BroadcasterManagerSP &manager_sp,
// The BroadcasterManager mutex must be locked before m_broadcasters_mutex to
// avoid violating the lock hierarchy (manager before broadcasters).
std::lock_guard<std::mutex> manager_guard(manager_sp->m_manager_mutex);
std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
std::lock_guard<std::mutex> guard(m_broadcasters_mutex);

uint32_t bits_acquired = manager_sp->RegisterListenerForEventsNoLock(
this->shared_from_this(), event_spec);
Expand All @@ -379,7 +374,7 @@ bool Listener::StopListeningForEventSpec(const BroadcasterManagerSP &manager_sp,
// The BroadcasterManager mutex must be locked before m_broadcasters_mutex to
// avoid violating the lock hierarchy (manager before broadcasters).
std::lock_guard<std::mutex> manager_guard(manager_sp->m_manager_mutex);
std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex);
std::lock_guard<std::mutex> guard(m_broadcasters_mutex);
return manager_sp->UnregisterListenerForEventsNoLock(this->shared_from_this(),
event_spec);
}
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/ADT/APInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class StringRef;
class hash_code;
class raw_ostream;
struct Align;
class DynamicAPInt;

template <typename T> class SmallVectorImpl;
template <typename T> class ArrayRef;
Expand Down Expand Up @@ -1895,6 +1896,9 @@ class [[nodiscard]] APInt {
friend struct DenseMapInfo<APInt, void>;
friend class APSInt;

// Make DynamicAPInt a friend so it can access BitWidth directly.
friend DynamicAPInt;

/// This constructor is used only internally for speed of construction of
/// temporaries. It is unsafe since it takes ownership of the pointer, so it
/// is not public.
Expand Down
32 changes: 21 additions & 11 deletions llvm/include/llvm/ADT/DynamicAPInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,23 @@ namespace llvm {
/// We always_inline all operations; removing these results in a 1.5x
/// performance slowdown.
///
/// When HoldsLarge is true, a SlowMPInt is held in the union. If it is false,
/// the int64_t is held. Using std::variant instead would lead to significantly
/// worse performance.
/// When isLarge returns true, a SlowMPInt is held in the union. If isSmall
/// returns true, the int64_t is held. We don't have a separate field for
/// indicating this, and instead "steal" memory from ValLarge when it is not in
/// use because we know that the memory layout of APInt is such that BitWidth
/// doesn't overlap with ValSmall (see static_assert_layout). Using std::variant
/// instead would lead to significantly worse performance.
class DynamicAPInt {
union {
int64_t ValSmall;
detail::SlowDynamicAPInt ValLarge;
};
unsigned HoldsLarge;

LLVM_ATTRIBUTE_ALWAYS_INLINE void initSmall(int64_t O) {
if (LLVM_UNLIKELY(isLarge()))
ValLarge.detail::SlowDynamicAPInt::~SlowDynamicAPInt();
ValSmall = O;
HoldsLarge = false;
ValLarge.Val.BitWidth = 0;
}
LLVM_ATTRIBUTE_ALWAYS_INLINE void
initLarge(const detail::SlowDynamicAPInt &O) {
Expand All @@ -66,14 +68,17 @@ class DynamicAPInt {
// and leak it.
ValLarge = O;
}
HoldsLarge = true;
}

LLVM_ATTRIBUTE_ALWAYS_INLINE explicit DynamicAPInt(
const detail::SlowDynamicAPInt &Val)
: ValLarge(Val), HoldsLarge(true) {}
LLVM_ATTRIBUTE_ALWAYS_INLINE bool isSmall() const { return !HoldsLarge; }
LLVM_ATTRIBUTE_ALWAYS_INLINE bool isLarge() const { return HoldsLarge; }
: ValLarge(Val) {}
LLVM_ATTRIBUTE_ALWAYS_INLINE constexpr bool isSmall() const {
return ValLarge.Val.BitWidth == 0;
}
LLVM_ATTRIBUTE_ALWAYS_INLINE constexpr bool isLarge() const {
return !isSmall();
}
/// Get the stored value. For getSmall/Large,
/// the stored value should be small/large.
LLVM_ATTRIBUTE_ALWAYS_INLINE int64_t getSmall() const {
Expand Down Expand Up @@ -105,14 +110,17 @@ class DynamicAPInt {

public:
LLVM_ATTRIBUTE_ALWAYS_INLINE explicit DynamicAPInt(int64_t Val)
: ValSmall(Val), HoldsLarge(false) {}
: ValSmall(Val) {
ValLarge.Val.BitWidth = 0;
}
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt() : DynamicAPInt(0) {}
LLVM_ATTRIBUTE_ALWAYS_INLINE ~DynamicAPInt() {
if (LLVM_UNLIKELY(isLarge()))
ValLarge.detail::SlowDynamicAPInt::~SlowDynamicAPInt();
}
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt(const DynamicAPInt &O)
: ValSmall(O.ValSmall), HoldsLarge(false) {
: ValSmall(O.ValSmall) {
ValLarge.Val.BitWidth = 0;
if (LLVM_UNLIKELY(O.isLarge()))
initLarge(O.ValLarge);
}
Expand Down Expand Up @@ -203,6 +211,8 @@ class DynamicAPInt {

friend hash_code hash_value(const DynamicAPInt &x); // NOLINT

void static_assert_layout(); // NOLINT

raw_ostream &print(raw_ostream &OS) const;
LLVM_DUMP_METHOD void dump() const;
};
Expand Down
7 changes: 7 additions & 0 deletions llvm/include/llvm/ADT/SlowDynamicAPInt.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include "llvm/ADT/APInt.h"
#include "llvm/Support/raw_ostream.h"

namespace llvm {
class DynamicAPInt;
} // namespace llvm

namespace llvm::detail {
/// A simple class providing dynamic arbitrary-precision arithmetic. Internally,
/// it stores an APInt, whose width is doubled whenever an overflow occurs at a
Expand Down Expand Up @@ -69,6 +73,9 @@ class SlowDynamicAPInt {
/// Overload to compute a hash_code for a SlowDynamicAPInt value.
friend hash_code hash_value(const SlowDynamicAPInt &X); // NOLINT

// Make DynamicAPInt a friend so it can access Val directly.
friend DynamicAPInt;

unsigned getBitWidth() const { return Val.getBitWidth(); }

void print(raw_ostream &OS) const;
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Analysis/BranchProbabilityInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ class BranchProbabilityInfo {

/// Helper to construct LoopBlock for \p BB.
LoopBlock getLoopBlock(const BasicBlock *BB) const {
return LoopBlock(BB, *LI, *SccI.get());
return LoopBlock(BB, *LI, *SccI);
}

/// Returns true if destination block belongs to some loop and source block is
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Analysis/LoopAccessAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,7 @@ class LoopAccessInfoManager {

const LoopAccessInfo &getInfo(Loop &L);

void clear() { LoopAccessInfoMap.clear(); }
void clear();

bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &Inv);
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Analysis/MLInlineAdvisor.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class MLInlineAdvisor : public InlineAdvisor {

bool isForcedToStop() const { return ForceStop; }
int64_t getLocalCalls(Function &F);
const MLModelRunner &getModelRunner() const { return *ModelRunner.get(); }
const MLModelRunner &getModelRunner() const { return *ModelRunner; }
FunctionPropertiesInfo &getCachedFPI(Function &) const;

protected:
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Analysis/MemorySSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@ class MemorySSAAnalysis : public AnalysisInfoMixin<MemorySSAAnalysis> {
struct Result {
Result(std::unique_ptr<MemorySSA> &&MSSA) : MSSA(std::move(MSSA)) {}

MemorySSA &getMSSA() { return *MSSA.get(); }
MemorySSA &getMSSA() { return *MSSA; }

std::unique_ptr<MemorySSA> MSSA;

Expand Down
3 changes: 0 additions & 3 deletions llvm/include/llvm/Analysis/ValueTracking.h
Original file line number Diff line number Diff line change
Expand Up @@ -904,9 +904,6 @@ bool isOverflowIntrinsicNoWrap(const WithOverflowInst *WO,
/// based on the vscale_range function attribute.
ConstantRange getVScaleRange(const Function *F, unsigned BitWidth);

/// Determine the possible constant range of a vector constant.
ConstantRange getVectorConstantRange(const Constant *C);

/// Determine the possible constant range of an integer or vector of integer
/// value. This is intended as a cheap, non-recursive check.
ConstantRange computeConstantRange(const Value *V, bool ForSigned,
Expand Down
6 changes: 5 additions & 1 deletion llvm/include/llvm/CodeGen/TargetInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,10 @@ class TargetInstrInfo : public MCInstrInfo {
return false;
}

/// Return true if the target will always try to convert predictable branches
/// to selects.
virtual bool shouldConvertPredictableBranches() const { return true; }

/// Return true if it is possible to insert a select
/// instruction that chooses between TrueReg and FalseReg based on the
/// condition code in Cond.
Expand Down Expand Up @@ -2214,7 +2218,7 @@ class TargetInstrInfo : public MCInstrInfo {
/// Return MIR formatter to format/parse MIR operands. Target can override
/// this virtual function and return target specific MIR formatter.
virtual const MIRFormatter *getMIRFormatter() const {
if (!Formatter.get())
if (!Formatter)
Formatter = std::make_unique<MIRFormatter>();
return Formatter.get();
}
Expand Down
99 changes: 99 additions & 0 deletions llvm/include/llvm/CodeGenData/OutlinedHashTree.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//===- OutlinedHashTree.h --------------------------------------*- 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
//
//===---------------------------------------------------------------------===//
//
// This defines the OutlinedHashTree class. It contains sequences of stable
// hash values of instructions that have been outlined. This OutlinedHashTree
// can be used to track the outlined instruction sequences across modules.
//
//===---------------------------------------------------------------------===//

#ifndef LLVM_CODEGENDATA_OUTLINEDHASHTREE_H
#define LLVM_CODEGENDATA_OUTLINEDHASHTREE_H

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StableHashing.h"
#include "llvm/ObjectYAML/YAML.h"
#include "llvm/Support/raw_ostream.h"

#include <unordered_map>
#include <vector>

namespace llvm {

/// A HashNode is an entry in an OutlinedHashTree, holding a hash value
/// and a collection of Successors (other HashNodes). If a HashNode has
/// a positive terminal value (Terminals > 0), it signifies the end of
/// a hash sequence with that occurrence count.
struct HashNode {
/// The hash value of the node.
stable_hash Hash = 0;
/// The number of terminals in the sequence ending at this node.
std::optional<unsigned> Terminals;
/// The successors of this node.
/// We don't use DenseMap as a stable_hash value can be tombstone.
std::unordered_map<stable_hash, std::unique_ptr<HashNode>> Successors;
};

class OutlinedHashTree {

using EdgeCallbackFn =
std::function<void(const HashNode *, const HashNode *)>;
using NodeCallbackFn = std::function<void(const HashNode *)>;

using HashSequence = SmallVector<stable_hash>;
using HashSequencePair = std::pair<HashSequence, unsigned>;

public:
/// Walks every edge and node in the OutlinedHashTree and calls CallbackEdge
/// for the edges and CallbackNode for the nodes with the stable_hash for
/// the source and the stable_hash of the sink for an edge. These generic
/// callbacks can be used to traverse a OutlinedHashTree for the purpose of
/// print debugging or serializing it.
void walkGraph(NodeCallbackFn CallbackNode,
EdgeCallbackFn CallbackEdge = nullptr,
bool SortedWalk = false) const;

/// Release all hash nodes except the root hash node.
void clear() {
assert(getRoot()->Hash == 0 && !getRoot()->Terminals);
getRoot()->Successors.clear();
}

/// \returns true if the hash tree has only the root node.
bool empty() { return size() == 1; }

/// \returns the size of a OutlinedHashTree by traversing it. If
/// \p GetTerminalCountOnly is true, it only counts the terminal nodes
/// (meaning it returns the the number of hash sequences in the
/// OutlinedHashTree).
size_t size(bool GetTerminalCountOnly = false) const;

/// \returns the depth of a OutlinedHashTree by traversing it.
size_t depth() const;

/// \returns the root hash node of a OutlinedHashTree.
const HashNode *getRoot() const { return &Root; }
HashNode *getRoot() { return &Root; }

/// Inserts a \p Sequence into the this tree. The last node in the sequence
/// will increase Terminals.
void insert(const HashSequencePair &SequencePair);

/// Merge a \p OtherTree into this Tree.
void merge(const OutlinedHashTree *OtherTree);

/// \returns the matching count if \p Sequence exists in the OutlinedHashTree.
std::optional<unsigned> find(const HashSequence &Sequence) const;

private:
HashNode Root;
};

} // namespace llvm

#endif
75 changes: 75 additions & 0 deletions llvm/include/llvm/CodeGenData/OutlinedHashTreeRecord.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//===- OutlinedHashTreeRecord.h --------------------------------*- 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
//
//===---------------------------------------------------------------------===//
//
// This defines the OutlinedHashTreeRecord class. This class holds the outlined
// hash tree for both serialization and deserialization processes. It utilizes
// two data formats for serialization: raw binary data and YAML.
// These two formats can be used interchangeably.
//
//===---------------------------------------------------------------------===//

#ifndef LLVM_CODEGENDATA_OUTLINEDHASHTREERECORD_H
#define LLVM_CODEGENDATA_OUTLINEDHASHTREERECORD_H

#include "llvm/CodeGenData/OutlinedHashTree.h"

namespace llvm {

/// HashNodeStable is the serialized, stable, and compact representation
/// of a HashNode.
struct HashNodeStable {
llvm::yaml::Hex64 Hash;
unsigned Terminals;
std::vector<unsigned> SuccessorIds;
};

using IdHashNodeStableMapTy = std::map<unsigned, HashNodeStable>;
using IdHashNodeMapTy = DenseMap<unsigned, HashNode *>;
using HashNodeIdMapTy = DenseMap<const HashNode *, unsigned>;

struct OutlinedHashTreeRecord {
std::unique_ptr<OutlinedHashTree> HashTree;

OutlinedHashTreeRecord() { HashTree = std::make_unique<OutlinedHashTree>(); }
OutlinedHashTreeRecord(std::unique_ptr<OutlinedHashTree> HashTree)
: HashTree(std::move(HashTree)) {};

/// Serialize the outlined hash tree to a raw_ostream.
void serialize(raw_ostream &OS) const;
/// Deserialize the outlined hash tree from a raw_ostream.
void deserialize(const unsigned char *&Ptr);
/// Serialize the outlined hash tree to a YAML stream.
void serializeYAML(yaml::Output &YOS) const;
/// Deserialize the outlined hash tree from a YAML stream.
void deserializeYAML(yaml::Input &YIS);

/// Merge the other outlined hash tree into this one.
void merge(const OutlinedHashTreeRecord &Other) {
HashTree->merge(Other.HashTree.get());
}

/// \returns true if the outlined hash tree is empty.
bool empty() const { return HashTree->empty(); }

/// Print the outlined hash tree in a YAML format.
void print(raw_ostream &OS = llvm::errs()) const {
yaml::Output YOS(OS);
serializeYAML(YOS);
}

private:
/// Convert the outlined hash tree to stable data.
void convertToStableData(IdHashNodeStableMapTy &IdNodeStableMap) const;

/// Convert the stable data back to the outlined hash tree.
void convertFromStableData(const IdHashNodeStableMapTy &IdNodeStableMap);
};

} // end namespace llvm

#endif // LLVM_CODEGENDATA_OUTLINEDHASHTREERECORD_H
5 changes: 5 additions & 0 deletions llvm/include/llvm/IR/Constant.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

namespace llvm {

class ConstantRange;
class APInt;

/// This is an important base class in LLVM. It provides the common facilities
Expand Down Expand Up @@ -154,6 +155,10 @@ class Constant : public User {
/// vector of constant integers, all equal, and the common value is returned.
const APInt &getUniqueInteger() const;

/// Convert constant to an approximate constant range. For vectors, the
/// range is the union over the element ranges. Poison elements are ignored.
ConstantRange toConstantRange() const;

/// Called if some element of this constant is no longer valid.
/// At this point only other constants may be on the use_list for this
/// constant. Any constants on our Use list must also be destroy'd. The
Expand Down
41 changes: 7 additions & 34 deletions llvm/include/llvm/MC/MCAssembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
Expand Down Expand Up @@ -55,18 +56,8 @@ class MCValue;

class MCAssembler {
public:
using SectionListType = std::vector<MCSection *>;
using SymbolDataListType = std::vector<const MCSymbol *>;

using SectionListType = SmallVector<MCSection *, 0>;
using const_iterator = pointee_iterator<SectionListType::const_iterator>;
using iterator = pointee_iterator<SectionListType::iterator>;

using const_symbol_iterator =
pointee_iterator<SymbolDataListType::const_iterator>;
using symbol_iterator = pointee_iterator<SymbolDataListType::iterator>;

using symbol_range = iterator_range<symbol_iterator>;
using const_symbol_range = iterator_range<const_symbol_iterator>;

/// MachO specific deployment target version info.
// A Major version of 0 indicates that no version information was supplied
Expand Down Expand Up @@ -98,7 +89,7 @@ class MCAssembler {

SectionListType Sections;

SymbolDataListType Symbols;
SmallVector<const MCSymbol *, 0> Symbols;

/// The list of linker options to propagate into the object file.
std::vector<std::vector<std::string>> LinkerOptions;
Expand Down Expand Up @@ -333,33 +324,15 @@ class MCAssembler {
BundleAlignSize = Size;
}

/// \name Section List Access
/// @{

iterator begin() { return Sections.begin(); }
const_iterator begin() const { return Sections.begin(); }

iterator end() { return Sections.end(); }
const_iterator end() const { return Sections.end(); }

size_t size() const { return Sections.size(); }

/// @}
/// \name Symbol List Access
/// @{
symbol_iterator symbol_begin() { return Symbols.begin(); }
const_symbol_iterator symbol_begin() const { return Symbols.begin(); }

symbol_iterator symbol_end() { return Symbols.end(); }
const_symbol_iterator symbol_end() const { return Symbols.end(); }

symbol_range symbols() { return make_range(symbol_begin(), symbol_end()); }
const_symbol_range symbols() const {
return make_range(symbol_begin(), symbol_end());
iterator_range<pointee_iterator<
typename SmallVector<const MCSymbol *, 0>::const_iterator>>
symbols() const {
return make_pointee_range(Symbols);
}

size_t symbol_size() const { return Symbols.size(); }

/// @}
/// \name Linker Option List Access
/// @{
Expand Down
77 changes: 54 additions & 23 deletions llvm/include/llvm/MC/MCDwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ class MCGenDwarfLabelEntry {

class MCCFIInstruction {
public:
enum OpType {
enum OpType : uint8_t {
OpSameValue,
OpRememberState,
OpRestoreState,
Expand All @@ -500,39 +500,56 @@ class MCCFIInstruction {
OpRegister,
OpWindowSave,
OpNegateRAState,
OpGnuArgsSize
OpGnuArgsSize,
OpLabel,
};

private:
OpType Operation;
MCSymbol *Label;
unsigned Register;
union {
int Offset;
unsigned Register2;
};
unsigned AddressSpace = ~0u;
struct {
unsigned Register;
int Offset;
} RI;
struct {
unsigned Register;
int Offset;
unsigned AddressSpace;
} RIA;
struct {
unsigned Register;
unsigned Register2;
} RR;
MCSymbol *CfiLabel;
} U;
OpType Operation;
SMLoc Loc;
std::vector<char> Values;
std::string Comment;

MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, SMLoc Loc,
StringRef V = "", StringRef Comment = "")
: Operation(Op), Label(L), Register(R), Offset(O), Loc(Loc),
Values(V.begin(), V.end()), Comment(Comment) {
: Label(L), Operation(Op), Loc(Loc), Values(V.begin(), V.end()),
Comment(Comment) {
assert(Op != OpRegister && Op != OpLLVMDefAspaceCfa);
U.RI = {R, O};
}

MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2, SMLoc Loc)
: Operation(Op), Label(L), Register(R1), Register2(R2), Loc(Loc) {
: Label(L), Operation(Op), Loc(Loc) {
assert(Op == OpRegister);
U.RR = {R1, R2};
}

MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, unsigned AS,
SMLoc Loc)
: Operation(Op), Label(L), Register(R), Offset(O), AddressSpace(AS),
Loc(Loc) {
: Label(L), Operation(Op), Loc(Loc) {
assert(Op == OpLLVMDefAspaceCfa);
U.RIA = {R, O, AS};
}

MCCFIInstruction(OpType Op, MCSymbol *L, MCSymbol *CfiLabel, SMLoc Loc)
: Label(L), Operation(Op), Loc(Loc) {
assert(Op == OpLabel);
U.CfiLabel = CfiLabel;
}

public:
Expand Down Expand Up @@ -655,34 +672,48 @@ class MCCFIInstruction {
return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, Loc);
}

static MCCFIInstruction createLabel(MCSymbol *L, MCSymbol *CfiLabel,
SMLoc Loc) {
return MCCFIInstruction(OpLabel, L, CfiLabel, Loc);
}

OpType getOperation() const { return Operation; }
MCSymbol *getLabel() const { return Label; }

unsigned getRegister() const {
if (Operation == OpRegister)
return U.RR.Register;
if (Operation == OpLLVMDefAspaceCfa)
return U.RIA.Register;
assert(Operation == OpDefCfa || Operation == OpOffset ||
Operation == OpRestore || Operation == OpUndefined ||
Operation == OpSameValue || Operation == OpDefCfaRegister ||
Operation == OpRelOffset || Operation == OpRegister ||
Operation == OpLLVMDefAspaceCfa);
return Register;
Operation == OpRelOffset);
return U.RI.Register;
}

unsigned getRegister2() const {
assert(Operation == OpRegister);
return Register2;
return U.RR.Register2;
}

unsigned getAddressSpace() const {
assert(Operation == OpLLVMDefAspaceCfa);
return AddressSpace;
return U.RIA.AddressSpace;
}

int getOffset() const {
if (Operation == OpLLVMDefAspaceCfa)
return U.RIA.Offset;
assert(Operation == OpDefCfa || Operation == OpOffset ||
Operation == OpRelOffset || Operation == OpDefCfaOffset ||
Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize ||
Operation == OpLLVMDefAspaceCfa);
return Offset;
Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize);
return U.RI.Offset;
}

MCSymbol *getCfiLabel() const {
assert(Operation == OpLabel);
return U.CfiLabel;
}

StringRef getValues() const {
Expand Down
Loading