1# How to add a new math function to LLVM-libc 2 3This document is to serve as a cookbook for adding a new math function 4implementation to LLVM libc. To add a new function, apart from the actual 5implementation, one has to follow a few other steps to setup proper registration 6and shipping of the new function. Each of these steps will be described in 7detail below. 8 9## Registration 10 11To register the function's entry points for supported OSes and architectures, 12together with its specifications: 13 14- Add entry points `libc.src.math.func` to the following files: 15``` 16 libc/config/linux/<arch>/entrypoints.txt 17 libc/config/windows/entrypoints.txt 18``` 19- Add function specs to the file: 20``` 21 libc/include/math.yaml 22``` 23 24## Implementation 25 26The function's actual implementation and its corresponding header should be 27added to the following locations: 28 29- Add `add_math_entrypoint_object(<func>)` to: 30``` 31 libc/src/math/CMakeLists.txt 32``` 33- Add function declaration (under `LIBC_NAMESPACE` namespace) to: 34``` 35 libc/src/math/<func>.h 36``` 37- Add function definition to: 38``` 39 libc/src/math/generic/<func>.cpp 40``` 41- Add the corresponding `add_entrypoint_object` to: 42``` 43 libc/src/math/generic/CMakeLists.txt 44``` 45- Add architectural specific implementations to: 46``` 47 libc/src/math/<arch>/<func>.cpp 48``` 49 50### Floating point utility 51 52- Floating point utilities and math functions that are also used internally are 53located at: 54``` 55 libc/src/__support/FPUtils 56``` 57- These are preferred to be included as header-only. 58- To manipulate bits of floating point numbers, use the template class 59`LIBC_NAMESPACE::fputil::FPBits<>` in the header file: 60``` 61 libc/src/__support/FPUtils/FPBits.h 62``` 63 64## Testing 65 66### MPFR utility 67 68In addition to the normal testing macros such as `EXPECT_EQ, ASSERT_THAT, ...` 69there are two special macros `ASSERT_MPFR_MATCH` and `EXPECT_MPFR_MATCH` to 70compare your outputs with the corresponding MPFR function. In 71order for your new function to be supported by these two macros, 72the following files will need to be updated: 73 74- Add the function enum to `LIBC_NAMESPACE::testing::mpfr::Operation` in the 75header file: 76``` 77 libc/utils/MPFRWrapper/MPFRUtils.h 78``` 79- Add support for `func` in the `MPFRNumber` class and the corresponding link 80between the enum and its call to the file: 81``` 82 libc/utils/MPFRWrapper/MPFRUtils.cpp 83``` 84 85### Unit tests 86 87Besides the usual testing macros like `EXPECT_EQ, ASSERT_TRUE, ...` there are 88testing macros specifically used for floating point values, such as 89`EXPECT_FP_EQ, ASSERT_FP_LE, ...` 90 91- Add smoke tests (simple cases and zeros / inf / nan inputs or outputs) to: 92``` 93 libc/test/src/math/smoke/<func>_test.cpp 94``` 95- Add unit test that might require MPFR to: 96``` 97 libc/test/src/math/<func>_test.cpp 98``` 99- Add the corresponding entry points to: 100``` 101 libc/test/src/math/smoke/CMakeLists.txt 102 libc/test/src/math/CMakeLists.txt 103``` 104 105### Exhaustive tests 106 107Exhaustive tests are long-running tests that are not included when you run 108`ninja check-libc`. These exhaustive tests are added and manually run in 109order to find exceptional cases for your function's implementation. 110 111- Add an exhaustive test to: 112``` 113 libc/test/src/math/exhaustive/<func>_test.cpp 114``` 115- Add the corresponding entry point to: 116``` 117 libc/test/src/math/exhaustive/CMakeLists.txt 118``` 119- The template class `LlvmLibcExhaustiveMathTest` located at: 120``` 121 libc/test/src/math/exhaustive/exhaustive_test.h 122``` 123can be used for conveniently parallelizing the exhaustive tests. 124 125### Performance tests 126 127Performance tests compare your function's implementation with the system libc 128implementation (which is very often glibc). 129 130- Add a performance test to: 131``` 132 libc/test/src/math/performance_testing/<func>_perf.cpp 133``` 134- Add the corresponding entry point to: 135``` 136 libc/test/src/math/performance_testing/CMakeLists.txt 137``` 138 139## Build and Run 140 141- Check out the LLVM source tree: 142``` 143 $ git clone https://github.com/llvm/llvm-project.git 144``` 145 146- Setup projects with CMake: 147``` 148 $ cd llvm-project 149 $ mkdir build 150 $ cd build 151 $ cmake ../llvm -G Ninja \ 152 -DLLVM_ENABLE_PROJECTS="llvm;libc" \ 153 -DCMAKE_BUILD_TYPE=Debug \ 154 -DCMAKE_C_COMPILER=clang \ 155 -DCMAKE_CXX_COMPILER=clang++ 156``` 157 158- Build the whole `libc`: 159``` 160 $ ninja libc 161``` 162 163- Run all unit tests: 164``` 165 $ ninja check-libc 166``` 167 168- Run math smoke tests only: 169``` 170 $ ninja libc-math-smoke-tests 171``` 172 173- Run math smoke and unit tests: 174``` 175 $ ninja libc-math-unittests 176``` 177 178- Build and Run a specific unit test: 179``` 180 $ ninja libc.test.src.math.<func>_test.__unit__ 181 $ projects/libc/test/src/math/libc.test.src.math.<func>_test 182``` 183 184- Build and Run exhaustive test (might take hours to run): 185``` 186 $ ninja libc.test.src.math.exhaustive.<func>_test 187 $ projects/libc/test/src/math/exhaustive/libc.test.src.math.exhaustive.<func>_test 188``` 189 190- Build and Run performance test: 191``` 192 $ ninja libc.test.src.math.performance_testing.<func>_perf 193 $ projects/libc/test/src/math/performance_testing/libc.test.src.math.performance_testing.<func>_perf 194 $ cat <func>_perf.log 195``` 196 197## Code reviews 198 199We use GitHub's inbuilt pull request system for code review: 200``` 201 https://docs.github.com/articles/about-collaborative-development-models 202 https://docs.github.com/articles/about-pull-requests 203``` 204