mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-17 16:31:02 +00:00
[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
This commit is contained in:
parent
9244be7b05
commit
b836ae24a9
@ -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}
|
||||
)
|
||||
|
||||
|
49
libc/config/linux/x86_64/entrypoints.txt
Normal file
49
libc/config/linux/x86_64/entrypoints.txt
Normal file
@ -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
|
||||
)
|
12
libc/config/linux/x86_64/headers.txt
Normal file
12
libc/config/linux/x86_64/headers.txt
Normal file
@ -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
|
||||
)
|
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -11,3 +11,5 @@ add_tablegen(libc-hdrgen llvm-libc
|
||||
PublicAPICommand.cpp
|
||||
PublicAPICommand.h
|
||||
)
|
||||
|
||||
add_subdirectory(PrototypeTestGen)
|
||||
|
3
libc/utils/HdrGen/PrototypeTestGen/.clang-tidy
Normal file
3
libc/utils/HdrGen/PrototypeTestGen/.clang-tidy
Normal file
@ -0,0 +1,3 @@
|
||||
CheckOptions:
|
||||
- key: readability-identifier-naming.VariableCase
|
||||
value: camelBack
|
5
libc/utils/HdrGen/PrototypeTestGen/CMakeLists.txt
Normal file
5
libc/utils/HdrGen/PrototypeTestGen/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
add_tablegen(libc-prototype-testgen llvm-libc
|
||||
PrototypeTestGen.cpp
|
||||
../PublicAPICommand.cpp
|
||||
../Command.cpp
|
||||
)
|
71
libc/utils/HdrGen/PrototypeTestGen/PrototypeTestGen.cpp
Normal file
71
libc/utils/HdrGen/PrototypeTestGen/PrototypeTestGen.cpp
Normal file
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user