clover: add CL_KERNEL_ATTRIBUTES for clGetKernelInfo
Reviewed-by: Francisco Jerez <currojerez@riseup.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4974>
This commit is contained in:
@@ -134,6 +134,10 @@ clGetKernelInfo(cl_kernel d_kern, cl_kernel_info param,
|
||||
buf.as_scalar<cl_program>() = desc(kern.program());
|
||||
break;
|
||||
|
||||
case CL_KERNEL_ATTRIBUTES:
|
||||
buf.as_string() = find(name_equals(kern.name()), kern.program().symbols()).attributes;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
@@ -190,6 +190,7 @@ namespace {
|
||||
static void
|
||||
proc(S &s, QT &x) {
|
||||
_proc(s, x.name);
|
||||
_proc(s, x.attributes);
|
||||
_proc(s, x.section);
|
||||
_proc(s, x.offset);
|
||||
_proc(s, x.args);
|
||||
|
@@ -128,12 +128,16 @@ namespace clover {
|
||||
};
|
||||
|
||||
struct symbol {
|
||||
symbol(const std::string &name, resource_id section,
|
||||
size_t offset, const std::vector<argument> &args) :
|
||||
name(name), section(section), offset(offset), args(args) { }
|
||||
symbol() : name(), section(0), offset(0), args() { }
|
||||
symbol(const std::string &name, const std::string &attributes,
|
||||
resource_id section, size_t offset,
|
||||
const std::vector<argument> &args) :
|
||||
name(name), attributes(attributes),
|
||||
section(section),
|
||||
offset(offset), args(args) { }
|
||||
symbol() : name(), attributes(), section(0), offset(0), args() { }
|
||||
|
||||
std::string name;
|
||||
std::string attributes;
|
||||
resource_id section;
|
||||
size_t offset;
|
||||
std::vector<argument> args;
|
||||
|
@@ -103,6 +103,39 @@ namespace {
|
||||
cl_address_qualifier, cl_access_qualifier);
|
||||
}
|
||||
|
||||
std::string
|
||||
kernel_attributes(const Module &mod, const std::string &kernel_name) {
|
||||
std::vector<std::string> attributes;
|
||||
|
||||
const Function &f = *mod.getFunction(kernel_name);
|
||||
|
||||
auto vec_type_hint = get_type_kernel_metadata(f, "vec_type_hint");
|
||||
if (!vec_type_hint.empty())
|
||||
attributes.emplace_back("vec_type_hint(" + vec_type_hint + ")");
|
||||
|
||||
auto work_group_size_hint = get_uint_vector_kernel_metadata(f, "work_group_size_hint");
|
||||
if (!work_group_size_hint.empty()) {
|
||||
std::string s = "work_group_size_hint(";
|
||||
s += detokenize(work_group_size_hint, ",");
|
||||
s += ")";
|
||||
attributes.emplace_back(s);
|
||||
}
|
||||
|
||||
auto reqd_work_group_size = get_uint_vector_kernel_metadata(f, "reqd_work_group_size");
|
||||
if (!reqd_work_group_size.empty()) {
|
||||
std::string s = "reqd_work_group_size(";
|
||||
s += detokenize(reqd_work_group_size, ",");
|
||||
s += ")";
|
||||
attributes.emplace_back(s);
|
||||
}
|
||||
|
||||
auto nosvm = get_str_kernel_metadata(f, "nosvm");
|
||||
if (!nosvm.empty())
|
||||
attributes.emplace_back("nosvm");
|
||||
|
||||
return detokenize(attributes, " ");
|
||||
}
|
||||
|
||||
std::vector<module::argument>
|
||||
make_kernel_args(const Module &mod, const std::string &kernel_name,
|
||||
const clang::CompilerInstance &c) {
|
||||
@@ -251,7 +284,8 @@ clover::llvm::build_module_common(const Module &mod,
|
||||
get_kernels(mod))) {
|
||||
const ::std::string name(llvm_name);
|
||||
if (offsets.count(name))
|
||||
m.syms.emplace_back(name, 0, offsets.at(name),
|
||||
m.syms.emplace_back(name, kernel_attributes(mod, name),
|
||||
0, offsets.at(name),
|
||||
make_kernel_args(mod, name, c));
|
||||
}
|
||||
|
||||
|
@@ -55,6 +55,94 @@ namespace clover {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Extract the string metadata node \p name.
|
||||
///
|
||||
inline std::string
|
||||
get_str_kernel_metadata(const ::llvm::Function &f,
|
||||
const std::string &name) {
|
||||
auto operands = detail::get_kernel_metadata_operands(f, name);
|
||||
if (operands.size()) {
|
||||
return ::llvm::cast< ::llvm::MDString>(
|
||||
detail::get_kernel_metadata_operands(f, name)[0])
|
||||
->getString().str();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Extract the string metadata node \p name.
|
||||
///
|
||||
inline std::vector<size_t>
|
||||
get_uint_vector_kernel_metadata(const ::llvm::Function &f,
|
||||
const std::string &name) {
|
||||
auto operands = detail::get_kernel_metadata_operands(f, name);
|
||||
if (operands.size()) {
|
||||
return map([=](const ::llvm::MDOperand& o) {
|
||||
auto value = ::llvm::cast< ::llvm::ConstantAsMetadata>(o)
|
||||
->getValue();
|
||||
return ::llvm::cast< ::llvm::ConstantInt>(value)
|
||||
->getLimitedValue(UINT_MAX);
|
||||
}, operands);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Extract the string metadata node \p name.
|
||||
///
|
||||
inline std::string
|
||||
get_type_kernel_metadata(const ::llvm::Function &f,
|
||||
const std::string &name) {
|
||||
auto operands = detail::get_kernel_metadata_operands(f, name);
|
||||
if (operands.size()) {
|
||||
auto value = ::llvm::cast< ::llvm::ConstantAsMetadata>(operands[0])
|
||||
->getValue();
|
||||
auto type = ::llvm::cast< ::llvm::UndefValue>(value)
|
||||
->getType();
|
||||
|
||||
value = ::llvm::cast< ::llvm::ConstantAsMetadata>(operands[1])
|
||||
->getValue();
|
||||
bool is_signed = ::llvm::cast< ::llvm::ConstantInt>(value)
|
||||
->getLimitedValue(UINT_MAX);
|
||||
|
||||
std::string data;
|
||||
if (type->isIntOrIntVectorTy()) {
|
||||
if (!is_signed)
|
||||
data = "unsigned ";
|
||||
|
||||
const auto size = type->getScalarSizeInBits();
|
||||
switch(size) {
|
||||
case 8:
|
||||
data += "char";
|
||||
break;
|
||||
case 16:
|
||||
data += "short";
|
||||
break;
|
||||
case 32:
|
||||
data += "int";
|
||||
break;
|
||||
case 64:
|
||||
data += "long";
|
||||
break;
|
||||
}
|
||||
if (type->isVectorTy())
|
||||
data += std::to_string(((::llvm::VectorType*)type)->getNumElements());
|
||||
|
||||
} else {
|
||||
::llvm::raw_string_ostream os { data };
|
||||
type->print(os);
|
||||
os.flush();
|
||||
}
|
||||
|
||||
return data;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Extract the string metadata node \p name corresponding to the kernel
|
||||
/// argument given by \p arg.
|
||||
|
@@ -390,7 +390,7 @@ module clover::nir::spirv_to_nir(const module &mod, const device &dev,
|
||||
reinterpret_cast<const char *>(&header) + sizeof(header));
|
||||
text.data.insert(text.data.end(), blob.data, blob.data + blob.size);
|
||||
|
||||
m.syms.emplace_back(sym.name, section_id, 0, args);
|
||||
m.syms.emplace_back(sym.name, std::string(), section_id, 0, args);
|
||||
m.secs.push_back(text);
|
||||
section_id++;
|
||||
}
|
||||
|
@@ -346,7 +346,7 @@ namespace {
|
||||
case SpvOpFunctionEnd:
|
||||
if (kernel_name.empty())
|
||||
break;
|
||||
m.syms.emplace_back(kernel_name, 0, kernel_nb, args);
|
||||
m.syms.emplace_back(kernel_name, std::string(), 0, kernel_nb, args);
|
||||
++kernel_nb;
|
||||
kernel_name.clear();
|
||||
args.clear();
|
||||
|
@@ -213,6 +213,34 @@ namespace clover {
|
||||
|
||||
r.erase(i, e);
|
||||
}
|
||||
|
||||
///
|
||||
/// Build a \a sep separated string from a vector of T
|
||||
///
|
||||
template<typename T>
|
||||
std::string
|
||||
detokenize(const std::vector<T> &ss, const std::string &sep) {
|
||||
std::string r;
|
||||
|
||||
for (const auto &s : ss)
|
||||
r += (r.empty() ? "" : sep) + std::to_string(s);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
///
|
||||
/// Build a \a sep separated string from a vector of string
|
||||
///
|
||||
template <>
|
||||
inline std::string
|
||||
detokenize(const std::vector<std::string> &ss, const std::string &sep) {
|
||||
std::string r;
|
||||
|
||||
for (const auto &s : ss)
|
||||
r += (r.empty() || s.empty() ? "" : sep) + s;
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user