diff --git a/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c b/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c index 2ff65a8b9ec3f..98611a75e85f1 100644 --- a/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c +++ b/compiler-rt/test/builtins/Unit/arm/aeabi_uldivmod_test.c @@ -1,3 +1,5 @@ +// This fails when libcxx is built with exceptions +// UNSUPPORTED: armv6m-target-arch // REQUIRES: arm-target-arch || armv6m-target-arch // RUN: %clang_builtins %s %librt -o %t && %run %t diff --git a/libc/config/config.json b/libc/config/config.json index 2005f4297bfc1..85297cd3fcb04 100644 --- a/libc/config/config.json +++ b/libc/config/config.json @@ -98,5 +98,11 @@ "value": "LIBC_QSORT_QUICK_SORT", "doc": "Configures sorting algorithm for qsort and qsort_r. Values accepted are LIBC_QSORT_QUICK_SORT, LIBC_QSORT_HEAP_SORT." } + }, + "setjmp": { + "LIBC_CONF_SETJMP_AARCH64_RESTORE_PLATFORM_REGISTER": { + "value": true, + "doc": "Make setjmp save the value of x18, and longjmp restore it. The AArch64 ABI delegates this register to platform ABIs, which can choose whether to make it caller-saved." + } } } diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 0be6f884f0368..d311878a8e349 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -710,6 +710,10 @@ if(LLVM_LIBC_FULL_BUILD) # sched.h entrypoints libc.src.sched.__sched_getcpucount + # setjmp.h entrypoints + libc.src.setjmp.longjmp + libc.src.setjmp.setjmp + # stdio.h entrypoints libc.src.stdio.clearerr libc.src.stdio.clearerr_unlocked diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst index 5c55e4ab0f181..d23ba477b3725 100644 --- a/libc/docs/configure.rst +++ b/libc/docs/configure.rst @@ -49,6 +49,8 @@ to learn about the defaults for your platform and target. * **"scanf" options** - ``LIBC_CONF_SCANF_DISABLE_FLOAT``: Disable parsing floating point values in scanf and friends. - ``LIBC_CONF_SCANF_DISABLE_INDEX_MODE``: Disable index mode in the scanf format string. +* **"setjmp" options** + - ``LIBC_CONF_SETJMP_AARCH64_RESTORE_PLATFORM_REGISTER``: Make setjmp save the value of x18, and longjmp restore it. The AArch64 ABI delegates this register to platform ABIs, which can choose whether to make it caller-saved. * **"string" options** - ``LIBC_CONF_MEMSET_X86_USE_SOFTWARE_PREFETCHING``: Inserts prefetch for write instructions (PREFETCHW) for memset on x86 to recover performance when hardware prefetcher is disabled. - ``LIBC_CONF_STRING_UNSAFE_WIDE_READ``: Read more than a byte at a time to perform byte-string operations like strlen. diff --git a/libc/include/llvm-libc-types/jmp_buf.h b/libc/include/llvm-libc-types/jmp_buf.h index 8949be9fa0ab7..60e033c6c65a9 100644 --- a/libc/include/llvm-libc-types/jmp_buf.h +++ b/libc/include/llvm-libc-types/jmp_buf.h @@ -35,6 +35,11 @@ typedef struct { #elif defined(__arm__) // r4, r5, r6, r7, r8, r9, r10, r11, r12, lr long opaque[10]; +#elif defined(__aarch64__) + long opaque[14]; // x19-x29, lr, sp, optional x18 +#if __ARM_FP + long fopaque[8]; // d8-d15 +#endif #else #error "__jmp_buf not available for your target architecture." #endif diff --git a/libc/src/setjmp/aarch64/CMakeLists.txt b/libc/src/setjmp/aarch64/CMakeLists.txt new file mode 100644 index 0000000000000..47eeb1a5c0ea6 --- /dev/null +++ b/libc/src/setjmp/aarch64/CMakeLists.txt @@ -0,0 +1,28 @@ +if(LIBC_CONF_SETJMP_AARCH64_RESTORE_PLATFORM_REGISTER) + list(APPEND setjmp_config_options "-DLIBC_COPT_SETJMP_AARCH64_RESTORE_PLATFORM_REGISTER") +endif() +if(setjmp_config_options) + list(PREPEND setjmp_config_options "COMPILE_OPTIONS") +endif() + +add_entrypoint_object( + setjmp + SRCS + setjmp.cpp + HDRS + ../setjmp_impl.h + DEPENDS + libc.include.setjmp + ${setjmp_config_options} +) + +add_entrypoint_object( + longjmp + SRCS + longjmp.cpp + HDRS + ../longjmp.h + DEPENDS + libc.include.setjmp + ${setjmp_config_options} +) diff --git a/libc/src/setjmp/aarch64/longjmp.cpp b/libc/src/setjmp/aarch64/longjmp.cpp new file mode 100644 index 0000000000000..3207cf40368c4 --- /dev/null +++ b/libc/src/setjmp/aarch64/longjmp.cpp @@ -0,0 +1,90 @@ +//===-- Implementation of longjmp for AArch64 -----------------------------===// +// +// 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/setjmp/longjmp.h" +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +// TODO: if MTE stack tagging is in use (-fsanitize=memtag-stack), we need to +// iterate over the region between the old and new values of sp, using STG or +// ST2G instructions to clear the memory tags on the invalidated region of the +// stack. But this requires a means of finding out that we're in that mode, and +// as far as I can see there isn't currently a predefined macro for that. +// +// (__ARM_FEATURE_MEMORY_TAGGING only indicates whether the target architecture +// supports the MTE instructions, not whether the compiler is configured to use +// them.) + +[[gnu::naked]] LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) { + // If BTI branch protection is in use, the compiler will automatically insert + // a BTI here, so we don't need to make any extra effort to do so. + + // If PAC branch protection is in use, there's no need to sign the return + // address at the start of longjmp, because we're not going to use it anyway! + + asm( + // Reload the callee-saved GPRs, including fp and lr. + R"( + ldp x19, x20, [x0, #0*16] + ldp x21, x22, [x0, #1*16] + ldp x23, x24, [x0, #2*16] + ldp x25, x26, [x0, #3*16] + ldp x27, x28, [x0, #4*16] + ldp x29, x30, [x0, #5*16] + )" + +#if LIBC_COPT_SETJMP_AARCH64_RESTORE_PLATFORM_REGISTER + // Reload the stack pointer, and the platform register x18. + R"( + ldp x2, x18, [x0, #6*16] + mov sp, x2 + )" +#else + // Reload just the stack pointer. + R"( + ldr x2, [x0, #6*16] + mov sp, x2 + )" +#endif + +#if __ARM_FP + // Reload the callee-saved FP registers. + R"( + ldp d8, d9, [x0, #7*16] + ldp d10, d11, [x0, #8*16] + ldp d12, d13, [x0, #9*16] + ldp d14, d15, [x0, #10*16] + )" +#endif + + // Calculate the return value. + R"( + cmp w1, #0 + cinc w0, w1, eq + )" + +#if __ARM_FEATURE_PAC_DEFAULT & 1 + // Authenticate the return address using the PAC A key. + R"( + autiasp + )" +#elif __ARM_FEATURE_PAC_DEFAULT & 2 + // Authenticate the return address using the PAC B key. + R"( + autibsp + )" +#endif + + R"( + ret + )"); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/setjmp/aarch64/setjmp.cpp b/libc/src/setjmp/aarch64/setjmp.cpp new file mode 100644 index 0000000000000..ba4dd645eaaa3 --- /dev/null +++ b/libc/src/setjmp/aarch64/setjmp.cpp @@ -0,0 +1,93 @@ +//===-- Implementation of setjmp for AArch64 ------------------------------===// +// +// 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/__support/common.h" +#include "src/__support/macros/config.h" +#include "src/setjmp/setjmp_impl.h" + +namespace LIBC_NAMESPACE_DECL { + +[[gnu::naked]] LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) { + // If BTI branch protection is in use, the compiler will automatically insert + // a BTI here, so we don't need to make any extra effort to do so. + + asm( +#if __ARM_FEATURE_PAC_DEFAULT & 1 + // Sign the return address using the PAC A key. + R"( + paciasp + )" +#elif __ARM_FEATURE_PAC_DEFAULT & 2 + // Sign the return address using the PAC B key. + R"( + pacibsp + )" +#endif + + // Store all the callee-saved GPRs, including fp (x29) and also lr (x30). + // Of course lr isn't normally callee-saved (the call instruction itself + // can't help clobbering it), but we certainly need to save it for this + // purpose. + R"( + stp x19, x20, [x0, #0*16] + stp x21, x22, [x0, #1*16] + stp x23, x24, [x0, #2*16] + stp x25, x26, [x0, #3*16] + stp x27, x28, [x0, #4*16] + stp x29, x30, [x0, #5*16] + )" + +#if LIBC_COPT_SETJMP_AARCH64_RESTORE_PLATFORM_REGISTER + // Store the stack pointer, and the platform register x18. + R"( + add x1, sp, #0 + stp x1, x18, [x0, #6*16] + )" +#else + // Store just the stack pointer. + R"( + add x1, sp, #0 + str x1, [x0, #6*16] + )" +#endif + +#if __ARM_FP + // Store the callee-saved FP registers. AAPCS64 only requires the low 64 + // bits of v8-v15 to be preserved, i.e. each of d8,...,d15. + R"( + stp d8, d9, [x0, #7*16] + stp d10, d11, [x0, #8*16] + stp d12, d13, [x0, #9*16] + stp d14, d15, [x0, #10*16] + )" +#endif + + // Set up return value of zero. + R"( + mov x0, #0 + )" + +#if (__ARM_FEATURE_PAC_DEFAULT & 7) == 5 + // Authenticate the return address using the PAC A key, since the + // compilation options ask for PAC protection even on leaf functions. + R"( + autiasp + )" +#elif (__ARM_FEATURE_PAC_DEFAULT & 7) == 6 + // Same, but using the PAC B key. + R"( + autibsp + )" +#endif + + R"( + ret + )"); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libcxx/cmake/caches/Armv7M-picolibc.cmake b/libcxx/cmake/caches/Armv7M-picolibc.cmake index b5f9089308d22..0a83e75ceceb4 100644 --- a/libcxx/cmake/caches/Armv7M-picolibc.cmake +++ b/libcxx/cmake/caches/Armv7M-picolibc.cmake @@ -18,6 +18,9 @@ set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "") set(LIBCXXABI_ENABLE_STATIC ON CACHE BOOL "") set(LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "") set(LIBCXXABI_ENABLE_THREADS OFF CACHE BOOL "") +# Long tests are prohibitively slow when run via emulation. +# The emulated target has limited memory. +set(LIBCXXABI_TEST_PARAMS "long_tests=False;large_tests=False" CACHE STRING "") set(LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "") set(LIBCXX_ENABLE_EXCEPTIONS ON CACHE BOOL "") set(LIBCXX_ENABLE_FILESYSTEM OFF CACHE STRING "") @@ -30,12 +33,16 @@ set(LIBCXX_ENABLE_THREADS OFF CACHE BOOL "") set(LIBCXX_ENABLE_WIDE_CHARACTERS OFF CACHE BOOL "") set(LIBCXX_INCLUDE_BENCHMARKS OFF CACHE BOOL "") # Long tests are prohibitively slow when run via emulation. -set(LIBCXX_TEST_PARAMS "long_tests=False" CACHE STRING "") +# The emulated target has limited memory. +set(LIBCXX_TEST_PARAMS "long_tests=False;large_tests=False" CACHE STRING "") set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") set(LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") set(LIBUNWIND_ENABLE_STATIC ON CACHE BOOL "") set(LIBUNWIND_ENABLE_THREADS OFF CACHE BOOL "") set(LIBUNWIND_IS_BAREMETAL ON CACHE BOOL "") set(LIBUNWIND_REMEMBER_HEAP_ALLOC ON CACHE BOOL "") +# Long tests are prohibitively slow when run via emulation. +# The emulated target has limited memory. +set(LIBUNWIND_TEST_PARAMS "long_tests=False;large_tests=False" CACHE STRING "") set(LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") find_program(QEMU_SYSTEM_ARM qemu-system-arm REQUIRED) diff --git a/libcxx/test/libcxx/atomics/lit.local.cfg b/libcxx/test/libcxx/atomics/lit.local.cfg new file mode 100644 index 0000000000000..5ecc58f3e3857 --- /dev/null +++ b/libcxx/test/libcxx/atomics/lit.local.cfg @@ -0,0 +1,3 @@ +# Disable all of the atomics tests if the correct feature is not available. +if "has-no-atomics" in config.available_features: + config.unsupported = True diff --git a/libcxx/test/libcxx/experimental/memory/lit.local.cfg b/libcxx/test/libcxx/experimental/memory/lit.local.cfg new file mode 100644 index 0000000000000..5ecc58f3e3857 --- /dev/null +++ b/libcxx/test/libcxx/experimental/memory/lit.local.cfg @@ -0,0 +1,3 @@ +# Disable all of the atomics tests if the correct feature is not available. +if "has-no-atomics" in config.available_features: + config.unsupported = True diff --git a/libcxx/test/libcxx/thread/thread.stoptoken/intrusive_shared_ptr.pass.cpp b/libcxx/test/libcxx/thread/thread.stoptoken/intrusive_shared_ptr.pass.cpp index 47440015f2c50..4350de3dfa654 100644 --- a/libcxx/test/libcxx/thread/thread.stoptoken/intrusive_shared_ptr.pass.cpp +++ b/libcxx/test/libcxx/thread/thread.stoptoken/intrusive_shared_ptr.pass.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// // +// XFAIL: has-no-atomics + // UNSUPPORTED: c++03, c++11, c++14, c++17 #include <__stop_token/intrusive_shared_ptr.h> diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort.pass.cpp index e2581fbf2fa6c..99a9e17755132 100644 --- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort.pass.cpp @@ -6,8 +6,7 @@ // //===----------------------------------------------------------------------===// -// This test appears to hang with picolibc & qemu. -// UNSUPPORTED: LIBCXX-PICOLIBC-FIXME +// REQUIRES: long_test // diff --git a/libcxx/test/std/atomics/lit.local.cfg b/libcxx/test/std/atomics/lit.local.cfg new file mode 100644 index 0000000000000..5ecc58f3e3857 --- /dev/null +++ b/libcxx/test/std/atomics/lit.local.cfg @@ -0,0 +1,3 @@ +# Disable all of the atomics tests if the correct feature is not available. +if "has-no-atomics" in config.available_features: + config.unsupported = True diff --git a/libcxx/test/std/experimental/memory/memory.polymorphic.allocator.class/lit.local.cfg b/libcxx/test/std/experimental/memory/memory.polymorphic.allocator.class/lit.local.cfg new file mode 100644 index 0000000000000..5ecc58f3e3857 --- /dev/null +++ b/libcxx/test/std/experimental/memory/memory.polymorphic.allocator.class/lit.local.cfg @@ -0,0 +1,3 @@ +# Disable all of the atomics tests if the correct feature is not available. +if "has-no-atomics" in config.available_features: + config.unsupported = True diff --git a/libcxx/test/std/experimental/memory/memory.resource.aliases/lit.local.cfg b/libcxx/test/std/experimental/memory/memory.resource.aliases/lit.local.cfg new file mode 100644 index 0000000000000..5ecc58f3e3857 --- /dev/null +++ b/libcxx/test/std/experimental/memory/memory.resource.aliases/lit.local.cfg @@ -0,0 +1,3 @@ +# Disable all of the atomics tests if the correct feature is not available. +if "has-no-atomics" in config.available_features: + config.unsupported = True diff --git a/libcxx/test/std/experimental/memory/memory.resource.global/lit.local.cfg b/libcxx/test/std/experimental/memory/memory.resource.global/lit.local.cfg new file mode 100644 index 0000000000000..5ecc58f3e3857 --- /dev/null +++ b/libcxx/test/std/experimental/memory/memory.resource.global/lit.local.cfg @@ -0,0 +1,3 @@ +# Disable all of the atomics tests if the correct feature is not available. +if "has-no-atomics" in config.available_features: + config.unsupported = True diff --git a/libcxx/test/std/language.support/cmp/cmp.alg/strong_order_long_double.verify.cpp b/libcxx/test/std/language.support/cmp/cmp.alg/strong_order_long_double.verify.cpp index c9c2ba2002149..4898a9a06e099 100644 --- a/libcxx/test/std/language.support/cmp/cmp.alg/strong_order_long_double.verify.cpp +++ b/libcxx/test/std/language.support/cmp/cmp.alg/strong_order_long_double.verify.cpp @@ -12,6 +12,11 @@ // This test does apply to aarch64 where Arm's AAPCS64 is followed. There they are different sizes. // XFAIL: target={{arm64|arm64e|armv(7|8)(l|m)?|powerpc|powerpc64}}-{{.+}} +// In internal LLVM arm BMT tests the target is fixed to "arm-none-eabi", so the +// "unsupported" cluase above does not work. TODO: find more generic way to +// detect equal sizes of double and long double +// XFAIL: LIBCXX-PICOLIBC-FIXME + // MSVC configurations have long double equal to regular double on all // architectures. // XFAIL: target={{.+}}-pc-windows-msvc diff --git a/libcxx/test/std/language.support/support.runtime/ctime.timespec.compile.pass.cpp b/libcxx/test/std/language.support/support.runtime/ctime.timespec.compile.pass.cpp index b7fd892003e2d..194262bb42e3b 100644 --- a/libcxx/test/std/language.support/support.runtime/ctime.timespec.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.runtime/ctime.timespec.compile.pass.cpp @@ -11,9 +11,6 @@ // UNSUPPORTED: c++03, c++11, c++14 -// picolibc doesn't define TIME_UTC. -// XFAIL: LIBCXX-PICOLIBC-FIXME - // ::timespec_get is provided by the C library, but it's marked as // unavailable until macOS 10.15 // XFAIL: target={{.+}}-apple-macosx10.{{13|14}} diff --git a/libcxx/test/std/language.support/support.start.term/quick_exit.pass.cpp b/libcxx/test/std/language.support/support.start.term/quick_exit.pass.cpp index d8eff69cb53fe..e16048df722e8 100644 --- a/libcxx/test/std/language.support/support.start.term/quick_exit.pass.cpp +++ b/libcxx/test/std/language.support/support.start.term/quick_exit.pass.cpp @@ -17,6 +17,9 @@ // test quick_exit and at_quick_exit +// TODO: Find out why the at_quick_exit symbol is not found. +// XFAIL: LIBCXX-PICOLIBC-FIXME + #include void f() {} diff --git a/libcxx/test/std/re/re.alg/re.alg.match/exponential.pass.cpp b/libcxx/test/std/re/re.alg/re.alg.match/exponential.pass.cpp index 2493f6a643a6d..f4f1bb642eaf2 100644 --- a/libcxx/test/std/re/re.alg/re.alg.match/exponential.pass.cpp +++ b/libcxx/test/std/re/re.alg/re.alg.match/exponential.pass.cpp @@ -10,6 +10,9 @@ // UNSUPPORTED: no-exceptions // UNSUPPORTED: c++03 +// fails with bad_alloc exception +// REQUIRES: large_tests + // template // bool // regex_match(BidirectionalIterator first, BidirectionalIterator last, diff --git a/libcxx/test/std/re/re.alg/re.alg.search/exponential.pass.cpp b/libcxx/test/std/re/re.alg/re.alg.search/exponential.pass.cpp index 64a6a135addab..057301e6f8681 100644 --- a/libcxx/test/std/re/re.alg/re.alg.search/exponential.pass.cpp +++ b/libcxx/test/std/re/re.alg/re.alg.search/exponential.pass.cpp @@ -10,6 +10,9 @@ // UNSUPPORTED: no-exceptions // UNSUPPORTED: c++03 +// fails with bad_alloc exception +// REQUIRES: large_tests + // template // bool // regex_search(BidirectionalIterator first, BidirectionalIterator last, diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py index e978875d543f3..015db3bf6ed28 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -215,6 +215,21 @@ def _mingwSupportsModules(cfg): """, ), ), + Feature( + name="has-no-atomics", + when=lambda cfg: not sourceBuilds( + cfg, + """ + #include + std::atomic_uint x; + int main(int, char**) { (void)x.load(); return 0; } + """, + ), + actions=[ + AddFeature("availability-pmr-missing"), + AddFeature("libcpp-has-no-incomplete-pstl"), + ], + ), # Tests that require 64-bit architecture Feature( name="32-bit-pointer", diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp index fe5598991b831..65d30a352814e 100644 --- a/libcxxabi/test/test_demangle.pass.cpp +++ b/libcxxabi/test/test_demangle.pass.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// // This test is too big for most embedded devices. -// XFAIL: LIBCXX-PICOLIBC-FIXME +// REQUIRES: large_tests // https://llvm.org/PR51407 was not fixed in some previously-released // demanglers, which causes them to run into the infinite loop.