| Convention for implementing entrypoints |
| ======================================= |
| |
| LLVM-libc entrypoints are defined in the entrypoints document. In this document, |
| we explain how the entrypoints are implemented. The source layout document |
| explains that, within the high level ``src`` directory, there exists one |
| directory for every public header file provided by LLVM-libc. The |
| implementations of related group of entrypoints will also live in a directory of |
| their own. This directory will have a name indicative of the related group of |
| entrypoints, and will be under the directory corresponding to the header file of |
| the entrypoints. For example, functions like ``fopen`` and ``fclose`` cannot be |
| tested independent of each other and hence will live in a directory named |
| ``src/stdio/file_operations``. On the other hand, the implementation of the |
| ``round`` function from ``math.h`` can be tested by itself, so it will live in |
| the directory of its own named ``src/math/round/``. |
| |
| Implementation of entrypoints can span multiple ``.cpp`` and ``.h`` files, but |
| there will be atleast one header file with name of the form |
| ``<entrypoint name>.h`` for every entrypoint. This header file is called as the |
| implementation header file. For the ``round`` function, the path to the |
| implementation header file will be ``src/math/round/round.h``. The rest of this |
| document explains the structure of implementation header files and ``.cpp`` |
| files. |
| |
| Implementation Header File Structure |
| ------------------------------------ |
| |
| We will use the ``round`` function from the public ``math.h`` header file as an |
| example. The ``round`` function will be declared in an internal header file |
| ``src/math/round/round.h`` as follows:: |
| |
| // --- round.h --- // |
| #ifndef LLVM_LIBC_SRC_MATH_ROUND_ROUND_H |
| #define LLVM_LIBC_SRC_MATH_ROUND_ROUND_H |
| |
| namespace __llvm_libc { |
| |
| double round(double); |
| |
| } // namespace __llvm_libc |
| |
| #endif LLVM_LIBC_SRC_MATH_ROUND_ROUND_H |
| |
| Notice that the ``round`` function declaration is nested inside the namespace |
| ``__llvm_libc``. All implementation constructs in LLVM-libc are declared within |
| the namespace ``__llvm_libc``. |
| |
| ``.cpp`` File Structure |
| ----------------------- |
| |
| The implementation can span multiple ``.cpp`` files. However, the signature of |
| the entrypoint function should make use of a special macro. For example, the |
| ``round`` function from ``math.h`` should be defined as follows, say in the file |
| ``src/math/math/round.cpp``:: |
| |
| // --- round.cpp --- // |
| |
| namespace __llvm_libc { |
| |
| double LLVM_LIBC_ENTRYPOINT(round)(double d) { |
| // ... implementation goes here. |
| } |
| |
| } // namespace __llvm_libc |
| |
| Notice the use of the macro ``LLVM_LIBC_ENTRYPOINT``. This macro helps us define |
| an C alias symbol for the C++ implementation. The C alias need not be added by |
| the macro by itself. For example, for ELF targets, the macro is defined as |
| follows:: |
| |
| #define ENTRYPOINT_SECTION_ATTRIBUTE(name) \ |
| __attribute__((section(".llvm.libc.entrypoint."#name))) |
| #define LLVM_LIBC_ENTRYPOINT(name) ENTRYPOINT_SECTION_ATTRIBUTE(name) name |
| |
| The macro places the C++ function in a unique section with name |
| ``.llvm.libc.entrypoint.<function name>``. This allows us to add a C alias using |
| a post build step. For example, for the ``round`` function, one can use |
| ``objcopy`` to add an alias symbol as follows:: |
| |
| objcopy --add-symbol round=.llvm.libc.entrypoint.round:0,function round.o |
| |
| NOTE: We use a post build ``objcopy`` step to add an alias instead of using |
| the ``__attribute__((alias))``. For C++, this ``alias`` attribute requires |
| mangled names of the referees. Using the post build ``objcopy`` step helps |
| us avoid putting mangled names with ``alias`` attributes. |