diff --git a/libsycl/CMakeLists.txt b/libsycl/CMakeLists.txt index fe08a4249bada..54ef3d4b1878a 100644 --- a/libsycl/CMakeLists.txt +++ b/libsycl/CMakeLists.txt @@ -37,8 +37,6 @@ option(LIBSYCL_ENABLE_PEDANTIC "Compile with pedantic enabled." OFF) set_property(GLOBAL PROPERTY USE_FOLDERS ON) -set(LIBSYCL_SHARED_OUTPUT_NAME "sycl" CACHE STRING "Output name for the shared libsycl runtime library.") - if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) set(LIBSYCL_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE}) if(LIBSYCL_LIBDIR_SUBDIR) @@ -65,7 +63,7 @@ set(LIBSYCL_SOURCE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBSYCL_LIBRARY_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBSYCL_LIBRARY_DIR}) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBSYCL_LIBRARY_DIR}) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_TOOLS_BINARY_DIR}) set(LIBSYCL_MAJOR_VERSION 0) set(LIBSYCL_MINOR_VERSION 1) @@ -117,10 +115,22 @@ add_custom_command( install(DIRECTORY "${LIBSYCL_SOURCE_INCLUDE_DIR}/sycl" DESTINATION ${LIBSYCL_INCLUDE_DIR} COMPONENT sycl-headers) install(DIRECTORY "${LIBSYCL_SOURCE_INCLUDE_DIR}/CL" DESTINATION ${LIBSYCL_INCLUDE_DIR} COMPONENT sycl-headers) -set(LIBSYCL_RT_LIBS ${LIBSYCL_SHARED_OUTPUT_NAME}) +set(LIBSYCL_LIB_NAME "sycl") +set(LIBSYCL_SHARED_OUTPUT_NAME "${LIBSYCL_LIB_NAME}") +if (CMAKE_SYSTEM_NAME STREQUAL Windows) + if (CMAKE_MSVC_RUNTIME_LIBRARY AND (NOT CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "DLL$")) + message(FATAL_ERROR "libsycl requires a DLL version of the MSVC CRT.") + endif() + if ((NOT CMAKE_MSVC_RUNTIME_LIBRARY AND uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") + OR (CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreadedDebugDLL")) + set(LIBSYCL_SHARED_OUTPUT_NAME "${LIBSYCL_SHARED_OUTPUT_NAME}d") + endif() +endif() add_subdirectory(src) +set(LIBSYCL_RT_LIBS ${LIBSYCL_SHARED_OUTPUT_NAME}) add_custom_target(libsycl-runtime-libraries DEPENDS ${LIBSYCL_RT_LIBS} ) +add_subdirectory(tools) diff --git a/libsycl/docs/index.rst b/libsycl/docs/index.rst index 78e76e73284d3..83df7807c9df9 100644 --- a/libsycl/docs/index.rst +++ b/libsycl/docs/index.rst @@ -69,11 +69,17 @@ To build LLVM with libsycl runtime enabled the following script can be used. mkdir -p $installprefix cmake -G Ninja -S $llvm/llvm -B $build_llvm \ - -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" \ + -DLLVM_ENABLE_PROJECTS="clang" \ -DLLVM_INSTALL_UTILS=ON \ -DCMAKE_INSTALL_PREFIX=$installprefix \ - -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libsycl;libunwind" \ + -DLLVM_ENABLE_RUNTIMES="offload;openmp;libsycl" \ -DCMAKE_BUILD_TYPE=Release ninja -C $build_llvm install - \ No newline at end of file + + +Limitations +======== + +SYCL runtime is not tested and is not guaranteed to work on Windows because offloading runtime (liboffload) used by SYCL runtime doesn't currently support Windows. +The limitation to be revised once liboffload will add support for Windows. diff --git a/libsycl/include/sycl/__impl/backend.hpp b/libsycl/include/sycl/__impl/backend.hpp new file mode 100644 index 0000000000000..bc361e487af69 --- /dev/null +++ b/libsycl/include/sycl/__impl/backend.hpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the declaration of the SYCL enum class backend that is +/// implementation-defined and is populated with a unique identifier for each +/// SYCL backend that the SYCL implementation can support. +/// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL___IMPL_BACKEND_HPP +#define _LIBSYCL___IMPL_BACKEND_HPP + +#include + +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +// 4.1. Backends +enum class backend : char { + opencl = 1, + level_zero = 2, + cuda = 3, + hip = 4, + all = 5, +}; + +namespace detail { +template struct is_backend_info_desc : std::false_type {}; +} // namespace detail + +// 4.5.1.1. Type traits backend_traits +template class backend_traits; + +template +using backend_input_t = + typename backend_traits::template input_type; +template +using backend_return_t = + typename backend_traits::template return_type; + +namespace detail { +inline std::string_view get_backend_name(const backend &Backend) { + switch (Backend) { + case backend::opencl: + return "opencl"; + case backend::level_zero: + return "level_zero"; + case backend::cuda: + return "cuda"; + case backend::hip: + return "hip"; + case backend::all: + return "all"; + } + + return ""; +} +} // namespace detail + +_LIBSYCL_END_NAMESPACE_SYCL + +#endif // _LIBSYCL___IMPL_BACKEND_HPP diff --git a/libsycl/include/sycl/__impl/detail/config.hpp b/libsycl/include/sycl/__impl/detail/config.hpp index cc9059762af1b..ea7a8530a8cfe 100644 --- a/libsycl/include/sycl/__impl/detail/config.hpp +++ b/libsycl/include/sycl/__impl/detail/config.hpp @@ -41,8 +41,8 @@ # else // _WIN32 -# define _LIBSYCL_DLL_LOCAL [[__gnu__::__visibility__("hidden")]] -# define _LIBSYCL_EXPORT [[__gnu__::__visibility__("default")]] +# define _LIBSYCL_DLL_LOCAL __attribute__((visibility("hidden"))) +# define _LIBSYCL_EXPORT __attribute__((visibility("default"))) # endif // _WIN32 # endif // _LIBSYCL_EXPORT diff --git a/libsycl/include/sycl/__impl/detail/macro_definitions.hpp b/libsycl/include/sycl/__impl/detail/macro_definitions.hpp new file mode 100644 index 0000000000000..c9e148709d721 --- /dev/null +++ b/libsycl/include/sycl/__impl/detail/macro_definitions.hpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains macro definitions used in SYCL implementation. +/// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL___IMPL_DETAIL_MACRO_DEFINITIONS_HPP +#define _LIBSYCL___IMPL_DETAIL_MACRO_DEFINITIONS_HPP + +#ifndef __SYCL2020_DEPRECATED +# if SYCL_LANGUAGE_VERSION == 202012L && \ + !defined(SYCL2020_DISABLE_DEPRECATION_WARNINGS) +# define __SYCL2020_DEPRECATED(message) [[deprecated(message)]] +# else +# define __SYCL2020_DEPRECATED(message) +# endif +#endif // __SYCL2020_DEPRECATED + +static_assert(__cplusplus >= 201703L, + "SYCL RT does not support C++ version earlier than C++17."); + +#if defined(_WIN32) && !defined(_DLL) && !defined(__SYCL_DEVICE_ONLY__) +// SYCL library is designed such a way that STL objects cross DLL boundary, +// which is guaranteed to work properly only when the application uses the same +// C++ runtime that SYCL library uses. +// The appplications using sycl.dll must be linked with dynamic/release C++ MSVC +// runtime, i.e. be compiled with /MD switch. Similarly, the applications using +// sycld.dll must be linked with dynamic/debug C++ runtime and be compiled with +// /MDd switch. +// Compiler automatically adds /MD or /MDd when -fsycl switch is used. +// The options /MD and /MDd that make the code to use dynamic runtime also +// define the _DLL macro. +# define ERROR_MESSAGE \ + "SYCL library is designed to work safely with dynamic C++ runtime." \ + "Please use /MD switch with sycl.dll, /MDd switch with sycld.dll, " \ + "or -fsycl switch to set C++ runtime automatically." +# if defined(_MSC_VER) +# pragma message(ERROR_MESSAGE) +# else +# warning ERROR_MESSAGE +# endif +# undef ERROR_MESSAGE +#endif // defined(_WIN32) && !defined(_DLL) && !defined(__SYCL_DEVICE_ONLY__) + +#endif //_LIBSYCL___IMPL_DETAIL_MACRO_DEFINITIONS_HPP diff --git a/libsycl/include/sycl/__impl/detail/obj_base.hpp b/libsycl/include/sycl/__impl/detail/obj_base.hpp new file mode 100644 index 0000000000000..d0314bbdbf767 --- /dev/null +++ b/libsycl/include/sycl/__impl/detail/obj_base.hpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains helper functions for tranformation between implementation +/// and SYCL's interface objects. +/// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL___IMPL_DETAIL_OBJ_BASE_HPP +#define _LIBSYCL___IMPL_DETAIL_OBJ_BASE_HPP + +#include + +#include +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +namespace detail { + +template class ObjBase { +public: + using ImplType = Impl; + using Base = ObjBase; + +protected: + ImplType &impl; + + explicit ObjBase(ImplType &pImpl) : impl(pImpl) {} + ObjBase() = default; + + static SyclObject createSyclProxy(ImplType &impl) { return SyclObject(impl); } + + template + friend const typename Obj::ImplType &getSyclObjImpl(const Obj &Object); + + template + friend Obj createSyclObjFromImpl( + std::add_lvalue_reference_t ImplObj); +}; + +template +const typename Obj::ImplType &getSyclObjImpl(const Obj &Object) { + return Object.impl; +} + +template +Obj createSyclObjFromImpl( + std::add_lvalue_reference_t ImplObj) { + return Obj::Base::createSyclProxy(ImplObj); +} + +} // namespace detail + +_LIBSYCL_END_NAMESPACE_SYCL + +#endif // _LIBSYCL___IMPL_DETAIL_OBJ_BASE_HPP diff --git a/libsycl/include/sycl/__impl/exception.hpp b/libsycl/include/sycl/__impl/exception.hpp new file mode 100644 index 0000000000000..d41a833e1bc10 --- /dev/null +++ b/libsycl/include/sycl/__impl/exception.hpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the declaration of the SYCL 2020 Exception class +/// interface (4.13.2.) +/// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL___IMPL_EXCEPTION_HPP +#define _LIBSYCL___IMPL_EXCEPTION_HPP + +#include + +#include +#include +#include +#include +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +class context; + +enum class errc : int { + success = 0, + runtime = 1, + kernel = 2, + accessor = 3, + nd_range = 4, + event = 5, + kernel_argument = 6, + build = 7, + invalid = 8, + memory_allocation = 9, + platform = 10, + profiling = 11, + feature_not_supported = 12, + kernel_not_supported = 13, + backend_mismatch = 14, +}; + +/// Constructs an error code using E and sycl_category() +_LIBSYCL_EXPORT std::error_code make_error_code(sycl::errc E) noexcept; + +/// Obtains a reference to the static error category object for SYCL errors. +_LIBSYCL_EXPORT const std::error_category &sycl_category() noexcept; + +// Derive from std::exception so uncaught exceptions are printed in c++ default +// exception handler. +// Virtual inheritance is mandated by SYCL 2020. +// 4.13.2. Exception class interface +class _LIBSYCL_EXPORT exception : public virtual std::exception { +public: + exception(std::error_code, const char *); + exception(std::error_code Ec, const std::string &Msg) + : exception(Ec, Msg.c_str()) {} + + exception(std::error_code EC) : exception(EC, "") {} + exception(int EV, const std::error_category &ECat, const std::string &WhatArg) + : exception(EV, ECat, WhatArg.c_str()) {} + exception(int EV, const std::error_category &ECat, const char *WhatArg) + : exception({EV, ECat}, WhatArg) {} + exception(int EV, const std::error_category &ECat) + : exception({EV, ECat}, "") {} + + virtual ~exception(); + + const std::error_code &code() const noexcept; + const std::error_category &category() const noexcept; + + const char *what() const noexcept final; + + bool has_context() const noexcept; + +private: + // Exceptions must be noexcept copy constructible, so cannot use std::string + // directly. + std::shared_ptr MMessage; + std::error_code MErrC = make_error_code(sycl::errc::invalid); +}; + +/// Used as a container for a list of asynchronous exceptions +/// +class _LIBSYCL_EXPORT exception_list { +public: + using value_type = std::exception_ptr; + using reference = value_type &; + using const_reference = const value_type &; + using size_type = std::size_t; + using iterator = std::vector::const_iterator; + using const_iterator = std::vector::const_iterator; + + size_type size() const; + // first asynchronous exception + iterator begin() const; + // refer to past-the-end last asynchronous exception + iterator end() const; + +private: + std::vector MList; +}; + +_LIBSYCL_END_NAMESPACE_SYCL + +namespace std { +template <> struct is_error_code_enum : true_type {}; +} // namespace std + +#endif // _LIBSYCL___IMPL_EXCEPTION_HPP diff --git a/libsycl/include/sycl/__impl/info/platform.def b/libsycl/include/sycl/__impl/info/platform.def new file mode 100644 index 0000000000000..68835fc3e3640 --- /dev/null +++ b/libsycl/include/sycl/__impl/info/platform.def @@ -0,0 +1,8 @@ +#ifndef __SYCL_PARAM_TRAITS_SPEC +static_assert(false, "__SYCL_PARAM_TRAITS_SPEC is required but not defined"); +#endif + +// 4.6.2.4. Information descriptors +__SYCL_PARAM_TRAITS_SPEC(platform, version, std::string, OL_PLATFORM_INFO_VERSION) +__SYCL_PARAM_TRAITS_SPEC(platform, name, std::string, OL_PLATFORM_INFO_NAME) +__SYCL_PARAM_TRAITS_SPEC(platform, vendor, std::string, OL_PLATFORM_INFO_VENDOR_NAME) diff --git a/libsycl/include/sycl/__impl/info/platform.hpp b/libsycl/include/sycl/__impl/info/platform.hpp new file mode 100644 index 0000000000000..d175b66adf570 --- /dev/null +++ b/libsycl/include/sycl/__impl/info/platform.hpp @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the declaration of SYCL 2020 platform info types. +/// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL___IMPL_INFO_PLATFORM_HPP +#define _LIBSYCL___IMPL_INFO_PLATFORM_HPP + +#include + +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +// A.1. Platform information descriptors +namespace info { +namespace platform { +#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, OffloadCode) \ + struct Desc { \ + using return_type = ReturnT; \ + }; + +// 4.6.2.4. Information descriptors +#include + +#undef __SYCL_PARAM_TRAITS_SPEC +} // namespace platform +} // namespace info + +namespace detail { +template struct is_platform_info_desc : std::false_type {}; + +#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, OffloadCode) \ + template <> \ + struct is_##DescType##_info_desc : std::true_type { \ + using return_type = info::DescType::Desc::return_type; \ + }; + +#include + +#undef __SYCL_PARAM_TRAITS_SPEC +} // namespace detail + +_LIBSYCL_END_NAMESPACE_SYCL + +#endif // _LIBSYCL___IMPL_INFO_PLATFORM_HPP diff --git a/libsycl/include/sycl/__impl/platform.hpp b/libsycl/include/sycl/__impl/platform.hpp index bac59ac93d3dd..b54c339208e84 100644 --- a/libsycl/include/sycl/__impl/platform.hpp +++ b/libsycl/include/sycl/__impl/platform.hpp @@ -15,15 +15,96 @@ #ifndef _LIBSYCL___IMPL_PLATFORM_HPP #define _LIBSYCL___IMPL_PLATFORM_HPP +#include #include +#include +#include + +#include +#include _LIBSYCL_BEGIN_NAMESPACE_SYCL -class _LIBSYCL_EXPORT platform { +namespace detail { +class platform_impl; +} // namespace detail + +// 4.6.2. Platform class +class _LIBSYCL_EXPORT platform + : public detail::ObjBase { public: - /// Constructs a SYCL platform which contains the default device. - platform(); + /// Constructs a platform object that is a copy of the platform which contains + /// the device returned by default_selector_v. + // platform(); + + /// Constructs a platform object that is a copy of the platform which contains + /// the device that is selected by selector. + /// \param DeviceSelectorInstance is SYCL 2020 Device Selector, a simple + /// callable taking a device reference and returning an integer rank. + // template + // explicit platform(const DeviceSelector& DeviceSelectorInstance); + + /// Returns the backend associated with this platform. + /// + /// \return the backend associated with this platform + backend get_backend() const noexcept; + + /// Returns all SYCL devices associated with this platform. + /// + /// If there are no devices that match given device + /// type, resulting vector is empty. + /// + /// \param DeviceType is a SYCL device type. + /// \return a vector of SYCL devices. + // std::vector + // get_devices(info::device_type DeviceType = info::device_type::all) + // const; + + /// Queries this SYCL platform for info. + /// + /// The return type depends on information being queried. + template + typename detail::is_platform_info_desc::return_type get_info() const { + return get_info_impl(); + } + + // template + // typename detail::is_backend_info_desc::return_type + // get_backend_info() const; + + /// Indicates if all of the SYCL devices on this platform have the + /// given feature. + /// + /// \param Aspect is one of the values in Table 4.20 of the SYCL 2020 + /// Provisional Spec. + /// + /// \return true if all of the SYCL devices on this platform have the + /// given feature. + // bool has(aspect Aspect) const; + + /// Checks if platform supports specified extension. + /// + /// \param ExtensionName is a string containing extension name. + /// \return true if specified extension is supported by this SYCL platform. + // __SYCL2020_DEPRECATED( + // "use platform::has() function with aspects APIs instead") + // bool has_extension(const std::string& ExtensionName) const; // Deprecated + + /// Returns all SYCL platforms from all backends that are available in the + /// system. + /// + /// \return A std::vector containing all of the platforms from all backends + /// that are available in the system. + static std::vector get_platforms(); + +private: + platform(detail::platform_impl &Impl) : ObjBase(Impl) {} + + template + typename detail::is_platform_info_desc::return_type + get_info_impl() const; + friend detail::ObjBase; }; // class platform _LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/include/sycl/sycl.hpp b/libsycl/include/sycl/sycl.hpp index 76399eba758d2..ef91ab2381770 100644 --- a/libsycl/include/sycl/sycl.hpp +++ b/libsycl/include/sycl/sycl.hpp @@ -14,6 +14,7 @@ #ifndef _LIBSYCL_SYCL_HPP #define _LIBSYCL_SYCL_HPP +#include #include #endif // _LIBSYCL_SYCL_HPP diff --git a/libsycl/src/CMakeLists.txt b/libsycl/src/CMakeLists.txt index 206b85681cb84..5c8010801f231 100644 --- a/libsycl/src/CMakeLists.txt +++ b/libsycl/src/CMakeLists.txt @@ -2,10 +2,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../runtimes/cmake/ include(WarningFlags) function(add_sycl_rt_library LIB_TARGET_NAME LIB_OBJ_NAME LIB_OUTPUT_NAME) - if (NOT LLVM_ENABLE_PIC) - message( FATAL_ERROR "Position-Independent Code generation is required for libsycl shared library" ) - endif() - cmake_parse_arguments(ARG "" "" "COMPILE_OPTIONS;SOURCES" ${ARGN}) add_library(${LIB_OBJ_NAME} OBJECT ${ARG_SOURCES}) @@ -20,6 +16,7 @@ function(add_sycl_rt_library LIB_TARGET_NAME LIB_OBJ_NAME LIB_OUTPUT_NAME) PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIBSYCL_BUILD_INCLUDE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/../../offload/liboffload/API ) add_library(${LIB_TARGET_NAME} SHARED @@ -27,6 +24,7 @@ function(add_sycl_rt_library LIB_TARGET_NAME LIB_OBJ_NAME LIB_OUTPUT_NAME) add_dependencies(${LIB_OBJ_NAME} sycl-headers + LLVMOffload ) set_target_properties(${LIB_TARGET_NAME} PROPERTIES LINKER_LANGUAGE CXX) @@ -49,7 +47,7 @@ function(add_sycl_rt_library LIB_TARGET_NAME LIB_OBJ_NAME LIB_OUTPUT_NAME) target_compile_options(${LIB_OBJ_NAME} PUBLIC /EHsc) else() target_compile_options(${LIB_OBJ_NAME} PUBLIC - -fvisibility=hidden -fvisibility-inlines-hidden) + -fvisibility=hidden -fvisibility-inlines-hidden -fPIC) if (UNIX AND NOT APPLE) set(linker_script "${CMAKE_CURRENT_SOURCE_DIR}/ld-version-script.txt") @@ -65,6 +63,7 @@ function(add_sycl_rt_library LIB_TARGET_NAME LIB_OBJ_NAME LIB_OUTPUT_NAME) PRIVATE ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT} + LLVMOffload ) set_target_properties(${LIB_TARGET_NAME} PROPERTIES @@ -74,22 +73,16 @@ function(add_sycl_rt_library LIB_TARGET_NAME LIB_OBJ_NAME LIB_OUTPUT_NAME) endfunction(add_sycl_rt_library) set(LIBSYCL_SOURCES + "exception.cpp" + "exception_list.cpp" "platform.cpp" + "detail/global_objects.cpp" + "detail/platform_impl.cpp" + "detail/offload/offload_utils.cpp" + "detail/offload/offload_topology.cpp" ) -set(LIB_NAME "sycl") -set(LIB_OUTPUT_NAME "${LIB_NAME}") -if (CMAKE_SYSTEM_NAME STREQUAL Windows) - if (CMAKE_MSVC_RUNTIME_LIBRARY AND (NOT CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "DLL$")) - message(FATAL_ERROR "libsycl requires a DLL version of the MSVC CRT.") - endif() - if ((NOT CMAKE_MSVC_RUNTIME_LIBRARY AND uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") - OR (CMAKE_MSVC_RUNTIME_LIBRARY STREQUAL "MultiThreadedDebugDLL")) - set(LIB_OUTPUT_NAME "${LIB_OUTPUT_NAME}d") - endif() -endif() - -add_sycl_rt_library(${LIB_NAME} sycl_object ${LIB_OUTPUT_NAME} +add_sycl_rt_library(${LIBSYCL_LIB_NAME} sycl_object ${LIBSYCL_SHARED_OUTPUT_NAME} SOURCES ${LIBSYCL_SOURCES}) install(TARGETS ${LIBSYCL_RT_LIBS} diff --git a/libsycl/src/detail/global_objects.cpp b/libsycl/src/detail/global_objects.cpp new file mode 100644 index 0000000000000..1dbb7074ed453 --- /dev/null +++ b/libsycl/src/detail/global_objects.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include +#include + +#ifdef _WIN32 +# include +#endif + +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL +namespace detail { + +std::vector &getOffloadTopologies() { + static std::vector Topologies( + OL_PLATFORM_BACKEND_LAST); + return Topologies; +} + +std::vector> &getPlatformCache() { + static std::vector> PlatformCache{}; + return PlatformCache; +} + +std::mutex &getPlatformMapMutex() { + static std::mutex PlatformMapMutex{}; + return PlatformMapMutex; +} + +void shutdown() { + // No error reporting in shutdown + std::ignore = olShutDown(); +} + +#ifdef _WIN32 +extern "C" _LIBSYCL_EXPORT BOOL WINAPI DllMain(HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpReserved) { + // Perform actions based on the reason for calling. + switch (fdwReason) { + case DLL_PROCESS_DETACH: + try { + shutdown(); + } catch (std::exception &e) { + // report + } + + break; + case DLL_PROCESS_ATTACH: + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + } + return TRUE; // Successful DLL_PROCESS_ATTACH. +} +#else +// Setting low priority on destructor ensures it runs after all other global +// destructors. Priorities 0-100 are reserved by the compiler. The priority +// value 110 allows SYCL users to run their destructors after runtime library +// deinitialization. +__attribute__((destructor(110))) static void syclUnload() { shutdown(); } +#endif +} // namespace detail +_LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/detail/global_objects.hpp b/libsycl/src/detail/global_objects.hpp new file mode 100644 index 0000000000000..57deee4e5529b --- /dev/null +++ b/libsycl/src/detail/global_objects.hpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL_GLOBAL_OBJECTS +#define _LIBSYCL_GLOBAL_OBJECTS + +#include +#include + +#include +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +namespace detail { +class platform_impl; + +// Offload topologies (one per backend) discovered from liboffload. +std::vector &getOffloadTopologies(); + +std::mutex &getPlatformMapMutex(); +std::vector> &getPlatformCache(); + +} // namespace detail +_LIBSYCL_END_NAMESPACE_SYCL + +#endif // _LIBSYCL_GLOBAL_OBJECTS diff --git a/libsycl/src/detail/offload/info_code.hpp b/libsycl/src/detail/offload/info_code.hpp new file mode 100644 index 0000000000000..a9734d380a7c4 --- /dev/null +++ b/libsycl/src/detail/offload/info_code.hpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL_INFO_CODE +#define _LIBSYCL_INFO_CODE + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +#include + +namespace detail { +template struct OffloadInfoCode; + +#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, OffloadCode) \ + template <> struct OffloadInfoCode { \ + static constexpr auto value = OffloadCode; \ + }; +#include +#undef __SYCL_PARAM_TRAITS_SPEC + +} // namespace detail + +_LIBSYCL_END_NAMESPACE_SYCL + +#endif // _LIBSYCL_INFO_CODE diff --git a/libsycl/src/detail/offload/offload_topology.cpp b/libsycl/src/detail/offload/offload_topology.cpp new file mode 100644 index 0000000000000..8a85ab477b885 --- /dev/null +++ b/libsycl/src/detail/offload/offload_topology.cpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +namespace detail { + +void discoverOffloadDevices() { + [[maybe_unused]] static auto DiscoverOnce = [&]() { + call_and_throw(olInit); + + using PerBackendDataType = + std::array, + OL_PLATFORM_BACKEND_LAST>; + + PerBackendDataType Mapping; + // olIterateDevices calls lambda for every device. + // Returning early means jump to next iteration/next device. + call_nocheck( + olIterateDevices, + [](ol_device_handle_t Dev, void *User) -> bool { + auto *Data = static_cast(User); + ol_platform_handle_t Plat = nullptr; + ol_result_t Res = + call_nocheck(olGetDeviceInfo, Dev, OL_DEVICE_INFO_PLATFORM, + sizeof(Plat), &Plat); + // If error occures, ignore platform and continue iteration + if (Res != OL_SUCCESS) + return true; + + ol_platform_backend_t OlBackend = OL_PLATFORM_BACKEND_UNKNOWN; + Res = call_nocheck(olGetPlatformInfo, Plat, OL_PLATFORM_INFO_BACKEND, + sizeof(OlBackend), &OlBackend); + // If error occures, ignore platform and continue iteration + if (Res != OL_SUCCESS) + return true; + + // Skip host & unknown backends + if (OL_PLATFORM_BACKEND_HOST == OlBackend || + OL_PLATFORM_BACKEND_UNKNOWN == OlBackend) + return true; + + // Ensure backend index fits into array size + if (OlBackend >= OL_PLATFORM_BACKEND_LAST) + return true; + + auto &[Map, DevCount] = (*Data)[static_cast(OlBackend)]; + Map[Plat].push_back(Dev); + DevCount++; + return true; + }, + &Mapping); + // Now register all platforms and devices into the topologies + auto &OffloadTopologies = getOffloadTopologies(); + for (size_t I = 0; I < OL_PLATFORM_BACKEND_LAST; ++I) { + OffloadTopology &Topo = OffloadTopologies[I]; + Topo.set_backend(static_cast(I)); + Topo.registerNewPlatformsAndDevices(Mapping[I].first, Mapping[I].second); + } + + return true; + }(); +} + +} // namespace detail + +_LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/detail/offload/offload_topology.hpp b/libsycl/src/detail/offload/offload_topology.hpp new file mode 100644 index 0000000000000..3bf2e78c10050 --- /dev/null +++ b/libsycl/src/detail/offload/offload_topology.hpp @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL_OFFLOAD_TOPOLOGY +#define _LIBSYCL_OFFLOAD_TOPOLOGY + +#include + +#include + +#include +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +namespace detail { + +// Minimal span-like view +template struct range_view { + const T *ptr{}; + size_t len{}; + const T *begin() const { return ptr; } + const T *end() const { return ptr + len; } + const T &operator[](size_t i) const { return ptr[i]; } + size_t size() const { return len; } +}; + +using PlatformWithDevStorageType = + std::unordered_map>; + +// Contiguous global storage of platform handlers and device handles (grouped by +// platform) for a backend. +struct OffloadTopology { + OffloadTopology() : MBackend(OL_PLATFORM_BACKEND_UNKNOWN) {} + OffloadTopology(ol_platform_backend_t OlBackend) : MBackend(OlBackend) {} + + void set_backend(ol_platform_backend_t B) { MBackend = B; } + + // Platforms for this backend + range_view platforms() const { + return {MPlatforms.data(), MPlatforms.size()}; + } + + // Devices for a specific platform (platform_id is index into Platforms) + range_view devicesForPlatform(size_t PlatformId) const { + if (PlatformId >= MDevRangePerPlatformId.size()) + return {nullptr, 0}; + return MDevRangePerPlatformId[PlatformId]; + } + + // Register new platform and devices into this topology under that platform. + void + registerNewPlatformsAndDevices(PlatformWithDevStorageType &PlatformsAndDev, + size_t TotalDevCount) { + if (!PlatformsAndDev.size()) + return; + + MPlatforms.reserve(PlatformsAndDev.size()); + MDevRangePerPlatformId.reserve(MPlatforms.size()); + MDevices.reserve(TotalDevCount); + + for (auto &[NewPlatform, NewDevs] : PlatformsAndDev) { + MPlatforms.push_back(NewPlatform); + range_view R{MDevices.data() + MDevices.size(), + NewDevs.size()}; + MDevices.insert(MDevices.end(), NewDevs.begin(), NewDevs.end()); + MDevRangePerPlatformId.push_back(R); + } + + assert(TotalDevCount == MDevices.size()); + } + + ol_platform_backend_t backend() { return MBackend; } + +private: + ol_platform_backend_t MBackend = OL_PLATFORM_BACKEND_UNKNOWN; + + // Platforms and devices belonging to this backend (flattened) + std::vector MPlatforms; + std::vector MDevices; // sorted by platform + + // Vector holding range of devices for each platform (index is platform index + // within Platforms) + std::vector> + MDevRangePerPlatformId; // PlatformDevices.size() == Platforms.size() +}; + +// Initialize the topologies by calling olIterateDevices. +void discoverOffloadDevices(); + +} // namespace detail + +_LIBSYCL_END_NAMESPACE_SYCL + +#endif // _LIBSYCL_OFFLOAD_TOPOLOGY diff --git a/libsycl/src/detail/offload/offload_utils.cpp b/libsycl/src/detail/offload/offload_utils.cpp new file mode 100644 index 0000000000000..2ccb27a9acf44 --- /dev/null +++ b/libsycl/src/detail/offload/offload_utils.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL +namespace detail { + +const char *stringifyErrorCode(int32_t error) { + switch (error) { +#define _OFFLOAD_ERRC(NAME) \ + case NAME: \ + return #NAME; + _OFFLOAD_ERRC(OL_ERRC_UNKNOWN) + _OFFLOAD_ERRC(OL_ERRC_HOST_IO) + _OFFLOAD_ERRC(OL_ERRC_INVALID_BINARY) + _OFFLOAD_ERRC(OL_ERRC_INVALID_NULL_POINTER) + _OFFLOAD_ERRC(OL_ERRC_INVALID_ARGUMENT) + _OFFLOAD_ERRC(OL_ERRC_NOT_FOUND) + _OFFLOAD_ERRC(OL_ERRC_OUT_OF_RESOURCES) + _OFFLOAD_ERRC(OL_ERRC_INVALID_SIZE) + _OFFLOAD_ERRC(OL_ERRC_INVALID_ENUMERATION) + _OFFLOAD_ERRC(OL_ERRC_HOST_TOOL_NOT_FOUND) + _OFFLOAD_ERRC(OL_ERRC_INVALID_VALUE) + _OFFLOAD_ERRC(OL_ERRC_UNIMPLEMENTED) + _OFFLOAD_ERRC(OL_ERRC_UNSUPPORTED) + _OFFLOAD_ERRC(OL_ERRC_ASSEMBLE_FAILURE) + _OFFLOAD_ERRC(OL_ERRC_COMPILE_FAILURE) + _OFFLOAD_ERRC(OL_ERRC_LINK_FAILURE) + _OFFLOAD_ERRC(OL_ERRC_BACKEND_FAILURE) + _OFFLOAD_ERRC(OL_ERRC_UNINITIALIZED) + _OFFLOAD_ERRC(OL_ERRC_INVALID_NULL_HANDLE) + _OFFLOAD_ERRC(OL_ERRC_INVALID_PLATFORM) + _OFFLOAD_ERRC(OL_ERRC_INVALID_DEVICE) + _OFFLOAD_ERRC(OL_ERRC_INVALID_QUEUE) + _OFFLOAD_ERRC(OL_ERRC_INVALID_EVENT) + _OFFLOAD_ERRC(OL_ERRC_SYMBOL_KIND) +#undef _OFFLOAD_ERRC + + default: + return "Unknown error code"; + } +} + +backend convertBackend(ol_platform_backend_t Backend) { + switch (Backend) { + // case OL_PLATFORM_BACKEND_LEVEL_ZERO: + // return backend::level_zero; + case OL_PLATFORM_BACKEND_CUDA: + return backend::cuda; + case OL_PLATFORM_BACKEND_AMDGPU: + return backend::hip; + default: + throw exception(make_error_code(errc::runtime), + "convertBackend: Unsupported backend"); + } +} + +} // namespace detail +_LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/detail/offload/offload_utils.hpp b/libsycl/src/detail/offload/offload_utils.hpp new file mode 100644 index 0000000000000..b48a6b49d2fd6 --- /dev/null +++ b/libsycl/src/detail/offload/offload_utils.hpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL_OFFLOAD_UTILS +#define _LIBSYCL_OFFLOAD_UTILS + +#include +#include +#include + +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +namespace detail { + +const char *stringifyErrorCode(int32_t error); + +inline std::string formatCodeString(int32_t code) { + return std::to_string(code) + " (" + std::string(stringifyErrorCode(code)) + + ")"; +} + +template +void checkAndThrow(ol_result_t Result) { + if (Result != OL_SUCCESS) { + throw sycl::exception(sycl::make_error_code(errc), + detail::formatCodeString(Result->Code)); + } +} + +/// Calls the API, doesn't check result. To be called when specific handling is +/// needed and explicitly done by developer after. +template +ol_result_t call_nocheck(FunctionType &Function, ArgsT &&...Args) { + return Function(std::forward(Args)...); +} + +/// Calls the API & checks the result +/// +/// \throw sycl::runtime_exception if the call was not successful. +template +void call_and_throw(FunctionType &Function, ArgsT &&...Args) { + auto Err = call_nocheck(Function, std::forward(Args)...); + checkAndThrow(Err); +} + +backend convertBackend(ol_platform_backend_t Backend); + +} // namespace detail + +_LIBSYCL_END_NAMESPACE_SYCL + +#endif // _LIBSYCL_OFFLOAD_UTILS diff --git a/libsycl/src/detail/platform_impl.cpp b/libsycl/src/detail/platform_impl.cpp new file mode 100644 index 0000000000000..324ec369cfcec --- /dev/null +++ b/libsycl/src/detail/platform_impl.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include +#include + +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +namespace detail { + +platform_impl * +platform_impl::getOrMakePlatformImpl(ol_platform_handle_t Platform, + size_t PlatformIndex) { + const std::lock_guard Guard(getPlatformMapMutex()); + + std::vector> &PlatformCache = + getPlatformCache(); + + // If we've already seen this platform, return the impl + for (const auto &PlatImpl : PlatformCache) { + if (PlatImpl->getHandleRef() == Platform) + return PlatImpl.get(); + } + + // Otherwise make the impl. + std::unique_ptr Result; + Result = std::make_unique(Platform, PlatformIndex); + PlatformCache.emplace_back(std::move(Result)); + + return PlatformCache.back().get(); +} + +std::vector platform_impl::getPlatforms() { + discoverOffloadDevices(); + std::vector Platforms; + for (const auto &Topo : getOffloadTopologies()) { + size_t PlatformIndex = 0; + for (const auto &OffloadPlatform : Topo.platforms()) { + platform Platform = detail::createSyclObjFromImpl( + *getOrMakePlatformImpl(OffloadPlatform, PlatformIndex++)); + Platforms.push_back(std::move(Platform)); + } + } + return Platforms; +} + +platform_impl::platform_impl(ol_platform_handle_t Platform, + size_t PlatformIndex) + : MOffloadPlatform(Platform), MOffloadPlatformIndex(PlatformIndex) { + ol_platform_backend_t Backend = OL_PLATFORM_BACKEND_UNKNOWN; + call_and_throw(olGetPlatformInfo, MOffloadPlatform, OL_PLATFORM_INFO_BACKEND, + sizeof(Backend), &Backend); + MBackend = convertBackend(Backend); + MOffloadBackend = Backend; +} +} // namespace detail +_LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/detail/platform_impl.hpp b/libsycl/src/detail/platform_impl.hpp new file mode 100644 index 0000000000000..45a1cf37c1d3b --- /dev/null +++ b/libsycl/src/detail/platform_impl.hpp @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL_PLATFORM_IMPL +#define _LIBSYCL_PLATFORM_IMPL + +#include +#include +#include + +#include "detail/offload/info_code.hpp" +#include "detail/offload/offload_utils.hpp" + +#include + +#include +#include +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +namespace detail { + +class platform_impl { +public: + /// Constructs platform_impl from a platform handle. + /// + /// \param Platform is a raw offload library handle representing platform. + /// \param PlatformIndex is a platform index in a backend (needed for a proper + /// indexing in device selector). + // + // Platforms can only be created under `GlobalHandler`'s ownership via + // `platform_impl::getOrMakePlatformImpl` method. + explicit platform_impl(ol_platform_handle_t Platform, size_t PlatformIndex); + + ~platform_impl() = default; + + /// Returns the backend associated with this platform. + backend getBackend() const noexcept { return MBackend; } + + /// Returns all SYCL platforms from all backends that are available in the + /// system. + static std::vector getPlatforms(); + + /// Returns raw underlying offload platform handle. + /// + /// It does not retain handle. It is caller responsibility to make sure that + /// platform stays alive while raw handle is in use. + /// + /// \return a raw plug-in platform handle. + const ol_platform_handle_t &getHandleRef() const { return MOffloadPlatform; } + + /// Returns platform index in a backend (needed for a proper indexing in + /// device selector). + size_t getPlatformIndex() const { return MOffloadPlatformIndex; } + + /// Queries the cache to see if the specified offloading RT platform has been + /// seen before. If so, return the cached platform_impl, otherwise create a + /// new one and cache it. + /// + /// \param Platform is the offloading RT Platform handle representing the + /// platform + /// \param PlatformIndex is a platform index in a backend (needed for a proper + /// indexing in device selector). + /// \return the platform_impl representing the offloading RT platform + static platform_impl *getOrMakePlatformImpl(ol_platform_handle_t Platform, + size_t PlatformIndex); + + /// Queries this SYCL platform for info. + /// + /// The return type depends on information being queried. + template typename Param::return_type get_info() const { + // for now we have only std::string properties + static_assert(std::is_same_v); + size_t ExpectedSize = 0; + call_and_throw(olGetPlatformInfoSize, MOffloadPlatform, + detail::OffloadInfoCode::value, &ExpectedSize); + std::string Result; + Result.resize(ExpectedSize - 1); + call_and_throw(olGetPlatformInfo, MOffloadPlatform, + detail::OffloadInfoCode::value, ExpectedSize, + Result.data()); + return Result; + } + +private: + ol_platform_handle_t MOffloadPlatform{}; + size_t MOffloadPlatformIndex{}; + ol_platform_backend_t MOffloadBackend{OL_PLATFORM_BACKEND_UNKNOWN}; + backend MBackend{}; +}; + +} // namespace detail +_LIBSYCL_END_NAMESPACE_SYCL + +#endif // _LIBSYCL_PLATFORM_IMPL diff --git a/libsycl/src/exception.cpp b/libsycl/src/exception.cpp new file mode 100644 index 0000000000000..38fd8816934b9 --- /dev/null +++ b/libsycl/src/exception.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the definition of the SYCL 2020 exception class interface +/// (4.13.2.) +/// +//===----------------------------------------------------------------------===// + +// 4.9.2 Exception Class Interface +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +namespace detail { +class SYCLCategory : public std::error_category { +public: + const char *name() const noexcept override { return "sycl"; } + std::string message(int) const override { return "SYCL Error"; } +}; +} // namespace detail + +// Free functions +const std::error_category &sycl_category() noexcept { + static const detail::SYCLCategory SYCLCategoryObj; + return SYCLCategoryObj; +} + +std::error_code make_error_code(sycl::errc Err) noexcept { + return std::error_code(static_cast(Err), sycl_category()); +} + +// Exception methods implementation +exception::exception(std::error_code EC, const char *Msg) + : MMessage(std::make_shared(Msg)), MErrC(EC) {} + +exception::~exception() {} + +const std::error_code &exception::code() const noexcept { return MErrC; } + +const std::error_category &exception::category() const noexcept { + return code().category(); +} + +const char *exception::what() const noexcept { return MMessage->c_str(); } + +bool exception::has_context() const noexcept { /*return (MContext != nullptr);*/ + return false; +} + +_LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/exception_list.cpp b/libsycl/src/exception_list.cpp new file mode 100644 index 0000000000000..3eaf213deaaec --- /dev/null +++ b/libsycl/src/exception_list.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the definition of the SYCL 2020 exception_list class +/// interface (4.13.2.) +/// +//===----------------------------------------------------------------------===// + +// 4.13.2. Exception class interface +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +exception_list::size_type exception_list::size() const { return MList.size(); } + +exception_list::iterator exception_list::begin() const { return MList.begin(); } + +exception_list::iterator exception_list::end() const { return MList.cend(); } + +_LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/platform.cpp b/libsycl/src/platform.cpp index b5d6517ee2120..1dc42a3f39b87 100644 --- a/libsycl/src/platform.cpp +++ b/libsycl/src/platform.cpp @@ -8,10 +8,29 @@ #include +#include + #include _LIBSYCL_BEGIN_NAMESPACE_SYCL -platform::platform() { throw std::runtime_error("Unimplemented"); } +backend platform::get_backend() const noexcept { return impl.getBackend(); } + +std::vector platform::get_platforms() { + return detail::platform_impl::getPlatforms(); +} + +template +typename detail::is_platform_info_desc::return_type +platform::get_info_impl() const { + return impl.template get_info(); +} + +#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, OffloadCode) \ + template _LIBSYCL_EXPORT ReturnT \ + platform::get_info_impl() const; + +#include +#undef __SYCL_PARAM_TRAITS_SPEC _LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/tools/CMakeLists.txt b/libsycl/tools/CMakeLists.txt new file mode 100644 index 0000000000000..74cfa653232c7 --- /dev/null +++ b/libsycl/tools/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(sycl-ls) diff --git a/libsycl/tools/sycl-ls/CMakeLists.txt b/libsycl/tools/sycl-ls/CMakeLists.txt new file mode 100644 index 0000000000000..302ed43248007 --- /dev/null +++ b/libsycl/tools/sycl-ls/CMakeLists.txt @@ -0,0 +1,25 @@ +add_executable(sycl-ls sycl-ls.cpp) + +target_include_directories(sycl-ls SYSTEM PRIVATE ${LLVM_MAIN_INCLUDE_DIR}) +target_link_libraries(sycl-ls PRIVATE LLVMSupport LLVMObject) + +add_dependencies(sycl-ls sycl) +target_include_directories(sycl-ls PRIVATE ${LIBSYCL_BUILD_INCLUDE_DIR}) + +target_link_libraries(sycl-ls + PRIVATE + ${LIBSYCL_SHARED_OUTPUT_NAME} +) + +include(CheckCXXCompilerFlag) +check_cxx_compiler_flag(-fno-rtti COMPILER_HAS_NORTTI_FLAG) +if (COMPILER_HAS_NORTTI_FLAG) + target_compile_options(sycl-ls PRIVATE -fno-rtti) +endif() + +if (WIN32) + # 0x900: Search for the dependency DLLs only in the System32 directory and in the directory with sycl-ls.exe + target_link_options(sycl-ls PRIVATE LINKER:/DEPENDENTLOADFLAG:0x900) +endif() +install(TARGETS sycl-ls + RUNTIME DESTINATION "bin" COMPONENT sycl-ls) diff --git a/libsycl/tools/sycl-ls/sycl-ls.cpp b/libsycl/tools/sycl-ls/sycl-ls.cpp new file mode 100644 index 0000000000000..d611a98af8063 --- /dev/null +++ b/libsycl/tools/sycl-ls/sycl-ls.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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 "sycl-ls" utility lists all platforms discovered by SYCL. +// +// There are two types of output: +// concise (default) and +// verbose (enabled with --verbose). +// +#include + +#include "llvm/Support/CommandLine.h" + +#include + +using namespace sycl; +using namespace std::literals; + +int main(int argc, char **argv) { + llvm::cl::opt Verbose( + "verbose", + llvm::cl::desc("Verbosely prints all the discovered platforms")); + llvm::cl::alias VerboseShort("v", llvm::cl::desc("Alias for -verbose"), + llvm::cl::aliasopt(Verbose)); + llvm::cl::ParseCommandLineOptions( + argc, argv, "This program lists all backends discovered by SYCL"); + + try { + const auto &Platforms = platform::get_platforms(); + + if (Platforms.size() == 0) { + std::cout << "No platforms found." << std::endl; + } + + for (const auto &Platform : Platforms) { + backend Backend = Platform.get_backend(); + std::cout << "[" << detail::get_backend_name(Backend) << ":" + << "unknown" << "]" << std::endl; + } + + if (Verbose) { + std::cout << "\nPlatforms: " << Platforms.size() << std::endl; + uint32_t PlatformNum = 0; + for (const auto &Platform : Platforms) { + ++PlatformNum; + auto PlatformVersion = Platform.get_info(); + auto PlatformName = Platform.get_info(); + auto PlatformVendor = Platform.get_info(); + std::cout << "Platform [#" << PlatformNum << "]:" << std::endl; + std::cout << " Version : " << PlatformVersion << std::endl; + std::cout << " Name : " << PlatformName << std::endl; + std::cout << " Vendor : " << PlatformVendor << std::endl; + + std::cout << " Devices : " << "unknown" << std::endl; + } + } else { + return EXIT_SUCCESS; + } + } catch (sycl::exception &e) { + std::cerr << "SYCL Exception encountered: " << e.what() << std::endl + << std::endl; + } + + return EXIT_SUCCESS; +}