14 #include "../online_compiler/ocloc_api.h"
15 #include "../split_string.hpp"
21 inline namespace _V1 {
22 namespace ext::oneapi::experimental {
27 void *OclocVersionHandle =
33 if (OclocVersionHandle) {
35 reinterpret_cast<decltype(::
oclocVersion) *
>(OclocVersionHandle);
36 LoadedVersion = OclocVersionFunc();
40 int LoadedVersionMajor = LoadedVersion >> 16;
41 int LoadedVersionMinor = LoadedVersion & 0xffff;
44 if (LoadedVersionMajor != CurrentVersionMajor ||
45 LoadedVersionMinor < CurrentVersionMinor) {
48 std::string(
"Found incompatible version of ocloc library: (") +
49 std::to_string(LoadedVersionMajor) +
"." +
50 std::to_string(LoadedVersionMinor) +
51 "). The supported versions are (" +
52 std::to_string(CurrentVersionMajor) +
53 ".N), where (N >= " + std::to_string(CurrentVersionMinor) +
").");
61 #ifdef __SYCL_RT_OS_WINDOWS
62 static const std::string OclocLibraryName =
"ocloc64.dll";
64 static const std::string OclocLibraryName =
"libocloc.so";
67 if (tempPtr ==
nullptr) {
70 if (tempPtr ==
nullptr)
72 "Unable to load ocloc library " + OclocLibraryName);
100 if (!oclocInvokeHandle) {
106 if (!oclocInvokeHandle)
111 if (!oclocFreeOutputHandle)
112 throw sycl::exception(the_errc,
"Cannot load oclocFreeOutput() function");
117 std::stringstream ss;
119 for (uint32_t ipVersion : IPVersionVec) {
121 if (ipVersion < 0x02000000)
133 const std::vector<uint32_t> &IPVersionVec,
134 const std::vector<std::string> &UserArgs,
135 std::string *LogPtr) {
136 std::vector<std::string> CMUserArgs = UserArgs;
137 CMUserArgs.push_back(
"-cmc");
140 static void *oclocInvokeHandle =
nullptr;
141 static void *oclocFreeOutputHandle =
nullptr;
144 SetupLibrary(oclocInvokeHandle, oclocFreeOutputHandle, build_errc);
147 std::string CombinedUserArgs =
148 std::accumulate(UserArgs.begin(), UserArgs.end(), std::string(
""),
149 [](
const std::string &acc,
const std::string &s) {
150 return acc + s +
" ";
153 std::vector<const char *> Args = {
"ocloc",
"-q",
"-spv_only",
"-options",
154 CombinedUserArgs.c_str()};
156 uint32_t NumOutputs = 0;
157 uint8_t **Outputs =
nullptr;
158 uint64_t *OutputLengths =
nullptr;
159 char **OutputNames =
nullptr;
161 const uint8_t *Sources[] = {
162 reinterpret_cast<const uint8_t *
>(Source.c_str())};
163 const char *SourceName =
"main.cl";
164 const uint64_t SourceLengths[] = {Source.length() + 1};
166 Args.push_back(
"-file");
167 Args.push_back(SourceName);
171 if (!IPVersionsStr.empty()) {
172 Args.push_back(
"-device");
173 Args.push_back(IPVersionsStr.c_str());
178 reinterpret_cast<decltype(::
oclocInvoke) *
>(oclocInvokeHandle);
180 OclocInvokeFunc(Args.size(), Args.data(), 1, Sources, SourceLengths,
181 &SourceName, 0,
nullptr,
nullptr,
nullptr, &NumOutputs,
182 &Outputs, &OutputLengths, &OutputNames);
186 std::string CompileLog;
187 for (uint32_t i = 0; i < NumOutputs; i++) {
188 size_t NameLen = strlen(OutputNames[i]);
189 if (NameLen >= 4 && strstr(OutputNames[i],
".spv") !=
nullptr &&
190 Outputs[i] !=
nullptr) {
191 assert(SpirV.size() == 0 &&
"More than one SPIR-V output found.");
192 SpirV =
spirv_vec_t(Outputs[i], Outputs[i] + OutputLengths[i]);
193 }
else if (!strcmp(OutputNames[i],
"stdout.log")) {
194 if (OutputLengths[i] > 0) {
195 const char *LogText =
reinterpret_cast<const char *
>(Outputs[i]);
196 CompileLog.append(LogText, OutputLengths[i]);
197 if (LogPtr !=
nullptr)
198 LogPtr->append(LogText, OutputLengths[i]);
205 reinterpret_cast<decltype(::
oclocFreeOutput) *
>(oclocFreeOutputHandle);
207 OclocFreeOutputFunc(&NumOutputs, &Outputs, &OutputLengths, &OutputNames);
210 throw sycl::exception(build_errc,
"ocloc reported compilation errors: {\n" +
215 "Unexpected output: ocloc did not return SPIR-V");
218 throw sycl::exception(build_errc,
"ocloc cannot safely free resources");
225 std::string QueryLog =
"";
228 static void *oclocInvokeHandle =
nullptr;
229 static void *oclocFreeOutputHandle =
nullptr;
232 SetupLibrary(oclocInvokeHandle, oclocFreeOutputHandle, the_errc);
234 uint32_t NumOutputs = 0;
235 uint8_t **Outputs =
nullptr;
236 uint64_t *OutputLengths =
nullptr;
237 char **OutputNames =
nullptr;
239 std::vector<const char *> Args = {
"ocloc",
"query"};
240 std::vector<uint32_t> IPVersionVec{IPVersion};
242 if (!IPVersionsStr.empty()) {
243 Args.push_back(
"-device");
244 Args.push_back(IPVersionsStr.c_str());
246 Args.push_back(identifier);
249 reinterpret_cast<decltype(::
oclocInvoke) *
>(oclocInvokeHandle);
251 int InvokeError = OclocInvokeFunc(
252 Args.size(), Args.data(), 0,
nullptr, 0,
nullptr, 0,
nullptr,
nullptr,
253 nullptr, &NumOutputs, &Outputs, &OutputLengths, &OutputNames);
256 for (uint32_t i = 0; i < NumOutputs; i++) {
257 if (!strcmp(OutputNames[i],
"stdout.log")) {
258 if (OutputLengths[i] > 0) {
259 const char *LogText =
reinterpret_cast<const char *
>(Outputs[i]);
260 QueryLog.append(LogText, OutputLengths[i]);
267 reinterpret_cast<decltype(::
oclocFreeOutput) *
>(oclocFreeOutputHandle);
269 OclocFreeOutputFunc(&NumOutputs, &Outputs, &OutputLengths, &OutputNames);
273 "ocloc reported errors: {\n" + QueryLog +
"\n}");
282 static std::string FeatureLog =
"";
283 if (FeatureLog.empty()) {
292 return (FeatureLog.find(Feature) != std::string::npos);
297 static std::string VersionLog =
"";
298 if (VersionLog.empty()) {
309 std::stringstream ss;
311 return VersionLog.find(ss.str()) != std::string::npos;
316 uint32_t IPVersion) {
318 static std::string ExtensionByVersionLog =
"";
319 if (ExtensionByVersionLog.empty()) {
321 ExtensionByVersionLog =
330 size_t where = ExtensionByVersionLog.find(Name);
331 if (
where == std::string::npos) {
335 size_t colon = ExtensionByVersionLog.find(
':',
where);
336 if (colon == std::string::npos) {
339 "trouble parsing query returned from CL_DEVICE_EXTENSIONS_WITH_VERSION "
340 "- extension not followed by colon (:)");
344 size_t space = ExtensionByVersionLog.find(
' ', colon);
346 size_t count = (space == std::string::npos) ? space : (space - colon);
348 std::string versionStr = ExtensionByVersionLog.substr(colon, count);
349 std::vector<std::string> versionVec =
351 if (versionVec.size() != 3) {
354 "trouble parsing query returned from "
355 "CL_DEVICE_EXTENSIONS_WITH_VERSION - version string unexpected: " +
359 VersionPtr->
major = std::stoi(versionVec[0]);
360 VersionPtr->
minor = std::stoi(versionVec[1]);
361 VersionPtr->
patch = std::stoi(versionVec[2]);
371 result.erase(std::remove_if(result.begin(), result.end(),
373 return !std::isprint(c) || std::isspace(c);
void * loadOsLibrary(const std::string &Library)
void * getOsLibraryFuncAddress(void *Library, const std::string &FunctionName)
std::vector< std::string > split_string(std::string_view str, char delimeter)
bool OpenCLC_Feature_Available(const std::string &Feature, uint32_t IPVersion)
std::string InvokeOclocQuery(uint32_t IPVersion, const char *identifier)
bool OpenCLC_Supports_Extension(const std::string &Name, ext::oneapi::experimental::cl_version *VersionPtr, uint32_t IPVersion)
spirv_vec_t OpenCLC_to_SPIRV(const std::string &Source, const std::vector< uint32_t > &IPVersionVec, const std::vector< std::string > &UserArgs, std::string *LogPtr)
bool OpenCLC_Compilation_Available()
std::vector< uint8_t > spirv_vec_t
std::string IPVersionsToString(const std::vector< uint32_t > IPVersionVec)
bool OpenCLC_Supports_Version(const ext::oneapi::experimental::cl_version &Version, uint32_t IPVersion)
void SetupLibrary(voidPtr &oclocInvokeHandle, voidPtr &oclocFreeOutputHandle, std::error_code the_errc)
void * loadOclocLibrary()
std::string OpenCLC_Profile(uint32_t IPVersion)
void checkOclocLibrary(void *OclocLibrary)
static void * OclocLibrary
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
SIGNATURE oclocVersion()
Returns the current version of ocloc.
SIGNATURE oclocInvoke(uint32_t NumArgs, const char *Argv[], uint32_t NumSources, const uint8_t **DataSources, const uint64_t *LenSources, const char **NameSources, uint32_t NumInputHeaders, const uint8_t **DataInputHeaders, const uint64_t *LenInputHeaders, const char **NameInputHeaders, uint32_t *NumOutputs, uint8_t ***DataOutputs, uint64_t **LenOutputs, char ***NameOutputs)
Invokes ocloc API using C interface.
@ OCLOC_VERSION_CURRENT
latest known version
@ OCLOC_VERSION_1_0
version 1.0
SIGNATURE oclocFreeOutput(uint32_t *NumOutputs, uint8_t ***DataOutputs, uint64_t **LenOutputs, char ***NameOutputs)
Frees results of oclocInvoke.
C++ wrapper of extern "C" PI interfaces.
where_expression< simd_mask< _Tp, _Abi >, simd< _Tp, _Abi > > where(const typename simd< _Tp, _Abi >::mask_type &, simd< _Tp, _Abi > &) noexcept