Skip to content

Commit 81e9be7

Browse files
joppermPennycook
andauthored
[SYCL][RTC] Clarify and test handling of include paths (#17307)
Multiple changes related to the handling of `#include`'s in RTC: - Fix a bug in how the in-memory pipeline rendered joined arguments - Add "current working directory" and "directories specified via `-I` in `build_options`" to the locations that extension will look for header files, and clarifiy search order, in the specification. This change is meant to establish clang's usual include behavior. - Add an extensive E2E test for include handling - Check if filename is not present in `include_files::add` to match specification - Add missing constructors and `add` method to `include_files` and `build_properties` to match specification --------- Signed-off-by: Julian Oppermann <[email protected]> Co-authored-by: John Pennycook <[email protected]>
1 parent dc5ce17 commit 81e9be7

File tree

9 files changed

+319
-36
lines changed

9 files changed

+319
-36
lines changed

sycl-jit/jit-compiler/lib/rtc/DeviceCompilation.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,10 @@ static void adjustArgs(const InputArgList &UserArgList,
333333
DAL.eraseArg(OPT_ftime_trace_granularity_EQ);
334334
DAL.eraseArg(OPT_ftime_trace_verbose);
335335

336-
for (auto *Arg : DAL) {
337-
CommandLine.emplace_back(Arg->getAsString(DAL));
338-
}
336+
ArgStringList ASL;
337+
for_each(DAL, [&DAL, &ASL](Arg *A) { A->render(DAL, ASL); });
338+
transform(ASL, std::back_inserter(CommandLine),
339+
[](const char *AS) { return std::string{AS}; });
339340
}
340341

341342
static void setupTool(ClangTool &Tool, const std::string &DPCPPRoot,

sycl/doc/extensions/experimental/sycl_ext_oneapi_kernel_compiler.asciidoc

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -363,20 +363,11 @@ whose _Name_ is `foo/bar.h`.
363363
If such an entry is found, the compiler uses the associated _Content_ as the
364364
content of the include file.
365365

366-
When the source language is `source_language::sycl`, the following header files
367-
are implicitly available.
368-
Therefore, the source string may `#include` these even without defining their
369-
content via the `include_files` property:
370-
371-
* `<sycl/sycl.hpp>`;
372-
* The {cpp} standard library headers;
373-
* The SYCL backend headers `"sycl/backend/<backend_name>.hpp"` for any backends
374-
that the implementation supports; and
375-
* Any SYCL extension headers in "sycl/ext" for extensions that the
376-
implementation supports.
377-
378-
The include files defined via the `include_files` property are searched first,
379-
before these implicitly available headers.
366+
[_Note_: This property is only required if an `#include` statement references a
367+
file that is not already implicitly available.
368+
For more information about implicitly available headers, see the section
369+
"Including files when the language is ``sycl``".
370+
_{endnote}_]
380371

381372
_Effects (1):_ Creates a new `include_files` property with no (_Name_,
382373
_Content_) pairs.
@@ -655,6 +646,27 @@ _Throws:_
655646
`ext_oneapi_has_kernel(name)` returns `false`.
656647
|====
657648

649+
=== Including files when the language is `sycl`
650+
651+
When the source language is `source_language::sycl`, the compiler searches
652+
multiple locations to find files referenced by `#include` statements.
653+
Any include files defined via the `include_files` property are searched first,
654+
followed by the directories below, in order:
655+
656+
1. The current working directory.
657+
2. Any directory added explicitly to the search list via the `build_options`
658+
property.
659+
660+
Finally, the compiler searches a set of implicitly available header files, which
661+
do not need to be specified via the `include_files` property:
662+
663+
* `<sycl/sycl.hpp>`;
664+
* The {cpp} standard library headers;
665+
* The SYCL backend headers `"sycl/backend/<backend_name>.hpp"` for any backends
666+
that the implementation supports; and
667+
* Any SYCL extension headers in `"sycl/ext"` for extensions that the
668+
implementation supports.
669+
658670
=== Obtaining a kernel when the language is `sycl`
659671

660672
When the kernel is defined in the language `source_language::sycl`, the host
@@ -938,3 +950,25 @@ There is no inherent reason why this functionality needs to be built into
938950
However, we don't yet have a utility library where this would go, and it may be
939951
hard for customers to discover this functionality if it is defined outside of
940952
this extension.
953+
954+
== Non-normative implementation notes for {dpcpp}
955+
956+
=== Supported `build_options` when the language is `sycl`
957+
958+
The SYCL runtime compiler supports the following {dpcpp} options to be passed in
959+
the `build_options` property.
960+
961+
[%header,cols="1,3"]
962+
|===
963+
|Option
964+
|Notes
965+
966+
|`-I<dir>` +
967+
`-I <dir>` +
968+
`--include-directory=<dir>` +
969+
`--include-directory <dir>`
970+
| Add `<dir>` to to the search list for include files (see section "Including
971+
files when the language is ``sycl``"). This is useful, for example, to compile
972+
kernels using external libraries. Note that for the second and fourth form,
973+
`dir` is a separate element in the `build_options` list.
974+
|===

sycl/include/sycl/kernel_bundle.hpp

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,22 @@
2626
#include <sycl/ext/oneapi/properties/property.hpp> // build_options
2727
#include <sycl/ext/oneapi/properties/property_value.hpp> // and log
2828

29+
#include <algorithm> // for copy
2930
#include <array> // for array
3031
#include <cstddef> // for std::byte
3132
#include <cstring> // for size_t, memcpy
3233
#include <functional> // for function
33-
#include <iterator> // for distance
34+
#include <iterator> // for distance, back_inserter
3435
#include <memory> // for shared_ptr, operator==, hash
3536
#if __has_include(<span>)
3637
#include <span>
3738
#endif
38-
#include <string> // for string
39-
#include <type_traits> // for enable_if_t, remove_refer...
40-
#include <utility> // for move
41-
#include <variant> // for hash
42-
#include <vector> // for vector
39+
#include <string> // for string
40+
#include <type_traits> // for enable_if_t, remove_refer...
41+
#include <unordered_map> // for unordered_map
42+
#include <utility> // for move
43+
#include <variant> // for hash
44+
#include <vector> // for vector
4345

4446
namespace sycl {
4547
inline namespace _V1 {
@@ -954,14 +956,19 @@ struct build_source_bundle_props;
954956
struct include_files
955957
: detail::run_time_property_key<include_files,
956958
detail::PropKind::IncludeFiles> {
957-
include_files();
959+
include_files() {}
958960
include_files(const std::string &name, const std::string &content) {
959-
record.emplace_back(std::make_pair(name, content));
961+
record.emplace(name, content);
960962
}
961963
void add(const std::string &name, const std::string &content) {
962-
record.emplace_back(std::make_pair(name, content));
964+
bool inserted = record.try_emplace(name, content).second;
965+
if (!inserted) {
966+
throw sycl::exception(make_error_code(errc::invalid),
967+
"Include file '" + name +
968+
"' is already registered");
969+
}
963970
}
964-
std::vector<std::pair<std::string, std::string>> record;
971+
std::unordered_map<std::string, std::string> record;
965972
};
966973
using include_files_key = include_files;
967974

@@ -977,8 +984,10 @@ struct build_options
977984
: detail::run_time_property_key<build_options,
978985
detail::PropKind::BuildOptions> {
979986
std::vector<std::string> opts;
987+
build_options() {}
980988
build_options(const std::string &optsArg) : opts{optsArg} {}
981989
build_options(const std::vector<std::string> &optsArg) : opts(optsArg) {}
990+
void add(const std::string &opt) { opts.push_back(opt); }
982991
};
983992
using build_options_key = build_options;
984993

@@ -1116,7 +1125,10 @@ kernel_bundle<bundle_state::ext_oneapi_source> create_kernel_bundle_from_source(
11161125
const std::string &Source, PropertyListT props = {}) {
11171126
std::vector<std::pair<std::string, std::string>> IncludePairsVec;
11181127
if constexpr (props.template has_property<include_files>()) {
1119-
IncludePairsVec = props.template get_property<include_files>().record;
1128+
const std::unordered_map<std::string, std::string> &IncludePairs =
1129+
props.template get_property<include_files>().record;
1130+
std::copy(IncludePairs.begin(), IncludePairs.end(),
1131+
std::back_inserter(IncludePairsVec));
11201132
}
11211133

11221134
return detail::make_kernel_bundle_from_source(SyclContext, Language, Source,
@@ -1132,7 +1144,10 @@ kernel_bundle<bundle_state::ext_oneapi_source> create_kernel_bundle_from_source(
11321144
const std::vector<std::byte> &Bytes, PropertyListT props = {}) {
11331145
std::vector<std::pair<std::string, std::string>> IncludePairsVec;
11341146
if constexpr (props.template has_property<include_files>()) {
1135-
IncludePairsVec = props.template get_property<include_files>().record;
1147+
const std::unordered_map<std::string, std::string> &IncludePairs =
1148+
props.template get_property<include_files>().record;
1149+
std::copy(IncludePairs.begin(), IncludePairs.end(),
1150+
std::back_inserter(IncludePairsVec));
11361151
}
11371152

11381153
return detail::make_kernel_bundle_from_source(SyclContext, Language, Bytes,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#define DEFINE_1 fsA
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#define DEFINE_2 fsB
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#define DEFINE_1 fsC

0 commit comments

Comments
 (0)