clover/llvm: don't use strings for version handling.

This is extracted from Pierre's WIP versioning patch.

Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7520>
This commit is contained in:
Pierre Moreau
2020-11-10 11:39:08 +10:00
committed by Dave Airlie
parent b8a96199cb
commit 330c524762
@@ -70,37 +70,41 @@ 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;
static const cl_version ANY_VERSION = CL_MAKE_VERSION(9, 9, 9);
const cl_version cl_versions[] = {
{ "1.0", 100},
{ "1.1", 110},
{ "1.2", 120},
{ "2.0", 200},
{ "2.1", 210},
{ "2.2", 220},
{ "3.0", 300},
CL_MAKE_VERSION(1, 1, 0),
CL_MAKE_VERSION(1, 2, 0),
CL_MAKE_VERSION(2, 0, 0),
CL_MAKE_VERSION(2, 1, 0),
CL_MAKE_VERSION(2, 2, 0),
CL_MAKE_VERSION(3, 0, 0),
};
struct clc_version_lang_std {
unsigned version_number; // CLC Version
cl_version 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},
{ CL_MAKE_VERSION(1, 0, 0), clang::LangStandard::lang_opencl10},
{ CL_MAKE_VERSION(1, 1, 0), clang::LangStandard::lang_opencl11},
{ CL_MAKE_VERSION(1, 2, 0), clang::LangStandard::lang_opencl12},
{ CL_MAKE_VERSION(2, 0, 0), clang::LangStandard::lang_opencl20},
#if LLVM_VERSION_MAJOR >= 12
{ 300, clang::LangStandard::lang_opencl30},
{ CL_MAKE_VERSION(3, 0, 0), clang::LangStandard::lang_opencl30},
#endif
};
bool
are_equal(cl_version_khr version1, cl_version_khr version2,
bool ignore_patch_version = false) {
if (ignore_patch_version) {
version1 &= ~CL_VERSION_PATCH_MASK_KHR;
version2 &= ~CL_VERSION_PATCH_MASK_KHR;
}
return version1 == version2;
}
void
init_targets() {
static bool targets_initialized = false;
@@ -144,11 +148,12 @@ namespace {
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) {
const cl_version
get_cl_version(cl_version requested,
cl_version max = ANY_VERSION) {
for (const auto &version : cl_versions) {
if (are_equal(version, max, true) ||
are_equal(version, requested, true)) {
return version;
}
}
@@ -156,41 +161,50 @@ namespace {
}
clang::LangStandard::Kind
get_lang_standard_from_version_str(const std::string &version_str,
bool is_build_opt = false) {
get_lang_standard_from_version(const cl_version input_version,
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);
get_cl_version(input_version, is_build_opt ? ANY_VERSION : 120);
const struct clc_version_lang_std standard =
get_cl_lang_standard(version.version_number);
get_cl_lang_standard(version);
return standard.clc_lang_standard;
}
clang::LangStandard::Kind
get_language_version(const std::vector<std::string> &opts,
const std::string &device_version) {
const cl_version 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) {
std::stringstream ver_str(opt.substr(pos + search.size()));
unsigned int ver_major = 0;
char separator = '\0';
unsigned int ver_minor = 0;
ver_str >> ver_major >> separator >> ver_minor;
if (ver_str.fail() || ver_str.bad() || !ver_str.eof() ||
separator != '.') {
throw build_error();
}
return get_lang_standard_from_version_str(ver, true);
const auto ver = CL_MAKE_VERSION_KHR(ver_major, ver_minor, 0);
const auto device_ver = get_cl_version(device_version);
const auto requested = get_cl_version(ver);
if (requested > device_ver) {
throw build_error();
}
return get_lang_standard_from_version(ver, true);
}
}
return get_lang_standard_from_version_str(device_version);
return get_lang_standard_from_version(device_version);
}
std::unique_ptr<clang::CompilerInstance>
@@ -209,7 +223,7 @@ namespace {
map(std::mem_fn(&std::string::c_str), opts);
const target &target = ir_target;
const std::string &device_clc_version = dev.device_clc_version_as_string();
const cl_version device_clc_version = dev.device_clc_version();
if (!compat::create_compiler_invocation_from_args(
c->getInvocation(), copts, diag))
@@ -272,9 +286,10 @@ namespace {
}
// Add definition for the OpenCL version
const auto dev_version = dev.device_version();
c.getPreprocessorOpts().addMacroDef("__OPENCL_VERSION__=" +
std::to_string(get_cl_version(
dev.device_version_as_string()).version_number));
std::to_string(CL_VERSION_MAJOR_KHR(dev_version)) +
std::to_string(CL_VERSION_MINOR_KHR(dev_version)) + "0");
// clc.h requires that this macro be defined:
c.getPreprocessorOpts().addMacroDef("cl_clang_storage_class_specifiers");