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/include/math.yaml
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 use GitHub's inbuilt pull request system for code review:
https://docs.github.com/articles/about-collaborative-development-models https://docs.github.com/articles/about-pull-requests