Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions libsycl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -117,10 +115,23 @@ 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})

add_subdirectory(src)
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()

set(LIBSYCL_RT_LIBS ${LIBSYCL_SHARED_OUTPUT_NAME})
add_custom_target(libsycl-runtime-libraries
DEPENDS ${LIBSYCL_RT_LIBS}
)

add_subdirectory(src)

add_subdirectory(tools)
12 changes: 9 additions & 3 deletions libsycl/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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



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.
71 changes: 71 additions & 0 deletions libsycl/include/sycl/__impl/backend.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//===----------------------------------------------------------------------===//
//
// 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 <sycl/__impl/detail/config.hpp>

#include <string_view>
#include <type_traits>

_LIBSYCL_BEGIN_NAMESPACE_SYCL

// 4.1. Backends
enum class backend : char {
opencl = 1,
level_zero = 2,
cuda = 3,
hip = 4,
all = 5,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is 0 reserved for some use? If so, a comment would be helpful. If not, then I recommend starting from 0.

Am I right in assuming these will all correspond to a liboffload plugin? If so, a comment to that affect would be helpful. Alternatively, perhaps there should only be a single backend corresponding to liboffload. If we were to add support for Unified Run-time at some point, would that be a distinct backend?

What is the current state of support for these in terms of sycl-ls? I think we should probably omit any that don't work at this time.

What is all used for? The SYCL spec doesn't indicate an "all" concept or specify such an enumerator. Its presence here would appear to necessitate a SYCL_BACKEND_ALL macro which seems strange.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of these backends are exposed (or will be exposed, e.g. opencl) via liboffload. From SYCL RT side there is no such term as "plugin" actually. it is implementation details of liboffload. liboffload is our only entry point. So I don't think we need any comments about implementation details in public headers.

these values will be returned by platform::get_backend except for backend::all.

backend::all will be used once we implement env var for device filter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hip, cuda & level_zero have mapping to liboffload values. opencl is not implemented in liboffload yet. but should be at later stages. I want to have it in enum from the very beginning since SYCL2020 spec mentions presence of opencl backend + we plan to enable it later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me that we are only planning to support one backend at present; liboffload. Since the liboffload plugins are an implementation detail of liboffload, why would we expose the choice of plugin here?

The way I interpret these enumerators is:

  • opencl: Uses OpenCL (directly, not via liboffload) as the backend.
  • level_zero: Uses Level Zero (directly, not via liboffload) as the backend.
  • cuda: Uses CUDA (directly, not via liboffload) as the backend.
  • hip: Uses HIP (directly, not via liboffload) as the backend.

I think we should be reserving the above names for potential hypothetical direct support of those technologies.

Again, let's say we found we needed to add support for Unified Runtime for some reason. How would that fit in. With my interpretation above, we would just add a unified_runtime enumerator (which could also support OpenCL, CUDA, HIP, L0, etc... via a plugin as an implementation detail).

The all enumerator doesn't make sense to me. The concept makes sense in terms of a device filter specified via an environment variable, but that would apply to configuration of a backend, not the choice of a backend.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strongly disagree.
first, liboffload or UR usage is an implementation details. I don't see any case when user should have any info about it in runtime.
second, we don't expose the choice of plugin. we expose information of plugin in use for device. To me it is not fully correct to say that we expose "plugin", it is more like we expose language that is used for SYCL objects.
This information is essential for support of interop scenarios which are part of SYCL 2020 spec. Users should have an information about used backend/plugin/standard/language so that they are able to interpret raw handles (get_native) correctly and so that they are able to choose the correct device/platform if they are interested in any specific backend.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me that we are only planning to support one backend at present; liboffload. Since the liboffload plugins are an implementation detail of liboffload, why would we expose the choice of plugin here?

Because from the point of view of the SYCL specification, the way how you communicate with actual low-level runtimes (i.e. liboffload) is an implementation detail, not the other way around. For example, opencl backend in SYCL has its own appendix section in the SYCL 2020 specification.

Uses OpenCL (directly, not via liboffload) as the backend.

I don't think that directly vs through a layer is important, at least not so much for most of SYCL users. Of course, quality of extra layers might be poor, but ultimately it is underlying backend which dictates what a device is capable of, not an intermediate layer.

Again, let's say we found we needed to add support for Unified Runtime for some reason. How would that fit in. With my interpretation above, we would just add a unified_runtime enumerator (which could also support OpenCL, CUDA, HIP, L0, etc... via a plugin as an implementation detail).

I would suggest an env variable to choose between the offloading mechanisms, i.e. UR vs liboffload.

};

namespace detail {
template <typename T> struct is_backend_info_desc : std::false_type {};
} // namespace detail

// 4.5.1.1. Type traits backend_traits
template <backend Backend> class backend_traits;

template <backend Backend, typename SYCLObjectT>
using backend_input_t =
typename backend_traits<Backend>::template input_type<SYCLObjectT>;
template <backend Backend, typename SYCLObjectT>
using backend_return_t =
typename backend_traits<Backend>::template return_type<SYCLObjectT>;

namespace detail {
// Used by SYCL tools
inline std::string_view get_backend_name(const backend &Backend) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to use something like _LIBCPP_HIDE_FROM_ABI here, if I understand the idea behind it correctly.

Copy link
Contributor Author

@KseniyaTikhomirova KseniyaTikhomirova Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave questions about ABI till the time I will add ABI tests

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, in intel/llvm this function is defined in headers only because we want to use it in the sycl-ls tool so the tool is always aligned on "known" backend with the SYCL RT.

If this intent still stands, I would add a comment about it, or otherwise this function should not exist here at all, because we don't use it anywhere else in the headers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is still used in sycl-ls.
added tiny comment
b15b6c0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend addressing ABI exposures as soon as possible. The code should be designed around ABI concerns if a stable ABI is to be supported. Delay could make handling ABI more complicated later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I will remove this function form public headers
  2. although I don't understand why inline detail fully defined in header function should have any specific ABI related handling. What case do we consider?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
4 changes: 2 additions & 2 deletions libsycl/include/sycl/__impl/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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")))
Comment on lines +44 to +45
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this change is fine, but I'm curious what motivated it. For consistency elsewhere perhaps?

Copy link
Contributor Author

@KseniyaTikhomirova KseniyaTikhomirova Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems that gnu::visibility has limitation that attribute (visibility) - don't:
the following code don't compile with old version:

template _LIBSYCL_EXPORT \
detail::is_platform_info_desc_t<info::platform::Desc> \
platform::get_info<info::platform::Desc>() const;

with
" error: an attribute list cannot appear here"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right; the C++11 attribute syntax is more restrictive in where it can be placed. Can we not use use the C++11 placement everywhere though? Or would that conflict with the syntax location required for Microsoft's __declspex(X) syntax? It would be great if we can standardize on the C++11 attribute placement requirements.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please clarify:
are you suggesting to use c++11+ attr everywhere?
or to avoid it everywhere?


# endif // _WIN32
# endif // _LIBSYCL_EXPORT
Expand Down
52 changes: 52 additions & 0 deletions libsycl/include/sycl/__impl/detail/macro_definitions.hpp
Original file line number Diff line number Diff line change
@@ -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
91 changes: 91 additions & 0 deletions libsycl/include/sycl/__impl/detail/obj_base.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//===----------------------------------------------------------------------===//
//
// 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 <sycl/__impl/detail/config.hpp>

#include <cassert>
#include <optional>
#include <type_traits>
#include <utility>

_LIBSYCL_BEGIN_NAMESPACE_SYCL

namespace detail {

template <typename Impl, typename SyclObject> class ObjBase;
template <typename Impl, typename SyclObject>
class ObjBase<Impl *, SyclObject> {
public:
using ImplType = Impl;
using ImplPtrType = Impl *;
using Base = ObjBase<Impl *, SyclObject>;

protected:
ImplPtrType impl;

explicit ObjBase(ImplPtrType pImpl) : impl(pImpl) {
assert(impl && "Impl can not be nullptr");
}
ObjBase() = default;

static SyclObject createSyclProxy(ImplPtrType impl) {
return SyclObject(impl);
}

ImplType &getImpl() const {
assert(impl && "Impl can not be nullptr");
return *impl;
}

template <class Obj>
friend const typename Obj::ImplType &getSyclObjImpl(const Obj &Object);

template <class Obj>
friend Obj createSyclObjFromImpl(
std::add_lvalue_reference_t<const typename Obj::ImplPtrType> ImplObj);
};

template <class Obj>
const typename Obj::ImplType &getSyclObjImpl(const Obj &Object) {
assert(Object.impl && "Impl can not be nullptr");
return *Object.impl;
}

template <class Obj>
Obj createSyclObjFromImpl(
std::add_lvalue_reference_t<const typename Obj::ImplPtrType> ImplObj) {
return Obj::Base::createSyclProxy(ImplObj);
}

// std::hash support (4.5.2. Common reference semantics)
template <typename T> struct HashBase {
size_t operator()(const T &Obj) const {
#ifdef __SYCL_DEVICE_ONLY__
(void)Obj;
return 0;
#else
auto &Impl = sycl::detail::getSyclObjImpl(Obj);
return std::hash<std::decay_t<decltype(Impl)>>{}(Impl);
#endif
}
};

} // namespace detail

_LIBSYCL_END_NAMESPACE_SYCL

#endif // _LIBSYCL___IMPL_DETAIL_OBJ_BASE_HPP
Loading
Loading