| // 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 <stdio.h> | |
| #include "iree/base/api.h" | |
| #include "iree/base/tooling/flags.h" | |
| #include "iree/hal/replay/dump.h" | |
| #include "iree/io/file_contents.h" | |
| IREE_FLAG(string, format, "text", "Output format: text or jsonl."); | |
| IREE_FLAG(bool, agents_md, false, | |
| "Prints AGENTS.md guidance for iree-dump-replay and exits."); | |
| static const char kIreeDumpReplayUsage[] = | |
| "Dumps information from an IREE HAL replay file.\n" | |
| "\n" | |
| "The dumper validates the replay container and emits projections without\n" | |
| "materializing large payload bytes. Blob data and embedded payloads are\n" | |
| "reported as byte ranges in the original .ireereplay file so JSONL and\n" | |
| "text output can reference the capture directly.\n" | |
| "\n" | |
| "Usage:\n" | |
| " iree-dump-replay [--format=text|jsonl] <capture.ireereplay>\n" | |
| "\n" | |
| "Formats:\n" | |
| " text\n" | |
| " Human-readable record stream for quick inspection.\n" | |
| " jsonl\n" | |
| " One JSON object per line for jq and automation. Payload bytes are\n" | |
| " represented as replay-file ranges.\n" | |
| "\n" | |
| "Important flags:\n" | |
| " --agents_md\n" | |
| " Prints AGENTS.md guidance specific to iree-dump-replay. Use\n" | |
| " `iree-run-replay --agents_md` for the full replay tool playbook.\n" | |
| "\n" | |
| "Examples:\n" | |
| " iree-dump-replay --format=text /tmp/model.ireereplay\n" | |
| " iree-dump-replay --format=jsonl /tmp/model.ireereplay | \\\n" | |
| " jq 'select(.kind==\"operation\" and " | |
| ".operation==\"device.queue_execute\")'\n"; | |
| static void iree_dump_replay_print_agent_markdown(FILE* file) { | |
| fputs( | |
| "# iree-dump-replay\n" | |
| "\n" | |
| "Use `iree-dump-replay --format=text` for quick inspection and\n" | |
| "`--format=jsonl` for agent workflows. JSONL emits one object per line " | |
| "and\n" | |
| "keeps payload bytes as replay-file ranges instead of dumping raw blob " | |
| "data.\n" | |
| "\n" | |
| "Useful queries:\n" | |
| "\n" | |
| "```bash\n" | |
| "iree-dump-replay --format=jsonl /tmp/model.ireereplay | \\\n" | |
| " jq 'select(.kind==\"operation\" and " | |
| ".operation==\"device.queue_execute\")'\n" | |
| "iree-dump-replay --format=jsonl /tmp/model.ireereplay | \\\n" | |
| " jq 'select(.payload_type==\"replay_scope\") | .payload.name'\n" | |
| "```\n" | |
| "\n" | |
| "Rows carry object ids, operation ids, queue wait/signal lists, buffer\n" | |
| "binding tables, file references, and replay-file byte ranges.\n" | |
| "\n" | |
| "For replay execution, executable substitution, file remapping, and the\n" | |
| "shared replay failure contract, pipe `iree-run-replay --agents_md` " | |
| "into\n" | |
| "your AGENTS.md.\n", | |
| file); | |
| } | |
| static iree_status_t iree_dump_replay_parse_format( | |
| const char* value, iree_hal_replay_dump_format_t* out_format) { | |
| iree_string_view_t format = iree_make_cstring_view(value); | |
| if (iree_string_view_equal(format, IREE_SV("text"))) { | |
| *out_format = IREE_HAL_REPLAY_DUMP_FORMAT_TEXT; | |
| return iree_ok_status(); | |
| } else if (iree_string_view_equal(format, IREE_SV("jsonl"))) { | |
| *out_format = IREE_HAL_REPLAY_DUMP_FORMAT_JSONL; | |
| return iree_ok_status(); | |
| } | |
| return iree_make_status(IREE_STATUS_INVALID_ARGUMENT, | |
| "unsupported --format=%s; expected text or jsonl", | |
| value); | |
| } | |
| static iree_status_t iree_dump_replay_write_file(void* user_data, | |
| iree_string_view_t text) { | |
| FILE* file = (FILE*)user_data; | |
| if (text.size == 0) return iree_ok_status(); | |
| if (IREE_UNLIKELY(fwrite(text.data, 1, text.size, file) != text.size)) { | |
| return iree_make_status(IREE_STATUS_INTERNAL, | |
| "failed to write replay dump output"); | |
| } | |
| return iree_ok_status(); | |
| } | |
| int main(int argc, char** argv) { | |
| IREE_TRACE_APP_ENTER(); | |
| IREE_TRACE_ZONE_BEGIN(z0); | |
| iree_allocator_t host_allocator = iree_allocator_system(); | |
| int exit_code = EXIT_SUCCESS; | |
| iree_flags_set_usage("iree-dump-replay", kIreeDumpReplayUsage); | |
| iree_flags_parse_checked(IREE_FLAGS_PARSE_MODE_DEFAULT, &argc, &argv); | |
| if (FLAG_agents_md) { | |
| iree_dump_replay_print_agent_markdown(stdout); | |
| fflush(stdout); | |
| IREE_TRACE_ZONE_END(z0); | |
| IREE_TRACE_APP_EXIT(exit_code); | |
| return exit_code; | |
| } | |
| iree_status_t status = iree_ok_status(); | |
| if (argc != 2) { | |
| status = iree_make_status(IREE_STATUS_INVALID_ARGUMENT, | |
| "expected one replay file path argument"); | |
| } | |
| iree_hal_replay_dump_options_t options = | |
| iree_hal_replay_dump_options_default(); | |
| if (iree_status_is_ok(status)) { | |
| status = iree_dump_replay_parse_format(FLAG_format, &options.format); | |
| } | |
| iree_io_file_contents_t* file_contents = NULL; | |
| if (iree_status_is_ok(status)) { | |
| status = iree_io_file_contents_map(iree_make_cstring_view(argv[1]), | |
| IREE_IO_FILE_ACCESS_READ, host_allocator, | |
| &file_contents); | |
| } | |
| if (iree_status_is_ok(status)) { | |
| iree_hal_replay_dump_write_callback_t write_callback = { | |
| .fn = iree_dump_replay_write_file, | |
| .user_data = stdout, | |
| }; | |
| status = iree_hal_replay_dump_file(file_contents->const_buffer, &options, | |
| write_callback, host_allocator); | |
| } | |
| iree_io_file_contents_free(file_contents); | |
| fflush(stdout); | |
| if (!iree_status_is_ok(status)) { | |
| iree_status_fprint(stderr, status); | |
| iree_status_free(status); | |
| exit_code = EXIT_FAILURE; | |
| } | |
| fflush(stderr); | |
| IREE_TRACE_ZONE_END(z0); | |
| IREE_TRACE_APP_EXIT(exit_code); | |
| return exit_code; | |
| } |