This document is to serve as a cookbook for adding a new math function implementation to LLVM libc. To add a new function, apart from the actual implementation, one has to follow a few other steps to setup proper registration and shipping of the new function. Each of these steps will be described in detail below.
To register the function's entry points for supported OSes and architectures, together with its specifications:
libc.src.math.func to the following files:libc/config/linux/<arch>/entrypoints.txt libc/config/windows/entrypoints.txt
libc/spec/stdc.td
The function's actual implementation and its corresponding header should be added to the following locations:
add_math_entrypoint_object(<func>) to:libc/src/math/CMakeLists.txt
LIBC_NAMESPACE namespace) to:libc/src/math/<func>.h
libc/src/math/generic/<func>.cpp
add_entrypoint_object to:libc/src/math/generic/CMakeLists.txt
libc/src/math/<arch>/<func>.cpp
libc/src/__support/FPUtils
LIBC_NAMESPACE::fputil::FPBits<> in the header file:libc/src/__support/FPUtils/FPBits.h
In addition to the normal testing macros such as EXPECT_EQ, ASSERT_THAT, ... there are two special macros ASSERT_MPFR_MATCH and EXPECT_MPFR_MATCH to compare your outputs with the corresponding MPFR function. In order for your new function to be supported by these two macros, the following files will need to be updated:
LIBC_NAMESPACE::testing::mpfr::Operation in the header file:libc/utils/MPFRWrapper/MPFRUtils.h
func in the MPFRNumber class and the corresponding link between the enum and its call to the file:libc/utils/MPFRWrapper/MPFRUtils.cpp
Besides the usual testing macros like EXPECT_EQ, ASSERT_TRUE, ... there are testing macros specifically used for floating point values, such as EXPECT_FP_EQ, ASSERT_FP_LE, ...
libc/test/src/math/smoke/<func>_test.cpp
libc/test/src/math/<func>_test.cpp
libc/test/src/math/smoke/CMakeLists.txt libc/test/src/math/CMakeLists.txt
Exhaustive tests are long-running tests that are not included when you run ninja check-libc. These exhaustive tests are added and manually run in order to find exceptional cases for your function's implementation.
libc/test/src/math/exhaustive/<func>_test.cpp
libc/test/src/math/exhaustive/CMakeLists.txt
LlvmLibcExhaustiveMathTest located at:libc/test/src/math/exhaustive/exhaustive_test.h
can be used for conveniently parallelizing the exhaustive tests.
Performance tests compare your function's implementation with the system libc implementation (which is very often glibc).
libc/test/src/math/performance_testing/<func>_perf.cpp
libc/test/src/math/performance_testing/CMakeLists.txt
$ git clone https://github.com/llvm/llvm-project.git
$ cd llvm-project $ mkdir build $ cd build $ cmake ../llvm -G Ninja \ -DLLVM_ENABLE_PROJECTS="llvm;libc" \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++
libc:$ ninja libc
$ ninja check-libc
$ ninja libc-math-smoke-tests
$ ninja libc-math-unittests
$ ninja libc.test.src.math.<func>_test.__unit__ $ projects/libc/test/src/math/libc.test.src.math.<func>_test
$ ninja libc.test.src.math.exhaustive.<func>_test $ projects/libc/test/src/math/exhaustive/libc.test.src.math.exhaustive.<func>_test
$ ninja libc.test.src.math.performance_testing.<func>_perf $ projects/libc/test/src/math/performance_testing/libc.test.src.math.performance_testing.<func>_perf $ cat <func>_perf.log
We follow the code review process of LLVM with Phabricator:
https://llvm.org/docs/Phabricator.html