diff options
author | Aaron Watry <[email protected]> | 2017-07-21 21:43:38 -0500 |
---|---|---|
committer | Aaron Watry <[email protected]> | 2018-03-21 06:59:37 -0500 |
commit | 29b4090d18fa3e7435450e30383d0416e536a425 (patch) | |
tree | e6084714c5adcc5c7b096e84c7d1939590f88182 | |
parent | 14fffefc60482fe84cffcd00a44a4c8b7e0d5a36 (diff) |
clover/llvm: Add get_[cl|language]_version, validation and some helpers
Used to calculate the default CLC language version based on the --cl-std in build args
and the device capabilities.
According to section 5.8.4.5 of the 2.0 spec, the CL C version is chosen by:
1) If you have -cl-std=CL1.1+ use the version specified
2) If not, use the highest 1.x version that the device supports
Curiously, there is no valid value for -cl-std=CL1.0
Validates requested cl-std against device_clc_version
Signed-off-by: Aaron Watry <[email protected]>
Reviewed-by: Pierre Moreau <[email protected]>
v7: (Pierre) Split cl/clc versions into separate lists and
make more references const.
v6: (Pierre) Add more const and fix some whitespace
v5: (Aaron) Use a collection of cl versions instead of switch cases
Consolidates the string, numeric version, and clc langstandard::kind
v4: (Pierre) Split get_language_version addition and use into separate patches
Squash patches that add the helpers and validate the language standard
v3: Change device_version to device_clc_version
v2: (Pierre) Move create_compiler_instance changes to correct patch
to prevent temporary build breakage.
Convert version_str into unsigned and use it to find language version
Add build_error for unknown language version string
Whitespace fixes
-rw-r--r-- | src/gallium/state_trackers/clover/llvm/invocation.cpp | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp index 0bc0cccc6e7..a485380a036 100644 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp @@ -63,6 +63,34 @@ using ::llvm::Module; using ::llvm::raw_string_ostream; namespace { + + struct cl_version { + std::string version_str; // CL Version + unsigned version_number; // Numeric CL Version + }; + + static const unsigned ANY_VERSION = 999; + const cl_version cl_versions[] = { + { "1.0", 100}, + { "1.1", 110}, + { "1.2", 120}, + { "2.0", 200}, + { "2.1", 210}, + { "2.2", 220}, + }; + + struct clc_version_lang_std { + unsigned version_number; // CLC Version + clang::LangStandard::Kind clc_lang_standard; + }; + + const clc_version_lang_std cl_version_lang_stds[] = { + { 100, clang::LangStandard::lang_opencl10}, + { 110, clang::LangStandard::lang_opencl11}, + { 120, clang::LangStandard::lang_opencl12}, + { 200, clang::LangStandard::lang_opencl20}, + }; + void init_targets() { static bool targets_initialized = false; @@ -93,6 +121,66 @@ namespace { return ctx; } + const struct clc_version_lang_std& + get_cl_lang_standard(unsigned requested, unsigned max = ANY_VERSION) { + for (const struct clc_version_lang_std &version : cl_version_lang_stds) { + if (version.version_number == max || + version.version_number == requested) { + return version; + } + } + throw build_error("Unknown/Unsupported language version"); + } + + const struct cl_version& + get_cl_version(const std::string &version_str, + unsigned max = ANY_VERSION) { + for (const struct cl_version &version : cl_versions) { + if (version.version_number == max || version.version_str == version_str) { + return version; + } + } + throw build_error("Unknown/Unsupported language version"); + } + + clang::LangStandard::Kind + get_lang_standard_from_version_str(const std::string &version_str, + bool is_build_opt = false) { + + //Per CL 2.0 spec, section 5.8.4.5: + // If it's an option, use the value directly. + // If it's a device version, clamp to max 1.x version, a.k.a. 1.2 + const cl_version version = + get_cl_version(version_str, is_build_opt ? ANY_VERSION : 120); + + const struct clc_version_lang_std standard = + get_cl_lang_standard(version.version_number); + + return standard.clc_lang_standard; + } + + clang::LangStandard::Kind + get_language_version(const std::vector<std::string> &opts, + const std::string &device_version) { + + const std::string search = "-cl-std=CL"; + + for (auto &opt: opts) { + auto pos = opt.find(search); + if (pos == 0){ + const auto ver = opt.substr(pos + search.size()); + const auto device_ver = get_cl_version(device_version); + const auto requested = get_cl_version(ver); + if (requested.version_number > device_ver.version_number) { + throw build_error(); + } + return get_lang_standard_from_version_str(ver, true); + } + } + + return get_lang_standard_from_version_str(device_version); + } + std::unique_ptr<clang::CompilerInstance> create_compiler_instance(const device &dev, const std::vector<std::string> &opts, |