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``` 21*62cd050bSRoland McGrath libc/include/math.yaml 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``` 33b6bc9d72SGuillaume Chatelet- Add function declaration (under `LIBC_NAMESPACE` 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 59b6bc9d72SGuillaume Chatelet`LIBC_NAMESPACE::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 74b6bc9d72SGuillaume Chatelet- Add the function enum to `LIBC_NAMESPACE::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 9184c899b2STue Ly- Add smoke tests (simple cases and zeros / inf / nan inputs or outputs) to: 9284c899b2STue Ly``` 9384c899b2STue Ly libc/test/src/math/smoke/<func>_test.cpp 9484c899b2STue Ly``` 9584c899b2STue Ly- Add unit test that might require MPFR to: 96a2b3e6beSTue Ly``` 979369aa14STue Ly libc/test/src/math/<func>_test.cpp 98a2b3e6beSTue Ly``` 9984c899b2STue Ly- Add the corresponding entry points to: 100a2b3e6beSTue Ly``` 10184c899b2STue Ly libc/test/src/math/smoke/CMakeLists.txt 102a2b3e6beSTue Ly libc/test/src/math/CMakeLists.txt 103a2b3e6beSTue Ly``` 104a2b3e6beSTue Ly 105a2b3e6beSTue Ly### Exhaustive tests 106a2b3e6beSTue Ly 107a2b3e6beSTue LyExhaustive tests are long-running tests that are not included when you run 108a2b3e6beSTue Ly`ninja check-libc`. These exhaustive tests are added and manually run in 109a2b3e6beSTue Lyorder to find exceptional cases for your function's implementation. 110a2b3e6beSTue Ly 111a2b3e6beSTue Ly- Add an exhaustive test to: 112a2b3e6beSTue Ly``` 1139369aa14STue Ly libc/test/src/math/exhaustive/<func>_test.cpp 114a2b3e6beSTue Ly``` 115a2b3e6beSTue Ly- Add the corresponding entry point to: 116a2b3e6beSTue Ly``` 117a2b3e6beSTue Ly libc/test/src/math/exhaustive/CMakeLists.txt 118a2b3e6beSTue Ly``` 1199532074aSTue Ly- The template class `LlvmLibcExhaustiveMathTest` located at: 120e11e973eSTue Ly``` 121e11e973eSTue Ly libc/test/src/math/exhaustive/exhaustive_test.h 122e11e973eSTue Ly``` 1239532074aSTue Lycan be used for conveniently parallelizing the exhaustive tests. 124a2b3e6beSTue Ly 125a2b3e6beSTue Ly### Performance tests 126a2b3e6beSTue Ly 127a2b3e6beSTue LyPerformance tests compare your function's implementation with the system libc 128a2b3e6beSTue Lyimplementation (which is very often glibc). 129a2b3e6beSTue Ly 130a2b3e6beSTue Ly- Add a performance test to: 131a2b3e6beSTue Ly``` 132d99bb014Slntue libc/test/src/math/performance_testing/<func>_perf.cpp 133a2b3e6beSTue Ly``` 134a2b3e6beSTue Ly- Add the corresponding entry point to: 135a2b3e6beSTue Ly``` 136d99bb014Slntue libc/test/src/math/performance_testing/CMakeLists.txt 137a2b3e6beSTue Ly``` 138a2b3e6beSTue Ly 139a2b3e6beSTue Ly## Build and Run 140a2b3e6beSTue Ly 141a2b3e6beSTue Ly- Check out the LLVM source tree: 142a2b3e6beSTue Ly``` 143a2b3e6beSTue Ly $ git clone https://github.com/llvm/llvm-project.git 144a2b3e6beSTue Ly``` 145a2b3e6beSTue Ly 146a2b3e6beSTue Ly- Setup projects with CMake: 147a2b3e6beSTue Ly``` 148a2b3e6beSTue Ly $ cd llvm-project 149a2b3e6beSTue Ly $ mkdir build 150a2b3e6beSTue Ly $ cd build 151a2b3e6beSTue Ly $ cmake ../llvm -G Ninja \ 152a2b3e6beSTue Ly -DLLVM_ENABLE_PROJECTS="llvm;libc" \ 153a2b3e6beSTue Ly -DCMAKE_BUILD_TYPE=Debug \ 154a2b3e6beSTue Ly -DCMAKE_C_COMPILER=clang \ 155a2b3e6beSTue Ly -DCMAKE_CXX_COMPILER=clang++ 156a2b3e6beSTue Ly``` 157a2b3e6beSTue Ly 158a2b3e6beSTue Ly- Build the whole `libc`: 159a2b3e6beSTue Ly``` 160a48c4a45STue Ly $ ninja libc 161a2b3e6beSTue Ly``` 162a2b3e6beSTue Ly 163a2b3e6beSTue Ly- Run all unit tests: 164a2b3e6beSTue Ly``` 165a2b3e6beSTue Ly $ ninja check-libc 166a2b3e6beSTue Ly``` 167a2b3e6beSTue Ly 16884c899b2STue Ly- Run math smoke tests only: 16984c899b2STue Ly``` 17084c899b2STue Ly $ ninja libc-math-smoke-tests 17184c899b2STue Ly``` 17284c899b2STue Ly 17384c899b2STue Ly- Run math smoke and unit tests: 17484c899b2STue Ly``` 17584c899b2STue Ly $ ninja libc-math-unittests 17684c899b2STue Ly``` 17784c899b2STue Ly 178a2b3e6beSTue Ly- Build and Run a specific unit test: 179a2b3e6beSTue Ly``` 180721f1495SJob Henandez Lara $ ninja libc.test.src.math.<func>_test.__unit__ 181a2b3e6beSTue Ly $ projects/libc/test/src/math/libc.test.src.math.<func>_test 182a2b3e6beSTue Ly``` 183a2b3e6beSTue Ly 184a2b3e6beSTue Ly- Build and Run exhaustive test (might take hours to run): 185a2b3e6beSTue Ly``` 186a2b3e6beSTue Ly $ ninja libc.test.src.math.exhaustive.<func>_test 187e11e973eSTue Ly $ projects/libc/test/src/math/exhaustive/libc.test.src.math.exhaustive.<func>_test 188a2b3e6beSTue Ly``` 189a2b3e6beSTue Ly 190a2b3e6beSTue Ly- Build and Run performance test: 191a2b3e6beSTue Ly``` 192d99bb014Slntue $ ninja libc.test.src.math.performance_testing.<func>_perf 193d99bb014Slntue $ projects/libc/test/src/math/performance_testing/libc.test.src.math.performance_testing.<func>_perf 194a2b3e6beSTue Ly $ cat <func>_perf.log 195a2b3e6beSTue Ly``` 196a2b3e6beSTue Ly 197a2b3e6beSTue Ly## Code reviews 198a2b3e6beSTue Ly 199d3455f4dSCyuriaWe use GitHub's inbuilt pull request system for code review: 200a2b3e6beSTue Ly``` 201d3455f4dSCyuria https://docs.github.com/articles/about-collaborative-development-models 202d3455f4dSCyuria https://docs.github.com/articles/about-pull-requests 203a2b3e6beSTue Ly``` 204