diff --git a/.gitmodules b/.gitmodules index 98ae1b00b750..2437417252d3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,3 +37,6 @@ [submodule "third_party/hsa-runtime-headers"] path = third_party/hsa-runtime-headers url = https://github.com/iree-org/hsa-runtime-headers.git +[submodule "third_party/printf"] + path = third_party/printf + url = https://github.com/eyalroz/printf.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c157b803b8b..08dce43a5be9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1042,6 +1042,9 @@ if(IREE_ENABLE_CPUINFO) endif() endif() +# Platform-independent printf implementation (eyalroz/printf). +add_subdirectory(build_tools/third_party/printf EXCLUDE_FROM_ALL) + # This defines the iree-flatcc-cli target, so we don't use EXCLUDE_FROM_ALL. add_subdirectory(build_tools/third_party/flatcc) diff --git a/MODULE.bazel b/MODULE.bazel index eb3defe19e7e..b4166d476795 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -80,6 +80,7 @@ use_repo( "iree_cuda", "llvm-raw", "nccl", + "printf_lib", "rccl", "spirv_cross", "stablehlo", diff --git a/build_tools/bazel/extensions.bzl b/build_tools/bazel/extensions.bzl index 1c2e2150110a..32696f73867c 100644 --- a/build_tools/bazel/extensions.bzl +++ b/build_tools/bazel/extensions.bzl @@ -96,6 +96,13 @@ def _iree_extension_impl(module_ctx): path = "third_party/rccl", ) + # eyalroz/printf (platform-independent printf implementation) + new_local_repository( + name = "printf_lib", + build_file = "@iree_core//:build_tools/third_party/printf/BUILD.overlay", + path = "third_party/printf", + ) + # WebGPU headers new_local_repository( name = "webgpu_headers", diff --git a/build_tools/bazel_to_cmake/bazel_to_cmake_targets.py b/build_tools/bazel_to_cmake/bazel_to_cmake_targets.py index fbe8a4171619..050a82166002 100644 --- a/build_tools/bazel_to_cmake/bazel_to_cmake_targets.py +++ b/build_tools/bazel_to_cmake/bazel_to_cmake_targets.py @@ -119,6 +119,7 @@ def __init__(self, repo_map: Dict[str, str]): "@vulkan_headers": ["Vulkan::Headers"], # Misc single targets "@com_google_benchmark//:benchmark": ["benchmark"], + "@printf_lib//:printf": ["printf::printf"], "@com_github_dvidelabs_flatcc//:flatcc": ["flatcc"], "@com_github_dvidelabs_flatcc//:parsing": ["flatcc::parsing"], "@com_github_dvidelabs_flatcc//:runtime": ["flatcc::runtime"], diff --git a/build_tools/cmake/linux_riscv64.cmake b/build_tools/cmake/linux_riscv64.cmake index c7a95f4f3b74..6f33aefdd93e 100644 --- a/build_tools/cmake/linux_riscv64.cmake +++ b/build_tools/cmake/linux_riscv64.cmake @@ -26,6 +26,22 @@ if(NOT "${RISCV_TOOLCHAIN_ROOT}" STREQUAL "") set(CMAKE_RANLIB "${RISCV_TOOLCHAIN_ROOT}/bin/${RISCV_TOOLCHAIN_PREFIX}llvm-ranlib") set(CMAKE_STRIP "${RISCV_TOOLCHAIN_ROOT}/bin/${RISCV_TOOLCHAIN_PREFIX}llvm-strip") set(CMAKE_SYSROOT "${RISCV_TOOLCHAIN_ROOT}/sysroot") + # Strip debug info from libgcc.a to work around LLD incompatibility. The + # GCC 12.2.0-compiled libgcc.a contains DWARF debug info with relocations + # that LLD cannot parse (unknown relocation types 60/61 in .debug_rnglists + # and .debug_loclists sections). Code and data sections are unaffected; + # only debug metadata is removed. This is idempotent. + file(GLOB_RECURSE _LIBGCC_ARCHIVES "${RISCV_TOOLCHAIN_ROOT}/lib/gcc/*/libgcc.a") + foreach(_LIBGCC IN LISTS _LIBGCC_ARCHIVES) + execute_process( + COMMAND "${RISCV_TOOLCHAIN_ROOT}/bin/${RISCV_TOOLCHAIN_PREFIX}llvm-objcopy" + --strip-debug "${_LIBGCC}" + RESULT_VARIABLE _strip_result + ) + if(NOT _strip_result EQUAL 0) + message(WARNING "Failed to strip debug from ${_LIBGCC}") + endif() + endforeach() endif() # Specify ISA spec for march=rv64gc. This is to resolve the mismatch between diff --git a/build_tools/scripts/git/runtime_submodules.txt b/build_tools/scripts/git/runtime_submodules.txt index a7dd9c885468..f19de30a0189 100644 --- a/build_tools/scripts/git/runtime_submodules.txt +++ b/build_tools/scripts/git/runtime_submodules.txt @@ -4,6 +4,7 @@ third_party/googletest third_party/hip-build-deps third_party/hsa-runtime-headers third_party/musl +third_party/printf third_party/spirv_cross third_party/tracy third_party/vulkan_headers diff --git a/build_tools/third_party/printf/BUILD.overlay b/build_tools/third_party/printf/BUILD.overlay new file mode 100644 index 000000000000..583f569b1b60 --- /dev/null +++ b/build_tools/third_party/printf/BUILD.overlay @@ -0,0 +1,23 @@ +# Copyright 2026 The IREE Authors +# +# Licensed under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "printf", + srcs = ["src/printf/printf.c"], + hdrs = ["src/printf/printf.h"], + copts = select({ + "@bazel_tools//src/conditions:windows": [], + "//conditions:default": [ + "-Wno-sign-conversion", + ], + }), + local_defines = [ + "PRINTF_SUPPORT_WRITEBACK_SPECIFIER=0", + ], + strip_include_prefix = "src", +) diff --git a/build_tools/third_party/printf/CMakeLists.txt b/build_tools/third_party/printf/CMakeLists.txt new file mode 100644 index 000000000000..9d8ab935be5a --- /dev/null +++ b/build_tools/third_party/printf/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright 2026 The IREE Authors +# +# Licensed under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set(PRINTF_ROOT "${IREE_ROOT_DIR}/third_party/printf/") + +# We don't install any headers because their only use is via the +# iree/base/printf.h wrapper. +set(IREE_HDRS_ROOT_PATH OFF) +# Considered part of the runtime. +set(IREE_INSTALL_LIBRARY_TARGETS_DEFAULT_COMPONENT IREEBundledLibraries) +set(IREE_INSTALL_LIBRARY_TARGETS_DEFAULT_EXPORT_SET Runtime) + +external_cc_library( + PACKAGE + printf + NAME + printf + ROOT + ${PRINTF_ROOT} + INCLUDES + "${PRINTF_ROOT}/src" + SRCS + "src/printf/printf.c" + HDRS + "src/printf/printf.h" + COPTS + "-DPRINTF_SUPPORT_WRITEBACK_SPECIFIER=0" + PUBLIC +) diff --git a/runtime/bindings/python/status_utils.cc b/runtime/bindings/python/status_utils.cc index 46d293c89437..6f7acdd494db 100644 --- a/runtime/bindings/python/status_utils.cc +++ b/runtime/bindings/python/status_utils.cc @@ -29,18 +29,16 @@ PyObject* ApiStatusToPyExcClass(iree_status_t status) { } // namespace std::string ApiStatusToString(iree_status_t status) { - iree_host_size_t buffer_length = 0; - if (IREE_UNLIKELY(!iree_status_format(status, /*buffer_capacity=*/0, - /*buffer=*/NULL, &buffer_length))) { - return ""; - } std::string result; - result.resize(buffer_length); - // NOTE: buffer capacity needs to be +1 for the NUL terminator in snprintf. - return iree_status_format(status, result.size() + 1, - const_cast(result.data()), &buffer_length) - ? result - : ""; + iree_status_format_to( + status, + [](iree_string_view_t chunk, void* user_data) -> bool { + auto* str = static_cast(user_data); + str->append(chunk.data, chunk.size); + return true; + }, + &result); + return result; } nanobind::python_error ApiStatusToPyExc(iree_status_t status, diff --git a/runtime/src/iree/async/cts/socket/lifecycle_test.cc b/runtime/src/iree/async/cts/socket/lifecycle_test.cc index 1a503711fdb0..abd6d944d87d 100644 --- a/runtime/src/iree/async/cts/socket/lifecycle_test.cc +++ b/runtime/src/iree/async/cts/socket/lifecycle_test.cc @@ -662,7 +662,7 @@ TEST_P(SocketTest, MultipleExchanges) { for (int round = 0; round < 3; ++round) { // Prepare send data with round number embedded. char send_data[64]; - snprintf(send_data, sizeof(send_data), "Message round %d", round); + iree_snprintf(send_data, sizeof(send_data), "Message round %d", round); iree_host_size_t send_length = strlen(send_data); iree_async_span_t send_span = iree_async_span_from_ptr((void*)send_data, send_length); diff --git a/runtime/src/iree/async/cts/socket/posix_test.cc b/runtime/src/iree/async/cts/socket/posix_test.cc index 0fe26f611472..4c1a30585cca 100644 --- a/runtime/src/iree/async/cts/socket/posix_test.cc +++ b/runtime/src/iree/async/cts/socket/posix_test.cc @@ -43,8 +43,9 @@ class SocketPosixTest : public SocketTestBase<> { std::string UniqueAbstractName(const char* base_name) { static std::atomic counter{0}; char buffer[108]; // sun_path max - snprintf(buffer, sizeof(buffer), "@iree_cts_%s_%d_%d", base_name, - (int)getpid(), counter.fetch_add(1, std::memory_order_relaxed)); + iree_snprintf(buffer, sizeof(buffer), "@iree_cts_%s_%d_%d", base_name, + (int)getpid(), + counter.fetch_add(1, std::memory_order_relaxed)); return std::string(buffer); } }; diff --git a/runtime/src/iree/async/cts/socket/tcp_transfer_test.cc b/runtime/src/iree/async/cts/socket/tcp_transfer_test.cc index fe9cb61beefa..0cba9abf031f 100644 --- a/runtime/src/iree/async/cts/socket/tcp_transfer_test.cc +++ b/runtime/src/iree/async/cts/socket/tcp_transfer_test.cc @@ -745,7 +745,7 @@ TEST_P(ConcurrentConnectionsTest, ConcurrentConnections_Sequential) { // Verify each connection is independent by sending unique data. for (int i = 0; i < kNumConnections; ++i) { char send_data[32]; - snprintf(send_data, sizeof(send_data), "Connection %d", i); + iree_snprintf(send_data, sizeof(send_data), "Connection %d", i); iree_host_size_t send_length = strlen(send_data); iree_async_span_t send_span = @@ -856,7 +856,7 @@ TEST_P(ConcurrentConnectionsTest, ConcurrentConnections_Parallel) { CompletionTracker recv_trackers[kNumConnections]; for (int i = 0; i < kNumConnections; ++i) { - snprintf(send_data[i], sizeof(send_data[i]), "Parallel %d", i); + iree_snprintf(send_data[i], sizeof(send_data[i]), "Parallel %d", i); send_spans[i] = iree_async_span_from_ptr((void*)send_data[i], strlen(send_data[i])); @@ -975,8 +975,8 @@ TEST_P(ConcurrentConnectionsTest, ConcurrentConnections_Interleaved) { // Submit all sends and recvs for this round. for (int i = 0; i < kNumConnections; ++i) { - snprintf(send_data[i], sizeof(send_data[i]), "Round %d Conn %d", round, - i); + iree_snprintf(send_data[i], sizeof(send_data[i]), "Round %d Conn %d", + round, i); send_spans[i] = iree_async_span_from_ptr((void*)send_data[i], strlen(send_data[i])); @@ -1214,7 +1214,7 @@ TEST_P(ScatterGatherTest, ScatterGather_ManyBuffers) { iree_host_size_t total_length = 0; for (int i = 0; i < kNumBuffers; ++i) { - snprintf(buffers[i], sizeof(buffers[i]), "[Chunk %d]", i); + iree_snprintf(buffers[i], sizeof(buffers[i]), "[Chunk %d]", i); iree_host_size_t len = strlen(buffers[i]); spans[i] = iree_async_span_from_ptr(buffers[i], len); total_length += len; diff --git a/runtime/src/iree/async/platform/io_uring/proactor.c b/runtime/src/iree/async/platform/io_uring/proactor.c index 6c09296bc2a3..b54c659b3b10 100644 --- a/runtime/src/iree/async/platform/io_uring/proactor.c +++ b/runtime/src/iree/async/platform/io_uring/proactor.c @@ -1605,8 +1605,9 @@ static iree_status_t iree_async_proactor_io_uring_import_file( file->primitive = primitive; file->fixed_file_index = -1; // Not using io_uring fixed files yet. - IREE_TRACE( - { snprintf(file->debug_path, sizeof(file->debug_path), "fd:%d", fd); }); + IREE_TRACE({ + iree_snprintf(file->debug_path, sizeof(file->debug_path), "fd:%d", fd); + }); *out_file = file; IREE_TRACE_ZONE_END(z0); diff --git a/runtime/src/iree/async/platform/io_uring/socket.c b/runtime/src/iree/async/platform/io_uring/socket.c index 37ade93a930b..42aea4b727eb 100644 --- a/runtime/src/iree/async/platform/io_uring/socket.c +++ b/runtime/src/iree/async/platform/io_uring/socket.c @@ -174,7 +174,8 @@ static void iree_async_socket_initialize( iree_atomic_store(&socket->failure_status, (intptr_t)iree_ok_status(), iree_memory_order_release); IREE_TRACE({ - snprintf(socket->debug_label, sizeof(socket->debug_label), "socket:%d", fd); + iree_snprintf(socket->debug_label, sizeof(socket->debug_label), "socket:%d", + fd); }); } diff --git a/runtime/src/iree/async/platform/iocp/proactor.c b/runtime/src/iree/async/platform/iocp/proactor.c index 99ac0adb9f32..d7fe14058abc 100644 --- a/runtime/src/iree/async/platform/iocp/proactor.c +++ b/runtime/src/iree/async/platform/iocp/proactor.c @@ -1742,9 +1742,10 @@ static iree_status_t iree_async_proactor_iocp_poll( (intptr_t)iree_ok_status(), iree_memory_order_release); IREE_TRACE({ - snprintf(accepted_socket->debug_label, - sizeof(accepted_socket->debug_label), - "accepted:%llu", (unsigned long long)accept_sock); + iree_snprintf(accepted_socket->debug_label, + sizeof(accepted_socket->debug_label), + "accepted:%llu", + (unsigned long long)accept_sock); }); accept_op->accepted_socket = accepted_socket; } else { @@ -2317,8 +2318,8 @@ static iree_status_t iree_async_proactor_iocp_import_file( file->fixed_file_index = -1; IREE_TRACE({ - snprintf(file->debug_path, sizeof(file->debug_path), "handle:%p", - (void*)handle); + iree_snprintf(file->debug_path, sizeof(file->debug_path), "handle:%p", + (void*)handle); }); *out_file = file; diff --git a/runtime/src/iree/async/platform/iocp/socket.c b/runtime/src/iree/async/platform/iocp/socket.c index a8ac333a7746..1dcb80d93c6a 100644 --- a/runtime/src/iree/async/platform/iocp/socket.c +++ b/runtime/src/iree/async/platform/iocp/socket.c @@ -164,8 +164,8 @@ static void iree_async_iocp_socket_initialize( iree_atomic_store(&socket->failure_status, (intptr_t)iree_ok_status(), iree_memory_order_release); IREE_TRACE({ - snprintf(socket->debug_label, sizeof(socket->debug_label), "socket:%llu", - (unsigned long long)sock); + iree_snprintf(socket->debug_label, sizeof(socket->debug_label), + "socket:%llu", (unsigned long long)sock); }); } diff --git a/runtime/src/iree/async/platform/posix/proactor.c b/runtime/src/iree/async/platform/posix/proactor.c index fb5e2df8a957..09c9d19a9191 100644 --- a/runtime/src/iree/async/platform/posix/proactor.c +++ b/runtime/src/iree/async/platform/posix/proactor.c @@ -3124,7 +3124,7 @@ static iree_status_t iree_async_proactor_posix_import_file( IREE_TRACE({ // For debugging, store a placeholder path since we don't know the actual // path for an imported fd. - snprintf(file->debug_path, sizeof(file->debug_path), "fd:%d", fd); + iree_snprintf(file->debug_path, sizeof(file->debug_path), "fd:%d", fd); }); *out_file = file; diff --git a/runtime/src/iree/async/platform/posix/socket.c b/runtime/src/iree/async/platform/posix/socket.c index c49e0bbb2271..ef1022f1c0f1 100644 --- a/runtime/src/iree/async/platform/posix/socket.c +++ b/runtime/src/iree/async/platform/posix/socket.c @@ -169,7 +169,8 @@ static void iree_async_socket_initialize(iree_async_socket_t* socket, iree_atomic_store(&socket->failure_status, (intptr_t)iree_ok_status(), iree_memory_order_release); IREE_TRACE({ - snprintf(socket->debug_label, sizeof(socket->debug_label), "socket:%d", fd); + iree_snprintf(socket->debug_label, sizeof(socket->debug_label), "socket:%d", + fd); }); } diff --git a/runtime/src/iree/base/BUILD.bazel b/runtime/src/iree/base/BUILD.bazel index 3fefaf6561e7..d1d452f2cdcb 100644 --- a/runtime/src/iree/base/BUILD.bazel +++ b/runtime/src/iree/base/BUILD.bazel @@ -34,6 +34,8 @@ iree_runtime_cc_library( "loop.h", "loop_inline.c", "loop_inline.h", + "printf.c", + "printf.h", "status.c", "status.h", "status_cc.h", @@ -57,6 +59,7 @@ iree_runtime_cc_library( "//runtime/src/iree/base/internal", "//runtime/src/iree/base/internal:time", "//runtime/src/iree/base/tracing:provider", + "@printf_lib//:printf", ], ) diff --git a/runtime/src/iree/base/CMakeLists.txt b/runtime/src/iree/base/CMakeLists.txt index cd829b9ab7de..dd14566427a0 100644 --- a/runtime/src/iree/base/CMakeLists.txt +++ b/runtime/src/iree/base/CMakeLists.txt @@ -66,6 +66,8 @@ iree_cc_library( "loop.h" "loop_inline.c" "loop_inline.h" + "printf.c" + "printf.h" "status.c" "status.h" "status_cc.h" @@ -88,6 +90,7 @@ iree_cc_library( iree::base::internal iree::base::internal::time iree::base::tracing::provider + printf::printf ${IREE_LIBBACKTRACE_TARGET} ${_IREE_ALLOCATOR_SYSTEM_DEPS} PUBLIC diff --git a/runtime/src/iree/base/api.h b/runtime/src/iree/base/api.h index f5021a588591..3a76d7ad8392 100644 --- a/runtime/src/iree/base/api.h +++ b/runtime/src/iree/base/api.h @@ -87,6 +87,7 @@ #include "iree/base/config.h" // IWYU pragma: export #include "iree/base/loop.h" // IWYU pragma: export #include "iree/base/loop_inline.h" // IWYU pragma: export +#include "iree/base/printf.h" // IWYU pragma: export #include "iree/base/status.h" // IWYU pragma: export #include "iree/base/string_builder.h" // IWYU pragma: export #include "iree/base/string_view.h" // IWYU pragma: export diff --git a/runtime/src/iree/base/internal/dynamic_library_posix.c b/runtime/src/iree/base/internal/dynamic_library_posix.c index cc6430fc952f..a3f6c2aa9c6a 100644 --- a/runtime/src/iree/base/internal/dynamic_library_posix.c +++ b/runtime/src/iree/base/internal/dynamic_library_posix.c @@ -41,8 +41,8 @@ static iree_status_t iree_dynamic_library_make_temp_file_path( const char* tmpdir, char** out_file_path) { // Stamp in a unique file name (replacing XXXXXX in the string). char temp_path[512]; - if (snprintf(temp_path, sizeof(temp_path), "%s/iree_dylib_XXXXXX", tmpdir) >= - sizeof(temp_path)) { + if (iree_snprintf(temp_path, sizeof(temp_path), "%s/iree_dylib_XXXXXX", + tmpdir) >= sizeof(temp_path)) { // NOTE: we could dynamically allocate things, but didn't seem worth it. return iree_make_status( IREE_STATUS_INVALID_ARGUMENT, @@ -57,15 +57,15 @@ static iree_status_t iree_dynamic_library_make_temp_file_path( // Allocate storage for the full file path and format it in. int file_path_length = - snprintf(NULL, 0, "%s_%s.%s", temp_path, prefix, extension); + iree_snprintf(NULL, 0, "%s_%s.%s", temp_path, prefix, extension); if (file_path_length < 0) { return iree_make_status(IREE_STATUS_INVALID_ARGUMENT, "unable to form temp path string"); } IREE_RETURN_IF_ERROR(iree_allocator_malloc( allocator, file_path_length + /*NUL=*/1, (void**)out_file_path)); - snprintf(*out_file_path, file_path_length + /*NUL=*/1, "%s_%s.%s", temp_path, - prefix, extension); + iree_snprintf(*out_file_path, file_path_length + /*NUL=*/1, "%s_%s.%s", + temp_path, prefix, extension); // Canonicalize away any double path separators. iree_file_path_canonicalize(*out_file_path, file_path_length); diff --git a/runtime/src/iree/base/internal/dynamic_library_win32.c b/runtime/src/iree/base/internal/dynamic_library_win32.c index 8cf1b0929cbb..af1f9f78aab2 100644 --- a/runtime/src/iree/base/internal/dynamic_library_win32.c +++ b/runtime/src/iree/base/internal/dynamic_library_win32.c @@ -67,9 +67,10 @@ static void iree_dynamic_library_init_temp_paths(void) { // Append the process ID to the path; this is like what _mktemp does but // without all the hoops. - snprintf(iree_dynamic_library_temp_path_base_, - sizeof(iree_dynamic_library_temp_path_base_), "%s\\iree_dylib_%08X", - temp_path, (uint32_t)GetCurrentProcessId()); + iree_snprintf(iree_dynamic_library_temp_path_base_, + sizeof(iree_dynamic_library_temp_path_base_), + "%s\\iree_dylib_%08X", temp_path, + (uint32_t)GetCurrentProcessId()); // Canonicalize away any double path separators. iree_file_path_canonicalize(iree_dynamic_library_temp_path_base_, @@ -95,17 +96,18 @@ static iree_status_t iree_dynamic_library_make_temp_file_path( &next_unique_id, 1, iree_memory_order_relaxed); // Allocate storage for the full file path and format it in. - int file_path_length = - snprintf(NULL, 0, "%s_%s_%08X.%s", iree_dynamic_library_temp_path_base_, - prefix, unique_id, extension); + int file_path_length = iree_snprintf(NULL, 0, "%s_%s_%08X.%s", + iree_dynamic_library_temp_path_base_, + prefix, unique_id, extension); if (file_path_length < 0) { return iree_make_status(IREE_STATUS_INVALID_ARGUMENT, "unable to form temp path string"); } IREE_RETURN_IF_ERROR(iree_allocator_malloc( allocator, file_path_length + /*NUL=*/1, (void**)out_file_path)); - snprintf(*out_file_path, file_path_length + /*NUL=*/1, "%s_%s_%08X.%s", - iree_dynamic_library_temp_path_base_, prefix, unique_id, extension); + iree_snprintf(*out_file_path, file_path_length + /*NUL=*/1, "%s_%s_%08X.%s", + iree_dynamic_library_temp_path_base_, prefix, unique_id, + extension); return iree_ok_status(); } diff --git a/runtime/src/iree/base/internal/shm_posix.c b/runtime/src/iree/base/internal/shm_posix.c index ba11e5b9c39d..909261c6c8d4 100644 --- a/runtime/src/iree/base/internal/shm_posix.c +++ b/runtime/src/iree/base/internal/shm_posix.c @@ -173,7 +173,8 @@ static iree_status_t iree_shm_create_anonymous_fd(iree_host_size_t size, for (int attempt = 0; attempt < 8; ++attempt) { int32_t sequence = iree_atomic_fetch_add(&counter, 1, iree_memory_order_relaxed); - snprintf(name, sizeof(name), "/iree_shm_%d_%d", (int)getpid(), sequence); + iree_snprintf(name, sizeof(name), "/iree_shm_%d_%d", (int)getpid(), + sequence); fd = shm_open(name, O_CREAT | O_RDWR | O_EXCL, 0600); if (fd != -1) break; if (errno != EEXIST) { diff --git a/runtime/src/iree/base/printf.c b/runtime/src/iree/base/printf.c new file mode 100644 index 000000000000..e68ab7f7b53e --- /dev/null +++ b/runtime/src/iree/base/printf.c @@ -0,0 +1,42 @@ +// Copyright 2026 The IREE Authors +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "iree/base/printf.h" + +#include "printf/printf.h" + +// eyalroz/printf requires consumers to provide a putchar_ implementation for +// its printf_/vprintf_ functions (stdout output). IREE only uses snprintf_/ +// vsnprintf_/vfctprintf so this is never called — but the library compiles the +// functions unconditionally, producing a linker reference we must satisfy. +void putchar_(char c) { (void)c; } + +int iree_snprintf(char* buffer, size_t count, const char* format, ...) { + va_list varargs; + va_start(varargs, format); + int result = vsnprintf_(buffer, count, format, varargs); + va_end(varargs); + return result; +} + +int iree_vsnprintf(char* buffer, size_t count, const char* format, + va_list varargs) { + return vsnprintf_(buffer, count, format, varargs); +} + +int iree_fctprintf(iree_printf_callback_t callback, void* user_data, + const char* format, ...) { + va_list varargs; + va_start(varargs, format); + int result = vfctprintf(callback, user_data, format, varargs); + va_end(varargs); + return result; +} + +int iree_vfctprintf(iree_printf_callback_t callback, void* user_data, + const char* format, va_list varargs) { + return vfctprintf(callback, user_data, format, varargs); +} diff --git a/runtime/src/iree/base/printf.h b/runtime/src/iree/base/printf.h new file mode 100644 index 000000000000..c719f4b1d2e7 --- /dev/null +++ b/runtime/src/iree/base/printf.h @@ -0,0 +1,55 @@ +// Copyright 2026 The IREE Authors +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Platform-independent printf implementation wrapping eyalroz/printf. +// All runtime code should use these functions instead of libc snprintf/ +// vsnprintf to ensure consistent formatting across all platforms. + +#ifndef IREE_BASE_PRINTF_H_ +#define IREE_BASE_PRINTF_H_ + +#include +#include + +#include "iree/base/attributes.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Callback type for iree_vfctprintf/iree_fctprintf. +// Called once per output character during formatting. +typedef void (*iree_printf_callback_t)(char character, void* user_data); + +// Formats a string into |buffer| of |count| bytes using a printf-style +// |format| string and variable arguments. Returns the number of characters +// that would have been written (excluding NUL) if the buffer were large enough. +// If |buffer| is NULL, no characters are written and the return value is the +// number of characters that would be written (dry-run for size measurement). +IREE_PRINTF_ATTRIBUTE(3, 4) +int iree_snprintf(char* buffer, size_t count, const char* format, ...); + +// Like iree_snprintf but takes a va_list. +int iree_vsnprintf(char* buffer, size_t count, const char* format, + va_list varargs); + +// Formats a string using a printf-style |format| and sends each character to +// |callback| with the provided |user_data|. The callback does NOT receive a NUL +// terminator. Returns the number of characters for which the callback was +// invoked. +IREE_PRINTF_ATTRIBUTE(3, 4) +int iree_fctprintf(iree_printf_callback_t callback, void* user_data, + const char* format, ...); + +// Like iree_fctprintf but takes a va_list. +int iree_vfctprintf(iree_printf_callback_t callback, void* user_data, + const char* format, va_list varargs); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // IREE_BASE_PRINTF_H_ diff --git a/runtime/src/iree/base/status.c b/runtime/src/iree/base/status.c index b6a7d894db35..e4142480bff1 100644 --- a/runtime/src/iree/base/status.c +++ b/runtime/src/iree/base/status.c @@ -20,7 +20,9 @@ #include "iree/base/allocator.h" #include "iree/base/assert.h" #include "iree/base/attributes.h" +#include "iree/base/printf.h" #include "iree/base/status_payload.h" +#include "iree/base/string_builder.h" //===----------------------------------------------------------------------===// // C11 aligned_alloc compatibility shim @@ -466,7 +468,7 @@ iree_status_allocate(iree_status_code_t code, const char* file, uint32_t line, IREE_MUST_USE_RESULT static iree_status_t iree_status_allocate_vf_impl( iree_status_code_t code, const char* file, uint32_t line, int skip_frames, - const char* format, va_list varargs_0, va_list varargs_1) { + const char* format, va_list varargs) { #if (IREE_STATUS_FEATURES & IREE_STATUS_FEATURE_ANNOTATIONS) == 0 // Annotations disabled; ignore the format string/args. return iree_status_allocate(code, file, line, iree_string_view_empty()); @@ -475,11 +477,19 @@ IREE_MUST_USE_RESULT static iree_status_t iree_status_allocate_vf_impl( // with this from marshaling code. if (IREE_UNLIKELY(code == IREE_STATUS_OK)) return iree_ok_status(); + // Copy varargs so we can walk the list twice: once to measure, once to + // format. The original is consumed by measurement; the copy by formatting. + va_list varargs_copy; + va_copy(varargs_copy, varargs); + // Compute the total number of bytes (including NUL) required to store the // message. int message_size = - vsnprintf(/*buffer=*/NULL, /*buffer_count=*/0, format, varargs_0); - if (message_size < 0) return iree_status_from_code(code); + iree_vsnprintf(/*buffer=*/NULL, /*buffer_count=*/0, format, varargs); + if (message_size < 0) { + va_end(varargs_copy); + return iree_status_from_code(code); + } ++message_size; // NUL byte // Allocate storage with the additional room to store the formatted message. @@ -492,18 +502,23 @@ IREE_MUST_USE_RESULT static iree_status_t iree_status_allocate_vf_impl( IREE_STRUCT_FIELD(message_size, char, &message_offset)); if (!iree_status_is_ok(layout_status)) { iree_status_ignore(layout_status); + va_end(varargs_copy); return iree_status_from_code(code); } iree_host_size_t storage_alignment = (IREE_STATUS_CODE_MASK + 1); iree_host_size_t storage_size = 0; if (!iree_host_size_checked_align(unaligned_size, storage_alignment, &storage_size)) { + va_end(varargs_copy); return iree_status_from_code(code); } iree_status_storage_t* storage = (iree_status_storage_t*)iree_aligned_alloc_raw(storage_alignment, storage_size); - if (IREE_UNLIKELY(!storage)) return iree_status_from_code(code); + if (IREE_UNLIKELY(!storage)) { + va_end(varargs_copy); + return iree_status_from_code(code); + } memset(storage, 0, sizeof(*storage)); #if (IREE_STATUS_FEATURES & IREE_STATUS_FEATURE_SOURCE_LOCATION) != 0 @@ -511,11 +526,12 @@ IREE_MUST_USE_RESULT static iree_status_t iree_status_allocate_vf_impl( storage->line = line; #endif // has IREE_STATUS_FEATURE_SOURCE_LOCATION - // vsnprintf directly into message buffer. + // Format directly into the message buffer using the copied varargs. storage->message.size = message_size - 1; storage->message.data = (const char*)storage + message_offset; - int ret = - vsnprintf((char*)storage->message.data, message_size, format, varargs_1); + int ret = iree_vsnprintf((char*)storage->message.data, message_size, format, + varargs_copy); + va_end(varargs_copy); if (IREE_UNLIKELY(ret < 0)) { iree_aligned_free_raw(storage); return (iree_status_t)code; @@ -530,21 +546,19 @@ IREE_MUST_USE_RESULT static iree_status_t iree_status_allocate_vf_impl( IREE_API_EXPORT IREE_MUST_USE_RESULT iree_status_t iree_status_allocate_f(iree_status_code_t code, const char* file, uint32_t line, const char* format, ...) { - va_list varargs_0, varargs_1; - va_start(varargs_0, format); - va_start(varargs_1, format); + va_list varargs; + va_start(varargs, format); iree_status_t ret = iree_status_allocate_vf_impl( - code, file, line, /*skip_frames=*/2, format, varargs_0, varargs_1); - va_end(varargs_0); - va_end(varargs_1); + code, file, line, /*skip_frames=*/2, format, varargs); + va_end(varargs); return ret; } -IREE_API_EXPORT IREE_MUST_USE_RESULT iree_status_t iree_status_allocate_vf( - iree_status_code_t code, const char* file, uint32_t line, - const char* format, va_list varargs_0, va_list varargs_1) { +IREE_API_EXPORT IREE_MUST_USE_RESULT iree_status_t +iree_status_allocate_vf(iree_status_code_t code, const char* file, + uint32_t line, const char* format, va_list varargs) { return iree_status_allocate_vf_impl(code, file, line, /*skip_frames=*/1, - format, varargs_0, varargs_1); + format, varargs); } IREE_API_EXPORT IREE_MUST_USE_RESULT iree_status_t @@ -662,8 +676,7 @@ iree_status_annotate(iree_status_t base_status, iree_string_view_t message) { } IREE_MUST_USE_RESULT static iree_status_t iree_status_annotate_vf( - iree_status_t base_status, const char* format, va_list varargs_0, - va_list varargs_1) { + iree_status_t base_status, const char* format, va_list varargs) { if (iree_status_is_ok(base_status)) return base_status; // If there's no storage yet we can just reuse normal allocation. Both that @@ -671,14 +684,22 @@ IREE_MUST_USE_RESULT static iree_status_t iree_status_annotate_vf( iree_status_storage_t* storage = iree_status_storage(base_status); if (!storage) { return iree_status_allocate_vf(iree_status_code(base_status), NULL, 0, - format, varargs_0, varargs_1); + format, varargs); } + // Copy varargs so we can walk the list twice: once to measure, once to + // format. The original is consumed by measurement; the copy by formatting. + va_list varargs_copy; + va_copy(varargs_copy, varargs); + // Compute the total number of bytes (including NUL) required to store the // message. int message_size = - vsnprintf(/*buffer=*/NULL, /*buffer_count=*/0, format, varargs_0); - if (message_size < 0) return base_status; + iree_vsnprintf(/*buffer=*/NULL, /*buffer_count=*/0, format, varargs); + if (message_size < 0) { + va_end(varargs_copy); + return base_status; + } ++message_size; // NUL byte // Allocate storage with the additional room to store the formatted message. @@ -691,25 +712,30 @@ IREE_MUST_USE_RESULT static iree_status_t iree_status_annotate_vf( IREE_STRUCT_FIELD(message_size, char, &message_offset)); if (!iree_status_is_ok(layout_status)) { iree_status_ignore(layout_status); + va_end(varargs_copy); return base_status; } iree_allocator_t allocator = iree_allocator_system(); iree_status_payload_message_t* payload = NULL; iree_status_ignore( iree_allocator_malloc(allocator, alloc_size, (void**)&payload)); - if (IREE_UNLIKELY(!payload)) return base_status; + if (IREE_UNLIKELY(!payload)) { + va_end(varargs_copy); + return base_status; + } memset(payload, 0, sizeof(*payload)); payload->header.type = IREE_STATUS_PAYLOAD_TYPE_MESSAGE; payload->header.allocator = allocator; payload->header.formatter = iree_status_payload_message_formatter; - // vsnprintf directly into message buffer. + // Format directly into the message buffer using the copied varargs. payload->message.size = message_size - 1; payload->message.data = (const char*)payload + message_offset; - int ret = vsnprintf((char*)payload->message.data, payload->message.size + 1, - format, varargs_1); + int ret = iree_vsnprintf((char*)payload->message.data, + payload->message.size + 1, format, varargs_copy); + va_end(varargs_copy); if (IREE_UNLIKELY(ret < 0)) { - iree_aligned_free_raw(payload); + iree_allocator_free(allocator, payload); return base_status; } return iree_status_append_payload(base_status, storage, @@ -718,16 +744,10 @@ IREE_MUST_USE_RESULT static iree_status_t iree_status_annotate_vf( IREE_API_EXPORT IREE_MUST_USE_RESULT iree_status_t IREE_PRINTF_ATTRIBUTE(2, 3) iree_status_annotate_f(iree_status_t base_status, const char* format, ...) { - // We walk the lists twice as each va_list can only be walked once we need to - // double-up. iree_status_annotate_vf could use va_copy to clone the single - // list however the proper management of va_end is trickier and this works. - va_list varargs_0, varargs_1; - va_start(varargs_0, format); - va_start(varargs_1, format); - iree_status_t ret = - iree_status_annotate_vf(base_status, format, varargs_0, varargs_1); - va_end(varargs_0); - va_end(varargs_1); + va_list varargs; + va_start(varargs, format); + iree_status_t ret = iree_status_annotate_vf(base_status, format, varargs); + va_end(varargs); return ret; } @@ -754,10 +774,10 @@ static bool iree_status_format_message(iree_status_t status, #if (IREE_STATUS_FEATURES & IREE_STATUS_FEATURE_ANNOTATIONS) != 0 // Append base storage message. if (storage && !iree_string_view_is_empty(storage->message)) { - n = snprintf(buffer ? buffer + buffer_length : NULL, - buffer ? buffer_capacity - buffer_length : 0, - has_prefix ? "; %.*s" : "%.*s", (int)storage->message.size, - storage->message.data); + n = iree_snprintf(buffer ? buffer + buffer_length : NULL, + buffer ? buffer_capacity - buffer_length : 0, + has_prefix ? "; %.*s" : "%.*s", + (int)storage->message.size, storage->message.data); if (IREE_UNLIKELY(n < 0)) { return false; } else if (buffer && n >= buffer_capacity - buffer_length) { @@ -827,17 +847,17 @@ IREE_API_EXPORT bool iree_status_format(iree_status_t status, int n = 0; #if (IREE_STATUS_FEATURES & IREE_STATUS_FEATURE_SOURCE_LOCATION) != 0 if (storage && storage->file) { - n = snprintf(buffer ? buffer : NULL, buffer ? buffer_capacity : 0, - "%s:%d: %s", storage->file, storage->line, - iree_status_code_string(status_code)); + n = iree_snprintf(buffer ? buffer : NULL, buffer ? buffer_capacity : 0, + "%s:%d: %s", storage->file, storage->line, + iree_status_code_string(status_code)); } else { - n = snprintf(buffer ? buffer : NULL, buffer ? buffer_capacity : 0, "%s", - iree_status_code_string(status_code)); + n = iree_snprintf(buffer ? buffer : NULL, buffer ? buffer_capacity : 0, + "%s", iree_status_code_string(status_code)); } #else - n = snprintf(buffer ? buffer + prefix_buffer_length : NULL, - buffer ? buffer_capacity - prefix_buffer_length : 0, "%s", - iree_status_code_string(status_code)); + n = iree_snprintf(buffer ? buffer + prefix_buffer_length : NULL, + buffer ? buffer_capacity - prefix_buffer_length : 0, "%s", + iree_status_code_string(status_code)); #endif // has IREE_STATUS_FEATURE_SOURCE_LOCATION if (IREE_UNLIKELY(n < 0)) { return false; @@ -858,6 +878,140 @@ IREE_API_EXPORT bool iree_status_format(iree_status_t status, return true; } +//===----------------------------------------------------------------------===// +// Callback-based status formatting (zero-allocation streaming) +//===----------------------------------------------------------------------===// + +// Streams the message and payload portions of a status to a callback. +// If |has_prefix| is true, the first annotation is preceded by "; ". +// Returns false if the callback requested early termination. +static bool iree_status_format_message_to(iree_status_t status, + iree_status_output_fn_t output_fn, + void* user_data, bool has_prefix) { + iree_status_storage_t* storage = iree_status_storage(status); + if (!storage) return true; + +#if (IREE_STATUS_FEATURES & IREE_STATUS_FEATURE_ANNOTATIONS) != 0 + if (!iree_string_view_is_empty(storage->message)) { + if (has_prefix) { + if (!output_fn(iree_make_cstring_view("; "), user_data)) return false; + } + if (!output_fn(storage->message, user_data)) return false; + has_prefix = true; + } +#endif // has IREE_STATUS_FEATURE_ANNOTATIONS + +#if IREE_STATUS_FEATURES != 0 + iree_status_payload_t* payload = storage->payload_head; + while (payload != NULL) { + if (!payload->formatter) { + payload = payload->next; + continue; + } + + if (!output_fn(iree_make_cstring_view("; "), user_data)) return false; + + // Fast path for message payloads: stream directly without buffering. + if (payload->type == IREE_STATUS_PAYLOAD_TYPE_MESSAGE) { + iree_status_payload_message_t* message_payload = + (iree_status_payload_message_t*)payload; + if (!output_fn(message_payload->message, user_data)) return false; + } else { + // Generic path: measure, then format into a stack buffer. If the payload + // exceeds the stack buffer (e.g., a stack trace), we try a heap + // allocation. We use raw malloc/free here rather than iree_allocator_t + // because status formatting runs on error paths where we cannot trust + // the allocator system to be functional, and threading an allocator + // through every formatting call would complicate the API for a transient + // buffer that exists only for the duration of this function. + iree_host_size_t payload_length = 0; + payload->formatter(payload, 0, NULL, &payload_length); + + char stack_buffer[512]; + char* buffer = stack_buffer; + iree_host_size_t buffer_capacity = sizeof(stack_buffer); + bool heap_allocated = false; + if (payload_length >= buffer_capacity) { + buffer = (char*)malloc(payload_length + 1); + if (!buffer) { + // Heap allocation failed; truncate into the stack buffer and append + // an indicator so the output signals that content was lost. + iree_host_size_t actual_length = 0; + payload->formatter(payload, sizeof(stack_buffer), stack_buffer, + &actual_length); + iree_host_size_t truncated_length = + actual_length < sizeof(stack_buffer) - 3 + ? actual_length + : sizeof(stack_buffer) - 4; + stack_buffer[truncated_length] = '.'; + stack_buffer[truncated_length + 1] = '.'; + stack_buffer[truncated_length + 2] = '.'; + if (!output_fn( + iree_make_string_view(stack_buffer, truncated_length + 3), + user_data)) { + return false; + } + payload = payload->next; + continue; + } + buffer_capacity = payload_length + 1; + heap_allocated = true; + } + + iree_host_size_t actual_length = 0; + payload->formatter(payload, buffer_capacity, buffer, &actual_length); + bool should_continue = + output_fn(iree_make_string_view(buffer, actual_length), user_data); + + if (heap_allocated) free(buffer); + if (!should_continue) return false; + } + + payload = payload->next; + } +#endif // has IREE_STATUS_FEATURES + return true; +} + +IREE_API_EXPORT bool iree_status_format_to(iree_status_t status, + iree_status_output_fn_t output_fn, + void* user_data) { + iree_status_storage_t* storage IREE_ATTRIBUTE_UNUSED = + iree_status_storage(status); + iree_status_code_t status_code = iree_status_code(status); + +#if (IREE_STATUS_FEATURES & IREE_STATUS_FEATURE_SOURCE_LOCATION) != 0 + if (storage && storage->file) { + // Stream file path and line number without buffering the path. + if (!output_fn(iree_make_cstring_view(storage->file), user_data)) + return false; + char line_buffer[16]; + int n = + iree_snprintf(line_buffer, sizeof(line_buffer), ":%u: ", storage->line); + if (n > 0) { + if (!output_fn( + iree_make_string_view( + line_buffer, iree_min((size_t)n, sizeof(line_buffer) - 1)), + user_data)) { + return false; + } + } + } +#endif // has IREE_STATUS_FEATURE_SOURCE_LOCATION + + if (!output_fn(iree_make_cstring_view(iree_status_code_string(status_code)), + user_data)) { + return false; + } + + return iree_status_format_message_to(status, output_fn, user_data, + /*has_prefix=*/true); +} + +//===----------------------------------------------------------------------===// +// Status freeze +//===----------------------------------------------------------------------===// + #if IREE_STATUS_FEATURES == 0 IREE_API_EXPORT IREE_MUST_USE_RESULT iree_status_t iree_status_freeze(iree_status_t status) { @@ -965,47 +1119,48 @@ iree_status_freeze(iree_status_t status) { } #endif // has any IREE_STATUS_FEATURES +// Callback that appends chunks to a string builder, returning false on +// allocation failure to short-circuit formatting. +static bool iree_status_to_string_output(iree_string_view_t chunk, + void* user_data) { + iree_string_builder_t* builder = (iree_string_builder_t*)user_data; + iree_status_t status = iree_string_builder_append_string(builder, chunk); + if (!iree_status_is_ok(status)) { + iree_status_ignore(status); + return false; + } + return true; +} + IREE_API_EXPORT bool iree_status_to_string( iree_status_t status, const iree_allocator_t* allocator, char** out_buffer, iree_host_size_t* out_buffer_length) { + *out_buffer = NULL; *out_buffer_length = 0; - iree_host_size_t buffer_length = 0; - if (IREE_UNLIKELY(!iree_status_format(status, /*buffer_capacity=*/0, - /*buffer=*/NULL, &buffer_length))) { - return false; - } - // Buffer capacity needs to be +1 for the NUL terminator (see snprintf). - char* buffer = NULL; - iree_status_t malloc_status = - iree_allocator_malloc(*allocator, buffer_length + 1, (void**)&buffer); - if (!iree_status_is_ok(malloc_status)) { - iree_status_ignore(malloc_status); - return false; - } - bool ret = - iree_status_format(status, buffer_length + 1, buffer, out_buffer_length); - if (ret) { - *out_buffer = buffer; - return true; - } else { - iree_allocator_free(*allocator, buffer); + // Single-pass: stream the formatted status into a string builder. + iree_string_builder_t builder; + iree_string_builder_initialize(*allocator, &builder); + + if (!iree_status_format_to(status, iree_status_to_string_output, &builder)) { + iree_string_builder_deinitialize(&builder); return false; } + + *out_buffer_length = iree_string_builder_size(&builder); + *out_buffer = iree_string_builder_take_storage(&builder); + return true; +} + +// Callback that writes chunks directly to a FILE*. +static bool iree_status_fwrite_output(iree_string_view_t chunk, + void* user_data) { + return fwrite(chunk.data, 1, chunk.size, (FILE*)user_data) == chunk.size; } IREE_API_EXPORT void iree_status_fprint(FILE* file, iree_status_t status) { - // TODO(benvanik): better support for colors/etc - possibly move to logging. - // TODO(benvanik): do this without allocation by streaming the status. - iree_allocator_t allocator = iree_allocator_system(); - char* status_buffer = NULL; - iree_host_size_t status_buffer_length = 0; - if (iree_status_to_string(status, &allocator, &status_buffer, - &status_buffer_length)) { - fprintf(file, "%.*s\n", (int)status_buffer_length, status_buffer); - iree_allocator_free(allocator, status_buffer); - } else { - fprintf(file, "(?)\n"); - } + // Stream the formatted status directly to the file with zero allocation. + iree_status_format_to(status, iree_status_fwrite_output, file); + fputc('\n', file); fflush(file); } diff --git a/runtime/src/iree/base/status.h b/runtime/src/iree/base/status.h index 057c047d5ab7..9502756b2d98 100644 --- a/runtime/src/iree/base/status.h +++ b/runtime/src/iree/base/status.h @@ -447,9 +447,9 @@ IREE_API_EXPORT IREE_MUST_USE_RESULT iree_status_t IREE_PRINTF_ATTRIBUTE(4, 5) iree_status_allocate_f(iree_status_code_t code, const char* file, uint32_t line, const char* format, ...); -IREE_API_EXPORT IREE_MUST_USE_RESULT iree_status_t iree_status_allocate_vf( - iree_status_code_t code, const char* file, uint32_t line, - const char* format, va_list varargs_0, va_list varargs_1); +IREE_API_EXPORT IREE_MUST_USE_RESULT iree_status_t +iree_status_allocate_vf(iree_status_code_t code, const char* file, + uint32_t line, const char* format, va_list varargs); // Clones |status| into a new status instance. // No payloads, if present, will be cloned. @@ -524,6 +524,23 @@ IREE_API_EXPORT bool iree_status_format(iree_status_t status, char* buffer, iree_host_size_t* out_buffer_length); +// Callback for streaming formatted status output. +// |string| is a chunk of the formatted output (not NUL-terminated). +// The callback is invoked zero or more times with sequential chunks. +// Returns true to continue receiving chunks, false to stop early (e.g., the +// output buffer is full or an allocation failed). +typedef bool (*iree_status_output_fn_t)(iree_string_view_t string, + void* user_data); + +// Formats the status and streams it to the callback in chunks. +// Equivalent to iree_status_format but avoids requiring a contiguous buffer or +// pre-measurement pass, making it suitable for streaming to FILE*, syslog, ring +// buffers, or other sinks without heap allocation. +// Returns false if a callback returned false (indicating early termination). +IREE_API_EXPORT bool iree_status_format_to(iree_status_t status, + iree_status_output_fn_t output_fn, + void* user_data); + // Converts the status to an allocated string value using the given allocator. // |out_buffer| will contain |out_buffer_length| characters as well as a NUL // terminator. The caller must free the buffer with |allocator|. diff --git a/runtime/src/iree/base/status_cc.h b/runtime/src/iree/base/status_cc.h index e9fd79a57204..45cb30654595 100644 --- a/runtime/src/iree/base/status_cc.h +++ b/runtime/src/iree/base/status_cc.h @@ -116,17 +116,15 @@ class Status final { if (iree_status_is_ok(status)) { return "OK"; } - iree_host_size_t buffer_length = 0; - if (IREE_UNLIKELY(!iree_status_format(status, /*buffer_capacity=*/0, - /*buffer=*/NULL, &buffer_length))) { - return ""; - } - std::string result(buffer_length, '\0'); - if (IREE_UNLIKELY(!iree_status_format(status, result.size() + 1, - const_cast(result.data()), - &buffer_length))) { - return ""; - } + std::string result; + iree_status_format_to( + status, + [](iree_string_view_t chunk, void* user_data) -> bool { + auto* str = static_cast(user_data); + str->append(chunk.data, chunk.size); + return true; + }, + &result); return result; } diff --git a/runtime/src/iree/base/status_stack_trace.c b/runtime/src/iree/base/status_stack_trace.c index 672e6461ad53..ff943973be67 100644 --- a/runtime/src/iree/base/status_stack_trace.c +++ b/runtime/src/iree/base/status_stack_trace.c @@ -37,6 +37,7 @@ #include "iree/base/allocator.h" #include "iree/base/assert.h" #include "iree/base/config.h" +#include "iree/base/printf.h" #include "iree/base/status.h" #include "iree/base/status_payload.h" #include "iree/base/tracing.h" @@ -60,8 +61,8 @@ static iree_host_size_t iree_string_buffer_append_cstr( iree_host_size_t buffer_capacity, char* buffer, iree_host_size_t buffer_length, const char* str) { iree_host_size_t n = - snprintf(buffer ? buffer + buffer_length : NULL, - buffer ? buffer_capacity - buffer_length : 0, "%s", str); + iree_snprintf(buffer ? buffer + buffer_length : NULL, + buffer ? buffer_capacity - buffer_length : 0, "%s", str); return IREE_UNLIKELY(n < 0) ? 0 : buffer_length + n; } @@ -72,9 +73,9 @@ static iree_host_size_t IREE_PRINTF_ATTRIBUTE(4, 5) const char* format, ...) { va_list varargs; va_start(varargs, format); - iree_host_size_t n = - vsnprintf(buffer ? buffer + buffer_length : NULL, - buffer ? buffer_capacity - buffer_length : 0, format, varargs); + iree_host_size_t n = iree_vsnprintf( + buffer ? buffer + buffer_length : NULL, + buffer ? buffer_capacity - buffer_length : 0, format, varargs); va_end(varargs); return IREE_UNLIKELY(n < 0) ? 0 : buffer_length + n; } diff --git a/runtime/src/iree/base/status_test.cc b/runtime/src/iree/base/status_test.cc index e9db6964dabf..95fb97f3df1e 100644 --- a/runtime/src/iree/base/status_test.cc +++ b/runtime/src/iree/base/status_test.cc @@ -102,5 +102,152 @@ TEST(StatusMacro, AssignOrReturn) { IREE_EXPECT_OK(assignOrReturn("foo")); } +// Helper: collects iree_status_format_to output into a std::string. +static std::string FormatStatusTo(iree_status_t status) { + std::string result; + iree_status_format_to( + status, + [](iree_string_view_t chunk, void* user_data) -> bool { + auto* str = static_cast(user_data); + str->append(chunk.data, chunk.size); + return true; + }, + &result); + return result; +} + +// Helper: collects iree_status_format output into a std::string. +static std::string FormatStatusBuffer(iree_status_t status) { + iree_host_size_t buffer_length = 0; + if (!iree_status_format(status, 0, NULL, &buffer_length)) return ""; + std::string result(buffer_length, '\0'); + iree_host_size_t actual_length = 0; + if (!iree_status_format(status, result.size() + 1, + const_cast(result.data()), &actual_length)) { + return ""; + } + result.resize(actual_length); + return result; +} + +TEST(StatusFormatTo, OkStatus) { + iree_status_t status = iree_ok_status(); + std::string cb_result = FormatStatusTo(status); + std::string buffer_result = FormatStatusBuffer(status); + EXPECT_EQ(cb_result, buffer_result); + EXPECT_THAT(cb_result, HasSubstr("OK")); +} + +TEST(StatusFormatTo, CodeOnly) { + iree_status_t status = iree_status_from_code(IREE_STATUS_INTERNAL); + std::string cb_result = FormatStatusTo(status); + std::string buffer_result = FormatStatusBuffer(status); + EXPECT_EQ(cb_result, buffer_result); + EXPECT_THAT(cb_result, HasSubstr("INTERNAL")); +} + +#if (IREE_STATUS_FEATURES & IREE_STATUS_FEATURE_ANNOTATIONS) != 0 + +TEST(StatusFormatTo, WithMessage) { + iree_status_t status = + iree_status_allocate(IREE_STATUS_NOT_FOUND, NULL, 0, + iree_make_cstring_view("something missing")); + std::string cb_result = FormatStatusTo(status); + std::string buffer_result = FormatStatusBuffer(status); + EXPECT_EQ(cb_result, buffer_result); + EXPECT_THAT(cb_result, HasSubstr("NOT_FOUND")); + EXPECT_THAT(cb_result, HasSubstr("something missing")); + iree_status_free(status); +} + +TEST(StatusFormatTo, WithFormatMessage) { + iree_status_t status = + iree_status_allocate_f(IREE_STATUS_INVALID_ARGUMENT, NULL, 0, + "value %d out of range [%d, %d]", 42, 0, 10); + std::string cb_result = FormatStatusTo(status); + std::string buffer_result = FormatStatusBuffer(status); + EXPECT_EQ(cb_result, buffer_result); + EXPECT_THAT(cb_result, HasSubstr("INVALID_ARGUMENT")); + EXPECT_THAT(cb_result, HasSubstr("value 42 out of range [0, 10]")); + iree_status_free(status); +} + +TEST(StatusFormatTo, WithAnnotation) { + iree_status_t status = + iree_status_allocate_f(IREE_STATUS_INTERNAL, NULL, 0, "base error %d", 1); + status = iree_status_annotate_f(status, "annotation %d", 2); + std::string cb_result = FormatStatusTo(status); + std::string buffer_result = FormatStatusBuffer(status); + EXPECT_EQ(cb_result, buffer_result); + EXPECT_THAT(cb_result, HasSubstr("INTERNAL")); + EXPECT_THAT(cb_result, HasSubstr("base error 1")); + EXPECT_THAT(cb_result, HasSubstr("annotation 2")); + iree_status_free(status); +} + +TEST(StatusFormatTo, WithMultipleAnnotations) { + iree_status_t status = + iree_status_allocate_f(IREE_STATUS_UNAVAILABLE, NULL, 0, "root cause"); + status = iree_status_annotate_f(status, "layer 1: %s", "retry failed"); + status = iree_status_annotate_f(status, "layer 2: attempt %d of %d", 3, 3); + std::string cb_result = FormatStatusTo(status); + std::string buffer_result = FormatStatusBuffer(status); + EXPECT_EQ(cb_result, buffer_result); + EXPECT_THAT(cb_result, HasSubstr("UNAVAILABLE")); + EXPECT_THAT(cb_result, HasSubstr("root cause")); + EXPECT_THAT(cb_result, HasSubstr("layer 1: retry failed")); + EXPECT_THAT(cb_result, HasSubstr("layer 2: attempt 3 of 3")); + iree_status_free(status); +} + +TEST(StatusFormatTo, CallbackShortCircuit) { + iree_status_t status = + iree_status_allocate_f(IREE_STATUS_INTERNAL, NULL, 0, "error %d", 42); + status = iree_status_annotate_f(status, "annotation %d", 1); + status = iree_status_annotate_f(status, "annotation %d", 2); + + // Callback that stops after receiving the first chunk. + int call_count = 0; + struct State { + int* call_count; + std::string first_chunk; + } state = {&call_count, {}}; + iree_status_format_to( + status, + [](iree_string_view_t chunk, void* user_data) -> bool { + auto* s = static_cast(user_data); + ++(*s->call_count); + s->first_chunk = std::string(chunk.data, chunk.size); + return false; // Stop after first chunk. + }, + &state); + // Should have been called exactly once. + EXPECT_EQ(call_count, 1); + // The first chunk should be the status code string. + EXPECT_THAT(state.first_chunk, HasSubstr("INTERNAL")); + iree_status_free(status); +} + +TEST(StatusToString, SinglePass) { + iree_status_t status = + iree_status_allocate_f(IREE_STATUS_INTERNAL, NULL, 0, "error %d", 42); + status = iree_status_annotate_f(status, "context: %s", "test"); + iree_allocator_t allocator = iree_allocator_system(); + char* buffer = NULL; + iree_host_size_t buffer_length = 0; + ASSERT_TRUE( + iree_status_to_string(status, &allocator, &buffer, &buffer_length)); + std::string result(buffer, buffer_length); + EXPECT_THAT(result, HasSubstr("INTERNAL")); + EXPECT_THAT(result, HasSubstr("error 42")); + EXPECT_THAT(result, HasSubstr("context: test")); + // Verify NUL termination. + EXPECT_EQ(buffer[buffer_length], '\0'); + iree_allocator_free(allocator, buffer); + iree_status_free(status); +} + +#endif // has IREE_STATUS_FEATURE_ANNOTATIONS + } // namespace } // namespace iree diff --git a/runtime/src/iree/base/string_builder.c b/runtime/src/iree/base/string_builder.c index ce6bffc2418a..46e5245c1bf7 100644 --- a/runtime/src/iree/base/string_builder.c +++ b/runtime/src/iree/base/string_builder.c @@ -7,6 +7,7 @@ #include "iree/base/string_builder.h" #include "iree/base/alignment.h" +#include "iree/base/printf.h" // Minimum alignment for storage buffer allocations. #define IREE_STRING_BUILDER_ALIGNMENT 128 @@ -182,49 +183,73 @@ IREE_API_EXPORT iree_status_t iree_string_builder_append_cstring( iree_make_cstring_view(value)); } -static iree_status_t iree_string_builder_append_format_impl( - iree_string_builder_t* builder, const char* format, va_list varargs_0, - va_list varargs_1) { - // Try to directly print into the buffer we have. This may work if we have - // capacity but otherwise will yield us the size we need to grow our buffer. - int n = vsnprintf(builder->buffer ? builder->buffer + builder->size : NULL, - builder->buffer ? builder->capacity - builder->size : 0, - format, varargs_0); - if (IREE_UNLIKELY(n < 0)) { - return iree_make_status(IREE_STATUS_INTERNAL, "printf try failed"); - } - if (n < builder->capacity - builder->size) { - // Printed into the buffer. - builder->size += n; - return iree_ok_status(); +// State threaded through the fctprintf callback during formatting. +typedef struct iree_string_builder_printf_state_t { + iree_string_builder_t* builder; + iree_status_t status; +} iree_string_builder_printf_state_t; + +// Per-character callback from iree_vfctprintf that appends to the builder. +// Handles both size-calculation mode (no buffer, just counting) and normal mode +// (writing characters and growing the buffer as needed). +static void iree_string_builder_printf_out(char character, void* user_data) { + iree_string_builder_printf_state_t* state = + (iree_string_builder_printf_state_t*)user_data; + iree_string_builder_t* builder = state->builder; + + // Size-calculation mode: just count characters, no buffer operations. + if (iree_string_builder_is_calculating_size(builder)) { + builder->size++; + return; } - if (!iree_string_builder_is_calculating_size(builder)) { - // Reserve new minimum capacity. - IREE_RETURN_IF_ERROR(iree_string_builder_reserve( - builder, iree_string_builder_size(builder) + n + /*NUL*/ 1)); - - // Try printing again. - vsnprintf(builder->buffer ? builder->buffer + builder->size : NULL, - builder->buffer ? builder->capacity - builder->size : 0, format, - varargs_1); - } + // Bail if a previous callback already failed (allocation error). + if (!iree_status_is_ok(state->status)) return; - builder->size += n; - return iree_ok_status(); + // Ensure capacity for this character + NUL terminator. + if (builder->size + 1 >= builder->capacity) { + state->status = iree_string_builder_reserve(builder, builder->size + 2); + if (!iree_status_is_ok(state->status)) return; + } + builder->buffer[builder->size++] = character; } IREE_API_EXPORT iree_status_t IREE_PRINTF_ATTRIBUTE(2, 3) iree_string_builder_append_format(iree_string_builder_t* builder, const char* format, ...) { - va_list varargs_0, varargs_1; - va_start(varargs_0, format); - va_start(varargs_1, format); - iree_status_t status = iree_string_builder_append_format_impl( - builder, format, varargs_0, varargs_1); - va_end(varargs_1); - va_end(varargs_0); - return status; + va_list varargs; + va_start(varargs, format); + iree_string_builder_printf_state_t state = {builder, iree_ok_status()}; + iree_vfctprintf(iree_string_builder_printf_out, &state, format, varargs); + va_end(varargs); + // NUL-terminate the buffer (fctprintf does not emit a terminator). + if (!iree_string_builder_is_calculating_size(builder) && builder->buffer) { + builder->buffer[builder->size] = '\0'; + } + return state.status; +} + +// Callback for iree_string_builder_append_status that appends chunks to a +// string builder. +static bool iree_string_builder_append_status_output(iree_string_view_t chunk, + void* user_data) { + iree_string_builder_t* builder = (iree_string_builder_t*)user_data; + iree_status_t status = iree_string_builder_append_string(builder, chunk); + if (!iree_status_is_ok(status)) { + iree_status_ignore(status); + return false; + } + return true; +} + +IREE_API_EXPORT iree_status_t iree_string_builder_append_status( + iree_string_builder_t* builder, iree_status_t status) { + if (!iree_status_format_to(status, iree_string_builder_append_status_output, + builder)) { + return iree_make_status(IREE_STATUS_RESOURCE_EXHAUSTED, + "failed to append formatted status to builder"); + } + return iree_ok_status(); } IREE_API_EXPORT void iree_string_pair_builder_initialize( @@ -257,7 +282,7 @@ IREE_API_EXPORT iree_status_t iree_string_pair_builder_add_int32(iree_string_pair_builder_t* builder, iree_string_view_t key, int32_t value) { char temp[32]; - snprintf(temp, sizeof(temp), "%d", value); + iree_snprintf(temp, sizeof(temp), "%d", value); iree_string_view_t value_string = iree_make_cstring_view(temp); IREE_RETURN_IF_ERROR( iree_string_pair_builder_emplace_string(builder, &value_string)); diff --git a/runtime/src/iree/base/string_builder.h b/runtime/src/iree/base/string_builder.h index 6ac933327acc..ec8034e9c9d6 100644 --- a/runtime/src/iree/base/string_builder.h +++ b/runtime/src/iree/base/string_builder.h @@ -158,6 +158,13 @@ IREE_API_EXPORT IREE_PRINTF_ATTRIBUTE(2, 3) iree_status_t iree_string_builder_append_format(iree_string_builder_t* builder, const char* format, ...); +// Appends the fully-formatted representation of |status| to the builder. +// This is the textual form produced by iree_status_format (status code, +// source location, message, and all payload annotations). +// Does not consume or free |status|. +IREE_API_EXPORT iree_status_t iree_string_builder_append_status( + iree_string_builder_t* builder, iree_status_t status); + // Lightweight builder for lists of iree_string_pair_t. // Includes a side pool for keeping dynamically allocated strings, since it is // common to need to create backed, temporary strings when constructing lists diff --git a/runtime/src/iree/base/threading/thread_pthreads.c b/runtime/src/iree/base/threading/thread_pthreads.c index 3f64055ec3a8..56ccc0188ece 100644 --- a/runtime/src/iree/base/threading/thread_pthreads.c +++ b/runtime/src/iree/base/threading/thread_pthreads.c @@ -313,8 +313,8 @@ static void iree_thread_make_cpu_set_from_node_id(uint32_t node_id, cpu_set_t* out_set) { // e.g. /sys/devices/system/node/node0/cpumap char cpumap_path[256]; - snprintf(cpumap_path, sizeof(cpumap_path), - "/sys/devices/system/node/node%u/cpumap", node_id); + iree_snprintf(cpumap_path, sizeof(cpumap_path), + "/sys/devices/system/node/node%u/cpumap", node_id); // Open file for reading. This should succeed under hypervisors/lockdown. FILE* file = fopen(cpumap_path, "r"); @@ -406,10 +406,10 @@ void iree_thread_request_affinity(iree_thread_t* thread, #if IREE_TRACING_FEATURES & IREE_TRACING_FEATURE_INSTRUMENTATION char affinity_desc[64]; int affinity_desc_length = - snprintf(affinity_desc, IREE_ARRAYSIZE(affinity_desc), - "group_any=%u, group=%u, id_assigned=%u, id=%u, smt=%u", - affinity.group_any, affinity.group, affinity.id_assigned, - affinity.id, affinity.smt); + iree_snprintf(affinity_desc, IREE_ARRAYSIZE(affinity_desc), + "group_any=%u, group=%u, id_assigned=%u, id=%u, smt=%u", + affinity.group_any, affinity.group, affinity.id_assigned, + affinity.id, affinity.smt); IREE_TRACE_ZONE_APPEND_TEXT(z0, affinity_desc, affinity_desc_length); #endif // IREE_TRACING_FEATURES & IREE_TRACING_FEATURE_INSTRUMENTATION diff --git a/runtime/src/iree/base/threading/thread_win32.c b/runtime/src/iree/base/threading/thread_win32.c index f8c44551ebe6..fb4ac6ab8aff 100644 --- a/runtime/src/iree/base/threading/thread_win32.c +++ b/runtime/src/iree/base/threading/thread_win32.c @@ -266,10 +266,10 @@ void iree_thread_request_affinity(iree_thread_t* thread, #if IREE_TRACING_FEATURES & IREE_TRACING_FEATURE_INSTRUMENTATION char affinity_desc[64]; int affinity_desc_length = - snprintf(affinity_desc, IREE_ARRAYSIZE(affinity_desc), - "group_any=%u, group=%u, id_assigned=%u, id=%u, smt=%u", - affinity.group_any, affinity.group, affinity.id_assigned, - affinity.id, affinity.smt); + iree_snprintf(affinity_desc, IREE_ARRAYSIZE(affinity_desc), + "group_any=%u, group=%u, id_assigned=%u, id=%u, smt=%u", + affinity.group_any, affinity.group, affinity.id_assigned, + affinity.id, affinity.smt); IREE_TRACE_ZONE_APPEND_TEXT(z0, affinity_desc, affinity_desc_length); #endif // IREE_TRACING_FEATURES & IREE_TRACING_FEATURE_INSTRUMENTATION diff --git a/runtime/src/iree/builtins/ukernel/tools/e2e_matmul_benchmark.c b/runtime/src/iree/builtins/ukernel/tools/e2e_matmul_benchmark.c index 367c803fabd5..e418a0c0773d 100644 --- a/runtime/src/iree/builtins/ukernel/tools/e2e_matmul_benchmark.c +++ b/runtime/src/iree/builtins/ukernel/tools/e2e_matmul_benchmark.c @@ -397,7 +397,7 @@ static void iree_uk_benchmark_register_e2e_matmul(const char* type_str, int M, int K, int N, bool accumulate, const char* cpu_features) { char name[128]; - snprintf(name, sizeof name, "e2e_matmul_%s_%dx%dx%d", type_str, M, K, N); + iree_snprintf(name, sizeof name, "e2e_matmul_%s_%dx%dx%d", type_str, M, K, N); iree_uk_uint32_t mmt4d_flags = iree_uk_mmt4d_parse_type_into_flag(type_str); mmt4d_flags |= IREE_UK_FLAG_MMT4D_ALLOW_GENERIC_FALLBACK_TILE_FUNCTION; if (accumulate) mmt4d_flags |= IREE_UK_FLAG_MMT4D_ACCUMULATE; diff --git a/runtime/src/iree/builtins/ukernel/tools/memcpy_benchmark.c b/runtime/src/iree/builtins/ukernel/tools/memcpy_benchmark.c index edf7afc1b7c4..a7a0556ee7c9 100644 --- a/runtime/src/iree/builtins/ukernel/tools/memcpy_benchmark.c +++ b/runtime/src/iree/builtins/ukernel/tools/memcpy_benchmark.c @@ -66,6 +66,6 @@ void iree_uk_benchmark_register_memcpy(int64_t working_set_size) { .user_data = user_data, }; char name[128]; - snprintf(name, sizeof name, "memcpy_wss_%" PRIi64, working_set_size); + iree_snprintf(name, sizeof name, "memcpy_wss_%" PRIi64, working_set_size); iree_benchmark_register(IREE_SV(name), &memcpy_benchmark_def); } diff --git a/runtime/src/iree/builtins/ukernel/tools/mmt4d_benchmark.c b/runtime/src/iree/builtins/ukernel/tools/mmt4d_benchmark.c index 190d87cd1e41..6ffc3c6f7dfe 100644 --- a/runtime/src/iree/builtins/ukernel/tools/mmt4d_benchmark.c +++ b/runtime/src/iree/builtins/ukernel/tools/mmt4d_benchmark.c @@ -94,8 +94,8 @@ static void iree_uk_benchmark_register_mmt4d_impl( iree_uk_mmt4d_type_t mmt4d_type = iree_uk_mmt4d_type(flags); iree_uk_type_triple_str(type_str, sizeof type_str, mmt4d_type); char name[128]; - snprintf(name, sizeof name, "mmt4d_%s_tile_%dx%dx%d%s", type_str, M0, N0, K0, - code_path_suffix); + iree_snprintf(name, sizeof name, "mmt4d_%s_tile_%dx%dx%d%s", type_str, M0, N0, + K0, code_path_suffix); iree_uk_mmt4d_params_t params = { .flags = flags | IREE_UK_FLAG_MMT4D_SKIP_INTERMEDIATE_ROUNDINGS | IREE_UK_FLAG_MMT4D_ALLOW_GENERIC_FALLBACK_TILE_FUNCTION, diff --git a/runtime/src/iree/builtins/ukernel/tools/mmt4d_test.c b/runtime/src/iree/builtins/ukernel/tools/mmt4d_test.c index e6ad9ab918c9..474962e970b5 100644 --- a/runtime/src/iree/builtins/ukernel/tools/mmt4d_test.c +++ b/runtime/src/iree/builtins/ukernel/tools/mmt4d_test.c @@ -515,8 +515,9 @@ static void iree_uk_test_mmt4d_impl(iree_uk_uint32_t flags, int M0, int N0, iree_uk_mmt4d_params_t params = { .flags = flags, .M0 = M0, .N0 = N0, .K0 = K0}; char test_label_str[256]; - snprintf(test_label_str, sizeof test_label_str, "types:%s tile:%dx%dx%d%s", - types_str, M0, N0, K0, code_path_suffix); + iree_snprintf(test_label_str, sizeof test_label_str, + "types:%s tile:%dx%dx%d%s", types_str, M0, N0, K0, + code_path_suffix); iree_uk_test(test_label_str, iree_uk_test_mmt4d_for_tile_params, ¶ms, cpu_features); } diff --git a/runtime/src/iree/builtins/ukernel/tools/pack_benchmark.c b/runtime/src/iree/builtins/ukernel/tools/pack_benchmark.c index 44a1b0e58516..6ae506030443 100644 --- a/runtime/src/iree/builtins/ukernel/tools/pack_benchmark.c +++ b/runtime/src/iree/builtins/ukernel/tools/pack_benchmark.c @@ -126,8 +126,9 @@ static void iree_uk_benchmark_register_pack(iree_uk_uint32_t flags, for (int i = 0; i < IREE_ARRAYSIZE(variants); ++i) { pack_variant_t variant = variants[i]; char name[128]; - snprintf(name, sizeof name, "pack_%s_tile_%dx%d_%s_wss_%" PRIi64, type_str, - tile_size0, tile_size1, variant.label, FLAG_working_set_size); + iree_snprintf(name, sizeof name, "pack_%s_tile_%dx%d_%s_wss_%" PRIi64, + type_str, tile_size0, tile_size1, variant.label, + FLAG_working_set_size); params.flags = flags | variant.flags; iree_uk_benchmark_register(name, iree_uk_benchmark_pack, ¶ms, sizeof params, cpu_features); diff --git a/runtime/src/iree/builtins/ukernel/tools/pack_test.c b/runtime/src/iree/builtins/ukernel/tools/pack_test.c index 496a919d4e01..e2badac5a720 100644 --- a/runtime/src/iree/builtins/ukernel/tools/pack_test.c +++ b/runtime/src/iree/builtins/ukernel/tools/pack_test.c @@ -202,8 +202,8 @@ static void iree_uk_test_pack(iree_uk_uint32_t flags, int tile_size0, iree_uk_pack_type_t type = iree_uk_pack_type(flags); iree_uk_type_pair_str(types_str, sizeof types_str, type); char test_label_str[256]; - snprintf(test_label_str, sizeof test_label_str, "types:%s tile:%dx%d", - types_str, tile_size0, tile_size1); + iree_snprintf(test_label_str, sizeof test_label_str, "types:%s tile:%dx%d", + types_str, tile_size0, tile_size1); iree_uk_test(test_label_str, iree_uk_test_pack_for_tile_params, ¶ms, cpu_features); } diff --git a/runtime/src/iree/builtins/ukernel/tools/test.c b/runtime/src/iree/builtins/ukernel/tools/test.c index 1e3972622500..56be951dd27c 100644 --- a/runtime/src/iree/builtins/ukernel/tools/test.c +++ b/runtime/src/iree/builtins/ukernel/tools/test.c @@ -136,8 +136,8 @@ void iree_uk_test(const char* name, } else { // CPU does not support features. Skip this part of the test. char msg[128]; - snprintf(msg, sizeof msg, "CPU does not support required feature %s", - iree_uk_cpu_first_unsupported_feature(test.cpu_data)); + iree_snprintf(msg, sizeof msg, "CPU does not support required feature %s", + iree_uk_cpu_first_unsupported_feature(test.cpu_data)); iree_uk_test_log_info(&test, "🦕", msg); // Set test status to SKIPPED if it was still the initial RUN. // Do not overwrite a FAILED from the run without optional CPU features. @@ -161,7 +161,7 @@ static const char iree_uk_test_abort_on_error_env[] = void iree_uk_test_fail(iree_uk_test_t* test, const char* file, int line) { test->status = IREE_UK_TEST_STATUS_FAILED; char msg_buf[256]; - snprintf(msg_buf, sizeof msg_buf, "Error occurred at %s:%d", file, line); + iree_snprintf(msg_buf, sizeof msg_buf, "Error occurred at %s:%d", file, line); iree_uk_test_log_error(test, msg_buf); if (getenv(iree_uk_test_abort_on_error_env)) { iree_abort(); diff --git a/runtime/src/iree/builtins/ukernel/tools/unpack_benchmark.c b/runtime/src/iree/builtins/ukernel/tools/unpack_benchmark.c index 6233d7448006..132220b077c0 100644 --- a/runtime/src/iree/builtins/ukernel/tools/unpack_benchmark.c +++ b/runtime/src/iree/builtins/ukernel/tools/unpack_benchmark.c @@ -125,9 +125,9 @@ static void iree_uk_benchmark_register_unpack(iree_uk_uint32_t flags, for (int i = 0; i < IREE_ARRAYSIZE(variants); ++i) { unpack_variant_t variant = variants[i]; char name[128]; - snprintf(name, sizeof name, "unpack_%s_tile_%dx%d_%s_wss_%" PRIi64, - type_str, tile_size0, tile_size1, variant.label, - FLAG_working_set_size); + iree_snprintf(name, sizeof name, "unpack_%s_tile_%dx%d_%s_wss_%" PRIi64, + type_str, tile_size0, tile_size1, variant.label, + FLAG_working_set_size); params.flags = flags | variant.flags; iree_uk_benchmark_register(name, iree_uk_benchmark_unpack, ¶ms, sizeof params, cpu_features); diff --git a/runtime/src/iree/builtins/ukernel/tools/unpack_test.c b/runtime/src/iree/builtins/ukernel/tools/unpack_test.c index e9468968b28b..c4f1239ab08f 100644 --- a/runtime/src/iree/builtins/ukernel/tools/unpack_test.c +++ b/runtime/src/iree/builtins/ukernel/tools/unpack_test.c @@ -189,8 +189,8 @@ static void iree_uk_test_unpack(iree_uk_uint32_t flags, int tile_size0, iree_uk_unpack_type_t unpack_type = iree_uk_unpack_type(flags); iree_uk_type_pair_str(types_str, sizeof types_str, unpack_type); char test_label_str[256]; - snprintf(test_label_str, sizeof test_label_str, "types:%s tile:%dx%d", - types_str, tile_size0, tile_size1); + iree_snprintf(test_label_str, sizeof test_label_str, "types:%s tile:%dx%d", + types_str, tile_size0, tile_size1); iree_uk_test(test_label_str, iree_uk_test_unpack_for_tile_params, ¶ms, cpu_features); } diff --git a/runtime/src/iree/builtins/ukernel/tools/util.c b/runtime/src/iree/builtins/ukernel/tools/util.c index f852b056a03f..a0f97e07f50a 100644 --- a/runtime/src/iree/builtins/ukernel/tools/util.c +++ b/runtime/src/iree/builtins/ukernel/tools/util.c @@ -190,8 +190,8 @@ static const char* iree_uk_type_category_str(const iree_uk_type_t type) { } int iree_uk_type_str(char* buf, int buf_length, const iree_uk_type_t type) { - return snprintf(buf, buf_length, "%s%d", iree_uk_type_category_str(type), - iree_uk_type_bit_count(type)); + return iree_snprintf(buf, buf_length, "%s%d", iree_uk_type_category_str(type), + iree_uk_type_bit_count(type)); } int iree_uk_type_pair_str(char* buf, int buf_length, @@ -200,7 +200,7 @@ int iree_uk_type_pair_str(char* buf, int buf_length, char type1_buf[8]; iree_uk_type_str(type0_buf, sizeof type0_buf, iree_uk_untie_type(0, pair)); iree_uk_type_str(type1_buf, sizeof type1_buf, iree_uk_untie_type(1, pair)); - return snprintf(buf, buf_length, "%s%s", type0_buf, type1_buf); + return iree_snprintf(buf, buf_length, "%s%s", type0_buf, type1_buf); } int iree_uk_type_triple_str(char* buf, int buf_length, @@ -211,7 +211,8 @@ int iree_uk_type_triple_str(char* buf, int buf_length, iree_uk_type_str(type0_buf, sizeof type0_buf, iree_uk_untie_type(0, triple)); iree_uk_type_str(type1_buf, sizeof type1_buf, iree_uk_untie_type(1, triple)); iree_uk_type_str(type2_buf, sizeof type2_buf, iree_uk_untie_type(2, triple)); - return snprintf(buf, buf_length, "%s%s%s", type0_buf, type1_buf, type2_buf); + return iree_snprintf(buf, buf_length, "%s%s%s", type0_buf, type1_buf, + type2_buf); } static bool iree_uk_map_cpu_feature_name_to_bit(const char* cpu_feature_ptr, diff --git a/runtime/src/iree/hal/command_buffer.c b/runtime/src/iree/hal/command_buffer.c index 5fdfdab100af..ad38ce590abc 100644 --- a/runtime/src/iree/hal/command_buffer.c +++ b/runtime/src/iree/hal/command_buffer.c @@ -86,21 +86,21 @@ IREE_API_EXPORT iree_string_view_t iree_hal_collective_op_format( int length = 0; switch (op->kind) { default: - length = snprintf(out_temp->buffer, sizeof(out_temp->buffer), - "iree_hal_collective_%.*s_%.*s", (int)kind_name.size, - kind_name.data, (int)element_type_name.size, - element_type_name.data); + length = iree_snprintf( + out_temp->buffer, sizeof(out_temp->buffer), + "iree_hal_collective_%.*s_%.*s", (int)kind_name.size, kind_name.data, + (int)element_type_name.size, element_type_name.data); break; case IREE_HAL_COLLECTIVE_KIND_ALL_REDUCE: case IREE_HAL_COLLECTIVE_KIND_REDUCE: case IREE_HAL_COLLECTIVE_KIND_REDUCE_SCATTER: { const iree_string_view_t reduction_name = reduction_names[(int)op->reduction]; - length = snprintf(out_temp->buffer, sizeof(out_temp->buffer), - "iree_hal_collective_%.*s_%.*s_%.*s", - (int)kind_name.size, kind_name.data, - (int)reduction_name.size, reduction_name.data, - (int)element_type_name.size, element_type_name.data); + length = iree_snprintf( + out_temp->buffer, sizeof(out_temp->buffer), + "iree_hal_collective_%.*s_%.*s_%.*s", (int)kind_name.size, + kind_name.data, (int)reduction_name.size, reduction_name.data, + (int)element_type_name.size, element_type_name.data); break; } } @@ -553,9 +553,9 @@ IREE_API_EXPORT iree_status_t iree_hal_command_buffer_dispatch( if (has_static_workgroup_count) { char xyz_string[32]; int xyz_string_length = - snprintf(xyz_string, IREE_ARRAYSIZE(xyz_string), "%ux%ux%u", - config.workgroup_count[0], config.workgroup_count[1], - config.workgroup_count[2]); + iree_snprintf(xyz_string, IREE_ARRAYSIZE(xyz_string), "%ux%ux%u", + config.workgroup_count[0], config.workgroup_count[1], + config.workgroup_count[2]); IREE_TRACE_ZONE_APPEND_TEXT(z0, xyz_string, xyz_string_length); } else { IREE_TRACE_ZONE_APPEND_TEXT(z0, "(indirect)"); diff --git a/runtime/src/iree/hal/drivers/amdgpu/host_service.c b/runtime/src/iree/hal/drivers/amdgpu/host_service.c index a323e5f46562..20f699e9ceed 100644 --- a/runtime/src/iree/hal/drivers/amdgpu/host_service.c +++ b/runtime/src/iree/hal/drivers/amdgpu/host_service.c @@ -496,9 +496,9 @@ iree_status_t iree_hal_amdgpu_host_service_initialize( // The worker may start immediately and use the queue/doorbell. if (iree_status_is_ok(status)) { char thread_name[32]; - snprintf(thread_name, IREE_ARRAYSIZE(thread_name), - "iree-amdgpu-host-%" PRIhsz "-%" PRIhsz, host_ordinal, - device_ordinal); + iree_snprintf(thread_name, IREE_ARRAYSIZE(thread_name), + "iree-amdgpu-host-%" PRIhsz "-%" PRIhsz, host_ordinal, + device_ordinal); const iree_thread_create_params_t thread_params = { .name = iree_make_cstring_view(thread_name), .stack_size = 0, // default diff --git a/runtime/src/iree/hal/drivers/amdgpu/util/libhsa.c b/runtime/src/iree/hal/drivers/amdgpu/util/libhsa.c index 9afa57f7420a..58b02a436325 100644 --- a/runtime/src/iree/hal/drivers/amdgpu/util/libhsa.c +++ b/runtime/src/iree/hal/drivers/amdgpu/util/libhsa.c @@ -248,34 +248,6 @@ static iree_status_t iree_hal_amdgpu_libhsa_load_symbols( return iree_ok_status(); } -// TODO(benvanik): move someplace central - status and string_builder have a -// cycle and it's tricky to move there right now. -static bool iree_string_builder_append_status(iree_string_builder_t* builder, - iree_status_t status) { - // Calculate total length minus the NUL terminator. - iree_host_size_t buffer_length = 0; - if (IREE_UNLIKELY(!iree_status_format(status, /*buffer_capacity=*/0, - /*buffer=*/NULL, &buffer_length))) { - return false; - } - - // Buffer capacity needs to be +1 for the NUL terminator (see snprintf). - char* buffer = NULL; - iree_status_t append_status = - iree_string_builder_append_inline(builder, buffer_length, &buffer); - if (!iree_status_is_ok(append_status)) { - iree_status_ignore(append_status); - return false; - } - if (!buffer) { - // Size calculation mode; builder has been updated but no need to format. - return true; - } - - // Format into the buffer. - return iree_status_format(status, buffer_length + 1, buffer, &buffer_length); -} - static bool iree_hal_amdgpu_libhsa_try_load_library_from_file( iree_hal_amdgpu_libhsa_flags_t flags, const char* file_path, iree_string_builder_t* error_builder, iree_allocator_t host_allocator, @@ -293,7 +265,7 @@ static bool iree_hal_amdgpu_libhsa_try_load_library_from_file( if (!iree_status_is_ok(status)) { IREE_IGNORE_ERROR(iree_string_builder_append_format( error_builder, "\n Tried: %s\n ", file_path)); - iree_string_builder_append_status(error_builder, status); + IREE_IGNORE_ERROR(iree_string_builder_append_status(error_builder, status)); } iree_status_ignore(status); diff --git a/runtime/src/iree/hal/drivers/cuda/cuda_driver.c b/runtime/src/iree/hal/drivers/cuda/cuda_driver.c index e30198682cd8..a456c675db0f 100644 --- a/runtime/src/iree/hal/drivers/cuda/cuda_driver.c +++ b/runtime/src/iree/hal/drivers/cuda/cuda_driver.c @@ -158,21 +158,21 @@ static iree_status_t iree_hal_cuda_populate_device_info( IREE_CUDA_RETURN_IF_ERROR(syms, cuDeviceGetUuid(&device_uuid, device), "cuDeviceGetUuid"); char device_path_str[4 + 36 + 1] = {0}; - snprintf(device_path_str, sizeof(device_path_str), - "GPU-" - "%02x%02x%02x%02x-" - "%02x%02x-" - "%02x%02x-" - "%02x%02x-" - "%02x%02x%02x%02x%02x%02x", - (uint8_t)device_uuid.bytes[0], (uint8_t)device_uuid.bytes[1], - (uint8_t)device_uuid.bytes[2], (uint8_t)device_uuid.bytes[3], - (uint8_t)device_uuid.bytes[4], (uint8_t)device_uuid.bytes[5], - (uint8_t)device_uuid.bytes[6], (uint8_t)device_uuid.bytes[7], - (uint8_t)device_uuid.bytes[8], (uint8_t)device_uuid.bytes[9], - (uint8_t)device_uuid.bytes[10], (uint8_t)device_uuid.bytes[11], - (uint8_t)device_uuid.bytes[12], (uint8_t)device_uuid.bytes[13], - (uint8_t)device_uuid.bytes[14], (uint8_t)device_uuid.bytes[15]); + iree_snprintf(device_path_str, sizeof(device_path_str), + "GPU-" + "%02x%02x%02x%02x-" + "%02x%02x-" + "%02x%02x-" + "%02x%02x-" + "%02x%02x%02x%02x%02x%02x", + (uint8_t)device_uuid.bytes[0], (uint8_t)device_uuid.bytes[1], + (uint8_t)device_uuid.bytes[2], (uint8_t)device_uuid.bytes[3], + (uint8_t)device_uuid.bytes[4], (uint8_t)device_uuid.bytes[5], + (uint8_t)device_uuid.bytes[6], (uint8_t)device_uuid.bytes[7], + (uint8_t)device_uuid.bytes[8], (uint8_t)device_uuid.bytes[9], + (uint8_t)device_uuid.bytes[10], (uint8_t)device_uuid.bytes[11], + (uint8_t)device_uuid.bytes[12], (uint8_t)device_uuid.bytes[13], + (uint8_t)device_uuid.bytes[14], (uint8_t)device_uuid.bytes[15]); buffer_ptr += iree_string_view_append_to_buffer( iree_make_string_view(device_path_str, IREE_ARRAYSIZE(device_path_str) - 1), diff --git a/runtime/src/iree/hal/drivers/hip/dynamic_symbols.c b/runtime/src/iree/hal/drivers/hip/dynamic_symbols.c index 7e3dbc7496b5..9830a2dc62f5 100644 --- a/runtime/src/iree/hal/drivers/hip/dynamic_symbols.c +++ b/runtime/src/iree/hal/drivers/hip/dynamic_symbols.c @@ -61,14 +61,9 @@ static bool iree_hal_hip_try_load_dylib(const char* file_path, return true; } - char* buffer = NULL; - iree_host_size_t length = 0; - if (iree_status_to_string(status, &allocator, &buffer, &length)) { - iree_status_ignore(iree_string_builder_append_format( - error_builder, "\n Tried: %s\n %.*s", file_path, (int)length, - buffer)); - iree_allocator_free(allocator, buffer); - } + IREE_IGNORE_ERROR(iree_string_builder_append_format( + error_builder, "\n Tried: %s\n ", file_path)); + IREE_IGNORE_ERROR(iree_string_builder_append_status(error_builder, status)); iree_status_ignore(status); return false; diff --git a/runtime/src/iree/hal/drivers/hip/hip_driver.c b/runtime/src/iree/hal/drivers/hip/hip_driver.c index 7c00a5adde16..426a33d597b6 100644 --- a/runtime/src/iree/hal/drivers/hip/hip_driver.c +++ b/runtime/src/iree/hal/drivers/hip/hip_driver.c @@ -162,21 +162,21 @@ static iree_status_t iree_hal_hip_populate_device_info( IREE_HIP_RETURN_IF_ERROR(syms, hipDeviceGetUuid(&device_uuid, device), "hipDeviceGetUuid"); char device_path_str[4 + 36 + 1] = {0}; - snprintf(device_path_str, sizeof(device_path_str), - "GPU-" - "%02x%02x%02x%02x-" - "%02x%02x-" - "%02x%02x-" - "%02x%02x-" - "%02x%02x%02x%02x%02x%02x", - (uint8_t)device_uuid.bytes[0], (uint8_t)device_uuid.bytes[1], - (uint8_t)device_uuid.bytes[2], (uint8_t)device_uuid.bytes[3], - (uint8_t)device_uuid.bytes[4], (uint8_t)device_uuid.bytes[5], - (uint8_t)device_uuid.bytes[6], (uint8_t)device_uuid.bytes[7], - (uint8_t)device_uuid.bytes[8], (uint8_t)device_uuid.bytes[9], - (uint8_t)device_uuid.bytes[10], (uint8_t)device_uuid.bytes[11], - (uint8_t)device_uuid.bytes[12], (uint8_t)device_uuid.bytes[13], - (uint8_t)device_uuid.bytes[14], (uint8_t)device_uuid.bytes[15]); + iree_snprintf(device_path_str, sizeof(device_path_str), + "GPU-" + "%02x%02x%02x%02x-" + "%02x%02x-" + "%02x%02x-" + "%02x%02x-" + "%02x%02x%02x%02x%02x%02x", + (uint8_t)device_uuid.bytes[0], (uint8_t)device_uuid.bytes[1], + (uint8_t)device_uuid.bytes[2], (uint8_t)device_uuid.bytes[3], + (uint8_t)device_uuid.bytes[4], (uint8_t)device_uuid.bytes[5], + (uint8_t)device_uuid.bytes[6], (uint8_t)device_uuid.bytes[7], + (uint8_t)device_uuid.bytes[8], (uint8_t)device_uuid.bytes[9], + (uint8_t)device_uuid.bytes[10], (uint8_t)device_uuid.bytes[11], + (uint8_t)device_uuid.bytes[12], (uint8_t)device_uuid.bytes[13], + (uint8_t)device_uuid.bytes[14], (uint8_t)device_uuid.bytes[15]); buffer_ptr += iree_string_view_append_to_buffer( iree_make_string_view(device_path_str, IREE_ARRAYSIZE(device_path_str) - 1), diff --git a/runtime/src/iree/hal/drivers/metal/metal_driver.m b/runtime/src/iree/hal/drivers/metal/metal_driver.m index a83191702420..a15d2414acc2 100644 --- a/runtime/src/iree/hal/drivers/metal/metal_driver.m +++ b/runtime/src/iree/hal/drivers/metal/metal_driver.m @@ -134,7 +134,7 @@ static iree_status_t iree_hal_metal_populate_device_info(id device, u // For Metal devices, we don't have a 128-bit UUID; so just use the 64-bit registry ID here. char device_path[16 + 1] = {0}; - snprintf(device_path, sizeof(device_path), "%016" PRIx64, device.registryID); + iree_snprintf(device_path, sizeof(device_path), "%016" PRIx64, device.registryID); buffer_ptr += iree_string_view_append_to_buffer( iree_make_string_view(device_path, IREE_ARRAYSIZE(device_path) - 1), &out_device_info->path, (char*)buffer_ptr); diff --git a/runtime/src/iree/hal/drivers/vulkan/direct_command_buffer.cc b/runtime/src/iree/hal/drivers/vulkan/direct_command_buffer.cc index 3a7d89fa7955..0d37f8908262 100644 --- a/runtime/src/iree/hal/drivers/vulkan/direct_command_buffer.cc +++ b/runtime/src/iree/hal/drivers/vulkan/direct_command_buffer.cc @@ -240,8 +240,8 @@ static iree_status_t iree_hal_vulkan_direct_command_buffer_begin_debug_group( label.size); if (command_buffer->syms->vkCmdBeginDebugUtilsLabelEXT) { char label_buffer[128]; - snprintf(label_buffer, sizeof(label_buffer), "%.*s", (int)label.size, - label.data); + iree_snprintf(label_buffer, sizeof(label_buffer), "%.*s", (int)label.size, + label.data); VkDebugUtilsLabelEXT label_info = { /*.sType=*/VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, /*.pNext=*/NULL, diff --git a/runtime/src/iree/hal/drivers/vulkan/vulkan_device.cc b/runtime/src/iree/hal/drivers/vulkan/vulkan_device.cc index d7abf33017e1..76c0c719d372 100644 --- a/runtime/src/iree/hal/drivers/vulkan/vulkan_device.cc +++ b/runtime/src/iree/hal/drivers/vulkan/vulkan_device.cc @@ -625,8 +625,8 @@ static iree_status_t iree_hal_vulkan_device_initialize_command_queues( char queue_name_buffer[32]; int queue_name_length = - snprintf(queue_name_buffer, IREE_ARRAYSIZE(queue_name_buffer), - "Vulkan[%c:%d]", 'D', (int)device->dispatch_queue_count); + iree_snprintf(queue_name_buffer, IREE_ARRAYSIZE(queue_name_buffer), + "Vulkan[%c:%d]", 'D', (int)device->dispatch_queue_count); iree_string_view_t queue_name = iree_make_string_view(queue_name_buffer, queue_name_length); @@ -663,8 +663,8 @@ static iree_status_t iree_hal_vulkan_device_initialize_command_queues( char queue_name_buffer[32]; int queue_name_length = - snprintf(queue_name_buffer, IREE_ARRAYSIZE(queue_name_buffer), - "Vulkan[%c:%d]", 'T', (int)device->transfer_queue_count); + iree_snprintf(queue_name_buffer, IREE_ARRAYSIZE(queue_name_buffer), + "Vulkan[%c:%d]", 'T', (int)device->transfer_queue_count); iree_string_view_t queue_name = iree_make_string_view(queue_name_buffer, queue_name_length); diff --git a/runtime/src/iree/hal/drivers/vulkan/vulkan_driver.cc b/runtime/src/iree/hal/drivers/vulkan/vulkan_driver.cc index acc42d5ed3e2..30748f83e35c 100644 --- a/runtime/src/iree/hal/drivers/vulkan/vulkan_driver.cc +++ b/runtime/src/iree/hal/drivers/vulkan/vulkan_driver.cc @@ -407,16 +407,17 @@ static uint8_t* iree_hal_vulkan_populate_device_info_if_visible( // Use the deviceUUID - which is _mostly_ persistent - as the primary path. const uint8_t* device_uuid = device_id_props.deviceUUID; char device_path_str[IREE_HAL_VULKAN_DEVICE_UUID_TEXT_LENGTH + 1] = {0}; - snprintf(device_path_str, sizeof(device_path_str), - "%02x%02x%02x%02x-" - "%02x%02x-" - "%02x%02x-" - "%02x%02x-" - "%02x%02x%02x%02x%02x%02x", - device_uuid[0], device_uuid[1], device_uuid[2], device_uuid[3], - device_uuid[4], device_uuid[5], device_uuid[6], device_uuid[7], - device_uuid[8], device_uuid[9], device_uuid[10], device_uuid[11], - device_uuid[12], device_uuid[13], device_uuid[14], device_uuid[15]); + iree_snprintf(device_path_str, sizeof(device_path_str), + "%02x%02x%02x%02x-" + "%02x%02x-" + "%02x%02x-" + "%02x%02x-" + "%02x%02x%02x%02x%02x%02x", + device_uuid[0], device_uuid[1], device_uuid[2], device_uuid[3], + device_uuid[4], device_uuid[5], device_uuid[6], device_uuid[7], + device_uuid[8], device_uuid[9], device_uuid[10], + device_uuid[11], device_uuid[12], device_uuid[13], + device_uuid[14], device_uuid[15]); iree_string_view_t device_path = iree_make_string_view( device_path_str, IREE_ARRAYSIZE(device_path_str) - 1); buffer_ptr += iree_string_view_append_to_buffer( diff --git a/runtime/src/iree/hal/local/local_executable.c b/runtime/src/iree/hal/local/local_executable.c index b9c8d04d04d8..4db2d1c14698 100644 --- a/runtime/src/iree/hal/local/local_executable.c +++ b/runtime/src/iree/hal/local/local_executable.c @@ -61,8 +61,8 @@ iree_status_t iree_hal_local_executable_issue_dispatch_inline( IREE_TRACE({ char xyz_string[32]; int xyz_string_length = - snprintf(xyz_string, IREE_ARRAYSIZE(xyz_string), "%ux%ux%u", - workgroup_count_x, workgroup_count_y, workgroup_count_z); + iree_snprintf(xyz_string, IREE_ARRAYSIZE(xyz_string), "%ux%ux%u", + workgroup_count_x, workgroup_count_y, workgroup_count_z); IREE_TRACE_ZONE_APPEND_TEXT(z0, xyz_string, xyz_string_length); }); #endif // IREE_HAL_VERBOSE_TRACING_ENABLE diff --git a/runtime/src/iree/hal/string_util.c b/runtime/src/iree/hal/string_util.c index d597770c1761..7a7b72f50c11 100644 --- a/runtime/src/iree/hal/string_util.c +++ b/runtime/src/iree/hal/string_util.c @@ -87,10 +87,10 @@ iree_hal_format_shape(iree_host_size_t shape_rank, const iree_hal_dim_t* shape, } iree_host_size_t buffer_length = 0; for (iree_host_size_t i = 0; i < shape_rank; ++i) { - int n = - snprintf(buffer ? buffer + buffer_length : NULL, - buffer ? buffer_capacity - buffer_length : 0, - (i < shape_rank - 1) ? "%" PRIdim "x" : "%" PRIdim, shape[i]); + int n = iree_snprintf(buffer ? buffer + buffer_length : NULL, + buffer ? buffer_capacity - buffer_length : 0, + (i < shape_rank - 1) ? "%" PRIdim "x" : "%" PRIdim, + shape[i]); if (IREE_UNLIKELY(n < 0)) { return iree_make_status(IREE_STATUS_FAILED_PRECONDITION, "snprintf failed to write dimension %" PRIhsz, i); @@ -200,7 +200,7 @@ IREE_API_EXPORT iree_status_t iree_hal_format_element_type( break; } if (special_name) { - int n = snprintf(buffer, buffer_capacity, "%s", special_name); + int n = iree_snprintf(buffer, buffer_capacity, "%s", special_name); if (n < 0) { return iree_make_status(IREE_STATUS_FAILED_PRECONDITION, "snprintf failed"); @@ -245,7 +245,7 @@ IREE_API_EXPORT iree_status_t iree_hal_format_element_type( prefix = "*"; break; } - int n = snprintf(buffer, buffer_capacity, "%s%d", prefix, bit_count); + int n = iree_snprintf(buffer, buffer_capacity, "%s%d", prefix, bit_count); if (n < 0) { return iree_make_status(IREE_STATUS_FAILED_PRECONDITION, "snprintf failed"); } @@ -568,75 +568,77 @@ IREE_API_EXPORT iree_status_t iree_hal_format_element( switch (element_type) { case IREE_HAL_ELEMENT_TYPE_INT_8: case IREE_HAL_ELEMENT_TYPE_SINT_8: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIi8, - *(const int8_t*)data.data); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIi8, + *(const int8_t*)data.data); break; case IREE_HAL_ELEMENT_TYPE_UINT_8: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIu8, - *(const uint8_t*)data.data); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIu8, + *(const uint8_t*)data.data); break; case IREE_HAL_ELEMENT_TYPE_INT_16: case IREE_HAL_ELEMENT_TYPE_SINT_16: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIi16, - *(const int16_t*)data.data); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIi16, + *(const int16_t*)data.data); break; case IREE_HAL_ELEMENT_TYPE_UINT_16: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIu16, - *(const uint16_t*)data.data); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIu16, + *(const uint16_t*)data.data); break; case IREE_HAL_ELEMENT_TYPE_INT_32: case IREE_HAL_ELEMENT_TYPE_SINT_32: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIi32, - *(const int32_t*)data.data); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIi32, + *(const int32_t*)data.data); break; case IREE_HAL_ELEMENT_TYPE_UINT_32: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIu32, - *(const uint32_t*)data.data); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIu32, + *(const uint32_t*)data.data); break; case IREE_HAL_ELEMENT_TYPE_INT_64: case IREE_HAL_ELEMENT_TYPE_SINT_64: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIi64, - *(const int64_t*)data.data); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIi64, + *(const int64_t*)data.data); break; case IREE_HAL_ELEMENT_TYPE_UINT_64: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIu64, - *(const uint64_t*)data.data); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%" PRIu64, + *(const uint64_t*)data.data); break; case IREE_HAL_ELEMENT_TYPE_FLOAT_8_E4M3_FN: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%G", - iree_math_f8e4m3fn_to_f32(*(const uint8_t*)data.data)); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%G", + iree_math_f8e4m3fn_to_f32(*(const uint8_t*)data.data)); break; case IREE_HAL_ELEMENT_TYPE_FLOAT_8_E4M3_FNUZ: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%G", - iree_math_f8e4m3fnuz_to_f32(*(const uint8_t*)data.data)); + n = iree_snprintf( + buffer, buffer ? buffer_capacity : 0, "%G", + iree_math_f8e4m3fnuz_to_f32(*(const uint8_t*)data.data)); break; case IREE_HAL_ELEMENT_TYPE_FLOAT_8_E5M2: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%G", - iree_math_f8e5m2_to_f32(*(const uint8_t*)data.data)); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%G", + iree_math_f8e5m2_to_f32(*(const uint8_t*)data.data)); break; case IREE_HAL_ELEMENT_TYPE_FLOAT_8_E5M2_FNUZ: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%G", - iree_math_f8e5m2fnuz_to_f32(*(const uint8_t*)data.data)); + n = iree_snprintf( + buffer, buffer ? buffer_capacity : 0, "%G", + iree_math_f8e5m2fnuz_to_f32(*(const uint8_t*)data.data)); break; case IREE_HAL_ELEMENT_TYPE_FLOAT_8_E8M0_FNU: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%G", - iree_math_f8e8m0fnu_to_f32(*(const uint8_t*)data.data)); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%G", + iree_math_f8e8m0fnu_to_f32(*(const uint8_t*)data.data)); break; case IREE_HAL_ELEMENT_TYPE_BFLOAT_16: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%G", - iree_math_bf16_to_f32(*(const uint16_t*)data.data)); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%G", + iree_math_bf16_to_f32(*(const uint16_t*)data.data)); break; case IREE_HAL_ELEMENT_TYPE_FLOAT_16: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%G", - iree_math_f16_to_f32(*(const uint16_t*)data.data)); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%G", + iree_math_f16_to_f32(*(const uint16_t*)data.data)); break; case IREE_HAL_ELEMENT_TYPE_FLOAT_32: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%G", - *(const float*)data.data); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%G", + *(const float*)data.data); break; case IREE_HAL_ELEMENT_TYPE_FLOAT_64: - n = snprintf(buffer, buffer ? buffer_capacity : 0, "%G", - *(const double*)data.data); + n = iree_snprintf(buffer, buffer ? buffer_capacity : 0, "%G", + *(const double*)data.data); break; default: { // Treat any unknown format as binary. diff --git a/runtime/src/iree/hal/utils/platform_topology_sysfs.c b/runtime/src/iree/hal/utils/platform_topology_sysfs.c index 240f8ca2129d..31bc240a6340 100644 --- a/runtime/src/iree/hal/utils/platform_topology_sysfs.c +++ b/runtime/src/iree/hal/utils/platform_topology_sysfs.c @@ -23,7 +23,8 @@ iree_host_size_t iree_hal_platform_query_numa_node_count_impl(void) { // Read /sys/devices/system/node/online to get the list of online NUMA nodes. // Format: "0-3" (4 nodes) or "0" (single node) or "0,2-4" (nodes 0,2,3,4). char path[256]; - snprintf(path, sizeof(path), "%s/node/online", iree_sysfs_get_root_path()); + iree_snprintf(path, sizeof(path), "%s/node/online", + iree_sysfs_get_root_path()); char buffer[256]; iree_host_size_t length = 0; @@ -101,8 +102,8 @@ iree_status_t iree_hal_platform_query_numa_distance_impl( // Format: space-separated list of distances from node A to all other nodes. // Example (4-node system): "10 20 20 20" (node 0 distances to 0,1,2,3). char path[256]; - snprintf(path, sizeof(path), "%s/node/node%u/distance", - iree_sysfs_get_root_path(), node_a); + iree_snprintf(path, sizeof(path), "%s/node/node%u/distance", + iree_sysfs_get_root_path(), node_a); char buffer[1024]; iree_host_size_t length = 0; @@ -175,12 +176,12 @@ static iree_status_t iree_hal_platform_query_pcie_root_hash( // Construct path: /sys/bus/pci/devices/::./ char device_path[256]; - snprintf(device_path, sizeof(device_path), - "/sys/bus/pci/devices/%04x:%02x:%02x.%x", - iree_hal_platform_pcie_bdf_domain(bdf), - iree_hal_platform_pcie_bdf_bus(bdf), - iree_hal_platform_pcie_bdf_device(bdf), - iree_hal_platform_pcie_bdf_function(bdf)); + iree_snprintf(device_path, sizeof(device_path), + "/sys/bus/pci/devices/%04x:%02x:%02x.%x", + iree_hal_platform_pcie_bdf_domain(bdf), + iree_hal_platform_pcie_bdf_bus(bdf), + iree_hal_platform_pcie_bdf_device(bdf), + iree_hal_platform_pcie_bdf_function(bdf)); // Read the device link to find the root complex. // We'll use domain+bus as a simple hash. @@ -238,8 +239,8 @@ iree_status_t iree_hal_platform_query_pcie_bdf_from_path_impl( device_path) { // Read properties file. char properties_path[512]; - snprintf(properties_path, sizeof(properties_path), "%s/properties", - device_path); + iree_snprintf(properties_path, sizeof(properties_path), "%s/properties", + device_path); char buffer[4096]; iree_host_size_t length = 0; diff --git a/runtime/src/iree/io/file_contents_test.cc b/runtime/src/iree/io/file_contents_test.cc index a870281d573e..54cc9ce2444a 100644 --- a/runtime/src/iree/io/file_contents_test.cc +++ b/runtime/src/iree/io/file_contents_test.cc @@ -56,8 +56,8 @@ static std::string GetUniquePath(const char* unique_name) { // just a random 64bit value. char unique_path[256]; std::uint64_t random = GetTrueRandomUint64(); - snprintf(unique_path, sizeof unique_path, "%s/iree_test_%" PRIx64 "_%s", - test_tmpdir, random, unique_name); + iree_snprintf(unique_path, sizeof unique_path, "%s/iree_test_%" PRIx64 "_%s", + test_tmpdir, random, unique_name); return unique_path; } diff --git a/runtime/src/iree/task/executor.c b/runtime/src/iree/task/executor.c index ca719d1f2be8..7b8e7b6c3dc4 100644 --- a/runtime/src/iree/task/executor.c +++ b/runtime/src/iree/task/executor.c @@ -103,7 +103,7 @@ iree_status_t iree_task_executor_create(iree_task_executor_options_t options, IREE_TRACE({ static iree_atomic_int32_t executor_id = IREE_ATOMIC_VAR_INIT(0); char trace_name[32]; - int trace_name_length = snprintf( + int trace_name_length = iree_snprintf( trace_name, sizeof(trace_name), "iree-executor-%d", iree_atomic_fetch_add(&executor_id, 1, iree_memory_order_seq_cst)); IREE_LEAK_CHECK_DISABLE_PUSH(); diff --git a/runtime/src/iree/task/task.c b/runtime/src/iree/task/task.c index d0e40103e814..f9698a393c21 100644 --- a/runtime/src/iree/task/task.c +++ b/runtime/src/iree/task/task.c @@ -588,9 +588,9 @@ void iree_task_dispatch_issue(iree_task_dispatch_t* dispatch_task, // TODO(benvanik): tracing.h helper that speeds this up; too slow. IREE_TRACE({ char xyz_string[32]; - int xyz_string_length = - snprintf(xyz_string, IREE_ARRAYSIZE(xyz_string), "%ux%ux%u", - workgroup_count[0], workgroup_count[1], workgroup_count[2]); + int xyz_string_length = iree_snprintf( + xyz_string, IREE_ARRAYSIZE(xyz_string), "%ux%ux%u", workgroup_count[0], + workgroup_count[1], workgroup_count[2]); IREE_TRACE_ZONE_APPEND_TEXT(z0, xyz_string, xyz_string_length); }); #endif // IREE_HAL_VERBOSE_TRACING_ENABLE diff --git a/runtime/src/iree/task/topology.c b/runtime/src/iree/task/topology.c index 5b0fe94cbb36..3fc11260806e 100644 --- a/runtime/src/iree/task/topology.c +++ b/runtime/src/iree/task/topology.c @@ -15,8 +15,8 @@ void iree_task_topology_group_initialize( uint8_t group_index, iree_task_topology_group_t* out_group) { memset(out_group, 0, sizeof(*out_group)); out_group->group_index = group_index; - snprintf(out_group->name, IREE_ARRAYSIZE(out_group->name), "iree-worker-%u", - group_index); + iree_snprintf(out_group->name, IREE_ARRAYSIZE(out_group->name), + "iree-worker-%u", group_index); iree_thread_affinity_set_any(&out_group->ideal_thread_affinity); out_group->constructive_sharing_mask = IREE_TASK_TOPOLOGY_GROUP_MASK_ALL; } diff --git a/runtime/src/iree/task/topology_sysfs.c b/runtime/src/iree/task/topology_sysfs.c index 36ccd64d0e5d..b45c1134f328 100644 --- a/runtime/src/iree/task/topology_sysfs.c +++ b/runtime/src/iree/task/topology_sysfs.c @@ -63,7 +63,8 @@ static bool iree_sysfs_count_cpus_callback(uint32_t start_cpu, uint32_t end_cpu, static uint32_t iree_sysfs_query_processor_count(void) { // Try /sys/devices/system/cpu/present first (most reliable). char path[256]; - snprintf(path, sizeof(path), "%s/cpu/present", iree_sysfs_get_root_path()); + iree_snprintf(path, sizeof(path), "%s/cpu/present", + iree_sysfs_get_root_path()); char buffer[256]; iree_host_size_t length = 0; iree_status_t status = @@ -80,7 +81,8 @@ static uint32_t iree_sysfs_query_processor_count(void) { iree_status_ignore(status); // Fallback to /sys/devices/system/cpu/kernel_max. - snprintf(path, sizeof(path), "%s/cpu/kernel_max", iree_sysfs_get_root_path()); + iree_snprintf(path, sizeof(path), "%s/cpu/kernel_max", + iree_sysfs_get_root_path()); uint32_t kernel_max = 0; status = iree_sysfs_read_uint32(path, &kernel_max); if (iree_status_is_ok(status)) { @@ -96,8 +98,8 @@ static uint32_t iree_sysfs_query_processor_count(void) { static iree_status_t iree_sysfs_query_core_id(uint32_t processor, uint32_t* out_core_id) { char path[256]; - snprintf(path, sizeof(path), "%s/cpu/cpu%u/topology/core_id", - iree_sysfs_get_root_path(), processor); + iree_snprintf(path, sizeof(path), "%s/cpu/cpu%u/topology/core_id", + iree_sysfs_get_root_path(), processor); return iree_sysfs_read_uint32(path, out_core_id); } @@ -130,8 +132,8 @@ static iree_status_t iree_sysfs_query_cluster_id(uint32_t processor, char path[256]; // Try cluster_id first (kernel 5.16+). - snprintf(path, sizeof(path), "%s/cpu/cpu%u/topology/cluster_id", - iree_sysfs_get_root_path(), processor); + iree_snprintf(path, sizeof(path), "%s/cpu/cpu%u/topology/cluster_id", + iree_sysfs_get_root_path(), processor); iree_status_t status = iree_sysfs_read_uint32(path, out_cluster_id); if (iree_status_is_ok(status)) { return status; @@ -139,8 +141,8 @@ static iree_status_t iree_sysfs_query_cluster_id(uint32_t processor, iree_status_ignore(status); // Fallback to physical_package_id (socket/package). - snprintf(path, sizeof(path), "%s/cpu/cpu%u/topology/physical_package_id", - iree_sysfs_get_root_path(), processor); + iree_snprintf(path, sizeof(path), "%s/cpu/cpu%u/topology/physical_package_id", + iree_sysfs_get_root_path(), processor); status = iree_sysfs_read_uint32(path, out_cluster_id); if (iree_status_is_ok(status)) { return status; @@ -158,8 +160,8 @@ static iree_status_t iree_sysfs_query_cluster_id(uint32_t processor, // Returns 0 if not available (x86 systems or older kernels). static uint32_t iree_sysfs_query_cpu_capacity(uint32_t processor) { char path[256]; - snprintf(path, sizeof(path), "%s/cpu/cpu%u/cpu_capacity", - iree_sysfs_get_root_path(), processor); + iree_snprintf(path, sizeof(path), "%s/cpu/cpu%u/cpu_capacity", + iree_sysfs_get_root_path(), processor); uint32_t capacity = 0; iree_status_ignore(iree_sysfs_read_uint32(path, &capacity)); return capacity; @@ -187,8 +189,8 @@ static iree_status_t iree_sysfs_query_cache_level( // Read cache type (Data, Instruction, or Unified). // If this fails the cache index doesn't exist. char path[256]; - snprintf(path, sizeof(path), "%s/cpu/cpu%u/cache/index%u/type", - iree_sysfs_get_root_path(), processor, cache_index); + iree_snprintf(path, sizeof(path), "%s/cpu/cpu%u/cache/index%u/type", + iree_sysfs_get_root_path(), processor, cache_index); char buffer[64]; iree_host_size_t length = 0; IREE_RETURN_IF_ERROR( @@ -201,15 +203,15 @@ static iree_status_t iree_sysfs_query_cache_level( iree_string_view_starts_with(type_str, IREE_SV("Unified")); // Read cache level (optional - ignore failures). - snprintf(path, sizeof(path), "%s/cpu/cpu%u/cache/index%u/level", - iree_sysfs_get_root_path(), processor, cache_index); + iree_snprintf(path, sizeof(path), "%s/cpu/cpu%u/cache/index%u/level", + iree_sysfs_get_root_path(), processor, cache_index); uint32_t level = 0; iree_status_ignore(iree_sysfs_read_uint32(path, &level)); out_cache->level = level; // Read cache size (optional - ignore failures). - snprintf(path, sizeof(path), "%s/cpu/cpu%u/cache/index%u/size", - iree_sysfs_get_root_path(), processor, cache_index); + iree_snprintf(path, sizeof(path), "%s/cpu/cpu%u/cache/index%u/size", + iree_sysfs_get_root_path(), processor, cache_index); uint64_t size = 0; iree_status_ignore(iree_sysfs_read_size(path, &size)); out_cache->size = size; @@ -333,8 +335,9 @@ static bool iree_sysfs_read_cache_shared_cpu_list(uint32_t processor, uint32_t cache_index, cpu_set_t* out_mask) { char path[256]; - snprintf(path, sizeof(path), "%s/cpu/cpu%u/cache/index%u/shared_cpu_list", - iree_sysfs_get_root_path(), processor, cache_index); + iree_snprintf(path, sizeof(path), + "%s/cpu/cpu%u/cache/index%u/shared_cpu_list", + iree_sysfs_get_root_path(), processor, cache_index); char buffer[256]; iree_host_size_t length = 0; diff --git a/runtime/src/iree/testing/coordinated_test.c b/runtime/src/iree/testing/coordinated_test.c index 83d8fca2fcae..832339d46608 100644 --- a/runtime/src/iree/testing/coordinated_test.c +++ b/runtime/src/iree/testing/coordinated_test.c @@ -377,8 +377,8 @@ static char* iree_coordinated_test_make_temp_dir(void) { DWORD pid = GetCurrentProcessId(); long count = InterlockedIncrement(&counter); char path[MAX_PATH]; - snprintf(path, sizeof(path), "%siree_ct_%lu_%ld", parent, (unsigned long)pid, - count); + iree_snprintf(path, sizeof(path), "%siree_ct_%lu_%ld", parent, + (unsigned long)pid, count); if (CreateDirectoryA(path, NULL)) { result = _strdup(path); } @@ -391,12 +391,12 @@ static char* iree_coordinated_test_make_temp_dir(void) { // produce is "/carrier.sock" (13 chars + NUL). // If TEST_TMPDIR is too long, fall back to /tmp. char template_path[256]; - int written = snprintf(template_path, sizeof(template_path), - "%s/iree_ct_XXXXXX", parent); + int written = iree_snprintf(template_path, sizeof(template_path), + "%s/iree_ct_XXXXXX", parent); if (written < 0 || (iree_host_size_t)written >= sizeof(template_path) || written + 14 > 107) { // Path too long for sun_path — fall back to /tmp. - snprintf(template_path, sizeof(template_path), "/tmp/iree_ct_XXXXXX"); + iree_snprintf(template_path, sizeof(template_path), "/tmp/iree_ct_XXXXXX"); } if (mkdtemp(template_path)) { result = strdup(template_path); @@ -417,7 +417,7 @@ static void iree_coordinated_test_remove_temp_dir(const char* path) { #if defined(IREE_PLATFORM_WINDOWS) char search_path[MAX_PATH]; - snprintf(search_path, sizeof(search_path), "%s\\*", path); + iree_snprintf(search_path, sizeof(search_path), "%s\\*", path); WIN32_FIND_DATAA find_data; HANDLE find_handle = FindFirstFileA(search_path, &find_data); if (find_handle != INVALID_HANDLE_VALUE) { @@ -426,8 +426,8 @@ static void iree_coordinated_test_remove_temp_dir(const char* path) { strcmp(find_data.cFileName, "..") == 0) continue; char child_path[MAX_PATH]; - snprintf(child_path, sizeof(child_path), "%s\\%s", path, - find_data.cFileName); + iree_snprintf(child_path, sizeof(child_path), "%s\\%s", path, + find_data.cFileName); if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { iree_coordinated_test_remove_temp_dir(child_path); } else { @@ -446,7 +446,8 @@ static void iree_coordinated_test_remove_temp_dir(const char* path) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; char child_path[512]; - snprintf(child_path, sizeof(child_path), "%s/%s", path, entry->d_name); + iree_snprintf(child_path, sizeof(child_path), "%s/%s", path, + entry->d_name); struct stat st; if (stat(child_path, &st) == 0 && S_ISDIR(st.st_mode)) { iree_coordinated_test_remove_temp_dir(child_path); @@ -469,7 +470,7 @@ static void iree_coordinated_test_remove_temp_dir(const char* path) { void iree_coordinated_test_signal_ready(const char* temp_directory) { IREE_TRACE_ZONE_BEGIN(z0); char ready_path[512]; - snprintf(ready_path, sizeof(ready_path), "%s/.ready", temp_directory); + iree_snprintf(ready_path, sizeof(ready_path), "%s/.ready", temp_directory); FILE* file = fopen(ready_path, "w"); if (file) fclose(file); IREE_TRACE_ZONE_END(z0); @@ -482,7 +483,7 @@ static bool iree_coordinated_test_wait_ready(const char* temp_directory, IREE_TRACE_ZONE_BEGIN(z0); bool found = false; char ready_path[512]; - snprintf(ready_path, sizeof(ready_path), "%s/.ready", temp_directory); + iree_snprintf(ready_path, sizeof(ready_path), "%s/.ready", temp_directory); int64_t remaining_ms = timeout_ms; while (remaining_ms > 0) { #if defined(IREE_PLATFORM_WINDOWS) @@ -580,8 +581,8 @@ int iree_coordinated_test_run(int argc, char** argv, // Build per-role flag strings. char role_flag[256]; char temp_dir_flag[512]; - snprintf(temp_dir_flag, sizeof(temp_dir_flag), "--iree_test_temp_dir=%s", - temp_directory); + iree_snprintf(temp_dir_flag, sizeof(temp_dir_flag), "--iree_test_temp_dir=%s", + temp_directory); // Spawn children. argv layout: [self_path, original_args..., --role, --temp, // NULL]. @@ -620,8 +621,8 @@ int iree_coordinated_test_run(int argc, char** argv, int64_t remaining_ms = timeout_ms; for (iree_host_size_t i = 0; i < config->role_count; ++i) { - snprintf(role_flag, sizeof(role_flag), "--iree_test_role=%s", - config->roles[i].name); + iree_snprintf(role_flag, sizeof(role_flag), "--iree_test_role=%s", + config->roles[i].name); child_argv[role_flag_index] = role_flag; fprintf(stderr, "coordinated_test: spawning role '%s'\n", diff --git a/runtime/src/iree/testing/coordinated_test_test.cc b/runtime/src/iree/testing/coordinated_test_test.cc index 254245844c04..4b020a30b680 100644 --- a/runtime/src/iree/testing/coordinated_test_test.cc +++ b/runtime/src/iree/testing/coordinated_test_test.cc @@ -30,7 +30,7 @@ static const char kExpectedMessage[] = "hello from writer"; static int writer_role(int argc, char** argv, const char* temp_directory) { // Write a message to a file in the shared temp directory. char file_path[512]; - snprintf(file_path, sizeof(file_path), "%s/message.txt", temp_directory); + iree_snprintf(file_path, sizeof(file_path), "%s/message.txt", temp_directory); FILE* file = fopen(file_path, "w"); if (!file) { fprintf(stderr, "writer: failed to create %s\n", file_path); @@ -47,7 +47,7 @@ static int writer_role(int argc, char** argv, const char* temp_directory) { static int reader_role(int argc, char** argv, const char* temp_directory) { // Read the message file written by the writer role. char file_path[512]; - snprintf(file_path, sizeof(file_path), "%s/message.txt", temp_directory); + iree_snprintf(file_path, sizeof(file_path), "%s/message.txt", temp_directory); FILE* file = fopen(file_path, "r"); if (!file) { fprintf(stderr, "reader: failed to open %s\n", file_path); diff --git a/runtime/src/iree/tokenizer/model/bpe.c b/runtime/src/iree/tokenizer/model/bpe.c index c80a803f1446..309f1e261f72 100644 --- a/runtime/src/iree/tokenizer/model/bpe.c +++ b/runtime/src/iree/tokenizer/model/bpe.c @@ -98,7 +98,8 @@ static void iree_tokenizer_bpe_build_byte_to_token( // Precompute byte fallback token: "<0xNN>". char fallback_token[8]; - snprintf(fallback_token, sizeof(fallback_token), "<0x%02X>", byte_value); + iree_snprintf(fallback_token, sizeof(fallback_token), "<0x%02X>", + byte_value); model->byte_fallback_token[byte_value] = iree_tokenizer_vocab_lookup( model->vocab, iree_make_cstring_view(fallback_token)); } diff --git a/runtime/src/iree/tokenizer/model/unigram.c b/runtime/src/iree/tokenizer/model/unigram.c index e4633046d335..6e6e228b7d46 100644 --- a/runtime/src/iree/tokenizer/model/unigram.c +++ b/runtime/src/iree/tokenizer/model/unigram.c @@ -183,7 +183,7 @@ static void iree_tokenizer_unigram_build_byte_to_token( iree_tokenizer_unigram_model_t* model) { for (int byte_value = 0; byte_value < 256; ++byte_value) { char byte_string[8]; - snprintf(byte_string, sizeof(byte_string), "<0x%02X>", byte_value); + iree_snprintf(byte_string, sizeof(byte_string), "<0x%02X>", byte_value); model->byte_to_token[byte_value] = iree_tokenizer_vocab_lookup( model->vocab, iree_make_string_view(byte_string, 6)); // "<0xXX>" is always 6 chars. diff --git a/runtime/src/iree/tokenizer/model/unigram_test.cc b/runtime/src/iree/tokenizer/model/unigram_test.cc index 50d5d5cc5be8..329cd9687214 100644 --- a/runtime/src/iree/tokenizer/model/unigram_test.cc +++ b/runtime/src/iree/tokenizer/model/unigram_test.cc @@ -119,7 +119,7 @@ TEST_F(UnigramModelTest, AllowsNoUnkWithByteFallback) { // Add byte fallback tokens. for (int i = 0; i < 256; ++i) { char text[8]; - snprintf(text, sizeof(text), "<0x%02X>", i); + iree_snprintf(text, sizeof(text), "<0x%02X>", i); builder.AddTokenWithScore(1 + i, text, -5.0f); } diff --git a/runtime/src/iree/vm/context.c b/runtime/src/iree/vm/context.c index a8405f292e7f..520e733be202 100644 --- a/runtime/src/iree/vm/context.c +++ b/runtime/src/iree/vm/context.c @@ -106,7 +106,7 @@ static iree_vm_context_id_t iree_vm_context_allocate_id(void) { // The string must remain live for the lifetime of the process. IREE_LEAK_CHECK_DISABLE_PUSH(); char* name = (char*)malloc(32); - snprintf(name, 32, "ctx-%04d", context_id - 1); + iree_snprintf(name, 32, "ctx-%04d", context_id - 1); IREE_LEAK_CHECK_DISABLE_POP(); return (iree_vm_context_id_t)name; #else diff --git a/runtime/src/iree/vm/invocation.c b/runtime/src/iree/vm/invocation.c index da8a811dec50..c666c600c562 100644 --- a/runtime/src/iree/vm/invocation.c +++ b/runtime/src/iree/vm/invocation.c @@ -246,7 +246,7 @@ static iree_vm_invocation_id_t iree_vm_invoke_allocate_id( iree_memory_order_relaxed); IREE_LEAK_CHECK_DISABLE_PUSH(); char* name = (char*)malloc(32); - snprintf(name, 32, "invoke-%04d", invocation_id - 1); + iree_snprintf(name, 32, "invoke-%04d", invocation_id - 1); IREE_LEAK_CHECK_DISABLE_POP(); return (iree_vm_invocation_id_t)name; } else { diff --git a/third_party/printf b/third_party/printf new file mode 160000 index 000000000000..f1b728cbd5c6 --- /dev/null +++ b/third_party/printf @@ -0,0 +1 @@ +Subproject commit f1b728cbd5c6e10dc1f140f1574edfd1ccdcbedb