src/third_party/llvm-libc/src/docs/dev/implementation_standard.rst
.. _implementation_standard:
The implementations of LLVM-libc entrypoints live in the src/ directory,
organized by the public header they belong to. Some entrypoints are platform-
specific, and so their implementations are in a subdirectory with the name of
the platform (e.g., stdio/linux/remove.cpp).
For a complete overview of what an entrypoint is and how it is managed in the
build system, see the :ref:entrypoints documentation.
Implementation of entrypoints can span multiple .cpp and .h files, but
there will be at least one header file with name of the form
<entrypoint name>.h for every entrypoint. This header file is called the
implementation header file. For the isalpha function, the path to the
implementation header file is src/ctype/isalpha.h.
We will use the isalpha function from the public ctype.h header file as an
example. The isalpha function will be declared in an internal header file
src/ctype/isalpha.h as follows::
// --- isalpha.h --- //
#ifndef LLVM_LIBC_SRC_CTYPE_ISALPHA_H
#define LLVM_LIBC_SRC_CTYPE_ISALPHA_H
namespace LIBC_NAMESPACE_DECL {
int isalpha(int c);
} // namespace LIBC_NAMESPACE_DECL
#endif LLVM_LIBC_SRC_CTYPE_ISALPHA_H
All LLVM-libc implementation constructs must be enclosed in the
LIBC_NAMESPACE_DECL namespace. See :ref:code_style for the full technical
rationale and macro definitions.
.cpp File StructureThe main .cpp file is named <entrypoint name>.cpp and is usually in the
same folder as the header. It contains the signature of the entrypoint function,
which must be defined with the LLVM_LIBC_FUNCTION macro. For example, the
isalpha function from ctype.h is defined as follows, in the file
src/ctype/isalpha.cpp::
// --- isalpha.cpp --- //
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, isalpha, (int c)) {
// ... implementation goes here.
}
} // namespace LIBC_NAMESPACE_DECL
Notice the use of the macro LLVM_LIBC_FUNCTION. This macro helps us define
a C alias symbol for the C++ implementation. For example, for a library build,
the macro is defined as follows::
#define LLVM_LIBC_FUNCTION(type, name, arglist)
LLVM_LIBC_FUNCTION_IMPL(type, name, arglist)
#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist)
LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name)
__##name##_impl__ __asm__(#name);
decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]];
type __##name##_impl__ arglist
The LLVM_LIBC_FUNCTION_ATTR macro is normally defined to nothing, but can be defined by vendors who want to set their own attributes.