DPC++ Runtime
Runtime libraries for oneAPI DPC++
pi.cpp
Go to the documentation of this file.
1 //===-- pi.cpp - PI utilities implementation -------------------*- C++ -*--===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
13 
14 #include "context_impl.hpp"
15 #include <detail/config.hpp>
17 #include <detail/plugin.hpp>
18 #include <detail/xpti_registry.hpp>
19 #include <sycl/context.hpp>
20 #include <sycl/detail/common.hpp>
22 #include <sycl/detail/pi.hpp>
24 #include <sycl/version.hpp>
25 
26 #include <bitset>
27 #include <cstdarg>
28 #include <cstring>
29 #include <iostream>
30 #include <map>
31 #include <sstream>
32 #include <stddef.h>
33 #include <string>
34 #include <tuple>
35 
36 #ifdef XPTI_ENABLE_INSTRUMENTATION
37 // Include the headers necessary for emitting
38 // traces using the trace framework
39 #include "xpti/xpti_trace_framework.h"
40 #endif
41 
42 namespace sycl {
43 inline namespace _V1 {
44 namespace detail {
45 #ifdef XPTI_ENABLE_INSTRUMENTATION
46 // Global (to the SYCL runtime) graph handle that all command groups are a
47 // child of
49 xpti_td *GSYCLGraphEvent = nullptr;
51 xpti_td *GPICallEvent = nullptr;
53 xpti_td *GPIArgCallEvent = nullptr;
54 xpti_td *GPIArgCallActiveEvent = nullptr;
55 
56 uint8_t PiCallStreamID = 0;
57 uint8_t PiDebugCallStreamID = 0;
58 
59 #endif // XPTI_ENABLE_INSTRUMENTATION
60 
61 template <sycl::backend BE> void *getPluginOpaqueData(void *OpaqueDataParam) {
62  void *ReturnOpaqueData = nullptr;
63  const PluginPtr &Plugin = pi::getPlugin<BE>();
64 
66  OpaqueDataParam, &ReturnOpaqueData);
67 
68  return ReturnOpaqueData;
69 }
70 
71 template __SYCL_EXPORT void *
72 getPluginOpaqueData<sycl::backend::ext_intel_esimd_emulator>(void *);
73 
74 namespace pi {
75 
76 static void initializePlugins(std::vector<PluginPtr> &Plugins);
77 
78 bool XPTIInitDone = false;
79 
80 // Implementation of the SYCL PI API call tracing methods that use XPTI
81 // framework to emit these traces that will be used by tools.
82 uint64_t emitFunctionBeginTrace(const char *FName) {
83  uint64_t CorrelationID = 0;
84 #ifdef XPTI_ENABLE_INSTRUMENTATION
85  // The function_begin and function_end trace point types are defined to
86  // trace library API calls and they are currently enabled here for support
87  // tools that need the API scope. The methods emitFunctionBeginTrace() and
88  // emitFunctionEndTrace() can be extended to also trace the arguments of the
89  // PI API call using a trace point type the extends the predefined trace
90  // point types.
91  //
92  // You can use the sample collector in llvm/xptifw/samples/syclpi_collector
93  // to print the API traces and also extend them to support arguments that
94  // may be traced later.
95  //
115  constexpr uint16_t NotificationTraceType =
116  (uint16_t)xpti::trace_point_type_t::function_begin;
117  if (xptiCheckTraceEnabled(PiCallStreamID, NotificationTraceType)) {
118  CorrelationID = xptiGetUniqueId();
119  xptiNotifySubscribers(PiCallStreamID, NotificationTraceType, GPICallEvent,
120  nullptr, CorrelationID,
121  static_cast<const void *>(FName));
122  }
123 #endif // XPTI_ENABLE_INSTRUMENTATION
124  return CorrelationID;
125 }
126 
127 void emitFunctionEndTrace(uint64_t CorrelationID, const char *FName) {
128 #ifdef XPTI_ENABLE_INSTRUMENTATION
129  constexpr uint16_t NotificationTraceType =
130  (uint16_t)xpti::trace_point_type_t::function_end;
131  if (xptiCheckTraceEnabled(PiCallStreamID, NotificationTraceType)) {
132  // CorrelationID is the unique ID that ties together a function_begin and
133  // function_end pair of trace calls. The splitting of a scoped_notify into
134  // two function calls incurs an additional overhead as the StreamID must
135  // be looked up twice.
136  xptiNotifySubscribers(PiCallStreamID, NotificationTraceType, GPICallEvent,
137  nullptr, CorrelationID,
138  static_cast<const void *>(FName));
139  }
140 #endif // XPTI_ENABLE_INSTRUMENTATION
141 }
142 
143 uint64_t emitFunctionWithArgsBeginTrace(uint32_t FuncID, const char *FuncName,
144  unsigned char *ArgsData,
145  pi_plugin Plugin) {
146  uint64_t CorrelationID = 0;
147 #ifdef XPTI_ENABLE_INSTRUMENTATION
148  constexpr uint16_t NotificationTraceType =
149  (uint16_t)xpti::trace_point_type_t::function_with_args_begin;
150  if (xptiCheckTraceEnabled(PiDebugCallStreamID, NotificationTraceType)) {
151  xpti::function_with_args_t Payload{FuncID, FuncName, ArgsData, nullptr,
152  &Plugin};
153  {
155  auto CodeLoc = Tls.query();
156  xpti::payload_t PL = xpti::payload_t(
157  CodeLoc.functionName(), CodeLoc.fileName(), CodeLoc.lineNumber(),
158  CodeLoc.columnNumber(), nullptr);
159  uint64_t InstanceNumber{};
160  assert(GPIArgCallActiveEvent == nullptr);
161  GPIArgCallActiveEvent =
162  xptiMakeEvent("Plugin interface call", &PL, xpti::trace_graph_event,
163  xpti_at::active, &InstanceNumber);
164  }
165 
166  CorrelationID = xptiGetUniqueId();
167  xptiNotifySubscribers(PiDebugCallStreamID, NotificationTraceType,
168  GPIArgCallEvent, GPIArgCallActiveEvent, CorrelationID,
169  &Payload);
170  }
171 #endif
172  return CorrelationID;
173 }
174 
175 void emitFunctionWithArgsEndTrace(uint64_t CorrelationID, uint32_t FuncID,
176  const char *FuncName, unsigned char *ArgsData,
177  pi_result Result, pi_plugin Plugin) {
178 #ifdef XPTI_ENABLE_INSTRUMENTATION
179  constexpr uint16_t NotificationTraceType =
180  (uint16_t)xpti::trace_point_type_t::function_with_args_end;
181  if (xptiCheckTraceEnabled(PiDebugCallStreamID, NotificationTraceType)) {
182  xpti::function_with_args_t Payload{FuncID, FuncName, ArgsData, &Result,
183  &Plugin};
184 
185  xptiNotifySubscribers(PiDebugCallStreamID, NotificationTraceType,
186  GPIArgCallEvent, GPIArgCallActiveEvent, CorrelationID,
187  &Payload);
188  GPIArgCallActiveEvent = nullptr;
189  }
190 #endif
191 }
192 
195  void *user_data) {
196  auto impl = getSyclObjImpl(context);
197  auto contextHandle = reinterpret_cast<pi_context>(impl->getHandleRef());
198  const auto &Plugin = impl->getPlugin();
199  Plugin->call<PiApiKind::piextContextSetExtendedDeleter>(contextHandle, func,
200  user_data);
201 }
202 
204  switch (info) {
206  return "PI_PLATFORM_INFO_PROFILE";
208  return "PI_PLATFORM_INFO_VERSION";
210  return "PI_PLATFORM_INFO_NAME";
212  return "PI_PLATFORM_INFO_VENDOR";
214  return "PI_PLATFORM_INFO_EXTENSIONS";
216  return "PI_EXT_PLATFORM_INFO_BACKEND";
217  }
218  die("Unknown pi_platform_info value passed to "
219  "sycl::detail::pi::platformInfoToString");
220 }
221 
222 std::string memFlagToString(pi_mem_flags Flag) {
223  assertion(((Flag == 0u) || ((Flag & (Flag - 1)) == 0)) &&
224  "More than one bit set");
225 
226  std::stringstream Sstream;
227 
228  switch (Flag) {
229  case pi_mem_flags{0}:
230  Sstream << "pi_mem_flags(0)";
231  break;
233  Sstream << "PI_MEM_FLAGS_ACCESS_RW";
234  break;
236  Sstream << "PI_MEM_FLAGS_HOST_PTR_USE";
237  break;
239  Sstream << "PI_MEM_FLAGS_HOST_PTR_COPY";
240  break;
241  default:
242  Sstream << "unknown pi_mem_flags bit == " << Flag;
243  }
244 
245  return Sstream.str();
246 }
247 
248 std::string memFlagsToString(pi_mem_flags Flags) {
249  std::stringstream Sstream;
250  bool FoundFlag = false;
251 
252  auto FlagSeparator = [](bool FoundFlag) { return FoundFlag ? "|" : ""; };
253 
254  pi_mem_flags ValidFlags[] = {PI_MEM_FLAGS_ACCESS_RW,
257 
258  if (Flags == 0u) {
259  Sstream << "pi_mem_flags(0)";
260  } else {
261  for (const auto Flag : ValidFlags) {
262  if (Flag & Flags) {
263  Sstream << FlagSeparator(FoundFlag) << memFlagToString(Flag);
264  FoundFlag = true;
265  }
266  }
267 
268  std::bitset<64> UnkownBits(Flags & ~(PI_MEM_FLAGS_ACCESS_RW |
271  if (UnkownBits.any()) {
272  Sstream << FlagSeparator(FoundFlag)
273  << "unknown pi_mem_flags bits == " << UnkownBits;
274  }
275  }
276 
277  return Sstream.str();
278 }
279 
280 // GlobalPlugin is a global Plugin used with Interoperability constructors that
281 // use OpenCL objects to construct SYCL class objects.
282 // TODO: GlobalPlugin does not seem to be needed anymore. Consider removing it!
283 std::shared_ptr<plugin> GlobalPlugin;
284 
285 // Find the plugin at the appropriate location and return the location.
286 std::vector<std::pair<std::string, backend>> findPlugins() {
287  std::vector<std::pair<std::string, backend>> PluginNames;
288 
289  // TODO: Based on final design discussions, change the location where the
290  // plugin must be searched; how to identify the plugins etc. Currently the
291  // search is done for libpi_opencl.so/pi_opencl.dll file in LD_LIBRARY_PATH
292  // env only.
293  //
295  if (!OdsTargetList) {
296  PluginNames.emplace_back(__SYCL_OPENCL_PLUGIN_NAME, backend::opencl);
297  PluginNames.emplace_back(__SYCL_LEVEL_ZERO_PLUGIN_NAME,
299  PluginNames.emplace_back(__SYCL_CUDA_PLUGIN_NAME, backend::ext_oneapi_cuda);
300  PluginNames.emplace_back(__SYCL_HIP_PLUGIN_NAME, backend::ext_oneapi_hip);
301  PluginNames.emplace_back(__SYCL_UR_PLUGIN_NAME, backend::all);
302  PluginNames.emplace_back(__SYCL_NATIVE_CPU_PLUGIN_NAME,
304 
305  } else {
306  ods_target_list &list = *OdsTargetList;
308  PluginNames.emplace_back(__SYCL_OPENCL_PLUGIN_NAME, backend::opencl);
309  }
311  PluginNames.emplace_back(__SYCL_LEVEL_ZERO_PLUGIN_NAME,
313  }
315  PluginNames.emplace_back(__SYCL_CUDA_PLUGIN_NAME,
317  }
319  PluginNames.emplace_back(__SYCL_HIP_PLUGIN_NAME, backend::ext_oneapi_hip);
320  }
322  PluginNames.emplace_back(__SYCL_NATIVE_CPU_PLUGIN_NAME,
324  }
325  PluginNames.emplace_back(__SYCL_UR_PLUGIN_NAME, backend::all);
326  }
327  return PluginNames;
328 }
329 
330 // Load the Plugin by calling the OS dependent library loading call.
331 // Return the handle to the Library.
332 void *loadPlugin(const std::string &PluginPath) {
333  return loadOsPluginLibrary(PluginPath);
334 }
335 
336 // Unload the given plugin by calling teh OS-specific library unloading call.
337 // \param Library OS-specific library handle created when loading.
338 int unloadPlugin(void *Library) { return unloadOsPluginLibrary(Library); }
339 
340 // Binds all the PI Interface APIs to Plugin Library Function Addresses.
341 // TODO: Remove the 'OclPtr' extension to PI_API.
342 // TODO: Change the functionality such that a single getOsLibraryFuncAddress
343 // call is done to get all Interface API mapping. The plugin interface also
344 // needs to setup infrastructure to route PI_CALLs to the appropriate plugins.
345 // Currently, we bind to a singe plugin.
346 bool bindPlugin(void *Library,
347  const std::shared_ptr<PiPlugin> &PluginInformation) {
348 
349  decltype(::piPluginInit) *PluginInitializeFunction =
350  (decltype(&::piPluginInit))(getOsLibraryFuncAddress(Library,
351  "piPluginInit"));
352  if (PluginInitializeFunction == nullptr)
353  return false;
354 
355  int Err = PluginInitializeFunction(PluginInformation.get());
356 
357  // TODO: Compare Supported versions and check for backward compatibility.
358  // Make sure err is PI_SUCCESS.
359  assert((Err == PI_SUCCESS) && "Unexpected error when binding to Plugin.");
360  (void)Err;
361 
362  // TODO: Return a more meaningful value/enum.
363  return true;
364 }
365 
366 bool trace(TraceLevel Level) {
367  auto TraceLevelMask = SYCLConfig<SYCL_PI_TRACE>::get();
368  return (TraceLevelMask & Level) == Level;
369 }
370 
371 // Initializes all available Plugins.
372 std::vector<PluginPtr> &initialize() {
373  // This uses static variable initialization to work around a gcc bug with
374  // std::call_once and exceptions.
375  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146
376  auto initializeHelper = []() {
378  return true;
379  };
380  static bool Initialized = initializeHelper();
381  std::ignore = Initialized;
382 
384 }
385 
386 // Implementation of this function is OS specific. Please see windows_pi.cpp and
387 // posix_pi.cpp.
388 // TODO: refactor code when support matrix for DPCPP changes and <filesystem> is
389 // available on all supported systems.
390 std::vector<std::tuple<std::string, backend, void *>>
391 loadPlugins(const std::vector<std::pair<std::string, backend>> &&PluginNames);
392 
393 static void initializePlugins(std::vector<PluginPtr> &Plugins) {
394  const std::vector<std::pair<std::string, backend>> PluginNames =
395  findPlugins();
396 
397  if (PluginNames.empty() && trace(PI_TRACE_ALL))
398  std::cerr << "SYCL_PI_TRACE[all]: "
399  << "No Plugins Found." << std::endl;
400 
401  // Get library handles for the list of plugins.
402  std::vector<std::tuple<std::string, backend, void *>> LoadedPlugins =
403  loadPlugins(std::move(PluginNames));
404 
405  bool IsAsanUsed = ProgramManager::getInstance().kernelUsesAsan();
406 
407  for (auto &[Name, Backend, Library] : LoadedPlugins) {
408  std::shared_ptr<PiPlugin> PluginInformation =
409  std::make_shared<PiPlugin>(PiPlugin{
411  /*Targets=*/nullptr, /*FunctionPointers=*/{},
412  /*IsAsanUsed*/
414 
415  if (!Library) {
416  if (trace(PI_TRACE_ALL)) {
417  std::cerr << "SYCL_PI_TRACE[all]: "
418  << "Check if plugin is present. "
419  << "Failed to load plugin: " << Name << std::endl;
420  }
421  continue;
422  }
423 
424  if (!bindPlugin(Library, PluginInformation)) {
425  if (trace(PI_TRACE_ALL)) {
426  std::cerr << "SYCL_PI_TRACE[all]: "
427  << "Failed to bind PI APIs to the plugin: " << Name
428  << std::endl;
429  }
430  continue;
431  }
432  PluginPtr &NewPlugin = Plugins.emplace_back(
433  std::make_shared<plugin>(PluginInformation, Backend, Library));
435  std::cerr << "SYCL_PI_TRACE[basic]: "
436  << "Plugin found and successfully loaded: " << Name
437  << " [ PluginVersion: "
438  << NewPlugin->getPiPlugin().PluginVersion << " ]" << std::endl;
439  }
440 
441 #ifdef XPTI_ENABLE_INSTRUMENTATION
443 
444  if (!(xptiTraceEnabled() && !XPTIInitDone))
445  return;
446  // Not sure this is the best place to initialize the framework; SYCL runtime
447  // team needs to advise on the right place, until then we piggy-back on the
448  // initialization of the PI layer.
449 
450  // Initialize the global events just once, in the case pi::initialize() is
451  // called multiple times
452  XPTIInitDone = true;
453  // Registers a new stream for 'sycl' and any plugin that wants to listen to
454  // this stream will register itself using this string or stream ID for this
455  // string.
456  uint8_t StreamID = xptiRegisterStream(SYCL_STREAM_NAME);
457  // Let all tool plugins know that a stream by the name of 'sycl' has been
458  // initialized and will be generating the trace stream.
461  // Create a tracepoint to indicate the graph creation
462  xpti::payload_t GraphPayload("application_graph");
463  uint64_t GraphInstanceNo;
464  GSYCLGraphEvent =
465  xptiMakeEvent("application_graph", &GraphPayload, xpti::trace_graph_event,
466  xpti_at::active, &GraphInstanceNo);
467  if (GSYCLGraphEvent) {
468  // The graph event is a global event and will be used as the parent for
469  // all nodes (command groups)
470  xptiNotifySubscribers(StreamID, xpti::trace_graph_create, nullptr,
471  GSYCLGraphEvent, GraphInstanceNo, nullptr);
472  }
473 
474  // Let subscribers know a new stream is being initialized
477  xpti::payload_t PIPayload("Plugin Interface Layer");
478  uint64_t PiInstanceNo;
479  GPICallEvent =
480  xptiMakeEvent("PI Layer", &PIPayload, xpti::trace_algorithm_event,
481  xpti_at::active, &PiInstanceNo);
482 
485  xpti::payload_t PIArgPayload(
486  "Plugin Interface Layer (with function arguments)");
487  uint64_t PiArgInstanceNo;
488  GPIArgCallEvent = xptiMakeEvent("PI Layer with arguments", &PIArgPayload,
489  xpti::trace_algorithm_event, xpti_at::active,
490  &PiArgInstanceNo);
491 
492  PiCallStreamID = xptiRegisterStream(SYCL_PICALL_STREAM_NAME);
493  PiDebugCallStreamID = xptiRegisterStream(SYCL_PIDEBUGCALL_STREAM_NAME);
494 #endif
495 }
496 
497 // Get the plugin serving given backend.
498 template <backend BE> const PluginPtr &getPlugin() {
499  static PluginPtr *Plugin = nullptr;
500  if (Plugin)
501  return *Plugin;
502 
503  std::vector<PluginPtr> &Plugins = pi::initialize();
504  for (auto &P : Plugins)
505  if (P->hasBackend(BE)) {
506  Plugin = &P;
507  return *Plugin;
508  }
509 
510  throw runtime_error("pi::getPlugin couldn't find plugin",
511  PI_ERROR_INVALID_OPERATION);
512 }
513 
514 template __SYCL_EXPORT const PluginPtr &getPlugin<backend::opencl>();
515 template __SYCL_EXPORT const PluginPtr &
516 getPlugin<backend::ext_oneapi_level_zero>();
517 template __SYCL_EXPORT const PluginPtr &
518 getPlugin<backend::ext_intel_esimd_emulator>();
519 template __SYCL_EXPORT const PluginPtr &getPlugin<backend::ext_oneapi_cuda>();
520 template __SYCL_EXPORT const PluginPtr &getPlugin<backend::ext_oneapi_hip>();
521 
522 // Report error and no return (keeps compiler from printing warnings).
523 // TODO: Probably change that to throw a catchable exception,
524 // but for now it is useful to see every failure.
525 //
526 [[noreturn]] void die(const char *Message) {
527  std::cerr << "pi_die: " << Message << std::endl;
528  std::terminate();
529 }
530 
531 void assertion(bool Condition, const char *Message) {
532  if (!Condition)
533  die(Message);
534 }
535 
536 // Reads an integer value from ELF data.
537 template <typename ResT>
538 static ResT readELFValue(const unsigned char *Data, size_t NumBytes,
539  bool IsBigEndian) {
540  assert(NumBytes <= sizeof(ResT));
541  ResT Result = 0;
542  if (IsBigEndian) {
543  for (size_t I = 0; I < NumBytes; ++I) {
544  Result = (Result << 8) | static_cast<ResT>(Data[I]);
545  }
546  } else {
547  std::copy(Data, Data + NumBytes, reinterpret_cast<char *>(&Result));
548  }
549  return Result;
550 }
551 
552 // Checks if an ELF image contains a section with a specified name.
553 static bool checkELFSectionPresent(const std::string &ExpectedSectionName,
554  const unsigned char *ImgData,
555  size_t ImgSize) {
556  // Check for 64bit and big-endian.
557  bool Is64bit = ImgData[4] == 2;
558  bool IsBigEndian = ImgData[5] == 2;
559 
560  // Make offsets based on whether the ELF file is 64bit or not.
561  size_t SectionHeaderOffsetInfoOffset = Is64bit ? 0x28 : 0x20;
562  size_t SectionHeaderSizeInfoOffset = Is64bit ? 0x3A : 0x2E;
563  size_t SectionHeaderNumInfoOffset = Is64bit ? 0x3C : 0x30;
564  size_t SectionStringsHeaderIndexInfoOffset = Is64bit ? 0x3E : 0x32;
565 
566  // if the image doesn't contain enough data for the header values, end early.
567  if (ImgSize < SectionStringsHeaderIndexInfoOffset + 2)
568  return false;
569 
570  // Read the e_shoff, e_shentsize, e_shnum, and e_shstrndx entries in the
571  // header.
572  uint64_t SectionHeaderOffset = readELFValue<uint64_t>(
573  ImgData + SectionHeaderOffsetInfoOffset, Is64bit ? 8 : 4, IsBigEndian);
574  uint16_t SectionHeaderSize = readELFValue<uint16_t>(
575  ImgData + SectionHeaderSizeInfoOffset, 2, IsBigEndian);
576  uint16_t SectionHeaderNum = readELFValue<uint16_t>(
577  ImgData + SectionHeaderNumInfoOffset, 2, IsBigEndian);
578  uint16_t SectionStringsHeaderIndex = readELFValue<uint16_t>(
579  ImgData + SectionStringsHeaderIndexInfoOffset, 2, IsBigEndian);
580 
581  // End early if we do not have the expected number of section headers or
582  // if the read section string header index is out-of-range.
583  if (ImgSize < SectionHeaderOffset + SectionHeaderNum * SectionHeaderSize ||
584  SectionStringsHeaderIndex >= SectionHeaderNum)
585  return false;
586 
587  // Get the location of the section string data.
588  size_t SectionStringsInfoOffset = Is64bit ? 0x18 : 0x10;
589  const unsigned char *SectionStringsHeaderData =
590  ImgData + SectionHeaderOffset +
591  SectionStringsHeaderIndex * SectionHeaderSize;
592  uint64_t SectionStrings = readELFValue<uint64_t>(
593  SectionStringsHeaderData + SectionStringsInfoOffset, Is64bit ? 8 : 4,
594  IsBigEndian);
595  const unsigned char *SectionStringsData = ImgData + SectionStrings;
596 
597  // For each section, check the name against the expected section and return
598  // true if we find it.
599  for (size_t I = 0; I < SectionHeaderNum; ++I) {
600  // Get the offset into the section string data of this sections name.
601  const unsigned char *HeaderData =
602  ImgData + SectionHeaderOffset + I * SectionHeaderSize;
603  uint32_t SectionNameOffset =
604  readELFValue<uint32_t>(HeaderData, 4, IsBigEndian);
605 
606  // Read the section name and check if it is the same as the name we are
607  // looking for.
608  const char *SectionName =
609  reinterpret_cast<const char *>(SectionStringsData + SectionNameOffset);
610  if (SectionName == ExpectedSectionName)
611  return true;
612  }
613  return false;
614 }
615 
616 // Returns the e_type field from an ELF image.
617 static uint16_t getELFHeaderType(const unsigned char *ImgData, size_t ImgSize) {
618  (void)ImgSize;
619  assert(ImgSize >= 18 && "Not enough bytes to have an ELF header type.");
620 
621  bool IsBigEndian = ImgData[5] == 2;
622  return readELFValue<uint16_t>(ImgData + 16, 2, IsBigEndian);
623 }
624 
626 getBinaryImageFormat(const unsigned char *ImgData, size_t ImgSize) {
627  // Top-level magic numbers for the recognized binary image formats.
628  auto MatchMagicNumber = [&](auto Number) {
629  return ImgSize >= sizeof(Number) &&
630  std::memcmp(ImgData, &Number, sizeof(Number)) == 0;
631  };
632 
633  if (MatchMagicNumber(uint32_t{0x07230203}))
635 
636  if (MatchMagicNumber(uint32_t{0xDEC04342}))
638 
639  if (MatchMagicNumber(uint32_t{0x43544E49}))
640  // 'I', 'N', 'T', 'C' ; Intel native
642 
643  // Check for ELF format, size requirements include data we'll read in case of
644  // succesful match.
645  if (ImgSize >= 18 && MatchMagicNumber(uint32_t{0x464c457F})) {
646  uint16_t ELFHdrType = getELFHeaderType(ImgData, ImgSize);
647  if (ELFHdrType == 0xFF04)
648  // OpenCL executable.
650 
651  if (ELFHdrType == 0xFF12)
652  // ZEBIN executable.
654 
655  // Newer ZEBIN format does not have a special header type, but can instead
656  // be identified by having a required .ze_info section.
657  if (checkELFSectionPresent(".ze_info", ImgData, ImgSize))
659  }
660 
661  if (MatchMagicNumber(std::array{'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}))
662  // "ar" format is used to pack binaries for multiple devices, e.g. via
663  //
664  // -Xsycl-target-backend=spir64_gen "-device acm-g10,acm-g11"
665  //
666  // option.
668 
670 }
671 
672 } // namespace pi
673 } // namespace detail
674 } // namespace _V1
675 } // namespace sycl
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:50
std::vector< PluginPtr > & getPlugins()
static GlobalHandler & instance()
static ProgramManager & getInstance()
static const char * get()
Definition: config.hpp:115
void initializeStream(const std::string &StreamName, uint32_t MajVer, uint32_t MinVer, const std::string &VerStr)
Notifies XPTI subscribers about new stream.
bool backendCompatible(backend Backend)
Data type that manages the code_location information in TLS.
Definition: common.hpp:129
const detail::code_location & query()
Query the information in the TLS slot.
Definition: common.cpp:54
__SYCL_EXTERN_STREAM_ATTRS ostream cerr
Linked to standard error (unbuffered)
std::string memFlagToString(pi_mem_flags Flag)
Definition: pi.cpp:222
static bool checkELFSectionPresent(const std::string &ExpectedSectionName, const unsigned char *ImgData, size_t ImgSize)
Definition: pi.cpp:553
void contextSetExtendedDeleter(const sycl::context &constext, pi_context_extended_deleter func, void *user_data)
Definition: pi.cpp:193
std::string memFlagsToString(pi_mem_flags Flags)
Definition: pi.cpp:248
void emitFunctionEndTrace(uint64_t CorrelationID, const char *FName)
Emits an XPTI trace after the PI API call has been made.
Definition: pi.cpp:127
static void initializePlugins(std::vector< PluginPtr > &Plugins)
Definition: pi.cpp:393
void * loadOsPluginLibrary(const std::string &Library)
Definition: posix_pi.cpp:33
std::vector< PluginPtr > & initialize()
Definition: pi.cpp:372
void die(const char *Message)
Definition: pi.cpp:526
uint64_t emitFunctionBeginTrace(const char *FName)
Emits an XPTI trace before a PI API call is made.
Definition: pi.cpp:82
void assertion(bool Condition, const char *Message=nullptr)
Definition: pi.cpp:531
std::vector< std::pair< std::string, backend > > findPlugins()
Definition: pi.cpp:286
void * loadPlugin(const std::string &PluginPath)
Definition: pi.cpp:332
PiDeviceBinaryType getBinaryImageFormat(const unsigned char *ImgData, size_t ImgSize)
Tries to determine the device binary image foramat.
Definition: pi.cpp:626
bool trace(TraceLevel level)
Definition: pi.cpp:366
static ResT readELFValue(const unsigned char *Data, size_t NumBytes, bool IsBigEndian)
Definition: pi.cpp:538
uint64_t emitFunctionWithArgsBeginTrace(uint32_t FuncID, const char *FName, unsigned char *ArgsData, pi_plugin Plugin)
Notifies XPTI subscribers about PI function calls and packs call arguments.
Definition: pi.cpp:143
std::string platformInfoToString(pi_platform_info info)
Definition: pi.cpp:203
std::shared_ptr< plugin > GlobalPlugin
Definition: pi.cpp:283
void emitFunctionWithArgsEndTrace(uint64_t CorrelationID, uint32_t FuncID, const char *FName, unsigned char *ArgsData, pi_result Result, pi_plugin Plugin)
Notifies XPTI subscribers about PI function call result.
Definition: pi.cpp:175
bool bindPlugin(void *Library, const std::shared_ptr< PiPlugin > &PluginInformation)
Definition: pi.cpp:346
static uint16_t getELFHeaderType(const unsigned char *ImgData, size_t ImgSize)
Definition: pi.cpp:617
::pi_device_binary_type PiDeviceBinaryType
Definition: pi.hpp:117
void * getOsLibraryFuncAddress(void *Library, const std::string &FunctionName)
Definition: posix_pi.cpp:47
int unloadOsPluginLibrary(void *Library)
Definition: posix_pi.cpp:39
std::vector< std::tuple< std::string, backend, void * > > loadPlugins(const std::vector< std::pair< std::string, backend >> &&PluginNames)
Definition: posix_pi.cpp:53
int unloadPlugin(void *Library)
Definition: pi.cpp:338
constexpr const char * SYCL_PIDEBUGCALL_STREAM_NAME
constexpr const char * SYCL_STREAM_NAME
static const PluginPtr & getPlugin(backend Backend)
Definition: backend.cpp:32
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:30
void * getPluginOpaqueData(void *opaquedata_arg)
Definition: pi.cpp:61
std::shared_ptr< plugin > PluginPtr
Definition: pi.hpp:47
constexpr const char * SYCL_PICALL_STREAM_NAME
void copy(handler &CGH, const T *Src, T *Dest, size_t Count)
Definition: access.hpp:18
static constexpr pi_device_binary_type PI_DEVICE_BINARY_TYPE_LLVMIR_BITCODE
Definition: pi.h:975
_pi_result
Definition: pi.h:235
#define _PI_H_VERSION_STRING
Definition: pi.h:195
static constexpr pi_device_binary_type PI_DEVICE_BINARY_TYPE_NATIVE
Definition: pi.h:970
pi_result piextPluginGetOpaqueData(void *opaque_data_param, void **opaque_data_return)
API to get Plugin internal data, opaque to SYCL RT.
Definition: pi_cuda.cpp:1245
_pi_platform_info
Definition: pi.h:250
@ PI_PLATFORM_INFO_VENDOR
Definition: pi.h:254
@ PI_PLATFORM_INFO_EXTENSIONS
Definition: pi.h:251
@ PI_PLATFORM_INFO_PROFILE
Definition: pi.h:253
@ PI_EXT_PLATFORM_INFO_BACKEND
Definition: pi.h:256
@ PI_PLATFORM_INFO_NAME
Definition: pi.h:252
@ PI_PLATFORM_INFO_VERSION
Definition: pi.h:255
constexpr pi_mem_flags PI_MEM_FLAGS_HOST_PTR_COPY
Definition: pi.h:791
pi_bitfield pi_mem_flags
Definition: pi.h:785
static constexpr pi_device_binary_type PI_DEVICE_BINARY_TYPE_SPIRV
Definition: pi.h:973
constexpr pi_mem_flags PI_MEM_FLAGS_HOST_PTR_USE
Definition: pi.h:790
void(* pi_context_extended_deleter)(void *user_data)
Definition: pi.h:1368
pi_result piPluginInit(pi_plugin *plugin_info)
Definition: pi_cuda.cpp:1282
@ _PI_SANITIZE_TYPE_ADDRESS
Definition: pi.h:2943
@ _PI_SANITIZE_TYPE_NONE
Definition: pi.h:2942
constexpr pi_mem_flags PI_MEM_FLAGS_ACCESS_RW
Definition: pi.h:787
pi_result piextContextSetExtendedDeleter(pi_context context, pi_context_extended_deleter func, void *user_data)
Definition: pi_cuda.cpp:132
static constexpr pi_device_binary_type PI_DEVICE_BINARY_TYPE_NONE
Definition: pi.h:968
C++ wrapper of extern "C" PI interfaces.
constexpr int GMajVer
Definition: tracing.cpp:27
constexpr int GMinVer
Definition: tracing.cpp:28
constexpr auto GVerStr
Definition: tracing.cpp:26