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 115### Performance tests 116 117Performance tests compare your function's implementation with the system libc 118implementation (which is very often glibc). 119 120- Add a performance test to: 121``` 122 libc/test/src/math/differential_testing/<func>_perf.cpp 123``` 124- Add the corresponding entry point to: 125``` 126 libc/test/src/math/differential_testing/CMakeLists.txt 127``` 128 129## Build and Run 130 131- Check out the LLVM source tree: 132``` 133 $ git clone https://github.com/llvm/llvm-project.git 134``` 135 136- Setup projects with CMake: 137``` 138 $ cd llvm-project 139 $ mkdir build 140 $ cd build 141 $ cmake ../llvm -G Ninja \ 142 -DLLVM_ENABLE_PROJECTS="llvm;libc" \ 143 -DCMAKE_BUILD_TYPE=Debug \ 144 -DCMAKE_C_COMPILER=clang \ 145 -DCMAKE_CXX_COMPILER=clang++ 146``` 147 148- Build the whole `libc`: 149``` 150 $ ninja llvmlibc 151``` 152 153- Run all unit tests: 154``` 155 $ ninja check-libc 156``` 157 158- Build and Run a specific unit test: 159``` 160 $ ninja libc.test.src.math.<func>_test 161 $ projects/libc/test/src/math/libc.test.src.math.<func>_test 162``` 163 164- Build and Run exhaustive test (might take hours to run): 165``` 166 $ ninja libc.test.src.math.exhaustive.<func>_test 167``` 168 169- Build and Run performance test: 170``` 171 $ ninja libc.test.src.math.differential_testing.<func>_perf 172 $ projects/libc/test/src/math/differential_testing/libc.test.src.math.differential_testing.<func>_perf 173 $ cat <func>_perf.log 174``` 175 176## Code reviews 177 178We follow the code review process of LLVM with Phabricator: 179``` 180 https://llvm.org/docs/Phabricator.html 181``` 182