Skip to content

Commit b836ae2

Browse files
committed
[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
1 parent 9244be7 commit b836ae2

File tree

9 files changed

+241
-63
lines changed

9 files changed

+241
-63
lines changed

libc/cmake/modules/LLVMLibCObjectRules.cmake

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ function(add_entrypoint_object target_name)
8181
)
8282

8383
get_fq_target_name(${target_name} fq_target_name)
84+
set(entrypoint_name ${target_name})
85+
if(ADD_ENTRYPOINT_OBJ_NAME)
86+
set(entrypoint_name ${ADD_ENTRYPOINT_OBJ_NAME})
87+
endif()
8488

8589
if(ADD_ENTRYPOINT_OBJ_ALIAS)
8690
# Alias targets help one add aliases to other entrypoint object targets.
@@ -109,6 +113,7 @@ function(add_entrypoint_object target_name)
109113
set_target_properties(
110114
${fq_target_name}
111115
PROPERTIES
116+
"ENTRYPOINT_NAME" ${entrypoint_name}
112117
"TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE}
113118
"IS_ALIAS" "YES"
114119
"OBJECT_FILE" ""
@@ -125,11 +130,6 @@ function(add_entrypoint_object target_name)
125130
message(FATAL_ERROR "`add_entrypoint_object` rule requires HDRS to be specified.")
126131
endif()
127132

128-
set(entrypoint_name ${target_name})
129-
if(ADD_ENTRYPOINT_OBJ_NAME)
130-
set(entrypoint_name ${ADD_ENTRYPOINT_OBJ_NAME})
131-
endif()
132-
133133
set(objects_target_name "${fq_target_name}_objects")
134134

135135
add_library(
@@ -199,6 +199,7 @@ function(add_entrypoint_object target_name)
199199
set_target_properties(
200200
${fq_target_name}
201201
PROPERTIES
202+
"ENTRYPOINT_NAME" ${entrypoint_name}
202203
"TARGET_TYPE" ${ENTRYPOINT_OBJ_TARGET_TYPE}
203204
"OBJECT_FILE" "${object_file}"
204205
"OBJECT_FILE_RAW" "${object_file_raw}"
@@ -255,7 +256,7 @@ function(add_entrypoint_object target_name)
255256
# crossplatform touch.
256257
COMMAND "${CMAKE_COMMAND}" -E touch ${lint_timestamp}
257258
COMMENT "Linting... ${target_name}"
258-
DEPENDS ${clang-tidy} ${objects_target_name} ${ADD_ENTRYPOINT_OBJ_SRCS}
259+
DEPENDS clang-tidy ${objects_target_name} ${ADD_ENTRYPOINT_OBJ_SRCS}
259260
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
260261
)
261262

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
set(LIBC_ENTRYPOINTS
2+
# assert.h entrypoints
3+
libc.src.assert.__assert_fail
4+
5+
# errno.h entrypoints
6+
libc.src.errno.__errno_location
7+
8+
# signal.h entrypoints
9+
libc.src.signal.raise
10+
libc.src.signal.sigaction
11+
libc.src.signal.sigdelset
12+
libc.src.signal.sigaddset
13+
libc.src.signal.sigemptyset
14+
libc.src.signal.sigprocmask
15+
libc.src.signal.sigfillset
16+
libc.src.signal.signal
17+
18+
# stdlib.h entrypoints
19+
libc.src.stdlib._Exit
20+
libc.src.stdlib.abort
21+
22+
# string.h entrypoints
23+
libc.src.string.memcpy
24+
libc.src.string.strcpy
25+
libc.src.string.strcat
26+
libc.src.string.strlen
27+
28+
# sys/mman.h entrypoints
29+
libc.src.sys.mman.mmap
30+
libc.src.sys.mman.munmap
31+
32+
# threads.h entrypoints
33+
libc.src.threads.mtx_init
34+
libc.src.threads.mtx_lock
35+
libc.src.threads.mtx_unlock
36+
libc.src.threads.thrd_create
37+
libc.src.threads.thrd_join
38+
39+
# unistd.h entrypoints
40+
libc.src.unistd.write
41+
)
42+
43+
set(LIBM_ENTRYPOINTS
44+
# math.h entrypoints
45+
libc.src.math.cosf
46+
libc.src.math.round
47+
libc.src.math.sincosf
48+
libc.src.math.sinf
49+
)

libc/config/linux/x86_64/headers.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
set(PUBLIC_HEADERS
2+
libc.include.assert_h
3+
libc.include.errno
4+
libc.include.math
5+
libc.include.signal
6+
libc.include.stdio
7+
libc.include.stdlib
8+
libc.include.sys_mman
9+
libc.include.sys_syscall
10+
libc.include.threads
11+
libc.include.unistd
12+
)

libc/lib/CMakeLists.txt

Lines changed: 4 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,16 @@
1+
include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/entrypoints.txt")
2+
include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/headers.txt")
13

24
add_entrypoint_library(
35
llvmlibc
46
DEPENDS
5-
# assert.h entrypoints
6-
libc.src.assert.__assert_fail
7-
8-
# errno.h entrypoints
9-
libc.src.errno.__errno_location
10-
11-
# signal.h entrypoints
12-
libc.src.signal.raise
13-
libc.src.signal.sigaction
14-
libc.src.signal.sigdelset
15-
libc.src.signal.sigaddset
16-
libc.src.signal.sigemptyset
17-
libc.src.signal.sigprocmask
18-
libc.src.signal.sigfillset
19-
libc.src.signal.signal
20-
21-
# stdlib.h entrypoints
22-
libc.src.stdlib._Exit
23-
libc.src.stdlib.abort
24-
25-
# string.h entrypoints
26-
libc.src.string.bzero
27-
libc.src.string.memcpy
28-
libc.src.string.memset
29-
libc.src.string.strcat
30-
libc.src.string.strcpy
31-
libc.src.string.strlen
32-
33-
# sys/mman.h entrypoints
34-
libc.src.sys.mman.mmap
35-
libc.src.sys.mman.munmap
36-
37-
# threads.h entrypoints
38-
libc.src.threads.call_once
39-
libc.src.threads.mtx_init
40-
libc.src.threads.mtx_lock
41-
libc.src.threads.mtx_unlock
42-
libc.src.threads.thrd_create
43-
libc.src.threads.thrd_join
44-
45-
# unistd.h entrypoints
46-
libc.src.unistd.write
7+
${LIBC_ENTRYPOINTS}
478
)
489

4910
add_entrypoint_library(
5011
llvmlibm
5112
DEPENDS
52-
# math.h entrypoints
53-
libc.src.math.ceil
54-
libc.src.math.ceilf
55-
libc.src.math.cosf
56-
libc.src.math.fabs
57-
libc.src.math.fabsf
58-
libc.src.math.floor
59-
libc.src.math.floorf
60-
libc.src.math.expf
61-
libc.src.math.exp2f
62-
libc.src.math.round
63-
libc.src.math.sincosf
64-
libc.src.math.sinf
65-
libc.src.math.trunc
66-
libc.src.math.truncf
13+
${LIBM_ENTRYPOINTS}
6714
)
6815

6916
add_redirector_library(

libc/test/src/CMakeLists.txt

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,91 @@ add_subdirectory(string)
88
add_subdirectory(sys)
99
add_subdirectory(threads)
1010
add_subdirectory(unistd)
11+
12+
include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/entrypoints.txt")
13+
include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_MACHINE}/headers.txt")
14+
15+
set(public_test ${CMAKE_CURRENT_BINARY_DIR}/public_integration_test.cpp)
16+
17+
set(entrypoints_name_list "")
18+
foreach(entry IN LISTS LIBC_ENTRYPOINTS LIBM_ENTRYPOINTS)
19+
get_target_property(entry_name ${entry} "ENTRYPOINT_NAME")
20+
list(APPEND entrypoints_name_list ${entry_name})
21+
endforeach()
22+
23+
# TODO: Remove these when they are added to the TableGen.
24+
list(REMOVE_ITEM entrypoints_name_list "__assert_fail" "__errno_location")
25+
list(TRANSFORM entrypoints_name_list PREPEND "-e=")
26+
27+
# Generate integration test souce code.
28+
add_custom_command(
29+
OUTPUT ${public_test}
30+
COMMAND $<TARGET_FILE:libc-prototype-testgen> -o ${public_test}
31+
${entrypoints_name_list}
32+
-I ${LIBC_SOURCE_DIR}
33+
${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td
34+
35+
DEPENDS ${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/api.td
36+
libc-prototype-testgen ${PUBLIC_HEADERS}
37+
llvmlibc llvmlibm
38+
)
39+
40+
add_executable(
41+
public_integration_test
42+
EXCLUDE_FROM_ALL
43+
${public_test}
44+
)
45+
# Blank out default include directories to prevent accidentally including
46+
# system headers or our own internal headers.
47+
set_target_properties(
48+
public_integration_test
49+
PROPERTIES
50+
INCLUDE_DIRECTORIES ""
51+
)
52+
# Only include we need is the include for cpp::IsSame and our generated
53+
# public headers.
54+
target_include_directories(
55+
public_integration_test BEFORE
56+
PRIVATE
57+
"${LIBC_SOURCE_DIR}/utils/CPP"
58+
"${LIBC_BUILD_DIR}/include"
59+
)
60+
target_compile_options(
61+
public_integration_test
62+
PRIVATE
63+
-ffreestanding
64+
)
65+
target_link_options(
66+
public_integration_test
67+
PRIVATE "-nostdlib"
68+
)
69+
set(library_files)
70+
foreach(library_name IN LISTS "llvmlibc;llvmlibm")
71+
get_target_property(library_file ${library_name} "LIBRARY_FILE")
72+
list(APPEND library_files ${library_file})
73+
endforeach()
74+
75+
if(COMPILER_RESOURCE_DIR AND LLVM_LIBC_ENABLE_LINTING)
76+
add_custom_target(
77+
public_integration_test-tidy
78+
VERBATIM
79+
COMMAND $<TARGET_FILE:clang-tidy> --system-headers
80+
--checks=-*,llvmlibc-restrict-system-libc-headers
81+
"--extra-arg=-resource-dir=${COMPILER_RESOURCE_DIR}"
82+
--header-filter=.*
83+
--warnings-as-errors=llvmlibc-*
84+
"-config={CheckOptions: [{key: llvmlibc-restrict-system-libc-headers.Includes, value: '-*, linux/*, asm/*.h, asm-generic/*.h'}]}"
85+
--quiet
86+
-p ${PROJECT_BINARY_DIR}
87+
${public_test}
88+
DEPENDS
89+
clang-tidy ${public_test}
90+
)
91+
add_dependencies(check-libc public_integration_test-tidy)
92+
endif()
93+
94+
target_link_libraries(public_integration_test
95+
PRIVATE
96+
${library_files}
97+
)
98+
add_dependencies(check-libc public_integration_test)

libc/utils/HdrGen/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ add_tablegen(libc-hdrgen llvm-libc
1111
PublicAPICommand.cpp
1212
PublicAPICommand.h
1313
)
14+
15+
add_subdirectory(PrototypeTestGen)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CheckOptions:
2+
- key: readability-identifier-naming.VariableCase
3+
value: camelBack
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
add_tablegen(libc-prototype-testgen llvm-libc
2+
PrototypeTestGen.cpp
3+
../PublicAPICommand.cpp
4+
../Command.cpp
5+
)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===-- PrototypeTestGen.cpp ----------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "../PublicAPICommand.h"
10+
11+
#include "llvm/ADT/StringRef.h"
12+
#include "llvm/Support/CommandLine.h"
13+
#include "llvm/TableGen/Main.h"
14+
#include "llvm/TableGen/Record.h"
15+
16+
namespace {
17+
18+
llvm::cl::list<std::string>
19+
EntrypointNamesOption("e", llvm::cl::desc("<list of entrypoints>"),
20+
llvm::cl::OneOrMore);
21+
22+
} // anonymous namespace
23+
24+
bool TestGeneratorMain(llvm::raw_ostream &OS, llvm::RecordKeeper &records) {
25+
OS << "#include \"TypeTraits.h\"\n";
26+
llvm_libc::APIIndexer G(records);
27+
for (const auto &header : G.PublicHeaders)
28+
OS << "#include <" << header << ">\n";
29+
OS << '\n';
30+
OS << "int main() {\n";
31+
for (const auto &entrypoint : EntrypointNamesOption) {
32+
auto match = G.FunctionSpecMap.find(entrypoint);
33+
if (match == G.FunctionSpecMap.end()) {
34+
llvm::errs() << "ERROR: entrypoint '" << entrypoint
35+
<< "' could not be found in spec in any public header\n";
36+
return true;
37+
}
38+
llvm::Record *functionSpec = match->second;
39+
llvm::Record *retValSpec = functionSpec->getValueAsDef("Return");
40+
std::string returnType =
41+
G.getTypeAsString(retValSpec->getValueAsDef("ReturnType"));
42+
// _Noreturn is an indication for the compiler that a function
43+
// doesn't return, and isn't a type understood by c++ templates.
44+
if (llvm::StringRef(returnType).contains("_Noreturn"))
45+
returnType = "void";
46+
47+
OS << " static_assert(__llvm_libc::cpp::IsSame<" << returnType << '(';
48+
auto args = functionSpec->getValueAsListOfDefs("Args");
49+
for (size_t i = 0, size = args.size(); i < size; ++i) {
50+
llvm::Record *argType = args[i]->getValueAsDef("ArgType");
51+
OS << G.getTypeAsString(argType);
52+
if (i < size - 1)
53+
OS << ", ";
54+
}
55+
OS << "), decltype(" << entrypoint << ")>::Value, ";
56+
OS << '"' << entrypoint
57+
<< " prototype in TableGen does not match public header" << '"';
58+
OS << ");\n";
59+
}
60+
61+
OS << '\n';
62+
OS << " return 0;\n";
63+
OS << "}\n\n";
64+
65+
return false;
66+
}
67+
68+
int main(int argc, char *argv[]) {
69+
llvm::cl::ParseCommandLineOptions(argc, argv);
70+
return TableGenMain(argv[0], TestGeneratorMain);
71+
}

0 commit comments

Comments
 (0)