//===--- Visibility.h - Visibility macros for runtime exports ---*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  These macros are used to declare symbols that should be exported from the
//  Swift runtime.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_STDLIB_SHIMS_VISIBILITY_H
#define SWIFT_STDLIB_SHIMS_VISIBILITY_H

#if !defined(__has_feature)
#define __has_feature(x) 0
#endif

#if !defined(__has_attribute)
#define __has_attribute(x) 0
#endif

#if !defined(__has_builtin)
#define __has_builtin(builtin) 0
#endif

#if !defined(__has_cpp_attribute)
#define __has_cpp_attribute(attribute) 0
#endif

// TODO: These macro definitions are duplicated in BridgedSwiftObject.h. Move
// them to a single file if we find a location that both Visibility.h and
// BridgedSwiftObject.h can import.
#if __has_feature(nullability)
// Provide macros to temporarily suppress warning about the use of
// _Nullable and _Nonnull.
# define SWIFT_BEGIN_NULLABILITY_ANNOTATIONS                        \
  _Pragma("clang diagnostic push")                                  \
  _Pragma("clang diagnostic ignored \"-Wnullability-extension\"")
# define SWIFT_END_NULLABILITY_ANNOTATIONS                          \
  _Pragma("clang diagnostic pop")

#else
// #define _Nullable and _Nonnull to nothing if we're not being built
// with a compiler that supports them.
# define _Nullable
# define _Nonnull
# define SWIFT_BEGIN_NULLABILITY_ANNOTATIONS
# define SWIFT_END_NULLABILITY_ANNOTATIONS
#endif

#define SWIFT_MACRO_CONCAT(A, B) A ## B
#define SWIFT_MACRO_IF_0(IF_TRUE, IF_FALSE) IF_FALSE
#define SWIFT_MACRO_IF_1(IF_TRUE, IF_FALSE) IF_TRUE
#define SWIFT_MACRO_IF(COND, IF_TRUE, IF_FALSE) \
  SWIFT_MACRO_CONCAT(SWIFT_MACRO_IF_, COND)(IF_TRUE, IF_FALSE)

#if __has_attribute(pure)
#define SWIFT_READONLY __attribute__((__pure__))
#else
#define SWIFT_READONLY
#endif

#if __has_attribute(const)
#define SWIFT_READNONE __attribute__((__const__))
#else
#define SWIFT_READNONE
#endif

#if __has_attribute(always_inline)
#define SWIFT_ALWAYS_INLINE __attribute__((always_inline))
#else
#define SWIFT_ALWAYS_INLINE
#endif

#if __has_attribute(noinline)
#define SWIFT_NOINLINE __attribute__((__noinline__))
#else
#define SWIFT_NOINLINE
#endif

#if __has_attribute(noreturn)
#define SWIFT_NORETURN __attribute__((__noreturn__))
#else
#define SWIFT_NORETURN
#endif

#if __has_attribute(used)
#define SWIFT_USED __attribute__((__used__))
#else
#define SWIFT_USED
#endif

#if __has_attribute(unavailable)
#define SWIFT_ATTRIBUTE_UNAVAILABLE __attribute__((__unavailable__))
#else
#define SWIFT_ATTRIBUTE_UNAVAILABLE
#endif

#if (__has_attribute(weak_import))
#define SWIFT_WEAK_IMPORT __attribute__((weak_import))
#else
#define SWIFT_WEAK_IMPORT
#endif

#if __has_attribute(musttail)
#define SWIFT_MUSTTAIL [[clang::musttail]]
#else
#define SWIFT_MUSTTAIL
#endif

// Define the appropriate attributes for sharing symbols across
// image (executable / shared-library) boundaries.
//
// SWIFT_ATTRIBUTE_FOR_EXPORTS will be placed on declarations that
// are known to be exported from the current image.  Typically, they
// are placed on header declarations and then inherited by the actual
// definitions.
//
// SWIFT_ATTRIBUTE_FOR_IMPORTS will be placed on declarations that
// are known to be exported from a different image.  This never
// includes a definition.
//
// Getting the right attribute on a declaration can be pretty awkward,
// but it's necessary under the C translation model.  All of this
// ceremony is familiar to Windows programmers; C/C++ programmers
// everywhere else usually don't bother, but since we have to get it
// right for Windows, we have everything set up to get it right on
// other targets as well, and doing so lets the compiler use more
// efficient symbol access patterns.
#if defined(__MACH__) || defined(__wasm__)

// On Mach-O and WebAssembly, we use non-hidden visibility.  We just use
// default visibility on both imports and exports, both because these
// targets don't support protected visibility but because they don't
// need it: symbols are not interposable outside the current image
// by default.
# define SWIFT_ATTRIBUTE_FOR_EXPORTS __attribute__((__visibility__("default")))
# define SWIFT_ATTRIBUTE_FOR_IMPORTS __attribute__((__visibility__("default")))

#elif defined(__ELF__)

// On ELF, we use non-hidden visibility.  For exports, we must use
// protected visibility to tell the compiler and linker that the symbols
// can't be interposed outside the current image.  For imports, we must
// use default visibility because protected visibility guarantees that
// the symbol is defined in the current library, which isn't true for
// an import.
//
// The compiler does assume that the runtime and standard library can
// refer to each other's symbols as DSO-local, so it's important that
// we get this right or we can get linker errors.
# define SWIFT_ATTRIBUTE_FOR_EXPORTS __attribute__((__visibility__("protected")))
# define SWIFT_ATTRIBUTE_FOR_IMPORTS __attribute__((__visibility__("default")))

#elif defined(__CYGWIN__)

// For now, we ignore all this on Cygwin.
# define SWIFT_ATTRIBUTE_FOR_EXPORTS
# define SWIFT_ATTRIBUTE_FOR_IMPORTS

// FIXME: this #else should be some sort of #elif Windows
#else // !__MACH__ && !__ELF__

# if defined(SWIFT_STATIC_STDLIB)
#   define SWIFT_ATTRIBUTE_FOR_EXPORTS /**/
#   define SWIFT_ATTRIBUTE_FOR_IMPORTS /**/
# else
#   define SWIFT_ATTRIBUTE_FOR_EXPORTS __declspec(dllexport)
#   define SWIFT_ATTRIBUTE_FOR_IMPORTS __declspec(dllimport)
# endif

#endif

// CMake conventionally passes -DlibraryName_EXPORTS when building
// code that goes into libraryName.  This isn't the best macro name,
// but it's conventional.  We do have to pass it explicitly in a few
// places in the build system for a variety of reasons.
//
// Unfortunately, defined(D) is a special function you can use in
// preprocessor conditions, not a macro you can use anywhere, so we
// need to manually check for all the libraries we know about so that
// we can use them in our condition below.s
#if defined(swiftCore_EXPORTS)
#define SWIFT_IMAGE_EXPORTS_swiftCore 1
#else
#define SWIFT_IMAGE_EXPORTS_swiftCore 0
#endif
#if defined(swift_Concurrency_EXPORTS)
#define SWIFT_IMAGE_EXPORTS_swift_Concurrency 1
#else
#define SWIFT_IMAGE_EXPORTS_swift_Concurrency 0
#endif
#if defined(swiftDistributed_EXPORTS)
#define SWIFT_IMAGE_EXPORTS_swiftDistributed 1
#else
#define SWIFT_IMAGE_EXPORTS_swiftDistributed 0
#endif
#if defined(swift_Differentiation_EXPORTS)
#define SWIFT_IMAGE_EXPORTS_swift_Differentiation 1
#else
#define SWIFT_IMAGE_EXPORTS_swift_Differentiation 0
#endif

#define SWIFT_EXPORT_FROM_ATTRIBUTE(LIBRARY)                          \
  SWIFT_MACRO_IF(SWIFT_IMAGE_EXPORTS_##LIBRARY,                       \
                 SWIFT_ATTRIBUTE_FOR_EXPORTS,                         \
                 SWIFT_ATTRIBUTE_FOR_IMPORTS)

// SWIFT_EXPORT_FROM(LIBRARY) declares something to be a C-linkage
// entity exported by the given library.
//
// SWIFT_RUNTIME_EXPORT is just SWIFT_EXPORT_FROM(swiftCore).
//
// TODO: use this in shims headers in overlays.
#if defined(__cplusplus)
#define SWIFT_EXPORT_FROM(LIBRARY) extern "C" SWIFT_EXPORT_FROM_ATTRIBUTE(LIBRARY)
#define SWIFT_EXTERN_C extern "C" 
#else
#define SWIFT_EXPORT_FROM(LIBRARY) SWIFT_EXPORT_FROM_ATTRIBUTE(LIBRARY)
#define SWIFT_EXTERN_C
#endif
#define SWIFT_RUNTIME_EXPORT SWIFT_EXPORT_FROM(swiftCore)
#define SWIFT_RUNTIME_EXPORT_ATTRIBUTE SWIFT_EXPORT_FROM_ATTRIBUTE(swiftCore)

#if __cplusplus > 201402l && __has_cpp_attribute(fallthrough)
#define SWIFT_FALLTHROUGH [[fallthrough]]
#elif __has_cpp_attribute(gnu::fallthrough)
#define SWIFT_FALLTHROUGH [[gnu::fallthrough]]
#elif __has_cpp_attribute(clang::fallthrough)
#define SWIFT_FALLTHROUGH [[clang::fallthrough]]
#elif __has_attribute(fallthrough)
#define SWIFT_FALLTHROUGH __attribute__((__fallthrough__))
#else
#define SWIFT_FALLTHROUGH
#endif

#if __cplusplus > 201402l && __has_cpp_attribute(nodiscard)
#define SWIFT_NODISCARD [[nodiscard]]
#elif __has_cpp_attribute(clang::warn_unused_result)
#define SWIFT_NODISCARD [[clang::warn_unused_result]]
#else
#define SWIFT_NODISCARD
#endif

#if __has_cpp_attribute(gnu::returns_nonnull)
#define SWIFT_RETURNS_NONNULL [[gnu::returns_nonnull]]
#elif defined(_MSC_VER) && defined(_Ret_notnull_)
#define SWIFT_RETURNS_NONNULL _Ret_notnull_
#else
#define SWIFT_RETURNS_NONNULL
#endif

/// Attributes for runtime-stdlib interfaces.
/// Use these for C implementations that are imported into Swift via SwiftShims
/// and for C implementations of Swift @_silgen_name declarations
/// Note that @_silgen_name implementations must also be marked SWIFT_CC(swift).
///
/// SWIFT_RUNTIME_STDLIB_API functions are called by compiler-generated code
/// or by @inlinable Swift code.
/// Such functions must be exported and must be supported forever as API.
/// The function name should be prefixed with `swift_`.
///
/// SWIFT_RUNTIME_STDLIB_SPI functions are called by overlay code.
/// Such functions must be exported, but are still SPI
/// and may be changed at any time.
/// The function name should be prefixed with `_swift_`.
///
/// SWIFT_RUNTIME_STDLIB_INTERNAL functions are called only by the stdlib.
/// Such functions are internal and are not exported.
#define SWIFT_RUNTIME_STDLIB_API       SWIFT_RUNTIME_EXPORT
#define SWIFT_RUNTIME_STDLIB_SPI       SWIFT_RUNTIME_EXPORT

// Match the definition of LLVM_LIBRARY_VISIBILITY from LLVM's
// Compiler.h. That header requires C++ and this needs to work in C.
#if __has_attribute(visibility) && (defined(__ELF__) || defined(__MACH__))
#define SWIFT_LIBRARY_VISIBILITY __attribute__ ((__visibility__("hidden")))
#else
#define SWIFT_LIBRARY_VISIBILITY
#endif

#if defined(__cplusplus)
#define SWIFT_RUNTIME_STDLIB_INTERNAL extern "C" SWIFT_LIBRARY_VISIBILITY
#else
#define SWIFT_RUNTIME_STDLIB_INTERNAL SWIFT_LIBRARY_VISIBILITY
#endif

#if __has_builtin(__builtin_expect)
#define SWIFT_LIKELY(expression) (__builtin_expect(!!(expression), 1))
#define SWIFT_UNLIKELY(expression) (__builtin_expect(!!(expression), 0))
#else
#define SWIFT_LIKELY(expression) ((expression))
#define SWIFT_UNLIKELY(expression) ((expression))
#endif

// SWIFT_STDLIB_SHIMS_VISIBILITY_H
#endif
