Skip to content

Commit 14d4200

Browse files
authored
spirv-val: Allow tool to process directories (KhronosGroup#6292)
This patch enables spirv-val to process a directory as its input. The behaviour remains unchanged, except now filename is printed alongside a line number in the error message, when a single file is passed. When a directory is passed the tool will process all files in the directory and its nested directories recursively. Only files with the `.spv` extension are processed. When in the "directory mode" the tool will process all files (no early exit) and print validation errors as it goes. When any of the files fails validation non-zero code is returned. The selection of the mode (single file or directory) is done transparently to the user based on the path passed to the tool. This change is done to improve validation of SPIR-V modules in SPIR-V MLIR (see KhronosGroup#6276).
1 parent 813b52d commit 14d4200

File tree

1 file changed

+76
-10
lines changed

1 file changed

+76
-10
lines changed

tools/val/val.cpp

Lines changed: 76 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <cassert>
1616
#include <cstdio>
1717
#include <cstring>
18+
#include <filesystem>
1819
#include <iostream>
1920
#include <vector>
2021

@@ -27,12 +28,15 @@
2728
void print_usage(char* argv0) {
2829
std::string target_env_list = spvTargetEnvList(36, 105);
2930
printf(
30-
R"(%s - Validate a SPIR-V binary file.
31+
R"(%s - Validate a SPIR-V binary file(s).
3132
32-
USAGE: %s [options] [<filename>]
33+
USAGE: %s [options] [<path>]
3334
34-
The SPIR-V binary is read from <filename>. If no file is specified,
35-
or if the filename is "-", then the binary is read from standard input.
35+
The SPIR-V binary is read from <path>. If no path is specified,
36+
or if the path is "-", then the binary is read from standard input.
37+
The <path> parameter may also specify a directory; in this case,
38+
the tool will recursively process all regular files with the .spv
39+
extension within that directory.
3640
3741
NOTE: The validator is a work in progress.
3842
@@ -79,6 +83,53 @@ NOTE: The validator is a work in progress.
7983
argv0, argv0, target_env_list.c_str());
8084
}
8185

86+
bool process_single_file(const char* filename, spv_target_env& target_env,
87+
spvtools::ValidatorOptions& options,
88+
bool use_default_msg_consumer) {
89+
std::vector<uint32_t> contents;
90+
if (!ReadBinaryFile(filename, &contents)) return false;
91+
92+
spvtools::SpirvTools tools(target_env);
93+
94+
// Use a lambda expression here so filename can be captured. Messages use a
95+
// fairly standard notation of `filename:line`.
96+
auto CLIMessageConsumerWithFilename =
97+
[filename](spv_message_level_t level, const char*,
98+
const spv_position_t& position, const char* message) {
99+
const char* pretty_filename = filename;
100+
if (!filename || 0 == strcmp(filename, "-")) {
101+
pretty_filename = "stdin";
102+
}
103+
104+
switch (level) {
105+
case SPV_MSG_FATAL:
106+
case SPV_MSG_INTERNAL_ERROR:
107+
case SPV_MSG_ERROR:
108+
std::cerr << "error: " << pretty_filename << ":" << position.index
109+
<< ": " << message << std::endl;
110+
break;
111+
case SPV_MSG_WARNING:
112+
std::cout << "warning: " << pretty_filename << ":" << position.index
113+
<< ": " << message << std::endl;
114+
break;
115+
case SPV_MSG_INFO:
116+
std::cout << "info: " << pretty_filename << ":" << position.index
117+
<< ": " << message << std::endl;
118+
break;
119+
default:
120+
break;
121+
}
122+
};
123+
124+
if (use_default_msg_consumer) {
125+
tools.SetMessageConsumer(spvtools::utils::CLIMessageConsumer);
126+
} else {
127+
tools.SetMessageConsumer(CLIMessageConsumerWithFilename);
128+
}
129+
130+
return tools.Validate(contents.data(), contents.size(), options);
131+
}
132+
82133
int main(int argc, char** argv) {
83134
const char* inFile = nullptr;
84135
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_6;
@@ -201,13 +252,28 @@ int main(int argc, char** argv) {
201252
return return_code;
202253
}
203254

204-
std::vector<uint32_t> contents;
205-
if (!ReadBinaryFile(inFile, &contents)) return 1;
255+
if (inFile &&
256+
std::filesystem::is_directory(std::filesystem::status(inFile))) {
257+
const std::filesystem::path dir(inFile);
258+
bool succeed = true;
259+
for (auto const& entry :
260+
std::filesystem::recursive_directory_iterator(dir)) {
261+
if (!entry.is_regular_file()) {
262+
continue;
263+
}
206264

207-
spvtools::SpirvTools tools(target_env);
208-
tools.SetMessageConsumer(spvtools::utils::CLIMessageConsumer);
265+
std::filesystem::path filepath = entry.path();
209266

210-
bool succeed = tools.Validate(contents.data(), contents.size(), options);
267+
if (filepath.extension() != ".spv") continue;
268+
269+
if (!process_single_file(filepath.u8string().c_str(), target_env, options,
270+
false)) {
271+
succeed = false;
272+
}
273+
}
274+
275+
return !succeed;
276+
}
211277

212-
return !succeed;
278+
return !process_single_file(inFile, target_env, options, true);
213279
}

0 commit comments

Comments
 (0)