[libc-commits] [libc] a499d68 - [libc] Create abort and _Exit

Alex Brachet via libc-commits libc-commits at lists.llvm.org
Thu Mar 5 11:22:53 PST 2020


Author: Alex Brachet
Date: 2020-03-05T14:21:18-05:00
New Revision: a499d6805664350095658878e25f6ae20a106748

URL: https://github.com/llvm/llvm-project/commit/a499d6805664350095658878e25f6ae20a106748
DIFF: https://github.com/llvm/llvm-project/commit/a499d6805664350095658878e25f6ae20a106748.diff

LOG: [libc] Create abort and _Exit

This revision creates abort and _Exit implementations

Differential Revision: https://reviews.llvm.org/D74949

Added: 
    libc/include/stdlib.h.def
    libc/src/stdlib/CMakeLists.txt
    libc/src/stdlib/_Exit.h
    libc/src/stdlib/abort.cpp
    libc/src/stdlib/abort.h
    libc/src/stdlib/linux/CMakeLists.txt
    libc/src/stdlib/linux/_Exit.cpp
    libc/test/src/stdlib/CMakeLists.txt
    libc/test/src/stdlib/_Exit_test.cpp
    libc/test/src/stdlib/abort_test.cpp

Modified: 
    libc/config/linux/api.td
    libc/include/CMakeLists.txt
    libc/include/__llvm-libc-common.h
    libc/lib/CMakeLists.txt
    libc/spec/spec.td
    libc/spec/stdc.td
    libc/src/CMakeLists.txt
    libc/test/src/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 3ed556a93c03..1c9fa8a36c2e 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -84,6 +84,13 @@ def StdIOAPI : PublicAPI<"stdio.h"> {
   ];
 }
 
+def StdlibAPI : PublicAPI<"stdlib.h"> {
+  let Functions = [
+    "_Exit",
+    "abort",
+  ];
+}
+
 def ErrnoAPI : PublicAPI<"errno.h"> {
   let Macros = [
     ErrnoMacro,

diff  --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 612b53196270..db5f371f75f3 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -63,6 +63,14 @@ add_gen_header(
     ../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.

diff  --git a/libc/include/__llvm-libc-common.h b/libc/include/__llvm-libc-common.h
index 7dc2f9e4e6d5..18b74e387800 100644
--- a/libc/include/__llvm-libc-common.h
+++ b/libc/include/__llvm-libc-common.h
@@ -17,6 +17,9 @@
 #undef __END_C_DECLS
 #define __END_C_DECLS }
 
+#undef _Noreturn
+#define _Noreturn [[noreturn]]
+
 #else // not __cplusplus
 
 #undef __BEGIN_C_DECLS

diff  --git a/libc/include/stdlib.h.def b/libc/include/stdlib.h.def
new file mode 100644
index 000000000000..97e3846350c7
--- /dev/null
+++ b/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

diff  --git a/libc/lib/CMakeLists.txt b/libc/lib/CMakeLists.txt
index b4ab4109d167..b67f8e4c686b 100644
--- a/libc/lib/CMakeLists.txt
+++ b/libc/lib/CMakeLists.txt
@@ -18,6 +18,10 @@ add_entrypoint_library(
     sigaddset
     sigemptyset
     sigprocmask
+
+    # stdlib.h entrypoints
+    _Exit
+    abort
 )
 
 add_entrypoint_library(

diff  --git a/libc/spec/spec.td b/libc/spec/spec.td
index 2272ef3da368..979efeaf066f 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -48,6 +48,9 @@ def CharType : NamedType<"char">;
 def VoidPtr : PtrType<VoidType>;
 def SizeTType : NamedType<"size_t">;
 
+// _Noreturn is really not a type, but it is convenient to treat it as a type.
+def NoReturn : NamedType<"_Noreturn void">;
+
 class Macro<string name> {
   string Name = name;
 }

diff  --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 0eff0205d74a..babfce4b6ad2 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -178,6 +178,17 @@ def StdC : StandardSpec<"stdc"> {
       ]
   >;
 
+  HeaderSpec StdLib = HeaderSpec<
+      "stdlib.h",
+      [], // Macros
+      [], // Types
+      [], // Enumerations
+      [
+          FunctionSpec<"abort", RetValSpec<NoReturn>, [ArgSpec<VoidType>]>,
+          FunctionSpec<"_Exit", RetValSpec<NoReturn>, [ArgSpec<IntType>]>,
+      ]
+  >;
+
   HeaderSpec Errno = HeaderSpec<
       "errno.h",
       [
@@ -278,6 +289,7 @@ def StdC : StandardSpec<"stdc"> {
     Math,
     String,
     StdIO,
+    StdLib,
     Signal,
     Threads,
   ];

diff  --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 0ff0a6ae70cd..7f8ef92e6cc5 100644
--- a/libc/src/CMakeLists.txt
+++ b/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)

diff  --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
new file mode 100644
index 000000000000..52beeb1ab135
--- /dev/null
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -0,0 +1,15 @@
+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
+)

diff  --git a/libc/src/stdlib/_Exit.h b/libc/src/stdlib/_Exit.h
new file mode 100644
index 000000000000..4ac5dd850c07
--- /dev/null
+++ b/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

diff  --git a/libc/src/stdlib/abort.cpp b/libc/src/stdlib/abort.cpp
new file mode 100644
index 000000000000..777e3fd649ec
--- /dev/null
+++ b/libc/src/stdlib/abort.cpp
@@ -0,0 +1,30 @@
+//===---------------------- 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 sigprocmask and sigaction land:
+  // Unblock SIGABRT, raise it, if it was ignored or the handler returned,
+  // change its action to SIG_DFL, raise it again.
+  // TODO: When C11 mutexes land:
+  // Aquire recursive mutex (in case the current signal handler for SIGABRT
+  // itself calls abort we don't want to deadlock on the same thread trying
+  // to aquire it's own mutex.)
+  __llvm_libc::raise(SIGABRT);
+  __llvm_libc::raise(SIGKILL);
+  __llvm_libc::_Exit(127);
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/stdlib/abort.h b/libc/src/stdlib/abort.h
new file mode 100644
index 000000000000..4bf347bb805f
--- /dev/null
+++ b/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

diff  --git a/libc/src/stdlib/linux/CMakeLists.txt b/libc/src/stdlib/linux/CMakeLists.txt
new file mode 100644
index 000000000000..854d45f2ee97
--- /dev/null
+++ b/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
+)

diff  --git a/libc/src/stdlib/linux/_Exit.cpp b/libc/src/stdlib/linux/_Exit.cpp
new file mode 100644
index 000000000000..1c5f60a17a27
--- /dev/null
+++ b/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

diff  --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index bc698a64fa7d..bf56591e1d47 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_subdirectory(errno)
 add_subdirectory(signal)
+add_subdirectory(stdlib)
 add_subdirectory(string)
 add_subdirectory(sys)

diff  --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
new file mode 100644
index 000000000000..6588d457e9a9
--- /dev/null
+++ b/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
+)

diff  --git a/libc/test/src/stdlib/_Exit_test.cpp b/libc/test/src/stdlib/_Exit_test.cpp
new file mode 100644
index 000000000000..49878bfd506e
--- /dev/null
+++ b/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);
+}

diff  --git a/libc/test/src/stdlib/abort_test.cpp b/libc/test/src/stdlib/abort_test.cpp
new file mode 100644
index 000000000000..cefb5d803687
--- /dev/null
+++ b/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);
+}


        


More information about the libc-commits mailing list