Skip to content

Commit d8eb099

Browse files
author
Alexander Batashev
authored
[SYCL] Initial ABI checks implementation (#1528)
Includes basic layout test and symbols checker Signed-off-by: Alexander Batashev <alexander.batashev@intel.com>
1 parent 937fec1 commit d8eb099

12 files changed

+3684
-2
lines changed

sycl/doc/ABIPolicyGuide.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# ABI Policy Guide
2+
3+
## Intro
4+
5+
Application Binary Interface is a contract between binary modules, that defines
6+
how structures and routines are accessed in machine code. Changing the ABI may
7+
break backwards compatibility of user application with the DPC++ runtime library
8+
for user-developed applications, resulting in need to rebuild such applications.
9+
The goal of this document is to provide guidelines for maintaining the current
10+
ABI of the DPC++ runtime library and mechanisms of notifying users about ABI
11+
changes.
12+
13+
All ABI changes can be divided into two large groups: breaking and non-breaking.
14+
A breaking change means that the new binary is incompatible with the previous
15+
version (i.e. it can not be used as a drop-in replacement). A non-breaking
16+
change means that the forward compatibility is broken (i.e. the old library
17+
can be replaced with newer version, but not vice versa).
18+
19+
The following non-exhaustive list contains changes that are considered to be
20+
breaking:
21+
22+
1. Changing the size of exported symbol (for example, adding new member field
23+
to the exported class).
24+
1. Removing the exported symbol (that includes both changing the signature of
25+
exported routine and removing it).
26+
1. Changing the alignment of exported symbol.
27+
1. Changing the layout of exported symbol (for example, reordering class field
28+
members).
29+
1. Adding or removing base classes.
30+
31+
Adding a new exported symbol is considered to be non-breaking change.
32+
33+
## ABI Versioning Policy
34+
35+
TBD
36+
37+
## `__SYCL_EXPORT` Macro
38+
39+
The `__SYCL_EXPORT` provides facilities for fine-grained control over exported
40+
symbols. Mark symbols that are supposed to be accessible by the user and that
41+
are implemented in the SYCL Runtime library with this macro. Template
42+
specializations also must be explicitly marked with `__SYCL_EXPORT` macro.
43+
Symbols not marked `__SYCL_EXPORT` have internal linkage.
44+
45+
A few examples of when it is necessary to mark symbols with the macro:
46+
47+
* The `device` class:
48+
- It is defined as API by the SYCL spec.
49+
- It is implemented in `device.cpp` file.
50+
* The `SYCLMemObjT` class:
51+
- It is not defined in the SYCL spec, but it is an implementation detail that
52+
is accessible by the user (buffer and image inherit from this class).
53+
- It has symbols that are implemented in the Runtime library.
54+
55+
When it is not necessary to mark symbols with `__SYCL_EXPORT`:
56+
* The `buffer` class:
57+
- It is defined by the SYCL spec, but it is fully implemented in the headers.
58+
* The `ProgramManager` class:
59+
- It is an implementation detail.
60+
- It is not accessed from the header files that are available to users.
61+
62+
## Automated ABI Changes Testing
63+
64+
> The automated tests deal with the most commonly occurring problems, but they
65+
> may not catch some corner cases. If you believe your PR breaks ABI, but the
66+
> test does not indicate that, please, notify the reviewers.
67+
68+
There is a set of tests to help identifying ABI changes:
69+
70+
* `test/abi/sycl_symbols_*.dump` contains dump of publicly available symbols.
71+
If you add a new symbol, it is considered non-breaking change. When the test
72+
reports missing symbols, it means you have either changed or remove some of
73+
existing API methods. In both cases you need to adjust the dump file. You
74+
can do it either manually, or by invoking the following command:
75+
```shell
76+
python3 sycl/tools/abi_check.py --mode dump_symbols --output path/to/output.dump path/to/sycl.so(.dll)
77+
```
78+
* `test/abi/layout*` and `test/abi/symbol_size*` are a group of tests to check
79+
the internal layout of some classes. The layout tests check Clang AST for
80+
changes, while symbol_size check `sizeof` for objects. Changing the class
81+
layout is a breaking change.
82+
83+
## Breaking ABI
84+
85+
Whenever you need to change the existing ABI, please, follow these steps:
86+
87+
1. Adjust you PR description to reflect (non-)breaking ABI changes. Make sure
88+
it is clear, why breaking ABI is necessary.
89+
2. Fix failing ABI tests in your Pull Request. Use aforementioned techniques to
90+
update test files.
91+
3. Update the library version according to the policies.

sycl/doc/contents.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ Developing oneAPI DPC++ Compiler
2424
CompilerAndRuntimeDesign
2525
EnvironmentVariables
2626
PluginInterface
27-
27+
ABIPolicyGuide

sycl/test/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ set(LLVM_TOOLS_DIR "${LLVM_BINARY_DIR}/bin/")
33
get_target_property(SYCL_BINARY_DIR sycl-toolchain BINARY_DIR)
44

55
set(SYCL_INCLUDE "${SYCL_INCLUDE_BUILD_DIR}")
6+
set(SYCL_TOOLS_SRC_DIR "${PROJECT_SOURCE_DIR}/tools/")
7+
set(LLVM_BUILD_BINARY_DIRS "${LLVM_BINARY_DIR}/bin/")
8+
set(LLVM_BUILD_LIBRARY_DIRS "${LLVM_BINARY_DIR}/lib/")
69

710
set(RT_TEST_ARGS ${RT_TEST_ARGS} "-v")
811
set(DEPLOY_RT_TEST_ARGS ${DEPLOY_RT_TEST_ARGS} "-v -D SYCL_TOOLS_DIR=${CMAKE_INSTALL_PREFIX}/bin -D SYCL_LIBS_DIR=${CMAKE_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX} -D SYCL_INCLUDE=${SYCL_INCLUDE_DEPLOY_DIR}")
@@ -27,6 +30,8 @@ list(APPEND SYCL_TEST_DEPS
2730
not
2831
get_device_count_by_type
2932
llvm-config
33+
llvm-cxxdump
34+
llvm-readobj
3035
)
3136

3237
list(APPEND SYCL_DEPLOY_TEST_DEPS

sycl/test/abi/layout_handler.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %clangxx -fsycl -c -fno-color-diagnostics -Xclang -ast-dump %s | FileCheck %s
2+
// REQUIRES: linux
3+
4+
#include <CL/sycl/handler.hpp>
5+
6+
// The order of field declarations and their types are important.
7+
8+
// CHECK: CXXRecordDecl {{.*}} class handler definition
9+
// CHECK: FieldDecl {{.*}} MQueue 'shared_ptr_class<detail::queue_impl>':'std::shared_ptr<cl::sycl::detail::queue_impl>'
10+
// CHECK-NEXT: FieldDecl {{.*}} MArgsStorage 'vector_class<vector_class<char> >':'std::vector<std::vector<char, std::allocator<char> >, std::allocator<std::vector<char, std::allocator<char> > > >'
11+
// CHECK-NEXT: FieldDecl {{.*}} MAccStorage 'vector_class<detail::AccessorImplPtr>':'std::vector<std::shared_ptr<cl::sycl::detail::AccessorImplHost>, std::allocator<std::shared_ptr<cl::sycl::detail::AccessorImplHost> > >'
12+
// CHECK-NEXT: FieldDecl {{.*}} MLocalAccStorage 'vector_class<detail::LocalAccessorImplPtr>':'std::vector<std::shared_ptr<cl::sycl::detail::LocalAccessorImplHost>, std::allocator<std::shared_ptr<cl::sycl::detail::LocalAccessorImplHost> > >'
13+
// CHECK-NEXT: FieldDecl {{.*}} MStreamStorage 'vector_class<shared_ptr_class<detail::stream_impl> >':'std::vector<std::shared_ptr<cl::sycl::detail::stream_impl>, std::allocator<std::shared_ptr<cl::sycl::detail::stream_impl> > >'
14+
// CHECK-NEXT: FieldDecl {{.*}} MSharedPtrStorage 'vector_class<shared_ptr_class<const void> >':'std::vector<std::shared_ptr<const void>, std::allocator<std::shared_ptr<const void> > >'
15+
// CHECK-NEXT: FieldDecl {{.*}} MArgs 'vector_class<detail::ArgDesc>':'std::vector<cl::sycl::detail::ArgDesc, std::allocator<cl::sycl::detail::ArgDesc> >'
16+
// CHECK-NEXT: FieldDecl {{.*}} MAssociatedAccesors 'vector_class<detail::ArgDesc>':'std::vector<cl::sycl::detail::ArgDesc, std::allocator<cl::sycl::detail::ArgDesc> >'
17+
// CHECK-NEXT: FieldDecl {{.*}} MRequirements 'vector_class<detail::Requirement *>':'std::vector<cl::sycl::detail::AccessorImplHost *, std::allocator<cl::sycl::detail::AccessorImplHost *> >'
18+
// CHECK-NEXT: FieldDecl {{.*}} MNDRDesc 'detail::NDRDescT':'cl::sycl::detail::NDRDescT'
19+
// CHECK-NEXT: FieldDecl {{.*}} MKernelName 'cl::sycl::string_class':'std::__cxx11::basic_string<char>'
20+
// CHECK-NEXT: FieldDecl {{.*}} MKernel 'shared_ptr_class<detail::kernel_impl>':'std::shared_ptr<cl::sycl::detail::kernel_impl>'
21+
// CHECK-NEXT: FieldDecl {{.*}} MCGType 'detail::CG::CGTYPE':'cl::sycl::detail::CG::CGTYPE'
22+
// CHECK-NEXT: DeclRefExpr {{.*}} 'cl::sycl::detail::CG::CGTYPE' EnumConstant {{.*}} 'NONE' 'cl::sycl::detail::CG::CGTYPE'
23+
// CHECK-NEXT: FieldDecl {{.*}} MSrcPtr 'void *'
24+
// CHECK-NEXT: ImplicitCastExpr {{.*}} <NullToPointer>
25+
// CHECK-NEXT: CXXNullPtrLiteralExpr {{.*}} 'nullptr_t'
26+
// CHECK-NEXT: FieldDecl {{.*}} MDstPtr 'void *'
27+
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void *' <NullToPointer>
28+
// CHECK-NEXT: CXXNullPtrLiteralExpr {{.*}} 'nullptr_t'
29+
// CHECK-NEXT: FieldDecl {{.*}} MLength 'size_t':'unsigned long'
30+
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'size_t':'unsigned long' <IntegralCast>
31+
// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0
32+
// CHECK-NEXT: FieldDecl {{.*}} MPattern 'vector_class<char>':'std::vector<char, std::allocator<char> >'
33+
// CHECK-NEXT: FieldDecl {{.*}} MHostKernel 'unique_ptr_class<detail::HostKernelBase>':'std::unique_ptr<cl::sycl::detail::HostKernelBase, std::default_delete<cl::sycl::detail::HostKernelBase> >'
34+
// CHECK-NEXT: FieldDecl {{.*}} MOSModuleHandle 'detail::OSModuleHandle':'long'
35+
// CHECK-NEXT: FieldDecl {{.*}} MInteropTask 'std::unique_ptr<detail::InteropTask>':'std::unique_ptr<cl::sycl::detail::InteropTask, std::default_delete<cl::sycl::detail::InteropTask> >'
36+
// CHECK-NEXT: FieldDecl {{.*}} MEvents 'vector_class<detail::EventImplPtr>':'std::vector<std::shared_ptr<cl::sycl::detail::event_impl>, std::allocator<std::shared_ptr<cl::sycl::detail::event_impl> > >'
37+
// CHECK-NEXT: FieldDecl {{.*}} MIsHost 'bool'
38+
// CHECK-NEXT: CXXBoolLiteralExpr {{.*}} 'bool' false

0 commit comments

Comments
 (0)