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/spec/stdc.td 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 `__llvm_libc` 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`__llvm_libc::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 `__llvm_libc::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 unit test to: 92``` 93 libc/test/src/math/<func>_test.cpp 94``` 95- Add the corresponding entry point to: 96``` 97 libc/test/src/math/CMakeLists.txt 98``` 99 100### Exhaustive tests 101 102Exhaustive tests are long-running tests that are not included when you run 103`ninja check-libc`. These exhaustive tests are added and manually run in 104order to find exceptional cases for your function's implementation. 105 106- Add an exhaustive test to: 107``` 108 libc/test/src/math/exhaustive/<func>_test.cpp 109``` 110- Add the corresponding entry point to: 111``` 112 libc/test/src/math/exhaustive/CMakeLists.txt 113``` 114- The template class `LlvmLibcExhaustiveTest` located at: 115``` 116 libc/test/src/math/exhaustive/exhaustive_test.h 117``` 118can be inherited for conveniently parallelizing the exhaustive tests. 119 120### Performance tests 121 122Performance tests compare your function's implementation with the system libc 123implementation (which is very often glibc). 124 125- Add a performance test to: 126``` 127 libc/test/src/math/differential_testing/<func>_perf.cpp 128``` 129- Add the corresponding entry point to: 130``` 131 libc/test/src/math/differential_testing/CMakeLists.txt 132``` 133 134## Build and Run 135 136- Check out the LLVM source tree: 137``` 138 $ git clone https://github.com/llvm/llvm-project.git 139``` 140 141- Setup projects with CMake: 142``` 143 $ cd llvm-project 144 $ mkdir build 145 $ cd build 146 $ cmake ../llvm -G Ninja \ 147 -DLLVM_ENABLE_PROJECTS="llvm;libc" \ 148 -DCMAKE_BUILD_TYPE=Debug \ 149 -DCMAKE_C_COMPILER=clang \ 150 -DCMAKE_CXX_COMPILER=clang++ 151``` 152 153- Build the whole `libc`: 154``` 155 $ ninja llvmlibc 156``` 157 158- Run all unit tests: 159``` 160 $ ninja check-libc 161``` 162 163- Build and Run a specific unit test: 164``` 165 $ ninja libc.test.src.math.<func>_test 166 $ projects/libc/test/src/math/libc.test.src.math.<func>_test 167``` 168 169- Build and Run exhaustive test (might take hours to run): 170``` 171 $ ninja libc.test.src.math.exhaustive.<func>_test 172 $ projects/libc/test/src/math/exhaustive/libc.test.src.math.exhaustive.<func>_test 173``` 174 175- Build and Run performance test: 176``` 177 $ ninja libc.test.src.math.differential_testing.<func>_perf 178 $ projects/libc/test/src/math/differential_testing/libc.test.src.math.differential_testing.<func>_perf 179 $ cat <func>_perf.log 180``` 181 182## Code reviews 183 184We follow the code review process of LLVM with Phabricator: 185``` 186 https://llvm.org/docs/Phabricator.html 187``` 188