[llvm] [SYCL] Add platform enumeration and info query using liboffload (PR #166927)

Kseniya Tikhomirova via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 12 06:30:14 PST 2025


https://github.com/KseniyaTikhomirova updated https://github.com/llvm/llvm-project/pull/166927

>From b22192afdcbda7441e7a8fe7cbc9a06903e9e6ea Mon Sep 17 00:00:00 2001
From: Kseniya Tikhomirova <kseniya.tikhomirova at intel.com>
Date: Fri, 7 Nov 2025 12:36:59 +0100
Subject: [PATCH 01/16] [SYCL] Add platform enumeration and info query using
 liboffload (#2)

This is part of the SYCL support upstreaming effort. The relevant RFCs can
be found here:

https://discourse.llvm.org/t/rfc-add-full-support-for-the-sycl-programming-model/74080
https://discourse.llvm.org/t/rfc-sycl-runtime-upstreaming/74479

The SYCL runtime is device-agnostic and uses liboffload for offloading to GPU.
This commit adds a dependency on liboffload, implementation of platform::get_platforms, platform::get_backend and platform::get_info methods, initial implementation of sycl-ls tool for manual testing of added functionality.

Plan for next PR:

device/context impl, rest of platform
test infrastructure (depends on L0 liboffload plugin CI, our effort is joined)
ABI tests
---
 libsycl/CMakeLists.txt                        |  18 ++-
 libsycl/docs/index.rst                        |  12 +-
 libsycl/include/sycl/__impl/backend.hpp       |  70 +++++++++++
 libsycl/include/sycl/__impl/detail/config.hpp |   4 +-
 .../sycl/__impl/detail/macro_definitions.hpp  |  52 ++++++++
 .../include/sycl/__impl/detail/obj_base.hpp   |  64 ++++++++++
 libsycl/include/sycl/__impl/exception.hpp     | 116 ++++++++++++++++++
 libsycl/include/sycl/__impl/info/platform.def |   8 ++
 libsycl/include/sycl/__impl/info/platform.hpp |  54 ++++++++
 libsycl/include/sycl/__impl/platform.hpp      |  87 ++++++++++++-
 libsycl/include/sycl/sycl.hpp                 |   1 +
 libsycl/src/CMakeLists.txt                    |  29 ++---
 libsycl/src/detail/global_objects.cpp         |  73 +++++++++++
 libsycl/src/detail/global_objects.hpp         |  33 +++++
 libsycl/src/detail/offload/info_code.hpp      |  30 +++++
 .../src/detail/offload/offload_topology.cpp   |  79 ++++++++++++
 .../src/detail/offload/offload_topology.hpp   | 101 +++++++++++++++
 libsycl/src/detail/offload/offload_utils.cpp  |  65 ++++++++++
 libsycl/src/detail/offload/offload_utils.hpp  |  59 +++++++++
 libsycl/src/detail/platform_impl.cpp          |  65 ++++++++++
 libsycl/src/detail/platform_impl.hpp          | 102 +++++++++++++++
 libsycl/src/exception.cpp                     |  57 +++++++++
 libsycl/src/exception_list.cpp                |  27 ++++
 libsycl/src/platform.cpp                      |  21 +++-
 libsycl/tools/CMakeLists.txt                  |   1 +
 libsycl/tools/sycl-ls/CMakeLists.txt          |  25 ++++
 libsycl/tools/sycl-ls/sycl-ls.cpp             |  70 +++++++++++
 27 files changed, 1292 insertions(+), 31 deletions(-)
 create mode 100644 libsycl/include/sycl/__impl/backend.hpp
 create mode 100644 libsycl/include/sycl/__impl/detail/macro_definitions.hpp
 create mode 100644 libsycl/include/sycl/__impl/detail/obj_base.hpp
 create mode 100644 libsycl/include/sycl/__impl/exception.hpp
 create mode 100644 libsycl/include/sycl/__impl/info/platform.def
 create mode 100644 libsycl/include/sycl/__impl/info/platform.hpp
 create mode 100644 libsycl/src/detail/global_objects.cpp
 create mode 100644 libsycl/src/detail/global_objects.hpp
 create mode 100644 libsycl/src/detail/offload/info_code.hpp
 create mode 100644 libsycl/src/detail/offload/offload_topology.cpp
 create mode 100644 libsycl/src/detail/offload/offload_topology.hpp
 create mode 100644 libsycl/src/detail/offload/offload_utils.cpp
 create mode 100644 libsycl/src/detail/offload/offload_utils.hpp
 create mode 100644 libsycl/src/detail/platform_impl.cpp
 create mode 100644 libsycl/src/detail/platform_impl.hpp
 create mode 100644 libsycl/src/exception.cpp
 create mode 100644 libsycl/src/exception_list.cpp
 create mode 100644 libsycl/tools/CMakeLists.txt
 create mode 100644 libsycl/tools/sycl-ls/CMakeLists.txt
 create mode 100644 libsycl/tools/sycl-ls/sycl-ls.cpp

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 <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) {
+  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 <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 {
+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);
+};
+
+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
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 <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;
+  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
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 <sycl/__impl/detail/config.hpp>
+
+#include <string>
+
+_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 <sycl/__impl/info/platform.def>
+
+#undef __SYCL_PARAM_TRAITS_SPEC
+} // namespace platform
+} // namespace info
+
+namespace detail {
+template <typename T> struct is_platform_info_desc : std::false_type {};
+
+#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, OffloadCode)         \
+  template <>                                                                  \
+  struct is_##DescType##_info_desc<info::DescType::Desc> : std::true_type {    \
+    using return_type = info::DescType::Desc::return_type;                     \
+  };
+
+#include <sycl/__impl/info/platform.def>
+
+#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 <sycl/__impl/backend.hpp>
 #include <sycl/__impl/detail/config.hpp>
+#include <sycl/__impl/detail/obj_base.hpp>
+#include <sycl/__impl/info/platform.hpp>
+
+#include <memory>
+#include <vector>
 
 _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<detail::platform_impl, platform> {
 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 <typename DeviceSelector>
+  // 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<device>
+  //     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 Param>
+  typename detail::is_platform_info_desc<Param>::return_type get_info() const {
+    return get_info_impl<Param>();
+  }
+
+  // template <typename Param>
+  // typename detail::is_backend_info_desc<Param>::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<platform> get_platforms();
+
+private:
+  platform(detail::platform_impl &Impl) : ObjBase(Impl) {}
+
+  template <typename Param>
+  typename detail::is_platform_info_desc<Param>::return_type
+  get_info_impl() const;
 
+  friend detail::ObjBase<detail::platform_impl, platform>;
 }; // 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 <sycl/__impl/exception.hpp>
 #include <sycl/__impl/platform.hpp>
 
 #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 <detail/global_objects.hpp>
+#include <detail/platform_impl.hpp>
+
+#ifdef _WIN32
+#  include <windows.h>
+#endif
+
+#include <vector>
+
+_LIBSYCL_BEGIN_NAMESPACE_SYCL
+namespace detail {
+
+std::vector<detail::OffloadTopology> &getOffloadTopologies() {
+  static std::vector<detail::OffloadTopology> Topologies(
+      OL_PLATFORM_BACKEND_LAST);
+  return Topologies;
+}
+
+std::vector<std::unique_ptr<platform_impl>> &getPlatformCache() {
+  static std::vector<std::unique_ptr<platform_impl>> 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 <detail/offload/offload_topology.hpp>
+#include <sycl/__impl/detail/config.hpp>
+
+#include <memory>
+#include <mutex>
+#include <vector>
+
+_LIBSYCL_BEGIN_NAMESPACE_SYCL
+
+namespace detail {
+class platform_impl;
+
+// Offload topologies (one per backend) discovered from liboffload.
+std::vector<detail::OffloadTopology> &getOffloadTopologies();
+
+std::mutex &getPlatformMapMutex();
+std::vector<std::unique_ptr<platform_impl>> &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 <OffloadAPI.h>
+
+namespace detail {
+template <typename T> struct OffloadInfoCode;
+
+#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, OffloadCode)         \
+  template <> struct OffloadInfoCode<info::DescType::Desc> {                   \
+    static constexpr auto value = OffloadCode;                                 \
+  };
+#include <sycl/__impl/info/platform.def>
+#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 <detail/global_objects.hpp>
+#include <detail/offload/offload_topology.hpp>
+#include <detail/offload/offload_utils.hpp>
+
+#include <array>
+#include <unordered_map>
+
+_LIBSYCL_BEGIN_NAMESPACE_SYCL
+
+namespace detail {
+
+void discoverOffloadDevices() {
+  [[maybe_unused]] static auto DiscoverOnce = [&]() {
+    call_and_throw(olInit);
+
+    using PerBackendDataType =
+        std::array<std::pair<PlatformWithDevStorageType, size_t /*DevCount*/>,
+                   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<PerBackendDataType *>(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<size_t>(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<ol_platform_backend_t>(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 <sycl/__impl/detail/config.hpp>
+
+#include <OffloadAPI.h>
+
+#include <cassert>
+#include <unordered_map>
+#include <vector>
+
+_LIBSYCL_BEGIN_NAMESPACE_SYCL
+
+namespace detail {
+
+// Minimal span-like view
+template <class T> 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<ol_platform_handle_t, std::vector<ol_device_handle_t>>;
+
+// 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<ol_platform_handle_t> platforms() const {
+    return {MPlatforms.data(), MPlatforms.size()};
+  }
+
+  // Devices for a specific platform (platform_id is index into Platforms)
+  range_view<ol_device_handle_t> 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<ol_device_handle_t> 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<ol_platform_handle_t> MPlatforms;
+  std::vector<ol_device_handle_t> MDevices; // sorted by platform
+
+  // Vector holding range of devices for each platform (index is platform index
+  // within Platforms)
+  std::vector<range_view<ol_device_handle_t>>
+      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 <detail/offload/offload_utils.hpp>
+
+_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 <sycl/__impl/backend.hpp>
+#include <sycl/__impl/detail/config.hpp>
+#include <sycl/__impl/exception.hpp>
+
+#include <OffloadAPI.h>
+
+_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 <sycl::errc errc = sycl::errc::runtime>
+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 <typename FunctionType, typename... ArgsT>
+ol_result_t call_nocheck(FunctionType &Function, ArgsT &&...Args) {
+  return Function(std::forward<ArgsT>(Args)...);
+}
+
+/// Calls the API & checks the result
+///
+/// \throw sycl::runtime_exception if the call was not successful.
+template <typename FunctionType, typename... ArgsT>
+void call_and_throw(FunctionType &Function, ArgsT &&...Args) {
+  auto Err = call_nocheck(Function, std::forward<ArgsT>(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 <sycl/__impl/detail/config.hpp>
+#include <sycl/__impl/detail/obj_base.hpp>
+
+#include <detail/global_objects.hpp>
+#include <detail/platform_impl.hpp>
+
+_LIBSYCL_BEGIN_NAMESPACE_SYCL
+
+namespace detail {
+
+platform_impl *
+platform_impl::getOrMakePlatformImpl(ol_platform_handle_t Platform,
+                                     size_t PlatformIndex) {
+  const std::lock_guard<std::mutex> Guard(getPlatformMapMutex());
+
+  std::vector<std::unique_ptr<platform_impl>> &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<platform_impl> Result;
+  Result = std::make_unique<platform_impl>(Platform, PlatformIndex);
+  PlatformCache.emplace_back(std::move(Result));
+
+  return PlatformCache.back().get();
+}
+
+std::vector<platform> platform_impl::getPlatforms() {
+  discoverOffloadDevices();
+  std::vector<platform> Platforms;
+  for (const auto &Topo : getOffloadTopologies()) {
+    size_t PlatformIndex = 0;
+    for (const auto &OffloadPlatform : Topo.platforms()) {
+      platform Platform = detail::createSyclObjFromImpl<platform>(
+          *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 <sycl/__impl/backend.hpp>
+#include <sycl/__impl/detail/config.hpp>
+#include <sycl/__impl/platform.hpp>
+
+#include "detail/offload/info_code.hpp"
+#include "detail/offload/offload_utils.hpp"
+
+#include <OffloadAPI.h>
+
+#include <memory>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+_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<platform> 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> typename Param::return_type get_info() const {
+    // for now we have only std::string properties
+    static_assert(std::is_same_v<typename Param::return_type, std::string>);
+    size_t ExpectedSize = 0;
+    call_and_throw(olGetPlatformInfoSize, MOffloadPlatform,
+                   detail::OffloadInfoCode<Param>::value, &ExpectedSize);
+    std::string Result;
+    Result.resize(ExpectedSize - 1);
+    call_and_throw(olGetPlatformInfo, MOffloadPlatform,
+                   detail::OffloadInfoCode<Param>::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 <sycl/__impl/detail/config.hpp>
+#include <sycl/__impl/exception.hpp>
+
+_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<int>(Err), sycl_category());
+}
+
+// Exception methods implementation
+exception::exception(std::error_code EC, const char *Msg)
+    : MMessage(std::make_shared<std::string>(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 <sycl/__impl/detail/config.hpp>
+#include <sycl/__impl/exception.hpp>
+
+_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 <sycl/__impl/platform.hpp>
 
+#include <detail/platform_impl.hpp>
+
 #include <stdexcept>
 
 _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
-platform::platform() { throw std::runtime_error("Unimplemented"); }
+backend platform::get_backend() const noexcept { return impl.getBackend(); }
+
+std::vector<platform> platform::get_platforms() {
+  return detail::platform_impl::getPlatforms();
+}
+
+template <typename Param>
+typename detail::is_platform_info_desc<Param>::return_type
+platform::get_info_impl() const {
+  return impl.template get_info<Param>();
+}
+
+#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, OffloadCode)         \
+  template _LIBSYCL_EXPORT ReturnT                                             \
+  platform::get_info_impl<info::platform::Desc>() const;
+
+#include <sycl/__impl/info/platform.def>
+#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 <sycl/sycl.hpp>
+
+#include "llvm/Support/CommandLine.h"
+
+#include <iostream>
+
+using namespace sycl;
+using namespace std::literals;
+
+int main(int argc, char **argv) {
+  llvm::cl::opt<bool> 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<info::platform::version>();
+        auto PlatformName = Platform.get_info<info::platform::name>();
+        auto PlatformVendor = Platform.get_info<info::platform::vendor>();
+        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;
+}

>From bcb27113006043db629942ce7cd6eb9afbe593ff Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Tue, 18 Nov 2025 05:03:39 -0800
Subject: [PATCH 02/16] add partial spec and base for std::hash support

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 .../include/sycl/__impl/detail/obj_base.hpp   | 20 +++++++++++++++++--
 libsycl/include/sycl/__impl/platform.hpp      |  8 ++++++--
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/libsycl/include/sycl/__impl/detail/obj_base.hpp b/libsycl/include/sycl/__impl/detail/obj_base.hpp
index d0314bbdbf767..0ccbde1de6059 100644
--- a/libsycl/include/sycl/__impl/detail/obj_base.hpp
+++ b/libsycl/include/sycl/__impl/detail/obj_base.hpp
@@ -18,6 +18,7 @@
 #include <sycl/__impl/detail/config.hpp>
 
 #include <cassert>
+#include <optional>
 #include <type_traits>
 #include <utility>
 
@@ -25,10 +26,12 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
 namespace detail {
 
-template <class Impl, class SyclObject> class ObjBase {
+template <typename Impl, typename SyclObject> class ObjBase;
+template <typename Impl, typename SyclObject>
+class ObjBase<Impl &, SyclObject> {
 public:
   using ImplType = Impl;
-  using Base = ObjBase<Impl, SyclObject>;
+  using Base = ObjBase<Impl &, SyclObject>;
 
 protected:
   ImplType &impl;
@@ -57,6 +60,19 @@ Obj createSyclObjFromImpl(
   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
diff --git a/libsycl/include/sycl/__impl/platform.hpp b/libsycl/include/sycl/__impl/platform.hpp
index b54c339208e84..85182e7d52a68 100644
--- a/libsycl/include/sycl/__impl/platform.hpp
+++ b/libsycl/include/sycl/__impl/platform.hpp
@@ -31,7 +31,7 @@ class platform_impl;
 
 // 4.6.2. Platform class
 class _LIBSYCL_EXPORT platform
-    : public detail::ObjBase<detail::platform_impl, platform> {
+    : public detail::ObjBase<detail::platform_impl &, platform> {
 public:
   /// Constructs a platform object that is a copy of the platform which contains
   /// the device returned by default_selector_v.
@@ -104,9 +104,13 @@ class _LIBSYCL_EXPORT platform
   typename detail::is_platform_info_desc<Param>::return_type
   get_info_impl() const;
 
-  friend detail::ObjBase<detail::platform_impl, platform>;
+  friend detail::ObjBase<detail::platform_impl &, platform>;
 }; // class platform
 
 _LIBSYCL_END_NAMESPACE_SYCL
 
+template <>
+struct std::hash<sycl::platform>
+    : public sycl::detail::HashBase<sycl::platform> {};
+
 #endif // _LIBSYCL___IMPL_PLATFORM_HPP

>From b15b6c09f1090f53deef483a8cf41cdcd173ec51 Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Wed, 19 Nov 2025 05:43:55 -0800
Subject: [PATCH 03/16] fix comments

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/include/sycl/__impl/backend.hpp  |  1 +
 libsycl/include/sycl/__impl/platform.hpp |  8 +-------
 libsycl/src/detail/platform_impl.hpp     |  4 ++--
 libsycl/src/platform.cpp                 | 11 +++++------
 4 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/libsycl/include/sycl/__impl/backend.hpp b/libsycl/include/sycl/__impl/backend.hpp
index bc361e487af69..4b467f50cce5f 100644
--- a/libsycl/include/sycl/__impl/backend.hpp
+++ b/libsycl/include/sycl/__impl/backend.hpp
@@ -47,6 +47,7 @@ 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) {
   switch (Backend) {
   case backend::opencl:
diff --git a/libsycl/include/sycl/__impl/platform.hpp b/libsycl/include/sycl/__impl/platform.hpp
index 85182e7d52a68..3e3fb3fb9facf 100644
--- a/libsycl/include/sycl/__impl/platform.hpp
+++ b/libsycl/include/sycl/__impl/platform.hpp
@@ -64,9 +64,7 @@ class _LIBSYCL_EXPORT platform
   ///
   /// The return type depends on information being queried.
   template <typename Param>
-  typename detail::is_platform_info_desc<Param>::return_type get_info() const {
-    return get_info_impl<Param>();
-  }
+  typename detail::is_platform_info_desc<Param>::return_type get_info() const;
 
   // template <typename Param>
   // typename detail::is_backend_info_desc<Param>::return_type
@@ -100,10 +98,6 @@ class _LIBSYCL_EXPORT platform
 private:
   platform(detail::platform_impl &Impl) : ObjBase(Impl) {}
 
-  template <typename Param>
-  typename detail::is_platform_info_desc<Param>::return_type
-  get_info_impl() const;
-
   friend detail::ObjBase<detail::platform_impl &, platform>;
 }; // class platform
 
diff --git a/libsycl/src/detail/platform_impl.hpp b/libsycl/src/detail/platform_impl.hpp
index 45a1cf37c1d3b..1d7301d4687df 100644
--- a/libsycl/src/detail/platform_impl.hpp
+++ b/libsycl/src/detail/platform_impl.hpp
@@ -13,8 +13,8 @@
 #include <sycl/__impl/detail/config.hpp>
 #include <sycl/__impl/platform.hpp>
 
-#include "detail/offload/info_code.hpp"
-#include "detail/offload/offload_utils.hpp"
+#include <detail/offload/info_code.hpp>
+#include <detail/offload/offload_utils.hpp>
 
 #include <OffloadAPI.h>
 
diff --git a/libsycl/src/platform.cpp b/libsycl/src/platform.cpp
index 1dc42a3f39b87..48d19148beb58 100644
--- a/libsycl/src/platform.cpp
+++ b/libsycl/src/platform.cpp
@@ -22,14 +22,13 @@ std::vector<platform> platform::get_platforms() {
 
 template <typename Param>
 typename detail::is_platform_info_desc<Param>::return_type
-platform::get_info_impl() const {
-  return impl.template get_info<Param>();
+platform::get_info() const {
+  return impl.get_info<Param>();
 }
 
-#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, OffloadCode)         \
-  template _LIBSYCL_EXPORT ReturnT                                             \
-  platform::get_info_impl<info::platform::Desc>() const;
-
+#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, PiCode)              \
+  template _LIBSYCL_EXPORT ReturnT platform::get_info<info::platform::Desc>()  \
+      const;
 #include <sycl/__impl/info/platform.def>
 #undef __SYCL_PARAM_TRAITS_SPEC
 

>From 88d313c48f009086708ebba03ae989825c7b3e2d Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Wed, 19 Nov 2025 11:31:37 -0800
Subject: [PATCH 04/16] early init of platforms

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/src/detail/common.hpp                 | 34 +++++++
 libsycl/src/detail/global_objects.cpp         |  5 --
 libsycl/src/detail/global_objects.hpp         |  1 -
 .../src/detail/offload/offload_topology.cpp   | 89 +++++++++----------
 .../src/detail/offload/offload_topology.hpp   | 12 +--
 libsycl/src/detail/platform_impl.cpp          | 46 ++++------
 libsycl/src/detail/platform_impl.hpp          | 10 +--
 libsycl/src/platform.cpp                      |  9 +-
 8 files changed, 110 insertions(+), 96 deletions(-)
 create mode 100644 libsycl/src/detail/common.hpp

diff --git a/libsycl/src/detail/common.hpp b/libsycl/src/detail/common.hpp
new file mode 100644
index 0000000000000..e47c231f9ab81
--- /dev/null
+++ b/libsycl/src/detail/common.hpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COMMON
+#define _LIBSYCL_COMMON
+
+#include <sycl/__impl/detail/config.hpp>
+
+#include <cstddef>
+
+_LIBSYCL_BEGIN_NAMESPACE_SYCL
+
+namespace detail {
+
+// Minimal span-like view
+template <class T> 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; }
+};
+
+} // namespace detail
+
+_LIBSYCL_END_NAMESPACE_SYCL
+
+#endif // _LIBSYCL_COMMON
diff --git a/libsycl/src/detail/global_objects.cpp b/libsycl/src/detail/global_objects.cpp
index 1dbb7074ed453..e48eb9d9d0ae9 100644
--- a/libsycl/src/detail/global_objects.cpp
+++ b/libsycl/src/detail/global_objects.cpp
@@ -29,11 +29,6 @@ std::vector<std::unique_ptr<platform_impl>> &getPlatformCache() {
   return PlatformCache;
 }
 
-std::mutex &getPlatformMapMutex() {
-  static std::mutex PlatformMapMutex{};
-  return PlatformMapMutex;
-}
-
 void shutdown() {
   // No error reporting in shutdown
   std::ignore = olShutDown();
diff --git a/libsycl/src/detail/global_objects.hpp b/libsycl/src/detail/global_objects.hpp
index 57deee4e5529b..81899623aed68 100644
--- a/libsycl/src/detail/global_objects.hpp
+++ b/libsycl/src/detail/global_objects.hpp
@@ -24,7 +24,6 @@ class platform_impl;
 // Offload topologies (one per backend) discovered from liboffload.
 std::vector<detail::OffloadTopology> &getOffloadTopologies();
 
-std::mutex &getPlatformMapMutex();
 std::vector<std::unique_ptr<platform_impl>> &getPlatformCache();
 
 } // namespace detail
diff --git a/libsycl/src/detail/offload/offload_topology.cpp b/libsycl/src/detail/offload/offload_topology.cpp
index 8a85ab477b885..c1509a39263e0 100644
--- a/libsycl/src/detail/offload/offload_topology.cpp
+++ b/libsycl/src/detail/offload/offload_topology.cpp
@@ -18,60 +18,55 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL
 namespace detail {
 
 void discoverOffloadDevices() {
-  [[maybe_unused]] static auto DiscoverOnce = [&]() {
-    call_and_throw(olInit);
+  call_and_throw(olInit);
 
-    using PerBackendDataType =
-        std::array<std::pair<PlatformWithDevStorageType, size_t /*DevCount*/>,
-                   OL_PLATFORM_BACKEND_LAST>;
+  using PerBackendDataType =
+      std::array<std::pair<PlatformWithDevStorageType, size_t /*DevCount*/>,
+                 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<PerBackendDataType *>(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;
+  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<PerBackendDataType *>(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;
 
-          // Skip host & unknown backends
-          if (OL_PLATFORM_BACKEND_HOST == OlBackend ||
-              OL_PLATFORM_BACKEND_UNKNOWN == OlBackend)
-            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;
 
-          // Ensure backend index fits into array size
-          if (OlBackend >= OL_PLATFORM_BACKEND_LAST)
-            return true;
+        // Skip host & unknown backends
+        if (OL_PLATFORM_BACKEND_HOST == OlBackend ||
+            OL_PLATFORM_BACKEND_UNKNOWN == OlBackend)
+          return true;
 
-          auto &[Map, DevCount] = (*Data)[static_cast<size_t>(OlBackend)];
-          Map[Plat].push_back(Dev);
-          DevCount++;
+        // Ensure backend index fits into array size
+        if (OlBackend >= OL_PLATFORM_BACKEND_LAST)
           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<ol_platform_backend_t>(I));
-      Topo.registerNewPlatformsAndDevices(Mapping[I].first, Mapping[I].second);
-    }
 
-    return true;
-  }();
+        auto &[Map, DevCount] = (*Data)[static_cast<size_t>(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<ol_platform_backend_t>(I));
+    Topo.registerNewPlatformsAndDevices(Mapping[I].first, Mapping[I].second);
+  }
 }
 
 } // namespace detail
diff --git a/libsycl/src/detail/offload/offload_topology.hpp b/libsycl/src/detail/offload/offload_topology.hpp
index 3bf2e78c10050..211f6a88a18e6 100644
--- a/libsycl/src/detail/offload/offload_topology.hpp
+++ b/libsycl/src/detail/offload/offload_topology.hpp
@@ -11,6 +11,8 @@
 
 #include <sycl/__impl/detail/config.hpp>
 
+#include <detail/common.hpp>
+
 #include <OffloadAPI.h>
 
 #include <cassert>
@@ -21,16 +23,6 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
 namespace detail {
 
-// Minimal span-like view
-template <class T> 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<ol_platform_handle_t, std::vector<ol_device_handle_t>>;
 
diff --git a/libsycl/src/detail/platform_impl.cpp b/libsycl/src/detail/platform_impl.cpp
index 324ec369cfcec..e282a8bb12912 100644
--- a/libsycl/src/detail/platform_impl.cpp
+++ b/libsycl/src/detail/platform_impl.cpp
@@ -16,40 +16,32 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
 namespace detail {
 
-platform_impl *
-platform_impl::getOrMakePlatformImpl(ol_platform_handle_t Platform,
-                                     size_t PlatformIndex) {
-  const std::lock_guard<std::mutex> Guard(getPlatformMapMutex());
-
-  std::vector<std::unique_ptr<platform_impl>> &PlatformCache =
-      getPlatformCache();
-
-  // If we've already seen this platform, return the impl
+platform_impl *platform_impl::getPlatformImpl(ol_platform_handle_t Platform) {
+  auto &PlatformCache = getPlatformCache();
   for (const auto &PlatImpl : PlatformCache) {
     if (PlatImpl->getHandleRef() == Platform)
       return PlatImpl.get();
   }
-
-  // Otherwise make the impl.
-  std::unique_ptr<platform_impl> Result;
-  Result = std::make_unique<platform_impl>(Platform, PlatformIndex);
-  PlatformCache.emplace_back(std::move(Result));
-
-  return PlatformCache.back().get();
+  assert(false && "All platform_impl objects must be created during initial "
+                  "device & platform discovery");
+  return nullptr;
 }
 
-std::vector<platform> platform_impl::getPlatforms() {
-  discoverOffloadDevices();
-  std::vector<platform> Platforms;
-  for (const auto &Topo : getOffloadTopologies()) {
-    size_t PlatformIndex = 0;
-    for (const auto &OffloadPlatform : Topo.platforms()) {
-      platform Platform = detail::createSyclObjFromImpl<platform>(
-          *getOrMakePlatformImpl(OffloadPlatform, PlatformIndex++));
-      Platforms.push_back(std::move(Platform));
+range_view<std::unique_ptr<platform_impl>> platform_impl::getPlatforms() {
+  [[maybe_unused]] static auto InitPlatformsOnce = []() {
+    discoverOffloadDevices();
+    auto &PlatformCache = getPlatformCache();
+    for (const auto &Topo : getOffloadTopologies()) {
+      size_t PlatformIndex = 0;
+      for (const auto &OffloadPlatform : Topo.platforms()) {
+        PlatformCache.emplace_back(
+            std::make_unique<platform_impl>(OffloadPlatform, PlatformIndex++));
+      }
     }
-  }
-  return Platforms;
+    return true;
+  }();
+  auto &PlatformCache = getPlatformCache();
+  return {PlatformCache.data(), PlatformCache.size()};
 }
 
 platform_impl::platform_impl(ol_platform_handle_t Platform,
diff --git a/libsycl/src/detail/platform_impl.hpp b/libsycl/src/detail/platform_impl.hpp
index 1d7301d4687df..4681cc69799d9 100644
--- a/libsycl/src/detail/platform_impl.hpp
+++ b/libsycl/src/detail/platform_impl.hpp
@@ -13,6 +13,7 @@
 #include <sycl/__impl/detail/config.hpp>
 #include <sycl/__impl/platform.hpp>
 
+#include <detail/common.hpp>
 #include <detail/offload/info_code.hpp>
 #include <detail/offload/offload_utils.hpp>
 
@@ -44,9 +45,9 @@ class platform_impl {
   /// 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<platform> getPlatforms();
+  /// Returns range-view to all SYCL platforms from all backends that are
+  /// available in the system.
+  static range_view<std::unique_ptr<platform_impl>> getPlatforms();
 
   /// Returns raw underlying offload platform handle.
   ///
@@ -69,8 +70,7 @@ class platform_impl {
   /// \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);
+  static platform_impl *getPlatformImpl(ol_platform_handle_t Platform);
 
   /// Queries this SYCL platform for info.
   ///
diff --git a/libsycl/src/platform.cpp b/libsycl/src/platform.cpp
index 48d19148beb58..f2acb7b2afcab 100644
--- a/libsycl/src/platform.cpp
+++ b/libsycl/src/platform.cpp
@@ -17,7 +17,14 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL
 backend platform::get_backend() const noexcept { return impl.getBackend(); }
 
 std::vector<platform> platform::get_platforms() {
-  return detail::platform_impl::getPlatforms();
+  auto PlatformsView = detail::platform_impl::getPlatforms();
+  std::vector<platform> Platforms;
+  for (size_t i = 0; i < PlatformsView.len; i++) {
+    platform Platform =
+        detail::createSyclObjFromImpl<platform>(*PlatformsView.ptr[i].get());
+    Platforms.push_back(std::move(Platform));
+  }
+  return Platforms;
 }
 
 template <typename Param>

>From 849fed99b6b2f603b23faeff0b6fbf3e2f93299c Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Thu, 20 Nov 2025 03:13:37 -0800
Subject: [PATCH 05/16] remove unique_ptr, make ref const, add operator==

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 .../include/sycl/__impl/detail/obj_base.hpp   | 10 +++++-----
 libsycl/include/sycl/__impl/platform.hpp      | 14 +++++++++++++-
 libsycl/src/detail/global_objects.cpp         |  4 ++--
 libsycl/src/detail/global_objects.hpp         |  2 +-
 libsycl/src/detail/platform_impl.cpp          | 19 +++++++++----------
 libsycl/src/detail/platform_impl.hpp          |  4 ++--
 libsycl/src/platform.cpp                      |  5 +++--
 7 files changed, 35 insertions(+), 23 deletions(-)

diff --git a/libsycl/include/sycl/__impl/detail/obj_base.hpp b/libsycl/include/sycl/__impl/detail/obj_base.hpp
index 0ccbde1de6059..eb5af900c1584 100644
--- a/libsycl/include/sycl/__impl/detail/obj_base.hpp
+++ b/libsycl/include/sycl/__impl/detail/obj_base.hpp
@@ -34,19 +34,19 @@ class ObjBase<Impl &, SyclObject> {
   using Base = ObjBase<Impl &, SyclObject>;
 
 protected:
-  ImplType &impl;
+  const ImplType &impl;
 
-  explicit ObjBase(ImplType &pImpl) : impl(pImpl) {}
+  explicit ObjBase(const ImplType &pImpl) : impl(pImpl) {}
   ObjBase() = default;
 
-  static SyclObject createSyclProxy(ImplType &impl) { return SyclObject(impl); }
+  static SyclObject createSyclProxy(const 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);
+      std::add_lvalue_reference_t<const typename Obj::ImplType> ImplObj);
 };
 
 template <class Obj>
@@ -56,7 +56,7 @@ const typename Obj::ImplType &getSyclObjImpl(const Obj &Object) {
 
 template <class Obj>
 Obj createSyclObjFromImpl(
-    std::add_lvalue_reference_t<typename Obj::ImplType> ImplObj) {
+    std::add_lvalue_reference_t<const typename Obj::ImplType> ImplObj) {
   return Obj::Base::createSyclProxy(ImplObj);
 }
 
diff --git a/libsycl/include/sycl/__impl/platform.hpp b/libsycl/include/sycl/__impl/platform.hpp
index 3e3fb3fb9facf..ba30fdcd809c3 100644
--- a/libsycl/include/sycl/__impl/platform.hpp
+++ b/libsycl/include/sycl/__impl/platform.hpp
@@ -37,6 +37,18 @@ class _LIBSYCL_EXPORT platform
   /// the device returned by default_selector_v.
   // platform();
 
+  platform(const platform &rhs) = default;
+
+  platform(platform &&rhs) = default;
+
+  platform &operator=(const platform &rhs) = default;
+
+  platform &operator=(platform &&rhs) = default;
+
+  bool operator==(const platform &rhs) const { return &impl == &rhs.impl; }
+
+  bool operator!=(const platform &rhs) const { return !(*this == rhs); }
+
   /// 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
@@ -96,7 +108,7 @@ class _LIBSYCL_EXPORT platform
   static std::vector<platform> get_platforms();
 
 private:
-  platform(detail::platform_impl &Impl) : ObjBase(Impl) {}
+  platform(const detail::platform_impl &Impl) : ObjBase(Impl) {}
 
   friend detail::ObjBase<detail::platform_impl &, platform>;
 }; // class platform
diff --git a/libsycl/src/detail/global_objects.cpp b/libsycl/src/detail/global_objects.cpp
index e48eb9d9d0ae9..9990b4d27824a 100644
--- a/libsycl/src/detail/global_objects.cpp
+++ b/libsycl/src/detail/global_objects.cpp
@@ -24,8 +24,8 @@ std::vector<detail::OffloadTopology> &getOffloadTopologies() {
   return Topologies;
 }
 
-std::vector<std::unique_ptr<platform_impl>> &getPlatformCache() {
-  static std::vector<std::unique_ptr<platform_impl>> PlatformCache{};
+std::vector<platform_impl> &getPlatformCache() {
+  static std::vector<platform_impl> PlatformCache{};
   return PlatformCache;
 }
 
diff --git a/libsycl/src/detail/global_objects.hpp b/libsycl/src/detail/global_objects.hpp
index 81899623aed68..0b5ac246692bf 100644
--- a/libsycl/src/detail/global_objects.hpp
+++ b/libsycl/src/detail/global_objects.hpp
@@ -24,7 +24,7 @@ class platform_impl;
 // Offload topologies (one per backend) discovered from liboffload.
 std::vector<detail::OffloadTopology> &getOffloadTopologies();
 
-std::vector<std::unique_ptr<platform_impl>> &getPlatformCache();
+std::vector<platform_impl> &getPlatformCache();
 
 } // namespace detail
 _LIBSYCL_END_NAMESPACE_SYCL
diff --git a/libsycl/src/detail/platform_impl.cpp b/libsycl/src/detail/platform_impl.cpp
index e282a8bb12912..37a8be00a5a9d 100644
--- a/libsycl/src/detail/platform_impl.cpp
+++ b/libsycl/src/detail/platform_impl.cpp
@@ -16,26 +16,25 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
 namespace detail {
 
-platform_impl *platform_impl::getPlatformImpl(ol_platform_handle_t Platform) {
+platform_impl& platform_impl::getPlatformImpl(ol_platform_handle_t Platform) {
   auto &PlatformCache = getPlatformCache();
-  for (const auto &PlatImpl : PlatformCache) {
-    if (PlatImpl->getHandleRef() == Platform)
-      return PlatImpl.get();
+  for (auto &PlatImpl : PlatformCache) {
+    if (PlatImpl.getHandleRef() == Platform)
+      return PlatImpl;
   }
-  assert(false && "All platform_impl objects must be created during initial "
-                  "device & platform discovery");
-  return nullptr;
+
+  throw sycl::exception(sycl::make_error_code(sycl::errc::runtime),
+                              "Platform for requested handle can't be created. This handle is not in the list of platforms discovered by liboffload");
 }
 
-range_view<std::unique_ptr<platform_impl>> platform_impl::getPlatforms() {
+range_view<platform_impl> platform_impl::getPlatforms() {
   [[maybe_unused]] static auto InitPlatformsOnce = []() {
     discoverOffloadDevices();
     auto &PlatformCache = getPlatformCache();
     for (const auto &Topo : getOffloadTopologies()) {
       size_t PlatformIndex = 0;
       for (const auto &OffloadPlatform : Topo.platforms()) {
-        PlatformCache.emplace_back(
-            std::make_unique<platform_impl>(OffloadPlatform, PlatformIndex++));
+        PlatformCache.emplace_back(platform_impl(OffloadPlatform, PlatformIndex++));
       }
     }
     return true;
diff --git a/libsycl/src/detail/platform_impl.hpp b/libsycl/src/detail/platform_impl.hpp
index 4681cc69799d9..f794f791d6295 100644
--- a/libsycl/src/detail/platform_impl.hpp
+++ b/libsycl/src/detail/platform_impl.hpp
@@ -47,7 +47,7 @@ class platform_impl {
 
   /// Returns range-view to all SYCL platforms from all backends that are
   /// available in the system.
-  static range_view<std::unique_ptr<platform_impl>> getPlatforms();
+  static range_view<platform_impl> getPlatforms();
 
   /// Returns raw underlying offload platform handle.
   ///
@@ -70,7 +70,7 @@ class platform_impl {
   /// \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 *getPlatformImpl(ol_platform_handle_t Platform);
+  static platform_impl& getPlatformImpl(ol_platform_handle_t Platform);
 
   /// Queries this SYCL platform for info.
   ///
diff --git a/libsycl/src/platform.cpp b/libsycl/src/platform.cpp
index f2acb7b2afcab..66c76d1c6bd73 100644
--- a/libsycl/src/platform.cpp
+++ b/libsycl/src/platform.cpp
@@ -19,9 +19,10 @@ backend platform::get_backend() const noexcept { return impl.getBackend(); }
 std::vector<platform> platform::get_platforms() {
   auto PlatformsView = detail::platform_impl::getPlatforms();
   std::vector<platform> Platforms;
-  for (size_t i = 0; i < PlatformsView.len; i++) {
+  Platforms.reserve(PlatformsView.size());
+  for (size_t i = 0; i < PlatformsView.size(); i++) {
     platform Platform =
-        detail::createSyclObjFromImpl<platform>(*PlatformsView.ptr[i].get());
+        detail::createSyclObjFromImpl<platform>(PlatformsView[i]);
     Platforms.push_back(std::move(Platform));
   }
   return Platforms;

>From 7f62590c2b830b83c81e59d95186565a12bd7072 Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Thu, 20 Nov 2025 03:29:50 -0800
Subject: [PATCH 06/16] fix installation

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/CMakeLists.txt | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libsycl/CMakeLists.txt b/libsycl/CMakeLists.txt
index 54ef3d4b1878a..f25f51def0cc7 100644
--- a/libsycl/CMakeLists.txt
+++ b/libsycl/CMakeLists.txt
@@ -127,10 +127,11 @@ if (CMAKE_SYSTEM_NAME STREQUAL Windows)
   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(src)
+
 add_subdirectory(tools)

>From f081eeaf758558533582b6ba119dcca72b9f0d75 Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Thu, 20 Nov 2025 03:31:07 -0800
Subject: [PATCH 07/16] fix format

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/include/sycl/__impl/detail/obj_base.hpp |  4 +++-
 libsycl/src/detail/platform_impl.cpp            | 11 +++++++----
 libsycl/src/detail/platform_impl.hpp            |  2 +-
 3 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/libsycl/include/sycl/__impl/detail/obj_base.hpp b/libsycl/include/sycl/__impl/detail/obj_base.hpp
index eb5af900c1584..fbeb47a70ebdd 100644
--- a/libsycl/include/sycl/__impl/detail/obj_base.hpp
+++ b/libsycl/include/sycl/__impl/detail/obj_base.hpp
@@ -39,7 +39,9 @@ class ObjBase<Impl &, SyclObject> {
   explicit ObjBase(const ImplType &pImpl) : impl(pImpl) {}
   ObjBase() = default;
 
-  static SyclObject createSyclProxy(const ImplType &impl) { return SyclObject(impl); }
+  static SyclObject createSyclProxy(const ImplType &impl) {
+    return SyclObject(impl);
+  }
 
   template <class Obj>
   friend const typename Obj::ImplType &getSyclObjImpl(const Obj &Object);
diff --git a/libsycl/src/detail/platform_impl.cpp b/libsycl/src/detail/platform_impl.cpp
index 37a8be00a5a9d..6bdb9188732d4 100644
--- a/libsycl/src/detail/platform_impl.cpp
+++ b/libsycl/src/detail/platform_impl.cpp
@@ -16,15 +16,17 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
 namespace detail {
 
-platform_impl& platform_impl::getPlatformImpl(ol_platform_handle_t Platform) {
+platform_impl &platform_impl::getPlatformImpl(ol_platform_handle_t Platform) {
   auto &PlatformCache = getPlatformCache();
   for (auto &PlatImpl : PlatformCache) {
     if (PlatImpl.getHandleRef() == Platform)
       return PlatImpl;
   }
 
-  throw sycl::exception(sycl::make_error_code(sycl::errc::runtime),
-                              "Platform for requested handle can't be created. This handle is not in the list of platforms discovered by liboffload");
+  throw sycl::exception(
+      sycl::make_error_code(sycl::errc::runtime),
+      "Platform for requested handle can't be created. This handle is not in "
+      "the list of platforms discovered by liboffload");
 }
 
 range_view<platform_impl> platform_impl::getPlatforms() {
@@ -34,7 +36,8 @@ range_view<platform_impl> platform_impl::getPlatforms() {
     for (const auto &Topo : getOffloadTopologies()) {
       size_t PlatformIndex = 0;
       for (const auto &OffloadPlatform : Topo.platforms()) {
-        PlatformCache.emplace_back(platform_impl(OffloadPlatform, PlatformIndex++));
+        PlatformCache.emplace_back(
+            platform_impl(OffloadPlatform, PlatformIndex++));
       }
     }
     return true;
diff --git a/libsycl/src/detail/platform_impl.hpp b/libsycl/src/detail/platform_impl.hpp
index f794f791d6295..41ca27ab34b94 100644
--- a/libsycl/src/detail/platform_impl.hpp
+++ b/libsycl/src/detail/platform_impl.hpp
@@ -70,7 +70,7 @@ class platform_impl {
   /// \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& getPlatformImpl(ol_platform_handle_t Platform);
+  static platform_impl &getPlatformImpl(ol_platform_handle_t Platform);
 
   /// Queries this SYCL platform for info.
   ///

>From 2224ab81d3f045b1f4daf9feb64ab0bb7b7a5d8b Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Wed, 26 Nov 2025 04:50:06 -0800
Subject: [PATCH 08/16] remove offload codes from distributed headers

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/include/sycl/__impl/info/platform.def |  6 ++--
 libsycl/include/sycl/__impl/info/platform.hpp |  4 +--
 libsycl/src/detail/offload/info_code.hpp      | 30 -------------------
 libsycl/src/detail/platform_impl.hpp          | 23 ++++++++++----
 libsycl/src/platform.cpp                      |  2 +-
 5 files changed, 23 insertions(+), 42 deletions(-)
 delete mode 100644 libsycl/src/detail/offload/info_code.hpp

diff --git a/libsycl/include/sycl/__impl/info/platform.def b/libsycl/include/sycl/__impl/info/platform.def
index 68835fc3e3640..f4198b610715c 100644
--- a/libsycl/include/sycl/__impl/info/platform.def
+++ b/libsycl/include/sycl/__impl/info/platform.def
@@ -3,6 +3,6 @@ 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)
+__SYCL_PARAM_TRAITS_SPEC(platform, version, std::string)
+__SYCL_PARAM_TRAITS_SPEC(platform, name, std::string)
+__SYCL_PARAM_TRAITS_SPEC(platform, vendor, std::string)
diff --git a/libsycl/include/sycl/__impl/info/platform.hpp b/libsycl/include/sycl/__impl/info/platform.hpp
index d175b66adf570..ceaa818b5ebe4 100644
--- a/libsycl/include/sycl/__impl/info/platform.hpp
+++ b/libsycl/include/sycl/__impl/info/platform.hpp
@@ -23,7 +23,7 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL
 // A.1. Platform information descriptors
 namespace info {
 namespace platform {
-#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, OffloadCode)         \
+#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT)                      \
   struct Desc {                                                                \
     using return_type = ReturnT;                                               \
   };
@@ -38,7 +38,7 @@ namespace platform {
 namespace detail {
 template <typename T> struct is_platform_info_desc : std::false_type {};
 
-#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, OffloadCode)         \
+#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT)                      \
   template <>                                                                  \
   struct is_##DescType##_info_desc<info::DescType::Desc> : std::true_type {    \
     using return_type = info::DescType::Desc::return_type;                     \
diff --git a/libsycl/src/detail/offload/info_code.hpp b/libsycl/src/detail/offload/info_code.hpp
deleted file mode 100644
index a9734d380a7c4..0000000000000
--- a/libsycl/src/detail/offload/info_code.hpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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 <OffloadAPI.h>
-
-namespace detail {
-template <typename T> struct OffloadInfoCode;
-
-#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, OffloadCode)         \
-  template <> struct OffloadInfoCode<info::DescType::Desc> {                   \
-    static constexpr auto value = OffloadCode;                                 \
-  };
-#include <sycl/__impl/info/platform.def>
-#undef __SYCL_PARAM_TRAITS_SPEC
-
-} // namespace detail
-
-_LIBSYCL_END_NAMESPACE_SYCL
-
-#endif // _LIBSYCL_INFO_CODE
diff --git a/libsycl/src/detail/platform_impl.hpp b/libsycl/src/detail/platform_impl.hpp
index 41ca27ab34b94..ebb9ff7fc1e77 100644
--- a/libsycl/src/detail/platform_impl.hpp
+++ b/libsycl/src/detail/platform_impl.hpp
@@ -14,7 +14,6 @@
 #include <sycl/__impl/platform.hpp>
 
 #include <detail/common.hpp>
-#include <detail/offload/info_code.hpp>
 #include <detail/offload/offload_utils.hpp>
 
 #include <OffloadAPI.h>
@@ -72,20 +71,32 @@ class platform_impl {
   /// \return the platform_impl representing the offloading RT platform
   static platform_impl &getPlatformImpl(ol_platform_handle_t Platform);
 
+  template <typename InfoDesc>
+  static constexpr ol_platform_info_t getOffloadInfo() {
+    if constexpr (std::is_same_v<InfoDesc, sycl::info::platform::version>)
+      return OL_PLATFORM_INFO_VERSION;
+    else if constexpr (std::is_same_v<InfoDesc, sycl::info::platform::name>)
+      return OL_PLATFORM_INFO_NAME;
+    else if constexpr (std::is_same_v<InfoDesc, sycl::info::platform::vendor>)
+      return OL_PLATFORM_INFO_VENDOR_NAME;
+    else
+      static_assert(false && "Convertion list for platform info is not full.");
+  }
   /// Queries this SYCL platform for info.
   ///
   /// The return type depends on information being queried.
   template <typename Param> typename Param::return_type get_info() const {
     // for now we have only std::string properties
     static_assert(std::is_same_v<typename Param::return_type, std::string>);
+    constexpr ol_platform_info_t OffloadCode = getOffloadInfo<Param>();
+
     size_t ExpectedSize = 0;
-    call_and_throw(olGetPlatformInfoSize, MOffloadPlatform,
-                   detail::OffloadInfoCode<Param>::value, &ExpectedSize);
+    call_and_throw(olGetPlatformInfoSize, MOffloadPlatform, OffloadCode,
+                   &ExpectedSize);
     std::string Result;
     Result.resize(ExpectedSize - 1);
-    call_and_throw(olGetPlatformInfo, MOffloadPlatform,
-                   detail::OffloadInfoCode<Param>::value, ExpectedSize,
-                   Result.data());
+    call_and_throw(olGetPlatformInfo, MOffloadPlatform, OffloadCode,
+                   ExpectedSize, Result.data());
     return Result;
   }
 
diff --git a/libsycl/src/platform.cpp b/libsycl/src/platform.cpp
index 66c76d1c6bd73..e275d1d299777 100644
--- a/libsycl/src/platform.cpp
+++ b/libsycl/src/platform.cpp
@@ -34,7 +34,7 @@ platform::get_info() const {
   return impl.get_info<Param>();
 }
 
-#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, PiCode)              \
+#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT)                      \
   template _LIBSYCL_EXPORT ReturnT platform::get_info<info::platform::Desc>()  \
       const;
 #include <sycl/__impl/info/platform.def>

>From 71dcdf971846cf50f90f9c4bfc79e6b685828745 Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Thu, 27 Nov 2025 04:00:58 -0800
Subject: [PATCH 09/16] change ref to impl to raw ptr

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 .../include/sycl/__impl/detail/obj_base.hpp   | 19 +++++++++++--------
 libsycl/include/sycl/__impl/platform.hpp      |  6 +++---
 libsycl/src/detail/common.hpp                 |  8 ++++----
 .../src/detail/offload/offload_topology.hpp   | 13 +++++++------
 libsycl/src/platform.cpp                      |  8 +++++---
 5 files changed, 30 insertions(+), 24 deletions(-)

diff --git a/libsycl/include/sycl/__impl/detail/obj_base.hpp b/libsycl/include/sycl/__impl/detail/obj_base.hpp
index fbeb47a70ebdd..66598dc461e31 100644
--- a/libsycl/include/sycl/__impl/detail/obj_base.hpp
+++ b/libsycl/include/sycl/__impl/detail/obj_base.hpp
@@ -28,37 +28,40 @@ namespace detail {
 
 template <typename Impl, typename SyclObject> class ObjBase;
 template <typename Impl, typename SyclObject>
-class ObjBase<Impl &, SyclObject> {
+class ObjBase<Impl *, SyclObject> {
 public:
   using ImplType = Impl;
-  using Base = ObjBase<Impl &, SyclObject>;
+  using ImplPtrType = Impl *;
+  using Base = ObjBase<Impl *, SyclObject>;
 
 protected:
-  const ImplType &impl;
+  ImplPtrType impl;
 
-  explicit ObjBase(const ImplType &pImpl) : impl(pImpl) {}
+  explicit ObjBase(ImplPtrType pImpl) : impl(pImpl) {}
   ObjBase() = default;
 
-  static SyclObject createSyclProxy(const ImplType &impl) {
+  static SyclObject createSyclProxy(ImplPtrType impl) {
     return SyclObject(impl);
   }
 
+  ImplType &getImpl() const { 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::ImplType> ImplObj);
+      std::add_lvalue_reference_t<const typename Obj::ImplPtrType> ImplObj);
 };
 
 template <class Obj>
 const typename Obj::ImplType &getSyclObjImpl(const Obj &Object) {
-  return Object.impl;
+  return *Object.impl;
 }
 
 template <class Obj>
 Obj createSyclObjFromImpl(
-    std::add_lvalue_reference_t<const typename Obj::ImplType> ImplObj) {
+    std::add_lvalue_reference_t<const typename Obj::ImplPtrType> ImplObj) {
   return Obj::Base::createSyclProxy(ImplObj);
 }
 
diff --git a/libsycl/include/sycl/__impl/platform.hpp b/libsycl/include/sycl/__impl/platform.hpp
index ba30fdcd809c3..9bba6c6897b7c 100644
--- a/libsycl/include/sycl/__impl/platform.hpp
+++ b/libsycl/include/sycl/__impl/platform.hpp
@@ -31,7 +31,7 @@ class platform_impl;
 
 // 4.6.2. Platform class
 class _LIBSYCL_EXPORT platform
-    : public detail::ObjBase<detail::platform_impl &, platform> {
+    : public detail::ObjBase<detail::platform_impl *, platform> {
 public:
   /// Constructs a platform object that is a copy of the platform which contains
   /// the device returned by default_selector_v.
@@ -108,9 +108,9 @@ class _LIBSYCL_EXPORT platform
   static std::vector<platform> get_platforms();
 
 private:
-  platform(const detail::platform_impl &Impl) : ObjBase(Impl) {}
+  platform(detail::platform_impl *Impl) : ObjBase(Impl) {}
 
-  friend detail::ObjBase<detail::platform_impl &, platform>;
+  friend detail::ObjBase<detail::platform_impl *, platform>;
 }; // class platform
 
 _LIBSYCL_END_NAMESPACE_SYCL
diff --git a/libsycl/src/detail/common.hpp b/libsycl/src/detail/common.hpp
index e47c231f9ab81..43bee0560e2e8 100644
--- a/libsycl/src/detail/common.hpp
+++ b/libsycl/src/detail/common.hpp
@@ -19,11 +19,11 @@ namespace detail {
 
 // Minimal span-like view
 template <class T> struct range_view {
-  const T *ptr{};
+  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]; }
+  T *begin() const { return ptr; }
+  T *end() const { return ptr + len; }
+  T &operator[](size_t i) const { return ptr[i]; }
   size_t size() const { return len; }
 };
 
diff --git a/libsycl/src/detail/offload/offload_topology.hpp b/libsycl/src/detail/offload/offload_topology.hpp
index 211f6a88a18e6..36a488e486fe3 100644
--- a/libsycl/src/detail/offload/offload_topology.hpp
+++ b/libsycl/src/detail/offload/offload_topology.hpp
@@ -35,12 +35,13 @@ struct OffloadTopology {
   void set_backend(ol_platform_backend_t B) { MBackend = B; }
 
   // Platforms for this backend
-  range_view<ol_platform_handle_t> platforms() const {
+  range_view<const ol_platform_handle_t> platforms() const {
     return {MPlatforms.data(), MPlatforms.size()};
   }
 
   // Devices for a specific platform (platform_id is index into Platforms)
-  range_view<ol_device_handle_t> devicesForPlatform(size_t PlatformId) const {
+  range_view<const ol_device_handle_t>
+  devicesForPlatform(size_t PlatformId) const {
     if (PlatformId >= MDevRangePerPlatformId.size())
       return {nullptr, 0};
     return MDevRangePerPlatformId[PlatformId];
@@ -59,8 +60,8 @@ struct OffloadTopology {
 
     for (auto &[NewPlatform, NewDevs] : PlatformsAndDev) {
       MPlatforms.push_back(NewPlatform);
-      range_view<ol_device_handle_t> R{MDevices.data() + MDevices.size(),
-                                       NewDevs.size()};
+      range_view<const ol_device_handle_t> R{MDevices.data() + MDevices.size(),
+                                             NewDevs.size()};
       MDevices.insert(MDevices.end(), NewDevs.begin(), NewDevs.end());
       MDevRangePerPlatformId.push_back(R);
     }
@@ -68,7 +69,7 @@ struct OffloadTopology {
     assert(TotalDevCount == MDevices.size());
   }
 
-  ol_platform_backend_t backend() { return MBackend; }
+  ol_platform_backend_t backend() const { return MBackend; }
 
 private:
   ol_platform_backend_t MBackend = OL_PLATFORM_BACKEND_UNKNOWN;
@@ -79,7 +80,7 @@ struct OffloadTopology {
 
   // Vector holding range of devices for each platform (index is platform index
   // within Platforms)
-  std::vector<range_view<ol_device_handle_t>>
+  std::vector<range_view<const ol_device_handle_t>>
       MDevRangePerPlatformId; // PlatformDevices.size() == Platforms.size()
 };
 
diff --git a/libsycl/src/platform.cpp b/libsycl/src/platform.cpp
index e275d1d299777..79d83e4c957c0 100644
--- a/libsycl/src/platform.cpp
+++ b/libsycl/src/platform.cpp
@@ -14,7 +14,9 @@
 
 _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
-backend platform::get_backend() const noexcept { return impl.getBackend(); }
+backend platform::get_backend() const noexcept {
+  return getImpl().getBackend();
+}
 
 std::vector<platform> platform::get_platforms() {
   auto PlatformsView = detail::platform_impl::getPlatforms();
@@ -22,7 +24,7 @@ std::vector<platform> platform::get_platforms() {
   Platforms.reserve(PlatformsView.size());
   for (size_t i = 0; i < PlatformsView.size(); i++) {
     platform Platform =
-        detail::createSyclObjFromImpl<platform>(PlatformsView[i]);
+        detail::createSyclObjFromImpl<platform>(&PlatformsView[i]);
     Platforms.push_back(std::move(Platform));
   }
   return Platforms;
@@ -31,7 +33,7 @@ std::vector<platform> platform::get_platforms() {
 template <typename Param>
 typename detail::is_platform_info_desc<Param>::return_type
 platform::get_info() const {
-  return impl.get_info<Param>();
+  return getImpl().get_info<Param>();
 }
 
 #define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT)                      \

>From 51529c19bca2480c21c75f1b7b17a01ba114c09f Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Thu, 27 Nov 2025 04:07:34 -0800
Subject: [PATCH 10/16] add asserts for impl

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/include/sycl/__impl/detail/obj_base.hpp | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/libsycl/include/sycl/__impl/detail/obj_base.hpp b/libsycl/include/sycl/__impl/detail/obj_base.hpp
index 66598dc461e31..8248791ac9ab7 100644
--- a/libsycl/include/sycl/__impl/detail/obj_base.hpp
+++ b/libsycl/include/sycl/__impl/detail/obj_base.hpp
@@ -37,14 +37,19 @@ class ObjBase<Impl *, SyclObject> {
 protected:
   ImplPtrType impl;
 
-  explicit ObjBase(ImplPtrType pImpl) : impl(pImpl) {}
+  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 { return *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);
@@ -56,6 +61,7 @@ class ObjBase<Impl *, SyclObject> {
 
 template <class Obj>
 const typename Obj::ImplType &getSyclObjImpl(const Obj &Object) {
+  assert(Object.impl && "Impl can not be nullptr");
   return *Object.impl;
 }
 

>From 821a30646717d6dfb49ff499bfb9bce080a6e0ff Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Mon, 1 Dec 2025 03:40:29 -0800
Subject: [PATCH 11/16] apply proposed impl of get_info

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 .../include/sycl/__impl/info/desc_base.hpp    | 38 ++++++++++++++++++
 libsycl/include/sycl/__impl/info/platform.def |  8 ----
 libsycl/include/sycl/__impl/info/platform.hpp | 39 ++++++++-----------
 libsycl/include/sycl/__impl/platform.hpp      |  2 +-
 libsycl/src/detail/offload/offload_utils.hpp  | 21 ++++++++++
 libsycl/src/detail/platform_impl.hpp          | 16 ++++++--
 libsycl/src/platform.cpp                      | 16 ++++----
 7 files changed, 98 insertions(+), 42 deletions(-)
 create mode 100644 libsycl/include/sycl/__impl/info/desc_base.hpp
 delete mode 100644 libsycl/include/sycl/__impl/info/platform.def

diff --git a/libsycl/include/sycl/__impl/info/desc_base.hpp b/libsycl/include/sycl/__impl/info/desc_base.hpp
new file mode 100644
index 0000000000000..930555db80e0b
--- /dev/null
+++ b/libsycl/include/sycl/__impl/info/desc_base.hpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 helpers for info descriptors
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBSYCL___IMPL_INFO_DESC_BASE_HPP
+#define _LIBSYCL___IMPL_INFO_DESC_BASE_HPP
+
+#include <sycl/__impl/detail/config.hpp>
+
+_LIBSYCL_BEGIN_NAMESPACE_SYCL
+
+namespace detail {
+
+template <typename Desc, typename DescOf> struct info_desc_tag {};
+template <typename Desc, typename DescOf, typename = void>
+struct is_info_desc : std::false_type {};
+template <typename Desc, typename DescOf>
+struct is_info_desc<
+    Desc, DescOf,
+    std::enable_if_t<std::is_base_of_v<info_desc_tag<Desc, DescOf>, Desc>>>
+    : std::true_type {
+  using return_type = typename Desc::return_type;
+};
+
+} // namespace detail
+
+_LIBSYCL_END_NAMESPACE_SYCL
+
+#endif // _LIBSYCL___IMPL_INFO_DESC_BASE_HPP
diff --git a/libsycl/include/sycl/__impl/info/platform.def b/libsycl/include/sycl/__impl/info/platform.def
deleted file mode 100644
index f4198b610715c..0000000000000
--- a/libsycl/include/sycl/__impl/info/platform.def
+++ /dev/null
@@ -1,8 +0,0 @@
-#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)
-__SYCL_PARAM_TRAITS_SPEC(platform, name, std::string)
-__SYCL_PARAM_TRAITS_SPEC(platform, vendor, std::string)
diff --git a/libsycl/include/sycl/__impl/info/platform.hpp b/libsycl/include/sycl/__impl/info/platform.hpp
index ceaa818b5ebe4..9e7dd061a8a6c 100644
--- a/libsycl/include/sycl/__impl/info/platform.hpp
+++ b/libsycl/include/sycl/__impl/info/platform.hpp
@@ -15,40 +15,35 @@
 #define _LIBSYCL___IMPL_INFO_PLATFORM_HPP
 
 #include <sycl/__impl/detail/config.hpp>
+#include <sycl/__impl/info/desc_base.hpp>
 
 #include <string>
 
 _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
+class platform;
+
+namespace detail {
+template <typename T>
+using is_platform_info_desc_t = typename is_info_desc<T, platform>::return_type;
+} // namespace detail
+
 // A.1. Platform information descriptors
 namespace info {
 namespace platform {
-#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT)                      \
-  struct Desc {                                                                \
-    using return_type = ReturnT;                                               \
-  };
-
 // 4.6.2.4. Information descriptors
-#include <sycl/__impl/info/platform.def>
-
-#undef __SYCL_PARAM_TRAITS_SPEC
+struct version : detail::info_desc_tag<version, sycl::platform> {
+  using return_type = std::string;
+};
+struct name : detail::info_desc_tag<name, sycl::platform> {
+  using return_type = std::string;
+};
+struct vendor : detail::info_desc_tag<vendor, sycl::platform> {
+  using return_type = std::string;
+};
 } // namespace platform
 } // namespace info
 
-namespace detail {
-template <typename T> struct is_platform_info_desc : std::false_type {};
-
-#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT)                      \
-  template <>                                                                  \
-  struct is_##DescType##_info_desc<info::DescType::Desc> : std::true_type {    \
-    using return_type = info::DescType::Desc::return_type;                     \
-  };
-
-#include <sycl/__impl/info/platform.def>
-
-#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 9bba6c6897b7c..681eb68eacaf8 100644
--- a/libsycl/include/sycl/__impl/platform.hpp
+++ b/libsycl/include/sycl/__impl/platform.hpp
@@ -76,7 +76,7 @@ class _LIBSYCL_EXPORT platform
   ///
   /// The return type depends on information being queried.
   template <typename Param>
-  typename detail::is_platform_info_desc<Param>::return_type get_info() const;
+  detail::is_platform_info_desc_t<Param> get_info() const;
 
   // template <typename Param>
   // typename detail::is_backend_info_desc<Param>::return_type
diff --git a/libsycl/src/detail/offload/offload_utils.hpp b/libsycl/src/detail/offload/offload_utils.hpp
index b48a6b49d2fd6..5f02feea98e3b 100644
--- a/libsycl/src/detail/offload/offload_utils.hpp
+++ b/libsycl/src/detail/offload/offload_utils.hpp
@@ -52,6 +52,27 @@ void call_and_throw(FunctionType &Function, ArgsT &&...Args) {
 
 backend convertBackend(ol_platform_backend_t Backend);
 
+/// Helper to map SYCL information descriptors to OL_<HANDLE>_INFO_<SMTH>. To be
+/// used like:
+///
+/// using Map = info_ol_mapping<ol_foo_info_t>;
+/// constexpr auto olInfo = map_info_desc<FromDesc, ol_foo_info_t>(
+///                                            Map::M<DescVal0>{OL_FOO_INFO_VAL0},
+///                                            Map::M<DescVal1>{OL_FOO_INFO_VAL1},
+///                                            ...)
+template <typename To> struct info_ol_mapping {
+  template <typename From> struct M {
+    To value;
+    constexpr M(To value) : value(value) {}
+  };
+};
+template <typename From, typename To, typename... Ts>
+constexpr To map_info_desc(typename info_ol_mapping<To>::template M<Ts>... ms) {
+  return std::get<typename info_ol_mapping<To>::template M<From>>(
+             std::tuple{ms...})
+      .value;
+}
+
 } // namespace detail
 
 _LIBSYCL_END_NAMESPACE_SYCL
diff --git a/libsycl/src/detail/platform_impl.hpp b/libsycl/src/detail/platform_impl.hpp
index ebb9ff7fc1e77..8fbf76ce8e330 100644
--- a/libsycl/src/detail/platform_impl.hpp
+++ b/libsycl/src/detail/platform_impl.hpp
@@ -88,15 +88,23 @@ class platform_impl {
   template <typename Param> typename Param::return_type get_info() const {
     // for now we have only std::string properties
     static_assert(std::is_same_v<typename Param::return_type, std::string>);
-    constexpr ol_platform_info_t OffloadCode = getOffloadInfo<Param>();
+
+    using namespace info::platform;
+    using Map = info_ol_mapping<ol_platform_info_t>;
+
+    constexpr ol_platform_info_t olInfo =
+        map_info_desc<Param, ol_platform_info_t>(
+            Map::M<version>{OL_PLATFORM_INFO_VERSION},
+            Map::M<name>{OL_PLATFORM_INFO_NAME},
+            Map::M<vendor>{OL_PLATFORM_INFO_VENDOR_NAME});
 
     size_t ExpectedSize = 0;
-    call_and_throw(olGetPlatformInfoSize, MOffloadPlatform, OffloadCode,
+    call_and_throw(olGetPlatformInfoSize, MOffloadPlatform, olInfo,
                    &ExpectedSize);
     std::string Result;
     Result.resize(ExpectedSize - 1);
-    call_and_throw(olGetPlatformInfo, MOffloadPlatform, OffloadCode,
-                   ExpectedSize, Result.data());
+    call_and_throw(olGetPlatformInfo, MOffloadPlatform, olInfo, ExpectedSize,
+                   Result.data());
     return Result;
   }
 
diff --git a/libsycl/src/platform.cpp b/libsycl/src/platform.cpp
index 79d83e4c957c0..6d35c8534f2a3 100644
--- a/libsycl/src/platform.cpp
+++ b/libsycl/src/platform.cpp
@@ -31,15 +31,17 @@ std::vector<platform> platform::get_platforms() {
 }
 
 template <typename Param>
-typename detail::is_platform_info_desc<Param>::return_type
-platform::get_info() const {
+detail::is_platform_info_desc_t<Param> platform::get_info() const {
   return getImpl().get_info<Param>();
 }
 
-#define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT)                      \
-  template _LIBSYCL_EXPORT ReturnT platform::get_info<info::platform::Desc>()  \
-      const;
-#include <sycl/__impl/info/platform.def>
-#undef __SYCL_PARAM_TRAITS_SPEC
+#define _LIBSYCL_EXPORT_GET_INFO(Desc)                                         \
+  template _LIBSYCL_EXPORT                                                     \
+      detail::is_platform_info_desc_t<info::platform::Desc>                    \
+      platform::get_info<info::platform::Desc>() const;
+_LIBSYCL_EXPORT_GET_INFO(version)
+_LIBSYCL_EXPORT_GET_INFO(name)
+_LIBSYCL_EXPORT_GET_INFO(vendor)
+#undef _LIBSYCL_EXPORT_GET_INFO
 
 _LIBSYCL_END_NAMESPACE_SYCL

>From 87442d1a48c48be0e511b6f200bd36e4c37f7a80 Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Tue, 2 Dec 2025 04:06:41 -0800
Subject: [PATCH 12/16] fix leftover of base class impl w/o friend funcs

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/include/sycl/__impl/detail/obj_base.hpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libsycl/include/sycl/__impl/detail/obj_base.hpp b/libsycl/include/sycl/__impl/detail/obj_base.hpp
index 8248791ac9ab7..16c383beb1f46 100644
--- a/libsycl/include/sycl/__impl/detail/obj_base.hpp
+++ b/libsycl/include/sycl/__impl/detail/obj_base.hpp
@@ -29,12 +29,11 @@ namespace detail {
 template <typename Impl, typename SyclObject> class ObjBase;
 template <typename Impl, typename SyclObject>
 class ObjBase<Impl *, SyclObject> {
-public:
+protected:
   using ImplType = Impl;
   using ImplPtrType = Impl *;
   using Base = ObjBase<Impl *, SyclObject>;
 
-protected:
   ImplPtrType impl;
 
   explicit ObjBase(ImplPtrType pImpl) : impl(pImpl) {

>From e4e6fd234fd88b40b2858bb18cc7dda627dd3b03 Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Fri, 5 Dec 2025 04:10:49 -0800
Subject: [PATCH 13/16] fix comments

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 .../include/sycl/__impl/detail/obj_base.hpp   | 90 -------------------
 .../include/sycl/__impl/detail/obj_utils.hpp  | 81 +++++++++++++++++
 libsycl/include/sycl/__impl/platform.hpp      | 10 +--
 libsycl/src/detail/global_objects.cpp         |  4 +-
 libsycl/src/detail/global_objects.hpp         |  2 +-
 libsycl/src/detail/offload/offload_utils.cpp  |  2 +-
 libsycl/src/detail/offload/offload_utils.hpp  | 10 +--
 libsycl/src/detail/platform_impl.cpp          | 17 ++--
 libsycl/src/detail/platform_impl.hpp          | 17 ++--
 libsycl/src/exception.cpp                     |  4 +-
 libsycl/src/platform.cpp                      | 15 ++--
 libsycl/tools/sycl-ls/sycl-ls.cpp             |  3 +-
 12 files changed, 122 insertions(+), 133 deletions(-)
 delete mode 100644 libsycl/include/sycl/__impl/detail/obj_base.hpp
 create mode 100644 libsycl/include/sycl/__impl/detail/obj_utils.hpp

diff --git a/libsycl/include/sycl/__impl/detail/obj_base.hpp b/libsycl/include/sycl/__impl/detail/obj_base.hpp
deleted file mode 100644
index 16c383beb1f46..0000000000000
--- a/libsycl/include/sycl/__impl/detail/obj_base.hpp
+++ /dev/null
@@ -1,90 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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> {
-protected:
-  using ImplType = Impl;
-  using ImplPtrType = Impl *;
-  using Base = ObjBase<Impl *, SyclObject>;
-
-  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
diff --git a/libsycl/include/sycl/__impl/detail/obj_utils.hpp b/libsycl/include/sycl/__impl/detail/obj_utils.hpp
new file mode 100644
index 0000000000000..abbf9039856d0
--- /dev/null
+++ b/libsycl/include/sycl/__impl/detail/obj_utils.hpp
@@ -0,0 +1,81 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_UTILS_HPP
+#define _LIBSYCL___IMPL_DETAIL_OBJ_UTILS_HPP
+
+#include <sycl/__impl/detail/config.hpp>
+
+#include <cassert>
+#include <memory>
+#include <optional>
+#include <type_traits>
+#include <utility>
+
+_LIBSYCL_BEGIN_NAMESPACE_SYCL
+
+namespace detail {
+
+// Note! This class relies on the fact that all SYCL interface
+// classes contain "impl" field that points to implementation object. "impl"
+// field should be accessible from this class.
+struct ImplUtils {
+  // Helper function for extracting implementation from SYCL's interface
+  // objects.
+  template <class Obj>
+  static const decltype(Obj::impl) &getSyclObjImpl(const Obj &SyclObj) {
+    assert(SyclObj.impl && "every constructor should create an impl");
+    return SyclObj.impl;
+  }
+
+  // Helper function for creation SYCL interface objects from implementations.
+  template <typename SyclObject, typename From>
+  static SyclObject createSyclObjFromImpl(From &&from) {
+    if constexpr (std::is_same_v<decltype(SyclObject::impl),
+                                 std::shared_ptr<std::decay_t<From>>>)
+      return SyclObject{from.shared_from_this()};
+    else
+      return SyclObject{std::forward<From>(from)};
+  }
+};
+
+template <class Obj>
+auto getSyclObjImpl(const Obj &SyclObj)
+    -> decltype(ImplUtils::getSyclObjImpl(SyclObj)) {
+  return ImplUtils::getSyclObjImpl(SyclObj);
+}
+
+template <typename SyclObject, typename From>
+SyclObject createSyclObjFromImpl(From &&from) {
+  return ImplUtils::createSyclObjFromImpl<SyclObject>(std::forward<From>(from));
+}
+
+// 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_UTILS_HPP
diff --git a/libsycl/include/sycl/__impl/platform.hpp b/libsycl/include/sycl/__impl/platform.hpp
index 681eb68eacaf8..431b01fc7278d 100644
--- a/libsycl/include/sycl/__impl/platform.hpp
+++ b/libsycl/include/sycl/__impl/platform.hpp
@@ -17,7 +17,7 @@
 
 #include <sycl/__impl/backend.hpp>
 #include <sycl/__impl/detail/config.hpp>
-#include <sycl/__impl/detail/obj_base.hpp>
+#include <sycl/__impl/detail/obj_utils.hpp>
 #include <sycl/__impl/info/platform.hpp>
 
 #include <memory>
@@ -30,8 +30,7 @@ class platform_impl;
 } // namespace detail
 
 // 4.6.2. Platform class
-class _LIBSYCL_EXPORT platform
-    : public detail::ObjBase<detail::platform_impl *, platform> {
+class _LIBSYCL_EXPORT platform {
 public:
   /// Constructs a platform object that is a copy of the platform which contains
   /// the device returned by default_selector_v.
@@ -108,9 +107,10 @@ class _LIBSYCL_EXPORT platform
   static std::vector<platform> get_platforms();
 
 private:
-  platform(detail::platform_impl *Impl) : ObjBase(Impl) {}
+  platform(detail::platform_impl &Impl) : impl(&Impl) {}
+  detail::platform_impl *impl;
 
-  friend detail::ObjBase<detail::platform_impl *, platform>;
+  friend sycl::detail::ImplUtils;
 }; // class platform
 
 _LIBSYCL_END_NAMESPACE_SYCL
diff --git a/libsycl/src/detail/global_objects.cpp b/libsycl/src/detail/global_objects.cpp
index 9990b4d27824a..7998c2965bc2e 100644
--- a/libsycl/src/detail/global_objects.cpp
+++ b/libsycl/src/detail/global_objects.cpp
@@ -24,8 +24,8 @@ std::vector<detail::OffloadTopology> &getOffloadTopologies() {
   return Topologies;
 }
 
-std::vector<platform_impl> &getPlatformCache() {
-  static std::vector<platform_impl> PlatformCache{};
+std::vector<PlatformImplUPtr> &getPlatformCache() {
+  static std::vector<PlatformImplUPtr> PlatformCache{};
   return PlatformCache;
 }
 
diff --git a/libsycl/src/detail/global_objects.hpp b/libsycl/src/detail/global_objects.hpp
index 0b5ac246692bf..81899623aed68 100644
--- a/libsycl/src/detail/global_objects.hpp
+++ b/libsycl/src/detail/global_objects.hpp
@@ -24,7 +24,7 @@ class platform_impl;
 // Offload topologies (one per backend) discovered from liboffload.
 std::vector<detail::OffloadTopology> &getOffloadTopologies();
 
-std::vector<platform_impl> &getPlatformCache();
+std::vector<std::unique_ptr<platform_impl>> &getPlatformCache();
 
 } // namespace detail
 _LIBSYCL_END_NAMESPACE_SYCL
diff --git a/libsycl/src/detail/offload/offload_utils.cpp b/libsycl/src/detail/offload/offload_utils.cpp
index 2ccb27a9acf44..ccef4e582015b 100644
--- a/libsycl/src/detail/offload/offload_utils.cpp
+++ b/libsycl/src/detail/offload/offload_utils.cpp
@@ -11,7 +11,7 @@
 _LIBSYCL_BEGIN_NAMESPACE_SYCL
 namespace detail {
 
-const char *stringifyErrorCode(int32_t error) {
+const char *stringifyErrorCode(ol_errc_t error) {
   switch (error) {
 #define _OFFLOAD_ERRC(NAME)                                                    \
   case NAME:                                                                   \
diff --git a/libsycl/src/detail/offload/offload_utils.hpp b/libsycl/src/detail/offload/offload_utils.hpp
index 5f02feea98e3b..537fc6d80d505 100644
--- a/libsycl/src/detail/offload/offload_utils.hpp
+++ b/libsycl/src/detail/offload/offload_utils.hpp
@@ -19,18 +19,18 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
 namespace detail {
 
-const char *stringifyErrorCode(int32_t error);
+const char *stringifyErrorCode(ol_errc_t error);
 
-inline std::string formatCodeString(int32_t code) {
-  return std::to_string(code) + " (" + std::string(stringifyErrorCode(code)) +
-         ")";
+inline std::string formatCodeString(ol_result_t Result) {
+  return std::to_string(Result->Code) + " (" +
+         std::string(stringifyErrorCode(Result->Code)) + ")" + Result->Details;
 }
 
 template <sycl::errc errc = sycl::errc::runtime>
 void checkAndThrow(ol_result_t Result) {
   if (Result != OL_SUCCESS) {
     throw sycl::exception(sycl::make_error_code(errc),
-                          detail::formatCodeString(Result->Code));
+                          detail::formatCodeString(Result));
   }
 }
 
diff --git a/libsycl/src/detail/platform_impl.cpp b/libsycl/src/detail/platform_impl.cpp
index 6bdb9188732d4..d44d54b3a871c 100644
--- a/libsycl/src/detail/platform_impl.cpp
+++ b/libsycl/src/detail/platform_impl.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include <sycl/__impl/detail/config.hpp>
-#include <sycl/__impl/detail/obj_base.hpp>
+#include <sycl/__impl/detail/obj_utils.hpp>
 
 #include <detail/global_objects.hpp>
 #include <detail/platform_impl.hpp>
@@ -19,8 +19,8 @@ namespace detail {
 platform_impl &platform_impl::getPlatformImpl(ol_platform_handle_t Platform) {
   auto &PlatformCache = getPlatformCache();
   for (auto &PlatImpl : PlatformCache) {
-    if (PlatImpl.getHandleRef() == Platform)
-      return PlatImpl;
+    if (PlatImpl->getHandleRef() == Platform)
+      return *PlatImpl;
   }
 
   throw sycl::exception(
@@ -29,25 +29,24 @@ platform_impl &platform_impl::getPlatformImpl(ol_platform_handle_t Platform) {
       "the list of platforms discovered by liboffload");
 }
 
-range_view<platform_impl> platform_impl::getPlatforms() {
+const std::vector<PlatformImplUPtr> &platform_impl::getPlatforms() {
   [[maybe_unused]] static auto InitPlatformsOnce = []() {
     discoverOffloadDevices();
     auto &PlatformCache = getPlatformCache();
     for (const auto &Topo : getOffloadTopologies()) {
       size_t PlatformIndex = 0;
       for (const auto &OffloadPlatform : Topo.platforms()) {
-        PlatformCache.emplace_back(
-            platform_impl(OffloadPlatform, PlatformIndex++));
+        PlatformCache.emplace_back(std::make_unique<platform_impl>(
+            OffloadPlatform, PlatformIndex++, private_tag{}));
       }
     }
     return true;
   }();
-  auto &PlatformCache = getPlatformCache();
-  return {PlatformCache.data(), PlatformCache.size()};
+  return getPlatformCache();
 }
 
 platform_impl::platform_impl(ol_platform_handle_t Platform,
-                             size_t PlatformIndex)
+                             size_t PlatformIndex, private_tag)
     : MOffloadPlatform(Platform), MOffloadPlatformIndex(PlatformIndex) {
   ol_platform_backend_t Backend = OL_PLATFORM_BACKEND_UNKNOWN;
   call_and_throw(olGetPlatformInfo, MOffloadPlatform, OL_PLATFORM_INFO_BACKEND,
diff --git a/libsycl/src/detail/platform_impl.hpp b/libsycl/src/detail/platform_impl.hpp
index 8fbf76ce8e330..7d3090550f103 100644
--- a/libsycl/src/detail/platform_impl.hpp
+++ b/libsycl/src/detail/platform_impl.hpp
@@ -27,26 +27,31 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
 namespace detail {
 
+using PlatformImplUPtr = std::unique_ptr<platform_impl>;
+
 class platform_impl {
+  struct private_tag {
+    explicit private_tag() = default;
+  };
+
 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);
+  /// All platform impls are created during first getPlatforms() call.
+  explicit platform_impl(ol_platform_handle_t Platform, size_t PlatformIndex,
+                         private_tag);
 
   ~platform_impl() = default;
 
   /// Returns the backend associated with this platform.
   backend getBackend() const noexcept { return MBackend; }
 
-  /// Returns range-view to all SYCL platforms from all backends that are
+  /// Returns all SYCL platforms from all backends that are
   /// available in the system.
-  static range_view<platform_impl> getPlatforms();
+  static const std::vector<PlatformImplUPtr> &getPlatforms();
 
   /// Returns raw underlying offload platform handle.
   ///
diff --git a/libsycl/src/exception.cpp b/libsycl/src/exception.cpp
index 38fd8816934b9..88ffb527f4bef 100644
--- a/libsycl/src/exception.cpp
+++ b/libsycl/src/exception.cpp
@@ -50,8 +50,6 @@ const std::error_category &exception::category() const noexcept {
 
 const char *exception::what() const noexcept { return MMessage->c_str(); }
 
-bool exception::has_context() const noexcept { /*return (MContext != nullptr);*/
-  return false;
-}
+bool exception::has_context() const noexcept { return false; }
 
 _LIBSYCL_END_NAMESPACE_SYCL
diff --git a/libsycl/src/platform.cpp b/libsycl/src/platform.cpp
index 6d35c8534f2a3..d47af135dae3d 100644
--- a/libsycl/src/platform.cpp
+++ b/libsycl/src/platform.cpp
@@ -14,17 +14,14 @@
 
 _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
-backend platform::get_backend() const noexcept {
-  return getImpl().getBackend();
-}
+backend platform::get_backend() const noexcept { return impl->getBackend(); }
 
 std::vector<platform> platform::get_platforms() {
-  auto PlatformsView = detail::platform_impl::getPlatforms();
+  auto &PlatformImpls = detail::platform_impl::getPlatforms();
   std::vector<platform> Platforms;
-  Platforms.reserve(PlatformsView.size());
-  for (size_t i = 0; i < PlatformsView.size(); i++) {
-    platform Platform =
-        detail::createSyclObjFromImpl<platform>(&PlatformsView[i]);
+  Platforms.reserve(PlatformImpls.size());
+  for (auto &PlatformImpl : PlatformImpls) {
+    platform Platform = detail::createSyclObjFromImpl<platform>(*PlatformImpl);
     Platforms.push_back(std::move(Platform));
   }
   return Platforms;
@@ -32,7 +29,7 @@ std::vector<platform> platform::get_platforms() {
 
 template <typename Param>
 detail::is_platform_info_desc_t<Param> platform::get_info() const {
-  return getImpl().get_info<Param>();
+  return impl->get_info<Param>();
 }
 
 #define _LIBSYCL_EXPORT_GET_INFO(Desc)                                         \
diff --git a/libsycl/tools/sycl-ls/sycl-ls.cpp b/libsycl/tools/sycl-ls/sycl-ls.cpp
index d611a98af8063..fe49fa1bd50c2 100644
--- a/libsycl/tools/sycl-ls/sycl-ls.cpp
+++ b/libsycl/tools/sycl-ls/sycl-ls.cpp
@@ -35,6 +35,7 @@ int main(int argc, char **argv) {
 
     if (Platforms.size() == 0) {
       std::cout << "No platforms found." << std::endl;
+      return EXIT_SUCCESS;
     }
 
     for (const auto &Platform : Platforms) {
@@ -58,8 +59,6 @@ int main(int argc, char **argv) {
 
         std::cout << "    Devices  : " << "unknown" << std::endl;
       }
-    } else {
-      return EXIT_SUCCESS;
     }
   } catch (sycl::exception &e) {
     std::cerr << "SYCL Exception encountered: " << e.what() << std::endl

>From e8e28110ea51dcf358e7c9f582b43cfea0b5d5ae Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Fri, 5 Dec 2025 04:21:51 -0800
Subject: [PATCH 14/16] remove file common.hpp

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/src/detail/common.hpp                 | 34 -------------------
 .../src/detail/offload/offload_topology.hpp   | 12 +++++--
 libsycl/src/detail/platform_impl.hpp          |  1 -
 3 files changed, 10 insertions(+), 37 deletions(-)
 delete mode 100644 libsycl/src/detail/common.hpp

diff --git a/libsycl/src/detail/common.hpp b/libsycl/src/detail/common.hpp
deleted file mode 100644
index 43bee0560e2e8..0000000000000
--- a/libsycl/src/detail/common.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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_COMMON
-#define _LIBSYCL_COMMON
-
-#include <sycl/__impl/detail/config.hpp>
-
-#include <cstddef>
-
-_LIBSYCL_BEGIN_NAMESPACE_SYCL
-
-namespace detail {
-
-// Minimal span-like view
-template <class T> struct range_view {
-  T *ptr{};
-  size_t len{};
-  T *begin() const { return ptr; }
-  T *end() const { return ptr + len; }
-  T &operator[](size_t i) const { return ptr[i]; }
-  size_t size() const { return len; }
-};
-
-} // namespace detail
-
-_LIBSYCL_END_NAMESPACE_SYCL
-
-#endif // _LIBSYCL_COMMON
diff --git a/libsycl/src/detail/offload/offload_topology.hpp b/libsycl/src/detail/offload/offload_topology.hpp
index 36a488e486fe3..b8b5e9c94bd87 100644
--- a/libsycl/src/detail/offload/offload_topology.hpp
+++ b/libsycl/src/detail/offload/offload_topology.hpp
@@ -11,8 +11,6 @@
 
 #include <sycl/__impl/detail/config.hpp>
 
-#include <detail/common.hpp>
-
 #include <OffloadAPI.h>
 
 #include <cassert>
@@ -23,6 +21,16 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
 namespace detail {
 
+// Minimal span-like view
+template <class T> struct range_view {
+  T *ptr{};
+  size_t len{};
+  T *begin() const { return ptr; }
+  T *end() const { return ptr + len; }
+  T &operator[](size_t i) const { return ptr[i]; }
+  size_t size() const { return len; }
+};
+
 using PlatformWithDevStorageType =
     std::unordered_map<ol_platform_handle_t, std::vector<ol_device_handle_t>>;
 
diff --git a/libsycl/src/detail/platform_impl.hpp b/libsycl/src/detail/platform_impl.hpp
index 7d3090550f103..a877ac5751389 100644
--- a/libsycl/src/detail/platform_impl.hpp
+++ b/libsycl/src/detail/platform_impl.hpp
@@ -13,7 +13,6 @@
 #include <sycl/__impl/detail/config.hpp>
 #include <sycl/__impl/platform.hpp>
 
-#include <detail/common.hpp>
 #include <detail/offload/offload_utils.hpp>
 
 #include <OffloadAPI.h>

>From 9ce769553bcebd83c0a8327e5c5390d22d7844d0 Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Thu, 11 Dec 2025 06:14:40 -0800
Subject: [PATCH 15/16] fix code-review comments

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/README.md                             |  2 +-
 libsycl/docs/index.rst                        | 16 ++++---
 libsycl/include/sycl/__impl/backend.hpp       | 44 +++++--------------
 .../sycl/__impl/detail/macro_definitions.hpp  | 23 +++++-----
 .../include/sycl/__impl/detail/obj_utils.hpp  |  2 +-
 libsycl/include/sycl/__impl/exception.hpp     |  4 +-
 libsycl/include/sycl/__impl/info/platform.hpp |  4 +-
 libsycl/include/sycl/__impl/platform.hpp      |  2 +-
 libsycl/src/exception.cpp                     |  1 -
 libsycl/src/version.hpp.in                    |  2 +-
 libsycl/tools/sycl-ls/sycl-ls.cpp             | 19 +++++++-
 11 files changed, 57 insertions(+), 62 deletions(-)

diff --git a/libsycl/README.md b/libsycl/README.md
index 9fed3fdc4efa1..1452c158ca9d4 100644
--- a/libsycl/README.md
+++ b/libsycl/README.md
@@ -3,7 +3,7 @@
 The libsycl subproject is an implementation of the SYCL runtime library as defined by the
 [SYCL 2020 specification](https://registry.khronos.org/SYCL/specs/sycl-2020/html/sycl-2020.html).
 
-Subproject documentation is available at: [SYCL RT documentation](./docs).
+Subproject documentation is available at: [Libsycl documentation](./docs).
 
 libsycl runtime library and headers require C++17 support or higher.
 
diff --git a/libsycl/docs/index.rst b/libsycl/docs/index.rst
index 83df7807c9df9..6b7b0d23a8119 100644
--- a/libsycl/docs/index.rst
+++ b/libsycl/docs/index.rst
@@ -10,8 +10,10 @@ SYCL runtime implementation
 Current Status
 ========
 
-The implementation is in the very early stages of upstreaming. The first milestone is to get
-support for a simple SYCL application with device code using Unified Shared Memory:
+The implementation is in the very early stages of upstreaming. The first
+milestone is to get
+support for a simple SYCL application with device code using Unified Shared
+Memory:
 
 .. code-block:: c++
 
@@ -43,7 +45,8 @@ support for a simple SYCL application with device code using Unified Shared Memo
      return error;
    }
 
-This requires at least partial support of the following functionality on the libsycl side:
+This requires at least partial support of the following functionality on the
+libsycl side:
   * ``sycl::platform`` class
   * ``sycl::device`` class
   * ``sycl::context`` class
@@ -51,7 +54,8 @@ This requires at least partial support of the following functionality on the lib
   * ``sycl::handler`` class
   * ``sycl::id`` and ``sycl::range`` classes
   * Unified shared memory allocation/deallocation
-  * Program manager, an internal component for retrieving and using device images from the multi-architectural binaries
+  * Program manager, an internal component for retrieving and using device
+images from the multi-architectural binaries
 
 Build steps
 ========
@@ -81,5 +85,5 @@ To build LLVM with libsycl runtime enabled the following script can be used.
 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.
+Libsycl is not currently supported on Windows because it depends on liboffload
+which doesn't currently support Windows.
diff --git a/libsycl/include/sycl/__impl/backend.hpp b/libsycl/include/sycl/__impl/backend.hpp
index 4b467f50cce5f..3f1bd13c4e55d 100644
--- a/libsycl/include/sycl/__impl/backend.hpp
+++ b/libsycl/include/sycl/__impl/backend.hpp
@@ -23,48 +23,28 @@
 
 _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
-// 4.1. Backends
-enum class backend : char {
-  opencl = 1,
-  level_zero = 2,
-  cuda = 3,
-  hip = 4,
-  all = 5,
+// SYCL 2020 4.1. Backends
+enum class backend : unsigned char {
+  opencl = 0,
+  level_zero,
+  cuda,
+  hip,
+  all,
 };
 
 namespace detail {
 template <typename T> struct is_backend_info_desc : std::false_type {};
 } // namespace detail
 
-// 4.5.1.1. Type traits backend_traits
+// SYCL 2020  4.5.1.1. Type traits backend_traits
 template <backend Backend> class backend_traits;
 
-template <backend Backend, typename SYCLObjectT>
+template <backend Backend, typename SyclType>
 using backend_input_t =
-    typename backend_traits<Backend>::template input_type<SYCLObjectT>;
-template <backend Backend, typename SYCLObjectT>
+    typename backend_traits<Backend>::template input_type<SyclType>;
+template <backend Backend, typename SyclType>
 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) {
-  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
+    typename backend_traits<Backend>::template return_type<SyclType>;
 
 _LIBSYCL_END_NAMESPACE_SYCL
 
diff --git a/libsycl/include/sycl/__impl/detail/macro_definitions.hpp b/libsycl/include/sycl/__impl/detail/macro_definitions.hpp
index c9e148709d721..0938f4f88f67b 100644
--- a/libsycl/include/sycl/__impl/detail/macro_definitions.hpp
+++ b/libsycl/include/sycl/__impl/detail/macro_definitions.hpp
@@ -23,22 +23,19 @@
 #  endif
 #endif // __SYCL2020_DEPRECATED
 
-static_assert(__cplusplus >= 201703L,
-              "SYCL RT does not support C++ version earlier than C++17.");
+static_assert(__cplusplus >= 201703L, "Libsycl requires C++17 or later.");
 
 #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.
+// When built for use with the MSVC C++ standard library, libsycl requires
+// use of the DLL versions of the MSVC run-time (RT) library. This requirement
+// extends to applications that link with libsycl since the same MSVC run-time
+// library must be used to ensure ABI compatibility for objects of C++ standard
+// library types like std::vector that are passed to or returned from SYCL
+// interfaces. Applications must therefore compile and link with the /MD option
+// when linking to a release build of libsycl and with the /MDd option when
+// linking to a debug build.
 #  define ERROR_MESSAGE                                                        \
-    "SYCL library is designed to work safely with dynamic C++ runtime."        \
+    "Libsycl 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)
diff --git a/libsycl/include/sycl/__impl/detail/obj_utils.hpp b/libsycl/include/sycl/__impl/detail/obj_utils.hpp
index abbf9039856d0..ccf14a58ee8be 100644
--- a/libsycl/include/sycl/__impl/detail/obj_utils.hpp
+++ b/libsycl/include/sycl/__impl/detail/obj_utils.hpp
@@ -61,7 +61,7 @@ SyclObject createSyclObjFromImpl(From &&from) {
   return ImplUtils::createSyclObjFromImpl<SyclObject>(std::forward<From>(from));
 }
 
-// std::hash support (4.5.2. Common reference semantics)
+// SYCL 2020 4.5.2. Common reference semantics (std::hash support)
 template <typename T> struct HashBase {
   size_t operator()(const T &Obj) const {
 #ifdef __SYCL_DEVICE_ONLY__
diff --git a/libsycl/include/sycl/__impl/exception.hpp b/libsycl/include/sycl/__impl/exception.hpp
index d41a833e1bc10..95ca02be6d09d 100644
--- a/libsycl/include/sycl/__impl/exception.hpp
+++ b/libsycl/include/sycl/__impl/exception.hpp
@@ -26,8 +26,6 @@
 
 _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
-class context;
-
 enum class errc : int {
   success = 0,
   runtime = 1,
@@ -55,7 +53,7 @@ _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
+// SYCL 2020 4.13.2. Exception class interface
 class _LIBSYCL_EXPORT exception : public virtual std::exception {
 public:
   exception(std::error_code, const char *);
diff --git a/libsycl/include/sycl/__impl/info/platform.hpp b/libsycl/include/sycl/__impl/info/platform.hpp
index 9e7dd061a8a6c..0f3477fe1d711 100644
--- a/libsycl/include/sycl/__impl/info/platform.hpp
+++ b/libsycl/include/sycl/__impl/info/platform.hpp
@@ -28,10 +28,10 @@ template <typename T>
 using is_platform_info_desc_t = typename is_info_desc<T, platform>::return_type;
 } // namespace detail
 
-// A.1. Platform information descriptors
+// SYCL 2020 A.1. Platform information descriptors
 namespace info {
 namespace platform {
-// 4.6.2.4. Information descriptors
+// SYCL 2020 4.6.2.4. Information descriptors
 struct version : detail::info_desc_tag<version, sycl::platform> {
   using return_type = std::string;
 };
diff --git a/libsycl/include/sycl/__impl/platform.hpp b/libsycl/include/sycl/__impl/platform.hpp
index 431b01fc7278d..f1d2f17cc54aa 100644
--- a/libsycl/include/sycl/__impl/platform.hpp
+++ b/libsycl/include/sycl/__impl/platform.hpp
@@ -29,7 +29,7 @@ namespace detail {
 class platform_impl;
 } // namespace detail
 
-// 4.6.2. Platform class
+// SYCL 2020 4.6.2. Platform class
 class _LIBSYCL_EXPORT platform {
 public:
   /// Constructs a platform object that is a copy of the platform which contains
diff --git a/libsycl/src/exception.cpp b/libsycl/src/exception.cpp
index 88ffb527f4bef..43fb6e41da78a 100644
--- a/libsycl/src/exception.cpp
+++ b/libsycl/src/exception.cpp
@@ -12,7 +12,6 @@
 ///
 //===----------------------------------------------------------------------===//
 
-// 4.9.2 Exception Class Interface
 #include <sycl/__impl/detail/config.hpp>
 #include <sycl/__impl/exception.hpp>
 
diff --git a/libsycl/src/version.hpp.in b/libsycl/src/version.hpp.in
index a7215761e9d4c..e4a4f957e3eca 100644
--- a/libsycl/src/version.hpp.in
+++ b/libsycl/src/version.hpp.in
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 ///
 /// \file
-/// This file contains the declaration of SYCL RT version macro.
+/// This file contains the declaration of libsycl version macro.
 ///
 //===----------------------------------------------------------------------===//
 #define _LIBSYCL_MAJOR_VERSION ${LIBSYCL_MAJOR_VERSION}
diff --git a/libsycl/tools/sycl-ls/sycl-ls.cpp b/libsycl/tools/sycl-ls/sycl-ls.cpp
index fe49fa1bd50c2..b2dec7da16449 100644
--- a/libsycl/tools/sycl-ls/sycl-ls.cpp
+++ b/libsycl/tools/sycl-ls/sycl-ls.cpp
@@ -21,6 +21,23 @@
 using namespace sycl;
 using namespace std::literals;
 
+inline std::string_view getBackendName(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 "";
+}
+
 int main(int argc, char **argv) {
   llvm::cl::opt<bool> Verbose(
       "verbose",
@@ -40,7 +57,7 @@ int main(int argc, char **argv) {
 
     for (const auto &Platform : Platforms) {
       backend Backend = Platform.get_backend();
-      std::cout << "[" << detail::get_backend_name(Backend) << ":"
+      std::cout << "[" << getBackendName(Backend) << ":"
                 << "unknown" << "]" << std::endl;
     }
 

>From 20d562d947fc79793a13b468c3f45641a1e5fda0 Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Fri, 12 Dec 2025 06:29:51 -0800
Subject: [PATCH 16/16] fix more comments

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/include/sycl/__impl/detail/macro_definitions.hpp | 6 +++---
 libsycl/include/sycl/__impl/detail/obj_utils.hpp         | 4 ++++
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/libsycl/include/sycl/__impl/detail/macro_definitions.hpp b/libsycl/include/sycl/__impl/detail/macro_definitions.hpp
index 0938f4f88f67b..38ab6b1e45479 100644
--- a/libsycl/include/sycl/__impl/detail/macro_definitions.hpp
+++ b/libsycl/include/sycl/__impl/detail/macro_definitions.hpp
@@ -35,9 +35,9 @@ static_assert(__cplusplus >= 201703L, "Libsycl requires C++17 or later.");
 // when linking to a release build of libsycl and with the /MDd option when
 // linking to a debug build.
 #  define ERROR_MESSAGE                                                        \
-    "Libsycl 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."
+    "Libsycl requires use of a DLL version of the MSVC RT library. "           \
+    "Please use /MD to link with a release build of libsycl or /MDd to link"   \
+    " with a debug build."
 #  if defined(_MSC_VER)
 #    pragma message(ERROR_MESSAGE)
 #  else
diff --git a/libsycl/include/sycl/__impl/detail/obj_utils.hpp b/libsycl/include/sycl/__impl/detail/obj_utils.hpp
index ccf14a58ee8be..95a223dbebad5 100644
--- a/libsycl/include/sycl/__impl/detail/obj_utils.hpp
+++ b/libsycl/include/sycl/__impl/detail/obj_utils.hpp
@@ -65,8 +65,12 @@ SyclObject createSyclObjFromImpl(From &&from) {
 template <typename T> struct HashBase {
   size_t operator()(const T &Obj) const {
 #ifdef __SYCL_DEVICE_ONLY__
+#  if __has_builtin(__builtin_unreachable)
+    __builtin_unreachable()
+#  else
     (void)Obj;
     return 0;
+#  endif
 #else
     auto &Impl = sycl::detail::getSyclObjImpl(Obj);
     return std::hash<std::decay_t<decltype(Impl)>>{}(Impl);



More information about the llvm-commits mailing list