|
9 | 9 | #include "kernel_compiler_sycl.hpp" |
10 | 10 | #include <sycl/exception.hpp> // make_error_code |
11 | 11 |
|
12 | | -// CP |
13 | | -/* |
14 | | -#if __GNUC__ && __GNUC__ < 8 |
15 | | -
|
16 | | -// std::filesystem is not availalbe for GCC < 8 |
17 | | -// and much of the cross-platform file handling code depends upon it. |
18 | | -// Given that this extension is experimental and that the file |
19 | | -// handling aspects are most likely temporary, it makes sense to |
20 | | -// simply not support GCC<8. |
21 | | -
|
22 | | -namespace sycl { |
23 | | -inline namespace _V1 { |
24 | | -namespace ext::oneapi::experimental { |
25 | | -namespace detail { |
26 | | -
|
27 | | -bool SYCL_Compilation_Available() { return false; } |
28 | | -
|
29 | | -spirv_vec_t |
30 | | -SYCL_to_SPIRV(const std::string &SYCLSource, include_pairs_t IncludePairs, |
31 | | - const std::vector<std::string> &UserArgs, std::string *LogPtr, |
32 | | - const std::vector<std::string> &RegisteredKernelNames) { |
33 | | - (void)SYCLSource; |
34 | | - (void)IncludePairs; |
35 | | - (void)UserArgs; |
36 | | - (void)LogPtr; |
37 | | - (void)RegisteredKernelNames; |
38 | | - throw sycl::exception(sycl::errc::build, |
39 | | - "kernel_compiler does not support GCC<8"); |
40 | | -} |
41 | | -
|
42 | | -std::string userArgsAsString(const std::vector<std::string> &UserArguments) { |
43 | | - return std::accumulate(UserArguments.begin(), UserArguments.end(), |
44 | | - std::string(""), |
45 | | - [](const std::string &A, const std::string &B) { |
46 | | - return A.empty() ? B : A + " " + B; |
47 | | - }); |
48 | | -} |
49 | | -
|
50 | | -} // namespace detail |
51 | | -} // namespace ext::oneapi::experimental |
52 | | -} // namespace _V1 |
53 | | -} // namespace sycl |
54 | | -
|
55 | | -#else |
56 | | -*/ |
57 | | - |
58 | | -// #include <sycl/detail/os_util.hpp> |
59 | | - |
60 | | -// #include <ctime> |
61 | | -// #include <filesystem> |
62 | | -// #include <fstream> |
63 | | -// #include <random> |
64 | | -// #include <regex> |
65 | | -// #include <sstream> |
66 | | -// #include <stdio.h> |
67 | | - |
68 | | -namespace sycl { |
69 | | -inline namespace _V1 { |
70 | | -namespace ext::oneapi::experimental { |
71 | | -namespace detail { |
72 | | - |
73 | | -// std::string generateSemiUniqueId() { |
74 | | -// auto Now = std::chrono::high_resolution_clock::now(); |
75 | | -// auto Milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>( |
76 | | -// Now.time_since_epoch()); |
77 | | - |
78 | | -// // Generate random number between 10'000 and 99'900. |
79 | | -// std::random_device RD; |
80 | | -// std::mt19937 Gen(RD()); |
81 | | -// std::uniform_int_distribution<int> Distrib(10'000, 99'999); |
82 | | -// int RandomNumber = Distrib(Gen); |
83 | | - |
84 | | -// // Combine time and random number into a string. |
85 | | -// std::stringstream Ss; |
86 | | -// Ss << Milliseconds.count() << "_" << std::setfill('0') << std::setw(5) |
87 | | -// << RandomNumber; |
88 | | - |
89 | | -// return Ss.str(); |
90 | | -// } |
91 | | - |
92 | | -// std::filesystem::path prepareWS(const std::string &Id) { |
93 | | -// namespace fs = std::filesystem; |
94 | | -// const fs::path TmpDirectoryPath = fs::temp_directory_path(); |
95 | | -// fs::path NewDirectoryPath = TmpDirectoryPath / Id; |
96 | | - |
97 | | -// try { |
98 | | -// fs::create_directories(NewDirectoryPath); |
99 | | -// fs::permissions(NewDirectoryPath, fs::perms::owner_read | |
100 | | -// fs::perms::owner_write | |
101 | | -// fs::perms::owner_exec); // 0700 |
102 | | - |
103 | | -// } catch (const fs::filesystem_error &E) { |
104 | | -// throw sycl::exception(sycl::errc::build, E.what()); |
105 | | -// } |
106 | | - |
107 | | -// return NewDirectoryPath; |
108 | | -// } |
109 | | - |
110 | | -// void deleteWS(const std::filesystem::path &ParentDir) { |
111 | | -// try { |
112 | | -// std::filesystem::remove_all(ParentDir); |
113 | | -// } catch (const std::filesystem::filesystem_error &E) { |
114 | | -// // We could simply suppress this, since deleting the directory afterwards |
115 | | -// // is not critical. But if there are problems, seems good to know. |
116 | | -// throw sycl::exception(sycl::errc::build, E.what()); |
117 | | -// } |
118 | | -// } |
119 | | - |
120 | | -std::string userArgsAsString(const std::vector<std::string> &UserArguments) { |
121 | | - return std::accumulate(UserArguments.begin(), UserArguments.end(), |
122 | | - std::string(""), |
123 | | - [](const std::string &A, const std::string &B) { |
124 | | - return A.empty() ? B : A + " " + B; |
125 | | - }); |
126 | | -} |
127 | | - |
128 | | -// void outputPreamble(std::ofstream &Os, const std::filesystem::path &FilePath, |
129 | | -// const std::string &Id, |
130 | | -// const std::vector<std::string> &UserArgs) { |
131 | | - |
132 | | -// Os << "/*\n"; |
133 | | -// Os << " clang++ -fsycl -o " << Id << ".bin "; |
134 | | -// Os << userArgsAsString(UserArgs); |
135 | | -// Os << " -fno-sycl-dead-args-optimization -fsycl-dump-device-code=./ " << Id; |
136 | | -// Os << ".cpp \n */" << std::endl; |
137 | | -// } |
138 | | - |
139 | | -// std::filesystem::path |
140 | | -// outputCpp(const std::filesystem::path &ParentDir, const std::string &Id, |
141 | | -// std::string RawCodeString, const std::vector<std::string> &UserArgs, |
142 | | -// const std::vector<std::string> &RegisteredKernelNames) { |
143 | | -// std::filesystem::path FilePath = ParentDir / (Id + ".cpp"); |
144 | | -// std::ofstream Outfile(FilePath, std::ios::out | std::ios::trunc); |
145 | | - |
146 | | -// if (Outfile.is_open()) { |
147 | | -// outputPreamble(Outfile, FilePath, Id, UserArgs); |
148 | | -// Outfile << RawCodeString << std::endl; |
149 | | - |
150 | | -// // Temporarily needed until -c works with -fsycl-dump-spirv. |
151 | | -// Outfile << "int main() {\n"; |
152 | | -// for (const std::string &KernelName : RegisteredKernelNames) { |
153 | | -// Outfile << " " << KernelName << ";\n"; |
154 | | -// } |
155 | | -// Outfile << " return 0;\n}\n" << std::endl; |
156 | | - |
157 | | -// Outfile.close(); |
158 | | -// } else { |
159 | | -// throw sycl::exception(sycl::errc::build, |
160 | | -// "Failed to open .cpp file for write: " + |
161 | | -// FilePath.string()); |
162 | | -// } |
163 | | - |
164 | | -// return FilePath; |
165 | | -// } |
166 | | - |
167 | | -// void outputIncludeFiles(const std::filesystem::path &Dirpath, |
168 | | -// include_pairs_t IncludePairs) { |
169 | | -// using pairStrings = std::pair<std::string, std::string>; |
170 | | -// for (pairStrings p : IncludePairs) { |
171 | | -// std::filesystem::path FilePath = Dirpath / p.first; |
172 | | -// std::filesystem::create_directories(FilePath.parent_path()); |
173 | | -// std::ofstream outfile(FilePath, std::ios::out | std::ios::trunc); |
174 | | -// if (outfile.is_open()) { |
175 | | -// outfile << p.second << std::endl; |
176 | | - |
177 | | -// outfile.close(); |
178 | | -// } else { |
179 | | -// throw sycl::exception(sycl::errc::build, |
180 | | -// "Failed to open include file for write: " + |
181 | | -// FilePath.string()); |
182 | | -// } |
183 | | -// } |
184 | | -// } |
185 | | - |
186 | | -// std::string getCompilerName() { |
187 | | -// #ifdef _WIN32 |
188 | | -// std::string Compiler = "clang++.exe"; |
189 | | -// #else |
190 | | -// std::string Compiler = "clang++"; |
191 | | -// #endif |
192 | | -// return Compiler; |
193 | | -// } |
194 | | - |
195 | | -// // We are assuming that the compiler is in /bin and the shared lib in |
196 | | -// // the adjacent /lib. |
197 | | -// std::filesystem::path getCompilerPath() { |
198 | | -// std::string Compiler = getCompilerName(); |
199 | | -// const std::string LibSYCLDir = sycl::detail::OSUtil::getCurrentDSODir(); |
200 | | -// std::filesystem::path CompilerPath = |
201 | | -// std::filesystem::path(LibSYCLDir) / ".." / "bin" / Compiler; |
202 | | -// return CompilerPath; |
203 | | -// } |
204 | | - |
205 | | -// int invokeCommand(const std::string &command, std::string &output) { |
206 | | -// #ifdef _WIN32 |
207 | | -// FILE *pipe = _popen(command.c_str(), "r"); |
208 | | -// #else |
209 | | -// FILE *pipe = popen(command.c_str(), "r"); |
210 | | -// #endif |
211 | | -// if (!pipe) { |
212 | | -// return -1; |
213 | | -// } |
214 | | - |
215 | | -// char buffer[1024]; |
216 | | -// while (!feof(pipe)) { |
217 | | -// if (fgets(buffer, sizeof(buffer), pipe) != NULL) { |
218 | | -// output += buffer; |
219 | | -// } |
220 | | -// } |
221 | | - |
222 | | -// #ifdef _WIN32 |
223 | | -// _pclose(pipe); |
224 | | -// #else |
225 | | -// pclose(pipe); |
226 | | -// #endif |
227 | | - |
228 | | -// return 0; |
229 | | -// } |
230 | | - |
231 | | -// std::string invokeCompiler(const std::filesystem::path &FPath, |
232 | | -// const std::filesystem::path &DPath, |
233 | | -// const std::string &Id, |
234 | | -// const std::vector<std::string> &UserArgs, |
235 | | -// std::string *LogPtr) { |
236 | | - |
237 | | -// std::filesystem::path FilePath(FPath); |
238 | | -// std::filesystem::path ParentDir(DPath); |
239 | | -// std::filesystem::path TargetPath = ParentDir / (Id + ".bin"); |
240 | | -// std::filesystem::path LogPath = ParentDir / "compilation_log.txt"; |
241 | | -// std::string Compiler = getCompilerPath().make_preferred().string(); |
242 | | - |
243 | | -// std::string Command = |
244 | | -// Compiler + " -fsycl -o " + TargetPath.make_preferred().string() + " " + |
245 | | -// userArgsAsString(UserArgs) + |
246 | | -// " -fno-sycl-dead-args-optimization -fsycl-dump-device-code=" + |
247 | | -// ParentDir.make_preferred().string() + " " + |
248 | | -// FilePath.make_preferred().string() + " 2>&1"; |
249 | | - |
250 | | -// std::string CompileLog; |
251 | | -// int Result = invokeCommand(Command, CompileLog); |
252 | | - |
253 | | -// if (LogPtr != nullptr) { |
254 | | -// LogPtr->append(CompileLog); |
255 | | -// } |
256 | | - |
257 | | -// // There is little chance of Result being non-zero. |
258 | | -// // Actual compilation failure is not detected by error code, |
259 | | -// // but by missing .spv files. |
260 | | -// if (Result != 0) { |
261 | | -// throw sycl::exception(sycl::errc::build, |
262 | | -// "Compile failure: " + std::to_string(Result) + " " + |
263 | | -// CompileLog); |
264 | | -// } |
265 | | -// return CompileLog; |
266 | | -// } |
267 | | - |
268 | | -// std::filesystem::path findSpv(const std::filesystem::path &ParentDir, |
269 | | -// const std::string &Id, std::string &CompileLog) { |
270 | | -// std::regex PatternRegex(Id + R"(.*\.spv)"); |
271 | | - |
272 | | -// // Iterate through all files in the directory matching the pattern. |
273 | | -// for (const auto &Entry : std::filesystem::directory_iterator(ParentDir)) { |
274 | | -// if (Entry.is_regular_file() && |
275 | | -// std::regex_match(Entry.path().filename().string(), PatternRegex)) { |
276 | | -// return Entry.path(); // Return the path if it matches the SPV pattern. |
277 | | -// } |
278 | | -// } |
279 | | - |
280 | | -// // Missing .spv file indicates there was a compilation failure. |
281 | | -// throw sycl::exception(sycl::errc::build, "Compile failure: " + CompileLog); |
282 | | -// } |
283 | | - |
284 | | -// spirv_vec_t loadSpvFromFile(const std::filesystem::path &FileName) { |
285 | | -// std::ifstream SpvStream(FileName, std::ios::binary); |
286 | | -// SpvStream.seekg(0, std::ios::end); |
287 | | -// size_t Size = SpvStream.tellg(); |
288 | | -// SpvStream.seekg(0); |
289 | | -// spirv_vec_t Spv(Size); |
290 | | -// SpvStream.read(reinterpret_cast<char *>(Spv.data()), Size); |
291 | | - |
292 | | -// return Spv; |
293 | | -// } |
294 | | - |
295 | | -// spirv_vec_t |
296 | | -// SYCL_to_SPIRV(const std::string &SYCLSource, include_pairs_t IncludePairs, |
297 | | -// const std::vector<std::string> &UserArgs, std::string *LogPtr, |
298 | | -// const std::vector<std::string> &RegisteredKernelNames) { |
299 | | -// // clang-format off |
300 | | -// const std::string id = generateSemiUniqueId(); |
301 | | -// const std::filesystem::path ParentDir = prepareWS(id); |
302 | | -// std::filesystem::path FilePath = outputCpp(ParentDir, id, SYCLSource, UserArgs, RegisteredKernelNames); |
303 | | -// outputIncludeFiles(ParentDir, IncludePairs); |
304 | | -// std::string CompileLog = invokeCompiler(FilePath, ParentDir, id, UserArgs, LogPtr); |
305 | | -// std::filesystem::path SpvPath = findSpv(ParentDir, id, CompileLog); |
306 | | -// spirv_vec_t Spv = loadSpvFromFile(SpvPath); |
307 | | -// deleteWS(ParentDir); |
308 | | -// return Spv; |
309 | | -// // clang-format on |
310 | | -// } |
311 | | - |
312 | | -// bool SYCL_Compilation_Available() { |
313 | | -// // Is compiler on $PATH ? We try to invoke it. |
314 | | -// std::string id = generateSemiUniqueId(); |
315 | | -// const std::filesystem::path tmp = std::filesystem::temp_directory_path(); |
316 | | -// std::filesystem::path DumpPath = tmp / (id + "_version.txt"); |
317 | | -// std::string Compiler = getCompilerPath().make_preferred().string(); |
318 | | -// std::string TestCommand = |
319 | | -// Compiler + " --version > " + DumpPath.make_preferred().string(); |
320 | | -// int result = std::system(TestCommand.c_str()); |
321 | | - |
322 | | -// return (result == 0); |
323 | | -// } |
324 | | - |
325 | | -} // namespace detail |
326 | | -} // namespace ext::oneapi::experimental |
327 | | -} // namespace _V1 |
328 | | -} // namespace sycl |
329 | | -// // #endif |
330 | | - |
331 | 12 | #if SYCL_EXT_JIT_ENABLE |
332 | 13 | #include "../jit_compiler.hpp" |
333 | 14 | #endif |
@@ -360,6 +41,14 @@ spirv_vec_t SYCL_JIT_to_SPIRV( |
360 | 41 | #endif |
361 | 42 | } |
362 | 43 |
|
| 44 | +std::string userArgsAsString(const std::vector<std::string> &UserArguments) { |
| 45 | + return std::accumulate(UserArguments.begin(), UserArguments.end(), |
| 46 | + std::string(""), |
| 47 | + [](const std::string &A, const std::string &B) { |
| 48 | + return A.empty() ? B : A + " " + B; |
| 49 | + }); |
| 50 | +} |
| 51 | + |
363 | 52 | } // namespace detail |
364 | 53 | } // namespace ext::oneapi::experimental |
365 | 54 | } // namespace _V1 |
|
0 commit comments