Path: blob/main/contrib/llvm-project/libc/src/__support/common.h
213766 views
//===-- Common internal contructs -------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIBC_SRC___SUPPORT_COMMON_H9#define LLVM_LIBC_SRC___SUPPORT_COMMON_H1011#ifndef LIBC_NAMESPACE12#error "LIBC_NAMESPACE macro is not defined."13#endif1415#include "src/__support/macros/attributes.h"16#include "src/__support/macros/config.h"17#include "src/__support/macros/properties/architectures.h"1819#ifndef LLVM_LIBC_FUNCTION_ATTR20#define LLVM_LIBC_FUNCTION_ATTR21#endif2223// clang-format off24// Allow each function `func` to have extra attributes specified by defining:25// `LLVM_LIBC_FUNCTION_ATTR_func` macro, which should always start with26// "LLVM_LIBC_EMPTY, "27//28// For examples:29// #define LLVM_LIBC_FUNCTION_ATTR_memcpy LLVM_LIBC_EMPTY, [[gnu::weak]]30// #define LLVM_LIBC_FUNCTION_ATTR_memchr LLVM_LIBC_EMPTY, [[gnu::weak]] [[gnu::visibility("default")]]31// clang-format on32#define LLVM_LIBC_EMPTY3334#define GET_SECOND(first, second, ...) second35#define EXPAND_THEN_SECOND(name) GET_SECOND(name, LLVM_LIBC_EMPTY)3637#define LLVM_LIBC_ATTR(name) EXPAND_THEN_SECOND(LLVM_LIBC_FUNCTION_ATTR_##name)3839// At the moment, [[gnu::alias()]] is not supported on MacOS, and it is needed40// to cleanly export and alias the C++ symbol `LIBC_NAMESPACE::func` with the C41// symbol `func`. So for public packaging on MacOS, we will only export the C42// symbol. Moreover, a C symbol `func` in macOS is mangled as `_func`.43#if defined(LIBC_COPT_PUBLIC_PACKAGING)44#ifndef __APPLE__45#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \46LLVM_LIBC_ATTR(name) \47LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \48__##name##_impl__ __asm__(#name); \49decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \50type __##name##_impl__ arglist51#else // __APPLE__52#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \53LLVM_LIBC_ATTR(name) \54LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) name asm("_" #name); \55type name arglist56#endif // __APPLE__57#else // LIBC_COPT_PUBLIC_PACKAGING58#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) type name arglist59#endif // LIBC_COPT_PUBLIC_PACKAGING6061// This extra layer of macro allows `name` to be a macro to rename a function.62#define LLVM_LIBC_FUNCTION(type, name, arglist) \63LLVM_LIBC_FUNCTION_IMPL(type, name, arglist)6465namespace LIBC_NAMESPACE_DECL {66namespace internal {67LIBC_INLINE constexpr bool same_string(char const *lhs, char const *rhs) {68for (; *lhs || *rhs; ++lhs, ++rhs)69if (*lhs != *rhs)70return false;71return true;72}73} // namespace internal74} // namespace LIBC_NAMESPACE_DECL7576#define __LIBC_MACRO_TO_STRING(str) #str77#define LIBC_MACRO_TO_STRING(str) __LIBC_MACRO_TO_STRING(str)7879// LLVM_LIBC_IS_DEFINED checks whether a particular macro is defined.80// Usage: constexpr bool kUseAvx = LLVM_LIBC_IS_DEFINED(__AVX__);81//82// This works by comparing the stringified version of the macro with and without83// evaluation. If FOO is not undefined both stringifications yield "FOO". If FOO84// is defined, one stringification yields "FOO" while the other yields its85// stringified value "1".86#define LLVM_LIBC_IS_DEFINED(macro) \87!LIBC_NAMESPACE::internal::same_string( \88LLVM_LIBC_IS_DEFINED__EVAL_AND_STRINGIZE(macro), #macro)89#define LLVM_LIBC_IS_DEFINED__EVAL_AND_STRINGIZE(s) #s9091#endif // LLVM_LIBC_SRC___SUPPORT_COMMON_H929394