Skip to content

Commit

Permalink
[SYCL] Initial changes for C++11 ABI=0 support (#12193)
Browse files Browse the repository at this point in the history
This PR attempts to support the usage case where the user sets
_GLIBCXX_USE_CXX11_ABI=0 to use pre-C++11 ABI.
In fact, this change addresses a specific issue with using different
versions of the libstdc++ library
(https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html has
more details on this issue).

One of the major changes I made in this PR involves calling
`get_info<>()` API, which can return `stdA::string` as the requested
information.
Due to the ABI incompatibility issues, this API internally splits into 3
cases depending on the template parameter `<T>`.
1. `<T>`s that return a `std::string`.
2. `<T>`s that return a `std::vector<std::string>`
3. `<T>`s that return something other than 1 or 2 above.

The case 1 and 2 should return `detail::string` and
`std::vector<detail::string>` instead and reconstruct `std::string`s.
This is required because ABIs can be different between the header and
CPP files.
All these 3 cases are implemented using `get_info_impl<T>`.
Then, I changed the macro definition of `__SYCL_PARAM_TRAITS_SPEC` to
return different types depending on the `<T>` return_types.
This way, we can only change the boundary between the header file and
the entry point of the libsycl.

---------

Signed-off-by: Byoungro So <byoungro.so@intel.com>
Co-authored-by: Alexey Bader <alexey.bader@intel.com>
Co-authored-by: Victor Perez <victor.perez@intel.com>
Co-authored-by: Julian Oppermann <julian.oppermann@codeplay.com>
Co-authored-by: aelovikov-intel <andrei.elovikov@intel.com>
Co-authored-by: Sergey Semenov <sergey.semenov@intel.com>
  • Loading branch information
6 people committed Mar 1, 2024
1 parent f639a20 commit 459e122
Show file tree
Hide file tree
Showing 16 changed files with 467 additions and 75 deletions.
72 changes: 72 additions & 0 deletions sycl/include/sycl/detail/string.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//==----------------- string.hpp - SYCL standard header file ---------------==//
//
// 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 <cstring>
#include <string>

#pragma once

namespace sycl {
inline namespace _V1 {
namespace detail {

// This class and detail::string_view class are intended to support
// different ABIs between libsycl and the user program.
// This class is not inteded to replace std::string for general purpose usage.
class string {
char *str = nullptr;

public:
string() noexcept = default;
~string() { delete[] str; }

string(std::string_view strn) {
size_t len = strn.length();
str = new char[len + 1];
strn.copy(str, len);
str[len] = 0;
}

friend void swap(string &lhs, string &rhs) noexcept {
std::swap(lhs.str, rhs.str);
}

string(string &&other) noexcept { swap(*this, other); }
string(const string &other) {
if (other.str == nullptr)
return;
*this = string{other.str};
}

string &operator=(string &&other) noexcept {
swap(*this, other);
return *this;
}
string &operator=(const string &other) {
*this = string{other};
return *this;
}

string &operator=(std::string_view strn) {
*this = string{strn};
return *this;
}

const char *c_str() const noexcept { return str ? str : ""; }

friend bool operator==(const string &lhs, std::string_view rhs) noexcept {
return rhs == lhs.c_str();
}
friend bool operator==(std::string_view lhs, const string &rhs) noexcept {
return lhs == rhs.c_str();
}
};

} // namespace detail
} // namespace _V1
} // namespace sycl
52 changes: 52 additions & 0 deletions sycl/include/sycl/detail/string_view.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//==-------------- string_view.hpp - SYCL standard header file -------------==//
//
// 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 <string>

#pragma once

namespace sycl {
inline namespace _V1 {
namespace detail {

// This class and detail::string class are intended to support
// different ABIs between libsycl and the user program.
// This class is not inteded to replace std::string_view for general purpose
// usage.
class string_view {
const char *str = nullptr;

public:
string_view() noexcept = default;
string_view(const string_view &strn) noexcept = default;
string_view(string_view &&strn) noexcept = default;
string_view(std::string_view strn) noexcept : str(strn.data()) {}

string_view &operator=(string_view &&strn) noexcept = default;
string_view &operator=(const string_view &strn) noexcept = default;

string_view &operator=(std::string_view strn) noexcept {
str = strn.data();
return *this;
}

const char *data() const noexcept { return str; }

friend bool operator==(const string_view &lhs,
std::string_view rhs) noexcept {
return rhs == lhs.data();
}
friend bool operator==(std::string_view lhs,
const string_view &rhs) noexcept {
return lhs == rhs.data();
}
};

} // namespace detail
} // namespace _V1
} // namespace sycl
24 changes: 23 additions & 1 deletion sycl/include/sycl/detail/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
#ifndef __SYCL_DEVICE_ONLY

#include <sycl/detail/defines.hpp>

#ifdef __INTEL_PREVIEW_BREAKING_CHANGES
#include <sycl/detail/string.hpp>
#endif
#include <cstring>
#include <mutex>
#include <vector>
Expand Down Expand Up @@ -67,6 +69,26 @@ struct CmpCStr {

using SerializedObj = std::vector<unsigned char>;

#ifdef __INTEL_PREVIEW_BREAKING_CHANGES
template <typename T> struct ABINeutralT { using type = T; };
// We need special handling of std::string to handle ABI incompatibility
// for get_info<>() when it returns std::string and vector<std::string>.
// For this purpose, get_info_impl<>() is created to handle special
// cases, and it is only called internally and not exposed to the user.
// The following ReturnType structure is intended for general return type,
// and special return types (std::string and vector of it).

template <> struct ABINeutralT<std::string> { using type = detail::string; };

template <> struct ABINeutralT<std::vector<std::string>> {
using type = std::vector<detail::string>;
};

template <typename T> using ABINeutralT_t = typename ABINeutralT<T>::type;
#else
template <typename T> using ABINeutralT_t = T;
#endif

} // namespace detail
} // namespace _V1
} // namespace sycl
Expand Down
60 changes: 41 additions & 19 deletions sycl/include/sycl/device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,30 @@

#pragma once

#include <sycl/aspects.hpp> // for aspect
#include <sycl/backend_types.hpp> // for backend
#include <sycl/detail/defines_elementary.hpp> // for __SY...
#include <sycl/detail/export.hpp> // for __SY...
#include <sycl/detail/info_desc_helpers.hpp> // for is_d...
#include <sycl/detail/owner_less_base.hpp> // for Owne...
#include <sycl/detail/pi.h> // for pi_n...
#include <sycl/device_selector.hpp> // for Enab...
#include <sycl/ext/oneapi/experimental/device_architecture.hpp> // for arch...
#include <sycl/info/info_desc.hpp> // for part...
#include <sycl/platform.hpp> // for plat...

#include <cstddef> // for size_t
#include <memory> // for shar...
#include <string> // for string
#include <type_traits> // for add_...
#include <variant> // for hash
#include <vector> // for vector
#include <sycl/aspects.hpp>
#include <sycl/backend_types.hpp>
#include <sycl/detail/defines_elementary.hpp>
#include <sycl/detail/export.hpp>
#include <sycl/detail/info_desc_helpers.hpp>
#include <sycl/detail/owner_less_base.hpp>
#include <sycl/detail/pi.h>
#ifdef __INTEL_PREVIEW_BREAKING_CHANGES
#include <sycl/detail/string.hpp>
#include <sycl/detail/string_view.hpp>
#endif
#include <sycl/detail/util.hpp>
#include <sycl/device_selector.hpp>
#include <sycl/ext/oneapi/experimental/device_architecture.hpp>
#include <sycl/info/info_desc.hpp>
#include <sycl/platform.hpp>

#include <cstddef>
#include <memory>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <variant>
#include <vector>

namespace sycl {
inline namespace _V1 {
Expand Down Expand Up @@ -214,8 +220,17 @@ class __SYCL_EXPORT device : public detail::OwnerLessBase<device> {
/// type associated with the param parameter.
///
/// \return device info of type described in Table 4.20.
#ifdef __INTEL_PREVIEW_BREAKING_CHANGES
template <typename Param>
typename detail::is_device_info_desc<Param>::return_type get_info() const {
return detail::convert_from_abi_neutral(get_info_impl<Param>());
}
#else
template <typename Param>
typename detail::is_device_info_desc<Param>::return_type get_info() const;
detail::ABINeutralT_t<
typename detail::is_device_info_desc<Param>::return_type>
get_info() const;
#endif

/// Check SYCL extension support by device
///
Expand Down Expand Up @@ -291,6 +306,13 @@ class __SYCL_EXPORT device : public detail::OwnerLessBase<device> {
template <backend BackendName, class SyclObjectT>
friend auto get_native(const SyclObjectT &Obj)
-> backend_return_t<BackendName, SyclObjectT>;

#ifdef __INTEL_PREVIEW_BREAKING_CHANGES
template <typename Param>
typename detail::ABINeutralT_t<
typename detail::is_device_info_desc<Param>::return_type>
get_info_impl() const;
#endif
};

} // namespace _V1
Expand Down
42 changes: 30 additions & 12 deletions sycl/include/sycl/exception.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,21 @@ class __SYCL_EXPORT exception : public virtual std::exception {

exception(std::error_code, const char *Msg);

#ifdef __INTEL_PREVIEW_BREAKING_CHANGES
exception(std::error_code Ec, const std::string &Msg)
: exception(Ec, nullptr, Msg.c_str()) {}
#else
exception(std::error_code, const std::string &Msg);
#endif

// new SYCL 2020 constructors
exception(std::error_code);
#ifdef __INTEL_PREVIEW_BREAKING_CHANGES
exception(int EV, const std::error_category &ECat, const std::string &WhatArg)
: exception(EV, ECat, WhatArg.c_str()) {}
#else
exception(int, const std::error_category &, const std::string &);
#endif
exception(int, const std::error_category &, const char *);
exception(int, const std::error_category &);

Expand Down Expand Up @@ -111,24 +121,32 @@ class __SYCL_EXPORT exception : public virtual std::exception {

protected:
// base constructors used by SYCL 1.2.1 exception subclasses
exception(std::error_code ec, const char *Msg, const pi_int32 PIErr,
exception(std::error_code Ec, const char *Msg, const pi_int32 PIErr,
std::shared_ptr<context> Context = nullptr)
: exception(ec, std::string(Msg), PIErr, Context) {}
: exception(Ec, std::string(Msg), PIErr, Context) {}

exception(std::error_code ec, const std::string &Msg, const pi_int32 PIErr,
exception(std::error_code Ec, const std::string &Msg, const pi_int32 PIErr,
std::shared_ptr<context> Context = nullptr)
: exception(ec, Context, Msg + " " + detail::codeToString(PIErr)) {
: exception(Ec, Context, Msg + " " + detail::codeToString(PIErr)) {
MPIErr = PIErr;
}

exception(const std::string &Msg)
: MMsg(std::make_shared<std::string>(Msg)), MContext(nullptr) {}

// base constructor for all SYCL 2020 constructors
// exception(context *ctxPtr, std::error_code ec, const std::string
// exception(context *ctxPtr, std::error_code Ec, const std::string
// &what_arg);
exception(std::error_code ec, std::shared_ptr<context> SharedPtrCtx,
#ifdef __INTEL_PREVIEW_BREAKING_CHANGES
exception(std::error_code Ec, std::shared_ptr<context> SharedPtrCtx,
const std::string &what_arg)
: exception(Ec, SharedPtrCtx, what_arg.c_str()) {}
exception(std::error_code Ec, std::shared_ptr<context> SharedPtrCtx,
const char *WhatArg);
#else
exception(std::error_code Ec, std::shared_ptr<context> SharedPtrCtx,
const std::string &what_arg);
#endif
};

class __SYCL2020_DEPRECATED(
Expand All @@ -143,12 +161,12 @@ class __SYCL2020_DEPRECATED(
runtime_error(const std::string &Msg, pi_int32 Err)
: exception(make_error_code(errc::runtime), Msg, Err) {}

runtime_error(std::error_code ec, const std::string &Msg,
runtime_error(std::error_code Ec, const std::string &Msg,
const pi_int32 PIErr)
: exception(ec, Msg, PIErr) {}
: exception(Ec, Msg, PIErr) {}

protected:
runtime_error(std::error_code ec) : exception(ec) {}
runtime_error(std::error_code Ec) : exception(Ec) {}
};

class __SYCL2020_DEPRECATED("use sycl::exception with sycl::errc::kernel or "
Expand Down Expand Up @@ -230,10 +248,10 @@ class __SYCL2020_DEPRECATED(
: exception(make_error_code(errc::invalid), Msg, Err) {}

protected:
device_error(std::error_code ec) : exception(ec) {}
device_error(std::error_code Ec) : exception(Ec) {}

device_error(std::error_code ec, const std::string &Msg, const pi_int32 PIErr)
: exception(ec, Msg, PIErr) {}
device_error(std::error_code Ec, const std::string &Msg, const pi_int32 PIErr)
: exception(Ec, Msg, PIErr) {}
};

class __SYCL2020_DEPRECATED(
Expand Down
Loading

0 comments on commit 459e122

Please sign in to comment.