Porting iree/base/internal/file_io.h to C. (#5699)
Moved the old std::string-based GetFileContents out to vm_util.h. Future
changes will remove the use entirely but it's not worth cleaning up the
users here.
diff --git a/iree/base/internal/BUILD b/iree/base/internal/BUILD
index 3736bf9..50b3fc3 100644
--- a/iree/base/internal/BUILD
+++ b/iree/base/internal/BUILD
@@ -114,7 +114,7 @@
cc_library(
name = "file_io",
- srcs = ["file_io.cc"],
+ srcs = ["file_io.c"],
hdrs = ["file_io.h"],
deps = [
"//iree/base",
@@ -161,6 +161,7 @@
srcs = ["flags.c"],
hdrs = ["flags.h"],
deps = [
+ ":file_io",
":internal",
"//iree/base",
"//iree/base:tracing",
diff --git a/iree/base/internal/CMakeLists.txt b/iree/base/internal/CMakeLists.txt
index d01ba7c..67298a8 100644
--- a/iree/base/internal/CMakeLists.txt
+++ b/iree/base/internal/CMakeLists.txt
@@ -97,7 +97,7 @@
HDRS
"file_io.h"
SRCS
- "file_io.cc"
+ "file_io.c"
DEPS
iree::base
iree::base::core_headers
@@ -149,6 +149,7 @@
SRCS
"flags.c"
DEPS
+ ::file_io
::internal
iree::base
iree::base::tracing
diff --git a/iree/base/internal/file_io.c b/iree/base/internal/file_io.c
new file mode 100644
index 0000000..f44a859
--- /dev/null
+++ b/iree/base/internal/file_io.c
@@ -0,0 +1,128 @@
+// Copyright 2019 Google LLC
+//
+// 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
+//
+// https://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 "iree/base/internal/file_io.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "iree/base/target_platform.h"
+#include "iree/base/tracing.h"
+
+iree_status_t iree_file_exists(const char* path) {
+ IREE_ASSERT_ARGUMENT(path);
+ IREE_TRACE_ZONE_BEGIN(z0);
+
+ struct stat stat_buf;
+ iree_status_t status =
+ stat(path, &stat_buf) == 0
+ ? iree_ok_status()
+ : iree_make_status(IREE_STATUS_NOT_FOUND, "'%s'", path);
+
+ IREE_TRACE_ZONE_END(z0);
+ return status;
+}
+
+static iree_status_t iree_file_read_contents_impl(
+ FILE* file, iree_allocator_t allocator, iree_byte_span_t* out_contents) {
+ // Seek to the end of the file.
+ if (fseek(file, 0, SEEK_END) == -1) {
+ return iree_make_status(iree_status_code_from_errno(errno), "seek (end)");
+ }
+
+ // Query the position, telling us the total file length in bytes.
+ size_t file_size = ftell(file);
+ if (file_size == -1L) {
+ return iree_make_status(iree_status_code_from_errno(errno), "size query");
+ }
+
+ // Seek back to the file start.
+ if (fseek(file, 0, SEEK_SET) == -1) {
+ return iree_make_status(iree_status_code_from_errno(errno), "seek (beg)");
+ }
+
+ // Allocate +1 to force a trailing \0 in case this is a string.
+ char* contents = NULL;
+ IREE_RETURN_IF_ERROR(
+ iree_allocator_malloc(allocator, file_size + 1, (void**)&contents));
+
+ // Attempt to read the file into memory.
+ if (fread(contents, file_size, 1, file) != 1) {
+ iree_allocator_free(allocator, contents);
+ return iree_make_status(iree_status_code_from_errno(errno),
+ "unable to read entire %zu file bytes", file_size);
+ }
+
+ // Add trailing NUL to make the contents C-string compatible.
+ contents[file_size] = 0; // NUL
+ *out_contents = iree_make_byte_span(contents, file_size);
+ return iree_ok_status();
+}
+
+iree_status_t iree_file_read_contents(const char* path,
+ iree_allocator_t allocator,
+ iree_byte_span_t* out_contents) {
+ IREE_ASSERT_ARGUMENT(path);
+ IREE_ASSERT_ARGUMENT(out_contents);
+ IREE_TRACE_ZONE_BEGIN(z0);
+ *out_contents = iree_make_byte_span(NULL, 0);
+
+ FILE* file = fopen(path, "rb");
+ if (file == NULL) {
+ IREE_TRACE_ZONE_END(z0);
+ return iree_make_status(iree_status_code_from_errno(errno),
+ "failed to open file '%s'", path);
+ }
+
+ // Read the file contents into memory.
+ iree_status_t status =
+ iree_file_read_contents_impl(file, allocator, out_contents);
+ if (!iree_status_is_ok(status)) {
+ status = iree_status_annotate_f(status, "reading file '%s'", path);
+ }
+
+ fclose(file);
+
+ IREE_TRACE_ZONE_END(z0);
+ return status;
+}
+
+iree_status_t iree_file_write_contents(const char* path,
+ iree_const_byte_span_t content) {
+ IREE_ASSERT_ARGUMENT(path);
+ IREE_TRACE_ZONE_BEGIN(z0);
+
+ FILE* file = fopen(path, "wb");
+ if (file == NULL) {
+ IREE_TRACE_ZONE_END(z0);
+ return iree_make_status(iree_status_code_from_errno(errno),
+ "failed to open file '%s'", path);
+ }
+
+ int ret = fwrite((char*)content.data, content.data_length, 1, file);
+ iree_status_t status = iree_ok_status();
+ if (ret != 1) {
+ status =
+ iree_make_status(IREE_STATUS_DATA_LOSS,
+ "unable to write file contents of %zu bytes to '%s'",
+ content.data_length, path);
+ }
+
+ fclose(file);
+
+ IREE_TRACE_ZONE_END(z0);
+ return status;
+}
diff --git a/iree/base/internal/file_io.cc b/iree/base/internal/file_io.cc
deleted file mode 100644
index 288ac76..0000000
--- a/iree/base/internal/file_io.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2019 Google LLC
-//
-// 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
-//
-// https://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 "iree/base/internal/file_io.h"
-
-#include <errno.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "iree/base/target_platform.h"
-#include "iree/base/tracing.h"
-
-namespace iree {
-namespace file_io {
-
-iree_status_t FileExists(const char* path) {
- IREE_TRACE_ZONE_BEGIN(z0);
- struct stat stat_buf;
- iree_status_t status =
- stat(path, &stat_buf) == 0
- ? iree_ok_status()
- : iree_make_status(IREE_STATUS_NOT_FOUND, "'%s'", path);
- IREE_TRACE_ZONE_END(z0);
- return status;
-}
-
-iree_status_t GetFileContents(const char* path, std::string* out_contents) {
- IREE_TRACE_ZONE_BEGIN(z0);
- *out_contents = std::string();
- FILE* file = fopen(path, "rb");
- if (file == NULL) {
- IREE_TRACE_ZONE_END(z0);
- return iree_make_status(iree_status_code_from_errno(errno),
- "failed to open file '%s'", path);
- }
- iree_status_t status = iree_ok_status();
- if (fseek(file, 0, SEEK_END) == -1) {
- status = iree_make_status(iree_status_code_from_errno(errno), "seek (end)");
- }
- size_t file_size = 0;
- if (iree_status_is_ok(status)) {
- file_size = ftell(file);
- if (file_size == -1L) {
- status =
- iree_make_status(iree_status_code_from_errno(errno), "size query");
- }
- }
- if (iree_status_is_ok(status)) {
- if (fseek(file, 0, SEEK_SET) == -1) {
- status =
- iree_make_status(iree_status_code_from_errno(errno), "seek (beg)");
- }
- }
- std::string contents;
- if (iree_status_is_ok(status)) {
- contents.resize(file_size);
- if (fread((char*)contents.data(), file_size, 1, file) != 1) {
- status =
- iree_make_status(iree_status_code_from_errno(errno),
- "unable to read entire file contents of '%s'", path);
- }
- }
- if (iree_status_is_ok(status)) {
- *out_contents = std::move(contents);
- }
- fclose(file);
- IREE_TRACE_ZONE_END(z0);
- return status;
-}
-
-iree_status_t SetFileContents(const char* path,
- iree_const_byte_span_t content) {
- IREE_TRACE_ZONE_BEGIN(z0);
- FILE* file = fopen(path, "wb");
- if (file == NULL) {
- IREE_TRACE_ZONE_END(z0);
- return iree_make_status(iree_status_code_from_errno(errno),
- "failed to open file '%s'", path);
- }
- int ret = fwrite((char*)content.data, content.data_length, 1, file);
- iree_status_t status = iree_ok_status();
- if (ret != 1) {
- status =
- iree_make_status(IREE_STATUS_DATA_LOSS,
- "unable to write entire file contents of '%s'", path);
- }
- fclose(file);
- IREE_TRACE_ZONE_END(z0);
- return status;
-}
-
-} // namespace file_io
-} // namespace iree
diff --git a/iree/base/internal/file_io.h b/iree/base/internal/file_io.h
index 144204c..1e964cc 100644
--- a/iree/base/internal/file_io.h
+++ b/iree/base/internal/file_io.h
@@ -15,26 +15,35 @@
#ifndef IREE_BASE_INTERNAL_FILE_IO_H_
#define IREE_BASE_INTERNAL_FILE_IO_H_
-#include <string>
-
#include "iree/base/api.h"
-namespace iree {
-namespace file_io {
+#ifdef __cplusplus
+extern "C" {
+#endif
-// Checks if a file exists at the provided path.
+// Checks if a file exists at the provided |path|.
//
-// Returns an OK status if the file definitely exists.
-// Errors can include PermissionDeniedError, NotFoundError, etc.
-iree_status_t FileExists(const char* path);
+// Returns an OK status if the file definitely exists. An OK status does not
+// indicate that attempts to read or write the file will succeed.
+// Returns IREE_STATUS_NOT_FOUND if the file does not exist.
+iree_status_t iree_file_exists(const char* path);
-// Synchronously reads a file's contents into a string.
-iree_status_t GetFileContents(const char* path, std::string* out_contents);
+// Synchronously reads a file's contents into memory.
+//
+// Returns the contents of the file in |out_contents|.
+// |allocator| is used to allocate the memory and the caller must use the same
+// allocator when freeing it.
+iree_status_t iree_file_read_contents(const char* path,
+ iree_allocator_t allocator,
+ iree_byte_span_t* out_contents);
-// Synchronously writes a string into a file, overwriting its contents.
-iree_status_t SetFileContents(const char* path, iree_const_byte_span_t content);
+// Synchronously writes a byte buffer into a file.
+// Existing contents are overwritten.
+iree_status_t iree_file_write_contents(const char* path,
+ iree_const_byte_span_t content);
-} // namespace file_io
-} // namespace iree
+#ifdef __cplusplus
+} // extern "C"
+#endif
#endif // IREE_BASE_INTERNAL_FILE_IO_H_
diff --git a/iree/base/internal/file_io_test.cc b/iree/base/internal/file_io_test.cc
index e628fa9..d48c474 100644
--- a/iree/base/internal/file_io_test.cc
+++ b/iree/base/internal/file_io_test.cc
@@ -39,18 +39,34 @@
return std::string("Test with name ") + unique_name + "\n";
}
-TEST(FileIo, GetSetContents) {
- constexpr const char* kUniqueName = "GetSetContents";
+TEST(FileIO, ReadWriteContents) {
+ constexpr const char* kUniqueName = "ReadWriteContents";
auto path = GetUniquePath(kUniqueName);
- ASSERT_THAT(FileExists(path.c_str()), StatusIs(StatusCode::kNotFound));
- auto to_write = GetUniqueContents(kUniqueName);
- IREE_ASSERT_OK(SetFileContents(
+ // File must not exist.
+ ASSERT_THAT(Status(iree_file_exists(path.c_str())),
+ StatusIs(StatusCode::kNotFound));
+
+ // Generate file contents.
+ auto write_contents = GetUniqueContents(kUniqueName);
+
+ // Write the contents to disk.
+ IREE_ASSERT_OK(iree_file_write_contents(
path.c_str(),
- iree_make_const_byte_span(to_write.data(), to_write.size())));
- std::string read;
- IREE_ASSERT_OK(GetFileContents(path.c_str(), &read));
- EXPECT_EQ(to_write, read);
+ iree_make_const_byte_span(write_contents.data(), write_contents.size())));
+
+ // Read the contents from disk.
+ iree_byte_span_t read_contents;
+ IREE_ASSERT_OK(iree_file_read_contents(path.c_str(), iree_allocator_system(),
+ &read_contents));
+
+ // Expect the contents are equal.
+ EXPECT_EQ(write_contents.size(), read_contents.data_length);
+ EXPECT_EQ(memcmp(write_contents.data(), read_contents.data,
+ read_contents.data_length),
+ 0);
+
+ iree_allocator_free(iree_allocator_system(), read_contents.data);
}
} // namespace
diff --git a/iree/base/internal/flags.c b/iree/base/internal/flags.c
index 0b67591..3092b63 100644
--- a/iree/base/internal/flags.c
+++ b/iree/base/internal/flags.c
@@ -21,11 +21,11 @@
#include <stdlib.h>
#include <string.h>
+#if IREE_FLAGS_ENABLE_CLI == 1
+
#include "iree/base/internal/debugging.h"
#include "iree/base/tracing.h"
-#if IREE_FLAGS_ENABLE_CLI == 1
-
//===----------------------------------------------------------------------===//
// Flag manipulation utilities
//===----------------------------------------------------------------------===//
@@ -452,58 +452,7 @@
#if IREE_FLAGS_ENABLE_FLAG_FILE == 1
-// TODO(benvanik): use this to replace file_io.cc.
-static iree_status_t iree_file_read_contents(const char* path,
- iree_allocator_t allocator,
- iree_byte_span_t* out_contents) {
- IREE_TRACE_ZONE_BEGIN(z0);
- *out_contents = iree_make_byte_span(NULL, 0);
- FILE* file = fopen(path, "rb");
- if (file == NULL) {
- IREE_TRACE_ZONE_END(z0);
- return iree_make_status(iree_status_code_from_errno(errno),
- "failed to open file '%s'", path);
- }
- iree_status_t status = iree_ok_status();
- if (fseek(file, 0, SEEK_END) == -1) {
- status = iree_make_status(iree_status_code_from_errno(errno), "seek (end)");
- }
- size_t file_size = 0;
- if (iree_status_is_ok(status)) {
- file_size = ftell(file);
- if (file_size == -1L) {
- status =
- iree_make_status(iree_status_code_from_errno(errno), "size query");
- }
- }
- if (iree_status_is_ok(status)) {
- if (fseek(file, 0, SEEK_SET) == -1) {
- status =
- iree_make_status(iree_status_code_from_errno(errno), "seek (beg)");
- }
- }
- // Allocate +1 to force a trailing \0 in case this is a string.
- char* contents = NULL;
- if (iree_status_is_ok(status)) {
- status = iree_allocator_malloc(allocator, file_size + 1, (void**)&contents);
- }
- if (iree_status_is_ok(status)) {
- if (fread(contents, file_size, 1, file) != 1) {
- status =
- iree_make_status(iree_status_code_from_errno(errno),
- "unable to read entire file contents of '%s'", path);
- }
- }
- if (iree_status_is_ok(status)) {
- contents[file_size] = 0; // NUL
- *out_contents = iree_make_byte_span(contents, file_size);
- } else {
- iree_allocator_free(allocator, contents);
- }
- fclose(file);
- IREE_TRACE_ZONE_END(z0);
- return status;
-}
+#include "iree/base/internal/file_io.h"
// Parses a newline-separated list of flags from a file.
static iree_status_t iree_flags_parse_file(iree_string_view_t file_path) {
diff --git a/iree/base/testing/dynamic_library_test.cc b/iree/base/testing/dynamic_library_test.cc
index 559950b..22db908 100644
--- a/iree/base/testing/dynamic_library_test.cc
+++ b/iree/base/testing/dynamic_library_test.cc
@@ -61,7 +61,7 @@
library_temp_path_ = GetTempFilename(ext);
const auto* file_toc = dynamic_library_test_library_create();
- IREE_ASSERT_OK(file_io::SetFileContents(
+ IREE_ASSERT_OK(iree_file_write_contents(
library_temp_path_.c_str(),
iree_make_const_byte_span(file_toc->data, file_toc->size)));
diff --git a/iree/testing/vulkan/iree-run-module-vulkan-gui-main.cc b/iree/testing/vulkan/iree-run-module-vulkan-gui-main.cc
index 1e3f42b..08b0ce3 100644
--- a/iree/testing/vulkan/iree-run-module-vulkan-gui-main.cc
+++ b/iree/testing/vulkan/iree-run-module-vulkan-gui-main.cc
@@ -108,8 +108,7 @@
*out_contents = std::string{std::istreambuf_iterator<char>(std::cin),
std::istreambuf_iterator<char>()};
} else {
- IREE_RETURN_IF_ERROR(
- file_io::GetFileContents(module_file.c_str(), out_contents));
+ IREE_RETURN_IF_ERROR(GetFileContents(module_file.c_str(), out_contents));
}
return OkStatus();
}
diff --git a/iree/tools/BUILD b/iree/tools/BUILD
index 0d62597..b3bcab2 100644
--- a/iree/tools/BUILD
+++ b/iree/tools/BUILD
@@ -72,6 +72,7 @@
"//iree/base:status",
"//iree/base/internal:file_io",
"//iree/schemas:bytecode_module_def_c_fbs",
+ "//iree/tools/utils:vm_util",
],
)
diff --git a/iree/tools/CMakeLists.txt b/iree/tools/CMakeLists.txt
index 4998715..25720aa 100644
--- a/iree/tools/CMakeLists.txt
+++ b/iree/tools/CMakeLists.txt
@@ -113,6 +113,7 @@
iree::base::internal::file_io
iree::base::status
iree::schemas::bytecode_module_def_c_fbs
+ iree::tools::utils::vm_util
)
iree_cc_binary(
diff --git a/iree/tools/iree-benchmark-module-main.cc b/iree/tools/iree-benchmark-module-main.cc
index f5f9611..76662c2 100644
--- a/iree/tools/iree-benchmark-module-main.cc
+++ b/iree/tools/iree-benchmark-module-main.cc
@@ -132,8 +132,7 @@
*out_contents = std::string{std::istreambuf_iterator<char>(std::cin),
std::istreambuf_iterator<char>()};
} else {
- IREE_RETURN_IF_ERROR(
- file_io::GetFileContents(module_file.c_str(), out_contents));
+ IREE_RETURN_IF_ERROR(GetFileContents(module_file.c_str(), out_contents));
}
return OkStatus();
}
diff --git a/iree/tools/iree-check-module-main.cc b/iree/tools/iree-check-module-main.cc
index aee13e1..71eaf45 100644
--- a/iree/tools/iree-check-module-main.cc
+++ b/iree/tools/iree-check-module-main.cc
@@ -96,7 +96,7 @@
std::istreambuf_iterator<char>()};
} else {
IREE_RETURN_IF_ERROR(
- file_io::GetFileContents(module_file_path.c_str(), &module_data));
+ GetFileContents(module_file_path.c_str(), &module_data));
}
iree_vm_module_t* input_module = nullptr;
diff --git a/iree/tools/iree-dump-module-main.cc b/iree/tools/iree-dump-module-main.cc
index 273246a..362d523 100644
--- a/iree/tools/iree-dump-module-main.cc
+++ b/iree/tools/iree-dump-module-main.cc
@@ -19,6 +19,7 @@
#include "iree/base/internal/file_io.h"
#include "iree/base/status.h"
#include "iree/schemas/bytecode_module_def_json_printer.h"
+#include "iree/tools/utils/vm_util.h"
// Today we just print to JSON. We could do something more useful (size
// analysis, etc), but JSON should be enough.
@@ -32,7 +33,7 @@
return 1;
}
std::string module_contents;
- IREE_CHECK_OK(iree::file_io::GetFileContents(argv[1], &module_contents));
+ IREE_CHECK_OK(iree::GetFileContents(argv[1], &module_contents));
// Print direct to stdout.
flatcc_json_printer_t printer;
diff --git a/iree/tools/iree-run-module-main.cc b/iree/tools/iree-run-module-main.cc
index 24d4934..8f6b53c 100644
--- a/iree/tools/iree-run-module-main.cc
+++ b/iree/tools/iree-run-module-main.cc
@@ -76,8 +76,7 @@
*out_contents = std::string{std::istreambuf_iterator<char>(std::cin),
std::istreambuf_iterator<char>()};
} else {
- IREE_RETURN_IF_ERROR(
- file_io::GetFileContents(module_file.c_str(), out_contents));
+ IREE_RETURN_IF_ERROR(GetFileContents(module_file.c_str(), out_contents));
}
return OkStatus();
}
diff --git a/iree/tools/utils/vm_util.cc b/iree/tools/utils/vm_util.cc
index 3bfbbc9..b43f243 100644
--- a/iree/tools/utils/vm_util.cc
+++ b/iree/tools/utils/vm_util.cc
@@ -28,6 +28,50 @@
namespace iree {
+Status GetFileContents(const char* path, std::string* out_contents) {
+ IREE_TRACE_ZONE_BEGIN(z0);
+ *out_contents = std::string();
+ FILE* file = fopen(path, "rb");
+ if (file == NULL) {
+ IREE_TRACE_ZONE_END(z0);
+ return iree_make_status(iree_status_code_from_errno(errno),
+ "failed to open file '%s'", path);
+ }
+ iree_status_t status = iree_ok_status();
+ if (fseek(file, 0, SEEK_END) == -1) {
+ status = iree_make_status(iree_status_code_from_errno(errno), "seek (end)");
+ }
+ size_t file_size = 0;
+ if (iree_status_is_ok(status)) {
+ file_size = ftell(file);
+ if (file_size == -1L) {
+ status =
+ iree_make_status(iree_status_code_from_errno(errno), "size query");
+ }
+ }
+ if (iree_status_is_ok(status)) {
+ if (fseek(file, 0, SEEK_SET) == -1) {
+ status =
+ iree_make_status(iree_status_code_from_errno(errno), "seek (beg)");
+ }
+ }
+ std::string contents;
+ if (iree_status_is_ok(status)) {
+ contents.resize(file_size);
+ if (fread((char*)contents.data(), file_size, 1, file) != 1) {
+ status =
+ iree_make_status(iree_status_code_from_errno(errno),
+ "unable to read entire file contents of '%s'", path);
+ }
+ }
+ if (iree_status_is_ok(status)) {
+ *out_contents = std::move(contents);
+ }
+ fclose(file);
+ IREE_TRACE_ZONE_END(z0);
+ return status;
+}
+
Status ValidateFunctionAbi(const iree_vm_function_t& function) {
// Benchmark functions are always allowed through as they are () -> ().
// That we are requiring SIP for everything in this util file is bad, and this
diff --git a/iree/tools/utils/vm_util.h b/iree/tools/utils/vm_util.h
index 006961a..2b9bdc0 100644
--- a/iree/tools/utils/vm_util.h
+++ b/iree/tools/utils/vm_util.h
@@ -30,6 +30,9 @@
// TODO(benvanik) Update these when we can use RAII with the C API.
+// Synchronously reads a file's contents into a string.
+Status GetFileContents(const char* path, std::string* out_contents);
+
// Validates the ABI of the specified function is supported by current tooling.
Status ValidateFunctionAbi(const iree_vm_function_t& function);