Supporting file descriptors in iree_io_stream_open. (#19665)
diff --git a/runtime/src/iree/io/BUILD.bazel b/runtime/src/iree/io/BUILD.bazel
index 7d4c0e1..892989f 100644
--- a/runtime/src/iree/io/BUILD.bazel
+++ b/runtime/src/iree/io/BUILD.bazel
@@ -17,19 +17,6 @@
srcs = ["file_handle.c"],
hdrs = ["file_handle.h"],
deps = [
- ":memory_stream",
- ":stream",
- "//runtime/src/iree/base",
- "//runtime/src/iree/base/internal",
- ],
-)
-
-iree_runtime_cc_library(
- name = "memory_stream",
- srcs = ["memory_stream.c"],
- hdrs = ["memory_stream.h"],
- deps = [
- ":stream",
"//runtime/src/iree/base",
"//runtime/src/iree/base/internal",
],
@@ -39,7 +26,7 @@
name = "memory_stream_test",
srcs = ["memory_stream_test.cc"],
deps = [
- ":memory_stream",
+ ":stream",
"//runtime/src/iree/base",
"//runtime/src/iree/testing:gtest",
"//runtime/src/iree/testing:gtest_main",
@@ -93,32 +80,21 @@
)
iree_runtime_cc_library(
- name = "stdio_stream",
- srcs = ["stdio_stream.c"],
- hdrs = ["stdio_stream.h"],
- deps = [
- ":stream",
- "//runtime/src/iree/base",
- "//runtime/src/iree/base/internal",
- ],
-)
-
-iree_runtime_cc_library(
name = "stream",
- srcs = ["stream.c"],
- hdrs = ["stream.h"],
- deps = [
- "//runtime/src/iree/base",
- "//runtime/src/iree/base/internal",
+ srcs = [
+ "memory_stream.c",
+ "stdio_stream.c",
+ "stream.c",
+ "vec_stream.c",
],
-)
-
-iree_runtime_cc_library(
- name = "vec_stream",
- srcs = ["vec_stream.c"],
- hdrs = ["vec_stream.h"],
+ hdrs = [
+ "memory_stream.h",
+ "stdio_stream.h",
+ "stream.h",
+ "vec_stream.h",
+ ],
deps = [
- ":stream",
+ ":file_handle",
"//runtime/src/iree/base",
"//runtime/src/iree/base/internal",
],
@@ -128,7 +104,7 @@
name = "vec_stream_test",
srcs = ["vec_stream_test.cc"],
deps = [
- ":vec_stream",
+ ":stream",
"//runtime/src/iree/base",
"//runtime/src/iree/testing:gtest",
"//runtime/src/iree/testing:gtest_main",
diff --git a/runtime/src/iree/io/CMakeLists.txt b/runtime/src/iree/io/CMakeLists.txt
index cf4fd9f..b6ad802 100644
--- a/runtime/src/iree/io/CMakeLists.txt
+++ b/runtime/src/iree/io/CMakeLists.txt
@@ -18,22 +18,6 @@
SRCS
"file_handle.c"
DEPS
- ::memory_stream
- ::stream
- iree::base
- iree::base::internal
- PUBLIC
-)
-
-iree_cc_library(
- NAME
- memory_stream
- HDRS
- "memory_stream.h"
- SRCS
- "memory_stream.c"
- DEPS
- ::stream
iree::base
iree::base::internal
PUBLIC
@@ -45,7 +29,7 @@
SRCS
"memory_stream_test.cc"
DEPS
- ::memory_stream
+ ::stream
iree::base
iree::testing::gtest
iree::testing::gtest_main
@@ -111,40 +95,19 @@
iree_cc_library(
NAME
- stdio_stream
- HDRS
- "stdio_stream.h"
- SRCS
- "stdio_stream.c"
- DEPS
- ::stream
- iree::base
- iree::base::internal
- PUBLIC
-)
-
-iree_cc_library(
- NAME
stream
HDRS
+ "memory_stream.h"
+ "stdio_stream.h"
"stream.h"
- SRCS
- "stream.c"
- DEPS
- iree::base
- iree::base::internal
- PUBLIC
-)
-
-iree_cc_library(
- NAME
- vec_stream
- HDRS
"vec_stream.h"
SRCS
+ "memory_stream.c"
+ "stdio_stream.c"
+ "stream.c"
"vec_stream.c"
DEPS
- ::stream
+ ::file_handle
iree::base
iree::base::internal
PUBLIC
@@ -156,7 +119,7 @@
SRCS
"vec_stream_test.cc"
DEPS
- ::vec_stream
+ ::stream
iree::base
iree::testing::gtest
iree::testing::gtest_main
diff --git a/runtime/src/iree/io/file_handle.c b/runtime/src/iree/io/file_handle.c
index 9a6727b..22d9d80 100644
--- a/runtime/src/iree/io/file_handle.c
+++ b/runtime/src/iree/io/file_handle.c
@@ -7,7 +7,6 @@
#include "iree/io/file_handle.h"
#include "iree/base/internal/atomics.h"
-#include "iree/io/memory_stream.h"
#if IREE_FILE_IO_ENABLE
#if defined(IREE_PLATFORM_WINDOWS)
@@ -644,7 +643,7 @@
return iree_make_status(iree_status_code_from_win32_error(GetLastError()),
"failed to query file handle information");
}
- const uint64_t file_size = file_info.AllocationSize.QuadPart;
+ const uint64_t file_size = file_info.EndOfFile.QuadPart;
// Validate and adjust view size if needed.
iree_host_size_t adjusted_length = 0;
@@ -887,91 +886,3 @@
IREE_ASSERT_ARGUMENT(mapping);
return mapping->contents;
}
-
-//===----------------------------------------------------------------------===//
-// iree_io_stream_t utilities
-//===----------------------------------------------------------------------===//
-
-static void iree_io_memory_stream_file_release(void* user_data,
- iree_io_stream_t* stream) {
- iree_io_file_handle_t* file_handle = (iree_io_file_handle_t*)user_data;
- iree_io_file_handle_release(file_handle);
-}
-
-IREE_API_EXPORT iree_status_t iree_io_stream_open(
- iree_io_stream_mode_t mode, iree_io_file_handle_t* file_handle,
- uint64_t file_offset, iree_allocator_t host_allocator,
- iree_io_stream_t** out_stream) {
- IREE_ASSERT_ARGUMENT(file_handle);
- IREE_ASSERT_ARGUMENT(out_stream);
- *out_stream = NULL;
- IREE_TRACE_ZONE_BEGIN(z0);
-
- iree_status_t status = iree_ok_status();
- iree_io_stream_t* stream = NULL;
- iree_io_file_handle_primitive_t file_primitive =
- iree_io_file_handle_primitive(file_handle);
- switch (file_primitive.type) {
- case IREE_IO_FILE_HANDLE_TYPE_HOST_ALLOCATION: {
- if (file_offset > file_primitive.value.host_allocation.data_length) {
- status = iree_make_status(
- IREE_STATUS_OUT_OF_RANGE,
- "file offset %" PRIu64
- " out of range of host allocation with %" PRIhsz " bytes available",
- file_offset, file_primitive.value.host_allocation.data_length);
- break;
- }
- iree_io_stream_release_callback_t release_callback = {
- .fn = iree_io_memory_stream_file_release,
- .user_data = file_handle,
- };
- iree_io_file_handle_retain(file_handle);
- status = iree_io_memory_stream_wrap(
- mode,
- iree_make_byte_span(
- file_primitive.value.host_allocation.data + file_offset,
- file_primitive.value.host_allocation.data_length - file_offset),
- release_callback, host_allocator, &stream);
- if (!iree_status_is_ok(status)) iree_io_file_handle_release(file_handle);
- break;
- }
- default: {
- status =
- iree_make_status(IREE_STATUS_UNIMPLEMENTED,
- "stream open not yet supported on handle type %d",
- (int)file_primitive.type);
- break;
- }
- }
-
- if (iree_status_is_ok(status)) {
- *out_stream = stream;
- } else {
- iree_io_stream_release(stream);
- }
- IREE_TRACE_ZONE_END(z0);
- return status;
-}
-
-IREE_API_EXPORT iree_status_t iree_io_stream_write_file(
- iree_io_stream_t* stream, iree_io_file_handle_t* source_file_handle,
- uint64_t source_file_offset, iree_io_stream_pos_t length,
- iree_allocator_t host_allocator) {
- IREE_ASSERT_ARGUMENT(stream);
- IREE_ASSERT_ARGUMENT(source_file_handle);
- IREE_TRACE_ZONE_BEGIN(z0);
- IREE_TRACE_ZONE_APPEND_VALUE_I64(z0, (int64_t)length);
-
- iree_io_stream_t* source_stream = NULL;
- IREE_RETURN_AND_END_ZONE_IF_ERROR(
- z0,
- iree_io_stream_open(IREE_IO_STREAM_MODE_READABLE, source_file_handle,
- source_file_offset, host_allocator, &source_stream));
-
- iree_status_t status = iree_io_stream_copy(source_stream, stream, length);
-
- iree_io_stream_release(source_stream);
-
- IREE_TRACE_ZONE_END(z0);
- return status;
-}
diff --git a/runtime/src/iree/io/file_handle.h b/runtime/src/iree/io/file_handle.h
index 908f1e7..ba2f81b 100644
--- a/runtime/src/iree/io/file_handle.h
+++ b/runtime/src/iree/io/file_handle.h
@@ -10,7 +10,6 @@
#include <stdint.h>
#include "iree/base/api.h"
-#include "iree/io/stream.h"
#ifdef __cplusplus
extern "C" {
@@ -308,28 +307,6 @@
IREE_API_EXPORT iree_byte_span_t
iree_io_file_mapping_contents_rw(iree_io_file_mapping_t* mapping);
-//===----------------------------------------------------------------------===//
-// iree_io_stream_t utilities
-//===----------------------------------------------------------------------===//
-
-// TODO(benvanik): remove/rework iree_io_stream_open so that it doesn't pull in
-// any implementations by putting callbacks on the file handle constructors.
-
-// Opens a stream from the given |file_handle| at the absolute |file_offset|.
-// The returned stream will retain the file until it is released.
-IREE_API_EXPORT iree_status_t iree_io_stream_open(
- iree_io_stream_mode_t mode, iree_io_file_handle_t* file_handle,
- uint64_t file_offset, iree_allocator_t host_allocator,
- iree_io_stream_t** out_stream);
-
-// Writes up to |length| bytes of |source_file_handle| starting at offset
-// |source_file_offset| to the target |stream|. |host_allocator| may be used
-// for transient allocations required during file I/O.
-IREE_API_EXPORT iree_status_t iree_io_stream_write_file(
- iree_io_stream_t* stream, iree_io_file_handle_t* source_file_handle,
- uint64_t source_file_offset, iree_io_stream_pos_t length,
- iree_allocator_t host_allocator);
-
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
diff --git a/runtime/src/iree/io/stdio_stream.c b/runtime/src/iree/io/stdio_stream.c
index b190585..b26362c 100644
--- a/runtime/src/iree/io/stdio_stream.c
+++ b/runtime/src/iree/io/stdio_stream.c
@@ -17,13 +17,21 @@
#define IREE_SET_BINARY_MODE(handle) _setmode(_fileno(handle), O_BINARY)
+#define iree_dup _dup
+#define iree_close _close
+
#define iree_fseek _fseeki64
#define iree_ftell _ftelli64
#else
+#include <unistd.h>
+
#define IREE_SET_BINARY_MODE(handle) ((void)0)
+#define iree_dup dup
+#define iree_close close
+
#if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L
#define iree_fseek fseeko
#define iree_ftell ftello
@@ -91,6 +99,52 @@
}
#if IREE_FILE_IO_ENABLE
+
+// Populates the |out_fopen_mode| string for use with fopen-like calls based on
+// the iree_io_stdio_stream_mode_t bitmap.
+//
+// NOTE: not all implementations support all mode flags and this may have
+// different behavior. We should paper over it here but don't today given the
+// limited usage of this and our intent to rewrite it all using
+// platform-optimal APIs instead of stdio.
+static void iree_io_map_stdio_fopen_mode(iree_io_stdio_stream_mode_t stdio_mode,
+ char out_fopen_mode[16]) {
+ memset(out_fopen_mode, 0, 16);
+
+ if (iree_all_bits_set(stdio_mode, IREE_IO_STDIO_STREAM_MODE_READ |
+ IREE_IO_STDIO_STREAM_MODE_WRITE |
+ IREE_IO_STDIO_STREAM_MODE_APPEND)) {
+ strcat(out_fopen_mode, "a+");
+ } else if (iree_all_bits_set(stdio_mode,
+ IREE_IO_STDIO_STREAM_MODE_READ |
+ IREE_IO_STDIO_STREAM_MODE_WRITE |
+ IREE_IO_STDIO_STREAM_MODE_DISCARD)) {
+ strcat(out_fopen_mode, "w+");
+ } else if (iree_all_bits_set(stdio_mode,
+ IREE_IO_STDIO_STREAM_MODE_READ |
+ IREE_IO_STDIO_STREAM_MODE_WRITE)) {
+ strcat(out_fopen_mode, "r+");
+ } else if (iree_all_bits_set(stdio_mode,
+ IREE_IO_STDIO_STREAM_MODE_WRITE |
+ IREE_IO_STDIO_STREAM_MODE_APPEND)) {
+ strcat(out_fopen_mode, "a");
+ } else if (iree_all_bits_set(stdio_mode, IREE_IO_STDIO_STREAM_MODE_WRITE)) {
+ strcat(out_fopen_mode, "w");
+ } else if (iree_all_bits_set(stdio_mode, IREE_IO_STDIO_STREAM_MODE_READ)) {
+ strcat(out_fopen_mode, "r");
+ }
+ if (iree_all_bits_set(stdio_mode, IREE_IO_STDIO_STREAM_MODE_WRITE) &&
+ !iree_all_bits_set(stdio_mode, IREE_IO_STDIO_STREAM_MODE_DISCARD)) {
+ // If writable and not discard then the file must not exist.
+ // TODO(benvanik): actually observe this; the C11 spec says `x` is supported
+ // but at least on MSVC's CRT it isn't. We can emulate this with stat and
+ // such but today we don't have any uses that require it.
+ // strcat(out_fopen_mode, "x");
+ }
+ // Force binary mode (avoid Windows CRLF expansion).
+ strcat(out_fopen_mode, "b");
+}
+
IREE_API_EXPORT iree_status_t iree_io_stdio_stream_open(
iree_io_stdio_stream_mode_t mode, iree_string_view_t path,
iree_allocator_t host_allocator, iree_io_stream_t** out_stream) {
@@ -107,40 +161,8 @@
stream_mode |= IREE_IO_STREAM_MODE_WRITABLE;
}
- // NOTE: not all implementations support all mode flags and this may have
- // different behavior. We should paper over it here but don't today given the
- // limited usage of this and our intent to rewrite it all using
- // platform-optimal APIs instead of stdio.
char fopen_mode[16] = {0};
- if (iree_all_bits_set(mode, IREE_IO_STDIO_STREAM_MODE_READ |
- IREE_IO_STDIO_STREAM_MODE_WRITE |
- IREE_IO_STDIO_STREAM_MODE_APPEND)) {
- strcat(fopen_mode, "a+");
- } else if (iree_all_bits_set(mode, IREE_IO_STDIO_STREAM_MODE_READ |
- IREE_IO_STDIO_STREAM_MODE_WRITE |
- IREE_IO_STDIO_STREAM_MODE_DISCARD)) {
- strcat(fopen_mode, "w+");
- } else if (iree_all_bits_set(mode, IREE_IO_STDIO_STREAM_MODE_READ |
- IREE_IO_STDIO_STREAM_MODE_WRITE)) {
- strcat(fopen_mode, "r+");
- } else if (iree_all_bits_set(mode, IREE_IO_STDIO_STREAM_MODE_WRITE |
- IREE_IO_STDIO_STREAM_MODE_APPEND)) {
- strcat(fopen_mode, "a");
- } else if (iree_all_bits_set(mode, IREE_IO_STDIO_STREAM_MODE_WRITE)) {
- strcat(fopen_mode, "w");
- } else if (iree_all_bits_set(mode, IREE_IO_STDIO_STREAM_MODE_READ)) {
- strcat(fopen_mode, "r");
- }
- if (iree_all_bits_set(stream_mode, IREE_IO_STREAM_MODE_WRITABLE) &&
- !iree_all_bits_set(mode, IREE_IO_STDIO_STREAM_MODE_DISCARD)) {
- // If writable and not discard then the file must not exist.
- // TODO(benvanik): actually observe this; the C11 spec says `x` is supported
- // but at least on MSVC's CRT it isn't. We can emulate this with stat and
- // such but today we don't have any uses that require it.
- // strcat(fopen_mode, "x");
- }
- // Force binary mode (avoid Windows CRLF expansion).
- strcat(fopen_mode, "b");
+ iree_io_map_stdio_fopen_mode(mode, fopen_mode);
// Since we stack alloc the path we want to keep it reasonable.
// We could heap allocate instead but a few thousand chars is quite long and
@@ -188,7 +210,70 @@
IREE_TRACE_ZONE_END(z0);
return status;
}
+
+IREE_API_EXPORT iree_status_t iree_io_stdio_stream_open_fd(
+ iree_io_stdio_stream_mode_t mode, int fd, iree_allocator_t host_allocator,
+ iree_io_stream_t** out_stream) {
+ IREE_ASSERT_ARGUMENT(out_stream);
+ *out_stream = NULL;
+ IREE_TRACE_ZONE_BEGIN(z0);
+
+ // Duplicate the file descriptor so that we have our own copy of the seek
+ // position. The initial position will be preserved.
+ int dup_fd = iree_dup(fd);
+ if (dup_fd == -1) {
+ IREE_TRACE_ZONE_END(z0);
+ return iree_make_stdio_status(
+ "unable to duplicate file descriptor; possibly out of file descriptors "
+ "(see ulimit)");
+ }
+
+ iree_io_stream_mode_t stream_mode = IREE_IO_STREAM_MODE_SEEKABLE;
+ if (iree_all_bits_set(mode, IREE_IO_STDIO_STREAM_MODE_READ)) {
+ stream_mode |= IREE_IO_STREAM_MODE_READABLE;
+ }
+ if (iree_all_bits_set(mode, IREE_IO_STDIO_STREAM_MODE_WRITE)) {
+ stream_mode |= IREE_IO_STREAM_MODE_WRITABLE;
+ }
+
+ char fopen_mode[16] = {0};
+ iree_io_map_stdio_fopen_mode(mode, fopen_mode);
+
+ // NOTE: after this point the file handle is associated with dup_fd and
+ // anything we do to it (like closing) will apply to the dup_fd.
+ iree_status_t status = iree_ok_status();
+ FILE* handle = fdopen(dup_fd, fopen_mode);
+ if (handle == NULL) {
+ status = iree_make_stdio_statusf(
+ "unable to open file descriptor with mode %d", mode);
+ }
+
+ // Ownership of the handle (and the dup_fd backing it) is transferred.
+ iree_io_stream_t* stream = NULL;
+ if (iree_status_is_ok(status)) {
+ status = iree_io_stdio_stream_wrap(
+ stream_mode, handle, /*owns_handle=*/true, host_allocator, &stream);
+ }
+
+ if (iree_status_is_ok(status)) {
+ *out_stream = stream;
+ } else {
+ if (stream) {
+ // NOTE: closes the file handle/dup_fd.
+ iree_io_stream_release(stream);
+ } else if (handle) {
+ // NOTE: closes the dup_fd.
+ fclose(handle);
+ } else if (dup_fd > 0) {
+ iree_close(dup_fd);
+ }
+ }
+ IREE_TRACE_ZONE_END(z0);
+ return status;
+}
+
#else
+
IREE_API_EXPORT iree_status_t iree_io_stdio_stream_open(
iree_io_stdio_stream_mode_t mode, iree_string_view_t path,
iree_allocator_t host_allocator, iree_io_stream_t** out_stream) {
@@ -196,6 +281,15 @@
"file support has been compiled out of this binary; "
"set IREE_FILE_IO_ENABLE=1 to include it");
}
+
+IREE_API_EXPORT iree_status_t iree_io_stdio_stream_open_fd(
+ iree_io_stdio_stream_mode_t mode, int fd, iree_allocator_t host_allocator,
+ iree_io_stream_t** out_stream) {
+ return iree_make_status(IREE_STATUS_UNAVAILABLE,
+ "file support has been compiled out of this binary; "
+ "set IREE_FILE_IO_ENABLE=1 to include it");
+}
+
#endif // IREE_FILE_IO_ENABLE
static void iree_io_stdio_stream_destroy(
@@ -297,16 +391,16 @@
// reads in one go anyway.
iree_host_size_t bytes_read = 0;
while (bytes_read < buffer_capacity) {
- iree_host_size_t chunk_size =
+ const iree_host_size_t chunk_size =
iree_min(buffer_capacity - bytes_read, INT_MAX);
- iree_host_size_t read_size =
+ const iree_host_size_t read_size =
fread((uint8_t*)buffer + bytes_read, 1, chunk_size, stream->handle);
if (read_size != chunk_size) {
// Failed to read chunk - may have reached EOF.
if (feof(stream->handle)) {
if (out_buffer_length) {
// Ok to hit EOF; just return what's valid.
- *out_buffer_length = bytes_read + read_size;
+ bytes_read += read_size;
} else {
status = iree_make_status(IREE_STATUS_OUT_OF_RANGE,
"end-of-file encountered during read");
@@ -319,6 +413,9 @@
bytes_read += read_size;
}
+ if (out_buffer_length) {
+ *out_buffer_length = bytes_read;
+ }
IREE_TRACE_ZONE_END(z0);
return status;
}
diff --git a/runtime/src/iree/io/stdio_stream.h b/runtime/src/iree/io/stdio_stream.h
index ddb2773..aef08ef 100644
--- a/runtime/src/iree/io/stdio_stream.h
+++ b/runtime/src/iree/io/stdio_stream.h
@@ -51,6 +51,13 @@
iree_io_stdio_stream_mode_t mode, iree_string_view_t path,
iree_allocator_t host_allocator, iree_io_stream_t** out_stream);
+// Opens a file descriptor |fd| using fdopen with the mode determined by |mode|.
+// The file descriptor is duplicated and seeking the stream will not be visible
+// with any other users of the file descriptor.
+IREE_API_EXPORT iree_status_t iree_io_stdio_stream_open_fd(
+ iree_io_stdio_stream_mode_t mode, int fd, iree_allocator_t host_allocator,
+ iree_io_stream_t** out_stream);
+
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
diff --git a/runtime/src/iree/io/stream.c b/runtime/src/iree/io/stream.c
index 09efdca..5e021d4 100644
--- a/runtime/src/iree/io/stream.c
+++ b/runtime/src/iree/io/stream.c
@@ -6,6 +6,10 @@
#include "iree/io/stream.h"
+#include "iree/io/file_handle.h"
+#include "iree/io/memory_stream.h"
+#include "iree/io/stdio_stream.h"
+
// This is arbitrary - we should allow dynamic block sizes and such but keeping
// this small only requires a reasonable fixed size stack alloc.
#define IREE_IO_STREAM_COPY_BLOCK_SIZE (32 * 1024)
@@ -298,3 +302,107 @@
IREE_TRACE_ZONE_END(z0);
return status;
}
+
+//===----------------------------------------------------------------------===//
+// iree_io_stream_t utilities
+//===----------------------------------------------------------------------===//
+
+static void iree_io_memory_stream_file_release(void* user_data,
+ iree_io_stream_t* stream) {
+ iree_io_file_handle_t* file_handle = (iree_io_file_handle_t*)user_data;
+ iree_io_file_handle_release(file_handle);
+}
+
+IREE_API_EXPORT iree_status_t iree_io_stream_open(
+ iree_io_stream_mode_t mode, iree_io_file_handle_t* file_handle,
+ uint64_t file_offset, iree_allocator_t host_allocator,
+ iree_io_stream_t** out_stream) {
+ IREE_ASSERT_ARGUMENT(file_handle);
+ IREE_ASSERT_ARGUMENT(out_stream);
+ *out_stream = NULL;
+ IREE_TRACE_ZONE_BEGIN(z0);
+
+ iree_status_t status = iree_ok_status();
+ iree_io_stream_t* stream = NULL;
+ iree_io_file_handle_primitive_t file_primitive =
+ iree_io_file_handle_primitive(file_handle);
+ switch (file_primitive.type) {
+ case IREE_IO_FILE_HANDLE_TYPE_HOST_ALLOCATION: {
+ if (file_offset > file_primitive.value.host_allocation.data_length) {
+ status = iree_make_status(
+ IREE_STATUS_OUT_OF_RANGE,
+ "file offset %" PRIu64
+ " out of range of host allocation with %" PRIhsz " bytes available",
+ file_offset, file_primitive.value.host_allocation.data_length);
+ break;
+ }
+ iree_io_stream_release_callback_t release_callback = {
+ .fn = iree_io_memory_stream_file_release,
+ .user_data = file_handle,
+ };
+ iree_io_file_handle_retain(file_handle);
+ status = iree_io_memory_stream_wrap(
+ mode,
+ iree_make_byte_span(
+ file_primitive.value.host_allocation.data + file_offset,
+ file_primitive.value.host_allocation.data_length - file_offset),
+ release_callback, host_allocator, &stream);
+ if (!iree_status_is_ok(status)) iree_io_file_handle_release(file_handle);
+ break;
+ }
+ case IREE_IO_FILE_HANDLE_TYPE_FD: {
+ iree_io_stdio_stream_mode_t stdio_mode = 0;
+ if (iree_all_bits_set(mode, IREE_IO_STREAM_MODE_READABLE)) {
+ stdio_mode |= IREE_IO_STDIO_STREAM_MODE_READ;
+ }
+ if (iree_all_bits_set(mode, IREE_IO_STREAM_MODE_WRITABLE)) {
+ stdio_mode |= IREE_IO_STDIO_STREAM_MODE_WRITE;
+ }
+ status = iree_io_stdio_stream_open_fd(stdio_mode, file_primitive.value.fd,
+ host_allocator, &stream);
+ if (iree_status_is_ok(status)) {
+ status =
+ iree_io_stream_seek(stream, IREE_IO_STREAM_SEEK_SET, file_offset);
+ }
+ break;
+ }
+ default: {
+ status =
+ iree_make_status(IREE_STATUS_UNIMPLEMENTED,
+ "stream open not yet supported on handle type %d",
+ (int)file_primitive.type);
+ break;
+ }
+ }
+
+ if (iree_status_is_ok(status)) {
+ *out_stream = stream;
+ } else {
+ iree_io_stream_release(stream);
+ }
+ IREE_TRACE_ZONE_END(z0);
+ return status;
+}
+
+IREE_API_EXPORT iree_status_t iree_io_stream_write_file(
+ iree_io_stream_t* stream, iree_io_file_handle_t* source_file_handle,
+ uint64_t source_file_offset, iree_io_stream_pos_t length,
+ iree_allocator_t host_allocator) {
+ IREE_ASSERT_ARGUMENT(stream);
+ IREE_ASSERT_ARGUMENT(source_file_handle);
+ IREE_TRACE_ZONE_BEGIN(z0);
+ IREE_TRACE_ZONE_APPEND_VALUE_I64(z0, (int64_t)length);
+
+ iree_io_stream_t* source_stream = NULL;
+ IREE_RETURN_AND_END_ZONE_IF_ERROR(
+ z0,
+ iree_io_stream_open(IREE_IO_STREAM_MODE_READABLE, source_file_handle,
+ source_file_offset, host_allocator, &source_stream));
+
+ iree_status_t status = iree_io_stream_copy(source_stream, stream, length);
+
+ iree_io_stream_release(source_stream);
+
+ IREE_TRACE_ZONE_END(z0);
+ return status;
+}
diff --git a/runtime/src/iree/io/stream.h b/runtime/src/iree/io/stream.h
index 5cf0979..3265b93 100644
--- a/runtime/src/iree/io/stream.h
+++ b/runtime/src/iree/io/stream.h
@@ -16,6 +16,8 @@
extern "C" {
#endif // __cplusplus
+typedef struct iree_io_file_handle_t iree_io_file_handle_t;
+
//===----------------------------------------------------------------------===//
// iree_io_stream_t
//===----------------------------------------------------------------------===//
@@ -155,7 +157,7 @@
iree_io_stream_pos_t length);
//===----------------------------------------------------------------------===//
-// Lifetime management utilities
+// iree_io_stream_t utilities
//===----------------------------------------------------------------------===//
typedef void(IREE_API_PTR* iree_io_stream_release_fn_t)(
@@ -177,6 +179,27 @@
return callback;
}
+// TODO(benvanik): remove/rework iree_io_stream_open so that it doesn't pull in
+// any implementations by putting callbacks on the file handle constructors.
+// Today this requires we link the stream implementations we support into the
+// same library and that users wanting to add their own may only open them
+// explicitly. That may end up being sufficient.
+
+// Opens a stream from the given |file_handle| at the absolute |file_offset|.
+// The returned stream will retain the file until it is released.
+IREE_API_EXPORT iree_status_t iree_io_stream_open(
+ iree_io_stream_mode_t mode, iree_io_file_handle_t* file_handle,
+ uint64_t file_offset, iree_allocator_t host_allocator,
+ iree_io_stream_t** out_stream);
+
+// Writes up to |length| bytes of |source_file_handle| starting at offset
+// |source_file_offset| to the target |stream|. |host_allocator| may be used
+// for transient allocations required during file I/O.
+IREE_API_EXPORT iree_status_t iree_io_stream_write_file(
+ iree_io_stream_t* stream, iree_io_file_handle_t* source_file_handle,
+ uint64_t source_file_offset, iree_io_stream_pos_t length,
+ iree_allocator_t host_allocator);
+
//===----------------------------------------------------------------------===//
// iree_io_stream_t implementation details
//===----------------------------------------------------------------------===//
diff --git a/runtime/src/iree/tooling/BUILD.bazel b/runtime/src/iree/tooling/BUILD.bazel
index 39aed05..6b33185 100644
--- a/runtime/src/iree/tooling/BUILD.bazel
+++ b/runtime/src/iree/tooling/BUILD.bazel
@@ -115,9 +115,7 @@
":numpy_io",
"//runtime/src/iree/base",
"//runtime/src/iree/hal",
- "//runtime/src/iree/io:stdio_stream",
"//runtime/src/iree/io:stream",
- "//runtime/src/iree/io:vec_stream",
"//runtime/src/iree/modules/hal",
"//runtime/src/iree/vm",
],
@@ -130,7 +128,7 @@
":function_io",
"//runtime/src/iree/base",
"//runtime/src/iree/hal",
- "//runtime/src/iree/io:vec_stream",
+ "//runtime/src/iree/io:stream",
"//runtime/src/iree/modules/hal",
"//runtime/src/iree/testing:gtest",
"//runtime/src/iree/testing:gtest_main",
@@ -182,8 +180,7 @@
deps = [
":device_util",
":numpy_io",
- "//runtime/src/iree/io:memory_stream",
- "//runtime/src/iree/io:vec_stream",
+ "//runtime/src/iree/io:stream",
"//runtime/src/iree/testing:gtest",
"//runtime/src/iree/testing:gtest_main",
"//runtime/src/iree/tooling/testdata/npy",
@@ -223,7 +220,7 @@
"//runtime/src/iree/base",
"//runtime/src/iree/base/internal:flags",
"//runtime/src/iree/hal",
- "//runtime/src/iree/io:stdio_stream",
+ "//runtime/src/iree/io:stream",
"//runtime/src/iree/modules/hal:types",
"//runtime/src/iree/vm",
"//runtime/src/iree/vm/bytecode:module",
diff --git a/runtime/src/iree/tooling/CMakeLists.txt b/runtime/src/iree/tooling/CMakeLists.txt
index 451b3f8..1c1458f 100644
--- a/runtime/src/iree/tooling/CMakeLists.txt
+++ b/runtime/src/iree/tooling/CMakeLists.txt
@@ -130,9 +130,7 @@
::numpy_io
iree::base
iree::hal
- iree::io::stdio_stream
iree::io::stream
- iree::io::vec_stream
iree::modules::hal
iree::vm
PUBLIC
@@ -147,7 +145,7 @@
::function_io
iree::base
iree::hal
- iree::io::vec_stream
+ iree::io::stream
iree::modules::hal
iree::testing::gtest
iree::testing::gtest_main
@@ -208,8 +206,7 @@
DEPS
::device_util
::numpy_io
- iree::io::memory_stream
- iree::io::vec_stream
+ iree::io::stream
iree::testing::gtest
iree::testing::gtest_main
iree::tooling::testdata::npy
@@ -256,7 +253,7 @@
iree::base
iree::base::internal::flags
iree::hal
- iree::io::stdio_stream
+ iree::io::stream
iree::modules::hal::types
iree::vm
iree::vm::bytecode::module
diff --git a/tools/test/BUILD.bazel b/tools/test/BUILD.bazel
index 9369902..23a64db 100644
--- a/tools/test/BUILD.bazel
+++ b/tools/test/BUILD.bazel
@@ -28,6 +28,7 @@
"executable_sources.mlir",
"iree-benchmark-executable.mlir",
"iree-benchmark-module.mlir",
+ "iree-convert-parameters.txt",
"iree-dump-parameters.txt",
"iree-run-mlir.mlir",
"iree-run-module-expected.mlir",
@@ -62,6 +63,7 @@
"//tools:iree-benchmark-executable",
"//tools:iree-benchmark-module",
"//tools:iree-compile",
+ "//tools:iree-convert-parameters",
"//tools:iree-dump-parameters",
"//tools:iree-opt",
"//tools:iree-run-mlir",
diff --git a/tools/test/CMakeLists.txt b/tools/test/CMakeLists.txt
index f577ec6..9d515d8 100644
--- a/tools/test/CMakeLists.txt
+++ b/tools/test/CMakeLists.txt
@@ -23,6 +23,7 @@
"executable_sources.mlir"
"iree-benchmark-executable.mlir"
"iree-benchmark-module.mlir"
+ "iree-convert-parameters.txt"
"iree-dump-parameters.txt"
"iree-run-mlir.mlir"
"iree-run-module-expected.mlir"
@@ -43,6 +44,7 @@
iree-benchmark-executable
iree-benchmark-module
iree-compile
+ iree-convert-parameters
iree-dump-parameters
iree-opt
iree-run-mlir
diff --git a/tools/test/iree-convert-parameters.txt b/tools/test/iree-convert-parameters.txt
new file mode 100644
index 0000000..338610c
--- /dev/null
+++ b/tools/test/iree-convert-parameters.txt
@@ -0,0 +1,12 @@
+// RUN: (iree-convert-parameters \
+// RUN: --parameters=a=%p/parameters_a.safetensors \
+// RUN: --parameters=b=%p/parameters_b.safetensors \
+// RUN: --output=%t.irpa && \
+// RUN: iree-dump-parameters --parameters=%t.irpa) | \
+// RUN: FileCheck %s
+
+// CHECK: Parameter scope <global> (4 entries, 256 total bytes)
+// CHECK: 448 | 480 | 32 | `a0`
+// CHECK: 512 | 544 | 32 | `a1`
+// CHECK: 576 | 640 | 64 | `b0`
+// CHECK: 640 | 768 | 128 | `b1`