[libc-commits] [libc] b836ae2 - [libc] Add integration tests.

Paula Toth via libc-commits libc-commits at lists.llvm.org
Tue Jun 2 12:19:57 PDT 2020


Author: Paula Toth
Date: 2020-06-02T12:14:07-07:00
New Revision: b836ae24a9f4202a73a227bc3dac9b1a40979a7d

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

LOG: [libc] Add integration tests.

Summary:
This patch aims to add integration tests to check the following:
1) Header files are generated as expected.
2) Libc functions have the correct public name.
3) Libc functions have the correct return type and parameter types.
4) Symbols are exposed in the public lib.a files.

Reviewers: sivachandra, abrachet

Reviewed By: sivachandra

Subscribers: aheejin, ecnelises, dxf, mgorny, jfb, tschuett, libc-commits

Tags: #libc-project

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

Added: 
    libc/config/linux/x86_64/entrypoints.txt
    libc/config/linux/x86_64/headers.txt
    libc/utils/HdrGen/PrototypeTestGen/.clang-tidy
    libc/utils/HdrGen/PrototypeTestGen/CMakeLists.txt
    libc/utils/HdrGen/PrototypeTestGen/PrototypeTestGen.cpp

Modified: 
    libc/cmake/modules/LLVMLibCObjectRules.cmake
    libc/lib/CMakeLists.txt
    libc/test/src/CMakeLists.txt
    libc/utils/HdrGen/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/cmake/modules/LLVMLibCObjectRules.cmake b/libc/cmake/modules/LLVMLibCObjectRules.cmake
index 898831ca6818..d1d098d3dc38 100644
--- a/libc/cmake/modules/LLVMLibCObjectRules.cmake
+++ b/libc/cmake/modules/LLVMLibCObjectRules.cmake
@@ -81,6 +81,10 @@ function(add_entrypoint_object target_name)
   )
 
   get_fq_target_name(${target_name} fq_target_name)
+  set(entrypoint_name ${target_name})
+  if(ADD_ENTRYPOINT_OBJ_NAME)
+    set(entrypoint_name ${ADD_ENTRYPOINT_OBJ_NAME})
+  endif()
 
   if(ADD_ENTRYPOINT_OBJ_ALIAS)
     # Alias targets help one add aliases to other entrypoint object targets.
@@ -109,6 +113,7 @@ function(add_entrypoint_object target_name)
     set_target_properties(
       ${fq_target_name}
       PROPERTIES
+        "ENTRYPOINT_NAME" ${entrypoint_name}
         "TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE}
         "IS_ALIAS" "YES"
         "OBJECT_FILE" ""
@@ -125,11 +130,6 @@ function(add_entrypoint_object target_name)
     message(FATAL_ERROR "`add_entrypoint_object` rule requires HDRS to be specified.")
   endif()
 
-  set(entrypoint_name ${target_name})
-  if(ADD_ENTRYPOINT_OBJ_NAME)
-    set(entrypoint_name ${ADD_ENTRYPOINT_OBJ_NAME})
-  endif()
-
   set(objects_target_name "${fq_target_name}_objects")
 
   add_library(
@@ -199,6 +199,7 @@ function(add_entrypoint_object target_name)
   set_target_properties(
     ${fq_target_name}
     PROPERTIES
+      "ENTRYPOINT_NAME" ${entrypoint_name}
       "TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE}
       "OBJECT_FILE" "${object_file}"
       "OBJECT_FILE_RAW" "${object_file_raw}"
@@ -255,7 +256,7 @@ function(add_entrypoint_object target_name)
       # crossplatform touch.
       COMMAND "${CMAKE_COMMAND}" -E touch ${lint_timestamp}
       COMMENT "Linting... ${target_name}"
-      DEPENDS ${clang-tidy} ${objects_target_name} ${ADD_ENTRYPOINT_OBJ_SRCS}
+      DEPENDS clang-tidy ${objects_target_name} ${ADD_ENTRYPOINT_OBJ_SRCS}
       WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
     )
 

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
new file mode 100644
index 000000000000..2f79d7f256f8
--- /dev/null
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -0,0 +1,49 @@
+set(LIBC_ENTRYPOINTS
+    # assert.h entrypoints
+    libc.src.assert.__assert_fail
+
+    # errno.h entrypoints
+    libc.src.errno.__errno_location
+
+    # signal.h entrypoints
+    libc.src.signal.raise
+    libc.src.signal.sigaction
+    libc.src.signal.sigdelset
+    libc.src.signal.sigaddset
+    libc.src.signal.sigemptyset
+    libc.src.signal.sigprocmask
+    libc.src.signal.sigfillset
+    libc.src.signal.signal
+
+    # stdlib.h entrypoints
+    libc.src.stdlib._Exit
+    libc.src.stdlib.abort
+
+    # string.h entrypoints
+    libc.src.string.memcpy
+    libc.src.string.strcpy
+    libc.src.string.strcat
+    libc.src.string.strlen
+
+    # sys/mman.h entrypoints
+    libc.src.sys.mman.mmap
+    libc.src.sys.mman.munmap
+
+    # threads.h entrypoints
+    libc.src.threads.mtx_init
+    libc.src.threads.mtx_lock
+    libc.src.threads.mtx_unlock
+    libc.src.threads.thrd_create
+    libc.src.threads.thrd_join
+
+    # unistd.h entrypoints
+    libc.src.unistd.write
+)
+
+set(LIBM_ENTRYPOINTS
+    # math.h entrypoints
+    libc.src.math.cosf
+    libc.src.math.round
+    libc.src.math.sincosf
+    libc.src.math.sinf
+)
\ No newline at end of file

diff  --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt
new file mode 100644
index 000000000000..8c7d71eb4601
--- /dev/null
+++ b/libc/config/linux/x86_64/headers.txt
@@ -0,0 +1,12 @@
+set(PUBLIC_HEADERS
+    libc.include.assert_h
+    libc.include.errno
+    libc.include.math
+    libc.include.signal
+    libc.include.stdio
+    libc.include.stdlib
+    libc.include.sys_mman
+    libc.include.sys_syscall
+    libc.include.threads
+    libc.include.unistd
+)

diff  --git a/libc/lib/CMakeLists.txt b/libc/lib/CMakeLists.txt
index e0921d93d410..deae56e874ec 100644
--- a/libc/lib/CMakeLists.txt
+++ b/libc/lib/CMakeLists.txt
@@ -1,69 +1,16 @@
+include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/entrypoints.txt")
+include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/headers.txt")
 
 add_entrypoint_library(
   llvmlibc
   DEPENDS
-    # assert.h entrypoints
-    libc.src.assert.__assert_fail
-
-    # errno.h entrypoints
-    libc.src.errno.__errno_location
-
-    # signal.h entrypoints
-    libc.src.signal.raise
-    libc.src.signal.sigaction
-    libc.src.signal.sigdelset
-    libc.src.signal.sigaddset
-    libc.src.signal.sigemptyset
-    libc.src.signal.sigprocmask
-    libc.src.signal.sigfillset
-    libc.src.signal.signal
-
-    # stdlib.h entrypoints
-    libc.src.stdlib._Exit
-    libc.src.stdlib.abort
-
-    # string.h entrypoints
-    libc.src.string.bzero
-    libc.src.string.memcpy
-    libc.src.string.memset
-    libc.src.string.strcat
-    libc.src.string.strcpy
-    libc.src.string.strlen
-
-    # sys/mman.h entrypoints
-    libc.src.sys.mman.mmap
-    libc.src.sys.mman.munmap
-
-    # threads.h entrypoints
-    libc.src.threads.call_once
-    libc.src.threads.mtx_init
-    libc.src.threads.mtx_lock
-    libc.src.threads.mtx_unlock
-    libc.src.threads.thrd_create
-    libc.src.threads.thrd_join
-
-    # unistd.h entrypoints
-    libc.src.unistd.write
+  ${LIBC_ENTRYPOINTS}
 )
 
 add_entrypoint_library(
   llvmlibm
   DEPENDS
-    # math.h entrypoints
-    libc.src.math.ceil
-    libc.src.math.ceilf
-    libc.src.math.cosf
-    libc.src.math.fabs
-    libc.src.math.fabsf
-    libc.src.math.floor
-    libc.src.math.floorf
-    libc.src.math.expf
-    libc.src.math.exp2f
-    libc.src.math.round
-    libc.src.math.sincosf
-    libc.src.math.sinf
-    libc.src.math.trunc
-    libc.src.math.truncf
+  ${LIBM_ENTRYPOINTS}
 )
 
 add_redirector_library(

diff  --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index d333108aa02b..561a1299af08 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -8,3 +8,91 @@ add_subdirectory(string)
 add_subdirectory(sys)
 add_subdirectory(threads)
 add_subdirectory(unistd)
+
+include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/entrypoints.txt")
+include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/headers.txt")
+
+set(public_test ${CMAKE_CURRENT_BINARY_DIR}/public_integration_test.cpp)
+
+set(entrypoints_name_list "")
+foreach(entry IN LISTS LIBC_ENTRYPOINTS LIBM_ENTRYPOINTS)
+  get_target_property(entry_name ${entry} "ENTRYPOINT_NAME")
+  list(APPEND entrypoints_name_list ${entry_name})
+endforeach()
+
+# TODO: Remove these when they are added to the TableGen.
+list(REMOVE_ITEM entrypoints_name_list "__assert_fail" "__errno_location")
+list(TRANSFORM entrypoints_name_list PREPEND "-e=")
+
+# Generate integration test souce code.
+add_custom_command(
+  OUTPUT ${public_test}
+  COMMAND $<TARGET_FILE:libc-prototype-testgen> -o ${public_test}
+          ${entrypoints_name_list}
+          -I ${LIBC_SOURCE_DIR}
+          ${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td
+
+  DEPENDS ${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td
+          libc-prototype-testgen ${PUBLIC_HEADERS}
+          llvmlibc llvmlibm
+)
+
+add_executable(
+  public_integration_test
+  EXCLUDE_FROM_ALL
+  ${public_test}
+)
+# Blank out default include directories to prevent accidentally including
+# system headers or our own internal headers.
+set_target_properties(
+  public_integration_test
+  PROPERTIES
+  INCLUDE_DIRECTORIES ""
+)
+# Only include we need is the include for cpp::IsSame and our generated
+# public headers.
+target_include_directories(
+  public_integration_test BEFORE
+  PRIVATE
+    "${LIBC_SOURCE_DIR}/utils/CPP"
+    "${LIBC_BUILD_DIR}/include"
+)
+target_compile_options(
+  public_integration_test
+  PRIVATE
+  -ffreestanding
+)
+target_link_options(
+  public_integration_test
+  PRIVATE "-nostdlib"
+)
+set(library_files)
+foreach(library_name IN LISTS "llvmlibc;llvmlibm")
+  get_target_property(library_file ${library_name} "LIBRARY_FILE")
+  list(APPEND library_files ${library_file})
+endforeach()
+
+if(COMPILER_RESOURCE_DIR AND LLVM_LIBC_ENABLE_LINTING)
+  add_custom_target(
+    public_integration_test-tidy
+    VERBATIM
+    COMMAND $<TARGET_FILE:clang-tidy> --system-headers
+      --checks=-*,llvmlibc-restrict-system-libc-headers
+      "--extra-arg=-resource-dir=${COMPILER_RESOURCE_DIR}"
+      --header-filter=.*
+      --warnings-as-errors=llvmlibc-*
+      "-config={CheckOptions: [{key: llvmlibc-restrict-system-libc-headers.Includes, value: '-*, linux/*, asm/*.h, asm-generic/*.h'}]}"
+      --quiet
+      -p ${PROJECT_BINARY_DIR}
+      ${public_test}
+    DEPENDS
+      clang-tidy ${public_test}
+  )
+  add_dependencies(check-libc public_integration_test-tidy)
+endif()
+
+target_link_libraries(public_integration_test
+  PRIVATE
+  ${library_files}
+)
+add_dependencies(check-libc public_integration_test)

diff  --git a/libc/utils/HdrGen/CMakeLists.txt b/libc/utils/HdrGen/CMakeLists.txt
index 65eaa8b7eb26..65c2d65c7918 100644
--- a/libc/utils/HdrGen/CMakeLists.txt
+++ b/libc/utils/HdrGen/CMakeLists.txt
@@ -11,3 +11,5 @@ add_tablegen(libc-hdrgen llvm-libc
   PublicAPICommand.cpp
   PublicAPICommand.h
 )
+
+add_subdirectory(PrototypeTestGen)

diff  --git a/libc/utils/HdrGen/PrototypeTestGen/.clang-tidy b/libc/utils/HdrGen/PrototypeTestGen/.clang-tidy
new file mode 100644
index 000000000000..d404f83828f7
--- /dev/null
+++ b/libc/utils/HdrGen/PrototypeTestGen/.clang-tidy
@@ -0,0 +1,3 @@
+CheckOptions:
+  - key:             readability-identifier-naming.VariableCase
+    value:           camelBack

diff  --git a/libc/utils/HdrGen/PrototypeTestGen/CMakeLists.txt b/libc/utils/HdrGen/PrototypeTestGen/CMakeLists.txt
new file mode 100644
index 000000000000..e4ad5c209cd9
--- /dev/null
+++ b/libc/utils/HdrGen/PrototypeTestGen/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_tablegen(libc-prototype-testgen llvm-libc
+  PrototypeTestGen.cpp
+  ../PublicAPICommand.cpp
+  ../Command.cpp
+)

diff  --git a/libc/utils/HdrGen/PrototypeTestGen/PrototypeTestGen.cpp b/libc/utils/HdrGen/PrototypeTestGen/PrototypeTestGen.cpp
new file mode 100644
index 000000000000..aad451a8de22
--- /dev/null
+++ b/libc/utils/HdrGen/PrototypeTestGen/PrototypeTestGen.cpp
@@ -0,0 +1,71 @@
+//===-- PrototypeTestGen.cpp ----------------------------------------------===//
+//
+// 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 "../PublicAPICommand.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/TableGen/Main.h"
+#include "llvm/TableGen/Record.h"
+
+namespace {
+
+llvm::cl::list<std::string>
+    EntrypointNamesOption("e", llvm::cl::desc("<list of entrypoints>"),
+                          llvm::cl::OneOrMore);
+
+} // anonymous namespace
+
+bool TestGeneratorMain(llvm::raw_ostream &OS, llvm::RecordKeeper &records) {
+  OS << "#include \"TypeTraits.h\"\n";
+  llvm_libc::APIIndexer G(records);
+  for (const auto &header : G.PublicHeaders)
+    OS << "#include <" << header << ">\n";
+  OS << '\n';
+  OS << "int main() {\n";
+  for (const auto &entrypoint : EntrypointNamesOption) {
+    auto match = G.FunctionSpecMap.find(entrypoint);
+    if (match == G.FunctionSpecMap.end()) {
+      llvm::errs() << "ERROR: entrypoint '" << entrypoint
+                   << "' could not be found in spec in any public header\n";
+      return true;
+    }
+    llvm::Record *functionSpec = match->second;
+    llvm::Record *retValSpec = functionSpec->getValueAsDef("Return");
+    std::string returnType =
+        G.getTypeAsString(retValSpec->getValueAsDef("ReturnType"));
+    // _Noreturn is an indication for the compiler that a function
+    // doesn't return, and isn't a type understood by c++ templates.
+    if (llvm::StringRef(returnType).contains("_Noreturn"))
+      returnType = "void";
+
+    OS << "  static_assert(__llvm_libc::cpp::IsSame<" << returnType << '(';
+    auto args = functionSpec->getValueAsListOfDefs("Args");
+    for (size_t i = 0, size = args.size(); i < size; ++i) {
+      llvm::Record *argType = args[i]->getValueAsDef("ArgType");
+      OS << G.getTypeAsString(argType);
+      if (i < size - 1)
+        OS << ", ";
+    }
+    OS << "), decltype(" << entrypoint << ")>::Value, ";
+    OS << '"' << entrypoint
+       << " prototype in TableGen does not match public header" << '"';
+    OS << ");\n";
+  }
+
+  OS << '\n';
+  OS << "  return 0;\n";
+  OS << "}\n\n";
+
+  return false;
+}
+
+int main(int argc, char *argv[]) {
+  llvm::cl::ParseCommandLineOptions(argc, argv);
+  return TableGenMain(argv[0], TestGeneratorMain);
+}


        


More information about the libc-commits mailing list