[libc] Create abort and _Exit
authorAlex Brachet <alexbrachetmialot@gmail.com>
Thu, 5 Mar 2020 19:21:18 +0000 (14:21 -0500)
committerAlex Brachet <alexbrachetmialot@gmail.com>
Thu, 5 Mar 2020 19:21:18 +0000 (14:21 -0500)
This revision creates abort and _Exit implementations

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

18 files changed:
libc/config/linux/api.td
libc/include/CMakeLists.txt
libc/include/__llvm-libc-common.h
libc/include/stdlib.h.def [new file with mode: 0644]
libc/lib/CMakeLists.txt
libc/spec/spec.td
libc/spec/stdc.td
libc/src/CMakeLists.txt
libc/src/stdlib/CMakeLists.txt [new file with mode: 0644]
libc/src/stdlib/_Exit.h [new file with mode: 0644]
libc/src/stdlib/abort.cpp [new file with mode: 0644]
libc/src/stdlib/abort.h [new file with mode: 0644]
libc/src/stdlib/linux/CMakeLists.txt [new file with mode: 0644]
libc/src/stdlib/linux/_Exit.cpp [new file with mode: 0644]
libc/test/src/CMakeLists.txt
libc/test/src/stdlib/CMakeLists.txt [new file with mode: 0644]
libc/test/src/stdlib/_Exit_test.cpp [new file with mode: 0644]
libc/test/src/stdlib/abort_test.cpp [new file with mode: 0644]

index 3ed556a..1c9fa8a 100644 (file)
@@ -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,
index 612b531..db5f371 100644 (file)
@@ -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.
index 7dc2f9e..18b74e3 100644 (file)
@@ -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 (file)
index 0000000..97e3846
--- /dev/null
@@ -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 b4ab410..b67f8e4 100644 (file)
@@ -18,6 +18,10 @@ add_entrypoint_library(
     sigaddset
     sigemptyset
     sigprocmask
+
+    # stdlib.h entrypoints
+    _Exit
+    abort
 )
 
 add_entrypoint_library(
index 2272ef3..979efea 100644 (file)
@@ -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;
 }
index 0eff020..babfce4 100644 (file)
@@ -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,
   ];
index 0ff0a6a..7f8ef92 100644 (file)
@@ -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 (file)
index 0000000..52beeb1
--- /dev/null
@@ -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 (file)
index 0000000..4ac5dd8
--- /dev/null
@@ -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 (file)
index 0000000..777e3fd
--- /dev/null
@@ -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 (file)
index 0000000..4bf347b
--- /dev/null
@@ -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 (file)
index 0000000..854d45f
--- /dev/null
@@ -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 (file)
index 0000000..1c5f60a
--- /dev/null
@@ -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 bc698a6..bf56591 100644 (file)
@@ -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 (file)
index 0000000..6588d45
--- /dev/null
@@ -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 (file)
index 0000000..49878bf
--- /dev/null
@@ -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 (file)
index 0000000..cefb5d8
--- /dev/null
@@ -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);
+}