DPC++ Runtime
Runtime libraries for oneAPI DPC++
common.hpp
Go to the documentation of this file.
1 //==---------- common.hpp ----- Common declarations ------------------------==//
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 
9 #pragma once
10 
11 #include <sycl/detail/defines_elementary.hpp> // for __SYCL_ALWAYS_INLINE
12 #include <sycl/detail/export.hpp> // for __SYCL_EXPORT
13 #include <ur_api.h> // for ur_code_location_t
14 
15 #include <array> // for array
16 #include <cassert> // for assert
17 #include <cstddef> // for size_t
18 #include <string> // for allocator, operator+
19 #include <type_traits> // for enable_if_t
20 #include <utility> // for index_sequence, make_i...
21 
22 // Default signature enables the passing of user code location information to
23 // public methods as a default argument.
24 namespace sycl {
25 inline namespace _V1 {
26 namespace detail {
27 
28 // The check for output iterator is commented out as it blocks set_final_data
29 // with void * argument to be used.
30 // TODO: Align these checks with the SYCL specification when the behaviour
31 // with void * is clarified.
32 template <typename DataT>
33 using EnableIfOutputPointerT = std::enable_if_t<
34  /*is_output_iterator<DataT>::value &&*/ std::is_pointer_v<DataT>>;
35 
36 template <typename DataT>
37 using EnableIfOutputIteratorT = std::enable_if_t<
38  /*is_output_iterator<DataT>::value &&*/ !std::is_pointer_v<DataT>>;
39 
40 #if !defined(NDEBUG) && (_MSC_VER > 1929 || __has_builtin(__builtin_FILE))
41 #define __CODELOC_FILE_NAME __builtin_FILE()
42 #else
43 #define __CODELOC_FILE_NAME nullptr
44 #endif
45 
46 #if _MSC_VER > 1929 || __has_builtin(__builtin_FUNCTION)
47 #define __CODELOC_FUNCTION __builtin_FUNCTION()
48 #else
49 #define __CODELOC_FUNCTION nullptr
50 #endif
51 
52 #if _MSC_VER > 1929 || __has_builtin(__builtin_LINE)
53 #define __CODELOC_LINE __builtin_LINE()
54 #else
55 #define __CODELOC_LINE 0
56 #endif
57 
58 #if _MSC_VER > 1929 || __has_builtin(__builtin_COLUMN)
59 #define __CODELOC_COLUMN __builtin_COLUMN()
60 #else
61 #define __CODELOC_COLUMN 0
62 #endif
63 
64 // Data structure that captures the user code location information using the
65 // builtin capabilities of the compiler
66 struct code_location {
67  static constexpr code_location
69  const char *funcName = __CODELOC_FUNCTION,
70  unsigned long lineNo = __CODELOC_LINE,
71  unsigned long columnNo = __CODELOC_COLUMN) noexcept {
72  return code_location(fileName, funcName, lineNo, columnNo);
73  }
74 
75 #undef __CODELOC_FILE_NAME
76 #undef __CODELOC_FUNCTION
77 #undef __CODELOC_LINE
78 #undef __CODELOC_COLUMN
79 
80  constexpr code_location(const char *file, const char *func, int line,
81  int col) noexcept
82  : MFileName(file), MFunctionName(func), MLineNo(line), MColumnNo(col) {}
83 
84  constexpr code_location() noexcept
85  : MFileName(nullptr), MFunctionName(nullptr), MLineNo(0), MColumnNo(0) {}
86 
87  constexpr unsigned long lineNumber() const noexcept { return MLineNo; }
88  constexpr unsigned long columnNumber() const noexcept { return MColumnNo; }
89  constexpr const char *fileName() const noexcept { return MFileName; }
90  constexpr const char *functionName() const noexcept { return MFunctionName; }
91 
92 private:
93  const char *MFileName;
94  const char *MFunctionName;
95  unsigned long MLineNo;
96  unsigned long MColumnNo;
97 };
98 
99 ur_code_location_t codeLocationCallback(void *);
100 
131 class __SYCL_EXPORT tls_code_loc_t {
132 public:
136  tls_code_loc_t();
139  tls_code_loc_t(const detail::code_location &CodeLoc);
141  ~tls_code_loc_t();
145  const detail::code_location &query();
146 
147 private:
148  // The flag that is used to determine if the object is in a local scope or in
149  // the top level scope.
150  bool MLocalScope = true;
151 };
152 
153 } // namespace detail
154 } // namespace _V1
155 } // namespace sycl
156 
157 #ifdef __SYCL_DEVICE_ONLY__
158 // TODO remove this when 'assert' is supported in device code
159 #define __SYCL_ASSERT(x)
160 #else
161 #define __SYCL_ASSERT(x) assert(x)
162 #endif // #ifdef __SYCL_DEVICE_ONLY__
163 
164 #define __SYCL_UR_ERROR_REPORT \
165  "Native API failed. " /*__FILE__*/ \
166  /* TODO: replace __FILE__ to report only relative path*/ \
167  /* ":" __SYCL_STRINGIFY(__LINE__) ": " */ \
168  "Native API returns: "
169 
170 #include <sycl/exception.hpp>
171 
172 namespace sycl {
173 inline namespace _V1 {
174 namespace detail {
175 // Produces N-dimensional object of type T whose all components are initialized
176 // to given integer value.
177 template <int N, template <int> class T> struct InitializedVal {
178  template <int Val> static T<N> get();
179 };
180 
181 // Specialization for a one-dimensional type.
182 template <template <int> class T> struct InitializedVal<1, T> {
183  template <int Val> static T<1> get() { return T<1>{Val}; }
184 };
185 
186 // Specialization for a two-dimensional type.
187 template <template <int> class T> struct InitializedVal<2, T> {
188  template <int Val> static T<2> get() { return T<2>{Val, Val}; }
189 };
190 
191 // Specialization for a three-dimensional type.
192 template <template <int> class T> struct InitializedVal<3, T> {
193  template <int Val> static T<3> get() { return T<3>{Val, Val, Val}; }
194 };
195 
197 template <int NDims, int Dim, template <int> class LoopBoundTy, typename FuncTy,
198  template <int> class LoopIndexTy>
200  NDLoopIterateImpl(const LoopIndexTy<NDims> &LowerBound,
201  const LoopBoundTy<NDims> &Stride,
202  const LoopBoundTy<NDims> &UpperBound, FuncTy f,
203  LoopIndexTy<NDims> &Index) {
204  constexpr size_t AdjIdx = NDims - 1 - Dim;
205  for (Index[AdjIdx] = LowerBound[AdjIdx]; Index[AdjIdx] < UpperBound[AdjIdx];
206  Index[AdjIdx] += Stride[AdjIdx]) {
207 
208  NDLoopIterateImpl<NDims, Dim - 1, LoopBoundTy, FuncTy, LoopIndexTy>{
209  LowerBound, Stride, UpperBound, f, Index};
210  }
211  }
212 };
213 
214 // Specialization for Dim=0 to terminate recursion
215 template <int NDims, template <int> class LoopBoundTy, typename FuncTy,
216  template <int> class LoopIndexTy>
217 struct NDLoopIterateImpl<NDims, 0, LoopBoundTy, FuncTy, LoopIndexTy> {
218  NDLoopIterateImpl(const LoopIndexTy<NDims> &LowerBound,
219  const LoopBoundTy<NDims> &Stride,
220  const LoopBoundTy<NDims> &UpperBound, FuncTy f,
221  LoopIndexTy<NDims> &Index) {
222 
223  constexpr size_t AdjIdx = NDims - 1;
224  for (Index[AdjIdx] = LowerBound[AdjIdx]; Index[AdjIdx] < UpperBound[AdjIdx];
225  Index[AdjIdx] += Stride[AdjIdx]) {
226 
227  f(Index);
228  }
229  }
230 };
231 
238 template <int NDims> struct NDLoop {
242  template <template <int> class LoopBoundTy, typename FuncTy,
243  template <int> class LoopIndexTy = LoopBoundTy>
244  static __SYCL_ALWAYS_INLINE void iterate(const LoopBoundTy<NDims> &UpperBound,
245  FuncTy f) {
246  const LoopIndexTy<NDims> LowerBound =
248  const LoopBoundTy<NDims> Stride =
250  LoopIndexTy<NDims> Index =
252 
253  NDLoopIterateImpl<NDims, NDims - 1, LoopBoundTy, FuncTy, LoopIndexTy>{
254  LowerBound, Stride, UpperBound, f, Index};
255  }
256 
260  template <template <int> class LoopBoundTy, typename FuncTy,
261  template <int> class LoopIndexTy = LoopBoundTy>
262  static __SYCL_ALWAYS_INLINE void iterate(const LoopIndexTy<NDims> &LowerBound,
263  const LoopBoundTy<NDims> &Stride,
264  const LoopBoundTy<NDims> &UpperBound,
265  FuncTy f) {
266  LoopIndexTy<NDims> Index =
268  NDLoopIterateImpl<NDims, NDims - 1, LoopBoundTy, FuncTy, LoopIndexTy>{
269  LowerBound, Stride, UpperBound, f, Index};
270  }
271 };
272 
273 constexpr size_t getNextPowerOfTwoHelper(size_t Var, size_t Offset) {
274  return Offset != 64
275  ? getNextPowerOfTwoHelper(Var | (Var >> Offset), Offset * 2)
276  : Var;
277 }
278 
279 // Returns the smallest power of two not less than Var
280 constexpr size_t getNextPowerOfTwo(size_t Var) {
281  return getNextPowerOfTwoHelper(Var - 1, 1) + 1;
282 }
283 
284 // Returns linear index by given index and range
285 template <int Dims, template <int> class T, template <int> class U>
286 size_t getLinearIndex(const T<Dims> &Index, const U<Dims> &Range) {
287  size_t LinearIndex = 0;
288  for (int I = 0; I < Dims; ++I)
289  LinearIndex = LinearIndex * Range[I] + Index[I];
290  return LinearIndex;
291 }
292 
293 template <typename T> struct InlineVariableHelper {
294  static constexpr T value{};
295 };
296 
297 template <typename T> constexpr T InlineVariableHelper<T>::value;
298 
299 // The function extends or truncates number of dimensions of objects of id
300 // or ranges classes. When extending the new values are filled with
301 // DefaultValue, truncation just removes extra values.
302 template <int NewDim, int DefaultValue, template <int> class T, int OldDim>
303 static T<NewDim> convertToArrayOfN(T<OldDim> OldObj) {
305  const int CopyDims = NewDim > OldDim ? OldDim : NewDim;
306  for (int I = 0; I < CopyDims; ++I)
307  NewObj[I] = OldObj[I];
308  for (int I = CopyDims; I < NewDim; ++I)
309  NewObj[I] = DefaultValue;
310  return NewObj;
311 }
312 
313 // Helper function for concatenating two std::array.
314 template <typename T, std::size_t... Is1, std::size_t... Is2>
315 constexpr std::array<T, sizeof...(Is1) + sizeof...(Is2)>
316 ConcatArrays(const std::array<T, sizeof...(Is1)> &A1,
317  const std::array<T, sizeof...(Is2)> &A2,
318  std::index_sequence<Is1...>, std::index_sequence<Is2...>) {
319  return {A1[Is1]..., A2[Is2]...};
320 }
321 template <typename T, std::size_t N1, std::size_t N2>
322 constexpr std::array<T, N1 + N2> ConcatArrays(const std::array<T, N1> &A1,
323  const std::array<T, N2> &A2) {
324  return ConcatArrays(A1, A2, std::make_index_sequence<N1>(),
325  std::make_index_sequence<N2>());
326 }
327 
328 // Utility for creating an std::array from the results of flattening the
329 // arguments using a flattening functor.
330 template <typename DataT, template <typename, typename> typename FlattenF,
331  typename... ArgTN>
333 template <typename DataT, template <typename, typename> typename FlattenF,
334  typename ArgT, typename... ArgTN>
335 struct ArrayCreator<DataT, FlattenF, ArgT, ArgTN...> {
336  static constexpr auto Create(const ArgT &Arg, const ArgTN &...Args) {
337  auto ImmArray = FlattenF<DataT, ArgT>()(Arg);
338  // Due to a bug in MSVC narrowing size_t to a bool in an if constexpr causes
339  // warnings. To avoid this we add the comparison to 0.
340  if constexpr (sizeof...(Args) > 0)
341  return ConcatArrays(
343  else
344  return ImmArray;
345  }
346 };
347 template <typename DataT, template <typename, typename> typename FlattenF>
348 struct ArrayCreator<DataT, FlattenF> {
349  static constexpr auto Create() { return std::array<DataT, 0>{}; }
350 };
351 
352 // Helper function for creating an arbitrary sized array with the same value
353 // repeating.
354 template <typename T, size_t... Is>
355 static constexpr std::array<T, sizeof...(Is)>
356 RepeatValueHelper(const T &Arg, std::index_sequence<Is...>) {
357  auto ReturnArg = [&](size_t) { return Arg; };
358  return {ReturnArg(Is)...};
359 }
360 template <size_t N, typename T>
361 static constexpr std::array<T, N> RepeatValue(const T &Arg) {
362  return RepeatValueHelper(Arg, std::make_index_sequence<N>());
363 }
364 
365 // to output exceptions caught in ~destructors
366 #ifndef NDEBUG
367 #define __SYCL_REPORT_EXCEPTION_TO_STREAM(str, e) \
368  { \
369  std::cerr << str << " " << e.what() << std::endl; \
370  assert(false); \
371  }
372 #else
373 #define __SYCL_REPORT_EXCEPTION_TO_STREAM(str, e)
374 #endif
375 
376 } // namespace detail
377 } // namespace _V1
378 } // namespace sycl
Data type that manages the code_location information in TLS.
Definition: common.hpp:131
std::function< void(interop_handle)> func
Definition: commands.cpp:322
#define __CODELOC_COLUMN
Definition: common.hpp:61
#define __CODELOC_FILE_NAME
Definition: common.hpp:43
#define __CODELOC_LINE
Definition: common.hpp:55
#define __CODELOC_FUNCTION
Definition: common.hpp:49
#define __SYCL_ALWAYS_INLINE
std::enable_if_t< std::is_pointer_v< DataT > > EnableIfOutputPointerT
Definition: common.hpp:34
static T< NewDim > convertToArrayOfN(T< OldDim > OldObj)
Definition: common.hpp:303
size_t getLinearIndex(const T< Dims > &Index, const U< Dims > &Range)
Definition: common.hpp:286
constexpr size_t getNextPowerOfTwo(size_t Var)
Definition: common.hpp:280
std::enable_if_t< !std::is_pointer_v< DataT > > EnableIfOutputIteratorT
Definition: common.hpp:38
constexpr std::array< T, sizeof...(Is1)+sizeof...(Is2)> ConcatArrays(const std::array< T, sizeof...(Is1)> &A1, const std::array< T, sizeof...(Is2)> &A2, std::index_sequence< Is1... >, std::index_sequence< Is2... >)
Definition: common.hpp:316
constexpr size_t getNextPowerOfTwoHelper(size_t Var, size_t Offset)
Definition: common.hpp:273
ur_code_location_t codeLocationCallback(void *)
Definition: common.cpp:32
static constexpr std::array< T, sizeof...(Is)> RepeatValueHelper(const T &Arg, std::index_sequence< Is... >)
Definition: common.hpp:356
static constexpr std::array< T, N > RepeatValue(const T &Arg)
Definition: common.hpp:361
Definition: access.hpp:18
_Abi const simd< _Tp, _Abi > & noexcept
Definition: simd.hpp:1324
static constexpr auto Create(const ArgT &Arg, const ArgTN &...Args)
Definition: common.hpp:336
NDLoopIterateImpl(const LoopIndexTy< NDims > &LowerBound, const LoopBoundTy< NDims > &Stride, const LoopBoundTy< NDims > &UpperBound, FuncTy f, LoopIndexTy< NDims > &Index)
Definition: common.hpp:218
Helper class for the NDLoop.
Definition: common.hpp:199
NDLoopIterateImpl(const LoopIndexTy< NDims > &LowerBound, const LoopBoundTy< NDims > &Stride, const LoopBoundTy< NDims > &UpperBound, FuncTy f, LoopIndexTy< NDims > &Index)
Definition: common.hpp:200
Generates an NDims-dimensional perfect loop nest.
Definition: common.hpp:238
static __SYCL_ALWAYS_INLINE void iterate(const LoopBoundTy< NDims > &UpperBound, FuncTy f)
Generates ND loop nest with {0,..0} .
Definition: common.hpp:244
static __SYCL_ALWAYS_INLINE void iterate(const LoopIndexTy< NDims > &LowerBound, const LoopBoundTy< NDims > &Stride, const LoopBoundTy< NDims > &UpperBound, FuncTy f)
Generates ND loop nest with LowerBound .
Definition: common.hpp:262
static constexpr code_location current(const char *fileName=__CODELOC_FILE_NAME, const char *funcName=__CODELOC_FUNCTION, unsigned long lineNo=__CODELOC_LINE, unsigned long columnNo=__CODELOC_COLUMN) noexcept
Definition: common.hpp:68
constexpr code_location(const char *file, const char *func, int line, int col) noexcept
Definition: common.hpp:80
constexpr code_location() noexcept
Definition: common.hpp:84
constexpr unsigned long columnNumber() const noexcept
Definition: common.hpp:88
constexpr const char * fileName() const noexcept
Definition: common.hpp:89
constexpr const char * functionName() const noexcept
Definition: common.hpp:90
constexpr unsigned long lineNumber() const noexcept
Definition: common.hpp:87