| //===-- Shared/APIHelpers.h - helpers for external APIs --*- C++ -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // The header contains helper functions to make interactions with external APIs | |
| // such as CUDA or level zero easier | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_APIHELPERS_H | |
| #define OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_APIHELPERS_H | |
| #include "DLWrap.h" | |
| #define API_HELPER_STRINGIFY_INNER(x) #x | |
| #define API_HELPER_STRINGIFY(x) API_HELPER_STRINGIFY_INNER(x) | |
| // Macro to mark external symbol as weak, so linker will be okay | |
| // if the symbol is missing. For direct linking only available on Linux, we need | |
| // to check if linker could find the symbol. For symbols loaded using dlsym we | |
| // call name##_loaded function. The name##_loaded function will be nullptr if | |
| // external library was linked directly. | |
| // _Pragma("weak name") retroactively downgrades any prior strong declaration | |
| // (e.g. from a vendor header included before this macro) to weak. | |
| #define API_HELPER_OPTIONAL(return_type, name, ...) \ | |
| _Pragma(API_HELPER_STRINGIFY(weak name)) namespace dlwrap { \ | |
| bool name##_loaded() __attribute__((weak)); \ | |
| } \ | |
| extern "C" return_type name(__VA_ARGS__) __attribute__((weak)); \ | |
| template <> inline bool api_helper::canCall<name>() { \ | |
| if (name == nullptr) \ | |
| /* Not loaded weak symbol, only possible on Linux */ \ | |
| return false; \ | |
| /* If symbol wasn't dlwrapped, i.e name##_loaded == nullptr and is not \ | |
| * nullptr, it means the symbol was linked directly, so we can call it */ \ | |
| if (dlwrap::name##_loaded == nullptr) \ | |
| return true; \ | |
| /* Symbol is not nullptr and it was dlwrapped, all symbols on Windows go \ | |
| * here*/ \ | |
| return dlwrap::name##_loaded(); \ | |
| } | |
| namespace api_helper { | |
| // Default template specialization for extra safety | |
| template <auto Fn> bool canCall() { | |
| static_assert(sizeof(decltype(Fn) *) == 0, | |
| "api_helper::canCall() should only be called on symbols " | |
| "decorated with API_HELPER_OPTIONAL!"); | |
| } | |
| } // namespace api_helper | |
| #endif // OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_APIHELPERS_H |