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