From 72141a4bcc1e7e59787940d022d93b8de1757fe2 Mon Sep 17 00:00:00 2001 From: Junyan He Date: Wed, 10 Sep 2014 15:39:41 +0800 Subject: [PATCH] Fix the issue of -cl-std=CLX.X option. The -cl-std= will specify the least version to compile the source code providing to our API. So we need to check it early, and return failure if our platform's version can not meet the request. In the backend, we just ignore this cmd line option. Signed-off-by: Junyan He Signed-off-by: Zhigang Gong --- backend/src/backend/program.cpp | 37 ++++++++++++++++++---- backend/src/libocl/tmpl/ocl_defines.tmpl.h | 3 +- src/cl_program.c | 50 +++++++++++++++++++++++++++++- 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp index 8c41d5e..b9dfc75 100644 --- a/backend/src/backend/program.cpp +++ b/backend/src/backend/program.cpp @@ -617,12 +617,15 @@ namespace gbe { SVAR(OCL_PCH_PATH, OCL_PCH_OBJECT); SVAR(OCL_HEADER_FILE_DIR, OCL_HEADER_DIR); - static void processSourceAndOption(const char *source, + static bool processSourceAndOption(const char *source, const char *options, const char *temp_header_path, std::vector& clOpt, std::string& clName, - int& optLevel) + int& optLevel, + size_t stringSize, + char *err, + size_t *errSize) { std::string dirs = OCL_PCH_PATH; std::istringstream idirs(dirs); @@ -646,6 +649,7 @@ namespace gbe { assert(findOcl); std::string includePath = "-I" + headerFilePath; clOpt.push_back(includePath); + bool useDefaultCLCVersion = true; if (options) { char *str = (char *)malloc(sizeof(char) * (strlen(options) + 1)); @@ -656,7 +660,6 @@ namespace gbe { const std::string uncompatiblePCHOptions = ("-cl-single-precision-constant, -cl-fast-relaxed-math"); const std::string fastMathOption = ("-cl-fast-relaxed-math"); - while (end != std::string::npos) { end = optionStr.find(' ', start); std::string str = optionStr.substr(start, end - start); @@ -664,8 +667,23 @@ namespace gbe { if(str.size() == 0) continue; - if(unsupportedOptions.find(str) != std::string::npos) + if(unsupportedOptions.find(str) != std::string::npos) { + continue; + } + + if(str.find("-cl-std=") != std::string::npos) { + useDefaultCLCVersion = false; + if (str == "-cl-std=CL1.1") + clOpt.push_back("-D__OPENCL_C_VERSION__=110"); + else if (str == "-cl-std=CL1.2") + clOpt.push_back("-D__OPENCL_C_VERSION__=120"); + else { + if (err && stringSize > 0 && errSize) + *errSize = snprintf(err, stringSize, "Invalid build option: %s\n", str.c_str()); + return false; + } continue; + } if (uncompatiblePCHOptions.find(str) != std::string::npos) invalidPCH = true; @@ -680,6 +698,8 @@ namespace gbe { free(str); } + if (useDefaultCLCVersion) + clOpt.push_back("-D__OPENCL_C_VERSION__=120"); //for clCompilerProgram usage. if(temp_header_path){ clOpt.push_back("-I"); @@ -712,6 +732,7 @@ namespace gbe { // Write the source to the cl file fwrite(source, strlen(source), 1, clFile); fclose(clFile); + return true; } static gbe_program programNewFromSource(uint32_t deviceID, @@ -724,7 +745,9 @@ namespace gbe { int optLevel = 1; std::vector clOpt; std::string clName; - processSourceAndOption(source, options, NULL, clOpt, clName, optLevel); + if (!processSourceAndOption(source, options, NULL, clOpt, clName, + optLevel, stringSize, err, errSize)) + return NULL; gbe_program p; // will delete the module and act in GenProgram::CleanLlvmResource(). @@ -775,7 +798,9 @@ namespace gbe { int optLevel = 1; std::vector clOpt; std::string clName; - processSourceAndOption(source, options, temp_header_path, clOpt, clName, optLevel); + if (!processSourceAndOption(source, options, temp_header_path, clOpt, clName, + optLevel, stringSize, err, errSize)) + return NULL; gbe_program p; acquireLLVMContextLock(); diff --git a/backend/src/libocl/tmpl/ocl_defines.tmpl.h b/backend/src/libocl/tmpl/ocl_defines.tmpl.h index 4548faf..446691c 100644 --- a/backend/src/libocl/tmpl/ocl_defines.tmpl.h +++ b/backend/src/libocl/tmpl/ocl_defines.tmpl.h @@ -18,9 +18,10 @@ #ifndef __OCL_COMMON_DEF_H__ #define __OCL_COMMON_DEF_H__ -#define __OPENCL_VERSION__ 110 +#define __OPENCL_VERSION__ 120 #define __CL_VERSION_1_0__ 100 #define __CL_VERSION_1_1__ 110 +#define __CL_VERSION_1_2__ 120 #define __ENDIAN_LITTLE__ 1 #define __IMAGE_SUPPORT__ 1 #define __kernel_exec(X, TYPE) __kernel __attribute__((work_group_size_hint(X,1,1))) \ diff --git a/src/cl_program.c b/src/cl_program.c index a745c00..3ecc49f 100644 --- a/src/cl_program.c +++ b/src/cl_program.c @@ -424,6 +424,43 @@ error: goto exit; } +/* Before we do the real work, we need to check whether our platform + cl version can meet -cl-std= */ +static int check_cl_version_option(cl_program p, const char* options) { + const char* s = NULL; + int ver1 = 0; + int ver2 = 0; + char version_str[64]; + + if (options && (s = strstr(options, "-cl-std="))) { + + if (s + strlen("-cl-std=CLX.X") > options + strlen(options)) { + return 0; + } + + if (s[8] != 'C' || s[9] != 'L' || s[10] > '9' || s[10] < '0' || s[11] != '.' + || s[12] > '9' || s[12] < '0') { + return 0; + } + + ver1 = (s[10] - '0') * 10 + (s[12] - '0'); + + if (cl_get_device_info(p->ctx->device, CL_DEVICE_OPENCL_C_VERSION, sizeof(version_str), + version_str, NULL) != CL_SUCCESS) + return 0; + + assert(strstr(version_str, "OpenCL") && version_str[0] == 'O'); + ver2 = (version_str[9] - '0') * 10 + (version_str[11] - '0'); + + if (ver2 < ver1) + return 0; + + return 1; + } + + return 1; +} + LOCAL cl_int cl_program_build(cl_program p, const char *options) { @@ -434,6 +471,9 @@ cl_program_build(cl_program p, const char *options) if (p->ref_n > 1) return CL_INVALID_OPERATION; + if (!check_cl_version_option(p, options)) + return CL_BUILD_PROGRAM_FAILURE; + if (options) { if(p->build_opts == NULL || strcmp(options, p->build_opts) != 0) { if(p->build_opts) { @@ -526,11 +566,16 @@ cl_program_link(cl_context context, cl_int* errcode_ret) { cl_program p = NULL; - cl_int err=CL_SUCCESS; + cl_int err = CL_SUCCESS; cl_int i = 0; int copyed = 0; p = cl_program_new(context); + if (!check_cl_version_option(p, options)) { + err = CL_BUILD_PROGRAM_FAILURE; + goto error; + } + p->opaque = compiler_program_new_gen_program(context->device->vendor_id, NULL, NULL); for(i = 0; i < num_input_programs; i++) { @@ -588,6 +633,9 @@ cl_program_compile(cl_program p, if (p->ref_n > 1) return CL_INVALID_OPERATION; + if (!check_cl_version_option(p, options)) + return CL_BUILD_PROGRAM_FAILURE; + if (options) { if(p->build_opts == NULL || strcmp(options, p->build_opts) != 0) { if(p->build_opts) { -- 2.7.4