1Convention for implementing entrypoints 2======================================= 3 4LLVM-libc entrypoints are defined in the entrypoints document. In this document, 5we explain how the entrypoints are implemented. The source layout document 6explains that, within the high level ``src`` directory, there exists one 7directory for every public header file provided by LLVM-libc. The 8implementations of related group of entrypoints will also live in a directory of 9their own. This directory will have a name indicative of the related group of 10entrypoints, and will be under the directory corresponding to the header file of 11the entrypoints. For example, functions like ``fopen`` and ``fclose`` cannot be 12tested independent of each other and hence will live in a directory named 13``src/stdio/file_operations``. On the other hand, the implementation of the 14``round`` function from ``math.h`` can be tested by itself, so it will live in 15the directory of its own named ``src/math/round/``. 16 17Implementation of entrypoints can span multiple ``.cpp`` and ``.h`` files, but 18there will be atleast one header file with name of the form 19``<entrypoint name>.h`` for every entrypoint. This header file is called as the 20implementation header file. For the ``round`` function, the path to the 21implementation header file will be ``src/math/round/round.h``. The rest of this 22document explains the structure of implementation header files and ``.cpp`` 23files. 24 25Implementation Header File Structure 26------------------------------------ 27 28We will use the ``round`` function from the public ``math.h`` header file as an 29example. The ``round`` function will be declared in an internal header file 30``src/math/round/round.h`` as follows:: 31 32 // --- round.h --- // 33 #ifndef LLVM_LIBC_SRC_MATH_ROUND_ROUND_H 34 #define LLVM_LIBC_SRC_MATH_ROUND_ROUND_H 35 36 namespace __llvm_libc { 37 38 double round(double); 39 40 } // namespace __llvm_libc 41 42 #endif LLVM_LIBC_SRC_MATH_ROUND_ROUND_H 43 44Notice that the ``round`` function declaration is nested inside the namespace 45``__llvm_libc``. All implementation constructs in LLVM-libc are declared within 46the namespace ``__llvm_libc``. 47 48``.cpp`` File Structure 49----------------------- 50 51The implementation can span multiple ``.cpp`` files. However, the signature of 52the entrypoint function should make use of a special macro. For example, the 53``round`` function from ``math.h`` should be defined as follows, say in the file 54``src/math/math/round.cpp``:: 55 56 // --- round.cpp --- // 57 58 namespace __llvm_libc { 59 60 double LLVM_LIBC_ENTRYPOINT(round)(double d) { 61 // ... implementation goes here. 62 } 63 64 } // namespace __llvm_libc 65 66Notice the use of the macro ``LLVM_LIBC_ENTRYPOINT``. This macro helps us define 67an C alias symbol for the C++ implementation. The C alias need not be added by 68the macro by itself. For example, for ELF targets, the macro is defined as 69follows:: 70 71 #define ENTRYPOINT_SECTION_ATTRIBUTE(name) \ 72 __attribute__((section(".llvm.libc.entrypoint."#name))) 73 #define LLVM_LIBC_ENTRYPOINT(name) ENTRYPOINT_SECTION_ATTRIBUTE(name) name 74 75The macro places the C++ function in a unique section with name 76``.llvm.libc.entrypoint.<function name>``. This allows us to add a C alias using 77a post build step. For example, for the ``round`` function, one can use 78``objcopy`` to add an alias symbol as follows:: 79 80 objcopy --add-symbol round=.llvm.libc.entrypoint.round:0,function round.o 81 82NOTE: We use a post build ``objcopy`` step to add an alias instead of using 83the ``__attribute__((alias))``. For C++, this ``alias`` attribute requires 84mangled names of the referees. Using the post build ``objcopy`` step helps 85us avoid putting mangled names with ``alias`` attributes. 86