blob: eb0856140a4b5f73013411182e739962f19341e2 [file] [log] [blame]
Ben Vanik11ced0c2023-11-03 14:24:08 -07001// Copyright 2023 The IREE Authors
2//
3// Licensed under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
7// Dumps parsed parameter file information.
8// We intentionally use the same flags and parsing behavior as the rest of the
9// runtime tools so that users can pass their parameter flags and see exactly
10// what the runtime tools would see post-indexing. We don't try to dump original
11// file metadata as we only support parsing enough information for what we need.
12//
13// We also support basic extraction of individual parameters in cases where
14// users want to dump them out. Since we don't parse or preserve metadata we
15// can't easily dump them to
16//
17// # List all available parameters and their index information:
18// $ iree-dump-parameters --parameters=my_scope=my_file.gguf [--parameters=...]
19// # Extract parameter binary contents from a file:
20// $ iree-dump-parameters ... --extract=scope::key0=file0.bin [--extract=...]
21
22#include <ctype.h>
23#include <stdio.h>
24
25#include "iree/base/api.h"
26#include "iree/base/internal/file_io.h"
27#include "iree/base/internal/flags.h"
28#include "iree/io/parameter_index.h"
29#include "iree/io/scope_map.h"
30#include "iree/tooling/parameter_util.h"
31
32//===----------------------------------------------------------------------===//
33// Parameter index information
34//===----------------------------------------------------------------------===//
35
36static iree_status_t iree_tooling_dump_parameter_index(
37 iree_string_view_t scope, iree_io_parameter_index_t* index) {
38 iree_host_size_t entry_count = iree_io_parameter_index_count(index);
39 uint64_t total_bytes = 0;
40 for (iree_host_size_t i = 0; i < entry_count; ++i) {
41 const iree_io_parameter_index_entry_t* entry = NULL;
42 IREE_RETURN_IF_ERROR(iree_io_parameter_index_get(index, i, &entry));
43 total_bytes += entry->length;
44 }
45 fprintf(stdout,
46 "//"
47 "===-----------------------------------------------------------------"
48 "---------------------------------------------===//\n");
49 fprintf(stdout,
50 "// Parameter scope `%.*s` (%" PRIhsz " entries, %" PRIu64
51 " total bytes)\n",
52 (int)scope.size, scope.data, entry_count, total_bytes);
53 fprintf(stdout,
54 "//===------------+------------------+------------------+------------"
55 "-----------------------------------------------===//\n");
56 fprintf(stdout,
57 "// Start | End | Length | Key\n");
58 fprintf(stdout,
59 "//---------------+------------------+------------------+------------"
60 "--------------------------------------------------//\n");
61 for (iree_host_size_t i = 0; i < entry_count; ++i) {
62 const iree_io_parameter_index_entry_t* entry = NULL;
63 IREE_RETURN_IF_ERROR(iree_io_parameter_index_get(index, i, &entry));
64 fprintf(stdout, "%16" PRIu64 " | %16" PRIu64 " | %16" PRIu64 " | `%.*s`\n",
65 entry->offset, entry->offset + entry->length, entry->length,
66 (int)entry->key.size, entry->key.data);
67 }
68 fprintf(stdout, "\n");
69 return iree_ok_status();
70}
71
72static iree_status_t iree_tooling_dump_scope_map(
73 iree_io_scope_map_t* scope_map) {
74 for (iree_host_size_t i = 0; i < scope_map->count; ++i) {
75 iree_string_view_t scope = scope_map->entries[i]->scope;
76 iree_io_parameter_index_t* index = scope_map->entries[i]->index;
77 IREE_RETURN_IF_ERROR(iree_tooling_dump_parameter_index(scope, index));
78 }
79 return iree_ok_status();
80}
81
82//===----------------------------------------------------------------------===//
83// Parameter extraction
84//===----------------------------------------------------------------------===//
85
86IREE_FLAG_LIST(string, extract,
87 "Extracts a parameter to a file as `[scope::]key=file.bin`.");
88
89static iree_status_t iree_tooling_extract_parameter(
90 iree_io_scope_map_t* scope_map, iree_string_view_t scope,
91 iree_string_view_t key, iree_string_view_t path,
92 iree_allocator_t host_allocator) {
93 // Lookup the index for the given scope.
94 iree_io_parameter_index_t* index = NULL; // unowned
95 IREE_RETURN_IF_ERROR(iree_io_scope_map_lookup(scope_map, scope, &index));
96
97 // Lookup the entry within the index.
98 const iree_io_parameter_index_entry_t* entry = NULL; // unowned
99 IREE_RETURN_IF_ERROR(iree_io_parameter_index_lookup(index, key, &entry));
100
101 fprintf(stdout, "Extracting parameter `");
102 if (!iree_string_view_is_empty(scope)) {
103 fprintf(stdout, "%.*s::", (int)scope.size, scope.data);
104 }
105 fprintf(stdout, "%.*s` (%" PRIu64 "b) to `%.*s`...\n", (int)key.size,
106 key.data, entry->length, (int)path.size, path.data);
107
108 // TODO(benvanik): support generic file handle IO instead of memory-only.
109 if (iree_io_file_handle_type(entry->file_handle) !=
110 IREE_IO_FILE_HANDLE_TYPE_HOST_ALLOCATION) {
111 return iree_make_status(
112 IREE_STATUS_UNIMPLEMENTED,
113 "only host allocation file handles are supported today");
114 }
115 iree_byte_span_t file_contents =
116 iree_io_file_handle_value(entry->file_handle).host_allocation;
117 iree_const_byte_span_t entry_contents = iree_make_const_byte_span(
118 file_contents.data + entry->offset, entry->length);
119 char* path_str = (char*)iree_alloca(path.size + 1);
120 memcpy(path_str, path.data, path.size);
121 path_str[path.size] = 0;
122 return iree_file_write_contents(path_str, entry_contents);
123}
124
125static iree_status_t iree_tooling_extract_parameters(
126 iree_io_scope_map_t* scope_map, iree_allocator_t host_allocator) {
127 for (iree_host_size_t i = 0; i < FLAG_extract_list().count; ++i) {
128 iree_string_view_t flag = FLAG_extract_list().values[i];
129 iree_string_view_t identifier, path;
130 iree_string_view_split(flag, '=', &identifier, &path);
131
132 iree_host_size_t separator_pos =
133 iree_string_view_find_first_of(identifier, IREE_SV("::"), 0);
134 iree_string_view_t scope = iree_string_view_empty();
135 iree_string_view_t key = iree_string_view_empty();
136 if (separator_pos != IREE_STRING_VIEW_NPOS) {
137 scope = iree_string_view_substr(identifier, 0, separator_pos);
138 key = iree_string_view_substr(identifier, separator_pos + 2,
139 IREE_HOST_SIZE_MAX);
140 } else {
141 key = identifier;
142 }
143
144 IREE_RETURN_IF_ERROR(iree_tooling_extract_parameter(scope_map, scope, key,
145 path, host_allocator),
146 "extracting parameter with flag `%.*s`",
147 (int)flag.size, flag.data);
148 }
149 return iree_ok_status();
150}
151
152//===----------------------------------------------------------------------===//
153// main
154//===----------------------------------------------------------------------===//
155
156int main(int argc, char** argv) {
157 IREE_TRACE_ZONE_BEGIN(z0);
158
159 iree_allocator_t host_allocator = iree_allocator_system();
160 int exit_code = EXIT_SUCCESS;
161
162 // Parse command line flags.
163 iree_flags_set_usage("iree-dump-parameters",
164 "Dumps information about parsed parameter files.\n");
165 iree_flags_parse_checked(IREE_FLAGS_PARSE_MODE_DEFAULT, &argc, &argv);
166
167 iree_io_scope_map_t scope_map = {0};
168 iree_io_scope_map_initialize(host_allocator, &scope_map);
169
170 // Parse parameters using the common tooling flags.
171 iree_status_t status =
172 iree_tooling_build_parameter_indices_from_flags(&scope_map);
173
174 // Dump parameter information.
175 if (iree_status_is_ok(status)) {
176 status = iree_tooling_dump_scope_map(&scope_map);
177 }
178
179 // Extract parameters as requested, if any.
180 if (iree_status_is_ok(status)) {
181 status = iree_tooling_extract_parameters(&scope_map, host_allocator);
182 }
183
184 iree_io_scope_map_deinitialize(&scope_map);
185
186 fflush(stdout);
187 if (!iree_status_is_ok(status)) {
188 iree_status_fprint(stderr, status);
189 iree_status_free(status);
190 exit_code = EXIT_FAILURE;
191 }
192 fflush(stderr);
193
194 IREE_TRACE_ZONE_END(z0);
195 return exit_code;
196}