assertOpenCL  September 19, 2018
assert.cl
Go to the documentation of this file.
1 /* -*- coding: latin-1 -*- */
2 /** \file OpenCL/assert.cl
3  * \brief
4  * C-like assert alternative (because assert doesn't exist in OpenCL),
5  * with necessary helper macros to transmit information to the host.
6  *
7  * If macro NDEBUG is defined or macro NASSERT is defined
8  * then these assert*() macros are simply ignored.
9  *
10  * The behavior is similar of C assert
11  * but instead abort when an assertion failed
12  * a message is printed (if at least OpenCL 1.2)
13  * and two buffers are used to transmit the information of the first assertion failed
14  * to the host program.
15  *
16  * See examples of use in examples/kernel/example.cl
17  *
18  * C assert documentation:
19  * https://en.cppreference.com/w/c/error/assert
20  *
21  * Piece of assertOpenCL
22  * --- GPLv3 --- Copyright (C) 2018 Olivier Pirson
23  * --- http://www.opimedia.be/
24  * --- September 16, 2018
25  */
26 
27 #ifdef NDEBUG
28 # ifndef DOXYGEN
29 # define NASSERT
30 # endif
31 #endif
32 
33 
34 
35 #undef ASSERT_DECLARE_UNIQUE_PARAMS
36 #undef ASSERT_DECLARE_PARAMS
37 #undef ASSERT_UNIQUE_PARAMS
38 #undef ASSERT_PARAMS
39 #undef assert_reset
40 
41 #undef assert
42 #undef assert_n
43 #undef assert_x
44 #undef assert_n_x
45 
46 #undef assert_r
47 #undef assert_n_r
48 #undef assert_x_r
49 #undef assert_n_x_r
50 
51 #undef assert_r0
52 #undef assert_n_r0
53 #undef assert_x_r0
54 #undef assert_n_x_r0
55 
56 #undef last_assert
57 #undef last_assert_n
58 #undef last_assert_x
59 #undef last_assert_n_x
60 
61 #undef last_assert_r
62 #undef last_assert_n_r
63 #undef last_assert_x_r
64 #undef last_assert_n_x_r
65 
66 #undef last_assert_r0
67 #undef last_assert_n_r0
68 #undef last_assert_x_r0
69 #undef last_assert_n_x_r0
70 
71 
72 
73 #ifdef NASSERT
74 # define ASSERT_DECLARE_UNIQUE_PARAMS
75 # define ASSERT_DECLARE_PARAMS
76 # define ASSERT_UNIQUE_PARAMS
77 # define ASSERT_PARAMS
78 # define assert_reset
79 
80 # define assert(test) ((void)0)
81 # define assert_n(test, integer_value) ((void)0)
82 # define assert_x(test, float_value) ((void)0)
83 # define assert_n_x(test, integer_value, float_value) ((void)0)
84 
85 # define assert_r(test) ((void)0)
86 # define assert_n_r(test, integer_value) ((void)0)
87 # define assert_x_r(test, float_value) ((void)0)
88 # define assert_n_x_r(test, integer_value, float_value) ((void)0)
89 
90 # define assert_r0(test) ((void)0)
91 # define assert_n_r0(test, integer_value) ((void)0)
92 # define assert_x_r0(test, float_value) ((void)0)
93 # define assert_n_x_r0(test, integer_value, float_value) ((void)0)
94 
95 # define last_assert(test) ((void)0)
96 # define last_assert_n(test, integer_value) ((void)0)
97 # define last_assert_x(test, float_value) ((void)0)
98 # define last_assert_n_x(test, integer_value, float_value) ((void)0)
99 
100 # define last_assert_r(test) ((void)0)
101 # define last_assert_n_r(test, integer_value) ((void)0)
102 # define last_assert_x_r(test, float_value) ((void)0)
103 # define last_assert_n_x_r(test, integer_value, float_value) ((void)0)
104 
105 # define last_assert_r0(test) ((void)0)
106 # define last_assert_n_r0(test, integer_value) ((void)0)
107 # define last_assert_x_r0(test, float_value) ((void)0)
108 # define last_assert_n_x_r0(test, integer_value, float_value) ((void)0)
109 
110 #else
111 /** \brief
112  * Declare extra parameters in the signature (without other params)
113  * of kernel function or other functions that use assertions.
114  *
115  * assert_result_ is two int on 64 bits that will contain the line number and the integer value.
116  * assert_result_float_ is one float on 32 bits that will contain the floating value.
117  */
118 # define ASSERT_DECLARE_UNIQUE_PARAMS __global unsigned long* const assert_result_, __global float* const assert_result_float_
119 
120 /** \brief
121  * Declare extra parameters in the signature (with other params)
122  * of kernel function or other functions that use assertions.
123  */
124 # define ASSERT_DECLARE_PARAMS , ASSERT_DECLARE_UNIQUE_PARAMS
125 
126 
127 /** \brief
128  * Transmit the extra parameters in the calling of a function with ASSERT_DECLARE_UNIQUE_PARAM.
129  */
130 # define ASSERT_UNIQUE_PARAMS assert_result_, assert_result_float_
131 
132 
133 /** \brief
134  * Transmit the extra parameters in the calling of a function with ASSERT_DECLARE_PARAM.
135  */
136 # define ASSERT_PARAMS , ASSERT_UNIQUE_PARAMS
137 
138 
139 /** \brief
140  * Clear previous assertions setting.
141  */
142 # define assert_reset { \
143  assert_result_[0] = 0; \
144  assert_result_[1] = 0; \
145  assert_result_float_[0] = 0.0; \
146  barrier(CLK_GLOBAL_MEM_FENCE); \
147  }
148 
149 
150 
151 /** \brief
152  * If test is true
153  * then do nothing.
154  * Else init (if they are still null) assert_result and assert_result_float
155  * with value 0 and 0.0,
156  * and print (if at least OpenCL 1.2) an assertion message.
157  *
158  * (If assertions are disabled then do nothing.)
159  *
160  * @param test the result of the assertion
161  */
162 # define assert(test) assert_n_x(test, 0, 0.0)
163 
164 
165 /** \brief
166  * If test is true
167  * then do nothing.
168  * Else init (if they are still null) assert_result and assert_result_float
169  * with value integer_value and 0.0,
170  * and print (if at least OpenCL 1.2) an assertion message.
171  *
172  * (If assertions are disabled then do nothing.)
173  *
174  * @param test the result of the assertion
175  * @param integer_value
176  */
177 # define assert_n(test, integer_value) assert_n_x(test, integer_value, 0.0)
178 
179 
180 /** \brief
181  * If test is true
182  * then do nothing.
183  * Else init (if they are still null) assert_result and assert_result_float
184  * with value 0 and float_value,
185  * and print (if at least OpenCL 1.2) an assertion message.
186  *
187  * (If assertions are disabled then do nothing.)
188  *
189  * @param test the result of the assertion
190  * @param float_value
191  */
192 # define assert_x(test, float_value) assert_n_x(test, 0, float_value)
193 
194 
195 /** \brief
196  * If test is true
197  * then do nothing.
198  * Else init (if they are still null) assert_result and assert_result_float
199  * with value integer_value and float_value,
200  * and print (if at least OpenCL 1.2) an assertion message.
201  *
202  * (If assertions are disabled then do nothing.)
203  *
204  * @param test the result of the assertion
205  * @param integer_value
206  * @param float_value
207  */
208 # define assert_n_x(test, integer_value, float_value) \
209  assert_fct_(test, __FILE__, __LINE__, #test, \
210  integer_value, float_value, \
211  assert_result_, assert_result_float_)
212 
213 
214 
215 /** \brief
216  * Like assert() but if assertion failed then return.
217  *
218  * Be careful if you have some barriers:
219  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
220  *
221  * @param test the result of the assertion
222  */
223 # define assert_r(test) { \
224  if (!assert(test)) { \
225  return; \
226  } \
227  }
228 
229 
230 /** \brief
231  * Like assert_n() but if assertion failed then return.
232  *
233  * Be careful if you have some barriers:
234  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
235  *
236  * @param test the result of the assertion
237  * @param integer_value
238  */
239 # define assert_n_r(test, integer_value) { \
240  if (!assert_n(test, integer_value)) { \
241  return; \
242  } \
243  }
244 
245 
246 /** \brief
247  * Like assert_x() but if assertion failed then return.
248  *
249  * Be careful if you have some barriers:
250  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
251  *
252  * @param test the result of the assertion
253  * @param float_value
254  */
255 # define assert_x_r(test, float_value) { \
256  if (!assert_x(test, float_value)) { \
257  return; \
258  } \
259  }
260 
261 
262 /** \brief
263  * Like assert_n_x() but if assertion failed then return.
264  *
265  * Be careful if you have some barriers:
266  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
267  *
268  * @param test the result of the assertion
269  * @param integer_value
270  * @param float_value
271  */
272 # define assert_n_x_r(test, integer_value, float_value) { \
273  if (!assert_n_x(test, integer_value, float_value)) { \
274  return; \
275  } \
276  }
277 
278 
279 
280 /** \brief
281  * Like assert() but if assertion failed then return 0.
282  *
283  * Be careful if you have some barriers:
284  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
285  *
286  * @param test the result of the assertion
287  */
288 # define assert_r0(test) { \
289  if (!assert(test)) { \
290  return 0; \
291  } \
292  }
293 
294 
295 /** \brief
296  * Like assert_n() but if assertion failed then return 0.
297  *
298  * Be careful if you have some barriers:
299  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
300  *
301  * @param test the result of the assertion
302  * @param integer_value
303  */
304 # define assert_n_r0(test, integer_value) { \
305  if (!assert_n(test, integer_value)) { \
306  return 0; \
307  } \
308  }
309 
310 
311 /** \brief
312  * Like assert_x() but if assertion failed then return 0.
313  *
314  * Be careful if you have some barriers:
315  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
316  *
317  * @param test the result of the assertion
318  * @param float_value
319  */
320 # define assert_x_r0(test, float_value) { \
321  if (!assert_x(test, float_value)) { \
322  return 0; \
323  } \
324  }
325 
326 
327 /** \brief
328  * Like assert_n_x() but if assertion failed then return 0.
329  *
330  * Be careful if you have some barriers:
331  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
332  *
333  * @param test the result of the assertion
334  * @param integer_value
335  * @param float_value
336  */
337 # define assert_n_x_r0(test, integer_value, float_value) { \
338  if (!assert_n_x(test, integer_value, float_value)) { \
339  return 0; \
340  } \
341  }
342 
343 
344 
345 /** \brief
346  * If test is true
347  * then do nothing.
348  * Else init (if they are still null) assert_result and assert_result_float
349  * with value 0 and 0.0,
350  * and print (if at least OpenCL 1.2) an assertion message.
351  *
352  * (If assertions are disabled then do nothing.)
353  *
354  * @param test the result of the assertion
355  */
356 # define last_assert(test) last_assert_n_x(test, 0, 0.0)
357 
358 
359 /** \brief
360  * If test is true
361  * then do nothing.
362  * Else init (if they are still null) assert_result and assert_result_float
363  * with value integer_value and 0.0,
364  * and print (if at least OpenCL 1.2) an assertion message.
365  *
366  * (If assertions are disabled then do nothing.)
367  *
368  * @param test the result of the assertion
369  * @param integer_value
370  */
371 # define last_assert_n(test, integer_value) last_assert_n_x(test, integer_value, 0.0)
372 
373 
374 /** \brief
375  * If test is true
376  * then do nothing.
377  * Else init (if they are still null) assert_result and assert_result_float
378  * with value 0 and float_value,
379  * and print (if at least OpenCL 1.2) an assertion message.
380  *
381  * (If assertions are disabled then do nothing.)
382  *
383  * @param test the result of the assertion
384  * @param float_value
385  */
386 # define last_assert_x(test, float_value) last_assert_n_x(test, 0, float_value)
387 
388 
389 /** \brief
390  * If test is true
391  * then do nothing.
392  * Else init (if they are still null) assert_result and assert_result_float
393  * with value integer_value and float_value,
394  * and print (if at least OpenCL 1.2) an assertion message.
395  *
396  * (If assertions are disabled then do nothing.)
397  *
398  * @param test the result of the assertion
399  * @param integer_value
400  * @param float_value
401  */
402 # define last_assert_n_x(test, integer_value, float_value) \
403  last_assert_fct_(test, __FILE__, __LINE__, #test, \
404  integer_value, float_value, \
405  assert_result_, assert_result_float_)
406 
407 
408 
409 /** \brief
410  * Like last_assert() but if assertion failed then return.
411  *
412  * Be careful if you have some barriers:
413  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
414  *
415  * @param test the result of the assertion
416  */
417 # define last_assert_r(test) { \
418  if (!last_assert(test)) { \
419  return; \
420  } \
421  }
422 
423 
424 /** \brief
425  * Like last_assert_n() but if assertion failed then return.
426  *
427  * Be careful if you have some barriers:
428  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
429  *
430  * @param test the result of the assertion
431  * @param integer_value
432  */
433 # define last_assert_n_r(test, integer_value) { \
434  if (!last_assert_n(test, integer_value)) { \
435  return; \
436  } \
437  }
438 
439 
440 /** \brief
441  * Like last_assert_x() but if assertion failed then return.
442  *
443  * Be careful if you have some barriers:
444  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
445  *
446  * @param test the result of the assertion
447  * @param float_value
448  */
449 # define last_assert_x_r(test, float_value) { \
450  if (!last_assert_x(test, float_value)) { \
451  return; \
452  } \
453  }
454 
455 
456 /** \brief
457  * Like last_assert_n_x() but if assertion failed then return.
458  *
459  * Be careful if you have some barriers:
460  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
461  *
462  * @param test the result of the assertion
463  * @param integer_value
464  * @param float_value
465  */
466 # define last_assert_n_x_r(test, integer_value, float_value) { \
467  if (!last_assert_n_x(test, integer_value, float_value)) { \
468  return; \
469  } \
470  }
471 
472 
473 
474 /** \brief
475  * Like last_assert() but if assertion failed then return 0.
476  *
477  * Be careful if you have some barriers:
478  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
479  *
480  * @param test the result of the assertion
481  */
482 # define last_assert_r0(test) { \
483  if (!last_assert(test)) { \
484  return 0; \
485  } \
486  }
487 
488 
489 /** \brief
490  * Like last_assert_n() but if assertion failed then return 0.
491  *
492  * Be careful if you have some barriers:
493  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
494  *
495  * @param test the result of the assertion
496  * @param integer_value
497  */
498 # define last_assert_n_r0(test, integer_value) { \
499  if (!last_assert_n(test, integer_value)) { \
500  return 0; \
501  } \
502  }
503 
504 
505 /** \brief
506  * Like last_assert_x() but if assertion failed then return 0.
507  *
508  * Be careful if you have some barriers:
509  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
510  *
511  * @param test the result of the assertion
512  * @param float_value
513  */
514 # define last_assert_x_r0(test, float_value) { \
515  if (!last_assert_x(test, float_value)) { \
516  return 0; \
517  } \
518  }
519 
520 
521 /** \brief
522  * Like last_assert_n_x() but if assertion failed then return 0.
523  *
524  * Be careful if you have some barriers:
525  * https://www.khronos.org/registry/OpenCL/sdk/1.2/docs/man/xhtml/barrier.html
526  *
527  * @param test the result of the assertion
528  * @param integer_value
529  * @param float_value
530  */
531 # define last_assert_n_x_r0(test, integer_value, float_value) { \
532  if (!last_assert_n_x(test, integer_value, float_value)) { \
533  return 0; \
534  } \
535  }
536 
537 #endif
538 
539 
540 
541 #ifndef ASSERT_CL_
542 #define ASSERT_CL_
543 
544 /* *******************
545  * Private functions *
546  *********************/
547 
548 /** \brief
549  * Generic function called by all assert*() macros in debug mode.
550  *
551  * If test is true
552  * then do nothing and return true.
553  * Else init (if they are still null) assert_result and assert_result_float,
554  * print (if at least OpenCL 1.2) an assertion message
555  * and return false.
556  *
557  * @param test the result of the assertion
558  * @param filename the filename of the OpenCL file
559  * @param line the line number of the assertion in filename to store in assert_result[0]
560  * @param assertion the string representation of the assertion checked
561  * @param integer_value a integer value to store in assert_result[1]
562  * @param float_value a float value to store in assert_result_float[0]
563  * @param assert_result
564  * @param assert_result_float
565  *
566  * @return test
567  */
568 bool
569 assert_fct_(const bool test,
570  __constant char* const filename, const unsigned int line,
571  __constant char* const assertion,
572  const unsigned long integer_value, const float float_value,
573  __global unsigned long* const assert_result,
574  __global float* const assert_result_float) {
575  if (!test) {
576  if (assert_result[0] == 0) {
577  assert_result[0] = line;
578  assert_result[1] = integer_value;
579  assert_result_float[0] = float_value;
580  }
581 #if __OPENCL_C_VERSION__ >= 120 // CL_VERSION_1_2
582  printf("[%s:%u\tAssertion `%s' failed |\t%lu\t%li |\t%f]\n", filename, line, assertion,
583  integer_value, (signed long)integer_value, float_value);
584 #endif
585  }
586 
587  return test;
588 }
589 
590 
591 /** \brief
592  * Generic function called by all last_assert*() macros in debug mode.
593  * Similar to assert_fct_() but sets results transmit to the host
594  * for each assert that fails instead only the first.
595  *
596  * If test is true
597  * then do nothing and return true.
598  * Else set assert_result and assert_result_float,
599  * print (if at least OpenCL 1.2) an assertion message
600  * and return false.
601  *
602  * @param test the result of the assertion
603  * @param filename the filename of the OpenCL file
604  * @param line the line number of the assertion in filename to store in assert_result[0]
605  * @param assertion the string representation of the assertion checked
606  * @param integer_value a integer value to store in assert_result[1]
607  * @param float_value a float value to store in assert_result_float[0]
608  * @param assert_result
609  * @param assert_result_float
610  *
611  * @return test
612  */
613 bool
614 last_assert_fct_(const bool test,
615  __constant char* const filename, const unsigned int line,
616  __constant char* const assertion,
617  const unsigned long integer_value, const float float_value,
618  __global unsigned long* const assert_result,
619  __global float* const assert_result_float) {
620  if (!test) {
621  assert_result[0] = line;
622  assert_result[1] = integer_value;
623  assert_result_float[0] = float_value;
624 #if __OPENCL_C_VERSION__ >= 120 // CL_VERSION_1_2
625  printf("[%s:%u\tAssertion `%s' failed |\t%lu\t%li\t%f]\n", filename, line, assertion,
626  integer_value, (signed long)integer_value, float_value);
627 #endif
628  }
629 
630  return test;
631 }
632 
633 #endif // ASSERT_CL_
bool assert_fct_(const bool test, __constant char *const filename, const unsigned int line, __constant char *const assertion, const unsigned long integer_value, const float float_value, __global unsigned long *const assert_result, __global float *const assert_result_float)
Generic function called by all assert*() macros in debug mode.
Definition: assert.cl:569
bool last_assert_fct_(const bool test, __constant char *const filename, const unsigned int line, __constant char *const assertion, const unsigned long integer_value, const float float_value, __global unsigned long *const assert_result, __global float *const assert_result_float)
Generic function called by all last_assert*() macros in debug mode. Similar to assert_fct_() but sets...
Definition: assert.cl:614