If you have improvements, new backends support, or new operators to contribute to the generic sycl backend, please send us your pull requests! For getting started, see GitHub howto.
Before sending your pull requests, ensure that you follow this checklist:
-
Ensure that your code includes proper documentation.
-
Ensure that the changes are consistent with the coding style.
If you find a bug or problem, please open a request under Issues.
Report security issues to [email protected]
The general principle is to follow the style of existing/surrounding code. If you are in doubt, use the clang-format
:
clang-format -style=file -i foo.cpp
This formats code using the .clang_format
file found in the generic-sycl-components top-level directory.
-
GN1: Use snake_case for all type names: classes, structures, enums, template type arguments, type aliases.
-
GN2: Use snake_case for all variables (global, local, files, function parameters), global and local constants (including constexpr), functions (member, non-member) and enum values.
-
GN3: Use capitalized SNAKE_CASE only for macros.
-
GF1: Each line of text in the code shall be at most 100 characters long.
-
GF2: Use only spaces, and indent 4 spaces at a time, never use tabs.
-
GF3: The open curly brace is always on the end of the last line of the statement (type, function, namespace declaration or control flow statement), not the start of the next line.
int foo() { // <-- curly brace here
do_something();
}
if (condition) { // <-- curly brace here
do_something();
}
else { // <-- curly brace here
do_something();
}
if (condition) { // <-- curly brace here
do_something();
} else { // <-- Also possible
do_something();
}
- GF4: There is never a space between the parentheses and the parameters in function declaration/invocation or control flow statements.
// Wrong
int foo( int arg_1, float arg_2 );
if ( condition );
call_foo( value_1, value_2 );
for ( int i = 0; i < loop_count; i++ );
// Right
int foo(int arg_1, float arg_2);
if (condition);
call_foo(value_1, value_2);
for (int i = 0; i < loop_count; i++);
-
FA1: Filenames should be lowercase and can include underscores "_".
-
FA2: C++ header files exposed to the user should end in .hpp.
-
FA3: C++ source files should end in .cpp.
-
FA4: All header files shall start with
#pragma once
guards to prevent multiple inclusion, refer to Structure of Header Files for more details. -
FA5: Each header file shall contain items in the following order:
- Copyright
- Single blank line
- Preprocessor guard
- Single blank line
- Include statements (if there)
- Single blank line if include statements are present
- Global macros* (if any)
- Single blank line if macros statements are present
- Type/function declarations wrapped into namespaces
Note: It is not necessary to put all macro definitions here. Sometimes it is convenient to have macros closer to the place where they are used. For example, sometimes it makes more sense to define macros inside the functions that use them (see Macros for more details). However, if the macro is used throughout the library, put it in header file between includes and the namespace declaration.
-
FA6: Each header file shall include other header files in the following order:
- C standard headers
- C++ standard headers
- Single blank line if C/C++ headers are present
- Third party libraries' header files (e.g., SYCL, TBB, OMP, etc.)
- Single blank line if third party headers are present
- Project's header files
-
NS1: Use snake_case: all lowercase, with underscores "_" between words for all namespaces.
-
NS2: Do not indent content inside a namespace scope.
// Wrong! Do not indent
namespace oneapi {
namespace math {
class table { };
} // namespace math
} // namespace oneapi
// Right
namespace oneapi {
namespace math {
class table { };
} // namespace math
} // namespace oneapi
- NS4: Put each namespace on its own line when declaring nested namespaces.
#include "oneapi/math/blas/path_to_some_header.hpp"
namespace oneapi {
namespace math {
namespace blas {
/* ... */
} // namespace blas
} // namespace math
} // namespace oneapi
- FU1: Use snake_case: all lowercase, with
// Underscores between words for all function names.
return_type class_name::function_name(type_1 arg_name_1, type_2 arg_name_2) {
do_something();
}
- FU2: There is never a space between the function name (or operator) and the open brace. This rule applies to both function declaration/definitions and calls.
Declaration
// Wrong
void foo (type arg_name);
void operator() (type arg_name);
void operator bool ();
// Right
void foo(type arg_name);
void operator()(type arg_name);
void operator bool();
Call
// Wrong
const auto x = foo (arg_1, arg_2);
// Right
const auto x = foo(arg_1, arg_2);
- FU3: Do not put the function signature and the body on the same line. The only exception is an empty body, in that case place the curly braces at the same line (see rule FU4).
// Wrong
std::int32_t get_something() const { return something_; }
// Right
std::int32_t get_something() const {
return something_;
}
- FU4: Empty function body shall be at the same line as function signature.
// Wrong
void empty_foo(type arg) {
}
// Right
void empty_foo(type arg) {}
- CS1: Use snake_case: lower case and all words are separated with underscore character (_).
class numeric_table;
class image;
struct params;
- CS2: The acceptable formats for initializer lists are when everything fits on one line:
my_class::my_class(int var) : some_var_(var) {
do_something();
}
If the signature and initializer list are not all on one line, you must line wrap before the colon, indent 8 spaces, put each member on its own line, and align them:
my_class::my_class(int var)
: some_var_(var), // <-- 8 space indent
some_other_var_(var + 1) { // lined up
do_something();
}
As with any other code block, the close curly brace can be on the same line as the open curly, if it fits:
my_class::my_class(int var)
: some_var_(var),
another_var_(0) {}
-
VC1: Use snake_case for all variables, function's arguments and constants.
-
VC2: Use variables and constant names followed by one underscore "_" for private and protected class-level variables.
-
VC3: The assignment operator "=" shall be surrounded by single whitespace.
const auto val = get_some_value();
- ST1: Each of the keywords if/else/do/while/for/switch shall be followed by one space. An open curly brace after the condition shall be prepended with one space.
while (condition) { // <-- one space after `while` and one space before `{`
do_something();
} // <-- `;` is not required
- ST2: Each of the keywords if/else/do/while/for/switch shall always have accompanying curly braces even if they contain a single-line statement.
// Wrong
if (my_const == my_var)
do_something();
// Right
if (my_const == my_var) {
do_something();
}
- ST3: The statements within parentheses for operators if, for, while shall have no spaces adjacent to the open and close parentheses characters:
// Wrong
for ( int i = 0; i < loop_size; i++ ) ...;
// Right
for (int i = 0; i < loop_size; i++) ...;