Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
18 changes: 14 additions & 4 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,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)
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.
70 changes: 70 additions & 0 deletions libsycl/include/sycl/__impl/backend.hpp
Original file line number Diff line number Diff line change
@@ -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 <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,
};

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 {
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.

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")))

# 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
64 changes: 64 additions & 0 deletions libsycl/include/sycl/__impl/detail/obj_base.hpp
Original file line number Diff line number Diff line change
@@ -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 <sycl/__impl/detail/config.hpp>

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

_LIBSYCL_BEGIN_NAMESPACE_SYCL

namespace detail {

template <class Impl, class SyclObject> class ObjBase {
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 it would make more sense to do this:

// Helper to implement classes that must obey SYCL's "common reference semantics"
template <typename Impl, typename SyclObject> class ObjBase;
template <typename Impl, typename SyclObject> class ObjBase<Impl &, SyclObject> {
  /* your impl almost unmodified */
};

That way when we start implementing other classes that would require lifetime management, we'd add another specialization like

template <typename Impl, typename SyclObject> class ObjBase<std::shared_ptr<Impl>, SyclObject> {
  /* ... */
};

public:
using ImplType = Impl;
using Base = ObjBase<Impl, SyclObject>;

protected:
ImplType &impl;

explicit ObjBase(ImplType &pImpl) : impl(pImpl) {}
ObjBase() = default;

static SyclObject createSyclProxy(ImplType &impl) { return SyclObject(impl); }

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

template <class Obj>
friend Obj createSyclObjFromImpl(
std::add_lvalue_reference_t<typename Obj::ImplType> ImplObj);
};
Copy link
Contributor

Choose a reason for hiding this comment

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

std::hash support should probably go here as well. We will require some boilerplate code to provide an actual specialization because C++20's

template <class T>
    requires(is_sycl_common_reference_semantics_class_v<T>)
struct std::hash<T> {
// sycl_obj_hash impl inlined here.
};

isn't available to us, but the implementation itself can be done generically here.


template <class Obj>
const typename Obj::ImplType &getSyclObjImpl(const Obj &Object) {
return Object.impl;
}

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

} // namespace detail

_LIBSYCL_END_NAMESPACE_SYCL

#endif // _LIBSYCL___IMPL_DETAIL_OBJ_BASE_HPP
116 changes: 116 additions & 0 deletions libsycl/include/sycl/__impl/exception.hpp
Original file line number Diff line number Diff line change
@@ -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 <sycl/__impl/detail/config.hpp>

#include <exception>
#include <memory>
#include <string>
#include <system_error>
#include <type_traits>
#include <vector>

_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<std::string> MMessage;
Comment on lines +83 to +85
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a great opportunity to start conversation with libcxx developers (@ldionne to start that, I think) on how/if we can share some of their implementation details. __libcpp_refstring would be perfect here.

Another potential opportunity (in a not so distant future PR) would be related to the implementation of std::shared_ptr. In a nutshell, some of the SYCL objects would probably be implemented (simplified) like this:

class event_impl; // defined inside libsycl.so, not exposed to the public headers
class event {
public:
  /* ... */
private:
  std::shared_ptr<event_impl> pImpl;
};

Ideally, we'd want to inherit event_impl from std::enable_shared_from_this. The problem we saw is that inheritance by itself slowed down construction of event_impl because even if know that we always create them via make_shared<event_iml> the implementation still had to initialize the std::enable_shared_from_this subobject with atomic operations resulting in a measurable overhead. If we could somehow use most the libc++'s implementation of these but with a way to communicate extra guarantees of how those objects are created and not to pay the price of these initialization atomics, that would be great, but I'm not sure if that's possible/worth maintenance efforts.

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<std::exception_ptr>::const_iterator;
using const_iterator = std::vector<std::exception_ptr>::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<std::exception_ptr> MList;
};

_LIBSYCL_END_NAMESPACE_SYCL

namespace std {
template <> struct is_error_code_enum<sycl::errc> : true_type {};
} // namespace std

#endif // _LIBSYCL___IMPL_EXCEPTION_HPP
8 changes: 8 additions & 0 deletions libsycl/include/sycl/__impl/info/platform.def
Original file line number Diff line number Diff line change
@@ -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)
Loading
Loading