Index: libc/include/CMakeLists.txt =================================================================== --- libc/include/CMakeLists.txt +++ libc/include/CMakeLists.txt @@ -55,6 +55,14 @@ ../config/${LIBC_TARGET_OS}/signal.h.in ) +add_gen_header( + stdlib_h + DEF_FILE stdlib.h.def + GEN_HDR stdlib.h + DEPENDS + llvm_libc_common_h +) + # TODO: Not all platforms will have a include/sys directory. Add the sys # directory and the targets for sys/*.h files conditional to the OS requiring # them. Index: libc/include/stdlib.h.def =================================================================== --- /dev/null +++ libc/include/stdlib.h.def @@ -0,0 +1,16 @@ +//===---------------- C standard library header stdlib.h ------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_STDLIB_H +#define LLVM_LIBC_STDLIB_H + +#include <__llvm-libc-common.h> + +%%public_api() + +#endif // LLVM_LIBC_STDLIB_H Index: libc/spec/stdc.td =================================================================== --- libc/spec/stdc.td +++ libc/spec/stdc.td @@ -167,6 +167,16 @@ ] >; + HeaderSpec StdLib = HeaderSpec< + "stdlib.h", + [], // Macros + [], // Types + [ + FunctionSpec<"abort", RetValSpec, [ArgSpec]>, + FunctionSpec<"_Exit", RetValSpec, [ArgSpec]>, + ] + >; + HeaderSpec Errno = HeaderSpec< "errno.h", [ Index: libc/src/CMakeLists.txt =================================================================== --- libc/src/CMakeLists.txt +++ libc/src/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(errno) add_subdirectory(math) add_subdirectory(signal) +add_subdirectory(stdlib) add_subdirectory(string) # TODO: Add this target conditional to the target OS. add_subdirectory(sys) Index: libc/src/stdlib/CMakeLists.txt =================================================================== --- /dev/null +++ libc/src/stdlib/CMakeLists.txt @@ -0,0 +1,16 @@ +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) + add_subdirectory(${LIBC_TARGET_OS}) +endif() + +add_entrypoint_object( + abort + SRCS + abort.cpp + HDRS + abort.h + DEPENDS + raise + _Exit + stdlib_h +) + Index: libc/src/stdlib/_Exit.h =================================================================== --- /dev/null +++ libc/src/stdlib/_Exit.h @@ -0,0 +1,18 @@ +//===----------------- Implementation header for _Exit ---------*- C++ -*--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC__EXIT_H +#define LLVM_LIBC_SRC__EXIT_H + +namespace __llvm_libc { + +[[noreturn]] void _Exit(int status); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC__EXIT_H Index: libc/src/stdlib/abort.h =================================================================== --- /dev/null +++ libc/src/stdlib/abort.h @@ -0,0 +1,18 @@ +//===----------------- Implementation header for abort ---------*- C++ -*--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_ABORT_H +#define LLVM_LIBC_SRC_ABORT_H + +namespace __llvm_libc { + +[[noreturn]] void abort(); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_ABORT_H Index: libc/src/stdlib/abort.cpp =================================================================== --- /dev/null +++ libc/src/stdlib/abort.cpp @@ -0,0 +1,24 @@ +//===---------------------- Implementation of abort -----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/common.h" +#include "src/signal/raise.h" +#include "src/stdlib/_Exit.h" + +#include "src/stdlib/abort.h" + +namespace __llvm_libc { + +void LLVM_LIBC_ENTRYPOINT(abort)() { + // TODO: when sigaction(3) is implemented make sure SIGABRT is SIG_DFL. + __llvm_libc::raise(SIGABRT); + __llvm_libc::raise(SIGKILL); + __llvm_libc::_Exit(127); +} + +} // namespace __llvm_libc Index: libc/src/stdlib/linux/CMakeLists.txt =================================================================== --- /dev/null +++ libc/src/stdlib/linux/CMakeLists.txt @@ -0,0 +1,11 @@ +add_entrypoint_object( + _Exit + SRCS + _Exit.cpp + HDRS + ../_Exit.h + DEPENDS + sys_syscall_h + linux_syscall_h + stdlib_h +) Index: libc/src/stdlib/linux/_Exit.cpp =================================================================== --- /dev/null +++ libc/src/stdlib/linux/_Exit.cpp @@ -0,0 +1,24 @@ +//===------------------- Linux Implementation of _Exit --------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "config/linux/syscall.h" // For internal syscall function. +#include "include/sys/syscall.h" // For syscall numbers. +#include "src/__support/common.h" + +#include "src/stdlib/_Exit.h" + +namespace __llvm_libc { + +void LLVM_LIBC_ENTRYPOINT(_Exit)(int status) { + for (;;) { + __llvm_libc::syscall(SYS_exit_group, status); + __llvm_libc::syscall(SYS_exit, status); + } +} + +} // namespace __llvm_libc Index: libc/test/src/CMakeLists.txt =================================================================== --- libc/test/src/CMakeLists.txt +++ libc/test/src/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(errno) add_subdirectory(signal) +add_subdirectory(stdlib) add_subdirectory(string) add_subdirectory(sys) Index: libc/test/src/stdlib/CMakeLists.txt =================================================================== --- /dev/null +++ libc/test/src/stdlib/CMakeLists.txt @@ -0,0 +1,26 @@ +add_libc_testsuite(libc_stdlib_unittests) + +add_libc_unittest( + _Exit_test + SUITE + libc_stdlib_unittests + SRCS + _Exit_test.cpp + DEPENDS + stdlib_h + _Exit +) + +add_libc_unittest( + abort_test + SUITE + libc_stdlib_unittests + SRCS + abort_test.cpp + DEPENDS + stdlib_h + signal_h + abort + _Exit + raise +) Index: libc/test/src/stdlib/_Exit_test.cpp =================================================================== --- /dev/null +++ libc/test/src/stdlib/_Exit_test.cpp @@ -0,0 +1,16 @@ +//===----------------------- Unittests for _Exit --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "include/stdlib.h" +#include "src/stdlib/_Exit.h" +#include "utils/UnitTest/Test.h" + +TEST(Stdlib, _Exit) { + EXPECT_EXITS([] { __llvm_libc::_Exit(1); }, 1); + EXPECT_EXITS([] { __llvm_libc::_Exit(65); }, 65); +} Index: libc/test/src/stdlib/abort_test.cpp =================================================================== --- /dev/null +++ libc/test/src/stdlib/abort_test.cpp @@ -0,0 +1,18 @@ +//===----------------------- Unittests for abort --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "include/signal.h" +#include "include/stdlib.h" +#include "src/stdlib/abort.h" +#include "utils/UnitTest/Test.h" + +TEST(Stdlib, abort) { + // -1 matches against any signal, which is necessary for now until + // __llvm_libc::abort() unblocks SIGABRT. + EXPECT_DEATH([] { __llvm_libc::abort(); }, -1); +}