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