| .. _code_style: |
| |
| =================== |
| The libc code style |
| =================== |
| |
| Naming style |
| ============ |
| |
| For the large part, the libc project follows the general `coding standards of |
| the LLVM project <https://llvm.org/docs/CodingStandards.html>`_. The libc |
| project differs from that standard with respect to the naming style. The |
| differences are as follows: |
| |
| #. **Non-const variables** - This includes function arguments, struct and |
| class data members, non-const globals and local variables. They all use the |
| ``snake_case`` style. |
| #. **const and constexpr variables** - They use the capitalized |
| ``SNAKE_CASE`` irrespective of whether they are local or global. |
| #. **Function and methods** - They use the ``snake_case`` style like the |
| non-const variables. |
| #. **Internal type names** - These are types which are internal to the libc |
| implementation. They use the ``CaptilizedCamelCase`` style. |
| #. **Public names** - These are the names as prescribed by the standards and |
| will follow the style as prescribed by the standards. |
| |
| Macro style |
| =========== |
| |
| We define two kinds of macros: **code defined** and **build defined** macros. |
| |
| #. **Build defined** macros are generated by `CMake` or `Bazel` and are passed |
| down to the compiler with the ``-D`` command line flag. They start with the |
| ``LIBC_COPT_`` prefix. They are used to tune the behavior of the libc. |
| They either denote an action or define a constant. |
| |
| #. **Code defined** macros are defined within the ``src/__support/macros`` |
| folder. They all start with the ``LIBC_`` prefix. They are of two kinds |
| |
| * **Properties** - Build related properties like used compiler, target |
| architecture or enabled CPU features defined by introspecting compiler |
| defined preprocessor definitions. e.g., ``LIBC_TARGET_ARCH_IS_ARM``, |
| ``LIBC_TARGET_CPU_HAS_AVX2``, ``LIBC_COMPILER_IS_CLANG``, ... |
| * **Attributes** - Compiler agnostic attributes or functions to handle |
| specific operations. e.g., ``LIBC_INLINE``, ``LIBC_NO_LOOP_UNROLL``, |
| ``LIBC_LIKELY``, ``LIBC_INLINE_ASM``. |
| |
| Inline functions defined in header files |
| ======================================== |
| |
| When defining functions inline in header files, we follow certain rules: |
| |
| #. The functions should not be given file-static linkage. There can be class |
| static methods defined inline however. |
| #. Instead of using the ``inline`` keyword, they should be tagged with the |
| ``LIBC_INLINE`` macro defined in ``src/__support/common.h``. For example: |
| |
| .. code-block:: c++ |
| |
| LIBC_INLINE ReturnType function_defined_inline(ArgType arg) { |
| ... |
| } |
| |
| #. The ``LIBC_INLINE`` tag should also be added to functions which have |
| definitions that are implicitly inline. Examples of such functions are |
| class methods (static and non-static) defined inline and ``constexpr`` |
| functions. |
| |
| Setting ``errno`` from runtime code |
| =================================== |
| |
| Many libc functions set ``errno`` to indicate an error condition. If LLVM's libc |
| is being used as the only libc, then the ``errno`` from LLVM's libc is affected. |
| If LLVM's libc is being used in the :ref:`overlay_mode`, then the ``errno`` from |
| the system libc is affected. When a libc function, which can potentially affect |
| the ``errno``, is called from a unit test, we do not want the global ``errno`` |
| (as in, the ``errno`` of the process thread running the unit test) to be |
| affected. If the global ``errno`` is affected, then the operation of the unit |
| test infrastructure itself can be affected. To avoid perturbing the unit test |
| infrastructure around the setting of ``errno``, the following rules are to be |
| followed: |
| |
| #. A special macro named ``libc_errno`` defined in ``src/errno/libc_errno.h`` |
| should be used when setting ``errno`` from libc runtime code. For example, |
| code to set ``errno`` to ``EINVAL`` should be: |
| |
| .. code-block:: c++ |
| |
| libc_errno = EINVAL; |
| |
| #. ``errno`` should be set just before returning from the implementation of the |
| public function. It should not be set from within helper functions. Helper |
| functions should use idiomatic C++ constructs like |
| `cpp::optional <https://github.com/llvm/llvm-project/blob/main/libc/src/__support/CPP/optional.h>`_ |
| and |
| `ErrorOr <https://github.com/llvm/llvm-project/blob/main/libc/src/__support/error_or.h>`_ |
| to return error values. |
| |
| #. The header file ``src/errno/libc_errno.h`` is shipped as part of the target |
| corresponding to the ``errno`` entrypoint ``libc.src.errno.errno``. We do |
| not in general allow dependencies between entrypoints. However, the ``errno`` |
| entrypoint is the only exceptional entrypoint on which other entrypoints |
| should explicitly depend on if they set ``errno`` to indicate error |
| conditions. |
| |
| Assertions in libc runtime code |
| =============================== |
| |
| The libc developers should, and are encouraged to, use assertions freely in |
| the libc runtime code. However, the assertion should be listed via the macro |
| ``LIBC_ASSERT`` defined in ``src/__support/libc_assert.h``. This macro can be |
| used from anywhere in the libc runtime code. Internally, all it does is to |
| print the assertion expression and exit. It does not implement the semantics |
| of the standard ``assert`` macro. Hence, it can be used from any where in the |
| libc runtime code without causing any recursive calls or chicken-and-egg |
| situations. |
| |
| Allocations in the libc runtime code |
| ==================================== |
| |
| Some libc functions allocate memory. For example, the ``strdup`` function |
| allocates new memory into which the input string is duplicated. Allocations |
| are typically done by calling a function from the ``malloc`` family of |
| functions. Such functions can fail and return an error value to indicate |
| allocation failure. To conform to standards, the libc should handle |
| allocation failures gracefully and surface the error conditions to the user |
| code as appropriate. Since LLVM's libc is implemented in C++, we want |
| allocations and deallocations to employ C++ operators ``new`` and ``delete`` |
| as they implicitly invoke constructors and destructors respectively. However, |
| if we use the default ``new`` and ``delete`` operators, the libc will end up |
| depending on the C++ runtime. To avoid such a dependence, and to handle |
| allocation failures gracefully, we use special ``new`` and ``delete`` operators |
| defined in |
| `src/__support/CPP/new.h <https://github.com/llvm/llvm-project/blob/main/libc/src/__support/CPP/new.h>`_. |
| Allocations and deallocations using these operators employ a pattern like |
| this: |
| |
| .. code-block:: c++ |
| |
| #include "src/__support/CPP/new.h" |
| |
| ... |
| |
| __llvm_libc::AllocChecker ac; |
| auto *obj = new (ac) Type(...); |
| if (!ac) { |
| // handle allocator failure. |
| } |
| ... |
| delete obj; |
| |
| The only exception to using the above pattern is if allocating using the |
| ``realloc`` function is of value. In such cases, prefer to use only the |
| ``malloc`` family of functions for allocations and deallocations. Allocation |
| failures will still need to be handled gracefully. Further, keep in mind that |
| these functions do not call the constructors and destructors of the |
| allocated/deallocated objects. So, use these functions carefully and only |
| when it is absolutely clear that constructor and destructor invocation is |
| not required. |