From 8af7a06089d4536625a8de6dbf313c2df25519a4 Mon Sep 17 00:00:00 2001 From: Diego Lopez Recas Date: Thu, 24 Apr 2025 13:48:34 +0000 Subject: [PATCH] Fix clc device selection on multi-device platform If a platform reports multiple devices, they will all have the same name and --device selection will be ambiguous. This adds a --device-idx cmd-line option to directly select by index. --- modules/cargo/include/cargo/argument_parser.h | 2 +- source/cl/tools/clc/clc.cpp | 88 +++++++++++++------ source/cl/tools/clc/clc.h | 3 + 3 files changed, 64 insertions(+), 29 deletions(-) diff --git a/modules/cargo/include/cargo/argument_parser.h b/modules/cargo/include/cargo/argument_parser.h index 2b2b4cc2c3..f5123bd83e 100644 --- a/modules/cargo/include/cargo/argument_parser.h +++ b/modules/cargo/include/cargo/argument_parser.h @@ -219,7 +219,7 @@ class argument { cargo::array_view Choices; }; union { - bool *Bool; + bool *Bool = {}; cargo::string_view *Value; ChoiceT Choice; cargo::small_vector *Values; diff --git a/source/cl/tools/clc/clc.cpp b/source/cl/tools/clc/clc.cpp index b717a71747..1136c57521 100644 --- a/source/cl/tools/clc/clc.cpp +++ b/source/cl/tools/clc/clc.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -152,6 +153,7 @@ driver::driver() dry_run(false), input_file(), output_file(""), + device_idx(0), device_name_substring(""), cl_build_args(), strip_binary_header(false), @@ -185,6 +187,9 @@ optional arguments: output file path, defaults to the name of the last input file ".bin" if present, or "-" otherwise to write to standard output + --device-idx index + the index (1..N) of the device to select. Takes precedence + over --device -d name, --device name a substring of the device name to select, choose from:%s --list-devices print the list of available devices and exit @@ -275,6 +280,19 @@ result driver::parseArguments(int argc, char **argv) { CHECK(parser.add_argument({"-o", output_file})); CHECK(parser.add_argument({"--output", output_file})); + CHECK(parser.add_argument({ + "--device-idx", + [](auto &&...) { return parse::INCOMPLETE; }, + [this](cargo::string_view str_value) { + auto [ptr, ec] = + std::from_chars(str_value.begin(), str_value.end(), device_idx); + if ((ptr != str_value.end()) || (device_idx == 0)) { + return parse::INVALID; + } + return parse::COMPLETE; + }, + })); + CHECK(parser.add_argument({"-d", device_name_substring})); CHECK(parser.add_argument({"--device", device_name_substring})); @@ -743,38 +761,52 @@ result driver::findDevice() { return result::failure; } - if (compilers.size() > 1 && device_name_substring.empty()) { - (void)std::fprintf(stderr, - "error: Multiple devices available, please choose one " - "(--device NAME):\n"); - printMuxCompilers(compilers); - return result::failure; - } + if (device_idx != 0) { + if (device_idx > compilers.size()) { + (void)std::fprintf(stderr, + "error: Invalid device selection; out of bounds. " + "Available devices:\n"); + printMuxCompilers(compilers); + return result::failure; + } + + compiler_info = compilers[device_idx - 1]; - bool found = false; - for (auto compiler : compilers) { - bool matches = true; - if (!device_name_substring.empty()) { - matches &= matchSubstring(compiler->device_info->device_name, - device_name_substring); + } else { + if (compilers.size() > 1 && device_name_substring.empty()) { + (void)std::fprintf(stderr, + "error: Multiple devices available, please choose one " + "(--device NAME | --device-idx INDEX):\n"); + printMuxCompilers(compilers); + return result::failure; } - if (matches) { - if (found) { - (void)std::fprintf( - stderr, "error: Device selection ambiguous, available devices:\n"); - printMuxCompilers(compilers); - return result::failure; + + bool found = false; + for (auto compiler : compilers) { + bool matches = true; + if (!device_name_substring.empty()) { + matches &= matchSubstring(compiler->device_info->device_name, + device_name_substring); + } + if (matches) { + if (found) { + (void)std::fprintf( + stderr, + "error: Device selection ambiguous, available devices:\n"); + printMuxCompilers(compilers); + return result::failure; + } + found = true; + compiler_info = compiler; } - found = true; - compiler_info = compiler; } - } - if (!found) { - (void)std::fprintf( - stderr, - "error: No device matched the given substring, available devices:\n"); - printMuxCompilers(compilers); - return result::failure; + if (!found) { + (void)std::fprintf( + stderr, + "error: No device matched the given substring, available devices:\n"); + printMuxCompilers(compilers); + return result::failure; + } } if (verbose) { diff --git a/source/cl/tools/clc/clc.h b/source/cl/tools/clc/clc.h index a51f53190f..4f683a2c6d 100644 --- a/source/cl/tools/clc/clc.h +++ b/source/cl/tools/clc/clc.h @@ -66,6 +66,9 @@ class driver { std::string input_file; /// @brief Path to the output file or `"-"` for `stdout`. cargo::string_view output_file; + /// @brief Device index to select from multiple devices. Takes precedence over + /// device name. + size_t device_idx; /// @brief Device name substring to select from multiple devices. cargo::string_view device_name_substring; /// @brief List of compile options passed to `clBuildProgram`.