clover: implements clGetKernelArgInfo

Reviewed-by: Francisco Jerez <currojerez@riseup.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4974>
This commit is contained in:
Serge Martin 2020-05-09 23:13:48 +02:00 committed by Marge Bot
parent d7d66e30f2
commit 9aea6e3374
6 changed files with 154 additions and 12 deletions

View file

@ -192,9 +192,46 @@ clGetKernelWorkGroupInfo(cl_kernel d_kern, cl_device_id d_dev,
CLOVER_API cl_int
clGetKernelArgInfo(cl_kernel d_kern,
cl_uint idx, cl_kernel_arg_info param,
size_t size, void *r_buf, size_t *r_size) {
CLOVER_NOT_SUPPORTED_UNTIL("1.2");
return CL_KERNEL_ARG_INFO_NOT_AVAILABLE;
size_t size, void *r_buf, size_t *r_size) try {
property_buffer buf { r_buf, size, r_size };
auto info = obj(d_kern).args_infos().at(idx);
if (info.arg_name.empty())
return CL_KERNEL_ARG_INFO_NOT_AVAILABLE;
switch (param) {
case CL_KERNEL_ARG_ADDRESS_QUALIFIER:
buf.as_scalar<cl_kernel_arg_address_qualifier>() = info.address_qualifier;
break;
case CL_KERNEL_ARG_ACCESS_QUALIFIER:
buf.as_scalar<cl_kernel_arg_access_qualifier>() = info.access_qualifier;
break;
case CL_KERNEL_ARG_TYPE_NAME:
buf.as_string() = info.type_name;
break;
case CL_KERNEL_ARG_TYPE_QUALIFIER:
buf.as_scalar<cl_kernel_arg_type_qualifier>() = info.type_qualifier;
break;
case CL_KERNEL_ARG_NAME:
buf.as_string() = info.arg_name;
break;
default:
throw error(CL_INVALID_VALUE);
}
return CL_SUCCESS;
} catch (std::out_of_range &e) {
return CL_INVALID_ARG_INDEX;
} catch (error &e) {
return e.get();
}
namespace {

View file

@ -153,6 +153,16 @@ kernel::args() const {
return map(derefs(), _args);
}
std::vector<clover::module::arg_info>
kernel::args_infos() {
std::vector<clover::module::arg_info> infos;
for (auto &marg: find(name_equals(_name), program().symbols()).args)
if (marg.semantic == clover::module::argument::general)
infos.emplace_back(marg.info);
return infos;
}
const module &
kernel::module(const command_queue &q) const {
return program().build(q.device()).binary;

View file

@ -141,6 +141,7 @@ namespace clover {
argument_range args();
const_argument_range args() const;
std::vector<clover::module::arg_info> args_infos();
const intrusive_ref<clover::program> program;

View file

@ -26,6 +26,8 @@
#include <vector>
#include <string>
#include "CL/cl.h"
namespace clover {
struct module {
typedef uint32_t resource_id;
@ -53,6 +55,25 @@ namespace clover {
std::vector<char> data;
};
struct arg_info {
arg_info(const std::string &arg_name, const std::string &type_name,
const cl_kernel_arg_type_qualifier type_qualifier,
const cl_kernel_arg_address_qualifier address_qualifier,
const cl_kernel_arg_access_qualifier access_qualifier) :
arg_name(arg_name), type_name(type_name),
type_qualifier(type_qualifier),
address_qualifier(address_qualifier),
access_qualifier(access_qualifier) { };
arg_info() : arg_name(""), type_name(""), type_qualifier(0),
address_qualifier(0), access_qualifier(0) { };
std::string arg_name;
std::string type_name;
cl_kernel_arg_type_qualifier type_qualifier;
cl_kernel_arg_address_qualifier address_qualifier;
cl_kernel_arg_access_qualifier access_qualifier;
};
struct argument {
enum type {
scalar,
@ -103,6 +124,7 @@ namespace clover {
size_t target_align;
ext_type ext_type;
semantic semantic;
arg_info info;
};
struct symbol {

View file

@ -66,6 +66,43 @@ namespace {
unreachable("Unknown image type");
}
module::arg_info create_arg_info(const std::string &arg_name,
const std::string &type_name,
const std::string &type_qualifier,
const int address_qualifier,
const std::string &access_qualifier) {
cl_kernel_arg_type_qualifier cl_type_qualifier =
CL_KERNEL_ARG_TYPE_NONE;
if (type_qualifier.find("const") != std::string::npos)
cl_type_qualifier |= CL_KERNEL_ARG_TYPE_CONST;
if (type_qualifier.find("restrict") != std::string::npos)
cl_type_qualifier |= CL_KERNEL_ARG_TYPE_RESTRICT;
if (type_qualifier.find("volatile") != std::string::npos)
cl_type_qualifier |= CL_KERNEL_ARG_TYPE_VOLATILE;
cl_kernel_arg_address_qualifier cl_address_qualifier =
CL_KERNEL_ARG_ADDRESS_PRIVATE;
if (address_qualifier == 1)
cl_address_qualifier = CL_KERNEL_ARG_ADDRESS_GLOBAL;
else if (address_qualifier == 2)
cl_address_qualifier = CL_KERNEL_ARG_ADDRESS_CONSTANT;
else if (address_qualifier == 3)
cl_address_qualifier = CL_KERNEL_ARG_ADDRESS_LOCAL;
cl_kernel_arg_access_qualifier cl_access_qualifier =
CL_KERNEL_ARG_ACCESS_NONE;
if (access_qualifier == "read_only")
cl_access_qualifier = CL_KERNEL_ARG_ACCESS_READ_ONLY;
else if (access_qualifier == "write_only")
cl_access_qualifier = CL_KERNEL_ARG_ACCESS_WRITE_ONLY;
else if (access_qualifier == "read_write")
cl_access_qualifier = CL_KERNEL_ARG_ACCESS_READ_WRITE;
return module::arg_info(arg_name, type_name, cl_type_qualifier,
cl_address_qualifier, cl_access_qualifier);
}
std::vector<module::argument>
make_kernel_args(const Module &mod, const std::string &kernel_name,
const clang::CompilerInstance &c) {
@ -87,12 +124,11 @@ namespace {
const unsigned target_size = dl.getTypeStoreSize(arg_type);
const unsigned target_align = dl.getABITypeAlignment(arg_type);
const auto type_name = get_argument_metadata(f, arg,
"kernel_arg_type");
const auto type_name = get_str_argument_metadata(f, arg,
"kernel_arg_type");
if (type_name == "image2d_t" || type_name == "image3d_t") {
// Image.
const auto access_qual = get_argument_metadata(
const auto access_qual = get_str_argument_metadata(
f, arg, "kernel_arg_access_qual");
args.emplace_back(get_image_type(type_name, access_qual),
target_size, target_size,
@ -153,6 +189,16 @@ namespace {
(needs_sign_ext ? module::argument::sign_ext :
module::argument::zero_ext));
}
// Add kernel argument infos if built with -cl-kernel-arg-info.
if (c.getCodeGenOpts().EmitOpenCLArgMetadata) {
args.back().info = create_arg_info(
get_str_argument_metadata(f, arg, "kernel_arg_name"),
type_name,
get_str_argument_metadata(f, arg, "kernel_arg_type_qual"),
get_uint_argument_metadata(f, arg, "kernel_arg_addr_space"),
get_str_argument_metadata(f, arg, "kernel_arg_access_qual"));
}
}
}

View file

@ -48,7 +48,10 @@ namespace clover {
get_kernel_metadata_operands(const ::llvm::Function &f,
const std::string &name) {
const auto data_node = f.getMetadata(name);
return range(data_node->op_begin(), data_node->op_end());
if (data_node)
return range(data_node->op_begin(), data_node->op_end());
else
return iterator_range< ::llvm::MDNode::op_iterator>();
}
}
@ -57,12 +60,35 @@ namespace clover {
/// argument given by \p arg.
///
inline std::string
get_argument_metadata(const ::llvm::Function &f,
get_str_argument_metadata(const ::llvm::Function &f,
const ::llvm::Argument &arg,
const std::string &name) {
return ::llvm::cast< ::llvm::MDString>(
detail::get_kernel_metadata_operands(f, name)[arg.getArgNo()])
->getString().str();
auto operands = detail::get_kernel_metadata_operands(f, name);
if (operands.size() > arg.getArgNo()) {
return ::llvm::cast< ::llvm::MDString>(operands[arg.getArgNo()])
->getString().str();
} else {
return "";
}
}
///
/// Extract the int metadata node \p name corresponding to the kernel
/// argument given by \p arg.
///
inline uint
get_uint_argument_metadata(const ::llvm::Function &f,
const ::llvm::Argument &arg,
const std::string &name) {
auto operands = detail::get_kernel_metadata_operands(f, name);
if (operands.size() >= arg.getArgNo()) {
auto meta_arg_value = ::llvm::cast< ::llvm::ConstantAsMetadata>(
operands[arg.getArgNo()])->getValue();
return ::llvm::cast< ::llvm::ConstantInt>(meta_arg_value)
->getLimitedValue(UINT_MAX);
} else {
return 0;
}
}
///