(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.
When defining a variable, use the LLVM_LIBC_VARIABLE macro:
LLVM_LIBC_VARIABLE(char **, environ) = nullptr;