|  | 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. | 
|  |  | 
|  | Implementaion 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`` atttributes. |