diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-06-14 19:30:29 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2023-06-14 19:30:29 +0000 |
commit | 730a9963fa65360c323634ca02cf353b35946e5a (patch) | |
tree | f12ffa955f8105409bb0ab2b022f9c289f561c97 | |
parent | 41ea538b401b10c9e2102a582289c29be718ab51 (diff) | |
parent | 04cf93f337c20b9e4ba6a3abb77bc2328e7df4ad (diff) | |
download | bionic-ndk-r26-release.tar.gz |
Merge "Snap for 10321980 from 6045af29318e0fef2075d7484988041439128ea2 to ndk-r26-release" into ndk-r26-releasendk-r26dndk-r26cndk-r26bndk-r26-rc1ndk-r26-beta1ndk-r26ndk-r26-release
78 files changed, 2978 insertions, 952 deletions
diff --git a/libc/Android.bp b/libc/Android.bp index ecabb06b7..1e2458a29 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -932,6 +932,21 @@ cc_library_static { "arch-riscv64/bionic/setjmp.S", "arch-riscv64/bionic/syscall.S", "arch-riscv64/bionic/vfork.S", + + "arch-riscv64/string/memchr_vext.S", + "arch-riscv64/string/memcmp_vext.S", + "arch-riscv64/string/memcpy_vext.S", + "arch-riscv64/string/memmove_vext.S", + "arch-riscv64/string/memset_vext.S", + "arch-riscv64/string/strcat_vext.S", + "arch-riscv64/string/strchr_vext.S", + "arch-riscv64/string/strcmp_vext.S", + "arch-riscv64/string/strcpy_vext.S", + "arch-riscv64/string/strlen_vext.S", + "arch-riscv64/string/strncat_vext.S", + "arch-riscv64/string/strncmp_vext.S", + "arch-riscv64/string/strncpy_vext.S", + "arch-riscv64/string/strnlen_vext.S", ], }, @@ -1541,6 +1556,9 @@ cc_library_static { arm64: { srcs: ["arch-arm64/static_function_dispatch.S"], }, + riscv64: { + srcs: ["arch-riscv64/static_function_dispatch.S"] + }, }, } @@ -1569,6 +1587,9 @@ cc_library_static { arm64: { srcs: ["arch-arm64/dynamic_function_dispatch.cpp"], }, + riscv64: { + srcs: ["arch-riscv64/dynamic_function_dispatch.cpp"] + }, }, } diff --git a/libc/NOTICE b/libc/NOTICE index 4d3a10861..441e79c03 100644 --- a/libc/NOTICE +++ b/libc/NOTICE @@ -4540,6 +4540,34 @@ SUCH DAMAGE. ------------------------------------------------------------------- +Copyright (c) 2023 SiFive, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------- + Copyright (c)1999 Citrus Project, All rights reserved. diff --git a/libc/arch-riscv64/dynamic_function_dispatch.cpp b/libc/arch-riscv64/dynamic_function_dispatch.cpp new file mode 100644 index 000000000..0925c5f6d --- /dev/null +++ b/libc/arch-riscv64/dynamic_function_dispatch.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <private/bionic_ifuncs.h> +#include <stddef.h> +#include <sys/auxv.h> + +#if defined(__riscv_v) +extern "C" { + +typedef void* memchr_func(const void*, int, size_t); +DEFINE_IFUNC_FOR(memchr) { + RETURN_FUNC(memchr_func, memchr_vext); +} + +typedef int memcmp_func(const void*, const void*, size_t); +DEFINE_IFUNC_FOR(memcmp) { + RETURN_FUNC(memcmp_func, memcmp_vext); +} + +typedef void* memcpy_func(void*, const void*, size_t); +DEFINE_IFUNC_FOR(memcpy) { + RETURN_FUNC(memcpy_func, memcpy_vext); +} + +typedef void* memmove_func(void*, const void*, size_t); +DEFINE_IFUNC_FOR(memmove) { + RETURN_FUNC(memmove_func, memmove_vext); +} + +typedef void* memset_func(void*, int, size_t); +DEFINE_IFUNC_FOR(memset) { + RETURN_FUNC(memset_func, memset_vext); +} + +typedef char* strcat_func(char*, const char*); +DEFINE_IFUNC_FOR(strcat) { + RETURN_FUNC(strcat_func, strcat_vext); +} + +typedef char* strchr_func(const char*, int); +DEFINE_IFUNC_FOR(strchr) { + RETURN_FUNC(strchr_func, strchr_vext); +} + +typedef int strcmp_func(const char*, const char*); +DEFINE_IFUNC_FOR(strcmp) { + RETURN_FUNC(strcmp_func, strcmp_vext); +} + +typedef char* strcpy_func(char*, const char*); +DEFINE_IFUNC_FOR(strcpy) { + RETURN_FUNC(strcpy_func, strcpy_vext); +} + +typedef size_t strlen_func(const char*); +DEFINE_IFUNC_FOR(strlen) { + RETURN_FUNC(strlen_func, strlen_vext); +} + +typedef char* strncat_func(char*, const char*, size_t); +DEFINE_IFUNC_FOR(strncat) { + RETURN_FUNC(strncat_func, strncat_vext); +} + +typedef int strncmp_func(const char*, const char*, size_t); +DEFINE_IFUNC_FOR(strncmp) { + RETURN_FUNC(strncmp_func, strncmp_vext); +} + +typedef char* strncpy_func(char*, const char*, size_t); +DEFINE_IFUNC_FOR(strncpy) { + RETURN_FUNC(strncpy_func, strncpy_vext); +} + +typedef size_t strnlen_func(const char*, size_t); +DEFINE_IFUNC_FOR(strnlen) { + RETURN_FUNC(strnlen_func, strnlen_vext); +} + +} // extern "C" +#endif diff --git a/libc/arch-riscv64/static_function_dispatch.S b/libc/arch-riscv64/static_function_dispatch.S new file mode 100644 index 000000000..3bf02754d --- /dev/null +++ b/libc/arch-riscv64/static_function_dispatch.S @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <private/bionic_asm.h> + +#define FUNCTION_DELEGATE(name, impl) \ +ENTRY(name); \ + j impl; \ +END(name) + +#if defined(__riscv_v) + +FUNCTION_DELEGATE(memchr, memchr_vext) +FUNCTION_DELEGATE(memcmp, memcmp_vext) +FUNCTION_DELEGATE(memcpy, memcpy_vext) +FUNCTION_DELEGATE(memmove, memmove_vext) +FUNCTION_DELEGATE(memset, memset_vext) +FUNCTION_DELEGATE(strcat, strcat_vext) +FUNCTION_DELEGATE(strchr, strchr_vext) +FUNCTION_DELEGATE(strcmp, strcmp_vext) +FUNCTION_DELEGATE(strcpy, strcpy_vext) +FUNCTION_DELEGATE(strlen, strlen_vext) +FUNCTION_DELEGATE(strncat, strncat_vext) +FUNCTION_DELEGATE(strncmp, strncmp_vext) +FUNCTION_DELEGATE(strncpy, strncpy_vext) +FUNCTION_DELEGATE(strnlen, strnlen_vext) + +#endif + +NOTE_GNU_PROPERTY() diff --git a/libc/arch-riscv64/string/memchr_vext.S b/libc/arch-riscv64/string/memchr_vext.S new file mode 100644 index 000000000..376126588 --- /dev/null +++ b/libc/arch-riscv64/string/memchr_vext.S @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define iResult a0 + +#define pSrc a0 +#define iValue a1 +#define iNum a2 + +#define iVL a3 +#define iTemp a4 + +#define ELEM_LMUL_SETTING m8 +#define vData v0 +#define vMask v8 + +ENTRY(memchr_vext) + +L(loop): + vsetvli iVL, iNum, e8, ELEM_LMUL_SETTING, ta, ma + + vle8ff.v vData, (pSrc) + vmseq.vx vMask, vData, iValue + vfirst.m iTemp, vMask + + # skip the loop if we find the matched value. + bgez iTemp, L(found) + + csrr iVL, vl + sub iNum, iNum, iVL + add pSrc, pSrc, iVL + + bnez iNum, L(loop) + + li iResult, 0 + ret + +L(found): + add iResult, pSrc, iTemp + ret + +END(memchr_vext) + +#endif diff --git a/libc/arch-riscv64/string/memcmp_vext.S b/libc/arch-riscv64/string/memcmp_vext.S new file mode 100644 index 000000000..d8e7a0692 --- /dev/null +++ b/libc/arch-riscv64/string/memcmp_vext.S @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define iResult a0 + +#define pSrc1 a0 +#define pSrc2 a1 +#define iNum a2 + +#define iVL a3 +#define iTemp a4 +#define iTemp1 a5 +#define iTemp2 a6 + +#define ELEM_LMUL_SETTING m8 +#define vData1 v0 +#define vData2 v8 +#define vMask v16 + +ENTRY(memcmp_vext) + +L(loop): + vsetvli iVL, iNum, e8, ELEM_LMUL_SETTING, ta, ma + + vle8.v vData1, (pSrc1) + vle8.v vData2, (pSrc2) + + vmsne.vv vMask, vData1, vData2 + sub iNum, iNum, iVL + vfirst.m iTemp, vMask + + /* skip the loop if we find the different + value between pSrc1 and pSrc2. */ + bgez iTemp, L(found) + + add pSrc1, pSrc1, iVL + add pSrc2, pSrc2, iVL + + bnez iNum, L(loop) + + li iResult, 0 + ret + +L(found): + add pSrc1, pSrc1, iTemp + add pSrc2, pSrc2, iTemp + lbu iTemp1, 0(pSrc1) + lbu iTemp2, 0(pSrc2) + sub iResult, iTemp1, iTemp2 + ret + +END(memcmp_vext) + +#endif diff --git a/libc/arch-riscv64/string/memcpy_vext.S b/libc/arch-riscv64/string/memcpy_vext.S new file mode 100644 index 000000000..100f538c0 --- /dev/null +++ b/libc/arch-riscv64/string/memcpy_vext.S @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define pDst a0 +#define pSrc a1 +#define iNum a2 + +#define iVL a3 +#define pDstPtr a4 + +#define ELEM_LMUL_SETTING m8 +#define vData v0 + +ENTRY(memcpy_vext) + + mv pDstPtr, pDst + +L(loop): + vsetvli iVL, iNum, e8, ELEM_LMUL_SETTING, ta, ma + + vle8.v vData, (pSrc) + sub iNum, iNum, iVL + add pSrc, pSrc, iVL + vse8.v vData, (pDstPtr) + add pDstPtr, pDstPtr, iVL + + bnez iNum, L(loop) + + ret + +END(memcpy_vext) + +#endif diff --git a/libc/arch-riscv64/string/memmove_vext.S b/libc/arch-riscv64/string/memmove_vext.S new file mode 100644 index 000000000..722ffd118 --- /dev/null +++ b/libc/arch-riscv64/string/memmove_vext.S @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define pDst a0 +#define pSrc a1 +#define iNum a2 + +#define iVL a3 +#define pDstPtr a4 +#define pSrcBackwardPtr a5 +#define pDstBackwardPtr a6 + +#define ELEM_LMUL_SETTING m8 +#define vData v0 + +ENTRY(memmove_vext) + + mv pDstPtr, pDst + + bgeu pSrc, pDst, L(forward_copy_loop) + add pSrcBackwardPtr, pSrc, iNum + add pDstBackwardPtr, pDst, iNum + bltu pDst, pSrcBackwardPtr, L(backward_copy_loop) + +L(forward_copy_loop): + vsetvli iVL, iNum, e8, ELEM_LMUL_SETTING, ta, ma + + vle8.v vData, (pSrc) + sub iNum, iNum, iVL + add pSrc, pSrc, iVL + vse8.v vData, (pDstPtr) + add pDstPtr, pDstPtr, iVL + + bnez iNum, L(forward_copy_loop) + ret + +L(backward_copy_loop): + vsetvli iVL, iNum, e8, ELEM_LMUL_SETTING, ta, ma + + sub pSrcBackwardPtr, pSrcBackwardPtr, iVL + vle8.v vData, (pSrcBackwardPtr) + sub iNum, iNum, iVL + sub pDstBackwardPtr, pDstBackwardPtr, iVL + vse8.v vData, (pDstBackwardPtr) + bnez iNum, L(backward_copy_loop) + ret + +END(memmove_vext) + +#endif diff --git a/libc/arch-riscv64/string/memset_vext.S b/libc/arch-riscv64/string/memset_vext.S new file mode 100644 index 000000000..ef8387dbd --- /dev/null +++ b/libc/arch-riscv64/string/memset_vext.S @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define pDst a0 +#define iValue a1 +#define iNum a2 + +#define iVL a3 +#define iTemp a4 +#define pDstPtr a5 + +#define ELEM_LMUL_SETTING m8 +#define vData v0 + +ENTRY(memset_vext) + + mv pDstPtr, pDst + + vsetvli iVL, iNum, e8, ELEM_LMUL_SETTING, ta, ma + vmv.v.x vData, iValue + +L(loop): + vse8.v vData, (pDstPtr) + sub iNum, iNum, iVL + add pDstPtr, pDstPtr, iVL + vsetvli iVL, iNum, e8, ELEM_LMUL_SETTING, ta, ma + bnez iNum, L(loop) + + ret + +END(memset_vext) + +#endif diff --git a/libc/arch-riscv64/string/strcat_vext.S b/libc/arch-riscv64/string/strcat_vext.S new file mode 100644 index 000000000..790c07ab2 --- /dev/null +++ b/libc/arch-riscv64/string/strcat_vext.S @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define pDst a0 +#define pSrc a1 +#define pDstPtr a2 + +#define iVL a3 +#define iCurrentVL a4 +#define iActiveElemPos a5 + +#define ELEM_LMUL_SETTING m1 +#define vMask1 v0 +#define vMask2 v1 +#define vStr1 v8 +#define vStr2 v16 + +ENTRY(strcat_vext) + + mv pDstPtr, pDst + + // the strlen of dst +L(strlen_loop): + vsetvli iVL, zero, e8, ELEM_LMUL_SETTING, ta, ma + + vle8ff.v vStr1, (pDstPtr) + // find the '\0' + vmseq.vx vMask1, vStr1, zero + csrr iCurrentVL, vl + vfirst.m iActiveElemPos, vMask1 + add pDstPtr, pDstPtr, iCurrentVL + bltz iActiveElemPos, L(strlen_loop) + + sub pDstPtr, pDstPtr, iCurrentVL + add pDstPtr, pDstPtr, iActiveElemPos + + // copy pSrc to pDstPtr +L(strcpy_loop): + vsetvli iVL, zero, e8, ELEM_LMUL_SETTING, ta, ma + + vle8ff.v vStr1, (pSrc) + vmseq.vx vMask2, vStr1, zero + csrr iCurrentVL, vl + vfirst.m iActiveElemPos, vMask2 + vmsif.m vMask1, vMask2 + add pSrc, pSrc, iCurrentVL + vse8.v vStr1, (pDstPtr), vMask1.t + add pDstPtr, pDstPtr, iCurrentVL + bltz iActiveElemPos, L(strcpy_loop) + + ret + +END(strcat_vext) + +#endif diff --git a/libc/arch-riscv64/string/strchr_vext.S b/libc/arch-riscv64/string/strchr_vext.S new file mode 100644 index 000000000..89828eafa --- /dev/null +++ b/libc/arch-riscv64/string/strchr_vext.S @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define pStr a0 +#define iCh a1 +#define iEndOffset a2 +#define iChOffset a3 +#define iTemp1 a4 +#define iTemp2 a5 +#define iCurrentVL a6 +#define iVL t0 + +#define ELEM_LMUL_SETTING m1 +#define vStr v0 +#define vMaskEnd v8 +#define vMaskCh v9 + +ENTRY(strchr_vext) + +L(strchr_loop): + vsetvli iVL, zero, e8, ELEM_LMUL_SETTING, ta, ma + vle8ff.v vStr, (pStr) + vmseq.vi vMaskEnd, vStr, 0 + vmseq.vx vMaskCh, vStr, iCh + vfirst.m iEndOffset, vMaskEnd /* first occurrence of \0 */ + vfirst.m iChOffset, vMaskCh /* first occurrence of ch */ + sltz iTemp1, iChOffset + sltu iTemp2, iEndOffset, iChOffset + or iTemp1, iTemp1, iTemp2 + beqz iTemp1, L(found_ch) /* Found ch, not preceded by \0? */ + csrr iCurrentVL, vl + add pStr, pStr, iCurrentVL + bltz iEndOffset, L(strchr_loop) /* Didn't find \0? */ + li pStr, 0 + ret +L(found_ch): + add pStr, pStr, iChOffset + ret + +END(strchr_vext) + +#endif diff --git a/libc/arch-riscv64/string/strcmp_vext.S b/libc/arch-riscv64/string/strcmp_vext.S new file mode 100644 index 000000000..d6ad96e4d --- /dev/null +++ b/libc/arch-riscv64/string/strcmp_vext.S @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define iResult a0 + +#define pStr1 a0 +#define pStr2 a1 + +#define iVL a2 +#define iTemp1 a3 +#define iTemp2 a4 +#define iLMUL1 a5 +#define iLMUL2 a6 +#define iLMUL4 a7 + +#define iLMUL t0 + +#define vStr1 v0 +#define vStr2 v8 +#define vMask1 v16 +#define vMask2 v17 + +ENTRY(strcmp_vext) + + # increase the lmul using the following sequences: + # 1/2, 1/2, 1, 2, 4, 4, 4, ... + + # lmul=1/2 + vsetvli iVL, zero, e8, mf2, ta, ma + + vle8ff.v vStr1, (pStr1) + # check if vStr1[i] == 0 + vmseq.vx vMask1, vStr1, zero + + vle8ff.v vStr2, (pStr2) + # check if vStr1[i] != vStr2[i] + vmsne.vv vMask2, vStr1, vStr2 + + # find the index x for vStr1[x]==0 + vfirst.m iTemp1, vMask1 + # find the index x for vStr1[x]!=vStr2[x] + vfirst.m iTemp2, vMask2 + + bgez iTemp1, L(check1) + bgez iTemp2, L(check2) + + # get the current vl updated by vle8ff. + csrr iVL, vl + add pStr1, pStr1, iVL + add pStr2, pStr2, iVL + + vsetvli iVL, zero, e8, mf2, ta, ma + addi iLMUL1, zero, 1 + addi iLMUL, zero, 1 + j L(loop) +L(m1): + vsetvli iVL, zero, e8, m1, ta, ma + addi iLMUL2, zero, 2 + addi iLMUL, zero, 2 + j L(loop) +L(m2): + vsetvli iVL, zero, e8, m2, ta, ma + addi iLMUL4, zero, 4 + addi iLMUL, zero, 4 + j L(loop) +L(m4): + vsetvli iVL, zero, e8, m4, ta, ma + +L(loop): + vle8ff.v vStr1, (pStr1) + vmseq.vx vMask1, vStr1, zero + + vle8ff.v vStr2, (pStr2) + vmsne.vv vMask2, vStr1, vStr2 + + vfirst.m iTemp1, vMask1 + vfirst.m iTemp2, vMask2 + + bgez iTemp1, L(check1) + bgez iTemp2, L(check2) + + csrr iVL, vl + add pStr1, pStr1, iVL + add pStr2, pStr2, iVL + + beq iLMUL, iLMUL1, L(m1) + beq iLMUL, iLMUL2, L(m2) + beq iLMUL, iLMUL4, L(m4) + j L(loop) + + // iTemp1>=0 +L(check1): + bltz iTemp2, 1f + blt iTemp2, iTemp1, L(check2) +1: + // iTemp2<0 + // iTemp2>=0 && iTemp1<iTemp2 + add pStr1, pStr1, iTemp1 + add pStr2, pStr2, iTemp1 + lbu iTemp1, 0(pStr1) + lbu iTemp2, 0(pStr2) + sub iResult, iTemp1, iTemp2 + ret + + // iTemp1<0 + // iTemp2>=0 +L(check2): + add pStr1, pStr1, iTemp2 + add pStr2, pStr2, iTemp2 + lbu iTemp1, 0(pStr1) + lbu iTemp2, 0(pStr2) + sub iResult, iTemp1, iTemp2 + ret + +END(strcmp_vext) + +#endif diff --git a/libc/arch-riscv64/string/strcpy_vext.S b/libc/arch-riscv64/string/strcpy_vext.S new file mode 100644 index 000000000..9c11f7df4 --- /dev/null +++ b/libc/arch-riscv64/string/strcpy_vext.S @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define pDst a0 +#define pSrc a1 +#define pDstPtr a2 + +#define iVL a3 +#define iCurrentVL a4 +#define iActiveElemPos a5 + +#define ELEM_LMUL_SETTING m1 +#define vMask1 v0 +#define vMask2 v1 +#define vStr1 v8 +#define vStr2 v16 + +ENTRY(strcpy_vext) + + mv pDstPtr, pDst + + // copy pSrc to pDstPtr +L(strcpy_loop): + vsetvli iVL, zero, e8, ELEM_LMUL_SETTING, ta, ma + vle8ff.v vStr1, (pSrc) + vmseq.vx vMask2, vStr1, zero + csrr iCurrentVL, vl + vfirst.m iActiveElemPos, vMask2 + vmsif.m vMask1, vMask2 + add pSrc, pSrc, iCurrentVL + vse8.v vStr1, (pDstPtr), vMask1.t + add pDstPtr, pDstPtr, iCurrentVL + bltz iActiveElemPos, L(strcpy_loop) + + ret + +END(strcpy_vext) + +#endif diff --git a/libc/arch-riscv64/string/strlen_vext.S b/libc/arch-riscv64/string/strlen_vext.S new file mode 100644 index 000000000..393af58b6 --- /dev/null +++ b/libc/arch-riscv64/string/strlen_vext.S @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define iResult a0 +#define pStr a0 +#define pCopyStr a1 +#define iVL a2 +#define iCurrentVL a2 +#define iEndOffset a3 + +#define ELEM_LMUL_SETTING m2 +#define vStr v0 +#define vMaskEnd v2 + +ENTRY(strlen_vext) + + mv pCopyStr, pStr +L(loop): + vsetvli iVL, zero, e8, ELEM_LMUL_SETTING, ta, ma + vle8ff.v vStr, (pCopyStr) + csrr iCurrentVL, vl + vmseq.vi vMaskEnd, vStr, 0 + vfirst.m iEndOffset, vMaskEnd + add pCopyStr, pCopyStr, iCurrentVL + bltz iEndOffset, L(loop) + + add pStr, pStr, iCurrentVL + add pCopyStr, pCopyStr, iEndOffset + sub iResult, pCopyStr, iResult + + ret + +END(strlen) + +#endif diff --git a/libc/arch-riscv64/string/strncat_vext.S b/libc/arch-riscv64/string/strncat_vext.S new file mode 100644 index 000000000..e9da434f1 --- /dev/null +++ b/libc/arch-riscv64/string/strncat_vext.S @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define pDst a0 +#define pSrc a1 +#define iLength a2 +#define pDstPtr a3 + +#define iVL a4 +#define iCurrentVL a5 +#define iActiveElemPos a6 + +#define ELEM_LMUL_SETTING m1 +#define vMask1 v0 +#define vMask2 v1 +#define vStr1 v8 +#define vStr2 v16 + +ENTRY(strncat_vext) + + mv pDstPtr, pDst + + // the strlen of dst +L(strlen_loop): + vsetvli iVL, zero, e8, ELEM_LMUL_SETTING, ta, ma + + vle8ff.v vStr1, (pDstPtr) + // find the '\0' + vmseq.vx vMask1, vStr1, zero + csrr iCurrentVL, vl + vfirst.m iActiveElemPos, vMask1 + add pDstPtr, pDstPtr, iCurrentVL + bltz iActiveElemPos, L(strlen_loop) + + sub pDstPtr, pDstPtr, iCurrentVL + add pDstPtr, pDstPtr, iActiveElemPos + + // copy pSrc to pDstPtr +L(strcpy_loop): + vsetvli iVL, iLength, e8, ELEM_LMUL_SETTING, ta, ma + + vle8ff.v vStr1, (pSrc) + vmseq.vx vMask2, vStr1, zero + csrr iCurrentVL, vl + vfirst.m iActiveElemPos, vMask2 + vmsif.m vMask1, vMask2 + add pSrc, pSrc, iCurrentVL + sub iLength, iLength, iCurrentVL + vse8.v vStr1, (pDstPtr), vMask1.t + add pDstPtr, pDstPtr, iCurrentVL + beqz iLength, L(fill_zero) + bltz iActiveElemPos, L(strcpy_loop) + + ret + +L(fill_zero): + bgez iActiveElemPos, L(fill_zero_end) + sb zero, (pDstPtr) + +L(fill_zero_end): + ret + +END(strncat_vext) + +#endif diff --git a/libc/arch-riscv64/string/strncmp_vext.S b/libc/arch-riscv64/string/strncmp_vext.S new file mode 100644 index 000000000..88f0f3e9c --- /dev/null +++ b/libc/arch-riscv64/string/strncmp_vext.S @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define iResult a0 + +#define pStr1 a0 +#define pStr2 a1 +#define iLength a2 + +#define iVL a3 +#define iTemp1 a4 +#define iTemp2 a5 + +#define ELEM_LMUL_SETTING m1 +#define vStr1 v0 +#define vStr2 v4 +#define vMask1 v8 +#define vMask2 v9 + +ENTRY(strncmp_vext) + + beqz iLength, L(zero_length) + +L(loop): + vsetvli iVL, iLength, e8, ELEM_LMUL_SETTING, ta, ma + + vle8ff.v vStr1, (pStr1) + # vStr1[i] == 0 + vmseq.vx vMask1, vStr1, zero + + vle8ff.v vStr2, (pStr2) + # vStr1[i] != vStr2[i] + vmsne.vv vMask2, vStr1, vStr2 + + csrr iVL, vl + + # r = mask1 | mask2 + # We could use vfirst.m to get the first zero char or the + # first different char between str1 and str2. + vmor.mm vMask1, vMask1, vMask2 + + sub iLength, iLength, iVL + + vfirst.m iTemp1, vMask1 + + bgez iTemp1, L(end_loop) + + add pStr1, pStr1, iVL + add pStr2, pStr2, iVL + bnez iLength, L(loop) +L(end_loop): + + add pStr1, pStr1, iTemp1 + add pStr2, pStr2, iTemp1 + lbu iTemp1, 0(pStr1) + lbu iTemp2, 0(pStr2) + + sub iResult, iTemp1, iTemp2 + ret + +L(zero_length): + li iResult, 0 + ret + +END(strncmp_vext) + +#endif diff --git a/libc/arch-riscv64/string/strncpy_vext.S b/libc/arch-riscv64/string/strncpy_vext.S new file mode 100644 index 000000000..1aedaf9cd --- /dev/null +++ b/libc/arch-riscv64/string/strncpy_vext.S @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define pDst a0 +#define pSrc a1 +#define iLength a2 +#define pDstPtr a3 + +#define iVL a4 +#define iCurrentVL a5 +#define iActiveElemPos a6 + +#define ELEM_LMUL_SETTING m1 +#define vMask1 v0 +#define vMask2 v1 +#define ZERO_FILL_ELEM_LMUL_SETTING m8 +#define vStr1 v8 +#define vStr2 v16 + +ENTRY(strncpy_vext) + + mv pDstPtr, pDst + + // copy pSrc to pDstPtr +L(strcpy_loop): + vsetvli iVL, iLength, e8, ELEM_LMUL_SETTING, ta, ma + vle8ff.v vStr1, (pSrc) + vmseq.vx vMask2, vStr1, zero + csrr iCurrentVL, vl + vfirst.m iActiveElemPos, vMask2 + vmsif.m vMask1, vMask2 + add pSrc, pSrc, iCurrentVL + sub iLength, iLength, iCurrentVL + vse8.v vStr1, (pDstPtr), vMask1.t + add pDstPtr, pDstPtr, iCurrentVL + bgez iActiveElemPos, L(fill_zero) + bnez iLength, L(strcpy_loop) + ret + + # fill the tail zero. +L(fill_zero): + sub iVL, iCurrentVL, iActiveElemPos + add iLength, iLength, iVL + bnez iLength, 1f + ret +1: + sub pDstPtr, pDstPtr, iVL + vsetvli zero, iLength, e8, ZERO_FILL_ELEM_LMUL_SETTING, ta, ma + vmv.v.x vStr2, zero + +L(fill_zero_loop): + vsetvli iVL, iLength, e8, ZERO_FILL_ELEM_LMUL_SETTING, ta, ma + vse8.v vStr2, (pDstPtr) + sub iLength, iLength, iVL + add pDstPtr, pDstPtr, iVL + bnez iLength, L(fill_zero_loop) + + ret + +END(strncpy_vext) + +#endif diff --git a/libc/arch-riscv64/string/strnlen_vext.S b/libc/arch-riscv64/string/strnlen_vext.S new file mode 100644 index 000000000..f546689bb --- /dev/null +++ b/libc/arch-riscv64/string/strnlen_vext.S @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__riscv_v) + +#include "sys/asm.h" + +#define pStr a0 +#define pCopyStr a2 +#define iRetValue a0 +#define iMaxlen a1 +#define iCurrentVL a3 +#define iEndOffset a4 + +#define ELEM_LMUL_SETTING m1 +#define vStr v0 +#define vMaskEnd v8 + +ENTRY(strnlen_vext) + + mv pCopyStr, pStr + mv iRetValue, iMaxlen +L(strnlen_loop): + beqz iMaxlen, L(end_strnlen_loop) + vsetvli zero, iMaxlen, e8, ELEM_LMUL_SETTING, ta, ma + vle8ff.v vStr, (pCopyStr) + vmseq.vi vMaskEnd, vStr, 0 + vfirst.m iEndOffset, vMaskEnd /* first occurrence of \0 */ + csrr iCurrentVL, vl + add pCopyStr, pCopyStr, iCurrentVL + sub iMaxlen, iMaxlen, iCurrentVL + bltz iEndOffset, L(strnlen_loop) + add iMaxlen, iMaxlen, iCurrentVL + sub iRetValue, iRetValue, iMaxlen + add iRetValue, iRetValue, iEndOffset +L(end_strnlen_loop): + ret + +END(strnlen_vext) + +#endif diff --git a/libc/arch-riscv64/string/sys/asm.h b/libc/arch-riscv64/string/sys/asm.h new file mode 100644 index 000000000..cc76dc515 --- /dev/null +++ b/libc/arch-riscv64/string/sys/asm.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 2023 SiFive, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY SIFIVE INC ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL SIFIVE INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_ASM_H +#define _SYS_ASM_H + +#undef LEAF +#define LEAF(symbol) \ + .globl symbol; \ + .align 2; \ + .type symbol, @function; \ + symbol: \ + .cfi_startproc; + +#undef END +#define END(function) \ + .cfi_endproc; \ + .size function, .- function + +#define ENTRY(name) LEAF(name) + +#define L(label) .L##label + +#endif /* _SYS_ASM_H */ diff --git a/libc/bionic/atexit.cpp b/libc/bionic/atexit.cpp index 5dbf322e3..dae15e0d8 100644 --- a/libc/bionic/atexit.cpp +++ b/libc/bionic/atexit.cpp @@ -73,8 +73,8 @@ class AtexitArray { // restart concurrent __cxa_finalize passes. uint64_t total_appends_; - static size_t page_start_of_index(size_t idx) { return PAGE_START(idx * sizeof(AtexitEntry)); } - static size_t page_end_of_index(size_t idx) { return PAGE_END(idx * sizeof(AtexitEntry)); } + static size_t page_start_of_index(size_t idx) { return page_start(idx * sizeof(AtexitEntry)); } + static size_t page_end_of_index(size_t idx) { return page_end(idx * sizeof(AtexitEntry)); } // Recompact the array if it will save at least one page of memory at the end. bool needs_recompaction() const { @@ -167,7 +167,7 @@ void AtexitArray::set_writable(bool writable, size_t start_idx, size_t num_entri // than one. bool AtexitArray::next_capacity(size_t capacity, size_t* result) { if (capacity == 0) { - *result = PAGE_END(sizeof(AtexitEntry)) / sizeof(AtexitEntry); + *result = page_end(sizeof(AtexitEntry)) / sizeof(AtexitEntry); return true; } size_t num_bytes; diff --git a/libc/bionic/bionic_allocator.cpp b/libc/bionic/bionic_allocator.cpp index 98183d415..53f944f84 100644 --- a/libc/bionic/bionic_allocator.cpp +++ b/libc/bionic/bionic_allocator.cpp @@ -95,12 +95,10 @@ static inline uint16_t log2(size_t number) { return result; } -BionicSmallObjectAllocator::BionicSmallObjectAllocator(uint32_t type, - size_t block_size) +BionicSmallObjectAllocator::BionicSmallObjectAllocator(uint32_t type, size_t block_size) : type_(type), block_size_(block_size), - blocks_per_page_((PAGE_SIZE - sizeof(small_object_page_info)) / - block_size), + blocks_per_page_((page_size() - sizeof(small_object_page_info)) / block_size), free_pages_cnt_(0), page_list_(nullptr) {} @@ -157,14 +155,13 @@ void BionicSmallObjectAllocator::free_page(small_object_page_info* page) { if (page_list_ == page) { page_list_ = page->next_page; } - munmap(page, PAGE_SIZE); + munmap(page, page_size()); free_pages_cnt_--; } void BionicSmallObjectAllocator::free(void* ptr) { small_object_page_info* const page = - reinterpret_cast<small_object_page_info*>( - PAGE_START(reinterpret_cast<uintptr_t>(ptr))); + reinterpret_cast<small_object_page_info*>(page_start(reinterpret_cast<uintptr_t>(ptr))); if (reinterpret_cast<uintptr_t>(ptr) % block_size_ != 0) { async_safe_fatal("invalid pointer: %p (block_size=%zd)", ptr, block_size_); @@ -192,14 +189,13 @@ void BionicSmallObjectAllocator::free(void* ptr) { } void BionicSmallObjectAllocator::alloc_page() { - void* const map_ptr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + void* const map_ptr = + mmap(nullptr, page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (map_ptr == MAP_FAILED) { async_safe_fatal("mmap failed: %s", strerror(errno)); } - prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, PAGE_SIZE, - "bionic_alloc_small_objects"); + prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, page_size(), "bionic_alloc_small_objects"); small_object_page_info* const page = reinterpret_cast<small_object_page_info*>(map_ptr); @@ -269,10 +265,10 @@ void* BionicAllocator::alloc_mmap(size_t align, size_t size) { size_t header_size = __BIONIC_ALIGN(kPageInfoSize, align); size_t allocated_size; if (__builtin_add_overflow(header_size, size, &allocated_size) || - PAGE_END(allocated_size) < allocated_size) { + page_end(allocated_size) < allocated_size) { async_safe_fatal("overflow trying to alloc %zu bytes", size); } - allocated_size = PAGE_END(allocated_size); + allocated_size = page_end(allocated_size); void* map_ptr = mmap(nullptr, allocated_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); @@ -317,7 +313,7 @@ void* BionicAllocator::alloc(size_t size) { void* BionicAllocator::memalign(size_t align, size_t size) { // The Bionic allocator only supports alignment up to one page, which is good // enough for ELF TLS. - align = MIN(align, PAGE_SIZE); + align = MIN(align, page_size()); align = MAX(align, 16); if (!powerof2(align)) { align = BIONIC_ROUND_UP_POWER_OF_2(align); @@ -327,7 +323,7 @@ void* BionicAllocator::memalign(size_t align, size_t size) { } inline page_info* BionicAllocator::get_page_info_unchecked(void* ptr) { - uintptr_t header_page = PAGE_START(reinterpret_cast<size_t>(ptr) - kPageInfoSize); + uintptr_t header_page = page_start(reinterpret_cast<size_t>(ptr) - kPageInfoSize); return reinterpret_cast<page_info*>(header_page); } diff --git a/libc/bionic/bionic_elf_tls.cpp b/libc/bionic/bionic_elf_tls.cpp index 79893e32f..077f31085 100644 --- a/libc/bionic/bionic_elf_tls.cpp +++ b/libc/bionic/bionic_elf_tls.cpp @@ -34,10 +34,11 @@ #include <sys/param.h> #include <unistd.h> +#include "platform/bionic/macros.h" +#include "platform/bionic/page.h" #include "private/ScopedRWLock.h" #include "private/ScopedSignalBlocker.h" #include "private/bionic_globals.h" -#include "platform/bionic/macros.h" #include "private/bionic_tls.h" #include "pthread_internal.h" @@ -81,7 +82,7 @@ bool __bionic_check_tls_alignment(size_t* alignment) { return false; } // Bionic only respects TLS alignment up to one page. - *alignment = MIN(*alignment, PAGE_SIZE); + *alignment = MIN(*alignment, page_size()); return true; } diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp index 6433b597d..3eb8c198b 100644 --- a/libc/bionic/fdsan.cpp +++ b/libc/bionic/fdsan.cpp @@ -40,6 +40,7 @@ #include <unistd.h> #include <async_safe/log.h> +#include <platform/bionic/page.h> #include <platform/bionic/reserved_signals.h> #include <sys/system_properties.h> @@ -80,7 +81,7 @@ FdEntry* FdTableImpl<inline_fds>::at(size_t idx) { size_t required_count = max - inline_fds; size_t required_size = sizeof(FdTableOverflow) + required_count * sizeof(FdEntry); - size_t aligned_size = __BIONIC_ALIGN(required_size, PAGE_SIZE); + size_t aligned_size = __BIONIC_ALIGN(required_size, page_size()); size_t aligned_count = (aligned_size - sizeof(FdTableOverflow)) / sizeof(FdEntry); void* allocation = diff --git a/libc/bionic/getpagesize.cpp b/libc/bionic/getpagesize.cpp index 3a5990025..da97633ca 100644 --- a/libc/bionic/getpagesize.cpp +++ b/libc/bionic/getpagesize.cpp @@ -27,9 +27,10 @@ */ #include <unistd.h> +#include "platform/bionic/page.h" // Portable code should use sysconf(_SC_PAGE_SIZE) directly instead. int getpagesize() { // We dont use sysconf(3) here because that drags in stdio, which makes static binaries fat. - return PAGE_SIZE; + return page_size(); } diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp index d64d402ab..3b0ab821b 100644 --- a/libc/bionic/libc_init_static.cpp +++ b/libc/bionic/libc_init_static.cpp @@ -129,8 +129,8 @@ static void apply_gnu_relro() { continue; } - ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr); - ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz); + ElfW(Addr) seg_page_start = page_start(phdr->p_vaddr); + ElfW(Addr) seg_page_end = page_end(phdr->p_vaddr + phdr->p_memsz); // Check return value here? What do we do if we fail? mprotect(reinterpret_cast<void*>(seg_page_start), seg_page_end - seg_page_start, PROT_READ); @@ -354,9 +354,9 @@ __attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte(const v __libc_shared_globals()->initial_memtag_stack = memtag_stack; if (memtag_stack) { - void* page_start = - reinterpret_cast<void*>(PAGE_START(reinterpret_cast<uintptr_t>(stack_top))); - if (mprotect(page_start, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_MTE | PROT_GROWSDOWN)) { + void* pg_start = + reinterpret_cast<void*>(page_start(reinterpret_cast<uintptr_t>(stack_top))); + if (mprotect(pg_start, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_MTE | PROT_GROWSDOWN)) { async_safe_fatal("error: failed to set PROT_MTE on main thread stack: %s\n", strerror(errno)); } diff --git a/libc/bionic/mmap.cpp b/libc/bionic/mmap.cpp index ed6b9c68f..f05dcb8ce 100644 --- a/libc/bionic/mmap.cpp +++ b/libc/bionic/mmap.cpp @@ -32,6 +32,7 @@ #include <unistd.h> #include "platform/bionic/macros.h" +#include "platform/bionic/page.h" #include "private/ErrnoRestorer.h" // mmap2(2) is like mmap(2), but the offset is in 4096-byte blocks, not bytes. @@ -46,7 +47,7 @@ void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offse } // Prevent allocations large enough for `end - start` to overflow. - size_t rounded = __BIONIC_ALIGN(size, PAGE_SIZE); + size_t rounded = __BIONIC_ALIGN(size, page_size()); if (rounded < size || rounded > PTRDIFF_MAX) { errno = ENOMEM; return MAP_FAILED; diff --git a/libc/bionic/mremap.cpp b/libc/bionic/mremap.cpp index d7c9353e0..88ec829de 100644 --- a/libc/bionic/mremap.cpp +++ b/libc/bionic/mremap.cpp @@ -33,12 +33,13 @@ #include <unistd.h> #include "platform/bionic/macros.h" +#include "platform/bionic/page.h" extern "C" void* __mremap(void*, size_t, size_t, int, void*); void* mremap(void* old_address, size_t old_size, size_t new_size, int flags, ...) { // prevent allocations large enough for `end - start` to overflow - size_t rounded = __BIONIC_ALIGN(new_size, PAGE_SIZE); + size_t rounded = __BIONIC_ALIGN(new_size, page_size()); if (rounded < new_size || rounded > PTRDIFF_MAX) { errno = ENOMEM; return MAP_FAILED; diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp index 89aa28966..cdae72cef 100644 --- a/libc/bionic/pthread_attr.cpp +++ b/libc/bionic/pthread_attr.cpp @@ -36,8 +36,9 @@ #include <async_safe/log.h> -#include "private/bionic_defs.h" +#include "platform/bionic/page.h" #include "private/ErrnoRestorer.h" +#include "private/bionic_defs.h" #include "pthread_internal.h" __BIONIC_WEAK_FOR_NATIVE_BRIDGE @@ -143,10 +144,10 @@ int pthread_attr_getstacksize(const pthread_attr_t* attr, size_t* stack_size) { __BIONIC_WEAK_FOR_NATIVE_BRIDGE int pthread_attr_setstack(pthread_attr_t* attr, void* stack_base, size_t stack_size) { - if ((stack_size & (PAGE_SIZE - 1) || stack_size < PTHREAD_STACK_MIN)) { + if ((stack_size & (page_size() - 1) || stack_size < PTHREAD_STACK_MIN)) { return EINVAL; } - if (reinterpret_cast<uintptr_t>(stack_base) & (PAGE_SIZE - 1)) { + if (reinterpret_cast<uintptr_t>(stack_base) & (page_size() - 1)) { return EINVAL; } attr->stack_base = stack_base; diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp index 844f9d8f3..b46c6cfed 100644 --- a/libc/bionic/pthread_create.cpp +++ b/libc/bionic/pthread_create.cpp @@ -42,6 +42,7 @@ #include "platform/bionic/macros.h" #include "platform/bionic/mte.h" +#include "platform/bionic/page.h" #include "private/ErrnoRestorer.h" #include "private/ScopedRWLock.h" #include "private/bionic_constants.h" @@ -71,7 +72,7 @@ void __init_bionic_tls_ptrs(bionic_tcb* tcb, bionic_tls* tls) { // Allocate a temporary bionic_tls that the dynamic linker's main thread can // use while it's loading the initial set of ELF modules. bionic_tls* __allocate_temp_bionic_tls() { - size_t allocation_size = __BIONIC_ALIGN(sizeof(bionic_tls), PAGE_SIZE); + size_t allocation_size = __BIONIC_ALIGN(sizeof(bionic_tls), page_size()); void* allocation = mmap(nullptr, allocation_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, @@ -84,7 +85,7 @@ bionic_tls* __allocate_temp_bionic_tls() { } void __free_temp_bionic_tls(bionic_tls* tls) { - munmap(tls, __BIONIC_ALIGN(sizeof(bionic_tls), PAGE_SIZE)); + munmap(tls, __BIONIC_ALIGN(sizeof(bionic_tls), page_size())); } static void __init_alternate_signal_stack(pthread_internal_t* thread) { @@ -203,12 +204,11 @@ int __init_thread(pthread_internal_t* thread) { return 0; } - // Allocate a thread's primary mapping. This mapping includes static TLS and // optionally a stack. Static TLS includes ELF TLS segments and the bionic_tls // struct. // -// The stack_guard_size must be a multiple of the PAGE_SIZE. +// The stack_guard_size must be a multiple of the page_size(). ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_size) { const StaticTlsLayout& layout = __libc_shared_globals()->static_tls_layout; @@ -220,7 +220,7 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si // Align the result to a page size. const size_t unaligned_size = mmap_size; - mmap_size = __BIONIC_ALIGN(mmap_size, PAGE_SIZE); + mmap_size = __BIONIC_ALIGN(mmap_size, page_size()); if (mmap_size < unaligned_size) return {}; // Create a new private anonymous map. Make the entire mapping PROT_NONE, then carve out a @@ -271,9 +271,9 @@ static int __allocate_thread(pthread_attr_t* attr, bionic_tcb** tcbp, void** chi if (attr->stack_base == nullptr) { // The caller didn't provide a stack, so allocate one. - // Make sure the guard size is a multiple of PAGE_SIZE. + // Make sure the guard size is a multiple of page_size(). const size_t unaligned_guard_size = attr->guard_size; - attr->guard_size = __BIONIC_ALIGN(attr->guard_size, PAGE_SIZE); + attr->guard_size = __BIONIC_ALIGN(attr->guard_size, page_size()); if (attr->guard_size < unaligned_guard_size) return EAGAIN; mapping = __allocate_thread_mapping(attr->stack_size, attr->guard_size); diff --git a/libc/bionic/strtold.cpp b/libc/bionic/strtold.cpp index 6b673e6e0..c55dd61c0 100644 --- a/libc/bionic/strtold.cpp +++ b/libc/bionic/strtold.cpp @@ -26,8 +26,6 @@ * SUCH DAMAGE. */ -#define __BIONIC_LP32_USE_LONG_DOUBLE - #include <float.h> #include <stdlib.h> diff --git a/libc/bionic/sysconf.cpp b/libc/bionic/sysconf.cpp index 1c06c9efc..3906e2ef3 100644 --- a/libc/bionic/sysconf.cpp +++ b/libc/bionic/sysconf.cpp @@ -38,6 +38,7 @@ #include <time.h> #include <unistd.h> +#include "platform/bionic/page.h" #include "private/bionic_tls.h" static long __sysconf_rlimit(int resource) { diff --git a/libc/bionic/sysinfo.cpp b/libc/bionic/sysinfo.cpp index 1e4a0e855..79fd55e01 100644 --- a/libc/bionic/sysinfo.cpp +++ b/libc/bionic/sysinfo.cpp @@ -33,8 +33,9 @@ #include <string.h> #include <unistd.h> -#include "private/get_cpu_count_from_string.h" +#include "platform/bionic/page.h" #include "private/ScopedReaddir.h" +#include "private/get_cpu_count_from_string.h" int __get_cpu_count(const char* sys_file) { int cpu_count = 1; @@ -64,11 +65,11 @@ int get_nprocs() { long get_phys_pages() { struct sysinfo si; sysinfo(&si); - return (static_cast<int64_t>(si.totalram) * si.mem_unit) / PAGE_SIZE; + return (static_cast<int64_t>(si.totalram) * si.mem_unit) / page_size(); } long get_avphys_pages() { struct sysinfo si; sysinfo(&si); - return ((static_cast<int64_t>(si.freeram) + si.bufferram) * si.mem_unit) / PAGE_SIZE; + return ((static_cast<int64_t>(si.freeram) + si.bufferram) * si.mem_unit) / page_size(); } diff --git a/libc/bionic/wcstod.cpp b/libc/bionic/wcstod.cpp index 75a59f554..c82d7882e 100644 --- a/libc/bionic/wcstod.cpp +++ b/libc/bionic/wcstod.cpp @@ -26,8 +26,6 @@ * SUCH DAMAGE. */ -#define __BIONIC_LP32_USE_LONG_DOUBLE - #include <wchar.h> #include <stdlib.h> diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h index efe4354cb..08fe45dfd 100644 --- a/libc/include/android/versioning.h +++ b/libc/include/android/versioning.h @@ -26,9 +26,6 @@ #define __REMOVED_IN(api_level) __attribute__((annotate("obsoleted_in=" #api_level))) #define __INTRODUCED_IN_32(api_level) __attribute__((annotate("introduced_in_32=" #api_level))) #define __INTRODUCED_IN_64(api_level) __attribute__((annotate("introduced_in_64=" #api_level))) -#define __INTRODUCED_IN_ARM(api_level) __attribute__((annotate("introduced_in_arm=" #api_level))) -#define __INTRODUCED_IN_X86(api_level) __attribute__((annotate("introduced_in_x86=" #api_level))) -#define __INTRODUCED_IN_X86_NO_GUARD_FOR_NDK(api_level) __attribute__((annotate("introduced_in_x86=" #api_level))) __VERSIONER_NO_GUARD #define __VERSIONER_NO_GUARD __attribute__((annotate("versioner_no_guard"))) #define __VERSIONER_FORTIFY_INLINE __attribute__((annotate("versioner_fortify_inline"))) @@ -52,11 +49,9 @@ #if defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__) #define __BIONIC_AVAILABILITY(__what) __attribute__((__availability__(android,__what))) #define __INTRODUCED_IN_NO_GUARD_FOR_NDK(api_level) __INTRODUCED_IN(api_level) -#define __INTRODUCED_IN_X86_NO_GUARD_FOR_NDK(api_level) __INTRODUCED_IN_X86(api_level) #else #define __BIONIC_AVAILABILITY(__what) __attribute__((__availability__(android,strict,__what))) #define __INTRODUCED_IN_NO_GUARD_FOR_NDK(api_level) -#define __INTRODUCED_IN_X86_NO_GUARD_FOR_NDK(api_level) #endif #define __INTRODUCED_IN(api_level) __BIONIC_AVAILABILITY(introduced=api_level) @@ -69,12 +64,6 @@ // // void foo() __INTRODUCED_IN_32(30) __INTRODUCED_IN_64(31); // -// This also takes the advantage of the fact that we never use bitness-specific macro with -// arch-specific macro. In other words, -// -// void foo() __INTRODUCED_IN_ARM(30) __INTRODUCED_IN_64(31); -// -// hasn't been supported and won't be. #if !defined(__LP64__) #define __INTRODUCED_IN_32(api_level) __BIONIC_AVAILABILITY(introduced=api_level) #define __INTRODUCED_IN_64(api_level) @@ -83,17 +72,6 @@ #define __INTRODUCED_IN_64(api_level) __BIONIC_AVAILABILITY(introduced=api_level) #endif -#if defined(__arm__) || defined(__aarch64__) -#define __INTRODUCED_IN_ARM(api_level) __BIONIC_AVAILABILITY(introduced=api_level) -#define __INTRODUCED_IN_X86(api_level) -#elif defined(__i386__) || defined(__x86_64__) -#define __INTRODUCED_IN_ARM(api_level) -#define __INTRODUCED_IN_X86(api_level) __BIONIC_AVAILABILITY(introduced=api_level) -#else -#define __INTRODUCED_IN_ARM(api_level) -#define __INTRODUCED_IN_X86(api_level) -#endif - #define __VERSIONER_NO_GUARD #define __VERSIONER_FORTIFY_INLINE diff --git a/libc/include/bits/fortify/fcntl.h b/libc/include/bits/fortify/fcntl.h index 1f6ebad71..ce600ff58 100644 --- a/libc/include/bits/fortify/fcntl.h +++ b/libc/include/bits/fortify/fcntl.h @@ -30,13 +30,13 @@ #error "Never include this file directly; instead, include <fcntl.h>" #endif -int __open_2(const char*, int) __INTRODUCED_IN(17); -int __openat_2(int, const char*, int) __INTRODUCED_IN(17); +int __open_2(const char* _Nonnull, int) __INTRODUCED_IN(17); +int __openat_2(int, const char* _Nonnull, int) __INTRODUCED_IN(17); /* * These are the easiest way to call the real open even in clang FORTIFY. */ -int __open_real(const char*, int, ...) __RENAME(open); -int __openat_real(int, const char*, int, ...) __RENAME(openat); +int __open_real(const char* _Nonnull, int, ...) __RENAME(open); +int __openat_real(int, const char* _Nonnull, int, ...) __RENAME(openat); #if defined(__BIONIC_FORTIFY) #define __open_too_many_args_error "too many arguments" @@ -46,7 +46,7 @@ int __openat_real(int, const char*, int, ...) __RENAME(openat); #define __open_modes_useful(flags) (((flags) & O_CREAT) || ((flags) & O_TMPFILE) == O_TMPFILE) __BIONIC_ERROR_FUNCTION_VISIBILITY -int open(const char* pathname, int flags, mode_t modes, ...) __overloadable +int open(const char* _Nonnull pathname, int flags, mode_t modes, ...) __overloadable __errorattr(__open_too_many_args_error); /* @@ -56,7 +56,7 @@ int open(const char* pathname, int flags, mode_t modes, ...) __overloadable * open(const char *, int, ...). */ __BIONIC_FORTIFY_INLINE -int open(const char* const __pass_object_size pathname, int flags) +int open(const char* _Nonnull const __pass_object_size pathname, int flags) __overloadable __clang_error_if(__open_modes_useful(flags), "'open' " __open_too_few_args_error) { #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED @@ -67,7 +67,7 @@ int open(const char* const __pass_object_size pathname, int flags) } __BIONIC_FORTIFY_INLINE -int open(const char* const __pass_object_size pathname, int flags, mode_t modes) +int open(const char* _Nonnull const __pass_object_size pathname, int flags, mode_t modes) __overloadable __clang_warning_if(!__open_modes_useful(flags) && modes, "'open' " __open_useless_modes_warning) { @@ -75,12 +75,12 @@ int open(const char* const __pass_object_size pathname, int flags, mode_t modes) } __BIONIC_ERROR_FUNCTION_VISIBILITY -int openat(int dirfd, const char* pathname, int flags, mode_t modes, ...) +int openat(int dirfd, const char* _Nonnull pathname, int flags, mode_t modes, ...) __overloadable __errorattr(__open_too_many_args_error); __BIONIC_FORTIFY_INLINE -int openat(int dirfd, const char* const __pass_object_size pathname, int flags) +int openat(int dirfd, const char* _Nonnull const __pass_object_size pathname, int flags) __overloadable __clang_error_if(__open_modes_useful(flags), "'openat' " __open_too_few_args_error) { #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED @@ -91,7 +91,7 @@ int openat(int dirfd, const char* const __pass_object_size pathname, int flags) } __BIONIC_FORTIFY_INLINE -int openat(int dirfd, const char* const __pass_object_size pathname, int flags, mode_t modes) +int openat(int dirfd, const char* _Nonnull const __pass_object_size pathname, int flags, mode_t modes) __overloadable __clang_warning_if(!__open_modes_useful(flags) && modes, "'openat' " __open_useless_modes_warning) { @@ -101,18 +101,18 @@ int openat(int dirfd, const char* const __pass_object_size pathname, int flags, /* Note that open == open64, so we reuse those bits in the open64 variants below. */ __BIONIC_ERROR_FUNCTION_VISIBILITY -int open64(const char* pathname, int flags, mode_t modes, ...) __overloadable +int open64(const char* _Nonnull pathname, int flags, mode_t modes, ...) __overloadable __errorattr(__open_too_many_args_error); __BIONIC_FORTIFY_INLINE -int open64(const char* const __pass_object_size pathname, int flags) +int open64(const char* _Nonnull const __pass_object_size pathname, int flags) __overloadable __clang_error_if(__open_modes_useful(flags), "'open64' " __open_too_few_args_error) { return open(pathname, flags); } __BIONIC_FORTIFY_INLINE -int open64(const char* const __pass_object_size pathname, int flags, mode_t modes) +int open64(const char* _Nonnull const __pass_object_size pathname, int flags, mode_t modes) __overloadable __clang_warning_if(!__open_modes_useful(flags) && modes, "'open64' " __open_useless_modes_warning) { @@ -120,19 +120,19 @@ int open64(const char* const __pass_object_size pathname, int flags, mode_t mode } __BIONIC_ERROR_FUNCTION_VISIBILITY -int openat64(int dirfd, const char* pathname, int flags, mode_t modes, ...) +int openat64(int dirfd, const char* _Nonnull pathname, int flags, mode_t modes, ...) __overloadable __errorattr(__open_too_many_args_error); __BIONIC_FORTIFY_INLINE -int openat64(int dirfd, const char* const __pass_object_size pathname, int flags) +int openat64(int dirfd, const char* _Nonnull const __pass_object_size pathname, int flags) __overloadable __clang_error_if(__open_modes_useful(flags), "'openat64' " __open_too_few_args_error) { return openat(dirfd, pathname, flags); } __BIONIC_FORTIFY_INLINE -int openat64(int dirfd, const char* const __pass_object_size pathname, int flags, mode_t modes) +int openat64(int dirfd, const char* _Nonnull const __pass_object_size pathname, int flags, mode_t modes) __overloadable __clang_warning_if(!__open_modes_useful(flags) && modes, "'openat64' " __open_useless_modes_warning) { diff --git a/libc/include/bits/fortify/poll.h b/libc/include/bits/fortify/poll.h index 0b5cd4bc7..f2e27d796 100644 --- a/libc/include/bits/fortify/poll.h +++ b/libc/include/bits/fortify/poll.h @@ -30,9 +30,9 @@ #error "Never include this file directly; instead, include <poll.h>" #endif -int __poll_chk(struct pollfd*, nfds_t, int, size_t) __INTRODUCED_IN(23); -int __ppoll_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset_t*, size_t) __INTRODUCED_IN(23); -int __ppoll64_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset64_t*, size_t) __INTRODUCED_IN(28); +int __poll_chk(struct pollfd* _Nullable, nfds_t, int, size_t) __INTRODUCED_IN(23); +int __ppoll_chk(struct pollfd* _Nullable, nfds_t, const struct timespec* _Nullable, const sigset_t* _Nullable, size_t) __INTRODUCED_IN(23); +int __ppoll64_chk(struct pollfd* _Nullable, nfds_t, const struct timespec* _Nullable, const sigset64_t* _Nullable, size_t) __INTRODUCED_IN(28); #if defined(__BIONIC_FORTIFY) #define __bos_fd_count_trivially_safe(bos_val, fds, fd_count) \ @@ -40,7 +40,7 @@ int __ppoll64_chk(struct pollfd*, nfds_t, const struct timespec*, const sigset64 (fd_count) <= __BIONIC_CAST(static_cast, nfds_t, -1) / sizeof(*fds)) __BIONIC_FORTIFY_INLINE -int poll(struct pollfd* const fds __pass_object_size, nfds_t fd_count, int timeout) +int poll(struct pollfd* _Nullable const fds __pass_object_size, nfds_t fd_count, int timeout) __overloadable __clang_error_if(__bos_unevaluated_lt(__bos(fds), sizeof(*fds) * fd_count), "in call to 'poll', fd_count is larger than the given buffer") { @@ -55,7 +55,7 @@ int poll(struct pollfd* const fds __pass_object_size, nfds_t fd_count, int timeo } __BIONIC_FORTIFY_INLINE -int ppoll(struct pollfd* const fds __pass_object_size, nfds_t fd_count, const struct timespec* timeout, const sigset_t* mask) +int ppoll(struct pollfd* _Nullable const fds __pass_object_size, nfds_t fd_count, const struct timespec* _Nullable timeout, const sigset_t* _Nullable mask) __overloadable __clang_error_if(__bos_unevaluated_lt(__bos(fds), sizeof(*fds) * fd_count), "in call to 'ppoll', fd_count is larger than the given buffer") { @@ -71,7 +71,7 @@ int ppoll(struct pollfd* const fds __pass_object_size, nfds_t fd_count, const st #if __ANDROID_API__ >= 28 __BIONIC_FORTIFY_INLINE -int ppoll64(struct pollfd* const fds __pass_object_size, nfds_t fd_count, const struct timespec* timeout, const sigset64_t* mask) +int ppoll64(struct pollfd* _Nullable const fds __pass_object_size, nfds_t fd_count, const struct timespec* _Nullable timeout, const sigset64_t* _Nullable mask) __overloadable __clang_error_if(__bos_unevaluated_lt(__bos(fds), sizeof(*fds) * fd_count), "in call to 'ppoll64', fd_count is larger than the given buffer") { diff --git a/libc/include/bits/fortify/socket.h b/libc/include/bits/fortify/socket.h index 9e7df6dd3..8297580f0 100644 --- a/libc/include/bits/fortify/socket.h +++ b/libc/include/bits/fortify/socket.h @@ -30,15 +30,15 @@ #error "Never include this file directly; instead, include <sys/socket.h>" #endif -extern ssize_t __sendto_chk(int, const void*, size_t, size_t, int, const struct sockaddr*, +extern ssize_t __sendto_chk(int, const void* _Nonnull, size_t, size_t, int, const struct sockaddr* _Nullable, socklen_t) __INTRODUCED_IN(26); -ssize_t __recvfrom_chk(int, void*, size_t, size_t, int, struct sockaddr*, - socklen_t*) __INTRODUCED_IN(21); +ssize_t __recvfrom_chk(int, void* _Nullable, size_t, size_t, int, struct sockaddr* _Nullable, + socklen_t* _Nullable) __INTRODUCED_IN(21); #if defined(__BIONIC_FORTIFY) __BIONIC_FORTIFY_INLINE -ssize_t recvfrom(int fd, void* const buf __pass_object_size0, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addr_len) +ssize_t recvfrom(int fd, void* _Nullable const buf __pass_object_size0, size_t len, int flags, struct sockaddr* _Nullable src_addr, socklen_t* _Nullable addr_len) __overloadable __clang_error_if(__bos_unevaluated_lt(__bos0(buf), len), "'recvfrom' called with size bigger than buffer") { @@ -53,7 +53,7 @@ ssize_t recvfrom(int fd, void* const buf __pass_object_size0, size_t len, int fl } __BIONIC_FORTIFY_INLINE -ssize_t sendto(int fd, const void* const buf __pass_object_size0, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addr_len) +ssize_t sendto(int fd, const void* _Nonnull const buf __pass_object_size0, size_t len, int flags, const struct sockaddr* _Nullable dest_addr, socklen_t addr_len) __overloadable __clang_error_if(__bos_unevaluated_lt(__bos0(buf), len), "'sendto' called with size bigger than buffer") { @@ -68,7 +68,7 @@ ssize_t sendto(int fd, const void* const buf __pass_object_size0, size_t len, in } __BIONIC_FORTIFY_INLINE -ssize_t recv(int socket, void* const buf __pass_object_size0, size_t len, int flags) +ssize_t recv(int socket, void* _Nullable const buf __pass_object_size0, size_t len, int flags) __overloadable __clang_error_if(__bos_unevaluated_lt(__bos0(buf), len), "'recv' called with size bigger than buffer") { @@ -76,7 +76,7 @@ ssize_t recv(int socket, void* const buf __pass_object_size0, size_t len, int fl } __BIONIC_FORTIFY_INLINE -ssize_t send(int socket, const void* const buf __pass_object_size0, size_t len, int flags) +ssize_t send(int socket, const void* _Nonnull const buf __pass_object_size0, size_t len, int flags) __overloadable __clang_error_if(__bos_unevaluated_lt(__bos0(buf), len), "'send' called with size bigger than buffer") { diff --git a/libc/include/bits/fortify/stdio.h b/libc/include/bits/fortify/stdio.h index 95db0178e..578d04c4d 100644 --- a/libc/include/bits/fortify/stdio.h +++ b/libc/include/bits/fortify/stdio.h @@ -30,29 +30,29 @@ #error "Never include this file directly; instead, include <stdio.h>" #endif -char* __fgets_chk(char*, int, FILE*, size_t) __INTRODUCED_IN(17); -size_t __fread_chk(void*, size_t, size_t, FILE*, size_t) __INTRODUCED_IN(24); -size_t __fwrite_chk(const void*, size_t, size_t, FILE*, size_t) __INTRODUCED_IN(24); +char* _Nullable __fgets_chk(char* _Nonnull, int, FILE* _Nonnull, size_t) __INTRODUCED_IN(17); +size_t __fread_chk(void* _Nonnull, size_t, size_t, FILE* _Nonnull, size_t) __INTRODUCED_IN(24); +size_t __fwrite_chk(const void* _Nonnull, size_t, size_t, FILE* _Nonnull, size_t) __INTRODUCED_IN(24); #if defined(__BIONIC_FORTIFY) && !defined(__BIONIC_NO_STDIO_FORTIFY) #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED /* No diag -- clang diagnoses misuses of this on its own. */ __BIONIC_FORTIFY_INLINE __printflike(3, 0) -int vsnprintf(char* const __pass_object_size dest, size_t size, const char* format, va_list ap) +int vsnprintf(char* const __BIONIC_COMPLICATED_NULLNESS __pass_object_size dest, size_t size, const char* _Nonnull format, va_list ap) __diagnose_as_builtin(__builtin_vsnprintf, 1, 2, 3, 4) __overloadable { return __builtin___vsnprintf_chk(dest, size, 0, __bos(dest), format, ap); } __BIONIC_FORTIFY_INLINE __printflike(2, 0) -int vsprintf(char* const __pass_object_size dest, const char* format, va_list ap) __overloadable { +int vsprintf(char* const __BIONIC_COMPLICATED_NULLNESS __pass_object_size dest, const char* _Nonnull format, va_list ap) __overloadable { return __builtin___vsprintf_chk(dest, 0, __bos(dest), format, ap); } #endif __BIONIC_ERROR_FUNCTION_VISIBILITY -int sprintf(char* dest, const char* format) +int sprintf(char* __BIONIC_COMPLICATED_NULLNESS dest, const char* _Nonnull format) __overloadable __enable_if(__bos_unevaluated_lt(__bos(dest), __builtin_strlen(format)), "format string will always overflow destination buffer") @@ -60,7 +60,7 @@ int sprintf(char* dest, const char* format) #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED __BIONIC_FORTIFY_VARIADIC __printflike(2, 3) -int sprintf(char* const __pass_object_size dest, const char* format, ...) __overloadable { +int sprintf(char* const __BIONIC_COMPLICATED_NULLNESS __pass_object_size dest, const char* _Nonnull format, ...) __overloadable { va_list va; va_start(va, format); int result = __builtin___vsprintf_chk(dest, 0, __bos(dest), format, va); @@ -70,7 +70,7 @@ int sprintf(char* const __pass_object_size dest, const char* format, ...) __over /* No diag -- clang diagnoses misuses of this on its own. */ __BIONIC_FORTIFY_VARIADIC __printflike(3, 4) -int snprintf(char* const __pass_object_size dest, size_t size, const char* format, ...) +int snprintf(char* const __BIONIC_COMPLICATED_NULLNESS __pass_object_size dest, size_t size, const char* _Nonnull format, ...) __diagnose_as_builtin(__builtin_snprintf, 1, 2, 3) __overloadable { va_list va; @@ -86,7 +86,7 @@ int snprintf(char* const __pass_object_size dest, size_t size, const char* forma !__unsafe_check_mul_overflow(size, count)) __BIONIC_FORTIFY_INLINE -size_t fread(void* const __pass_object_size0 buf, size_t size, size_t count, FILE* stream) +size_t fread(void* const _Nonnull __pass_object_size0 buf, size_t size, size_t count, FILE* _Nonnull stream) __overloadable __clang_error_if(__unsafe_check_mul_overflow(size, count), "in call to 'fread', size * count overflows") @@ -103,7 +103,7 @@ size_t fread(void* const __pass_object_size0 buf, size_t size, size_t count, FIL } __BIONIC_FORTIFY_INLINE -size_t fwrite(const void* const __pass_object_size0 buf, size_t size, size_t count, FILE* stream) +size_t fwrite(const void* const _Nonnull __pass_object_size0 buf, size_t size, size_t count, FILE* _Nonnull stream) __overloadable __clang_error_if(__unsafe_check_mul_overflow(size, count), "in call to 'fwrite', size * count overflows") @@ -121,7 +121,7 @@ size_t fwrite(const void* const __pass_object_size0 buf, size_t size, size_t cou #undef __bos_trivially_ge_mul __BIONIC_FORTIFY_INLINE -char* fgets(char* const __pass_object_size dest, int size, FILE* stream) +char* _Nullable fgets(char* const _Nonnull __pass_object_size dest, int size, FILE* _Nonnull stream) __overloadable __clang_error_if(size < 0, "in call to 'fgets', size should not be negative") __clang_error_if(__bos_unevaluated_lt(__bos(dest), size), diff --git a/libc/include/bits/fortify/stdlib.h b/libc/include/bits/fortify/stdlib.h index 623be583b..b84dae474 100644 --- a/libc/include/bits/fortify/stdlib.h +++ b/libc/include/bits/fortify/stdlib.h @@ -35,7 +35,7 @@ /* PATH_MAX is unavailable without polluting the namespace, but it's always 4096 on Linux */ #define __PATH_MAX 4096 -char* realpath(const char* path, char* resolved) +char* _Nullable realpath(const char* _Nonnull path, char* _Nullable resolved) __clang_error_if(!path, "'realpath': NULL path is never correct; flipped arguments?") __clang_error_if(__bos_unevaluated_lt(__bos(resolved), __PATH_MAX), "'realpath' output parameter must be NULL or a pointer to a buffer " diff --git a/libc/include/bits/fortify/string.h b/libc/include/bits/fortify/string.h index f668b9f71..3dc1ccaf7 100644 --- a/libc/include/bits/fortify/string.h +++ b/libc/include/bits/fortify/string.h @@ -30,20 +30,20 @@ #error "Never include this file directly; instead, include <string.h>" #endif -void* __memchr_chk(const void*, int, size_t, size_t) __INTRODUCED_IN(23); -void* __memrchr_chk(const void*, int, size_t, size_t) __INTRODUCED_IN(23); -char* __stpncpy_chk2(char*, const char*, size_t, size_t, size_t) __INTRODUCED_IN(21); -char* __strncpy_chk2(char*, const char*, size_t, size_t, size_t) __INTRODUCED_IN(21); -size_t __strlcpy_chk(char*, const char*, size_t, size_t) __INTRODUCED_IN(17); -size_t __strlcat_chk(char*, const char*, size_t, size_t) __INTRODUCED_IN(17); +void* _Nullable __memchr_chk(const void* _Nonnull, int, size_t, size_t) __INTRODUCED_IN(23); +void* _Nullable __memrchr_chk(const void* _Nonnull, int, size_t, size_t) __INTRODUCED_IN(23); +char* _Nonnull __stpncpy_chk2(char* _Nonnull, const char* _Nonnull, size_t, size_t, size_t) __INTRODUCED_IN(21); +char* _Nonnull __strncpy_chk2(char* _Nonnull, const char* _Nonnull, size_t, size_t, size_t) __INTRODUCED_IN(21); +size_t __strlcpy_chk(char* _Nonnull, const char* _Nonnull, size_t, size_t) __INTRODUCED_IN(17); +size_t __strlcat_chk(char* _Nonnull, const char* _Nonnull, size_t, size_t) __INTRODUCED_IN(17); #if defined(__BIONIC_FORTIFY) -extern void* __memrchr_real(const void*, int, size_t) __RENAME(memrchr); +extern void* _Nullable __memrchr_real(const void* _Nonnull, int, size_t) __RENAME(memrchr); #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED /* No diag -- clang diagnoses misuses of this on its own. */ __BIONIC_FORTIFY_INLINE -void* memcpy(void* const dst __pass_object_size0, const void* src, size_t copy_amount) +void* _Nonnull memcpy(void* _Nonnull const dst __pass_object_size0, const void* _Nonnull src, size_t copy_amount) __diagnose_as_builtin(__builtin_memcpy, 1, 2, 3) __overloadable { return __builtin___memcpy_chk(dst, src, copy_amount, __bos0(dst)); @@ -51,7 +51,7 @@ void* memcpy(void* const dst __pass_object_size0, const void* src, size_t copy_a /* No diag -- clang diagnoses misuses of this on its own. */ __BIONIC_FORTIFY_INLINE -void* memmove(void* const dst __pass_object_size0, const void* src, size_t len) +void* _Nonnull memmove(void* _Nonnull const dst __pass_object_size0, const void* _Nonnull src, size_t len) __diagnose_as_builtin(__builtin_memmove, 1, 2, 3) __overloadable { return __builtin___memmove_chk(dst, src, len, __bos0(dst)); @@ -61,7 +61,7 @@ void* memmove(void* const dst __pass_object_size0, const void* src, size_t len) #if defined(__USE_GNU) #if __ANDROID_API__ >= 30 __BIONIC_FORTIFY_INLINE -void* mempcpy(void* const dst __pass_object_size0, const void* src, size_t copy_amount) +void* _Nonnull mempcpy(void* _Nonnull const dst __pass_object_size0, const void* _Nonnull src, size_t copy_amount) __diagnose_as_builtin(__builtin_mempcpy, 1, 2, 3) __overloadable __clang_error_if(__bos_unevaluated_lt(__bos0(dst), copy_amount), @@ -78,7 +78,7 @@ void* mempcpy(void* const dst __pass_object_size0, const void* src, size_t copy_ #endif /* __USE_GNU */ __BIONIC_FORTIFY_INLINE -char* stpcpy(char* const dst __pass_object_size, const char* src) +char* _Nonnull stpcpy(char* _Nonnull const dst __pass_object_size, const char* _Nonnull src) __overloadable __clang_error_if(__bos_unevaluated_le(__bos(dst), __builtin_strlen(src)), "'stpcpy' called with string bigger than buffer") { @@ -90,7 +90,7 @@ char* stpcpy(char* const dst __pass_object_size, const char* src) } __BIONIC_FORTIFY_INLINE -char* strcpy(char* const dst __pass_object_size, const char* src) +char* _Nonnull strcpy(char* _Nonnull const dst __pass_object_size, const char* _Nonnull src) __diagnose_as_builtin(__builtin_strcpy, 1, 2) __overloadable __clang_error_if(__bos_unevaluated_le(__bos(dst), __builtin_strlen(src)), @@ -103,7 +103,7 @@ char* strcpy(char* const dst __pass_object_size, const char* src) } __BIONIC_FORTIFY_INLINE -char* strcat(char* const dst __pass_object_size, const char* src) +char* _Nonnull strcat(char* _Nonnull const dst __pass_object_size, const char* _Nonnull src) __overloadable __clang_error_if(__bos_unevaluated_le(__bos(dst), __builtin_strlen(src)), "'strcat' called with string bigger than buffer") { @@ -117,7 +117,7 @@ char* strcat(char* const dst __pass_object_size, const char* src) #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED /* No diag -- clang diagnoses misuses of this on its own. */ __BIONIC_FORTIFY_INLINE -char* strncat(char* const dst __pass_object_size, const char* src, size_t n) +char* _Nonnull strncat(char* _Nonnull const dst __pass_object_size, const char* _Nonnull src, size_t n) __diagnose_as_builtin(__builtin_strncat, 1, 2, 3) __overloadable { return __builtin___strncat_chk(dst, src, n, __bos(dst)); @@ -126,7 +126,7 @@ char* strncat(char* const dst __pass_object_size, const char* src, size_t n) /* No diag -- clang diagnoses misuses of this on its own. */ __BIONIC_FORTIFY_INLINE -void* memset(void* const s __pass_object_size0, int c, size_t n) __overloadable +void* _Nonnull memset(void* _Nonnull const s __pass_object_size0, int c, size_t n) __overloadable __diagnose_as_builtin(__builtin_memset, 1, 2, 3) /* If you're a user who wants this warning to go away: use `(&memset)(foo, bar, baz)`. */ __clang_warning_if(c && !n, "'memset' will set 0 bytes; maybe the arguments got flipped?") { @@ -139,7 +139,7 @@ void* memset(void* const s __pass_object_size0, int c, size_t n) __overloadable #if __ANDROID_API__ >= 23 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED __BIONIC_FORTIFY_INLINE -void* memchr(const void* const s __pass_object_size, int c, size_t n) __overloadable { +void* _Nullable memchr(const void* _Nonnull const s __pass_object_size, int c, size_t n) __overloadable { size_t bos = __bos(s); if (__bos_trivially_ge(bos, n)) { @@ -150,7 +150,7 @@ void* memchr(const void* const s __pass_object_size, int c, size_t n) __overload } __BIONIC_FORTIFY_INLINE -void* __memrchr_fortify(const void* const __pass_object_size s, int c, size_t n) __overloadable { +void* _Nullable __memrchr_fortify(const void* _Nonnull const __pass_object_size s, int c, size_t n) __overloadable { size_t bos = __bos(s); if (__bos_trivially_ge(bos, n)) { @@ -164,7 +164,7 @@ void* __memrchr_fortify(const void* const __pass_object_size s, int c, size_t n) #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED /* No diag -- clang diagnoses misuses of this on its own. */ __BIONIC_FORTIFY_INLINE -char* stpncpy(char* const dst __pass_object_size, const char* const src __pass_object_size, size_t n) +char* _Nonnull stpncpy(char* _Nonnull const dst __pass_object_size, const char* _Nonnull const src __pass_object_size, size_t n) __diagnose_as_builtin(__builtin_stpncpy, 1, 2, 3) __overloadable { size_t bos_dst = __bos(dst); @@ -180,7 +180,7 @@ char* stpncpy(char* const dst __pass_object_size, const char* const src __pass_o /* No diag -- clang diagnoses misuses of this on its own. */ __BIONIC_FORTIFY_INLINE -char* strncpy(char* const dst __pass_object_size, const char* const src __pass_object_size, size_t n) +char* _Nonnull strncpy(char* _Nonnull const dst __pass_object_size, const char* _Nonnull const src __pass_object_size, size_t n) __diagnose_as_builtin(__builtin_strncpy, 1, 2, 3) __overloadable { size_t bos_dst = __bos(dst); @@ -196,7 +196,7 @@ char* strncpy(char* const dst __pass_object_size, const char* const src __pass_o #endif __BIONIC_FORTIFY_INLINE -size_t strlcpy(char* const dst __pass_object_size, const char* src, size_t size) +size_t strlcpy(char* _Nonnull const dst __pass_object_size, const char* _Nonnull src, size_t size) __overloadable __clang_error_if(__bos_unevaluated_lt(__bos(dst), size), "'strlcpy' called with size bigger than buffer") { @@ -208,7 +208,7 @@ size_t strlcpy(char* const dst __pass_object_size, const char* src, size_t size) } __BIONIC_FORTIFY_INLINE -size_t strlcat(char* const dst __pass_object_size, const char* src, size_t size) +size_t strlcat(char* _Nonnull const dst __pass_object_size, const char* _Nonnull src, size_t size) __overloadable __clang_error_if(__bos_unevaluated_lt(__bos(dst), size), "'strlcat' called with size bigger than buffer") { @@ -221,13 +221,13 @@ size_t strlcat(char* const dst __pass_object_size, const char* src, size_t size) #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED __BIONIC_FORTIFY_INLINE -size_t strlen(const char* const s __pass_object_size0) __overloadable { +size_t strlen(const char* _Nonnull const s __pass_object_size0) __overloadable { return __strlen_chk(s, __bos0(s)); } #endif __BIONIC_FORTIFY_INLINE -char* strchr(const char* const s __pass_object_size, int c) __overloadable { +char* _Nullable strchr(const char* _Nonnull const s __pass_object_size, int c) __overloadable { #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED size_t bos = __bos(s); @@ -239,7 +239,7 @@ char* strchr(const char* const s __pass_object_size, int c) __overloadable { } __BIONIC_FORTIFY_INLINE -char* strrchr(const char* const s __pass_object_size, int c) __overloadable { +char* _Nullable strrchr(const char* _Nonnull const s __pass_object_size, int c) __overloadable { #if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED size_t bos = __bos(s); @@ -254,18 +254,18 @@ char* strrchr(const char* const s __pass_object_size, int c) __overloadable { #if defined(__cplusplus) extern "C++" { __BIONIC_FORTIFY_INLINE -void* memrchr(void* const __pass_object_size s, int c, size_t n) { +void* _Nullable memrchr(void* _Nonnull const __pass_object_size s, int c, size_t n) { return __memrchr_fortify(s, c, n); } __BIONIC_FORTIFY_INLINE -const void* memrchr(const void* const __pass_object_size s, int c, size_t n) { +const void* _Nullable memrchr(const void* _Nonnull const __pass_object_size s, int c, size_t n) { return __memrchr_fortify(s, c, n); } } #else __BIONIC_FORTIFY_INLINE -void* memrchr(const void* const __pass_object_size s, int c, size_t n) __overloadable { +void* _Nullable memrchr(const void* _Nonnull const __pass_object_size s, int c, size_t n) __overloadable { return __memrchr_fortify(s, c, n); } #endif diff --git a/libc/include/bits/fortify/strings.h b/libc/include/bits/fortify/strings.h index 5515ef9bb..a36f02c63 100644 --- a/libc/include/bits/fortify/strings.h +++ b/libc/include/bits/fortify/strings.h @@ -29,7 +29,7 @@ #if defined(__BIONIC_FORTIFY) __BIONIC_FORTIFY_INLINE -void __bionic_bcopy(const void *src, void* const dst __pass_object_size0, size_t len) +void __bionic_bcopy(const void * _Nonnull src, void* _Nonnull const dst __pass_object_size0, size_t len) __overloadable __clang_error_if(__bos_unevaluated_lt(__bos0(dst), len), "'bcopy' called with size bigger than buffer") { @@ -44,7 +44,7 @@ void __bionic_bcopy(const void *src, void* const dst __pass_object_size0, size_t } __BIONIC_FORTIFY_INLINE -void __bionic_bzero(void* const b __pass_object_size0, size_t len) +void __bionic_bzero(void* _Nonnull const b __pass_object_size0, size_t len) __overloadable __clang_error_if(__bos_unevaluated_lt(__bos0(b), len), "'bzero' called with size bigger than buffer") { diff --git a/libc/include/bits/fortify/unistd.h b/libc/include/bits/fortify/unistd.h index 335d0b534..bbc228d69 100644 --- a/libc/include/bits/fortify/unistd.h +++ b/libc/include/bits/fortify/unistd.h @@ -29,24 +29,24 @@ #error "Never include this file directly; instead, include <unistd.h>" #endif -char* __getcwd_chk(char*, size_t, size_t) __INTRODUCED_IN(24); +char* _Nullable __getcwd_chk(char* _Nullable, size_t, size_t) __INTRODUCED_IN(24); -ssize_t __pread_chk(int, void*, size_t, off_t, size_t) __INTRODUCED_IN(23); -ssize_t __pread_real(int, void*, size_t, off_t) __RENAME(pread); +ssize_t __pread_chk(int, void* _Nonnull, size_t, off_t, size_t) __INTRODUCED_IN(23); +ssize_t __pread_real(int, void* _Nonnull, size_t, off_t) __RENAME(pread); -ssize_t __pread64_chk(int, void*, size_t, off64_t, size_t) __INTRODUCED_IN(23); -ssize_t __pread64_real(int, void*, size_t, off64_t) __RENAME(pread64); +ssize_t __pread64_chk(int, void* _Nonnull, size_t, off64_t, size_t) __INTRODUCED_IN(23); +ssize_t __pread64_real(int, void* _Nonnull, size_t, off64_t) __RENAME(pread64); -ssize_t __pwrite_chk(int, const void*, size_t, off_t, size_t) __INTRODUCED_IN(24); -ssize_t __pwrite_real(int, const void*, size_t, off_t) __RENAME(pwrite); +ssize_t __pwrite_chk(int, const void* _Nonnull, size_t, off_t, size_t) __INTRODUCED_IN(24); +ssize_t __pwrite_real(int, const void* _Nonnull, size_t, off_t) __RENAME(pwrite); -ssize_t __pwrite64_chk(int, const void*, size_t, off64_t, size_t) __INTRODUCED_IN(24); -ssize_t __pwrite64_real(int, const void*, size_t, off64_t) __RENAME(pwrite64); +ssize_t __pwrite64_chk(int, const void* _Nonnull, size_t, off64_t, size_t) __INTRODUCED_IN(24); +ssize_t __pwrite64_real(int, const void* _Nonnull, size_t, off64_t) __RENAME(pwrite64); -ssize_t __read_chk(int, void*, size_t, size_t) __INTRODUCED_IN(21); -ssize_t __write_chk(int, const void*, size_t, size_t) __INTRODUCED_IN(24); -ssize_t __readlink_chk(const char*, char*, size_t, size_t) __INTRODUCED_IN(23); -ssize_t __readlinkat_chk(int dirfd, const char*, char*, size_t, size_t) __INTRODUCED_IN(23); +ssize_t __read_chk(int, void* __BIONIC_COMPLICATED_NULLNESS, size_t, size_t) __INTRODUCED_IN(21); +ssize_t __write_chk(int, const void* __BIONIC_COMPLICATED_NULLNESS, size_t, size_t) __INTRODUCED_IN(24); +ssize_t __readlink_chk(const char* _Nonnull, char* _Nonnull, size_t, size_t) __INTRODUCED_IN(23); +ssize_t __readlinkat_chk(int dirfd, const char* _Nonnull, char* _Nonnull, size_t, size_t) __INTRODUCED_IN(23); #if defined(__BIONIC_FORTIFY) @@ -70,7 +70,7 @@ ssize_t __readlinkat_chk(int dirfd, const char*, char*, size_t, size_t) __INTROD __builtin_constant_p(index) && (index) <= SSIZE_MAX)) __BIONIC_FORTIFY_INLINE -char* getcwd(char* const __pass_object_size buf, size_t size) +char* _Nullable getcwd(char* const _Nullable __pass_object_size buf, size_t size) __overloadable __error_if_overflows_objectsize(size, __bos(buf), getcwd) { #if __ANDROID_API__ >= 24 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED @@ -85,7 +85,7 @@ char* getcwd(char* const __pass_object_size buf, size_t size) #if !defined(__USE_FILE_OFFSET64) __BIONIC_FORTIFY_INLINE -ssize_t pread(int fd, void* const __pass_object_size0 buf, size_t count, off_t offset) +ssize_t pread(int fd, void* const _Nonnull __pass_object_size0 buf, size_t count, off_t offset) __overloadable __error_if_overflows_ssizet(count, pread) __error_if_overflows_objectsize(count, __bos0(buf), pread) { @@ -101,7 +101,7 @@ ssize_t pread(int fd, void* const __pass_object_size0 buf, size_t count, off_t o #endif /* !defined(__USE_FILE_OFFSET64) */ __BIONIC_FORTIFY_INLINE -ssize_t pread64(int fd, void* const __pass_object_size0 buf, size_t count, off64_t offset) +ssize_t pread64(int fd, void* const _Nonnull __pass_object_size0 buf, size_t count, off64_t offset) __overloadable __error_if_overflows_ssizet(count, pread64) __error_if_overflows_objectsize(count, __bos0(buf), pread64) { @@ -117,7 +117,7 @@ ssize_t pread64(int fd, void* const __pass_object_size0 buf, size_t count, off64 #if !defined(__USE_FILE_OFFSET64) __BIONIC_FORTIFY_INLINE -ssize_t pwrite(int fd, const void* const __pass_object_size0 buf, size_t count, off_t offset) +ssize_t pwrite(int fd, const void* const _Nonnull __pass_object_size0 buf, size_t count, off_t offset) __overloadable __error_if_overflows_ssizet(count, pwrite) __error_if_overflows_objectsize(count, __bos0(buf), pwrite) { @@ -133,7 +133,7 @@ ssize_t pwrite(int fd, const void* const __pass_object_size0 buf, size_t count, #endif /* !defined(__USE_FILE_OFFSET64) */ __BIONIC_FORTIFY_INLINE -ssize_t pwrite64(int fd, const void* const __pass_object_size0 buf, size_t count, off64_t offset) +ssize_t pwrite64(int fd, const void* const _Nonnull __pass_object_size0 buf, size_t count, off64_t offset) __overloadable __error_if_overflows_ssizet(count, pwrite64) __error_if_overflows_objectsize(count, __bos0(buf), pwrite64) { @@ -148,7 +148,7 @@ ssize_t pwrite64(int fd, const void* const __pass_object_size0 buf, size_t count } __BIONIC_FORTIFY_INLINE -ssize_t read(int fd, void* const __pass_object_size0 buf, size_t count) +ssize_t read(int fd, void* const __BIONIC_COMPLICATED_NULLNESS __pass_object_size0 buf, size_t count) __overloadable __error_if_overflows_ssizet(count, read) __error_if_overflows_objectsize(count, __bos0(buf), read) { @@ -163,7 +163,7 @@ ssize_t read(int fd, void* const __pass_object_size0 buf, size_t count) } __BIONIC_FORTIFY_INLINE -ssize_t write(int fd, const void* const __pass_object_size0 buf, size_t count) +ssize_t write(int fd, const void* const __BIONIC_COMPLICATED_NULLNESS __pass_object_size0 buf, size_t count) __overloadable __error_if_overflows_ssizet(count, write) __error_if_overflows_objectsize(count, __bos0(buf), write) { @@ -178,7 +178,7 @@ ssize_t write(int fd, const void* const __pass_object_size0 buf, size_t count) } __BIONIC_FORTIFY_INLINE -ssize_t readlink(const char* path, char* const __pass_object_size buf, size_t size) +ssize_t readlink(const char* _Nonnull path, char* _Nonnull const __pass_object_size buf, size_t size) __overloadable __error_if_overflows_ssizet(size, readlink) __error_if_overflows_objectsize(size, __bos(buf), readlink) { @@ -193,7 +193,7 @@ ssize_t readlink(const char* path, char* const __pass_object_size buf, size_t si } __BIONIC_FORTIFY_INLINE -ssize_t readlinkat(int dirfd, const char* path, char* const __pass_object_size buf, size_t size) +ssize_t readlinkat(int dirfd, const char* _Nonnull path, char* const _Nonnull __pass_object_size buf, size_t size) __overloadable __error_if_overflows_ssizet(size, readlinkat) __error_if_overflows_objectsize(size, __bos(buf), readlinkat) { diff --git a/libc/include/bits/stdatomic.h b/libc/include/bits/stdatomic.h index 2ce6ee655..fe3d68d09 100644 --- a/libc/include/bits/stdatomic.h +++ b/libc/include/bits/stdatomic.h @@ -269,18 +269,18 @@ typedef struct { #define ATOMIC_FLAG_INIT { ATOMIC_VAR_INIT(false) } -static __inline bool atomic_flag_test_and_set_explicit(volatile atomic_flag *__object, memory_order __order) { +static __inline bool atomic_flag_test_and_set_explicit(volatile atomic_flag * _Nonnull __object, memory_order __order) { return (atomic_exchange_explicit(&__object->__flag, 1, __order)); } -static __inline void atomic_flag_clear_explicit(volatile atomic_flag *__object, memory_order __order) { +static __inline void atomic_flag_clear_explicit(volatile atomic_flag * _Nonnull __object, memory_order __order) { atomic_store_explicit(&__object->__flag, 0, __order); } -static __inline bool atomic_flag_test_and_set(volatile atomic_flag *__object) { +static __inline bool atomic_flag_test_and_set(volatile atomic_flag * _Nonnull __object) { return (atomic_flag_test_and_set_explicit(__object, memory_order_seq_cst)); } -static __inline void atomic_flag_clear(volatile atomic_flag *__object) { +static __inline void atomic_flag_clear(volatile atomic_flag * _Nonnull __object) { atomic_flag_clear_explicit(__object, memory_order_seq_cst); } diff --git a/libc/include/bits/termios_inlines.h b/libc/include/bits/termios_inlines.h index 5f7cc424c..a884b595f 100644 --- a/libc/include/bits/termios_inlines.h +++ b/libc/include/bits/termios_inlines.h @@ -45,19 +45,19 @@ __BEGIN_DECLS // Supporting separate input and output speeds would require an ABI // change for `struct termios`. -static __inline speed_t cfgetspeed(const struct termios* s) { +static __inline speed_t cfgetspeed(const struct termios* _Nonnull s) { return __BIONIC_CAST(static_cast, speed_t, s->c_cflag & CBAUD); } -__BIONIC_TERMIOS_INLINE speed_t cfgetispeed(const struct termios* s) { +__BIONIC_TERMIOS_INLINE speed_t cfgetispeed(const struct termios* _Nonnull s) { return cfgetspeed(s); } -__BIONIC_TERMIOS_INLINE speed_t cfgetospeed(const struct termios* s) { +__BIONIC_TERMIOS_INLINE speed_t cfgetospeed(const struct termios* _Nonnull s) { return cfgetspeed(s); } -__BIONIC_TERMIOS_INLINE void cfmakeraw(struct termios* s) { +__BIONIC_TERMIOS_INLINE void cfmakeraw(struct termios* _Nonnull s) { s->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); s->c_oflag &= ~OPOST; s->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); @@ -67,7 +67,7 @@ __BIONIC_TERMIOS_INLINE void cfmakeraw(struct termios* s) { s->c_cc[VTIME] = 0; } -__BIONIC_TERMIOS_INLINE int cfsetspeed(struct termios* s, speed_t speed) { +__BIONIC_TERMIOS_INLINE int cfsetspeed(struct termios* _Nonnull s, speed_t speed) { // CBAUD is 0x100f, and every matching bit pattern has a Bxxx constant. if ((speed & ~CBAUD) != 0) { errno = EINVAL; @@ -77,11 +77,11 @@ __BIONIC_TERMIOS_INLINE int cfsetspeed(struct termios* s, speed_t speed) { return 0; } -__BIONIC_TERMIOS_INLINE int cfsetispeed(struct termios* s, speed_t speed) { +__BIONIC_TERMIOS_INLINE int cfsetispeed(struct termios* _Nonnull s, speed_t speed) { return cfsetspeed(s, speed); } -__BIONIC_TERMIOS_INLINE int cfsetospeed(struct termios* s, speed_t speed) { +__BIONIC_TERMIOS_INLINE int cfsetospeed(struct termios* _Nonnull s, speed_t speed) { return cfsetspeed(s, speed); } @@ -99,7 +99,7 @@ __BIONIC_TERMIOS_INLINE int tcflush(int fd, int queue) { return ioctl(fd, TCFLSH, __BIONIC_CAST(static_cast, unsigned long, queue)); } -__BIONIC_TERMIOS_INLINE int tcgetattr(int fd, struct termios* s) { +__BIONIC_TERMIOS_INLINE int tcgetattr(int fd, struct termios* _Nonnull s) { return ioctl(fd, TCGETS, s); } @@ -112,7 +112,7 @@ __BIONIC_TERMIOS_INLINE int tcsendbreak(int fd, int duration) { return ioctl(fd, TCSBRKP, __BIONIC_CAST(static_cast, unsigned long, duration)); } -__BIONIC_TERMIOS_INLINE int tcsetattr(int fd, int optional_actions, const struct termios* s) { +__BIONIC_TERMIOS_INLINE int tcsetattr(int fd, int optional_actions, const struct termios* _Nonnull s) { int cmd; switch (optional_actions) { case TCSANOW: cmd = TCSETS; break; diff --git a/libc/include/bits/threads_inlines.h b/libc/include/bits/threads_inlines.h index 17de4a11a..5878e0acc 100644 --- a/libc/include/bits/threads_inlines.h +++ b/libc/include/bits/threads_inlines.h @@ -48,46 +48,46 @@ static __inline int __bionic_thrd_error(int __pthread_code) { } } -__BIONIC_THREADS_INLINE void call_once(once_flag* __flag, - void (*__function)(void)) { +__BIONIC_THREADS_INLINE void call_once(once_flag* _Nonnull __flag, + void (* _Nonnull __function)(void)) { pthread_once(__flag, __function); } -__BIONIC_THREADS_INLINE int cnd_broadcast(cnd_t* __cnd) { +__BIONIC_THREADS_INLINE int cnd_broadcast(cnd_t* _Nonnull __cnd) { return __bionic_thrd_error(pthread_cond_broadcast(__cnd)); } -__BIONIC_THREADS_INLINE void cnd_destroy(cnd_t* __cnd) { +__BIONIC_THREADS_INLINE void cnd_destroy(cnd_t* _Nonnull __cnd) { pthread_cond_destroy(__cnd); } -__BIONIC_THREADS_INLINE int cnd_init(cnd_t* __cnd) { +__BIONIC_THREADS_INLINE int cnd_init(cnd_t* _Nonnull __cnd) { return __bionic_thrd_error(pthread_cond_init(__cnd, NULL)); } -__BIONIC_THREADS_INLINE int cnd_signal(cnd_t* __cnd) { +__BIONIC_THREADS_INLINE int cnd_signal(cnd_t* _Nonnull __cnd) { return __bionic_thrd_error(pthread_cond_signal(__cnd)); } -__BIONIC_THREADS_INLINE int cnd_timedwait(cnd_t* __cnd, - mtx_t* __mtx, - const struct timespec* __timeout) { +__BIONIC_THREADS_INLINE int cnd_timedwait(cnd_t* _Nonnull __cnd, + mtx_t* _Nonnull __mtx, + const struct timespec* _Nullable __timeout) { return __bionic_thrd_error(pthread_cond_timedwait(__cnd, __mtx, __timeout)); } -__BIONIC_THREADS_INLINE int cnd_wait(cnd_t* __cnd, mtx_t* __mtx) { +__BIONIC_THREADS_INLINE int cnd_wait(cnd_t* _Nonnull __cnd, mtx_t* _Nonnull __mtx) { return __bionic_thrd_error(pthread_cond_wait(__cnd, __mtx)); } -__BIONIC_THREADS_INLINE void mtx_destroy(mtx_t* __mtx) { +__BIONIC_THREADS_INLINE void mtx_destroy(mtx_t* _Nonnull __mtx) { pthread_mutex_destroy(__mtx); } -__BIONIC_THREADS_INLINE int mtx_init(mtx_t* __mtx, int __type) { +__BIONIC_THREADS_INLINE int mtx_init(mtx_t* _Nonnull __mtx, int __type) { int __pthread_type = (__type & mtx_recursive) ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL; __type &= ~mtx_recursive; @@ -99,31 +99,32 @@ __BIONIC_THREADS_INLINE int mtx_init(mtx_t* __mtx, int __type) { return __bionic_thrd_error(pthread_mutex_init(__mtx, &__attr)); } -__BIONIC_THREADS_INLINE int mtx_lock(mtx_t* __mtx) { +__BIONIC_THREADS_INLINE int mtx_lock(mtx_t* _Nonnull __mtx) { return __bionic_thrd_error(pthread_mutex_lock(__mtx)); } -__BIONIC_THREADS_INLINE int mtx_timedlock(mtx_t* __mtx, - const struct timespec* __timeout) { +__BIONIC_THREADS_INLINE int mtx_timedlock(mtx_t* _Nonnull __mtx, + const struct timespec* _Nullable __timeout) { return __bionic_thrd_error(pthread_mutex_timedlock(__mtx, __timeout)); } -__BIONIC_THREADS_INLINE int mtx_trylock(mtx_t* __mtx) { +__BIONIC_THREADS_INLINE int mtx_trylock(mtx_t* _Nonnull __mtx) { return __bionic_thrd_error(pthread_mutex_trylock(__mtx)); } -__BIONIC_THREADS_INLINE int mtx_unlock(mtx_t* __mtx) { +__BIONIC_THREADS_INLINE int mtx_unlock(mtx_t* _Nonnull __mtx) { return __bionic_thrd_error(pthread_mutex_unlock(__mtx)); } - - +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnullability-completeness" struct __bionic_thrd_data { thrd_start_t __func; void* __arg; }; +#pragma clang diagnostic pop -static inline void* __bionic_thrd_trampoline(void* __arg) { +static inline void* _Nonnull __bionic_thrd_trampoline(void* _Nonnull __arg) { struct __bionic_thrd_data __data = *__BIONIC_CAST(static_cast, struct __bionic_thrd_data*, __arg); free(__arg); @@ -132,9 +133,9 @@ static inline void* __bionic_thrd_trampoline(void* __arg) { __BIONIC_CAST(static_cast, uintptr_t, __result)); } -__BIONIC_THREADS_INLINE int thrd_create(thrd_t* __thrd, - thrd_start_t __func, - void* __arg) { +__BIONIC_THREADS_INLINE int thrd_create(thrd_t* _Nonnull __thrd, + thrd_start_t _Nonnull __func, + void* _Nullable __arg) { struct __bionic_thrd_data* __pthread_arg = __BIONIC_CAST(static_cast, struct __bionic_thrd_data*, malloc(sizeof(struct __bionic_thrd_data))); @@ -164,7 +165,7 @@ __BIONIC_THREADS_INLINE void thrd_exit(int __result) { __BIONIC_CAST(static_cast, uintptr_t, __result))); } -__BIONIC_THREADS_INLINE int thrd_join(thrd_t __thrd, int* __result) { +__BIONIC_THREADS_INLINE int thrd_join(thrd_t __thrd, int* _Nullable __result) { void* __pthread_result; if (pthread_join(__thrd, &__pthread_result) != 0) return thrd_error; if (__result) { @@ -173,8 +174,8 @@ __BIONIC_THREADS_INLINE int thrd_join(thrd_t __thrd, int* __result) { return thrd_success; } -__BIONIC_THREADS_INLINE int thrd_sleep(const struct timespec* __duration, - struct timespec* __remaining) { +__BIONIC_THREADS_INLINE int thrd_sleep(const struct timespec* _Nonnull __duration, + struct timespec* _Nullable __remaining) { int __rc = nanosleep(__duration, __remaining); if (__rc == 0) return 0; return (errno == EINTR) ? -1 : -2; @@ -186,7 +187,7 @@ __BIONIC_THREADS_INLINE void thrd_yield(void) { -__BIONIC_THREADS_INLINE int tss_create(tss_t* __key, tss_dtor_t __dtor) { +__BIONIC_THREADS_INLINE int tss_create(tss_t* _Nonnull __key, tss_dtor_t _Nullable __dtor) { return __bionic_thrd_error(pthread_key_create(__key, __dtor)); } @@ -194,11 +195,11 @@ __BIONIC_THREADS_INLINE void tss_delete(tss_t __key) { pthread_key_delete(__key); } -__BIONIC_THREADS_INLINE void* tss_get(tss_t __key) { +__BIONIC_THREADS_INLINE void* _Nullable tss_get(tss_t __key) { return pthread_getspecific(__key); } -__BIONIC_THREADS_INLINE int tss_set(tss_t __key, void* __value) { +__BIONIC_THREADS_INLINE int tss_set(tss_t __key, void* _Nonnull __value) { return __bionic_thrd_error(pthread_setspecific(__key, __value)); } diff --git a/libc/include/complex.h b/libc/include/complex.h index 50da3306d..f205abdba 100644 --- a/libc/include/complex.h +++ b/libc/include/complex.h @@ -55,99 +55,99 @@ __BEGIN_DECLS /* 7.3.5.1 The cacos functions */ double complex cacos(double complex __z) __INTRODUCED_IN(23); float complex cacosf(float complex __z) __INTRODUCED_IN(23); -long double complex cacosl(long double complex __z) __RENAME_LDBL(cacos, 23, 26); +long double complex cacosl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.5.2 The casin functions */ double complex casin(double complex __z) __INTRODUCED_IN(23); float complex casinf(float complex __z) __INTRODUCED_IN(23); -long double complex casinl(long double complex __z) __RENAME_LDBL(casin, 23, 26); +long double complex casinl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.5.1 The catan functions */ double complex catan(double complex __z) __INTRODUCED_IN(23); float complex catanf(float complex __z) __INTRODUCED_IN(23); -long double complex catanl(long double complex __z) __RENAME_LDBL(catan, 23, 26); +long double complex catanl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.5.1 The ccos functions */ double complex ccos(double complex __z) __INTRODUCED_IN(23); float complex ccosf(float complex __z) __INTRODUCED_IN(23); -long double complex ccosl(long double complex __z) __RENAME_LDBL(ccos, 23, 26); +long double complex ccosl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.5.1 The csin functions */ double complex csin(double complex __z) __INTRODUCED_IN(23); float complex csinf(float complex __z) __INTRODUCED_IN(23); -long double complex csinl(long double complex __z) __RENAME_LDBL(csin, 23, 26); +long double complex csinl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.5.1 The ctan functions */ double complex ctan(double complex __z) __INTRODUCED_IN(23); float complex ctanf(float complex __z) __INTRODUCED_IN(23); -long double complex ctanl(long double complex __z) __RENAME_LDBL(ctan, 23, 26); +long double complex ctanl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.6 Hyperbolic functions */ /* 7.3.6.1 The cacosh functions */ double complex cacosh(double complex __z) __INTRODUCED_IN(23); float complex cacoshf(float complex __z) __INTRODUCED_IN(23); -long double complex cacoshl(long double complex __z) __RENAME_LDBL(cacosh, 23, 26); +long double complex cacoshl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.6.2 The casinh functions */ double complex casinh(double complex __z) __INTRODUCED_IN(23); float complex casinhf(float complex __z) __INTRODUCED_IN(23); -long double complex casinhl(long double complex __z) __RENAME_LDBL(casinh, 23, 26); +long double complex casinhl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.6.3 The catanh functions */ double complex catanh(double complex __z) __INTRODUCED_IN(23); float complex catanhf(float complex __z) __INTRODUCED_IN(23); -long double complex catanhl(long double complex __z) __RENAME_LDBL(catanh, 23, 26); +long double complex catanhl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.6.4 The ccosh functions */ double complex ccosh(double complex __z) __INTRODUCED_IN(23); float complex ccoshf(float complex __z) __INTRODUCED_IN(23); -long double complex ccoshl(long double complex __z) __RENAME_LDBL(ccosh, 23, 26); +long double complex ccoshl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.6.5 The csinh functions */ double complex csinh(double complex __z) __INTRODUCED_IN(23); float complex csinhf(float complex __z) __INTRODUCED_IN(23); -long double complex csinhl(long double complex __z) __RENAME_LDBL(csinh, 23, 26); +long double complex csinhl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.6.6 The ctanh functions */ double complex ctanh(double complex __z) __INTRODUCED_IN(23); float complex ctanhf(float complex __z) __INTRODUCED_IN(23); -long double complex ctanhl(long double complex __z) __RENAME_LDBL(ctanh, 23, 26); +long double complex ctanhl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.7 Exponential and logarithmic functions */ /* 7.3.7.1 The cexp functions */ double complex cexp(double complex __z) __INTRODUCED_IN(23); float complex cexpf(float complex __z) __INTRODUCED_IN(23); -long double complex cexpl(long double complex __z) __RENAME_LDBL(cexp, 23, 26); +long double complex cexpl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.7.2 The clog functions */ double complex clog(double complex __z) __INTRODUCED_IN(26); float complex clogf(float complex __z) __INTRODUCED_IN(26); -long double complex clogl(long double complex __z) __RENAME_LDBL(clog, 26, 26); +long double complex clogl(long double complex __z) __INTRODUCED_IN(26); /* 7.3.8 Power and absolute-value functions */ /* 7.3.8.1 The cabs functions */ double cabs(double complex __z) __INTRODUCED_IN(23); float cabsf(float complex __z) __INTRODUCED_IN(23); -long double cabsl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23) /*__RENAME_LDBL(cabs)*/; +long double cabsl(long double complex __z) __INTRODUCED_IN(23); /* 7.3.8.2 The cpow functions */ double complex cpow(double complex __x, double complex __z) __INTRODUCED_IN(26); float complex cpowf(float complex __x, float complex __z) __INTRODUCED_IN(26); -long double complex cpowl(long double complex __x, long double complex __z) __RENAME_LDBL(cpow, 26, 26); +long double complex cpowl(long double complex __x, long double complex __z) __INTRODUCED_IN(26); /* 7.3.8.3 The csqrt functions */ double complex csqrt(double complex __z) __INTRODUCED_IN(23); float complex csqrtf(float complex __z) __INTRODUCED_IN(23); -long double complex csqrtl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23) /*__RENAME_LDBL(csqrt)*/; +long double complex csqrtl(long double complex __z) __INTRODUCED_IN(23); /* 7.3.9 Manipulation functions */ /* 7.3.9.1 The carg functions */ double carg(double complex __z) __INTRODUCED_IN(23); float cargf(float complex __z) __INTRODUCED_IN(23); -long double cargl(long double complex __z) __RENAME_LDBL(carg, 23, 23); +long double cargl(long double complex __z) __INTRODUCED_IN(23); /* 7.3.9.2 The cimag functions */ double cimag(double complex __z) __INTRODUCED_IN(23); float cimagf(float complex __z) __INTRODUCED_IN(23); -long double cimagl(long double complex __z) __RENAME_LDBL(cimag, 23, 23); +long double cimagl(long double complex __z) __INTRODUCED_IN(23); /* 7.3.9.3 The conj functions */ double complex conj(double complex __z) __INTRODUCED_IN(23); float complex conjf(float complex __z) __INTRODUCED_IN(23); -long double complex conjl(long double complex __z) __RENAME_LDBL(conj, 23, 23); +long double complex conjl(long double complex __z) __INTRODUCED_IN(23); /* 7.3.9.4 The cproj functions */ double complex cproj(double complex __z) __INTRODUCED_IN(23); float complex cprojf(float complex __z) __INTRODUCED_IN(23); -long double complex cprojl(long double complex __z) __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(23) /*__RENAME_LDBL(cproj)*/; +long double complex cprojl(long double complex __z) __INTRODUCED_IN(23); /* 7.3.9.5 The creal functions */ double creal(double complex __z) __INTRODUCED_IN(23); float crealf(float complex __z) __INTRODUCED_IN(23); -long double creall(long double complex __z) __RENAME_LDBL(creal, 23, 23); +long double creall(long double complex __z) __INTRODUCED_IN(23); __END_DECLS diff --git a/libc/include/fenv.h b/libc/include/fenv.h index 6e8ea57c4..f7dcc8e4f 100644 --- a/libc/include/fenv.h +++ b/libc/include/fenv.h @@ -29,6 +29,11 @@ #pragma once +/** + * @file fenv.h + * @brief Floating-point environment. + */ + #include <sys/cdefs.h> #if defined(__aarch64__) || defined(__arm__) @@ -43,33 +48,135 @@ __BEGIN_DECLS -int feclearexcept(int __exceptions) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); -int fegetexceptflag(fexcept_t* _Nonnull __flag_ptr, int __exceptions) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); -int feraiseexcept(int __exceptions) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); -int fesetexceptflag(const fexcept_t* _Nonnull __flag_ptr, int __exceptions) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); -int fetestexcept(int __exceptions) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); +/** + * [feclearexcept(3)](http://man7.org/linux/man-pages/man3/feclearexcept.3.html) + * clears the given `exceptions` in hardware. + * + * Returns 0 on success, and returns non-zero on failure. + */ +int feclearexcept(int __exceptions); -int fegetround(void) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); -int fesetround(int __rounding_mode) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); +/** + * [fegetexceptflag(3)](http://man7.org/linux/man-pages/man3/fegetexceptflag.3.html) + * copies the state of the given `exceptions` from hardware into `*flag_ptr`. + * See fesetexceptflag(). + * + * Returns 0 on success, and returns non-zero on failure. + */ +int fegetexceptflag(fexcept_t* _Nonnull __flag_ptr, int __exceptions); -int fegetenv(fenv_t* _Nonnull __env) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); -int feholdexcept(fenv_t* _Nonnull __env) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); -int fesetenv(const fenv_t* _Nonnull __env) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); -int feupdateenv(const fenv_t* _Nonnull __env) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); +/** + * [feraiseexcept(3)](http://man7.org/linux/man-pages/man3/feraiseexcept.3.html) + * raises the given `exceptions` in hardware. + * + * Returns 0 on success, and returns non-zero on failure. + */ +int feraiseexcept(int __exceptions); -int feenableexcept(int __exceptions) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); -int fedisableexcept(int __exceptions) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); -int fegetexcept(void) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_X86(9); +/** + * [fesetexceptflag(3)](http://man7.org/linux/man-pages/man3/fesetexceptflag.3.html) + * copies the state of the given `exceptions` from `*flag_ptr` into hardware. + * See fesetexceptflag(). + * + * Returns 0 on success, and returns non-zero on failure. + */ +int fesetexceptflag(const fexcept_t* _Nonnull __flag_ptr, int __exceptions); -/* - * The following constant represents the default floating-point environment - * (that is, the one installed at program startup) and has type pointer to - * const-qualified fenv_t. +/** + * [fetestexcept(3)](http://man7.org/linux/man-pages/man3/fetestexcept.3.html) + * tests whether the given `exceptions` are set in hardware. + * + * Returns the currently-set subset of `exceptions`. + */ +int fetestexcept(int __exceptions); + +/** + * [fegetround(3)](http://man7.org/linux/man-pages/man3/fegetround.3.html) + * returns the current rounding mode. + * + * Returns the rounding mode on success, and returns a negative value on failure. + */ +int fegetround(void); + +/** + * [fesetround(3)](http://man7.org/linux/man-pages/man3/fesetround.3.html) + * sets the current rounding mode. + * + * Returns 0 on success, and returns non-zero on failure. + */ +int fesetround(int __rounding_mode); + +/** + * [fegetenv(3)](http://man7.org/linux/man-pages/man3/fegetenv.3.html) + * gets the current floating-point environment. See fesetenv(). + * + * Returns 0 on success, and returns non-zero on failure. + */ +int fegetenv(fenv_t* _Nonnull __env); + +/** + * [feholdexcept(3)](http://man7.org/linux/man-pages/man3/feholdexcept.3.html) + * gets the current floating-point environment, clears the status flags, and + * ignores floating point exceptions. See fesetenv()/feupdateenv(). + * + * Returns 0 on success, and returns non-zero on failure. + */ +int feholdexcept(fenv_t* _Nonnull __env); + +/** + * [fesetenv(3)](http://man7.org/linux/man-pages/man3/fesetenv.3.html) + * sets the current floating-point environment. See fegetenv(). + * + * Returns 0 on success, and returns non-zero on failure. + */ +int fesetenv(const fenv_t* _Nonnull __env); + +/** + * [feupdateenv(3)](http://man7.org/linux/man-pages/man3/feupdateenv.3.html) + * sets the current floating-point environment to `*env` but with currently-raised + * exceptions still raised. See fesetenv(). + * + * Returns 0 on success, and returns non-zero on failure. + */ +int feupdateenv(const fenv_t* _Nonnull __env); + +/** + * [feenableexcept(3)](http://man7.org/linux/man-pages/man3/feenableexcept.3.html) + * sets the given `exceptions` to trap, if the hardware supports it. This is not + * generally useful on Android, because only x86/x86-64 can trap. + * + * Returns the previous set of enabled exceptions on success, and returns -1 on failure. + */ +int feenableexcept(int __exceptions); + +/** + * [fedisableexcept(3)](http://man7.org/linux/man-pages/man3/fedisableexcept.3.html) + * sets the given `exceptions` to not trap, if the hardware supports it. This is not + * generally useful on Android, because only x86/x86-64 can trap. + * + * Returns the previous set of enabled exceptions on success, and returns -1 on failure. + */ +int fedisableexcept(int __exceptions); + +/** + * [fegetexcept(3)](http://man7.org/linux/man-pages/man3/fegetexcept.3.html) + * returns the exceptions that currently trap. This is not generally useful on + * Android, because only x86/x86-64 can trap. + * + * Returns the exceptions that currently trap. + */ +int fegetexcept(void); + +/** See FE_DFL_ENV. */ +extern const fenv_t __fe_dfl_env; + +/** + * Constant representing the default floating-point environment + * (that is, the one installed at program startup). * * It can be used as an argument to the functions that manage the floating-point * environment, namely fesetenv() and feupdateenv(). */ -extern const fenv_t __fe_dfl_env; #define FE_DFL_ENV (&__fe_dfl_env) __END_DECLS diff --git a/libc/include/ftw.h b/libc/include/ftw.h index c5fa4de1d..ee154f0bb 100644 --- a/libc/include/ftw.h +++ b/libc/include/ftw.h @@ -57,8 +57,8 @@ struct FTW { __BEGIN_DECLS int ftw(const char* _Nonnull __dir_path, int (* _Nonnull __callback)(const char* _Nonnull, const struct stat* _Nonnull, int), int __max_fd_count) __INTRODUCED_IN(17); int nftw(const char* _Nonnull __dir_path, int (* _Nonnull __callback)(const char* _Nonnull, const struct stat* _Nonnull, int, struct FTW* _Nonnull), int __max_fd_count, int __flags) __INTRODUCED_IN(17); -int ftw64(const char* _Nonnull __dir_path, int (* _Nonnull __callback)(const char* _Nonnull, const struct stat64* _Nonnull, int), int __max_fd_count) __RENAME_STAT64(ftw, 17, 21); -int nftw64(const char* _Nonnull __dir_path, int (* _Nonnull __callback)(const char* _Nonnull, const struct stat64* _Nonnull, int, struct FTW* _Nonnull), int __max_fd_count, int __flags) __RENAME_STAT64(nftw, 17, 21); +int ftw64(const char* _Nonnull __dir_path, int (* _Nonnull __callback)(const char* _Nonnull, const struct stat64* _Nonnull, int), int __max_fd_count) __INTRODUCED_IN(21); +int nftw64(const char* _Nonnull __dir_path, int (* _Nonnull __callback)(const char* _Nonnull, const struct stat64* _Nonnull, int, struct FTW* _Nonnull), int __max_fd_count, int __flags) __INTRODUCED_IN(21); __END_DECLS #endif diff --git a/libc/include/iconv.h b/libc/include/iconv.h index 7cf36dcf2..794a2922b 100644 --- a/libc/include/iconv.h +++ b/libc/include/iconv.h @@ -54,7 +54,7 @@ typedef struct __iconv_t* iconv_t; * * Available since API level 28. */ -iconv_t _Nonnull iconv_open(const char* _Nonnull __src_encoding, const char* _Nonnull __dst_encoding) __INTRODUCED_IN(28); +iconv_t _Nonnull iconv_open(const char* _Nonnull __dst_encoding, const char* _Nonnull __src_encoding) __INTRODUCED_IN(28); /** * [iconv(3)](http://man7.org/linux/man-pages/man3/iconv.3.html) converts characters from one diff --git a/libc/include/math.h b/libc/include/math.h index a5fa7c3f3..0572238c1 100644 --- a/libc/include/math.h +++ b/libc/include/math.h @@ -75,232 +75,231 @@ typedef __float_t float_t; double acos(double __x); float acosf(float __x); -long double acosl(long double __x) __RENAME_LDBL(acos, 3, 21); +long double acosl(long double __x); double asin(double __x); float asinf(float __x); -long double asinl(long double __x) __RENAME_LDBL(asin, 3, 21); +long double asinl(long double __x); double atan(double __x); float atanf(float __x); -long double atanl(long double __x) __RENAME_LDBL(atan, 3, 21); +long double atanl(long double __x); double atan2(double __y, double __x); float atan2f(float __y, float __x); -long double atan2l(long double __y, long double __x) __RENAME_LDBL(atan2, 3, 21); +long double atan2l(long double __y, long double __x); double cos(double __x); float cosf(float __x); -long double cosl(long double __x) __RENAME_LDBL(cos, 3, 21); +long double cosl(long double __x); double sin(double __x); float sinf(float __x); -long double sinl(long double __x) __RENAME_LDBL(sin, 3, 21); +long double sinl(long double __x); double tan(double __x); float tanf(float __x); -long double tanl(long double __x) __RENAME_LDBL(tan, 3, 21); +long double tanl(long double __x); double acosh(double __x); float acoshf(float __x); -long double acoshl(long double __x) __RENAME_LDBL(acosh, 3, 21); +long double acoshl(long double __x); double asinh(double __x); float asinhf(float __x); -long double asinhl(long double __x) __RENAME_LDBL(asinh, 3, 21); +long double asinhl(long double __x); double atanh(double __x); float atanhf(float __x); -long double atanhl(long double __x) __RENAME_LDBL(atanh, 3, 21); +long double atanhl(long double __x); double cosh(double __x); float coshf(float __x); -long double coshl(long double __x) __RENAME_LDBL(cosh, 3, 21); +long double coshl(long double __x); double sinh(double __x); float sinhf(float __x); -long double sinhl(long double __x) __RENAME_LDBL(sinh, 3, 21); +long double sinhl(long double __x); double tanh(double __x); float tanhf(float __x); -long double tanhl(long double __x) __RENAME_LDBL(tanh, 3, 21); +long double tanhl(long double __x); double exp(double __x); float expf(float __x); -long double expl(long double __x) __RENAME_LDBL(exp, 3, 21); +long double expl(long double __x); double exp2(double __x); float exp2f(float __x); -long double exp2l(long double __x) __RENAME_LDBL(exp2, 3, 21); +long double exp2l(long double __x); double expm1(double __x); float expm1f(float __x); -long double expm1l(long double __x) __RENAME_LDBL(expm1, 3, 21); +long double expm1l(long double __x); double frexp(double __x, int* _Nonnull __exponent); float frexpf(float __x, int* _Nonnull __exponent); -long double frexpl(long double __x, int* _Nonnull __exponent) __RENAME_LDBL(frexp, 3, 21); +long double frexpl(long double __x, int* _Nonnull __exponent); int ilogb(double __x) __attribute_const__; int ilogbf(float __x) __attribute_const__; -int ilogbl(long double __x) __RENAME_LDBL(ilogb, 3, 3) __attribute_const__; +int ilogbl(long double __x) __attribute_const__; double ldexp(double __x, int __exponent); float ldexpf(float __x, int __exponent); -long double ldexpl(long double __x, int __exponent) __RENAME_LDBL(ldexp, 3, 3); +long double ldexpl(long double __x, int __exponent); double log(double __x); float logf(float __x); -long double logl(long double __x) __RENAME_LDBL(log, 3, 21); +long double logl(long double __x); double log10(double __x); float log10f(float __x); -long double log10l(long double __x) __RENAME_LDBL(log10, 3, 21); +long double log10l(long double __x); double log1p(double __x); float log1pf(float __x); -long double log1pl(long double __x) __RENAME_LDBL(log1p, 3, 21); +long double log1pl(long double __x); double log2(double __x) __INTRODUCED_IN(18); float log2f(float __x) __INTRODUCED_IN(18); -long double log2l(long double __x) __RENAME_LDBL(log2, 18, 18); +long double log2l(long double __x); double logb(double __x); float logbf(float __x); -long double logbl(long double __x) __RENAME_LDBL(logb, 3, 18); +long double logbl(long double __x); double modf(double __x, double* _Nonnull __integral_part); float modff(float __x, float* _Nonnull __integral_part); -long double modfl(long double __x, long double* _Nonnull __integral_part) __RENAME_LDBL(modf, 3, 21); +long double modfl(long double __x, long double* _Nonnull __integral_part); double scalbn(double __x, int __exponent); float scalbnf(float __x, int __exponent); -long double scalbnl(long double __x, int __exponent) __RENAME_LDBL(scalbn, 3, 3); +long double scalbnl(long double __x, int __exponent); -/* TODO: once the NDK only supports >= 18, use __RENAME_LDBL here too. */ -double scalbln(double __x, long __exponent) __INTRODUCED_IN_X86_NO_GUARD_FOR_NDK(18); -float scalblnf(float __x, long __exponent) __INTRODUCED_IN_X86_NO_GUARD_FOR_NDK(18); -long double scalblnl(long double __x, long __exponent) __INTRODUCED_IN_X86_NO_GUARD_FOR_NDK(18); +double scalbln(double __x, long __exponent); +float scalblnf(float __x, long __exponent); +long double scalblnl(long double __x, long __exponent); double cbrt(double __x); float cbrtf(float __x); -long double cbrtl(long double __x) __RENAME_LDBL(cbrt, 3, 21); +long double cbrtl(long double __x); double fabs(double __x) __attribute_const__; float fabsf(float __x) __attribute_const__; -long double fabsl(long double __x) __RENAME_LDBL(fabs, 3, 3) __attribute_const__; +long double fabsl(long double __x) __attribute_const__; double hypot(double __x, double __y); float hypotf(float __x, float __y); -long double hypotl(long double __x, long double __y) __RENAME_LDBL(hypot, 3, 21); +long double hypotl(long double __x, long double __y); double pow(double __x, double __y); float powf(float __x, float __y); -long double powl(long double __x, long double __y) __RENAME_LDBL(pow, 3, 21); +long double powl(long double __x, long double __y); double sqrt(double __x); float sqrtf(float __x); -long double sqrtl(long double __x) __RENAME_LDBL(sqrt, 3, 21); +long double sqrtl(long double __x); double erf(double __x); float erff(float __x); -long double erfl(long double __x) __RENAME_LDBL(erf, 3, 21); +long double erfl(long double __x); double erfc(double __x); float erfcf(float __x); -long double erfcl(long double __x) __RENAME_LDBL(erfc, 3, 21); +long double erfcl(long double __x); double lgamma(double __x); float lgammaf(float __x); -long double lgammal(long double __x) __RENAME_LDBL(lgamma, 3, 21); +long double lgammal(long double __x); double tgamma(double __x); float tgammaf(float __x); -long double tgammal(long double __x) __RENAME_LDBL(tgamma, 3, 21); +long double tgammal(long double __x); double ceil(double __x); float ceilf(float __x); -long double ceill(long double __x) __RENAME_LDBL(ceil, 3, 3); +long double ceill(long double __x); double floor(double __x); float floorf(float __x); -long double floorl(long double __x) __RENAME_LDBL(floor, 3, 3); +long double floorl(long double __x); double nearbyint(double __x); float nearbyintf(float __x); -long double nearbyintl(long double __x) __RENAME_LDBL(nearbyint, 3, 21); +long double nearbyintl(long double __x); double rint(double __x); float rintf(float __x); -long double rintl(long double __x) __RENAME_LDBL(rint, 3, 21); +long double rintl(long double __x); long lrint(double __x); long lrintf(float __x); -long lrintl(long double __x) __RENAME_LDBL(lrint, 3, 21); +long lrintl(long double __x); long long llrint(double __x); long long llrintf(float __x); -long long llrintl(long double __x) __RENAME_LDBL(llrint, 3, 21); +long long llrintl(long double __x); double round(double __x); float roundf(float __x); -long double roundl(long double __x) __RENAME_LDBL(roundl, 3, 3); +long double roundl(long double __x); long lround(double __x); long lroundf(float __x); -long lroundl(long double __x) __RENAME_LDBL(lround, 3, 3); +long lroundl(long double __x); long long llround(double __x); long long llroundf(float __x); -long long llroundl(long double __x) __RENAME_LDBL(llround, 3, 3); +long long llroundl(long double __x); double trunc(double __x); float truncf(float __x); -long double truncl(long double __x) __RENAME_LDBL(trunc, 3, 3); +long double truncl(long double __x); double fmod(double __x, double __y); float fmodf(float __x, float __y); -long double fmodl(long double __x, long double __y) __RENAME_LDBL(fmod, 3, 21); +long double fmodl(long double __x, long double __y); double remainder(double __x, double __y); float remainderf(float __x, float __y); -long double remainderl(long double __x, long double __y) __RENAME_LDBL(remainder, 3, 21); +long double remainderl(long double __x, long double __y); double remquo(double __x, double __y, int* _Nonnull __quotient_bits); float remquof(float __x, float __y, int* _Nonnull __quotient_bits); -long double remquol(long double __x, long double __y, int* _Nonnull __quotient_bits) __RENAME_LDBL(remquo, 3, 21); +long double remquol(long double __x, long double __y, int* _Nonnull __quotient_bits); double copysign(double __value, double __sign) __attribute_const__; float copysignf(float __value, float __sign) __attribute_const__; -long double copysignl(long double __value, long double __sign) __RENAME_LDBL(copysign, 3, 3) __attribute_const__; +long double copysignl(long double __value, long double __sign) __attribute_const__; double nan(const char* _Nonnull __kind) __attribute_const__; float nanf(const char* _Nonnull __kind) __attribute_const__; -long double nanl(const char* _Nonnull __kind) __RENAME_LDBL(nan, 13, 13) __attribute_const__; +long double nanl(const char* _Nonnull __kind) __attribute_const__; double nextafter(double __x, double __y); float nextafterf(float __x, float __y); -long double nextafterl(long double __x, long double __y) __RENAME_LDBL_NO_GUARD_FOR_NDK(nextafter, 3, 21); +long double nextafterl(long double __x, long double __y); -double nexttoward(double __x, long double __y) __INTRODUCED_IN_NO_GUARD_FOR_NDK(18); +double nexttoward(double __x, long double __y); float nexttowardf(float __x, long double __y); -long double nexttowardl(long double __x, long double __y) __RENAME_LDBL_NO_GUARD_FOR_NDK(nexttoward, 18, 18); +long double nexttowardl(long double __x, long double __y); double fdim(double __x, double __y); float fdimf(float __x, float __y); -long double fdiml(long double __x, long double __y) __RENAME_LDBL(fdim, 3, 3); +long double fdiml(long double __x, long double __y); double fmax(double __x, double __y) __attribute_const__; float fmaxf(float __x, float __y) __attribute_const__; -long double fmaxl(long double __x, long double __y) __RENAME_LDBL(fmax, 3, 3) __attribute_const__; +long double fmaxl(long double __x, long double __y) __attribute_const__; double fmin(double __x, double __y) __attribute_const__; float fminf(float __x, float __y) __attribute_const__; -long double fminl(long double __x, long double __y) __RENAME_LDBL(fmin, 3, 3) __attribute_const__; +long double fminl(long double __x, long double __y) __attribute_const__; double fma(double __x, double __y, double __z); float fmaf(float __x, float __y, float __z); -long double fmal(long double __x, long double __y, long double __z) __RENAME_LDBL_NO_GUARD_FOR_NDK(fma, 3, 21); +long double fmal(long double __x, long double __y, long double __z); #define isgreater(x, y) __builtin_isgreater((x), (y)) #define isgreaterequal(x, y) __builtin_isgreaterequal((x), (y)) diff --git a/libc/include/sched.h b/libc/include/sched.h index 26bc7423c..d11fddfb7 100644 --- a/libc/include/sched.h +++ b/libc/include/sched.h @@ -172,7 +172,7 @@ int sched_rr_get_interval(pid_t __pid, struct timespec* _Nonnull __quantum); * Returns the pid of the child to the caller on success and * returns -1 and sets `errno` on failure. */ -int clone(int (* __BIONIC_COMPLICATED_NULLNESS __fn)(void* __BIONIC_COMPLICATED_NULLNESS ), void* __BIONIC_COMPLICATED_NULLNESS __child_stack, int __flags, void* _Nullable __arg, ...) __INTRODUCED_IN_ARM(9) __INTRODUCED_IN_X86(17); +int clone(int (* __BIONIC_COMPLICATED_NULLNESS __fn)(void* __BIONIC_COMPLICATED_NULLNESS ), void* __BIONIC_COMPLICATED_NULLNESS __child_stack, int __flags, void* _Nullable __arg, ...); /** * [unshare(2)](http://man7.org/linux/man-pages/man2/unshare.2.html) diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h index 2bcb870fd..ee4b12afb 100644 --- a/libc/include/stdlib.h +++ b/libc/include/stdlib.h @@ -78,7 +78,7 @@ int posix_memalign(void* _Nullable * _Nullable __memptr, size_t __alignment, siz void* _Nullable aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28); double strtod(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr); -long double strtold(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr) __RENAME_LDBL(strtod, 3, 21); +long double strtold(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr) __INTRODUCED_IN(21); unsigned long strtoul_l(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr, int __base, locale_t _Nonnull __l) __INTRODUCED_IN(26); diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h index 484757e26..4154e62af 100644 --- a/libc/include/sys/cdefs.h +++ b/libc/include/sys/cdefs.h @@ -201,39 +201,6 @@ # define __RENAME_IF_FILE_OFFSET64(func) #endif -/* - * For LP32, `long double` == `double`. Historically many `long double` functions were incorrect - * on x86, missing on most architectures, and even if they are present and correct, linking to - * them just bloats your ELF file by adding extra relocations. The __BIONIC_LP32_USE_LONG_DOUBLE - * macro lets us test the headers both ways (and adds an escape valve). - * - * Note that some functions have their __RENAME_LDBL commented out as a sign that although we could - * use __RENAME_LDBL it would actually cause the function to be introduced later because the - * `long double` variant appeared before the `double` variant. - * - * The _NO_GUARD_FOR_NDK variants keep the __VERSIONER_NO_GUARD behavior working for the NDK. This - * allows libc++ to refer to these functions in inlines without needing to guard them, needed since - * libc++ doesn't currently guard these calls. There's no risk to the apps though because using - * those APIs will still cause a link error. - */ -#if defined(__LP64__) || defined(__BIONIC_LP32_USE_LONG_DOUBLE) -#define __RENAME_LDBL(rewrite,rewrite_api_level,regular_api_level) __INTRODUCED_IN(regular_api_level) -#define __RENAME_LDBL_NO_GUARD_FOR_NDK(rewrite,rewrite_api_level,regular_api_level) __INTRODUCED_IN_NO_GUARD_FOR_NDK(regular_api_level) -#else -#define __RENAME_LDBL(rewrite,rewrite_api_level,regular_api_level) __RENAME(rewrite) __INTRODUCED_IN(rewrite_api_level) -#define __RENAME_LDBL_NO_GUARD_FOR_NDK(rewrite,rewrite_api_level,regular_api_level) __RENAME(rewrite) __INTRODUCED_IN_NO_GUARD_FOR_NDK(rewrite_api_level) -#endif - -/* - * On all architectures, `struct stat` == `struct stat64`, but LP32 didn't gain the *64 functions - * until API level 21. - */ -#if defined(__LP64__) || defined(__BIONIC_LP32_USE_STAT64) -#define __RENAME_STAT64(rewrite,rewrite_api_level,regular_api_level) __INTRODUCED_IN(regular_api_level) -#else -#define __RENAME_STAT64(rewrite,rewrite_api_level,regular_api_level) __RENAME(rewrite) __INTRODUCED_IN(rewrite_api_level) -#endif - /* glibc compatibility. */ #if defined(__LP64__) #define __WORDSIZE 64 diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h index 54621b7b3..f773ff695 100644 --- a/libc/include/sys/stat.h +++ b/libc/include/sys/stat.h @@ -141,13 +141,13 @@ int fchmod(int __fd, mode_t __mode); int mkdir(const char* _Nonnull __path, mode_t __mode); int fstat(int __fd, struct stat* _Nonnull __buf); -int fstat64(int __fd, struct stat64* _Nonnull __buf) __RENAME_STAT64(fstat, 3, 21); +int fstat64(int __fd, struct stat64* _Nonnull __buf) __INTRODUCED_IN(21); int fstatat(int __dir_fd, const char* _Nonnull __path, struct stat* _Nonnull __buf, int __flags); -int fstatat64(int __dir_fd, const char* _Nonnull __path, struct stat64* _Nonnull __buf, int __flags) __RENAME_STAT64(fstatat, 3, 21); +int fstatat64(int __dir_fd, const char* _Nonnull __path, struct stat64* _Nonnull __buf, int __flags) __INTRODUCED_IN(21); int lstat(const char* _Nonnull __path, struct stat* _Nonnull __buf); -int lstat64(const char* _Nonnull __path, struct stat64* _Nonnull __buf) __RENAME_STAT64(lstat, 3, 21); +int lstat64(const char* _Nonnull __path, struct stat64* _Nonnull __buf) __INTRODUCED_IN(21); int stat(const char* _Nonnull __path, struct stat* _Nonnull __buf); -int stat64(const char* _Nonnull __path, struct stat64* _Nonnull __buf) __RENAME_STAT64(stat, 3, 21); +int stat64(const char* _Nonnull __path, struct stat64* _Nonnull __buf) __INTRODUCED_IN(21); int mknod(const char* _Nonnull __path, mode_t __mode, dev_t __dev); mode_t umask(mode_t __mask); diff --git a/libc/include/sys/thread_properties.h b/libc/include/sys/thread_properties.h index b5d30c77e..efd212a78 100644 --- a/libc/include/sys/thread_properties.h +++ b/libc/include/sys/thread_properties.h @@ -50,8 +50,8 @@ __BEGIN_DECLS * * Available since API level 31. */ -void __libc_get_static_tls_bounds(void** __static_tls_begin, - void** __static_tls_end) __INTRODUCED_IN(31); +void __libc_get_static_tls_bounds(void* _Nonnull * _Nonnull __static_tls_begin, + void* _Nonnull * _Nonnull __static_tls_end) __INTRODUCED_IN(31); /** @@ -66,7 +66,7 @@ void __libc_get_static_tls_bounds(void** __static_tls_begin, * * Available since API level 31. */ -void __libc_register_thread_exit_callback(void (*__cb)(void)) __INTRODUCED_IN(31); +void __libc_register_thread_exit_callback(void (* _Nonnull __cb)(void)) __INTRODUCED_IN(31); /** * Iterates over all dynamic TLS chunks for the given thread. @@ -76,11 +76,11 @@ void __libc_register_thread_exit_callback(void (*__cb)(void)) __INTRODUCED_IN(31 * Available since API level 31. */ void __libc_iterate_dynamic_tls(pid_t __tid, - void (*__cb)(void* __dynamic_tls_begin, - void* __dynamic_tls_end, + void (* _Nonnull __cb)(void* _Nonnull __dynamic_tls_begin, + void* _Nonnull __dynamic_tls_end, size_t __dso_id, - void* __arg), - void* __arg) __INTRODUCED_IN(31); + void* _Nullable __arg), + void* _Nullable __arg) __INTRODUCED_IN(31); /** * Register on_creation and on_destruction callbacks, which will be called after a dynamic @@ -89,9 +89,9 @@ void __libc_iterate_dynamic_tls(pid_t __tid, * Available since API level 31. */ void __libc_register_dynamic_tls_listeners( - void (*__on_creation)(void* __dynamic_tls_begin, - void* __dynamic_tls_end), - void (*__on_destruction)(void* __dynamic_tls_begin, - void* __dynamic_tls_end)) __INTRODUCED_IN(31); + void (* _Nonnull __on_creation)(void* _Nonnull __dynamic_tls_begin, + void* _Nonnull __dynamic_tls_end), + void (* _Nonnull __on_destruction)(void* _Nonnull __dynamic_tls_begin, + void* _Nonnull __dynamic_tls_end)) __INTRODUCED_IN(31); __END_DECLS diff --git a/libc/include/wchar.h b/libc/include/wchar.h index 39f937479..cd09a1930 100644 --- a/libc/include/wchar.h +++ b/libc/include/wchar.h @@ -102,7 +102,7 @@ wchar_t* _Nullable wcstok(wchar_t* _Nullable __s, const wchar_t* _Nonnull __deli long wcstol(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base); long wcstol_l(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base, locale_t _Nonnull __l) __INTRODUCED_IN(28); long long wcstoll(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base) __INTRODUCED_IN(21); -long double wcstold(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr) __RENAME_LDBL(wcstod, 3, 21); +long double wcstold(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr) __INTRODUCED_IN(21); unsigned long wcstoul(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base); unsigned long wcstoul_l(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base, locale_t _Nonnull __l) __INTRODUCED_IN(28); unsigned long long wcstoull(const wchar_t* _Nonnull __s, wchar_t* __BIONIC_COMPLICATED_NULLNESS * _Nullable __end_ptr, int __base) __INTRODUCED_IN(21); diff --git a/libc/platform/bionic/page.h b/libc/platform/bionic/page.h index d063a9863..5f4bb6f0f 100644 --- a/libc/platform/bionic/page.h +++ b/libc/platform/bionic/page.h @@ -16,15 +16,39 @@ #pragma once -// Get PAGE_SIZE and PAGE_MASK. +#include <stddef.h> +#include <stdint.h> +#include <sys/auxv.h> + +// For PAGE_SIZE. #include <sys/user.h> +inline size_t page_size() { + /* + * PAGE_SIZE defines the maximum supported page size. Since 4096 is the + * minimum supported page size we can just let it be constant folded if it's + * also the maximum. + */ +#if PAGE_SIZE == 4096 + return PAGE_SIZE; +#else + static size_t size = getauxval(AT_PAGESZ); + return size; +#endif +} + // Returns the address of the page containing address 'x'. -#define PAGE_START(x) ((x) & PAGE_MASK) +inline uintptr_t page_start(uintptr_t x) { + return x & ~(page_size() - 1); +} // Returns the offset of address 'x' in its page. -#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK) +inline uintptr_t page_offset(uintptr_t x) { + return x & (page_size() - 1); +} // Returns the address of the next page after address 'x', unless 'x' is // itself at the start of a page. -#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1)) +inline uintptr_t page_end(uintptr_t x) { + return page_start(x + page_size() - 1); +} diff --git a/libc/stdio/scanf_common.h b/libc/stdio/scanf_common.h new file mode 100644 index 000000000..8132e90de --- /dev/null +++ b/libc/stdio/scanf_common.h @@ -0,0 +1,115 @@ +/* $OpenBSD: vfscanf.c,v 1.31 2014/03/19 05:17:01 guenther Exp $ */ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <ctype.h> +#include <inttypes.h> +#include <limits.h> +#include <locale.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/param.h> +#include <wctype.h> +#include "local.h" + +#include <platform/bionic/macros.h> +#include <private/bionic_fortify.h> +#include <private/bionic_mbstate.h> + +#define BUF 513 /* Maximum length of numeric string. */ + +// Flags used during conversion. +// Size/type: +#define LONG 0x00001 // l: long or double +#define LONGDBL 0x00002 // L: long double +#define SHORT 0x00004 // h: short +#define SHORTSHORT 0x00008 // hh: 8 bit integer +#define LLONG 0x00010 // ll: long long (+ deprecated q: quad) +#define POINTER 0x00020 // p: void* (as hex) +#define SIZEINT 0x00040 // z: (signed) size_t +#define MAXINT 0x00080 // j: intmax_t +#define PTRINT 0x00100 // t: ptrdiff_t +#define NOSKIP 0x00200 // [ or c: do not skip blanks +// Modifiers: +#define SUPPRESS 0x00400 // *: suppress assignment +#define UNSIGNED 0x00800 // %[oupxX] conversions +#define ALLOCATE 0x01000 // m: allocate a char* +// Internal use during integer parsing: +#define SIGNOK 0x02000 // +/- is (still) legal +#define HAVESIGN 0x04000 // Sign detected +#define NDIGITS 0x08000 // No digits detected +#define PFXOK 0x10000 // "0x" prefix is (still) legal +#define PFBOK 0x20000 // "0b" prefix is (still) legal +#define NZDIGITS 0x40000 // No zero digits detected + +// Conversion types. +#define CT_CHAR 0 // %c conversion +#define CT_CCL 1 // %[...] conversion +#define CT_STRING 2 // %s conversion +#define CT_INT 3 // Integer: strtoimax/strtoumax +#define CT_FLOAT 4 // Float: strtod + +#define to_digit(c) static_cast<int>((c) - '0') +#define is_digit(c) ((unsigned)to_digit(c) <= 9) + +// Append a digit to a value and check for overflow. +#define APPEND_DIGIT(val, dig) \ + do { \ + if ((val) > INT_MAX / 10) \ + errno = ENOMEM; \ + else { \ + (val) *= 10; \ + if ((val) > INT_MAX - to_digit((dig))) \ + errno = ENOMEM; \ + else \ + (val) += to_digit((dig)); \ + } \ + } while (0) + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +// Trasnlate a fixed size integer argument for the %w/%wf format to a +// flag representation. Supported sizes are 8, 16, 32, and 64 so far. +// See details in bionic/libc/include/stdint.h +static int w_to_flag(int size, bool fast) { + static constexpr int fast_size = sizeof(void*) == 8 ? LLONG : 0; + if (size == 8) return SHORTSHORT; + if (size == 16) return fast ? fast_size : SHORT; + if (size == 32) return fast ? fast_size : 0; + if (size == 64) return LLONG; + __fortify_fatal("%%w%s%d is unsupported", fast ? "f" : "", size); +} + +#pragma clang diagnostic pop
\ No newline at end of file diff --git a/libc/stdio/vfscanf.cpp b/libc/stdio/vfscanf.cpp index dfd001d35..65f54a521 100644 --- a/libc/stdio/vfscanf.cpp +++ b/libc/stdio/vfscanf.cpp @@ -31,53 +31,7 @@ * SUCH DAMAGE. */ -#include <ctype.h> -#include <inttypes.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/param.h> -#include <wctype.h> -#include "local.h" - -#include <private/bionic_fortify.h> -#include <platform/bionic/macros.h> -#include <private/bionic_mbstate.h> - -#define BUF 513 /* Maximum length of numeric string. */ - -// Flags used during conversion. -// Size/type: -#define LONG 0x00001 // l: long or double -#define LONGDBL 0x00002 // L: long double -#define SHORT 0x00004 // h: short -#define SHORTSHORT 0x00008 // hh: 8 bit integer -#define LLONG 0x00010 // ll: long long (+ deprecated q: quad) -#define POINTER 0x00020 // p: void* (as hex) -#define SIZEINT 0x00040 // z: (signed) size_t -#define MAXINT 0x00080 // j: intmax_t -#define PTRINT 0x00100 // t: ptrdiff_t -#define NOSKIP 0x00200 // [ or c: do not skip blanks -// Modifiers: -#define SUPPRESS 0x00400 // *: suppress assignment -#define UNSIGNED 0x00800 // %[oupxX] conversions -#define ALLOCATE 0x01000 // m: allocate a char* -// Internal use during integer parsing: -#define SIGNOK 0x02000 // +/- is (still) legal -#define HAVESIGN 0x04000 // Sign detected -#define NDIGITS 0x08000 // No digits detected -#define PFXOK 0x10000 // "0x" prefix is (still) legal -#define PFBOK 0x20000 // "0b" prefix is (still) legal -#define NZDIGITS 0x40000 // No zero digits detected - -// Conversion types. -#define CT_CHAR 0 // %c conversion -#define CT_CCL 1 // %[...] conversion -#define CT_STRING 2 // %s conversion -#define CT_INT 3 // Integer: strtoimax/strtoumax -#define CT_FLOAT 4 // Float: strtod +#include "scanf_common.h" static const unsigned char* __sccl(char*, const unsigned char*); @@ -122,6 +76,7 @@ int __svfscanf(FILE* fp, const char* fmt0, va_list ap) { */ again: c = *fmt++; +reswitch: switch (c) { case '%': literal: @@ -220,6 +175,18 @@ literal: base = 10; break; + case 'w': { + int size = 0; + bool fast = false; + c = *fmt++; + while (is_digit(c)) { + APPEND_DIGIT(size, c); + c = *fmt++; + } + flags |= w_to_flag(size, fast); + goto reswitch; + } + case 'X': case 'x': flags |= PFXOK; /* enable 0x prefixing */ diff --git a/libc/stdio/vfwscanf.cpp b/libc/stdio/vfwscanf.cpp index 5f21acd0b..14b175415 100644 --- a/libc/stdio/vfwscanf.cpp +++ b/libc/stdio/vfwscanf.cpp @@ -31,62 +31,7 @@ * SUCH DAMAGE. */ -#include <inttypes.h> -#include <limits.h> -#include <locale.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <wctype.h> -#include "local.h" - -#include <platform/bionic/macros.h> - -#define BUF 513 /* Maximum length of numeric string. */ - -/* - * Flags used during conversion. - */ -#define LONG 0x00001 /* l: long or double */ -#define LONGDBL 0x00002 /* L: long double */ -#define SHORT 0x00004 /* h: short */ -#define SHORTSHORT 0x00008 /* hh: 8 bit integer */ -#define LLONG 0x00010 /* ll: long long (+ deprecated q: quad) */ -#define POINTER 0x00020 /* p: void * (as hex) */ -#define SIZEINT 0x00040 /* z: (signed) size_t */ -#define MAXINT 0x00080 /* j: intmax_t */ -#define PTRINT 0x00100 /* t: ptrdiff_t */ -#define NOSKIP 0x00200 /* [ or c: do not skip blanks */ -#define SUPPRESS 0x00400 /* *: suppress assignment */ -#define UNSIGNED 0x00800 /* %[oupxX] conversions */ - -/* - * The following are used in numeric conversions only: - * SIGNOK, HAVESIGN, NDIGITS, DPTOK, and EXPOK are for floating point; - * SIGNOK, HAVESIGN, NDIGITS, PFXOK, and NZDIGITS are for integral. - */ -#define SIGNOK 0x01000 /* +/- is (still) legal */ -#define HAVESIGN 0x02000 /* sign detected */ -#define NDIGITS 0x04000 /* no digits detected */ - -#define DPTOK 0x08000 /* (float) decimal point is still legal */ -#define EXPOK 0x10000 /* (float) exponent (e+3, etc) still legal */ - -#define PFBOK 0x20000 /* 0x prefix is (still) legal */ -#define PFXOK 0x40000 /* 0x prefix is (still) legal */ -#define NZDIGITS 0x80000 /* no zero digits detected */ - -/* - * Conversion types. - */ -#define CT_CHAR 0 /* %c conversion */ -#define CT_CCL 1 /* %[...] conversion */ -#define CT_STRING 2 /* %s conversion */ -#define CT_INT 3 /* integer, i.e., strtoimax or strtoumax */ -#define CT_FLOAT 4 /* floating, i.e., strtod */ - +#include "scanf_common.h" // An interpretive version of __sccl from vfscanf.c --- a table of all wchar_t values would // be a little too expensive, and some kind of compressed version isn't worth the trouble. static inline bool in_ccl(wchar_t wc, const wchar_t* ccl) { @@ -176,6 +121,7 @@ int __vfwscanf(FILE* __restrict fp, const wchar_t* __restrict fmt, __va_list ap) */ again: c = *fmt++; + reswitch: switch (c) { case '%': literal: @@ -273,6 +219,18 @@ int __vfwscanf(FILE* __restrict fp, const wchar_t* __restrict fmt, __va_list ap) base = 10; break; + case 'w': { + int size = 0; + bool fast = false; + c = *fmt++; + while (is_digit(c)) { + APPEND_DIGIT(size, c); + c = *fmt++; + } + flags |= w_to_flag(size, fast); + goto reswitch; + } + case 'X': case 'x': flags |= PFXOK; /* enable 0x prefixing */ diff --git a/libm/Android.bp b/libm/Android.bp index 13fbf9a79..079fd9a2c 100644 --- a/libm/Android.bp +++ b/libm/Android.bp @@ -400,7 +400,6 @@ cc_library { ], cflags: [ - "-D__BIONIC_LP32_USE_LONG_DOUBLE", "-D_BSD_SOURCE", "-DFLT_EVAL_METHOD=0", "-include freebsd-compat.h", diff --git a/linker/linker.cpp b/linker/linker.cpp index 17b574fc1..5c26944ff 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -962,7 +962,7 @@ static int open_library_in_zipfile(ZipArchiveCache* zip_archive_cache, } // Check if it is properly stored - if (entry.method != kCompressStored || (entry.offset % PAGE_SIZE) != 0) { + if (entry.method != kCompressStored || (entry.offset % page_size()) != 0) { close(fd); return -1; } @@ -1171,7 +1171,7 @@ static bool load_library(android_namespace_t* ns, "load_library(ns=%s, task=%s, flags=0x%x, realpath=%s, search_linked_namespaces=%d)", ns->get_name(), name, rtld_flags, realpath.c_str(), search_linked_namespaces); - if ((file_offset % PAGE_SIZE) != 0) { + if ((file_offset % page_size()) != 0) { DL_OPEN_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset); return false; } diff --git a/linker/linker_cfi.cpp b/linker/linker_cfi.cpp index 6bc261545..247a25d57 100644 --- a/linker/linker_cfi.cpp +++ b/linker/linker_cfi.cpp @@ -50,8 +50,8 @@ class ShadowWrite { ShadowWrite(uint16_t* s, uint16_t* e) { shadow_start = reinterpret_cast<char*>(s); shadow_end = reinterpret_cast<char*>(e); - aligned_start = reinterpret_cast<char*>(PAGE_START(reinterpret_cast<uintptr_t>(shadow_start))); - aligned_end = reinterpret_cast<char*>(PAGE_END(reinterpret_cast<uintptr_t>(shadow_end))); + aligned_start = reinterpret_cast<char*>(page_start(reinterpret_cast<uintptr_t>(shadow_start))); + aligned_end = reinterpret_cast<char*>(page_end(reinterpret_cast<uintptr_t>(shadow_end))); tmp_start = reinterpret_cast<char*>(mmap(nullptr, aligned_end - aligned_start, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); @@ -204,7 +204,7 @@ bool CFIShadowWriter::NotifyLibDl(soinfo* solist, uintptr_t p) { shadow_start = reinterpret_cast<uintptr_t* (*)(uintptr_t)>(cfi_init)(p); CHECK(shadow_start != nullptr); CHECK(*shadow_start == p); - mprotect(shadow_start, PAGE_SIZE, PROT_READ); + mprotect(shadow_start, page_size(), PROT_READ); return true; } diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp index 26e222876..f7c8ea959 100644 --- a/linker/linker_main.cpp +++ b/linker/linker_main.cpp @@ -580,8 +580,8 @@ static void set_bss_vma_name(soinfo* si) { } ElfW(Addr) seg_start = phdr->p_vaddr + si->load_bias; - ElfW(Addr) seg_page_end = PAGE_END(seg_start + phdr->p_memsz); - ElfW(Addr) seg_file_end = PAGE_END(seg_start + phdr->p_filesz); + ElfW(Addr) seg_page_end = page_end(seg_start + phdr->p_memsz); + ElfW(Addr) seg_file_end = page_end(seg_start + phdr->p_filesz); if (seg_page_end > seg_file_end) { prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, diff --git a/linker/linker_mapped_file_fragment.cpp b/linker/linker_mapped_file_fragment.cpp index cbe5f6680..6be1b2bfe 100644 --- a/linker/linker_mapped_file_fragment.cpp +++ b/linker/linker_mapped_file_fragment.cpp @@ -29,6 +29,7 @@ #include "linker_mapped_file_fragment.h" #include "linker_debug.h" #include "linker_utils.h" +#include "platform/bionic/page.h" #include <inttypes.h> #include <stdlib.h> diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp index 73cfced38..97ae7090f 100644 --- a/linker/linker_phdr.cpp +++ b/linker/linker_phdr.cpp @@ -116,7 +116,7 @@ static int GetTargetElfMachine() { can only memory-map at page boundaries, this means that the bias is computed as: - load_bias = phdr0_load_address - PAGE_START(phdr0->p_vaddr) + load_bias = phdr0_load_address - page_start(phdr0->p_vaddr) (NOTE: The value must be used as a 32-bit unsigned integer, to deal with possible wrap around UINT32_MAX for possible large p_vaddr values). @@ -124,11 +124,11 @@ static int GetTargetElfMachine() { And that the phdr0_load_address must start at a page boundary, with the segment's real content starting at: - phdr0_load_address + PAGE_OFFSET(phdr0->p_vaddr) + phdr0_load_address + page_offset(phdr0->p_vaddr) Note that ELF requires the following condition to make the mmap()-ing work: - PAGE_OFFSET(phdr0->p_vaddr) == PAGE_OFFSET(phdr0->p_offset) + page_offset(phdr0->p_vaddr) == page_offset(phdr0->p_offset) The load_bias must be added to any p_vaddr value read from the ELF file to determine the corresponding memory address. @@ -529,8 +529,8 @@ size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count, min_vaddr = 0; } - min_vaddr = PAGE_START(min_vaddr); - max_vaddr = PAGE_END(max_vaddr); + min_vaddr = page_start(min_vaddr); + max_vaddr = page_end(max_vaddr); if (out_min_vaddr != nullptr) { *out_min_vaddr = min_vaddr; @@ -545,7 +545,7 @@ size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count, // program header table. Used to determine whether the file should be loaded at // a specific virtual address alignment for use with huge pages. size_t phdr_table_get_maximum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count) { - size_t maximum_alignment = PAGE_SIZE; + size_t maximum_alignment = page_size(); for (size_t i = 0; i < phdr_count; ++i) { const ElfW(Phdr)* phdr = &phdr_table[i]; @@ -563,7 +563,7 @@ size_t phdr_table_get_maximum_alignment(const ElfW(Phdr)* phdr_table, size_t phd #if defined(__LP64__) return maximum_alignment; #else - return PAGE_SIZE; + return page_size(); #endif } @@ -574,7 +574,7 @@ static void* ReserveWithAlignmentPadding(size_t size, size_t mapping_align, size int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS; // Reserve enough space to properly align the library's start address. mapping_align = std::max(mapping_align, start_align); - if (mapping_align == PAGE_SIZE) { + if (mapping_align == page_size()) { void* mmap_ptr = mmap(nullptr, size, PROT_NONE, mmap_flags, -1, 0); if (mmap_ptr == MAP_FAILED) { return nullptr; @@ -593,7 +593,7 @@ static void* ReserveWithAlignmentPadding(size_t size, size_t mapping_align, size constexpr size_t kMaxGapUnits = 32; // Allocate enough space so that the end of the desired region aligned up is still inside the // mapping. - size_t mmap_size = align_up(size, mapping_align) + mapping_align - PAGE_SIZE; + size_t mmap_size = align_up(size, mapping_align) + mapping_align - page_size(); uint8_t* mmap_ptr = reinterpret_cast<uint8_t*>(mmap(nullptr, mmap_size, PROT_NONE, mmap_flags, -1, 0)); if (mmap_ptr == MAP_FAILED) { @@ -610,7 +610,7 @@ static void* ReserveWithAlignmentPadding(size_t size, size_t mapping_align, size mapping_align = std::max(mapping_align, kGapAlignment); gap_size = kGapAlignment * (is_first_stage_init() ? 1 : arc4random_uniform(kMaxGapUnits - 1) + 1); - mmap_size = align_up(size + gap_size, mapping_align) + mapping_align - PAGE_SIZE; + mmap_size = align_up(size + gap_size, mapping_align) + mapping_align - page_size(); mmap_ptr = reinterpret_cast<uint8_t*>(mmap(nullptr, mmap_size, PROT_NONE, mmap_flags, -1, 0)); if (mmap_ptr == MAP_FAILED) { return nullptr; @@ -665,12 +665,12 @@ bool ElfReader::ReserveAddressSpace(address_space_params* address_space) { load_size_ - address_space->reserved_size, load_size_, name_.c_str()); return false; } - size_t start_alignment = PAGE_SIZE; + size_t start_alignment = page_size(); if (get_transparent_hugepages_supported() && get_application_target_sdk_version() >= 31) { size_t maximum_alignment = phdr_table_get_maximum_alignment(phdr_table_, phdr_num_); // Limit alignment to PMD size as other alignments reduce the number of // bits available for ASLR for no benefit. - start_alignment = maximum_alignment == kPmdSize ? kPmdSize : PAGE_SIZE; + start_alignment = maximum_alignment == kPmdSize ? kPmdSize : page_size(); } start = ReserveWithAlignmentPadding(load_size_, kLibraryAlignment, start_alignment, &gap_start_, &gap_size_); @@ -706,8 +706,8 @@ bool ElfReader::LoadSegments() { ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_; ElfW(Addr) seg_end = seg_start + phdr->p_memsz; - ElfW(Addr) seg_page_start = PAGE_START(seg_start); - ElfW(Addr) seg_page_end = PAGE_END(seg_end); + ElfW(Addr) seg_page_start = page_start(seg_start); + ElfW(Addr) seg_page_end = page_end(seg_end); ElfW(Addr) seg_file_end = seg_start + phdr->p_filesz; @@ -715,7 +715,7 @@ bool ElfReader::LoadSegments() { ElfW(Addr) file_start = phdr->p_offset; ElfW(Addr) file_end = file_start + phdr->p_filesz; - ElfW(Addr) file_page_start = PAGE_START(file_start); + ElfW(Addr) file_page_start = page_start(file_start); ElfW(Addr) file_length = file_end - file_page_start; if (file_size_ <= 0) { @@ -768,11 +768,11 @@ bool ElfReader::LoadSegments() { // if the segment is writable, and does not end on a page boundary, // zero-fill it until the page limit. - if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) { - memset(reinterpret_cast<void*>(seg_file_end), 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end)); + if ((phdr->p_flags & PF_W) != 0 && page_offset(seg_file_end) > 0) { + memset(reinterpret_cast<void*>(seg_file_end), 0, page_size() - page_offset(seg_file_end)); } - seg_file_end = PAGE_END(seg_file_end); + seg_file_end = page_end(seg_file_end); // seg_file_end is now the first page address after the file // content. If seg_end is larger, we need to zero anything @@ -811,8 +811,8 @@ static int _phdr_table_set_load_prot(const ElfW(Phdr)* phdr_table, size_t phdr_c continue; } - ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; - ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; + ElfW(Addr) seg_page_start = page_start(phdr->p_vaddr) + load_bias; + ElfW(Addr) seg_page_end = page_end(phdr->p_vaddr + phdr->p_memsz) + load_bias; int prot = PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags; if ((prot & PROT_WRITE) != 0) { @@ -912,8 +912,8 @@ static int _phdr_table_set_gnu_relro_prot(const ElfW(Phdr)* phdr_table, size_t p // the program is likely to fail at runtime. So in effect the // linker must only emit a PT_GNU_RELRO segment if it ensures // that it starts on a page boundary. - ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; - ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; + ElfW(Addr) seg_page_start = page_start(phdr->p_vaddr) + load_bias; + ElfW(Addr) seg_page_end = page_end(phdr->p_vaddr + phdr->p_memsz) + load_bias; int ret = mprotect(reinterpret_cast<void*>(seg_page_start), seg_page_end - seg_page_start, @@ -972,8 +972,8 @@ int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, continue; } - ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; - ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; + ElfW(Addr) seg_page_start = page_start(phdr->p_vaddr) + load_bias; + ElfW(Addr) seg_page_end = page_end(phdr->p_vaddr + phdr->p_memsz) + load_bias; ssize_t size = seg_page_end - seg_page_start; ssize_t written = TEMP_FAILURE_RETRY(write(fd, reinterpret_cast<void*>(seg_page_start), size)); @@ -1035,8 +1035,8 @@ int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, continue; } - ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; - ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; + ElfW(Addr) seg_page_start = page_start(phdr->p_vaddr) + load_bias; + ElfW(Addr) seg_page_end = page_end(phdr->p_vaddr + phdr->p_memsz) + load_bias; char* file_base = static_cast<char*>(temp_mapping) + *file_offset; char* mem_base = reinterpret_cast<char*>(seg_page_start); @@ -1053,15 +1053,15 @@ int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, while (match_offset < size) { // Skip over dissimilar pages. while (match_offset < size && - memcmp(mem_base + match_offset, file_base + match_offset, PAGE_SIZE) != 0) { - match_offset += PAGE_SIZE; + memcmp(mem_base + match_offset, file_base + match_offset, page_size()) != 0) { + match_offset += page_size(); } // Count similar pages. size_t mismatch_offset = match_offset; while (mismatch_offset < size && - memcmp(mem_base + mismatch_offset, file_base + mismatch_offset, PAGE_SIZE) == 0) { - mismatch_offset += PAGE_SIZE; + memcmp(mem_base + mismatch_offset, file_base + mismatch_offset, page_size()) == 0) { + mismatch_offset += page_size(); } // Map over similar pages. diff --git a/linker/linker_utils.cpp b/linker/linker_utils.cpp index 29110ed56..cd03eedae 100644 --- a/linker/linker_utils.cpp +++ b/linker/linker_utils.cpp @@ -169,12 +169,6 @@ bool parse_zip_path(const char* input_path, std::string* zip_path, std::string* return true; } -constexpr off64_t kPageMask = ~static_cast<off64_t>(PAGE_SIZE-1); - -off64_t page_start(off64_t offset) { - return offset & kPageMask; -} - bool safe_add(off64_t* out, off64_t a, size_t b) { CHECK(a >= 0); if (static_cast<uint64_t>(INT64_MAX - a) < b) { @@ -185,10 +179,6 @@ bool safe_add(off64_t* out, off64_t a, size_t b) { return true; } -size_t page_offset(off64_t offset) { - return static_cast<size_t>(offset & (PAGE_SIZE-1)); -} - void split_path(const char* path, const char* delimiters, std::vector<std::string>* paths) { if (path != nullptr && path[0] != 0) { diff --git a/linker/linker_utils.h b/linker/linker_utils.h index 5073b1068..3049e5347 100644 --- a/linker/linker_utils.h +++ b/linker/linker_utils.h @@ -55,7 +55,5 @@ void split_path(const char* path, const char* delimiters, std::vector<std::strin std::string dirname(const char* path); -off64_t page_start(off64_t offset); -size_t page_offset(off64_t offset); bool safe_add(off64_t* out, off64_t a, size_t b); bool is_first_stage_init(); diff --git a/linker/linker_utils_test.cpp b/linker/linker_utils_test.cpp index 44907dabf..0b881d432 100644 --- a/linker/linker_utils_test.cpp +++ b/linker/linker_utils_test.cpp @@ -33,6 +33,7 @@ #include <gtest/gtest.h> #include "linker_utils.h" +#include "platform/bionic/page.h" TEST(linker_utils, format_string) { std::vector<std::pair<std::string, std::string>> params = {{ "LIB", "lib32"}, { "SDKVER", "42"}}; @@ -104,9 +105,9 @@ TEST(linker_utils, parse_zip_path_smoke) { } TEST(linker_utils, page_start) { - ASSERT_EQ(0x0001000, page_start(0x0001000)); - ASSERT_EQ(0x3002000, page_start(0x300222f)); - ASSERT_EQ(0x6001000, page_start(0x6001fff)); + ASSERT_EQ(0x0001000U, page_start(0x0001000)); + ASSERT_EQ(0x3002000U, page_start(0x300222f)); + ASSERT_EQ(0x6001000U, page_start(0x6001fff)); } TEST(linker_utils, page_offset) { diff --git a/tests/Android.bp b/tests/Android.bp index 281e29d6a..36a3a3794 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -386,7 +386,6 @@ cc_test_library { "bug_26110743_test.cpp", "byteswap_test.cpp", "complex_test.cpp", - "complex_force_long_double_test.cpp", "ctype_test.cpp", "dirent_test.cpp", "elf_test.cpp", @@ -423,7 +422,6 @@ cc_test_library { "malloc_iterate_test.cpp", "malloc_test.cpp", "math_test.cpp", - "math_force_long_double_test.cpp", "membarrier_test.cpp", "memtag_stack_test.cpp", "mntent_test.cpp", diff --git a/tests/complex_force_long_double_test.cpp b/tests/complex_force_long_double_test.cpp deleted file mode 100644 index 2ea7bd449..000000000 --- a/tests/complex_force_long_double_test.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define __BIONIC_LP32_USE_LONG_DOUBLE -#include "complex_test.cpp" diff --git a/tests/complex_test.cpp b/tests/complex_test.cpp index f015b2c2d..6a1831f78 100644 --- a/tests/complex_test.cpp +++ b/tests/complex_test.cpp @@ -14,20 +14,11 @@ * limitations under the License. */ -#if defined(__BIONIC_LP32_USE_LONG_DOUBLE) -#define COMPLEX_TEST complex_h_force_long_double -#else -#define COMPLEX_TEST complex_h -#endif - // This file is compiled against both glibc and bionic, and our complex.h // depends on bionic-specific macros, so hack around that. #include <sys/cdefs.h> #if !defined(__INTRODUCED_IN) #define __INTRODUCED_IN(x) -#define __INTRODUCED_IN_32(x) -#define __INTRODUCED_IN_64(x) -#define __RENAME_LDBL(a,b,c) #endif // libc++ actively gets in the way of including <complex.h> from C++, so we @@ -62,259 +53,259 @@ inline void PrintTo(const long double _Complex& c, std::ostream* os) { #include <gtest/gtest.h> #pragma pop_macro("I") -TEST(COMPLEX_TEST, cabs) { +TEST(complex_h, cabs) { ASSERT_EQ(0.0, cabs(0)); } -TEST(COMPLEX_TEST, cabsf) { +TEST(complex_h, cabsf) { ASSERT_EQ(0.0, cabsf(0)); } -TEST(COMPLEX_TEST, cabsl) { +TEST(complex_h, cabsl) { ASSERT_EQ(0.0, cabsl(0)); } -TEST(COMPLEX_TEST, cacos) { +TEST(complex_h, cacos) { ASSERT_EQ(M_PI_2, cacos(0.0)); } -TEST(COMPLEX_TEST, cacosf) { +TEST(complex_h, cacosf) { ASSERT_EQ(static_cast<float>(M_PI_2), cacosf(0.0)); } -TEST(COMPLEX_TEST, cacosl) { +TEST(complex_h, cacosl) { ASSERT_EQ(M_PI_2l, cacosl(0.0)); } -TEST(COMPLEX_TEST, cacosh) { +TEST(complex_h, cacosh) { ASSERT_EQ(0.0, cacosh(1.0)); } -TEST(COMPLEX_TEST, cacoshl) { +TEST(complex_h, cacoshl) { ASSERT_EQ(0.0, cacoshl(1.0)); } -TEST(COMPLEX_TEST, cacoshf) { +TEST(complex_h, cacoshf) { ASSERT_EQ(0.0, cacoshf(1.0)); } -TEST(COMPLEX_TEST, carg) { +TEST(complex_h, carg) { ASSERT_EQ(0.0, carg(0)); } -TEST(COMPLEX_TEST, cargf) { +TEST(complex_h, cargf) { ASSERT_EQ(0.0, cargf(0)); } -TEST(COMPLEX_TEST, cargl) { +TEST(complex_h, cargl) { ASSERT_EQ(0.0, cargl(0)); } -TEST(COMPLEX_TEST, casin) { +TEST(complex_h, casin) { ASSERT_EQ(0.0, casin(0)); } -TEST(COMPLEX_TEST, casinf) { +TEST(complex_h, casinf) { ASSERT_EQ(0.0, casinf(0)); } -TEST(COMPLEX_TEST, casinl) { +TEST(complex_h, casinl) { ASSERT_EQ(0.0, casinl(0)); } -TEST(COMPLEX_TEST, casinh) { +TEST(complex_h, casinh) { ASSERT_EQ(0.0, casinh(0)); } -TEST(COMPLEX_TEST, casinhf) { +TEST(complex_h, casinhf) { ASSERT_EQ(0.0, casinhf(0)); } -TEST(COMPLEX_TEST, casinhl) { +TEST(complex_h, casinhl) { ASSERT_EQ(0.0, casinhl(0)); } -TEST(COMPLEX_TEST, catan) { +TEST(complex_h, catan) { ASSERT_EQ(0.0, catan(0)); } -TEST(COMPLEX_TEST, catanf) { +TEST(complex_h, catanf) { ASSERT_EQ(0.0, catanf(0)); } -TEST(COMPLEX_TEST, catanl) { +TEST(complex_h, catanl) { ASSERT_EQ(0.0, catanl(0)); } -TEST(COMPLEX_TEST, catanh) { +TEST(complex_h, catanh) { ASSERT_EQ(0.0, catanh(0)); } -TEST(COMPLEX_TEST, catanhf) { +TEST(complex_h, catanhf) { ASSERT_EQ(0.0, catanhf(0)); } -TEST(COMPLEX_TEST, catanhl) { +TEST(complex_h, catanhl) { ASSERT_EQ(0.0, catanhl(0)); } -TEST(COMPLEX_TEST, ccos) { +TEST(complex_h, ccos) { ASSERT_EQ(1.0, ccos(0)); } -TEST(COMPLEX_TEST, ccosf) { +TEST(complex_h, ccosf) { ASSERT_EQ(1.0, ccosf(0)); } -TEST(COMPLEX_TEST, ccosl) { +TEST(complex_h, ccosl) { ASSERT_EQ(1.0, ccosl(0)); } -TEST(COMPLEX_TEST, ccosh) { +TEST(complex_h, ccosh) { ASSERT_EQ(1.0, ccosh(0)); } -TEST(COMPLEX_TEST, ccoshf) { +TEST(complex_h, ccoshf) { ASSERT_EQ(1.0, ccoshf(0)); } -TEST(COMPLEX_TEST, ccoshl) { +TEST(complex_h, ccoshl) { ASSERT_EQ(1.0, ccoshl(0)); } -TEST(COMPLEX_TEST, cexp) { +TEST(complex_h, cexp) { ASSERT_EQ(1.0, cexp(0)); } -TEST(COMPLEX_TEST, cexpf) { +TEST(complex_h, cexpf) { ASSERT_EQ(1.0, cexpf(0)); } -TEST(COMPLEX_TEST, cexpl) { +TEST(complex_h, cexpl) { ASSERT_EQ(1.0, cexpl(0)); } -TEST(COMPLEX_TEST, cimag) { +TEST(complex_h, cimag) { ASSERT_EQ(0.0, cimag(0)); } -TEST(COMPLEX_TEST, cimagf) { +TEST(complex_h, cimagf) { ASSERT_EQ(0.0f, cimagf(0)); } -TEST(COMPLEX_TEST, cimagl) { +TEST(complex_h, cimagl) { ASSERT_EQ(0.0, cimagl(0)); } -TEST(COMPLEX_TEST, clog) { +TEST(complex_h, clog) { ASSERT_EQ(0.0, clog(1.0)); } -TEST(COMPLEX_TEST, clogf) { +TEST(complex_h, clogf) { ASSERT_EQ(0.0f, clogf(1.0f)); } -TEST(COMPLEX_TEST, clogl) { +TEST(complex_h, clogl) { ASSERT_EQ(0.0L, clogl(1.0L)); } -TEST(COMPLEX_TEST, conj) { +TEST(complex_h, conj) { ASSERT_EQ(0.0, conj(0)); } -TEST(COMPLEX_TEST, conjf) { +TEST(complex_h, conjf) { ASSERT_EQ(0.0f, conjf(0)); } -TEST(COMPLEX_TEST, conjl) { +TEST(complex_h, conjl) { ASSERT_EQ(0.0, conjl(0)); } -TEST(COMPLEX_TEST, cpow) { +TEST(complex_h, cpow) { ASSERT_EQ(8.0, cpow(2.0, 3.0)); } -TEST(COMPLEX_TEST, cpowf) { +TEST(complex_h, cpowf) { ASSERT_EQ(8.0f, cpowf(2.0f, 3.0f)); } -TEST(COMPLEX_TEST, cpowl) { +TEST(complex_h, cpowl) { ASSERT_EQ(8.0L, cpowl(2.0L, 3.0L)); } -TEST(COMPLEX_TEST, cproj) { +TEST(complex_h, cproj) { ASSERT_EQ(0.0, cproj(0)); } -TEST(COMPLEX_TEST, cprojf) { +TEST(complex_h, cprojf) { ASSERT_EQ(0.0f, cprojf(0)); } -TEST(COMPLEX_TEST, cprojl) { +TEST(complex_h, cprojl) { ASSERT_EQ(0.0, cprojl(0)); } -TEST(COMPLEX_TEST, creal) { +TEST(complex_h, creal) { ASSERT_EQ(2.0, creal(2.0 + 3.0I)); } -TEST(COMPLEX_TEST, crealf) { +TEST(complex_h, crealf) { ASSERT_EQ(2.0f, crealf(2.0f + 3.0fI)); } -TEST(COMPLEX_TEST, creall) { +TEST(complex_h, creall) { ASSERT_EQ(2.0, creall(2.0L + 3.0LI)); } -TEST(COMPLEX_TEST, csin) { +TEST(complex_h, csin) { ASSERT_EQ(0.0, csin(0)); } -TEST(COMPLEX_TEST, csinf) { +TEST(complex_h, csinf) { ASSERT_EQ(0.0, csinf(0)); } -TEST(COMPLEX_TEST, csinl) { +TEST(complex_h, csinl) { ASSERT_EQ(0.0, csinl(0)); } -TEST(COMPLEX_TEST, csinh) { +TEST(complex_h, csinh) { ASSERT_EQ(0.0, csinh(0)); } -TEST(COMPLEX_TEST, csinhf) { +TEST(complex_h, csinhf) { ASSERT_EQ(0.0, csinhf(0)); } -TEST(COMPLEX_TEST, csinhl) { +TEST(complex_h, csinhl) { ASSERT_EQ(0.0, csinhl(0)); } -TEST(COMPLEX_TEST, csqrt) { +TEST(complex_h, csqrt) { ASSERT_EQ(0.0, csqrt(0)); } -TEST(COMPLEX_TEST, csqrtf) { +TEST(complex_h, csqrtf) { ASSERT_EQ(0.0f, csqrtf(0)); } -TEST(COMPLEX_TEST, csqrtl) { +TEST(complex_h, csqrtl) { ASSERT_EQ(0.0, csqrtl(0)); } -TEST(COMPLEX_TEST, ctan) { +TEST(complex_h, ctan) { ASSERT_EQ(0.0, ctan(0)); } -TEST(COMPLEX_TEST, ctanf) { +TEST(complex_h, ctanf) { ASSERT_EQ(0.0, ctanf(0)); } -TEST(COMPLEX_TEST, ctanl) { +TEST(complex_h, ctanl) { ASSERT_EQ(0.0, ctanl(0)); } -TEST(COMPLEX_TEST, ctanh) { +TEST(complex_h, ctanh) { ASSERT_EQ(0.0, ctanh(0)); double complex z; @@ -335,7 +326,7 @@ TEST(COMPLEX_TEST, ctanh) { ASSERT_TRUE(isnan(cimag(z))); } -TEST(COMPLEX_TEST, ctanhf) { +TEST(complex_h, ctanhf) { ASSERT_EQ(0.0f, ctanhf(0.0f)); float complex z; @@ -356,7 +347,7 @@ TEST(COMPLEX_TEST, ctanhf) { ASSERT_TRUE(isnan(cimagf(z))); } -TEST(COMPLEX_TEST, ctanhl) { +TEST(complex_h, ctanhl) { ASSERT_EQ(0.0L, ctanhl(0.0L)); long double complex z; diff --git a/tests/math_force_long_double_test.cpp b/tests/math_force_long_double_test.cpp deleted file mode 100644 index 432182b72..000000000 --- a/tests/math_force_long_double_test.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#define __BIONIC_LP32_USE_LONG_DOUBLE -#include "math_test.cpp" diff --git a/tests/math_test.cpp b/tests/math_test.cpp index 60872f373..493f3aff7 100644 --- a/tests/math_test.cpp +++ b/tests/math_test.cpp @@ -48,12 +48,6 @@ template<typename T> inline int test_capture_isinf(const T in) { } } -#if defined(__BIONIC_LP32_USE_LONG_DOUBLE) -#define MATH_TEST math_h_force_long_double -#else -#define MATH_TEST math_h -#endif - #include "math_data_test.h" #include <gtest/gtest.h> @@ -103,7 +97,7 @@ static long double ldouble_subnormal() { return u.e; } -TEST(MATH_TEST, fpclassify) { +TEST(math_h, fpclassify) { ASSERT_EQ(FP_INFINITE, fpclassify(INFINITY)); ASSERT_EQ(FP_INFINITE, fpclassify(HUGE_VALF)); ASSERT_EQ(FP_INFINITE, fpclassify(-HUGE_VALF)); @@ -129,7 +123,7 @@ TEST(MATH_TEST, fpclassify) { ASSERT_EQ(FP_ZERO, fpclassify(0.0L)); } -TEST(MATH_TEST, isfinite) { +TEST(math_h, isfinite) { ASSERT_TRUE(test_capture_isfinite(123.0f)); ASSERT_TRUE(test_capture_isfinite(123.0)); ASSERT_TRUE(test_capture_isfinite(123.0L)); @@ -141,7 +135,7 @@ TEST(MATH_TEST, isfinite) { ASSERT_FALSE(test_capture_isfinite(-HUGE_VALL)); } -TEST(MATH_TEST, isinf) { +TEST(math_h, isinf) { ASSERT_FALSE(test_capture_isinf(123.0f)); ASSERT_FALSE(test_capture_isinf(123.0)); ASSERT_FALSE(test_capture_isinf(123.0L)); @@ -153,7 +147,7 @@ TEST(MATH_TEST, isinf) { ASSERT_TRUE(test_capture_isinf(-HUGE_VALL)); } -TEST(MATH_TEST, isnan) { +TEST(math_h, isnan) { ASSERT_FALSE(test_capture_isnan(123.0f)); ASSERT_FALSE(test_capture_isnan(123.0)); ASSERT_FALSE(test_capture_isnan(123.0L)); @@ -162,7 +156,7 @@ TEST(MATH_TEST, isnan) { ASSERT_TRUE(test_capture_isnan(nanl(""))); } -TEST(MATH_TEST, isnormal) { +TEST(math_h, isnormal) { ASSERT_TRUE(isnormal(123.0f)); ASSERT_TRUE(isnormal(123.0)); ASSERT_TRUE(isnormal(123.0L)); @@ -172,7 +166,7 @@ TEST(MATH_TEST, isnormal) { } // TODO: isgreater, isgreaterequals, isless, islessequal, islessgreater, isunordered -TEST(MATH_TEST, signbit) { +TEST(math_h, signbit) { ASSERT_EQ(0, test_capture_signbit(0.0f)); ASSERT_EQ(0, test_capture_signbit(0.0)); ASSERT_EQ(0, test_capture_signbit(0.0L)); @@ -192,7 +186,7 @@ extern "C" int __fpclassifyd(double); extern "C" int __fpclassifyf(float); extern "C" int __fpclassifyl(long double); -TEST(MATH_TEST, __fpclassify) { +TEST(math_h, __fpclassify) { ASSERT_EQ(FP_INFINITE, __fpclassify(HUGE_VAL)); ASSERT_EQ(FP_INFINITE, __fpclassify(-HUGE_VAL)); ASSERT_EQ(FP_NAN, __fpclassify(nan(""))); @@ -201,7 +195,7 @@ TEST(MATH_TEST, __fpclassify) { ASSERT_EQ(FP_ZERO, __fpclassify(0.0)); } -TEST(MATH_TEST, __fpclassifyd) { +TEST(math_h, __fpclassifyd) { #if defined(__GLIBC__) || defined(ANDROID_HOST_MUSL) #define __fpclassifyd __fpclassify #endif @@ -213,7 +207,7 @@ TEST(MATH_TEST, __fpclassifyd) { ASSERT_EQ(FP_ZERO, __fpclassifyd(0.0)); } -TEST(MATH_TEST, __fpclassifyf) { +TEST(math_h, __fpclassifyf) { ASSERT_EQ(FP_INFINITE, __fpclassifyf(HUGE_VALF)); ASSERT_EQ(FP_INFINITE, __fpclassifyf(-HUGE_VALF)); ASSERT_EQ(FP_NAN, __fpclassifyf(nanf(""))); @@ -222,7 +216,7 @@ TEST(MATH_TEST, __fpclassifyf) { ASSERT_EQ(FP_ZERO, __fpclassifyf(0.0f)); } -TEST(MATH_TEST, __fpclassifyl) { +TEST(math_h, __fpclassifyl) { EXPECT_EQ(FP_INFINITE, __fpclassifyl(HUGE_VALL)); EXPECT_EQ(FP_INFINITE, __fpclassifyl(-HUGE_VALL)); EXPECT_EQ(FP_NAN, __fpclassifyl(nanl(""))); @@ -231,7 +225,7 @@ TEST(MATH_TEST, __fpclassifyl) { EXPECT_EQ(FP_ZERO, __fpclassifyl(0.0L)); } -TEST(MATH_TEST, finitef) { +TEST(math_h, finitef) { ASSERT_TRUE(finitef(123.0f)); ASSERT_FALSE(finitef(HUGE_VALF)); ASSERT_FALSE(finitef(-HUGE_VALF)); @@ -244,7 +238,7 @@ extern "C" int isfinitef(float); extern "C" int __isfinitel(long double); extern "C" int isfinitel(long double); -TEST(MATH_TEST, __isfinite) { +TEST(math_h, __isfinite) { #if defined(__GLIBC__) #define __isfinite __finite #elif defined(ANDROID_HOST_MUSL) @@ -255,7 +249,7 @@ TEST(MATH_TEST, __isfinite) { ASSERT_FALSE(__isfinite(-HUGE_VAL)); } -TEST(MATH_TEST, __isfinitef) { +TEST(math_h, __isfinitef) { #if defined(__GLIBC__) #define __isfinitef __finitef #elif defined(ANDROID_HOST_MUSL) @@ -266,7 +260,7 @@ TEST(MATH_TEST, __isfinitef) { ASSERT_FALSE(__isfinitef(-HUGE_VALF)); } -TEST(MATH_TEST, isfinitef) { +TEST(math_h, isfinitef) { #if defined(__GLIBC__) #define isfinitef __finitef #elif defined(ANDROID_HOST_MUSL) @@ -277,7 +271,7 @@ TEST(MATH_TEST, isfinitef) { ASSERT_FALSE(isfinitef(-HUGE_VALF)); } -TEST(MATH_TEST, __isfinitel) { +TEST(math_h, __isfinitel) { #if defined(__GLIBC__) #define __isfinitel __finitel #elif defined(ANDROID_HOST_MUSL) @@ -288,7 +282,7 @@ TEST(MATH_TEST, __isfinitel) { ASSERT_FALSE(__isfinitel(-HUGE_VALL)); } -TEST(MATH_TEST, isfinitel) { +TEST(math_h, isfinitel) { #if defined(__GLIBC__) #define isfinitel __finitel #elif defined(ANDROID_HOST_MUSL) @@ -299,13 +293,13 @@ TEST(MATH_TEST, isfinitel) { ASSERT_FALSE(isfinitel(-HUGE_VALL)); } -TEST(MATH_TEST, finite) { +TEST(math_h, finite) { ASSERT_TRUE(finite(123.0)); ASSERT_FALSE(finite(HUGE_VAL)); ASSERT_FALSE(finite(-HUGE_VAL)); } -TEST(MATH_TEST, isinf_function) { +TEST(math_h, isinf_function) { // The isinf macro deals with all three types; the isinf function is for doubles. ASSERT_FALSE((isinf)(123.0)); ASSERT_TRUE((isinf)(HUGE_VAL)); @@ -319,7 +313,7 @@ extern "C" int isinff(float); extern "C" int __isinfl(long double); extern "C" int isinfl(long double); -TEST(MATH_TEST, __isinf) { +TEST(math_h, __isinf) { #if defined(ANDROID_HOST_MUSL) #define __isinf isinf #endif @@ -328,7 +322,7 @@ TEST(MATH_TEST, __isinf) { ASSERT_TRUE(__isinf(-HUGE_VAL)); } -TEST(MATH_TEST, __isinff) { +TEST(math_h, __isinff) { #if defined(ANDROID_HOST_MUSL) #define __isinff isinf #endif @@ -337,7 +331,7 @@ TEST(MATH_TEST, __isinff) { ASSERT_TRUE(__isinff(-HUGE_VALF)); } -TEST(MATH_TEST, isinff) { +TEST(math_h, isinff) { #if defined(ANDROID_HOST_MUSL) #define isinff isinf #endif @@ -346,7 +340,7 @@ TEST(MATH_TEST, isinff) { ASSERT_TRUE(isinff(-HUGE_VALF)); } -TEST(MATH_TEST, __isinfl) { +TEST(math_h, __isinfl) { #if defined(ANDROID_HOST_MUSL) #define __isinfl isinf #endif @@ -355,7 +349,7 @@ TEST(MATH_TEST, __isinfl) { ASSERT_TRUE(__isinfl(-HUGE_VALL)); } -TEST(MATH_TEST, isinfl) { +TEST(math_h, isinfl) { #if defined(ANDROID_HOST_MUSL) #define isinfl isinf #endif @@ -364,7 +358,7 @@ TEST(MATH_TEST, isinfl) { ASSERT_TRUE(isinfl(-HUGE_VALL)); } -TEST(MATH_TEST, isnan_function) { +TEST(math_h, isnan_function) { // The isnan macro deals with all three types; the isnan function is for doubles. ASSERT_FALSE((isnan)(123.0)); ASSERT_TRUE((isnan)(nan(""))); @@ -377,7 +371,7 @@ extern "C" int isnanf(float); extern "C" int __isnanl(long double); extern "C" int isnanl(long double); -TEST(MATH_TEST, __isnan) { +TEST(math_h, __isnan) { #if defined(ANDROID_HOST_MUSL) #define __isnan isnan #endif @@ -385,7 +379,7 @@ TEST(MATH_TEST, __isnan) { ASSERT_TRUE(__isnan(nan(""))); } -TEST(MATH_TEST, __isnanf) { +TEST(math_h, __isnanf) { #if defined(ANDROID_HOST_MUSL) #define __isnanf isnan #endif @@ -393,7 +387,7 @@ TEST(MATH_TEST, __isnanf) { ASSERT_TRUE(__isnanf(nanf(""))); } -TEST(MATH_TEST, isnanf) { +TEST(math_h, isnanf) { #if defined(ANDROID_HOST_MUSL) #define isnanf isnan #endif @@ -401,7 +395,7 @@ TEST(MATH_TEST, isnanf) { ASSERT_TRUE(isnanf(nanf(""))); } -TEST(MATH_TEST, __isnanl) { +TEST(math_h, __isnanl) { #if defined(ANDROID_HOST_MUSL) #define __isnanl isnan #endif @@ -409,7 +403,7 @@ TEST(MATH_TEST, __isnanl) { ASSERT_TRUE(__isnanl(nanl(""))); } -TEST(MATH_TEST, isnanl) { +TEST(math_h, isnanl) { #if defined(ANDROID_HOST_MUSL) #define isnanl isnan #endif @@ -424,7 +418,7 @@ extern "C" int isnormalf(float); extern "C" int __isnormall(long double); extern "C" int isnormall(long double); -TEST(MATH_TEST, __isnormal) { +TEST(math_h, __isnormal) { #if defined(__BIONIC__) ASSERT_TRUE(__isnormal(123.0)); ASSERT_FALSE(__isnormal(double_subnormal())); @@ -433,7 +427,7 @@ TEST(MATH_TEST, __isnormal) { #endif // __BIONIC__ } -TEST(MATH_TEST, __isnormalf) { +TEST(math_h, __isnormalf) { #if defined(__BIONIC__) ASSERT_TRUE(__isnormalf(123.0f)); ASSERT_FALSE(__isnormalf(float_subnormal())); @@ -442,7 +436,7 @@ TEST(MATH_TEST, __isnormalf) { #endif // __BIONIC__ } -TEST(MATH_TEST, isnormalf) { +TEST(math_h, isnormalf) { #if defined(__BIONIC__) ASSERT_TRUE(isnormalf(123.0f)); ASSERT_FALSE(isnormalf(float_subnormal())); @@ -451,7 +445,7 @@ TEST(MATH_TEST, isnormalf) { #endif // __BIONIC__ } -TEST(MATH_TEST, __isnormall) { +TEST(math_h, __isnormall) { #if defined(__BIONIC__) ASSERT_TRUE(__isnormall(123.0L)); ASSERT_FALSE(__isnormall(ldouble_subnormal())); @@ -460,7 +454,7 @@ TEST(MATH_TEST, __isnormall) { #endif // __BIONIC__ } -TEST(MATH_TEST, isnormall) { +TEST(math_h, isnormall) { #if defined(__BIONIC__) ASSERT_TRUE(isnormall(123.0L)); ASSERT_FALSE(isnormall(ldouble_subnormal())); @@ -474,370 +468,370 @@ extern "C" int __signbit(double); extern "C" int __signbitf(float); extern "C" int __signbitl(long double); -TEST(MATH_TEST, __signbit) { +TEST(math_h, __signbit) { ASSERT_EQ(0, __signbit(0.0)); ASSERT_EQ(0, __signbit(1.0)); ASSERT_NE(0, __signbit(-1.0)); } -TEST(MATH_TEST, __signbitf) { +TEST(math_h, __signbitf) { ASSERT_EQ(0, __signbitf(0.0f)); ASSERT_EQ(0, __signbitf(1.0f)); ASSERT_NE(0, __signbitf(-1.0f)); } -TEST(MATH_TEST, __signbitl) { +TEST(math_h, __signbitl) { ASSERT_EQ(0L, __signbitl(0.0L)); ASSERT_EQ(0L, __signbitl(1.0L)); ASSERT_NE(0L, __signbitl(-1.0L)); } -TEST(MATH_TEST, acos) { +TEST(math_h, acos) { ASSERT_DOUBLE_EQ(M_PI/2.0, acos(0.0)); } -TEST(MATH_TEST, acosf) { +TEST(math_h, acosf) { ASSERT_FLOAT_EQ(static_cast<float>(M_PI)/2.0f, acosf(0.0f)); } -TEST(MATH_TEST, acosl) { +TEST(math_h, acosl) { ASSERT_DOUBLE_EQ(M_PI/2.0L, acosl(0.0L)); } -TEST(MATH_TEST, asin) { +TEST(math_h, asin) { ASSERT_DOUBLE_EQ(0.0, asin(0.0)); } -TEST(MATH_TEST, asinf) { +TEST(math_h, asinf) { ASSERT_FLOAT_EQ(0.0f, asinf(0.0f)); } -TEST(MATH_TEST, asinl) { +TEST(math_h, asinl) { ASSERT_DOUBLE_EQ(0.0L, asinl(0.0L)); } -TEST(MATH_TEST, atan) { +TEST(math_h, atan) { ASSERT_DOUBLE_EQ(0.0, atan(0.0)); } -TEST(MATH_TEST, atanf) { +TEST(math_h, atanf) { ASSERT_FLOAT_EQ(0.0f, atanf(0.0f)); } -TEST(MATH_TEST, atanl) { +TEST(math_h, atanl) { ASSERT_DOUBLE_EQ(0.0L, atanl(0.0L)); } -TEST(MATH_TEST, atan2) { +TEST(math_h, atan2) { ASSERT_DOUBLE_EQ(0.0, atan2(0.0, 0.0)); } -TEST(MATH_TEST, atan2f) { +TEST(math_h, atan2f) { ASSERT_FLOAT_EQ(0.0f, atan2f(0.0f, 0.0f)); } -TEST(MATH_TEST, atan2l) { +TEST(math_h, atan2l) { ASSERT_DOUBLE_EQ(0.0L, atan2l(0.0L, 0.0L)); } -TEST(MATH_TEST, cos) { +TEST(math_h, cos) { ASSERT_DOUBLE_EQ(1.0, cos(0.0)); } -TEST(MATH_TEST, cosf) { +TEST(math_h, cosf) { ASSERT_FLOAT_EQ(1.0f, cosf(0.0f)); } -TEST(MATH_TEST, cosl) { +TEST(math_h, cosl) { ASSERT_DOUBLE_EQ(1.0L, cosl(0.0L)); } -TEST(MATH_TEST, sin) { +TEST(math_h, sin) { ASSERT_DOUBLE_EQ(0.0, sin(0.0)); } -TEST(MATH_TEST, sinf) { +TEST(math_h, sinf) { ASSERT_FLOAT_EQ(0.0f, sinf(0.0f)); } -TEST(MATH_TEST, sinl) { +TEST(math_h, sinl) { ASSERT_DOUBLE_EQ(0.0L, sinl(0.0L)); } -TEST(MATH_TEST, sincos) { +TEST(math_h, sincos) { double s, c; sincos(0.0, &s, &c); ASSERT_DOUBLE_EQ(0.0, s); ASSERT_DOUBLE_EQ(1.0, c); } -TEST(MATH_TEST, sincosf) { +TEST(math_h, sincosf) { float s, c; sincosf(0.0f, &s, &c); ASSERT_FLOAT_EQ(0.0f, s); ASSERT_FLOAT_EQ(1.0f, c); } -TEST(MATH_TEST, sincosl) { +TEST(math_h, sincosl) { long double s, c; sincosl(0.0L, &s, &c); ASSERT_DOUBLE_EQ(0.0L, s); ASSERT_DOUBLE_EQ(1.0L, c); } -TEST(MATH_TEST, tan) { +TEST(math_h, tan) { ASSERT_DOUBLE_EQ(0.0, tan(0.0)); } -TEST(MATH_TEST, tanf) { +TEST(math_h, tanf) { ASSERT_FLOAT_EQ(0.0f, tanf(0.0f)); } -TEST(MATH_TEST, tanl) { +TEST(math_h, tanl) { ASSERT_DOUBLE_EQ(0.0L, tanl(0.0L)); } -TEST(MATH_TEST, acosh) { +TEST(math_h, acosh) { ASSERT_DOUBLE_EQ(0.0, acosh(1.0)); } -TEST(MATH_TEST, acoshf) { +TEST(math_h, acoshf) { ASSERT_FLOAT_EQ(0.0f, acoshf(1.0f)); } -TEST(MATH_TEST, acoshl) { +TEST(math_h, acoshl) { ASSERT_DOUBLE_EQ(0.0L, acoshl(1.0L)); } -TEST(MATH_TEST, asinh) { +TEST(math_h, asinh) { ASSERT_DOUBLE_EQ(0.0, asinh(0.0)); } -TEST(MATH_TEST, asinhf) { +TEST(math_h, asinhf) { ASSERT_FLOAT_EQ(0.0f, asinhf(0.0f)); } -TEST(MATH_TEST, asinhl) { +TEST(math_h, asinhl) { ASSERT_DOUBLE_EQ(0.0L, asinhl(0.0L)); } -TEST(MATH_TEST, atanh) { +TEST(math_h, atanh) { ASSERT_DOUBLE_EQ(0.0, atanh(0.0)); } -TEST(MATH_TEST, atanhf) { +TEST(math_h, atanhf) { ASSERT_FLOAT_EQ(0.0f, atanhf(0.0f)); } -TEST(MATH_TEST, atanhl) { +TEST(math_h, atanhl) { ASSERT_DOUBLE_EQ(0.0L, atanhl(0.0L)); } -TEST(MATH_TEST, cosh) { +TEST(math_h, cosh) { ASSERT_DOUBLE_EQ(1.0, cosh(0.0)); } -TEST(MATH_TEST, coshf) { +TEST(math_h, coshf) { ASSERT_FLOAT_EQ(1.0f, coshf(0.0f)); } -TEST(MATH_TEST, coshl) { +TEST(math_h, coshl) { ASSERT_DOUBLE_EQ(1.0L, coshl(0.0L)); } -TEST(MATH_TEST, sinh) { +TEST(math_h, sinh) { ASSERT_DOUBLE_EQ(0.0, sinh(0.0)); } -TEST(MATH_TEST, sinhf) { +TEST(math_h, sinhf) { ASSERT_FLOAT_EQ(0.0f, sinhf(0.0f)); } -TEST(MATH_TEST, sinhl) { +TEST(math_h, sinhl) { ASSERT_DOUBLE_EQ(0.0L, sinhl(0.0L)); } -TEST(MATH_TEST, tanh) { +TEST(math_h, tanh) { ASSERT_DOUBLE_EQ(0.0, tanh(0.0)); } -TEST(MATH_TEST, tanhf) { +TEST(math_h, tanhf) { ASSERT_FLOAT_EQ(0.0f, tanhf(0.0f)); } -TEST(MATH_TEST, tanhl) { +TEST(math_h, tanhl) { ASSERT_DOUBLE_EQ(0.0L, tanhl(0.0L)); } -TEST(MATH_TEST, log) { +TEST(math_h, log) { ASSERT_DOUBLE_EQ(1.0, log(M_E)); } -TEST(MATH_TEST, logf) { +TEST(math_h, logf) { ASSERT_FLOAT_EQ(1.0f, logf(static_cast<float>(M_E))); } -TEST(MATH_TEST, logl) { +TEST(math_h, logl) { ASSERT_DOUBLE_EQ(1.0L, logl(M_E)); } -TEST(MATH_TEST, log2) { +TEST(math_h, log2) { ASSERT_DOUBLE_EQ(12.0, log2(4096.0)); } -TEST(MATH_TEST, log2f) { +TEST(math_h, log2f) { ASSERT_FLOAT_EQ(12.0f, log2f(4096.0f)); } -TEST(MATH_TEST, log2l) { +TEST(math_h, log2l) { ASSERT_DOUBLE_EQ(12.0L, log2l(4096.0L)); } -TEST(MATH_TEST, log10) { +TEST(math_h, log10) { ASSERT_DOUBLE_EQ(3.0, log10(1000.0)); } -TEST(MATH_TEST, log10f) { +TEST(math_h, log10f) { ASSERT_FLOAT_EQ(3.0f, log10f(1000.0f)); } -TEST(MATH_TEST, log10l) { +TEST(math_h, log10l) { ASSERT_DOUBLE_EQ(3.0L, log10l(1000.0L)); } -TEST(MATH_TEST, cbrt) { +TEST(math_h, cbrt) { ASSERT_DOUBLE_EQ(3.0, cbrt(27.0)); } -TEST(MATH_TEST, cbrtf) { +TEST(math_h, cbrtf) { ASSERT_FLOAT_EQ(3.0f, cbrtf(27.0f)); } -TEST(MATH_TEST, cbrtl) { +TEST(math_h, cbrtl) { ASSERT_DOUBLE_EQ(3.0L, cbrtl(27.0L)); } -TEST(MATH_TEST, sqrt) { +TEST(math_h, sqrt) { ASSERT_DOUBLE_EQ(2.0, sqrt(4.0)); } -TEST(MATH_TEST, sqrtf) { +TEST(math_h, sqrtf) { ASSERT_FLOAT_EQ(2.0f, sqrtf(4.0f)); } -TEST(MATH_TEST, sqrtl) { +TEST(math_h, sqrtl) { ASSERT_DOUBLE_EQ(2.0L, sqrtl(4.0L)); } -TEST(MATH_TEST, exp) { +TEST(math_h, exp) { ASSERT_DOUBLE_EQ(1.0, exp(0.0)); ASSERT_DOUBLE_EQ(M_E, exp(1.0)); } -TEST(MATH_TEST, expf) { +TEST(math_h, expf) { ASSERT_FLOAT_EQ(1.0f, expf(0.0f)); ASSERT_FLOAT_EQ(static_cast<float>(M_E), expf(1.0f)); } -TEST(MATH_TEST, expl) { +TEST(math_h, expl) { ASSERT_DOUBLE_EQ(1.0L, expl(0.0L)); ASSERT_DOUBLE_EQ(M_E, expl(1.0L)); } -TEST(MATH_TEST, exp2) { +TEST(math_h, exp2) { ASSERT_DOUBLE_EQ(8.0, exp2(3.0)); } -TEST(MATH_TEST, exp2f) { +TEST(math_h, exp2f) { ASSERT_FLOAT_EQ(8.0f, exp2f(3.0f)); } -TEST(MATH_TEST, exp2l) { +TEST(math_h, exp2l) { ASSERT_DOUBLE_EQ(8.0L, exp2l(3.0L)); } -TEST(MATH_TEST, expm1) { +TEST(math_h, expm1) { ASSERT_DOUBLE_EQ(M_E - 1.0, expm1(1.0)); } -TEST(MATH_TEST, expm1f) { +TEST(math_h, expm1f) { ASSERT_FLOAT_EQ(static_cast<float>(M_E) - 1.0f, expm1f(1.0f)); } -TEST(MATH_TEST, expm1l) { +TEST(math_h, expm1l) { ASSERT_DOUBLE_EQ(M_E - 1.0L, expm1l(1.0L)); } -TEST(MATH_TEST, pow) { +TEST(math_h, pow) { ASSERT_TRUE(isnan(pow(nan(""), 3.0))); ASSERT_DOUBLE_EQ(1.0, (pow(1.0, nan("")))); ASSERT_TRUE(isnan(pow(2.0, nan("")))); ASSERT_DOUBLE_EQ(8.0, pow(2.0, 3.0)); } -TEST(MATH_TEST, powf) { +TEST(math_h, powf) { ASSERT_TRUE(isnanf(powf(nanf(""), 3.0f))); ASSERT_FLOAT_EQ(1.0f, (powf(1.0f, nanf("")))); ASSERT_TRUE(isnanf(powf(2.0f, nanf("")))); ASSERT_FLOAT_EQ(8.0f, powf(2.0f, 3.0f)); } -TEST(MATH_TEST, powl) { +TEST(math_h, powl) { ASSERT_TRUE(__isnanl(powl(nanl(""), 3.0L))); ASSERT_DOUBLE_EQ(1.0L, (powl(1.0L, nanl("")))); ASSERT_TRUE(__isnanl(powl(2.0L, nanl("")))); ASSERT_DOUBLE_EQ(8.0L, powl(2.0L, 3.0L)); } -TEST(MATH_TEST, ceil) { +TEST(math_h, ceil) { ASSERT_DOUBLE_EQ(1.0, ceil(0.9)); } -TEST(MATH_TEST, ceilf) { +TEST(math_h, ceilf) { ASSERT_FLOAT_EQ(1.0f, ceilf(0.9f)); } -TEST(MATH_TEST, ceill) { +TEST(math_h, ceill) { ASSERT_DOUBLE_EQ(1.0L, ceill(0.9L)); } -TEST(MATH_TEST, floor) { +TEST(math_h, floor) { ASSERT_DOUBLE_EQ(1.0, floor(1.1)); } -TEST(MATH_TEST, floorf) { +TEST(math_h, floorf) { ASSERT_FLOAT_EQ(1.0f, floorf(1.1f)); } -TEST(MATH_TEST, floorl) { +TEST(math_h, floorl) { ASSERT_DOUBLE_EQ(1.0L, floorl(1.1L)); } -TEST(MATH_TEST, fabs) { +TEST(math_h, fabs) { ASSERT_DOUBLE_EQ(1.0, fabs(-1.0)); } -TEST(MATH_TEST, fabsf) { +TEST(math_h, fabsf) { ASSERT_FLOAT_EQ(1.0f, fabsf(-1.0f)); } -TEST(MATH_TEST, fabsl) { +TEST(math_h, fabsl) { ASSERT_DOUBLE_EQ(1.0L, fabsl(-1.0L)); } -TEST(MATH_TEST, ldexp) { +TEST(math_h, ldexp) { ASSERT_DOUBLE_EQ(16.0, ldexp(2.0, 3.0)); } -TEST(MATH_TEST, ldexpf) { +TEST(math_h, ldexpf) { ASSERT_FLOAT_EQ(16.0f, ldexpf(2.0f, 3.0f)); } -TEST(MATH_TEST, ldexpl) { +TEST(math_h, ldexpl) { ASSERT_DOUBLE_EQ(16.0L, ldexpl(2.0L, 3.0)); } -TEST(MATH_TEST, fmod) { +TEST(math_h, fmod) { ASSERT_DOUBLE_EQ(2.0, fmod(12.0, 10.0)); // If x is an infinity, NaN is returned. @@ -852,7 +846,7 @@ TEST(MATH_TEST, fmod) { ASSERT_TRUE(isnan(fmod(3.0, 0.0))); } -TEST(MATH_TEST, fmodf) { +TEST(math_h, fmodf) { ASSERT_FLOAT_EQ(2.0f, fmodf(12.0f, 10.0f)); // If x is an infinity, NaN is returned. @@ -867,7 +861,7 @@ TEST(MATH_TEST, fmodf) { ASSERT_TRUE(isnanf(fmodf(3.0f, 0.0f))); } -TEST(MATH_TEST, fmodl) { +TEST(math_h, fmodl) { ASSERT_DOUBLE_EQ(2.0L, fmodl(12.0L, 10.0L)); // If x is an infinity, NaN is returned. @@ -882,7 +876,7 @@ TEST(MATH_TEST, fmodl) { ASSERT_TRUE(isnanl(fmodl(3.0L, 0.0L))); } -TEST(MATH_TEST, remainder) { +TEST(math_h, remainder) { ASSERT_DOUBLE_EQ(2.0, remainder(12.0, 10.0)); // If x or y is a NaN, NaN is returned. @@ -897,7 +891,7 @@ TEST(MATH_TEST, remainder) { ASSERT_TRUE(isnan(remainder(12.0, 0.0))); } -TEST(MATH_TEST, remainderf) { +TEST(math_h, remainderf) { ASSERT_FLOAT_EQ(2.0f, remainderf(12.0f, 10.0f)); // If x or y is a NaN, NaN is returned. @@ -912,7 +906,7 @@ TEST(MATH_TEST, remainderf) { ASSERT_TRUE(isnanf(remainderf(12.0f, 0.0f))); } -TEST(MATH_TEST, remainderl) { +TEST(math_h, remainderl) { ASSERT_DOUBLE_EQ(2.0L, remainderl(12.0L, 10.0L)); // If x or y is a NaN, NaN is returned. @@ -927,63 +921,63 @@ TEST(MATH_TEST, remainderl) { ASSERT_TRUE(isnanl(remainderl(12.0L, 0.0L))); } -TEST(MATH_TEST, drem) { +TEST(math_h, drem) { ASSERT_DOUBLE_EQ(2.0, drem(12.0, 10.0)); } -TEST(MATH_TEST, dremf) { +TEST(math_h, dremf) { ASSERT_FLOAT_EQ(2.0f, dremf(12.0f, 10.0f)); } -TEST(MATH_TEST, fmax) { +TEST(math_h, fmax) { ASSERT_DOUBLE_EQ(12.0, fmax(12.0, 10.0)); ASSERT_DOUBLE_EQ(12.0, fmax(12.0, nan(""))); ASSERT_DOUBLE_EQ(12.0, fmax(nan(""), 12.0)); } -TEST(MATH_TEST, fmaxf) { +TEST(math_h, fmaxf) { ASSERT_FLOAT_EQ(12.0f, fmaxf(12.0f, 10.0f)); ASSERT_FLOAT_EQ(12.0f, fmaxf(12.0f, nanf(""))); ASSERT_FLOAT_EQ(12.0f, fmaxf(nanf(""), 12.0f)); } -TEST(MATH_TEST, fmaxl) { +TEST(math_h, fmaxl) { ASSERT_DOUBLE_EQ(12.0L, fmaxl(12.0L, 10.0L)); ASSERT_DOUBLE_EQ(12.0L, fmaxl(12.0L, nanl(""))); ASSERT_DOUBLE_EQ(12.0L, fmaxl(nanl(""), 12.0L)); } -TEST(MATH_TEST, fmin) { +TEST(math_h, fmin) { ASSERT_DOUBLE_EQ(10.0, fmin(12.0, 10.0)); ASSERT_DOUBLE_EQ(12.0, fmin(12.0, nan(""))); ASSERT_DOUBLE_EQ(12.0, fmin(nan(""), 12.0)); } -TEST(MATH_TEST, fminf) { +TEST(math_h, fminf) { ASSERT_FLOAT_EQ(10.0f, fminf(12.0f, 10.0f)); ASSERT_FLOAT_EQ(12.0f, fminf(12.0f, nanf(""))); ASSERT_FLOAT_EQ(12.0f, fminf(nanf(""), 12.0f)); } -TEST(MATH_TEST, fminl) { +TEST(math_h, fminl) { ASSERT_DOUBLE_EQ(10.0L, fminl(12.0L, 10.0L)); ASSERT_DOUBLE_EQ(12.0L, fminl(12.0L, nanl(""))); ASSERT_DOUBLE_EQ(12.0L, fminl(nanl(""), 12.0L)); } -TEST(MATH_TEST, fma) { +TEST(math_h, fma) { ASSERT_DOUBLE_EQ(10.0, fma(2.0, 3.0, 4.0)); } -TEST(MATH_TEST, fmaf) { +TEST(math_h, fmaf) { ASSERT_FLOAT_EQ(10.0f, fmaf(2.0f, 3.0f, 4.0f)); } -TEST(MATH_TEST, fmal) { +TEST(math_h, fmal) { ASSERT_DOUBLE_EQ(10.0L, fmal(2.0L, 3.0L, 4.0L)); } -TEST(MATH_TEST, hypot) { +TEST(math_h, hypot) { ASSERT_DOUBLE_EQ(5.0, hypot(3.0, 4.0)); // If x or y is an infinity, returns positive infinity. @@ -997,7 +991,7 @@ TEST(MATH_TEST, hypot) { ASSERT_TRUE(isnan(hypot(nan(""), 4.0))); } -TEST(MATH_TEST, hypotf) { +TEST(math_h, hypotf) { ASSERT_FLOAT_EQ(5.0f, hypotf(3.0f, 4.0f)); // If x or y is an infinity, returns positive infinity. @@ -1011,7 +1005,7 @@ TEST(MATH_TEST, hypotf) { ASSERT_TRUE(isnanf(hypotf(nanf(""), 4.0f))); } -TEST(MATH_TEST, hypotl) { +TEST(math_h, hypotl) { ASSERT_DOUBLE_EQ(5.0L, hypotl(3.0L, 4.0L)); // If x or y is an infinity, returns positive infinity. @@ -1025,31 +1019,31 @@ TEST(MATH_TEST, hypotl) { ASSERT_TRUE(isnanl(hypotl(nanl(""), 4.0L))); } -TEST(MATH_TEST, erf) { +TEST(math_h, erf) { ASSERT_DOUBLE_EQ(0.84270079294971489, erf(1.0)); } -TEST(MATH_TEST, erff) { +TEST(math_h, erff) { ASSERT_FLOAT_EQ(0.84270078f, erff(1.0f)); } -TEST(MATH_TEST, erfl) { +TEST(math_h, erfl) { ASSERT_DOUBLE_EQ(0.84270079294971489L, erfl(1.0L)); } -TEST(MATH_TEST, erfc) { +TEST(math_h, erfc) { ASSERT_DOUBLE_EQ(0.15729920705028513, erfc(1.0)); } -TEST(MATH_TEST, erfcf) { +TEST(math_h, erfcf) { ASSERT_FLOAT_EQ(0.15729921f, erfcf(1.0f)); } -TEST(MATH_TEST, erfcl) { +TEST(math_h, erfcl) { ASSERT_DOUBLE_EQ(0.15729920705028513L, erfcl(1.0L)); } -TEST(MATH_TEST, lrint) { +TEST(math_h, lrint) { auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); }); fesetround(FE_UPWARD); // lrint/lrintf/lrintl obey the rounding mode. @@ -1071,7 +1065,7 @@ TEST(MATH_TEST, lrint) { EXPECT_EQ(1234L, llrintl(1234.01L)); } -TEST(MATH_TEST, rint) { +TEST(math_h, rint) { auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); }); fesetround(FE_UPWARD); // rint/rintf/rintl obey the rounding mode. @@ -1099,7 +1093,7 @@ TEST(MATH_TEST, rint) { ASSERT_EQ(1234.0, rintl(1234.01L)); } -TEST(MATH_TEST, nearbyint) { +TEST(math_h, nearbyint) { auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); }); fesetround(FE_UPWARD); // nearbyint/nearbyintf/nearbyintl obey the rounding mode. feclearexcept(FE_ALL_EXCEPT); // nearbyint/nearbyintf/nearbyintl don't set the FE_INEXACT flag. @@ -1126,7 +1120,7 @@ TEST(MATH_TEST, nearbyint) { ASSERT_EQ(1234.0, nearbyintl(1234.01L)); } -TEST(MATH_TEST, lround) { +TEST(math_h, lround) { auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); }); fesetround(FE_UPWARD); // lround ignores the rounding mode. ASSERT_EQ(1234, lround(1234.01)); @@ -1134,7 +1128,7 @@ TEST(MATH_TEST, lround) { ASSERT_EQ(1234, lroundl(1234.01L)); } -TEST(MATH_TEST, llround) { +TEST(math_h, llround) { auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); }); fesetround(FE_UPWARD); // llround ignores the rounding mode. ASSERT_EQ(1234L, llround(1234.01)); @@ -1142,7 +1136,7 @@ TEST(MATH_TEST, llround) { ASSERT_EQ(1234L, llroundl(1234.01L)); } -TEST(MATH_TEST, ilogb) { +TEST(math_h, ilogb) { ASSERT_EQ(FP_ILOGB0, ilogb(0.0)); ASSERT_EQ(FP_ILOGBNAN, ilogb(nan(""))); ASSERT_EQ(INT_MAX, ilogb(HUGE_VAL)); @@ -1151,7 +1145,7 @@ TEST(MATH_TEST, ilogb) { ASSERT_EQ(3, ilogb(10.0)); } -TEST(MATH_TEST, ilogbf) { +TEST(math_h, ilogbf) { ASSERT_EQ(FP_ILOGB0, ilogbf(0.0f)); ASSERT_EQ(FP_ILOGBNAN, ilogbf(nanf(""))); ASSERT_EQ(INT_MAX, ilogbf(HUGE_VALF)); @@ -1160,7 +1154,7 @@ TEST(MATH_TEST, ilogbf) { ASSERT_EQ(3, ilogbf(10.0f)); } -TEST(MATH_TEST, ilogbl) { +TEST(math_h, ilogbl) { ASSERT_EQ(FP_ILOGB0, ilogbl(0.0L)); ASSERT_EQ(FP_ILOGBNAN, ilogbl(nanl(""))); ASSERT_EQ(INT_MAX, ilogbl(HUGE_VALL)); @@ -1169,7 +1163,7 @@ TEST(MATH_TEST, ilogbl) { ASSERT_EQ(3L, ilogbl(10.0L)); } -TEST(MATH_TEST, logb) { +TEST(math_h, logb) { ASSERT_EQ(-HUGE_VAL, logb(0.0)); ASSERT_TRUE(isnan(logb(nan("")))); ASSERT_TRUE(isinf(logb(HUGE_VAL))); @@ -1178,7 +1172,7 @@ TEST(MATH_TEST, logb) { ASSERT_EQ(3.0, logb(10.0)); } -TEST(MATH_TEST, logbf) { +TEST(math_h, logbf) { ASSERT_EQ(-HUGE_VALF, logbf(0.0f)); ASSERT_TRUE(isnanf(logbf(nanf("")))); ASSERT_TRUE(isinff(logbf(HUGE_VALF))); @@ -1187,7 +1181,7 @@ TEST(MATH_TEST, logbf) { ASSERT_EQ(3.0f, logbf(10.0f)); } -TEST(MATH_TEST, logbl) { +TEST(math_h, logbl) { ASSERT_EQ(-HUGE_VAL, logbl(0.0L)); ASSERT_TRUE(isnan(logbl(nanl("")))); ASSERT_TRUE(isinf(logbl(HUGE_VALL))); @@ -1196,7 +1190,7 @@ TEST(MATH_TEST, logbl) { ASSERT_EQ(3.0L, logbl(10.0L)); } -TEST(MATH_TEST, log1p) { +TEST(math_h, log1p) { ASSERT_EQ(-HUGE_VAL, log1p(-1.0)); ASSERT_TRUE(isnan(log1p(nan("")))); ASSERT_TRUE(isinf(log1p(HUGE_VAL))); @@ -1204,7 +1198,7 @@ TEST(MATH_TEST, log1p) { ASSERT_DOUBLE_EQ(1.0, log1p(M_E - 1.0)); } -TEST(MATH_TEST, log1pf) { +TEST(math_h, log1pf) { ASSERT_EQ(-HUGE_VALF, log1pf(-1.0f)); ASSERT_TRUE(isnanf(log1pf(nanf("")))); ASSERT_TRUE(isinff(log1pf(HUGE_VALF))); @@ -1212,7 +1206,7 @@ TEST(MATH_TEST, log1pf) { ASSERT_FLOAT_EQ(1.0f, log1pf(static_cast<float>(M_E) - 1.0f)); } -TEST(MATH_TEST, log1pl) { +TEST(math_h, log1pl) { ASSERT_EQ(-HUGE_VALL, log1pl(-1.0L)); ASSERT_TRUE(isnanl(log1pl(nanl("")))); ASSERT_TRUE(isinfl(log1pl(HUGE_VALL))); @@ -1220,25 +1214,25 @@ TEST(MATH_TEST, log1pl) { ASSERT_DOUBLE_EQ(1.0L, log1pl(M_E - 1.0L)); } -TEST(MATH_TEST, fdim) { +TEST(math_h, fdim) { ASSERT_DOUBLE_EQ(0.0, fdim(1.0, 1.0)); ASSERT_DOUBLE_EQ(1.0, fdim(2.0, 1.0)); ASSERT_DOUBLE_EQ(0.0, fdim(1.0, 2.0)); } -TEST(MATH_TEST, fdimf) { +TEST(math_h, fdimf) { ASSERT_FLOAT_EQ(0.0f, fdimf(1.0f, 1.0f)); ASSERT_FLOAT_EQ(1.0f, fdimf(2.0f, 1.0f)); ASSERT_FLOAT_EQ(0.0f, fdimf(1.0f, 2.0f)); } -TEST(MATH_TEST, fdiml) { +TEST(math_h, fdiml) { ASSERT_DOUBLE_EQ(0.0L, fdiml(1.0L, 1.0L)); ASSERT_DOUBLE_EQ(1.0L, fdiml(2.0L, 1.0L)); ASSERT_DOUBLE_EQ(0.0L, fdiml(1.0L, 2.0L)); } -TEST(MATH_TEST, round) { +TEST(math_h, round) { auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); }); fesetround(FE_TOWARDZERO); // round ignores the rounding mode and always rounds away from zero. ASSERT_DOUBLE_EQ(1.0, round(0.5)); @@ -1250,7 +1244,7 @@ TEST(MATH_TEST, round) { ASSERT_DOUBLE_EQ(-HUGE_VAL, round(-HUGE_VAL)); } -TEST(MATH_TEST, roundf) { +TEST(math_h, roundf) { auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); }); fesetround(FE_TOWARDZERO); // roundf ignores the rounding mode and always rounds away from zero. ASSERT_FLOAT_EQ(1.0f, roundf(0.5f)); @@ -1262,7 +1256,7 @@ TEST(MATH_TEST, roundf) { ASSERT_FLOAT_EQ(-HUGE_VALF, roundf(-HUGE_VALF)); } -TEST(MATH_TEST, roundl) { +TEST(math_h, roundl) { auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); }); fesetround(FE_TOWARDZERO); // roundl ignores the rounding mode and always rounds away from zero. ASSERT_DOUBLE_EQ(1.0L, roundl(0.5L)); @@ -1274,7 +1268,7 @@ TEST(MATH_TEST, roundl) { ASSERT_DOUBLE_EQ(-HUGE_VALL, roundl(-HUGE_VALL)); } -TEST(MATH_TEST, trunc) { +TEST(math_h, trunc) { auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); }); fesetround(FE_UPWARD); // trunc ignores the rounding mode and always rounds toward zero. ASSERT_DOUBLE_EQ(1.0, trunc(1.5)); @@ -1286,7 +1280,7 @@ TEST(MATH_TEST, trunc) { ASSERT_DOUBLE_EQ(-HUGE_VAL, trunc(-HUGE_VAL)); } -TEST(MATH_TEST, truncf) { +TEST(math_h, truncf) { auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); }); fesetround(FE_UPWARD); // truncf ignores the rounding mode and always rounds toward zero. ASSERT_FLOAT_EQ(1.0f, truncf(1.5f)); @@ -1298,7 +1292,7 @@ TEST(MATH_TEST, truncf) { ASSERT_FLOAT_EQ(-HUGE_VALF, truncf(-HUGE_VALF)); } -TEST(MATH_TEST, truncl) { +TEST(math_h, truncl) { auto guard = android::base::make_scope_guard([]() { fesetenv(FE_DFL_ENV); }); fesetround(FE_UPWARD); // truncl ignores the rounding mode and always rounds toward zero. ASSERT_DOUBLE_EQ(1.0L, truncl(1.5L)); @@ -1310,19 +1304,19 @@ TEST(MATH_TEST, truncl) { ASSERT_DOUBLE_EQ(-HUGE_VALL, truncl(-HUGE_VALL)); } -TEST(MATH_TEST, nextafter) { +TEST(math_h, nextafter) { ASSERT_DOUBLE_EQ(0.0, nextafter(0.0, 0.0)); ASSERT_DOUBLE_EQ(4.9406564584124654e-324, nextafter(0.0, 1.0)); ASSERT_DOUBLE_EQ(-4.9406564584124654e-324, nextafter(0.0, -1.0)); } -TEST(MATH_TEST, nextafterf) { +TEST(math_h, nextafterf) { ASSERT_FLOAT_EQ(0.0f, nextafterf(0.0f, 0.0f)); ASSERT_FLOAT_EQ(1.4012985e-45f, nextafterf(0.0f, 1.0f)); ASSERT_FLOAT_EQ(-1.4012985e-45f, nextafterf(0.0f, -1.0f)); } -TEST(MATH_TEST, nextafterl) { +TEST(math_h, nextafterl) { ASSERT_DOUBLE_EQ(0.0L, nextafterl(0.0L, 0.0L)); // Use a runtime value to accomodate the case when // sizeof(double) == sizeof(long double) @@ -1331,19 +1325,19 @@ TEST(MATH_TEST, nextafterl) { ASSERT_DOUBLE_EQ(-smallest_positive, nextafterl(0.0L, -1.0L)); } -TEST(MATH_TEST, nexttoward) { +TEST(math_h, nexttoward) { ASSERT_DOUBLE_EQ(0.0, nexttoward(0.0, 0.0L)); ASSERT_DOUBLE_EQ(4.9406564584124654e-324, nexttoward(0.0, 1.0L)); ASSERT_DOUBLE_EQ(-4.9406564584124654e-324, nexttoward(0.0, -1.0L)); } -TEST(MATH_TEST, nexttowardf) { +TEST(math_h, nexttowardf) { ASSERT_FLOAT_EQ(0.0f, nexttowardf(0.0f, 0.0L)); ASSERT_FLOAT_EQ(1.4012985e-45f, nexttowardf(0.0f, 1.0L)); ASSERT_FLOAT_EQ(-1.4012985e-45f, nexttowardf(0.0f, -1.0L)); } -TEST(MATH_TEST, nexttowardl) { +TEST(math_h, nexttowardl) { ASSERT_DOUBLE_EQ(0.0L, nexttowardl(0.0L, 0.0L)); // Use a runtime value to accomodate the case when // sizeof(double) == sizeof(long double) @@ -1352,40 +1346,40 @@ TEST(MATH_TEST, nexttowardl) { ASSERT_DOUBLE_EQ(-smallest_positive, nexttowardl(0.0L, -1.0L)); } -TEST(MATH_TEST, copysign) { +TEST(math_h, copysign) { ASSERT_DOUBLE_EQ(0.0, copysign(0.0, 1.0)); ASSERT_DOUBLE_EQ(-0.0, copysign(0.0, -1.0)); ASSERT_DOUBLE_EQ(2.0, copysign(2.0, 1.0)); ASSERT_DOUBLE_EQ(-2.0, copysign(2.0, -1.0)); } -TEST(MATH_TEST, copysignf) { +TEST(math_h, copysignf) { ASSERT_FLOAT_EQ(0.0f, copysignf(0.0f, 1.0f)); ASSERT_FLOAT_EQ(-0.0f, copysignf(0.0f, -1.0f)); ASSERT_FLOAT_EQ(2.0f, copysignf(2.0f, 1.0f)); ASSERT_FLOAT_EQ(-2.0f, copysignf(2.0f, -1.0f)); } -TEST(MATH_TEST, copysignl) { +TEST(math_h, copysignl) { ASSERT_DOUBLE_EQ(0.0L, copysignl(0.0L, 1.0L)); ASSERT_DOUBLE_EQ(-0.0L, copysignl(0.0L, -1.0L)); ASSERT_DOUBLE_EQ(2.0L, copysignl(2.0L, 1.0L)); ASSERT_DOUBLE_EQ(-2.0L, copysignl(2.0L, -1.0L)); } -TEST(MATH_TEST, significand) { +TEST(math_h, significand) { ASSERT_DOUBLE_EQ(0.0, significand(0.0)); ASSERT_DOUBLE_EQ(1.2, significand(1.2)); ASSERT_DOUBLE_EQ(1.53125, significand(12.25)); } -TEST(MATH_TEST, significandf) { +TEST(math_h, significandf) { ASSERT_FLOAT_EQ(0.0f, significandf(0.0f)); ASSERT_FLOAT_EQ(1.2f, significandf(1.2f)); ASSERT_FLOAT_EQ(1.53125f, significandf(12.25f)); } -TEST(MATH_TEST, significandl) { +TEST(math_h, significandl) { #if !defined(ANDROID_HOST_MUSL) ASSERT_DOUBLE_EQ(0.0L, significandl(0.0L)); ASSERT_DOUBLE_EQ(1.2L, significandl(1.2L)); @@ -1395,40 +1389,39 @@ TEST(MATH_TEST, significandl) { #endif } - -TEST(MATH_TEST, scalb) { +TEST(math_h, scalb) { ASSERT_DOUBLE_EQ(12.0, scalb(3.0, 2.0)); } -TEST(MATH_TEST, scalbf) { +TEST(math_h, scalbf) { ASSERT_FLOAT_EQ(12.0f, scalbf(3.0f, 2.0f)); } -TEST(MATH_TEST, scalbln) { +TEST(math_h, scalbln) { ASSERT_DOUBLE_EQ(12.0, scalbln(3.0, 2L)); } -TEST(MATH_TEST, scalblnf) { +TEST(math_h, scalblnf) { ASSERT_FLOAT_EQ(12.0f, scalblnf(3.0f, 2L)); } -TEST(MATH_TEST, scalblnl) { +TEST(math_h, scalblnl) { ASSERT_DOUBLE_EQ(12.0L, scalblnl(3.0L, 2L)); } -TEST(MATH_TEST, scalbn) { +TEST(math_h, scalbn) { ASSERT_DOUBLE_EQ(12.0, scalbn(3.0, 2)); } -TEST(MATH_TEST, scalbnf) { +TEST(math_h, scalbnf) { ASSERT_FLOAT_EQ(12.0f, scalbnf(3.0f, 2)); } -TEST(MATH_TEST, scalbnl) { +TEST(math_h, scalbnl) { ASSERT_DOUBLE_EQ(12.0L, scalbnl(3.0L, 2)); } -TEST(MATH_TEST, gamma) { +TEST(math_h, gamma) { #if !defined(ANDROID_HOST_MUSL) ASSERT_DOUBLE_EQ(log(24.0), gamma(5.0)); #else @@ -1436,7 +1429,7 @@ TEST(MATH_TEST, gamma) { #endif } -TEST(MATH_TEST, gammaf) { +TEST(math_h, gammaf) { #if !defined(ANDROID_HOST_MUSL) ASSERT_FLOAT_EQ(logf(24.0f), gammaf(5.0f)); #else @@ -1444,7 +1437,7 @@ TEST(MATH_TEST, gammaf) { #endif } -TEST(MATH_TEST, gamma_r) { +TEST(math_h, gamma_r) { #if defined(__BIONIC__) int sign; ASSERT_DOUBLE_EQ(log(24.0), gamma_r(5.0, &sign)); @@ -1454,7 +1447,7 @@ TEST(MATH_TEST, gamma_r) { #endif // __BIONIC__ } -TEST(MATH_TEST, gammaf_r) { +TEST(math_h, gammaf_r) { #if defined(__BIONIC__) int sign; ASSERT_FLOAT_EQ(logf(24.0f), gammaf_r(5.0f, &sign)); @@ -1464,25 +1457,25 @@ TEST(MATH_TEST, gammaf_r) { #endif // __BIONIC__ } -TEST(MATH_TEST, lgamma) { +TEST(math_h, lgamma) { ASSERT_DOUBLE_EQ(log(24.0), lgamma(5.0)); } -TEST(MATH_TEST, lgammaf) { +TEST(math_h, lgammaf) { ASSERT_FLOAT_EQ(logf(24.0f), lgammaf(5.0f)); } -TEST(MATH_TEST, lgammal) { +TEST(math_h, lgammal) { ASSERT_DOUBLE_EQ(logl(24.0L), lgammal(5.0L)); } -TEST(MATH_TEST, lgamma_r) { +TEST(math_h, lgamma_r) { int sign; ASSERT_DOUBLE_EQ(log(24.0), lgamma_r(5.0, &sign)); ASSERT_EQ(1, sign); } -TEST(MATH_TEST, lgamma_r_17471883) { +TEST(math_h, lgamma_r_17471883) { int sign; sign = 0; @@ -1493,13 +1486,13 @@ TEST(MATH_TEST, lgamma_r_17471883) { ASSERT_EQ(-1, sign); } -TEST(MATH_TEST, lgammaf_r) { +TEST(math_h, lgammaf_r) { int sign; ASSERT_FLOAT_EQ(logf(24.0f), lgammaf_r(5.0f, &sign)); ASSERT_EQ(1, sign); } -TEST(MATH_TEST, lgammaf_r_17471883) { +TEST(math_h, lgammaf_r_17471883) { int sign; sign = 0; @@ -1510,13 +1503,13 @@ TEST(MATH_TEST, lgammaf_r_17471883) { ASSERT_EQ(-1, sign); } -TEST(MATH_TEST, lgammal_r) { +TEST(math_h, lgammal_r) { int sign; ASSERT_DOUBLE_EQ(log(24.0L), lgamma_r(5.0L, &sign)); ASSERT_EQ(1, sign); } -TEST(MATH_TEST, lgammal_r_17471883) { +TEST(math_h, lgammal_r_17471883) { int sign; sign = 0; @@ -1527,142 +1520,142 @@ TEST(MATH_TEST, lgammal_r_17471883) { ASSERT_EQ(-1, sign); } -TEST(MATH_TEST, tgamma_NaN) { +TEST(math_h, tgamma_NaN) { ASSERT_TRUE(isnan(tgamma(nan("")))); ASSERT_TRUE(isnanf(tgammaf(nanf("")))); ASSERT_TRUE(isnanl(tgammal(nanl("")))); } -TEST(MATH_TEST, tgamma_inf) { +TEST(math_h, tgamma_inf) { ASSERT_TRUE(isinf(tgamma(HUGE_VAL))); ASSERT_TRUE(isinff(tgammaf(HUGE_VALF))); ASSERT_TRUE(isinfl(tgammal(HUGE_VALL))); } -TEST(MATH_TEST, tgamma_negative) { +TEST(math_h, tgamma_negative) { ASSERT_TRUE(isnan(tgamma(-1.0))); ASSERT_TRUE(isnanf(tgammaf(-1.0f))); ASSERT_TRUE(isnanl(tgammal(-1.0L))); } -TEST(MATH_TEST, tgamma) { +TEST(math_h, tgamma) { ASSERT_DOUBLE_EQ(24.0, tgamma(5.0)); ASSERT_DOUBLE_EQ(120.0, tgamma(6.0)); ASSERT_TRUE(isinf(tgamma(172.0))); } -TEST(MATH_TEST, tgammaf) { +TEST(math_h, tgammaf) { ASSERT_FLOAT_EQ(24.0f, tgammaf(5.0f)); ASSERT_FLOAT_EQ(120.0f, tgammaf(6.0f)); ASSERT_TRUE(isinff(tgammaf(172.0f))); } -TEST(MATH_TEST, tgammal) { +TEST(math_h, tgammal) { ASSERT_DOUBLE_EQ(24.0L, tgammal(5.0L)); ASSERT_DOUBLE_EQ(120.0L, tgammal(6.0L)); ASSERT_TRUE(isinf(tgammal(172.0L))); } -TEST(MATH_TEST, j0) { +TEST(math_h, j0) { ASSERT_DOUBLE_EQ(1.0, j0(0.0)); ASSERT_DOUBLE_EQ(0.76519768655796661, j0(1.0)); } -TEST(MATH_TEST, j0f) { +TEST(math_h, j0f) { ASSERT_FLOAT_EQ(1.0f, j0f(0.0f)); ASSERT_FLOAT_EQ(0.76519769f, j0f(1.0f)); } -TEST(MATH_TEST, j1) { +TEST(math_h, j1) { ASSERT_DOUBLE_EQ(0.0, j1(0.0)); ASSERT_DOUBLE_EQ(0.44005058574493355, j1(1.0)); } -TEST(MATH_TEST, j1f) { +TEST(math_h, j1f) { ASSERT_FLOAT_EQ(0.0f, j1f(0.0f)); ASSERT_FLOAT_EQ(0.44005057f, j1f(1.0f)); } -TEST(MATH_TEST, jn) { +TEST(math_h, jn) { ASSERT_DOUBLE_EQ(0.0, jn(4, 0.0)); ASSERT_DOUBLE_EQ(0.0024766389641099553, jn(4, 1.0)); } -TEST(MATH_TEST, jnf) { +TEST(math_h, jnf) { ASSERT_FLOAT_EQ(0.0f, jnf(4, 0.0f)); ASSERT_FLOAT_EQ(0.0024766389f, jnf(4, 1.0f)); } -TEST(MATH_TEST, y0) { +TEST(math_h, y0) { ASSERT_DOUBLE_EQ(-HUGE_VAL, y0(0.0)); ASSERT_DOUBLE_EQ(0.08825696421567697, y0(1.0)); } -TEST(MATH_TEST, y0f) { +TEST(math_h, y0f) { ASSERT_FLOAT_EQ(-HUGE_VALF, y0f(0.0f)); ASSERT_FLOAT_EQ(0.088256963f, y0f(1.0f)); } -TEST(MATH_TEST, y1) { +TEST(math_h, y1) { ASSERT_DOUBLE_EQ(-HUGE_VAL, y1(0.0)); ASSERT_DOUBLE_EQ(-0.78121282130028868, y1(1.0)); } -TEST(MATH_TEST, y1f) { +TEST(math_h, y1f) { ASSERT_FLOAT_EQ(-HUGE_VALF, y1f(0.0f)); ASSERT_FLOAT_EQ(-0.78121281f, y1f(1.0f)); } -TEST(MATH_TEST, yn) { +TEST(math_h, yn) { ASSERT_DOUBLE_EQ(-HUGE_VAL, yn(4, 0.0)); ASSERT_DOUBLE_EQ(-33.278423028972114, yn(4, 1.0)); } -TEST(MATH_TEST, ynf) { +TEST(math_h, ynf) { ASSERT_FLOAT_EQ(-HUGE_VALF, ynf(4, 0.0f)); ASSERT_FLOAT_EQ(-33.278423f, ynf(4, 1.0f)); } -TEST(MATH_TEST, frexp) { +TEST(math_h, frexp) { int exp; double dr = frexp(1024.0, &exp); ASSERT_DOUBLE_EQ(1024.0, scalbn(dr, exp)); } -TEST(MATH_TEST, frexpf) { +TEST(math_h, frexpf) { int exp; float fr = frexpf(1024.0f, &exp); ASSERT_FLOAT_EQ(1024.0f, scalbnf(fr, exp)); } -TEST(MATH_TEST, frexpl) { +TEST(math_h, frexpl) { int exp; long double ldr = frexpl(1024.0L, &exp); ASSERT_DOUBLE_EQ(1024.0L, scalbnl(ldr, exp)); } -TEST(MATH_TEST, modf) { +TEST(math_h, modf) { double di; double df = modf(123.75, &di); ASSERT_DOUBLE_EQ(123.0, di); ASSERT_DOUBLE_EQ(0.75, df); } -TEST(MATH_TEST, modff) { +TEST(math_h, modff) { float fi; float ff = modff(123.75f, &fi); ASSERT_FLOAT_EQ(123.0f, fi); ASSERT_FLOAT_EQ(0.75f, ff); } -TEST(MATH_TEST, modfl) { +TEST(math_h, modfl) { long double ldi; long double ldf = modfl(123.75L, &ldi); ASSERT_DOUBLE_EQ(123.0L, ldi); ASSERT_DOUBLE_EQ(0.75L, ldf); } -TEST(MATH_TEST, remquo) { +TEST(math_h, remquo) { int q; double d = remquo(13.0, 4.0, &q); ASSERT_EQ(3, q); @@ -1680,7 +1673,7 @@ TEST(MATH_TEST, remquo) { ASSERT_TRUE(isnan(remquo(12.0, 0.0, &q))); } -TEST(MATH_TEST, remquof) { +TEST(math_h, remquof) { int q; float f = remquof(13.0f, 4.0f, &q); ASSERT_EQ(3, q); @@ -1698,7 +1691,7 @@ TEST(MATH_TEST, remquof) { ASSERT_TRUE(isnanf(remquof(12.0f, 0.0f, &q))); } -TEST(MATH_TEST, remquol) { +TEST(math_h, remquol) { int q; long double ld = remquol(13.0L, 4.0L, &q); ASSERT_DOUBLE_EQ(3L, q); @@ -1717,13 +1710,13 @@ TEST(MATH_TEST, remquol) { } // https://code.google.com/p/android/issues/detail?id=6697 -TEST(MATH_TEST, frexpf_public_bug_6697) { +TEST(math_h, frexpf_public_bug_6697) { int exp; float fr = frexpf(14.1f, &exp); ASSERT_FLOAT_EQ(14.1f, scalbnf(fr, exp)); } -TEST(MATH_TEST, exp2_STRICT_ALIGN_OpenBSD_bug) { +TEST(math_h, exp2_STRICT_ALIGN_OpenBSD_bug) { // OpenBSD/x86's libm had a bug here, but it was already fixed in FreeBSD: // http://svnweb.FreeBSD.org/base/head/lib/msun/src/math_private.h?revision=240827&view=markup ASSERT_DOUBLE_EQ(5.0, exp2(log2(5))); @@ -1731,7 +1724,7 @@ TEST(MATH_TEST, exp2_STRICT_ALIGN_OpenBSD_bug) { ASSERT_DOUBLE_EQ(5.0L, exp2l(log2l(5))); } -TEST(MATH_TEST, nextafterl_OpenBSD_bug) { +TEST(math_h, nextafterl_OpenBSD_bug) { // OpenBSD/x86's libm had a bug here. ASSERT_TRUE(nextafter(1.0, 0.0) - 1.0 < 0.0); ASSERT_TRUE(nextafterf(1.0f, 0.0f) - 1.0f < 0.0f); @@ -1739,511 +1732,511 @@ TEST(MATH_TEST, nextafterl_OpenBSD_bug) { } #include "math_data/acos_intel_data.h" -TEST(MATH_TEST, acos_intel) { +TEST(math_h, acos_intel) { DoMathDataTest<1>(g_acos_intel_data, acos); } #include "math_data/acosf_intel_data.h" -TEST(MATH_TEST, acosf_intel) { +TEST(math_h, acosf_intel) { DoMathDataTest<1>(g_acosf_intel_data, acosf); } #include "math_data/acosh_intel_data.h" -TEST(MATH_TEST, acosh_intel) { +TEST(math_h, acosh_intel) { DoMathDataTest<2>(g_acosh_intel_data, acosh); } #include "math_data/acoshf_intel_data.h" -TEST(MATH_TEST, acoshf_intel) { +TEST(math_h, acoshf_intel) { DoMathDataTest<2>(g_acoshf_intel_data, acoshf); } #include "math_data/asin_intel_data.h" -TEST(MATH_TEST, asin_intel) { +TEST(math_h, asin_intel) { DoMathDataTest<1>(g_asin_intel_data, asin); } #include "math_data/asinf_intel_data.h" -TEST(MATH_TEST, asinf_intel) { +TEST(math_h, asinf_intel) { DoMathDataTest<1>(g_asinf_intel_data, asinf); } #include "math_data/asinh_intel_data.h" -TEST(MATH_TEST, asinh_intel) { +TEST(math_h, asinh_intel) { DoMathDataTest<2>(g_asinh_intel_data, asinh); } #include "math_data/asinhf_intel_data.h" -TEST(MATH_TEST, asinhf_intel) { +TEST(math_h, asinhf_intel) { DoMathDataTest<2>(g_asinhf_intel_data, asinhf); } #include "math_data/atan2_intel_data.h" -TEST(MATH_TEST, atan2_intel) { +TEST(math_h, atan2_intel) { DoMathDataTest<2>(g_atan2_intel_data, atan2); } #include "math_data/atan2f_intel_data.h" -TEST(MATH_TEST, atan2f_intel) { +TEST(math_h, atan2f_intel) { DoMathDataTest<2>(g_atan2f_intel_data, atan2f); } #include "math_data/atan_intel_data.h" -TEST(MATH_TEST, atan_intel) { +TEST(math_h, atan_intel) { DoMathDataTest<1>(g_atan_intel_data, atan); } #include "math_data/atanf_intel_data.h" -TEST(MATH_TEST, atanf_intel) { +TEST(math_h, atanf_intel) { DoMathDataTest<1>(g_atanf_intel_data, atanf); } #include "math_data/atanh_intel_data.h" -TEST(MATH_TEST, atanh_intel) { +TEST(math_h, atanh_intel) { DoMathDataTest<2>(g_atanh_intel_data, atanh); } #include "math_data/atanhf_intel_data.h" -TEST(MATH_TEST, atanhf_intel) { +TEST(math_h, atanhf_intel) { DoMathDataTest<2>(g_atanhf_intel_data, atanhf); } #include "math_data/cbrt_intel_data.h" -TEST(MATH_TEST, cbrt_intel) { +TEST(math_h, cbrt_intel) { DoMathDataTest<1>(g_cbrt_intel_data, cbrt); } #include "math_data/cbrtf_intel_data.h" -TEST(MATH_TEST, cbrtf_intel) { +TEST(math_h, cbrtf_intel) { DoMathDataTest<1>(g_cbrtf_intel_data, cbrtf); } #include "math_data/ceil_intel_data.h" -TEST(MATH_TEST, ceil_intel) { +TEST(math_h, ceil_intel) { DoMathDataTest<1>(g_ceil_intel_data, ceil); } #include "math_data/ceilf_intel_data.h" -TEST(MATH_TEST, ceilf_intel) { +TEST(math_h, ceilf_intel) { DoMathDataTest<1>(g_ceilf_intel_data, ceilf); } #include "math_data/copysign_intel_data.h" -TEST(MATH_TEST, copysign_intel) { +TEST(math_h, copysign_intel) { DoMathDataTest<1>(g_copysign_intel_data, copysign); } #include "math_data/copysignf_intel_data.h" -TEST(MATH_TEST, copysignf_intel) { +TEST(math_h, copysignf_intel) { DoMathDataTest<1>(g_copysignf_intel_data, copysignf); } #include "math_data/cos_intel_data.h" -TEST(MATH_TEST, cos_intel) { +TEST(math_h, cos_intel) { DoMathDataTest<1>(g_cos_intel_data, cos); } #include "math_data/cosf_intel_data.h" -TEST(MATH_TEST, cosf_intel) { +TEST(math_h, cosf_intel) { DoMathDataTest<1>(g_cosf_intel_data, cosf); } #include "math_data/cosh_intel_data.h" -TEST(MATH_TEST, cosh_intel) { +TEST(math_h, cosh_intel) { DoMathDataTest<2>(g_cosh_intel_data, cosh); } #include "math_data/coshf_intel_data.h" -TEST(MATH_TEST, coshf_intel) { +TEST(math_h, coshf_intel) { DoMathDataTest<2>(g_coshf_intel_data, coshf); } #include "math_data/exp_intel_data.h" -TEST(MATH_TEST, exp_intel) { +TEST(math_h, exp_intel) { DoMathDataTest<1>(g_exp_intel_data, exp); } #include "math_data/expf_intel_data.h" -TEST(MATH_TEST, expf_intel) { +TEST(math_h, expf_intel) { DoMathDataTest<1>(g_expf_intel_data, expf); } #include "math_data/exp2_intel_data.h" -TEST(MATH_TEST, exp2_intel) { +TEST(math_h, exp2_intel) { DoMathDataTest<1>(g_exp2_intel_data, exp2); } #include "math_data/exp2f_intel_data.h" -TEST(MATH_TEST, exp2f_intel) { +TEST(math_h, exp2f_intel) { DoMathDataTest<1>(g_exp2f_intel_data, exp2f); } #include "math_data/expm1_intel_data.h" -TEST(MATH_TEST, expm1_intel) { +TEST(math_h, expm1_intel) { DoMathDataTest<1>(g_expm1_intel_data, expm1); } #include "math_data/expm1f_intel_data.h" -TEST(MATH_TEST, expm1f_intel) { +TEST(math_h, expm1f_intel) { DoMathDataTest<1>(g_expm1f_intel_data, expm1f); } #include "math_data/fabs_intel_data.h" -TEST(MATH_TEST, fabs_intel) { +TEST(math_h, fabs_intel) { DoMathDataTest<1>(g_fabs_intel_data, fabs); } #include "math_data/fabsf_intel_data.h" -TEST(MATH_TEST, fabsf_intel) { +TEST(math_h, fabsf_intel) { DoMathDataTest<1>(g_fabsf_intel_data, fabsf); } #include "math_data/fdim_intel_data.h" -TEST(MATH_TEST, fdim_intel) { +TEST(math_h, fdim_intel) { DoMathDataTest<1>(g_fdim_intel_data, fdim); } #include "math_data/fdimf_intel_data.h" -TEST(MATH_TEST, fdimf_intel) { +TEST(math_h, fdimf_intel) { DoMathDataTest<1>(g_fdimf_intel_data, fdimf); } #include "math_data/floor_intel_data.h" -TEST(MATH_TEST, floor_intel) { +TEST(math_h, floor_intel) { DoMathDataTest<1>(g_floor_intel_data, floor); } #include "math_data/floorf_intel_data.h" -TEST(MATH_TEST, floorf_intel) { +TEST(math_h, floorf_intel) { DoMathDataTest<1>(g_floorf_intel_data, floorf); } #include "math_data/fma_intel_data.h" -TEST(MATH_TEST, fma_intel) { +TEST(math_h, fma_intel) { DoMathDataTest<1>(g_fma_intel_data, fma); } #include "math_data/fmaf_intel_data.h" -TEST(MATH_TEST, fmaf_intel) { +TEST(math_h, fmaf_intel) { DoMathDataTest<1>(g_fmaf_intel_data, fmaf); } #include "math_data/fmax_intel_data.h" -TEST(MATH_TEST, fmax_intel) { +TEST(math_h, fmax_intel) { DoMathDataTest<1>(g_fmax_intel_data, fmax); } #include "math_data/fmaxf_intel_data.h" -TEST(MATH_TEST, fmaxf_intel) { +TEST(math_h, fmaxf_intel) { DoMathDataTest<1>(g_fmaxf_intel_data, fmaxf); } #include "math_data/fmin_intel_data.h" -TEST(MATH_TEST, fmin_intel) { +TEST(math_h, fmin_intel) { DoMathDataTest<1>(g_fmin_intel_data, fmin); } #include "math_data/fminf_intel_data.h" -TEST(MATH_TEST, fminf_intel) { +TEST(math_h, fminf_intel) { DoMathDataTest<1>(g_fminf_intel_data, fminf); } #include "math_data/fmod_intel_data.h" -TEST(MATH_TEST, fmod_intel) { +TEST(math_h, fmod_intel) { DoMathDataTest<1>(g_fmod_intel_data, fmod); } #include "math_data/fmodf_intel_data.h" -TEST(MATH_TEST, fmodf_intel) { +TEST(math_h, fmodf_intel) { DoMathDataTest<1>(g_fmodf_intel_data, fmodf); } #include "math_data/frexp_intel_data.h" -TEST(MATH_TEST, frexp_intel) { +TEST(math_h, frexp_intel) { DoMathDataTest<1>(g_frexp_intel_data, frexp); } #include "math_data/frexpf_intel_data.h" -TEST(MATH_TEST, frexpf_intel) { +TEST(math_h, frexpf_intel) { DoMathDataTest<1>(g_frexpf_intel_data, frexpf); } #include "math_data/hypot_intel_data.h" -TEST(MATH_TEST, hypot_intel) { +TEST(math_h, hypot_intel) { DoMathDataTest<1>(g_hypot_intel_data, hypot); } #include "math_data/hypotf_intel_data.h" -TEST(MATH_TEST, hypotf_intel) { +TEST(math_h, hypotf_intel) { DoMathDataTest<1>(g_hypotf_intel_data, hypotf); } #include "math_data/ilogb_intel_data.h" -TEST(MATH_TEST, ilogb_intel) { +TEST(math_h, ilogb_intel) { DoMathDataTest<1>(g_ilogb_intel_data, ilogb); } #include "math_data/ilogbf_intel_data.h" -TEST(MATH_TEST, ilogbf_intel) { +TEST(math_h, ilogbf_intel) { DoMathDataTest<1>(g_ilogbf_intel_data, ilogbf); } #include "math_data/ldexp_intel_data.h" -TEST(MATH_TEST, ldexp_intel) { +TEST(math_h, ldexp_intel) { DoMathDataTest<1>(g_ldexp_intel_data, ldexp); } #include "math_data/ldexpf_intel_data.h" -TEST(MATH_TEST, ldexpf_intel) { +TEST(math_h, ldexpf_intel) { DoMathDataTest<1>(g_ldexpf_intel_data, ldexpf); } #include "math_data/llrint_intel_data.h" -TEST(MATH_TEST, llrint_intel) { +TEST(math_h, llrint_intel) { DoMathDataTest<1>(g_llrint_intel_data, llrint); } #include "math_data/llrintf_intel_data.h" -TEST(MATH_TEST, llrintf_intel) { +TEST(math_h, llrintf_intel) { DoMathDataTest<1>(g_llrintf_intel_data, llrintf); } #include "math_data/log_intel_data.h" -TEST(MATH_TEST, log_intel) { +TEST(math_h, log_intel) { DoMathDataTest<1>(g_log_intel_data, log); } #include "math_data/logf_intel_data.h" -TEST(MATH_TEST, logf_intel) { +TEST(math_h, logf_intel) { DoMathDataTest<1>(g_logf_intel_data, logf); } #include "math_data/log10_intel_data.h" -TEST(MATH_TEST, log10_intel) { +TEST(math_h, log10_intel) { DoMathDataTest<1>(g_log10_intel_data, log10); } #include "math_data/log10f_intel_data.h" -TEST(MATH_TEST, log10f_intel) { +TEST(math_h, log10f_intel) { DoMathDataTest<1>(g_log10f_intel_data, log10f); } #include "math_data/log1p_intel_data.h" -TEST(MATH_TEST, log1p_intel) { +TEST(math_h, log1p_intel) { DoMathDataTest<1>(g_log1p_intel_data, log1p); } #include "math_data/log1pf_intel_data.h" -TEST(MATH_TEST, log1pf_intel) { +TEST(math_h, log1pf_intel) { DoMathDataTest<1>(g_log1pf_intel_data, log1pf); } #include "math_data/log2_intel_data.h" -TEST(MATH_TEST, log2_intel) { +TEST(math_h, log2_intel) { DoMathDataTest<1>(g_log2_intel_data, log2); } #include "math_data/log2f_intel_data.h" -TEST(MATH_TEST, log2f_intel) { +TEST(math_h, log2f_intel) { DoMathDataTest<1>(g_log2f_intel_data, log2f); } #include "math_data/logb_intel_data.h" -TEST(MATH_TEST, logb_intel) { +TEST(math_h, logb_intel) { DoMathDataTest<1>(g_logb_intel_data, logb); } #include "math_data/logbf_intel_data.h" -TEST(MATH_TEST, logbf_intel) { +TEST(math_h, logbf_intel) { DoMathDataTest<1>(g_logbf_intel_data, logbf); } #include "math_data/lrint_intel_data.h" -TEST(MATH_TEST, lrint_intel) { +TEST(math_h, lrint_intel) { DoMathDataTest<1>(g_lrint_intel_data, lrint); } #include "math_data/lrintf_intel_data.h" -TEST(MATH_TEST, lrintf_intel) { +TEST(math_h, lrintf_intel) { DoMathDataTest<1>(g_lrintf_intel_data, lrintf); } #include "math_data/modf_intel_data.h" -TEST(MATH_TEST, modf_intel) { +TEST(math_h, modf_intel) { DoMathDataTest<1>(g_modf_intel_data, modf); } #include "math_data/modff_intel_data.h" -TEST(MATH_TEST, modff_intel) { +TEST(math_h, modff_intel) { DoMathDataTest<1>(g_modff_intel_data, modff); } #include "math_data/nearbyint_intel_data.h" -TEST(MATH_TEST, nearbyint_intel) { +TEST(math_h, nearbyint_intel) { DoMathDataTest<1>(g_nearbyint_intel_data, nearbyint); } #include "math_data/nearbyintf_intel_data.h" -TEST(MATH_TEST, nearbyintf_intel) { +TEST(math_h, nearbyintf_intel) { DoMathDataTest<1>(g_nearbyintf_intel_data, nearbyintf); } #include "math_data/nextafter_intel_data.h" -TEST(MATH_TEST, nextafter_intel) { +TEST(math_h, nextafter_intel) { DoMathDataTest<1>(g_nextafter_intel_data, nextafter); } #include "math_data/nextafterf_intel_data.h" -TEST(MATH_TEST, nextafterf_intel) { +TEST(math_h, nextafterf_intel) { DoMathDataTest<1>(g_nextafterf_intel_data, nextafterf); } #include "math_data/pow_intel_data.h" -TEST(MATH_TEST, pow_intel) { +TEST(math_h, pow_intel) { DoMathDataTest<1>(g_pow_intel_data, pow); } #include "math_data/powf_intel_data.h" -TEST(MATH_TEST, powf_intel) { +TEST(math_h, powf_intel) { DoMathDataTest<1>(g_powf_intel_data, powf); } #include "math_data/remainder_intel_data.h" -TEST(MATH_TEST, remainder_intel) { +TEST(math_h, remainder_intel) { DoMathDataTest<1>(g_remainder_intel_data, remainder); } #include "math_data/remainderf_intel_data.h" -TEST(MATH_TEST, remainderf_intel) { +TEST(math_h, remainderf_intel) { DoMathDataTest<1>(g_remainderf_intel_data, remainderf); } #include "math_data/remquo_intel_data.h" -TEST(MATH_TEST, remquo_intel) { +TEST(math_h, remquo_intel) { DoMathDataTest<1>(g_remquo_intel_data, remquo); } #include "math_data/remquof_intel_data.h" -TEST(MATH_TEST, remquof_intel) { +TEST(math_h, remquof_intel) { DoMathDataTest<1>(g_remquof_intel_data, remquof); } #include "math_data/rint_intel_data.h" -TEST(MATH_TEST, rint_intel) { +TEST(math_h, rint_intel) { DoMathDataTest<1>(g_rint_intel_data, rint); } #include "math_data/rintf_intel_data.h" -TEST(MATH_TEST, rintf_intel) { +TEST(math_h, rintf_intel) { DoMathDataTest<1>(g_rintf_intel_data, rintf); } #include "math_data/round_intel_data.h" -TEST(MATH_TEST, round_intel) { +TEST(math_h, round_intel) { DoMathDataTest<1>(g_round_intel_data, round); } #include "math_data/roundf_intel_data.h" -TEST(MATH_TEST, roundf_intel) { +TEST(math_h, roundf_intel) { DoMathDataTest<1>(g_roundf_intel_data, roundf); } #include "math_data/scalb_intel_data.h" -TEST(MATH_TEST, scalb_intel) { +TEST(math_h, scalb_intel) { DoMathDataTest<1>(g_scalb_intel_data, scalb); } #include "math_data/scalbf_intel_data.h" -TEST(MATH_TEST, scalbf_intel) { +TEST(math_h, scalbf_intel) { DoMathDataTest<1>(g_scalbf_intel_data, scalbf); } #include "math_data/scalbn_intel_data.h" -TEST(MATH_TEST, scalbn_intel) { +TEST(math_h, scalbn_intel) { DoMathDataTest<1>(g_scalbn_intel_data, scalbn); } #include "math_data/scalbnf_intel_data.h" -TEST(MATH_TEST, scalbnf_intel) { +TEST(math_h, scalbnf_intel) { DoMathDataTest<1>(g_scalbnf_intel_data, scalbnf); } #include "math_data/significand_intel_data.h" -TEST(MATH_TEST, significand_intel) { +TEST(math_h, significand_intel) { DoMathDataTest<1>(g_significand_intel_data, significand); } #include "math_data/significandf_intel_data.h" -TEST(MATH_TEST, significandf_intel) { +TEST(math_h, significandf_intel) { DoMathDataTest<1>(g_significandf_intel_data, significandf); } #include "math_data/sin_intel_data.h" -TEST(MATH_TEST, sin_intel) { +TEST(math_h, sin_intel) { DoMathDataTest<1>(g_sin_intel_data, sin); } #include "math_data/sinf_intel_data.h" -TEST(MATH_TEST, sinf_intel) { +TEST(math_h, sinf_intel) { DoMathDataTest<1>(g_sinf_intel_data, sinf); } #include "math_data/sinh_intel_data.h" -TEST(MATH_TEST, sinh_intel) { +TEST(math_h, sinh_intel) { DoMathDataTest<2>(g_sinh_intel_data, sinh); } #include "math_data/sinhf_intel_data.h" -TEST(MATH_TEST, sinhf_intel) { +TEST(math_h, sinhf_intel) { DoMathDataTest<2>(g_sinhf_intel_data, sinhf); } #include "math_data/sincos_intel_data.h" -TEST(MATH_TEST, sincos_intel) { +TEST(math_h, sincos_intel) { DoMathDataTest<1>(g_sincos_intel_data, sincos); } #include "math_data/sincosf_intel_data.h" -TEST(MATH_TEST, sincosf_intel) { +TEST(math_h, sincosf_intel) { DoMathDataTest<1>(g_sincosf_intel_data, sincosf); } #include "math_data/sqrt_intel_data.h" -TEST(MATH_TEST, sqrt_intel) { +TEST(math_h, sqrt_intel) { DoMathDataTest<1>(g_sqrt_intel_data, sqrt); } #include "math_data/sqrtf_intel_data.h" -TEST(MATH_TEST, sqrtf_intel) { +TEST(math_h, sqrtf_intel) { DoMathDataTest<1>(g_sqrtf_intel_data, sqrtf); } #include "math_data/tan_intel_data.h" -TEST(MATH_TEST, tan_intel) { +TEST(math_h, tan_intel) { DoMathDataTest<1>(g_tan_intel_data, tan); } #include "math_data/tanf_intel_data.h" -TEST(MATH_TEST, tanf_intel) { +TEST(math_h, tanf_intel) { DoMathDataTest<1>(g_tanf_intel_data, tanf); } #include "math_data/tanh_intel_data.h" -TEST(MATH_TEST, tanh_intel) { +TEST(math_h, tanh_intel) { DoMathDataTest<2>(g_tanh_intel_data, tanh); } #include "math_data/tanhf_intel_data.h" -TEST(MATH_TEST, tanhf_intel) { +TEST(math_h, tanhf_intel) { DoMathDataTest<2>(g_tanhf_intel_data, tanhf); } #include "math_data/trunc_intel_data.h" -TEST(MATH_TEST, trunc_intel) { +TEST(math_h, trunc_intel) { DoMathDataTest<1>(g_trunc_intel_data, trunc); } #include "math_data/truncf_intel_data.h" -TEST(MATH_TEST, truncf_intel) { +TEST(math_h, truncf_intel) { DoMathDataTest<1>(g_truncf_intel_data, truncf); } diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp index b85edfb2a..c20597b37 100644 --- a/tests/stdio_test.cpp +++ b/tests/stdio_test.cpp @@ -3486,3 +3486,141 @@ TEST(STDIO_TEST, swprintf_invalid_wf_width) { GTEST_SKIP() << "no %w in glibc"; #endif } + +TEST(STDIO_TEST, sscanf_w_base) { +#if defined(__BIONIC__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-invalid-specifier" + int8_t a; + EXPECT_EQ(1, sscanf("<0b101>", "<%w8b>", &a)); + EXPECT_EQ(0b101, a); + int8_t b1; + EXPECT_EQ(1, sscanf("<0xFF>", "<%w8i>", &b1)); + EXPECT_EQ(-1, b1); + int8_t b2; + EXPECT_EQ(1, sscanf("<0x1FF>", "<%w8i>", &b2)); + EXPECT_EQ(-1, b2); + int16_t c1; + EXPECT_EQ(1, sscanf("<0xFFFF>", "<%w16i>", &c1)); + EXPECT_EQ(-1, c1); + uint16_t c2; + EXPECT_EQ(1, sscanf("<64>", "<%w16d>", &c2)); + EXPECT_EQ(64, c2); + int32_t d; + EXPECT_EQ(1, sscanf("<021>", "<%w32o>", &d)); + EXPECT_EQ(021, d); + uint32_t e; + EXPECT_EQ(1, sscanf("<-1>", "<%w32u>", &e)); + EXPECT_EQ(4294967295, e); + int64_t f; + EXPECT_EQ(1, sscanf("<0x3b>", "<%w64x>", &f)); + EXPECT_EQ(0x3b, f); + EXPECT_EQ(1, sscanf("<0x3b>", "<%w64X>", &f)); + EXPECT_EQ(0x3B, f); +#pragma clang diagnostic pop +#else + GTEST_SKIP() << "no %w in glibc"; +#endif +} + +TEST(STDIO_TEST, sscanf_w_combination) { +#if defined(__BIONIC__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat" +#pragma clang diagnostic ignored "-Wformat-invalid-specifier" +#pragma clang diagnostic ignored "-Wformat-extra-args" + uint32_t a; + int64_t b; + char c; + + EXPECT_EQ(3, sscanf("<0b10101010101010101010101010101010 0x3333333344444444 1>", + "<%w32b %w64x %c>", &a, &b, &c)); + EXPECT_EQ(0xaaaaaaaa, a); + EXPECT_EQ(0x3333333344444444, b); + EXPECT_EQ('1', c); +#pragma clang diagnostic pop +#else + GTEST_SKIP() << "no %w in glibc"; +#endif +} + +TEST(STDIO_TEST, sscanf_invalid_w_width) { +#if defined(__BIONIC__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-invalid-specifier" + int32_t a; + EXPECT_DEATH(sscanf("<100>", "<%w20d>", &a), "%w20 is unsupported"); +#pragma clang diagnostic pop +#else + GTEST_SKIP() << "no %w in glibc"; +#endif +} + +TEST(STDIO_TEST, swscanf_w_base) { +#if defined(__BIONIC__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-invalid-specifier" + int8_t a; + EXPECT_EQ(1, swscanf(L"<0b101>", L"<%w8b>", &a)); + EXPECT_EQ(0b101, a); + int8_t b1; + EXPECT_EQ(1, swscanf(L"<0xFF>", L"<%w8i>", &b1)); + EXPECT_EQ(-1, b1); + int8_t b2; + EXPECT_EQ(1, swscanf(L"<0x1FF>", L"<%w8i>", &b2)); + EXPECT_EQ(-1, b2); + int16_t c1; + EXPECT_EQ(1, swscanf(L"<0xFFFF>", L"<%w16i>", &c1)); + EXPECT_EQ(-1, c1); + uint16_t c2; + EXPECT_EQ(1, swscanf(L"<64>", L"<%w16d>", &c2)); + EXPECT_EQ(64, c2); + int32_t d; + EXPECT_EQ(1, swscanf(L"<021>", L"<%w32o>", &d)); + EXPECT_EQ(021, d); + uint32_t e; + EXPECT_EQ(1, swscanf(L"<-1>", L"<%w32u>", &e)); + EXPECT_EQ(4294967295, e); + int64_t f; + EXPECT_EQ(1, swscanf(L"<0x3b>", L"<%w64x>", &f)); + EXPECT_EQ(0x3b, f); + EXPECT_EQ(1, swscanf(L"<0x3b>", L"<%w64X>", &f)); + EXPECT_EQ(0x3B, f); +#pragma clang diagnostic pop +#else + GTEST_SKIP() << "no %w in glibc"; +#endif +} + +TEST(STDIO_TEST, swscanf_w_combination) { +#if defined(__BIONIC__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat" +#pragma clang diagnostic ignored "-Wformat-invalid-specifier" +#pragma clang diagnostic ignored "-Wformat-extra-args" + uint32_t a; + int64_t b; + char c; + + EXPECT_EQ(3, swscanf(L"<0b10101010101010101010101010101010 0x3333333344444444 1>", + L"<%w32b %w64x %c>", &a, &b, &c)); + EXPECT_EQ(0xaaaaaaaa, a); + EXPECT_EQ(0x3333333344444444, b); + EXPECT_EQ('1', c); +#pragma clang diagnostic pop +#else + GTEST_SKIP() << "no %w in glibc"; +#endif +} + +TEST(STDIO_TEST, swscanf_invalid_w_width) { +#if defined(__BIONIC__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-invalid-specifier" + int32_t a; + EXPECT_DEATH(swscanf(L"<100>", L"<%w20d>", &a), "%w20 is unsupported"); +#pragma clang diagnostic pop +#else + GTEST_SKIP() << "no %w in glibc"; +#endif +}
\ No newline at end of file diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp index c818197a0..5afa00baa 100644 --- a/tools/versioner/src/versioner.cpp +++ b/tools/versioner/src/versioner.cpp @@ -284,8 +284,8 @@ static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) { // If a function is declared as an inline before a certain version, the inline definition // should have no version tag. // 3. Each availability type must only be present globally or on a per-arch basis. -// (e.g. __INTRODUCED_IN_ARM(9) __INTRODUCED_IN_X86(10) __DEPRECATED_IN(11) is fine, -// but not __INTRODUCED_IN(9) __INTRODUCED_IN_X86(10)) +// (e.g. __INTRODUCED_IN_32(21) __INTRODUCED_IN_64(22) __DEPRECATED_IN(23) is fine, +// but not __INTRODUCED_IN(9) __INTRODUCED_IN_32(10)) static bool checkSymbol(const Symbol& symbol) { std::string cwd = getWorkingDir() + "/"; diff --git a/tools/versioner/tests/preprocessor/expected/foo.h b/tools/versioner/tests/preprocessor/expected/foo.h index d7de9a0f8..4f74927dc 100644 --- a/tools/versioner/tests/preprocessor/expected/foo.h +++ b/tools/versioner/tests/preprocessor/expected/foo.h @@ -54,15 +54,16 @@ int multiple_archs() __INTRODUCED_IN(14); // __INTRODUCED_IN_64(21) should be ignored. -#if (!defined(__LP64__) && __ANDROID_API__ >= 13) || (defined(__LP64__)) -int multiple_introduced_1() __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_X86(13) __INTRODUCED_IN_64(21); -#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 13) || (defined(__LP64__)) */ +#if (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__)) +int multiple_introduced_1() __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(21); +#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__)) */ +// This needs different guards for 32 vs 64. -#if (!defined(__LP64__) && __ANDROID_API__ >= 13) || (defined(__LP64__) && __ANDROID_API__ >= 22) -int multiple_introduced_2() __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_X86(13) __INTRODUCED_IN_64(22); -#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 13) || (defined(__LP64__) && __ANDROID_API__ >= 22) */ +#if (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__) && __ANDROID_API__ >= 26) +int multiple_introduced_2() __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(26); +#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 24) || (defined(__LP64__) && __ANDROID_API__ >= 26) */ // This produces both an LP64 and a not-LP64 check, but it doesn't need to check for all 64-bit @@ -74,9 +75,9 @@ int multiple_introduced_3() __INTRODUCED_IN_32(23) __INTRODUCED_IN_64(23); -#if (!defined(__LP64__) && __ANDROID_API__ >= 12) || (defined(__LP64__)) -int group_lp32() __INTRODUCED_IN_ARM(12) __INTRODUCED_IN_X86(12); -#endif /* (!defined(__LP64__) && __ANDROID_API__ >= 12) || (defined(__LP64__)) */ +#if (!defined(__LP64__)) || (defined(__LP64__) && __ANDROID_API__ >= 28) +int added_to_lp64_late() __INTRODUCED_IN_64(28); +#endif /* (!defined(__LP64__)) || (defined(__LP64__) && __ANDROID_API__ >= 28) */ #if defined(__cplusplus) diff --git a/tools/versioner/tests/preprocessor/headers/foo.h b/tools/versioner/tests/preprocessor/headers/foo.h index 7b39f29c5..b01d8a981 100644 --- a/tools/versioner/tests/preprocessor/headers/foo.h +++ b/tools/versioner/tests/preprocessor/headers/foo.h @@ -37,15 +37,16 @@ int multiple_archs() __INTRODUCED_IN(14); #endif // __INTRODUCED_IN_64(21) should be ignored. -int multiple_introduced_1() __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_X86(13) __INTRODUCED_IN_64(21); +int multiple_introduced_1() __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(21); -int multiple_introduced_2() __INTRODUCED_IN_ARM(13) __INTRODUCED_IN_X86(13) __INTRODUCED_IN_64(22); +// This needs different guards for 32 vs 64. +int multiple_introduced_2() __INTRODUCED_IN_32(24) __INTRODUCED_IN_64(26); // This produces both an LP64 and a not-LP64 check, but it doesn't need to check for all 64-bit // targets separately. int multiple_introduced_3() __INTRODUCED_IN_32(23) __INTRODUCED_IN_64(23); -int group_lp32() __INTRODUCED_IN_ARM(12) __INTRODUCED_IN_X86(12); +int added_to_lp64_late() __INTRODUCED_IN_64(28); #if defined(__cplusplus) } |