Skip to content

Commit

Permalink
tools: Move io utils to cpp (#5869)
Browse files Browse the repository at this point in the history
In preparation for more code in that file, which would get unwieldy in a
header.
  • Loading branch information
ShabbyX authored Oct 28, 2024
1 parent ce92630 commit 5f1e86c
Show file tree
Hide file tree
Showing 16 changed files with 229 additions and 173 deletions.
1 change: 1 addition & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ cc_library(
cc_library(
name = "tools_io",
hdrs = ["tools/io.h"],
srcs = ["tools/io.cpp"],
copts = COMMON_COPTS,
)

Expand Down
17 changes: 17 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1466,13 +1466,23 @@ source_set("spvtools_tools_util") {
configs += [ ":spvtools_internal_config" ]
}

source_set("spvtools_tools_io") {
sources = [
"tools/io.cpp",
"tools/io.h",
]
deps = [ ":spvtools_headers" ]
configs += [ ":spvtools_internal_config" ]
}

if (spvtools_build_executables) {
executable("spirv-as") {
sources = [ "tools/as/as.cpp" ]
deps = [
":spvtools",
":spvtools_software_version",
":spvtools_tools_util",
":spvtools_tools_io",
]
configs += [ ":spvtools_internal_config" ]
}
Expand All @@ -1483,6 +1493,7 @@ if (spvtools_build_executables) {
":spvtools",
":spvtools_software_version",
":spvtools_tools_util",
":spvtools_tools_io",
]
configs += [ ":spvtools_internal_config" ]
}
Expand All @@ -1493,6 +1504,7 @@ if (spvtools_build_executables) {
":spvtools",
":spvtools_software_version",
":spvtools_tools_util",
":spvtools_tools_io",
":spvtools_val",
]
configs += [ ":spvtools_internal_config" ]
Expand All @@ -1508,6 +1520,7 @@ if (spvtools_build_executables) {
":spvtools",
":spvtools_software_version",
":spvtools_tools_util",
":spvtools_tools_io",
]
configs += [ ":spvtools_internal_config" ]
}
Expand All @@ -1519,6 +1532,7 @@ if (spvtools_build_executables) {
":spvtools_opt",
":spvtools_software_version",
":spvtools_tools_util",
":spvtools_tools_io",
":spvtools_val",
]
configs += [ ":spvtools_internal_config" ]
Expand All @@ -1532,6 +1546,7 @@ if (spvtools_build_executables) {
":spvtools_opt",
":spvtools_software_version",
":spvtools_tools_util",
":spvtools_tools_io",
":spvtools_val",
]
configs += [ ":spvtools_internal_config" ]
Expand All @@ -1552,6 +1567,7 @@ if (!is_ios && !spirv_is_winuwp && build_with_chromium && spvtools_build_executa
":spvtools_reduce",
":spvtools_software_version",
":spvtools_tools_util",
":spvtools_tools_io",
":spvtools_val",
"//third_party/protobuf:protobuf_full",
]
Expand All @@ -1571,6 +1587,7 @@ if (!is_ios && !spirv_is_winuwp && spvtools_build_executables) {
":spvtools_reduce",
":spvtools_software_version",
":spvtools_tools_util",
":spvtools_tools_io",
":spvtools_val",
]
configs += [ ":spvtools_internal_config" ]
Expand Down
3 changes: 2 additions & 1 deletion test/fuzz/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ if (${SPIRV_BUILD_FUZZER})
transformation_wrap_early_terminator_in_function_test.cpp
transformation_wrap_region_in_selection_test.cpp
transformation_wrap_vector_synonym_test.cpp
uniform_buffer_element_descriptor_test.cpp)
uniform_buffer_element_descriptor_test.cpp
${spirv-tools_SOURCE_DIR}/tools/io.cpp)

if (${SPIRV_ENABLE_LONG_FUZZER_TESTS})
# These are long-running tests that depend on random seeds. We do not want
Expand Down
1 change: 1 addition & 0 deletions test/reduce/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ add_spvtools_unittest(TARGET reduce
structured_construct_to_block_test.cpp
structured_loop_to_selection_test.cpp
validation_during_reduction_test.cpp
${spirv-tools_SOURCE_DIR}/tools/io.cpp
LIBS SPIRV-Tools-reduce
)

19 changes: 11 additions & 8 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,18 @@ endfunction()
set(COMMON_TOOLS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/util/flags.cpp")

if (NOT ${SPIRV_SKIP_EXECUTABLES})
add_spvtools_tool(TARGET spirv-diff SRCS ${COMMON_TOOLS_SRCS} diff/diff.cpp util/cli_consumer.cpp LIBS SPIRV-Tools-diff SPIRV-Tools-opt ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-dis SRCS ${COMMON_TOOLS_SRCS} dis/dis.cpp LIBS ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-val SRCS ${COMMON_TOOLS_SRCS} val/val.cpp util/cli_consumer.cpp LIBS ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-opt SRCS ${COMMON_TOOLS_SRCS} opt/opt.cpp util/cli_consumer.cpp LIBS SPIRV-Tools-opt ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-diff SRCS ${COMMON_TOOLS_SRCS} diff/diff.cpp util/cli_consumer.cpp io.cpp LIBS SPIRV-Tools-diff SPIRV-Tools-opt ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-dis SRCS ${COMMON_TOOLS_SRCS} dis/dis.cpp io.cpp LIBS ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-val SRCS ${COMMON_TOOLS_SRCS} val/val.cpp util/cli_consumer.cpp io.cpp LIBS ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-opt SRCS ${COMMON_TOOLS_SRCS} opt/opt.cpp util/cli_consumer.cpp io.cpp LIBS SPIRV-Tools-opt ${SPIRV_TOOLS_FULL_VISIBILITY})
if(NOT (${CMAKE_SYSTEM_NAME} STREQUAL "iOS")) # iOS does not allow std::system calls which spirv-reduce requires
add_spvtools_tool(TARGET spirv-reduce SRCS ${COMMON_TOOLS_SRCS} reduce/reduce.cpp util/cli_consumer.cpp LIBS SPIRV-Tools-reduce ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-reduce SRCS ${COMMON_TOOLS_SRCS} reduce/reduce.cpp util/cli_consumer.cpp io.cpp LIBS SPIRV-Tools-reduce ${SPIRV_TOOLS_FULL_VISIBILITY})
endif()
add_spvtools_tool(TARGET spirv-link SRCS ${COMMON_TOOLS_SRCS} link/linker.cpp LIBS SPIRV-Tools-link ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-lint SRCS ${COMMON_TOOLS_SRCS} lint/lint.cpp util/cli_consumer.cpp LIBS SPIRV-Tools-lint SPIRV-Tools-opt ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-link SRCS ${COMMON_TOOLS_SRCS} link/linker.cpp io.cpp LIBS SPIRV-Tools-link ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-lint SRCS ${COMMON_TOOLS_SRCS} lint/lint.cpp util/cli_consumer.cpp io.cpp LIBS SPIRV-Tools-lint SPIRV-Tools-opt ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-as
SRCS as/as.cpp
io.cpp
${COMMON_TOOLS_SRCS}
LIBS ${SPIRV_TOOLS_FULL_VISIBILITY})
target_include_directories(spirv-as PRIVATE ${spirv-tools_SOURCE_DIR}
Expand All @@ -61,6 +62,7 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES})
SRCS cfg/cfg.cpp
cfg/bin_to_dot.h
cfg/bin_to_dot.cpp
io.cpp
${COMMON_TOOLS_SRCS}
LIBS ${SPIRV_TOOLS_FULL_VISIBILITY})
target_include_directories(spirv-cfg PRIVATE ${spirv-tools_SOURCE_DIR}
Expand All @@ -73,6 +75,7 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES})
SRCS objdump/objdump.cpp
objdump/extract_source.cpp
util/cli_consumer.cpp
io.cpp
${COMMON_TOOLS_SRCS}
LIBS ${SPIRV_TOOLS_FULL_VISIBILITY})
target_include_directories(spirv-objdump PRIVATE ${spirv-tools_SOURCE_DIR}
Expand All @@ -85,7 +88,7 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES})
endif()

if(SPIRV_BUILD_FUZZER)
add_spvtools_tool(TARGET spirv-fuzz SRCS fuzz/fuzz.cpp util/cli_consumer.cpp LIBS SPIRV-Tools-fuzz ${SPIRV_TOOLS_FULL_VISIBILITY})
add_spvtools_tool(TARGET spirv-fuzz SRCS fuzz/fuzz.cpp util/cli_consumer.cpp io.cpp LIBS SPIRV-Tools-fuzz ${SPIRV_TOOLS_FULL_VISIBILITY})
set(SPIRV_INSTALL_TARGETS ${SPIRV_INSTALL_TARGETS} spirv-fuzz)
endif(SPIRV_BUILD_FUZZER)

Expand Down
2 changes: 1 addition & 1 deletion tools/as/as.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ int main(int, const char** argv) {
std::string inFile = flags::positional_arguments[0];

std::vector<char> contents;
if (!ReadTextFile<char>(inFile.c_str(), &contents)) return 1;
if (!ReadTextFile(inFile.c_str(), &contents)) return 1;

spv_binary binary;
spv_diagnostic diagnostic = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion tools/cfg/cfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ int main(int, const char** argv) {

// Read the input binary.
std::vector<uint32_t> contents;
if (!ReadBinaryFile<uint32_t>(inFile.c_str(), &contents)) return 1;
if (!ReadBinaryFile(inFile.c_str(), &contents)) return 1;
spv_context context = spvContextCreate(kDefaultEnvironment);
spv_diagnostic diagnostic = nullptr;

Expand Down
4 changes: 2 additions & 2 deletions tools/diff/diff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ bool is_assembly(const char* path) {
std::unique_ptr<spvtools::opt::IRContext> load_module(const char* path) {
if (is_assembly(path)) {
std::vector<char> contents;
if (!ReadTextFile<char>(path, &contents)) return {};
if (!ReadTextFile(path, &contents)) return {};

return spvtools::BuildModule(
kDefaultEnvironment, spvtools::utils::CLIMessageConsumer,
Expand All @@ -92,7 +92,7 @@ std::unique_ptr<spvtools::opt::IRContext> load_module(const char* path) {
}

std::vector<uint32_t> contents;
if (!ReadBinaryFile<uint32_t>(path, &contents)) return {};
if (!ReadBinaryFile(path, &contents)) return {};

return spvtools::BuildModule(kDefaultEnvironment,
spvtools::utils::CLIMessageConsumer,
Expand Down
2 changes: 1 addition & 1 deletion tools/dis/dis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ int main(int, const char** argv) {

// Read the input binary.
std::vector<uint32_t> contents;
if (!ReadBinaryFile<uint32_t>(inFile.c_str(), &contents)) return 1;
if (!ReadBinaryFile(inFile.c_str(), &contents)) return 1;

// If printing to standard output, then spvBinaryToText should
// do the printing. In particular, colour printing on Windows is
Expand Down
5 changes: 2 additions & 3 deletions tools/fuzz/fuzz.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -584,8 +584,7 @@ bool Fuzz(const spv_target_env& target_env,
[donor_filename, message_consumer,
target_env]() -> std::unique_ptr<spvtools::opt::IRContext> {
std::vector<uint32_t> donor_binary;
if (!ReadBinaryFile<uint32_t>(donor_filename.c_str(),
&donor_binary)) {
if (!ReadBinaryFile(donor_filename.c_str(), &donor_binary)) {
return nullptr;
}
return spvtools::BuildModule(target_env, message_consumer,
Expand Down Expand Up @@ -712,7 +711,7 @@ int main(int argc, const char** argv) {
}

std::vector<uint32_t> binary_in;
if (!ReadBinaryFile<uint32_t>(in_binary_file.c_str(), &binary_in)) {
if (!ReadBinaryFile(in_binary_file.c_str(), &binary_in)) {
return 1;
}

Expand Down
175 changes: 175 additions & 0 deletions tools/io.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// Copyright (c) 2024 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "io.h"

#include <assert.h>

#if defined(SPIRV_WINDOWS)
#include <fcntl.h>
#include <io.h>

#define SET_STDIN_TO_BINARY_MODE() _setmode(_fileno(stdin), O_BINARY);
#define SET_STDIN_TO_TEXT_MODE() _setmode(_fileno(stdin), O_TEXT);
#define SET_STDOUT_TO_BINARY_MODE() _setmode(_fileno(stdout), O_BINARY);
#define SET_STDOUT_TO_TEXT_MODE() _setmode(_fileno(stdout), O_TEXT);
#define SET_STDOUT_MODE(mode) _setmode(_fileno(stdout), mode);
#else
#define SET_STDIN_TO_BINARY_MODE()
#define SET_STDIN_TO_TEXT_MODE()
#define SET_STDOUT_TO_BINARY_MODE() 0
#define SET_STDOUT_TO_TEXT_MODE() 0
#define SET_STDOUT_MODE(mode)
#endif

namespace {
// Appends the contents of the |file| to |data|, assuming each element in the
// file is of type |T|.
template <typename T>
void ReadFile(FILE* file, std::vector<T>* data) {
if (file == nullptr) return;

const int buf_size = 1024;
T buf[buf_size];
while (size_t len = fread(buf, sizeof(T), buf_size, file)) {
data->insert(data->end(), buf, buf + len);
}
}

// Returns true if |file| has encountered an error opening the file or reading
// the file as a series of element of type |T|. If there was an error, writes an
// error message to standard error.
template <class T>
bool WasFileCorrectlyRead(FILE* file, const char* filename) {
if (file == nullptr) {
fprintf(stderr, "error: file does not exist '%s'\n", filename);
return false;
}

if (ftell(file) == -1L) {
if (ferror(file)) {
fprintf(stderr, "error: error reading file '%s'\n", filename);
return false;
}
} else {
if (sizeof(T) != 1 && (ftell(file) % sizeof(T))) {
fprintf(
stderr,
"error: file size should be a multiple of %zd; file '%s' corrupt\n",
sizeof(T), filename);
return false;
}
}
return true;
}
} // namespace

bool ReadBinaryFile(const char* filename, std::vector<uint32_t>* data) {
assert(data->empty());

const bool use_file = filename && strcmp("-", filename);
FILE* fp = nullptr;
if (use_file) {
fp = fopen(filename, "rb");
} else {
SET_STDIN_TO_BINARY_MODE();
fp = stdin;
}

ReadFile(fp, data);
bool succeeded = WasFileCorrectlyRead<uint32_t>(fp, filename);
if (use_file && fp) fclose(fp);
return succeeded;
}

bool ReadTextFile(const char* filename, std::vector<char>* data) {
assert(data->empty());

const bool use_file = filename && strcmp("-", filename);
FILE* fp = nullptr;
if (use_file) {
fp = fopen(filename, "r");
} else {
SET_STDIN_TO_TEXT_MODE();
fp = stdin;
}

ReadFile(fp, data);
bool succeeded = WasFileCorrectlyRead<char>(fp, filename);
if (use_file && fp) fclose(fp);
return succeeded;
}

namespace {
// A class to create and manage a file for outputting data.
class OutputFile {
public:
// Opens |filename| in the given mode. If |filename| is nullptr, the empty
// string or "-", stdout will be set to the given mode.
OutputFile(const char* filename, const char* mode) : old_mode_(0) {
const bool use_stdout =
!filename || (filename[0] == '-' && filename[1] == '\0');
if (use_stdout) {
if (strchr(mode, 'b')) {
old_mode_ = SET_STDOUT_TO_BINARY_MODE();
} else {
old_mode_ = SET_STDOUT_TO_TEXT_MODE();
}
fp_ = stdout;
} else {
fp_ = fopen(filename, mode);
}
}

~OutputFile() {
if (fp_ == stdout) {
fflush(stdout);
SET_STDOUT_MODE(old_mode_);
} else if (fp_ != nullptr) {
fclose(fp_);
}
}

// Returns a file handle to the file.
FILE* GetFileHandle() const { return fp_; }

private:
FILE* fp_;
int old_mode_;
};
} // namespace

template <typename T>
bool WriteFile(const char* filename, const char* mode, const T* data,
size_t count) {
OutputFile file(filename, mode);
FILE* fp = file.GetFileHandle();
if (fp == nullptr) {
fprintf(stderr, "error: could not open file '%s'\n", filename);
return false;
}

size_t written = fwrite(data, sizeof(T), count, fp);
if (count != written) {
fprintf(stderr, "error: could not write to file '%s'\n", filename);
return false;
}

return true;
}

template bool WriteFile<uint32_t>(const char* filename, const char* mode,
const uint32_t* data, size_t count);
template bool WriteFile<char>(const char* filename, const char* mode,
const char* data, size_t count);
Loading

0 comments on commit 5f1e86c

Please sign in to comment.