Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SYCL] Implementation of fallback assert #3767

Merged
merged 205 commits into from
Sep 1, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
205 commits
Select commit Hold shift + click to select a range
2911ea7
[SYCL] [DOC] Prepare design-document for assert feature
Mar 31, 2021
b69a1cd
Remove redundant file
Mar 31, 2021
15ea88e
Fix typo
Apr 1, 2021
ca08fec
Address some review comments. Add description of built-ins.
Apr 5, 2021
1f8d9a9
Fix links
Apr 5, 2021
2ee590c
Clarify that assertion failure message is printed by DPCPP Runtime
Apr 5, 2021
77699a2
Clarify that fallback assert impl is synchronous
Apr 6, 2021
001a573
Fix typo in level-zero ext draft
Apr 6, 2021
32b6479
Address some review comments.
Apr 7, 2021
b8637c2
Add exception extension
Apr 8, 2021
b0cd85f
Use error-code instead of distinct exception.
Apr 8, 2021
8c03648
[SYCL] Add OpenCL extension for assert error code
Apr 9, 2021
121c945
[SYCL] Add Level-Zero extension for assert error code
Apr 9, 2021
13b40fd
Merge branch 'private/s-kanaev/assert-ocl-l0' into private/s-kanaev/a…
Apr 9, 2021
a4b4884
Remove draft files
Apr 9, 2021
c06db5f
Remove unwanted part
Apr 9, 2021
823124a
Merge branch 'private/s-kanaev/assert-ocl-l0' into private/s-kanaev/a…
Apr 9, 2021
a99368b
Add limitations on submit to same queue after exception thrown.
Apr 9, 2021
78d7fcb
Add format of assert message
Apr 9, 2021
6882e95
Clarify where kernel wrapping takes place
Apr 9, 2021
32663e0
Changes to SYCL specification
Apr 13, 2021
2b84a83
Elaborate on limitations
Apr 13, 2021
423107b
Fix link
Apr 14, 2021
7611511
Add sequence describing how DPCPP RT gets to know about assert failure
Apr 14, 2021
a31b808
Add notes on property set usage
Apr 14, 2021
257054a
Address comments
Apr 14, 2021
3f50173
Fix typo and format note
Apr 14, 2021
c1326aa
Fix typo
Apr 14, 2021
5095b1a
Add extension to README
Apr 14, 2021
5078fcc
Note on how property set gets to be set
Apr 14, 2021
4dc7b1f
Merge branch 'sycl' into private/s-kanaev/assert-abort
Apr 15, 2021
9bcac02
Partially remove mentioning of async exception throw
Apr 15, 2021
7ec3ac8
Add Assert.md to index
Apr 15, 2021
8cbfde7
Remove the rest of exception throws
Apr 15, 2021
cc085f5
Address review comments
Apr 22, 2021
8835bf8
Document program-scope variable approach
May 6, 2021
8835756
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
May 6, 2021
ecb8659
Remove L0 and OCL extensions.
May 7, 2021
4c91fa3
[SYCL] Add PoC for using global variable
May 7, 2021
07debdb
Address comments
May 11, 2021
995e4d8
Fix typo
May 12, 2021
b57ac48
Fix typo
May 12, 2021
d2f13ff
Address review comments
May 17, 2021
e97abb3
Merge branch 'private/s-kanaev/assert-abort' into private/s-kanaev/as…
May 17, 2021
6fdcf87
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
May 17, 2021
6281bc5
Switch to __devicelib_assert_read
May 19, 2021
a5461f3
Remove use of NDEBUG from suggested changes
May 19, 2021
32a32f4
Reorder text to increase readability
May 19, 2021
2a7955f
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
May 19, 2021
3113d64
Merge branch 'private/s-kanaev/assert-abort' into private/s-kanaev/as…
May 19, 2021
eb49adb
Put variable into namespace
May 20, 2021
641d071
Address review comment
May 20, 2021
dc058a9
Address review comments
May 27, 2021
16fd8f0
Add aspect
May 27, 2021
c1e31dd
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
May 27, 2021
4a55261
Merge branch 'private/s-kanaev/assert-abort' into private/s-kanaev/as…
May 27, 2021
7fce041
Worked on implementation
May 27, 2021
3f3e1f5
Worked on implementation
May 31, 2021
c02de94
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
May 31, 2021
1490e91
Worked on implementation
May 31, 2021
44004d4
Worked on implementation
Jun 1, 2021
fc97981
Fix code style issues. Code clean-up
Jun 1, 2021
d2038be
Add doc
Jun 1, 2021
490b697
Fix code style issue
Jun 1, 2021
0d05368
Add missing file
Jun 1, 2021
8e64d96
Elaborate on preprocessor macro function
Jun 1, 2021
e1a7f45
Add missing symbols
Jun 1, 2021
e6e0e94
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Jun 1, 2021
8a9effd
Fix runtime issues
Jun 1, 2021
2d2018b
Report CUDA device as of no support for assert
Jun 1, 2021
2c66765
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Jun 2, 2021
5e3647a
Disable fallback assert in unit-tests
Jun 2, 2021
4d204f8
Address some review comments
Jun 2, 2021
6be5ac5
Add FIXME comments in devicelib
Jun 2, 2021
6de4d5c
Move AssertHappenedMem out of namespace
Jun 2, 2021
e39e15f
Updated comment
Jun 2, 2021
60a2121
Update document
Jun 2, 2021
436e8a6
Update document
Jun 2, 2021
7c2ea4b
[PI] Get to know if extension is present w/ variable ext name for bac…
Jun 3, 2021
acce48c
Add atomic operations
Jun 3, 2021
a64d966
Updated document
Jun 3, 2021
26c1c9c
Clang format fix
Jun 3, 2021
a302871
Add missing change
Jun 3, 2021
0284064
Fix style issues
Jun 3, 2021
89b93a9
Fix style issue and typo
Jun 4, 2021
30237e8
Fix build issues
Jun 4, 2021
7bac294
Fix ABI tests
Jun 4, 2021
c846ad5
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Jun 7, 2021
3e70b01
Rename AssertFlagCopier => AssertInfoCopier
Jun 7, 2021
04b39ab
Move buffer delete to distinct host task
Jun 7, 2021
acb8662
Fix cuda build
Jun 8, 2021
07b43a7
Eliminate 'unused capture' warning
Jun 8, 2021
22e5376
Fix failing unit tests
Jun 8, 2021
966756b
Rename CAS and make it static inline
Jun 8, 2021
415b35e
Fix style issue.
Jun 8, 2021
c96534d
Fix cuda build
Jun 8, 2021
2365eb4
Disable fallback assert in L0 dynamic batch test
Jun 9, 2021
565a1fd
Merge branch 'sycl' into private/s-kanaev/assert-abort-impl
Jun 10, 2021
0368946
Uncomment lines after FE changes
Jun 10, 2021
dedf682
Workaround FE restriction
Jun 11, 2021
1144198
Remove unwanted changes
Jun 11, 2021
954a24c
Remove unwanted comment
Jun 11, 2021
0088a7d
Add missing file
Jun 11, 2021
0994acc
Fix style issues
Jun 11, 2021
2ae9346
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Jun 11, 2021
1c429d8
Update PI
Jun 11, 2021
d264d16
Copy assert message elements
Jun 11, 2021
293123a
Fix warning as error for msvc: 'fprintf' : format string '%lu' requir…
dm-vodopyanov Jun 15, 2021
cfbbbef
Merge remote-tracking branch 'upstream/sycl' into private/s-kanaev/as…
dm-vodopyanov Jun 16, 2021
51a8c9c
Fix "_GLOBAL__sub_I_fallback_cassert.cpp is undefined" error on Linux
dm-vodopyanov Jun 17, 2021
88af340
Temporarily enable CUDA support + fix clang-format
dm-vodopyanov Jun 18, 2021
17378c3
More fixes
dm-vodopyanov Jun 18, 2021
2368040
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Jun 21, 2021
a68f6d4
Fix checker host-task
Jun 21, 2021
2a4ecb3
Fix assert message
Jun 21, 2021
6b501bb
Fix style issue
Jun 21, 2021
d6fbb25
Remove call to spirv printf
Jun 21, 2021
52d854c
Use proper naming in libdevice
Jun 21, 2021
0b66b0e
Fix comment
Jun 21, 2021
e7ef209
Enable querying device binary property set
Jun 22, 2021
81a1dc2
Guard builds for CUDA target
Jun 22, 2021
3448969
Fix style issues
Jun 22, 2021
c8ec496
Revert "Enable querying device binary property set"
Jun 22, 2021
eb4bdc7
Overcome msvc behaviour
Jun 23, 2021
6cb0a43
Fix message style
Jun 23, 2021
9f9421b
Fix style issue
Jun 23, 2021
9cc989a
Fix build issue
Jun 24, 2021
7eec090
Overcome msvc behaviour. pt2
Jun 24, 2021
66c816c
Move AssertInfoCopier kernel name class to detail namespace
Jun 24, 2021
b9c39bb
Add structure layout description
Jun 24, 2021
f797224
Eliminate ABI break
Jun 25, 2021
901fe80
Store assert usage info in the event instead of runtime fetching.
Jun 25, 2021
0b011d3
Use postprocessor lambda instead of storing additional data in event
Jun 25, 2021
2b2b897
Resolve style issue
Jun 25, 2021
a02420d
Reuse assert info buffer in per-queue manner to eliminate deadlock si…
Jun 25, 2021
8b0b8fd
Fix symbols dump test
Jun 28, 2021
4774852
Don't emit assert post-processing for host
Jun 28, 2021
c6d3698
Remove unwanted change
Jun 28, 2021
84138b7
Revert unwanted change
Jun 28, 2021
dc63e89
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Jun 28, 2021
7f7ca75
Make the global variable of internal linkage
Jun 28, 2021
f6ee7af
Remove redundant lines
Jun 28, 2021
ef7677e
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Jun 28, 2021
e6d74e9
Check if kernel uses assert
Jun 29, 2021
553efba
Don't disable asserts in unit-tests.
Jun 29, 2021
377a598
Allocate device binary images in-place, not in cache
Jun 29, 2021
22dd99f
Fix style issue
Jun 29, 2021
5854804
Fix unit-test
Jun 29, 2021
5cf7587
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Jun 29, 2021
a3532d6
Fix style issue
Jun 29, 2021
41cf02f
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Jul 1, 2021
d64c439
Workaround for interference with reductions feature
Jul 1, 2021
a5bffb6
Remove redundant comment
Jul 1, 2021
5950432
Enforce assert copier after kernels built from source
Jul 1, 2021
6df5886
Fixed typo
Jul 2, 2021
c1767b6
Fix style issue
Jul 2, 2021
d9caaaf
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Jul 2, 2021
82a14e1
Fix style issue
Jul 2, 2021
3397542
Fix required wg size unit-test
Jul 2, 2021
743451d
Fix required wg size unit-test
Jul 5, 2021
7478ac2
[SYCL] Make cmake file for unit-tests more robust
Jul 7, 2021
07f0871
Revert "Fix required wg size unit-test"
Jul 7, 2021
6aa3d96
Revert "Fix required wg size unit-test"
Jul 7, 2021
8a30c3e
Revert "Fix unit-test"
Jul 7, 2021
433d340
[SYCL] Eliminate use of dereference of past-the-end iterator in unit …
Jul 7, 2021
69fa419
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Jul 7, 2021
764afb4
Revert "Make the global variable of internal linkage"
Jul 7, 2021
c63f1e9
Address review comments on libdevice
Jul 8, 2021
211c4d1
Address review comment
Jul 8, 2021
a84695c
Add unit-test
Jul 9, 2021
b6c768e
Report exceptions during wait for host-tasks dependencies
Jul 9, 2021
cc090c6
Remove additional API and use unified extension name instead
Jul 9, 2021
d10d7f4
Disable test for CUDA
Jul 9, 2021
a51611d
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Jul 9, 2021
c8514aa
Fix style issue
Jul 9, 2021
661f2b8
Fix ABI test after API remove
Jul 12, 2021
1b270cb
Fix atomic_fence test failure
Jul 11, 2021
b952457
Fix test
Jul 12, 2021
8f51b2c
Merge branch 'sycl' into private/s-kanaev/assert-abort-impl
Jul 16, 2021
75dc44d
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Aug 19, 2021
9a2fec9
Fix merge issues
Aug 19, 2021
35dafd0
Merge branch 'private/s-kanaev/assert-abort-impl' of github.com:s-kan…
Aug 19, 2021
fc78175
Fix ABI test
Aug 20, 2021
4f2db4e
[SYCL] Remove backend-specific code form device_impl::isAssertFailSup…
Jul 15, 2021
e156acd
[SYCL] Eliminate use of literal in device_impl::isAssertFailSupported
Aug 24, 2021
c305bb5
[SYCL] Update test to positive
Aug 24, 2021
4d9be64
[SYCL] Move assert unit-test to misc
Aug 24, 2021
8433cd0
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Aug 24, 2021
ab30424
Fix styling
Aug 25, 2021
d694e62
Revert "[SYCL] Move assert unit-test to misc"
Aug 25, 2021
afc47dc
Fix styling
Aug 25, 2021
e153824
Fix test
Aug 25, 2021
9325bdc
Fix styling
Aug 25, 2021
9c8a3fd
Attempt to fix test
Aug 25, 2021
28b802c
Fix test on windows and cuda
Aug 26, 2021
0a7a72b
Rename macro
Aug 26, 2021
eed89bd
Employ macro instead of literal in cuda plugin
Aug 26, 2021
4478f3b
Update comment
Aug 26, 2021
1c12c0d
Fix test return. Add wait in test to ensure assert trigger on host an…
Aug 26, 2021
decb7be
Update sycl/doc/extensions/C-CXX-StandardLibrary/DeviceLibExtensions.rst
Aug 26, 2021
585babf
Change macro description
Aug 27, 2021
ba5717e
Fix endif comments
Aug 27, 2021
6c7a94d
Fix wording in Assert.md
Aug 27, 2021
295ac91
Add comments to test
Aug 30, 2021
a2f2473
Merge remote-tracking branch 'public/sycl' into private/s-kanaev/asse…
Aug 30, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Document program-scope variable approach
Signed-off-by: Sergey Kanaev <sergey.kanaev@intel.com>
  • Loading branch information
Sergey Kanaev committed May 6, 2021
commit 8835bf8a1ae5dfc1146e455ae672e3e39c1e3caf
308 changes: 152 additions & 156 deletions sycl/doc/Assert.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ practical cases.
based on input SPIR-V image.
- Low-level Runtime - the backend/runtime behind DPCPP Runtime attached via the
Plugin Interface.
- Accessor metadata - parts of accessor representation at device-side: pointer,
ranges, offset.


## How it works?
Expand Down Expand Up @@ -125,49 +123,73 @@ The following sequence of events describes how user code gets notified:
3. Low-Level Runtime calls `abort()`


### Fallback approach
## Fallback approach

If Device-side Runtime doesn't support `__devicelib_assert_fail` then a buffer
based approach comes in place. The approach doesn't require any support from
If Device-side Runtime doesn't support `__devicelib_assert_fail` then a fallback
approach comes in place. The approach doesn't require any support from
Device-side Runtime and Native Device Compiler. Neither it does from Low-level
Runtime.

Within this approach, a dedicated assert buffer is allocated and implicit kernel
argument is introduced. The argument is an accessor that has either
`access_mode::read_write` or `access_mode::write` access mode and was
constructed with the `property::no_init property`. Accessor metadata is stored
to program scope variable. This allows to refer to the accessor without
modifying each and every user's function. Fallback implementation of
`__devicelib_assert_fail` restores accessor metadata from program scope variable
and writes assert information to the assert buffer. Atomic operations are used
in order to not overwrite existing information.

DPCPP Runtime checks contents of the assert buffer for assert failure flag after
kernel finishes.
Within this approach, a mutable program scope variable is introduced. This
variable stores a flag which says if an assert failure was encountered. Fallback
implementation of `__devicelib_assert_fail` atomically raises the flag so that
DPCPP Runtime is able to detect assert failure after kernel finishes.

The following sequence of events describes how user code gets notified:
- Device side:
1. Assert fails in device-code in kernel
2. Fallback version of `__devicelib_assert_fail` is called
3. Assert information is stored into assert buffer
3. Assert information is stored into program-scope variable
4. Kernel continues running
- Host side:
1. A distinct thread is launched no later than the point of enqueue of the
first kernel with assertions
2. This thread polls the enqueued kernels for finish and checks the assert
buffer for assert data
3. If assert data is present DPCPP Runtime calls `abort()`
1. A copy 'kernel' is enqueued as the one depending on user's kernel to get
the value of assert failure flag.
2. A host-task is enqueued to check value of assert failure flag.
3. The host task calls abort whenever assert failure flag is set.

Illustrating this with an example, lets assume the user enqueues three kernels:
- `Kernel #1`
- `Kernel #2`
- `Kernel #3`, which depends on `Kernel #1`

The resulting graph will look like this: ![graph](images/assert-fallback-graph.svg)

### Interface to program scope variable

Multiple translation units could be compiled/linked into a single device binary
image. All of them should have `extern` declaration of program scope variable
available. Definition of the variable is only available within devicelib in the
same binary image where fallback `__devicelib_assert_fail` resides.

<a name="prog-scope-var-decl">The variable has the following structure and
declaration:</a>

```c++
struct AssertHappened {
int Flag = 0;
};

#ifdef __SYCL_DEVICE_ONLY__
extern SYCL_GLOBAL_VAR AssertHappened AssertHappenedMem;
#endif
```

Here, `SYCL_GLOBAL_VAR` is a macro which wraps special attribute to allow for
mutable program-scope variable.

#### Online-linking fallback `__devicelib_assert_fail`
The reference to extern variable is resolved within online-linking against
fallback devicelib.

### Online-linking fallback `__devicelib_assert_fail`

Online linking against fallback implementation of `__devicelib_assert_fail` is
performed only when assertion is enabled and Device-side Runtime doesn't provide
implementation of `__devicelib_assert_fail`.

In DPCPP headers one can see if assert is enabled with status of `NDEBUG` macro
with `#ifdef`'s. This allows to add implicit buffer argument to kernel
invocation. Here "implicit" means "implicit to the user".
with `#ifdef`'s. This allows to enqueue a copy kernel and host task. The copy
kernel will copy `AssertHappenedMem` to host and host-task will check the `Flag`
value and `abort()` as needed.

When in DPCPP Runtime Library this knowledge is obtained from device binary
image descriptor's property sets.
Expand Down Expand Up @@ -213,8 +235,62 @@ translation unit was compiled with assertions enabled i.e. `NDEBUG` undefined.
The property is added by `sycl-post-link` tool depending on module metadata.
Metadata is provided by Clang frontend. Metadata name is `is_assert_enabled`.

Suppose the following example user code:
```c++
void user_func(int X) {
assert(X && “X is nil”);
}

int main() {
queue Q(...);
Q.submit([&] (handler& CGH) {
CGH.single_task([=] () {
do_smth();
user_func(0);
do_smth_else();
});
});
...
}
```

The following LLVM IR pseudo code will be generated after linking against
fallback implementation of devicelib:
```
@AssertHappenedMem = global AssertHappened

/// user's code
void user_func(int X) {
if (!(X && “X is nil")) {
__assert_fail(...);
}
}

##### Compiling with assert enabled/disabled
kernel(...) {
do_smth()
user_func(0);
do_smth_else();
}

/// __assert_fail belongs to Linux version of devicelib
void __assert_fail(...) {
...
__devicelib_assert_fail(...);
}

void __devicelib_assert_fail(Expr, File, Line, GlobalID, LocalID) {
...
volatile int *Ptr = (volatile int *)AssertHappenedMem.Flag;
int Expected = 0;
int Desired = 1;

if (atomic_CAS(&AssertHappenedMem.Flag, Expected, Desired))
printf("Assertion `%s' failed in %s at line %i. GlobalID: %i, LocalID: %i",
Expr, File, Line, GlobalID, LocalID);
}
```

#### Compiling with assert enabled/disabled

Consider the following example sources:
```c++
Expand Down Expand Up @@ -275,145 +351,65 @@ fail. Having assertions enabled in at least one translation unit with device
code requires for `isAssertEnabled` property set being present in device image
descriptor structure.

### Raising assert failure flag and reading it on host

#### Storing accessor metadata and writing assert failure to buffer
Each and every translation unit provided by user should have `extern`
declaration of `AssertHappenedMem` i.e. DPCPP headers includes appropriate file
with [declaration](#prog-scope-var-decl).

Both storing of accessor metadata and writing assert failure is performed with
help of built-ins. Implementations of these builtins are substituted by
frontend.
The definition is only provided within devicelib along with
`__devicelib_assert_fail` function which raises the flag.

User's kernel is executed through a wrapper. Wrapping takes place in DPCPP
Runtime headers in a following manner:
Reading of assert failure flag is performed with the help of auxiliary kernel
which is enqueued as dependent on user's one. The flag state is checked later
in host-task. This is achieved with approximately the following changes:

```
class handler {
```c++
#include <assert_happened.hpp> // contains extern decl of AssertHappenedMem

template <typename KernelName> parallel_for(KernelFunc, Range) {
#ifndef NDEBUG
// Assert required
  if (!MQueue->get_device()->assert_fail_supported()) {
    using KName2 = class ASSERT_WRAPPER_NAME(KernelName);

    auto AssertBufferAcc = MQueue->get_context()->getAssertBufferAccessor(this);

    parallel_for_impl<KName2>(
      Range,
      [=](Item) {
        __store_acc(AssertBuffAcc);
        KernelFunc(Item);
      });
  } else {
class AssertFlagCopier;
#endif

// (No assert required) OR (Assert supported by device)
     // ordinary enqueue process

class queue {
template <typename T> event submit(T CGF) {
event Event = submit_impl(CGF);
#ifndef NDEBUG
}
// assert required
if (!get_device()->assert_fail_supported()) {
// __devicelib_assert_fail isn't supported by Device-side Runtime
// Linking against fallback impl of __devicelib_assert_fail is performed
// by program manager class
AssertHappened *AH = new AssertHappened;
buffer<AssertHappened, 1> *Buffer = new buffer<AssertHappened, 1>{1, AH};

// read flag value
event CopierEv = submit_impl([&](handler &CGH) {
CGH.depends_on(Event);

auto Acc = Buffer->get_access<access::mode::write>(CGH);

CGH.single_task<AssertFlagCopier>([=] {
Acc[0].Flag = atomic_load(&AssertHappenedMem.Flag);
});
});

// check flag state
submit_impl([=](handler &CGH) {
CGH.depends_on(CopierEv);

CGH.codeplay_host_task([=] {
if (AH->Flag)
abort();

free(Buffer);
free(AH);
});
});
}
#endif
}

}
```


#### Built-ins operation

Accessor is a pointer augmented with offset and two ranges (access range and
memory range).

There are two built-ins provided by frontend:
* `__store_acc()` - to store accessor metadata into program-scope variable.
* `__store_assert_failure()` - to store flag about assert failure in a buffer
using the metadata stored in program-scope variable.

The accessor should be stored to program scope variable in global address space
using atomic operations. Motivation for using atomic operations: the program may
contain several kernels and some of them could be running simultaneously on a
single device.

The `__store_assert_failure()` built-in atomically sets a flag in a buffer. The
buffer is accessed using accessor metadata from program-scope variable. This
built-in return a boolean value which is `true` if the flag is set by this call
to `__store_assert_failure()` and `false` if the flag was already set.
Motivation for using atomic operation is the same as with `__store_acc()`
builtin.

The following pseudo-code snippets shows how these built-ins are used.
First of all, assume the following code as user's one:
```
void user_func(int X) {
assert(X && “X is nil”);
}

int main() {
queue Q(...);
Q.submit([&] (handler& CGH) {
CGH.single_task([=] () {
do_smth();
user_func(0);
do_smth_else();
});
});
...
}
```

The following LLVM IR pseudo code will be generated for the user's code:
```
@AssertBufferPtr = global void* null
@AssertBufferAccessRange = ...
@AssertBufferMemoryRange = ...
@AssertBufferOffset = ...

/// user's code
void user_func(int X) {
if (!(X && “X is nil")) {
__assert_fail(...);
return Event;
}
}

users_kernel(...) {
do_smth()
user_func(0);
do_smth_else();
}

/// a wrapped user's kernel
kernel(AssertBufferAccessor, OtherArguments...) {
__store_acc(AssertBufferAccessor);
users_kernel(OtherArguments...);
}

/// __assert_fail belongs to Linux version of devicelib
void __assert_fail(...) {
...
__devicelib_assert_fail(...);
}

void __devicelib_assert_fail(Expr, File, Line, GlobalID, LocalID) {
...
if (__store_assert_info())
printf("Assertion `%s' failed in %s at line %i. GlobalID: %i, LocalID: %i",
Expr, File, Line, GlobalID, LocalID);
}

/// The following are built-ins provided by frontend
void __store_acc(accessor) {
%1 = accessor.getPtr();
store void * %1, void * @AssertBufferPtr
}

bool __store_assert_info(...) {
AssertBAcc = __fetch_acc();
// fill in data in AsBAcc
volatile int *Ptr = (volatile int *)AssertBAcc.getPtr();
bool Expected = false;
bool Desired = true;

return atomic_cas(Ptr, Expected, Desired, SequentialConsistentMemoryOrder);
// or it could be:
// return !atomic_exchange(Ptr, Desired, SequentialConsistentMemoryOrder);
}
};
```

Loading