blob: bee468bf572c09f3b292008fbf6732176c844a0a [file] [log] [blame]
Geoffrey Martin-Noble552d3f82021-05-25 17:56:09 -07001// Copyright 2019 The IREE Authors
Stella Laurenzof4469e72019-11-11 18:08:55 -08002//
Geoffrey Martin-Noble552d3f82021-05-25 17:56:09 -07003// 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
Stella Laurenzof4469e72019-11-11 18:08:55 -08006
Ben Vanik163547a2023-05-15 11:59:13 -07007// Loads a VM module from the provided file and outputs the requested
8// information.
9//
10// $ iree-dump-module [--output=...] module.vmfb
11// --output=metadata: module metadata and size breakdown.
12// --output=flatbuffer-binary: module flatbuffer in binary format.
13// --output=flatbuffer-json: module flatbuffer in JSON format.
14
15#include <ctype.h>
Ben Vanik35bc9a12022-03-09 09:05:58 -080016#include <stdio.h>
Stella Laurenzof4469e72019-11-11 18:08:55 -080017
Ben Vanik931a3b12021-05-20 13:27:13 -070018#include "iree/base/api.h"
Ben Vanik5507c6e2021-02-02 21:27:08 -080019#include "iree/base/internal/file_io.h"
Ben Vanik163547a2023-05-15 11:59:13 -070020#include "iree/base/internal/flags.h"
Ben Vanik784db042023-02-25 11:10:21 -080021#include "iree/vm/bytecode/archive.h"
Ben Vanikcf49d692023-02-24 20:24:09 -080022#include "iree/vm/bytecode/module.h"
Stella Laurenzof4469e72019-11-11 18:08:55 -080023
Ben Vanik163547a2023-05-15 11:59:13 -070024// NOTE: include order matters:
25#include "iree/base/internal/flatcc/parsing.h"
26#include "iree/schemas/bytecode_module_def_json_printer.h"
27#include "iree/schemas/bytecode_module_def_reader.h"
28#include "iree/schemas/bytecode_module_def_verifier.h"
29
30//===----------------------------------------------------------------------===//
31// IO utilities
32//===----------------------------------------------------------------------===//
33
34#if defined(IREE_PLATFORM_WINDOWS)
35#include <fcntl.h>
36#include <io.h>
37#define IREE_SET_BINARY_MODE(handle) _setmode(_fileno(handle), O_BINARY)
38#else
39#define IREE_SET_BINARY_MODE(handle) ((void)0)
40#endif // IREE_PLATFORM_WINDOWS
41
42static void iree_tooling_print_indent(int indent) {
43 fprintf(stdout, "%*s", indent, "");
44}
45
46static void iree_tooling_printf_section_header(const char* format, ...) {
47 fprintf(stdout,
48 "//"
49 "===-----------------------------------------------------------------"
50 "---------------------------------------------===//\n");
51 fprintf(stdout, "// ");
52 va_list args;
53 va_start(args, format);
54 vfprintf(stdout, format, args);
55 va_end(args);
56 fprintf(stdout, "\n");
57 fprintf(stdout,
58 "//"
59 "===-----------------------------------------------------------------"
60 "---------------------------------------------===//\n");
61}
62
63//===----------------------------------------------------------------------===//
64// --output=metadata
65//===----------------------------------------------------------------------===//
66
67static size_t iree_tooling_print_feature_bits(iree_vm_FeatureBits_enum_t bits) {
68 size_t length = 0;
69 if (bits & iree_vm_FeatureBits_EXT_F32) {
70 if (length) fprintf(stdout, " | ");
71 fprintf(stdout, "EXT_F32");
72 length += strlen("EXT_F32");
73 bits = bits & ~iree_vm_FeatureBits_EXT_F32;
74 }
75 if (bits & iree_vm_FeatureBits_EXT_F64) {
76 if (length) fprintf(stdout, " | ");
77 fprintf(stdout, "EXT_F64");
78 length += strlen("EXT_F64");
79 bits = bits & ~iree_vm_FeatureBits_EXT_F64;
80 }
81 if (bits) {
82 if (length) fprintf(stdout, " | ");
83 fprintf(stdout, "%08X", bits);
84 length += 8;
85 }
86 return length;
87}
88
89static void iree_tooling_print_attr_def(iree_vm_AttrDef_table_t attr_def) {
90 fprintf(stdout, "%s: %s", iree_vm_AttrDef_key(attr_def),
91 iree_vm_AttrDef_value(attr_def));
92}
93
94static void iree_tooling_print_attr_defs(iree_vm_AttrDef_vec_t attr_defs,
95 int indent) {
96 for (size_t i = 0; i < iree_vm_AttrDef_vec_len(attr_defs); ++i) {
97 iree_tooling_print_indent(indent);
98 iree_tooling_print_attr_def(iree_vm_AttrDef_vec_at(attr_defs, i));
99 fprintf(stdout, "\n");
100 }
101}
102
103static void iree_tooling_print_type_def(iree_vm_TypeDef_table_t type_def) {
104 fprintf(stdout, "%s", iree_vm_TypeDef_full_name(type_def));
105}
106
107static void iree_tooling_print_type_defs(iree_vm_TypeDef_vec_t type_defs,
108 int indent) {
109 for (size_t i = 0; i < iree_vm_TypeDef_vec_len(type_defs); ++i) {
110 iree_tooling_print_indent(indent);
111 fprintf(stdout, "[%3zu] ", i);
112 iree_tooling_print_type_def(iree_vm_TypeDef_vec_at(type_defs, i));
113 fprintf(stdout, "\n");
114 }
115}
116
117static void iree_tooling_print_module_dependency_def(
118 iree_vm_ModuleDependencyDef_table_t dependency_def) {
119 fprintf(stdout, "%s, version >= %d, ",
120 iree_vm_ModuleDependencyDef_name(dependency_def),
121 iree_vm_ModuleDependencyDef_minimum_version(dependency_def));
122 if (iree_vm_ModuleDependencyDef_flags(dependency_def) &
123 iree_vm_ModuleDependencyFlagBits_OPTIONAL) {
124 fprintf(stdout, "optional");
125 } else {
126 fprintf(stdout, "required");
127 }
128}
129
130static void iree_tooling_print_module_dependency_defs(
131 iree_vm_ModuleDependencyDef_vec_t dependency_defs, int indent) {
132 for (size_t i = 0; i < iree_vm_ModuleDependencyDef_vec_len(dependency_defs);
133 ++i) {
134 iree_tooling_print_indent(indent);
135 iree_tooling_print_module_dependency_def(
136 iree_vm_ModuleDependencyDef_vec_at(dependency_defs, i));
137 fprintf(stdout, "\n");
138 }
139}
140
141static iree_status_t iree_tooling_print_cconv_fragment(
142 iree_string_view_t cconv_fragment) {
143 for (iree_host_size_t i = 0; i < cconv_fragment.size; ++i) {
144 if (i > 0) fprintf(stdout, ", ");
145 switch (cconv_fragment.data[i]) {
146 case IREE_VM_CCONV_TYPE_VOID:
147 break;
148 case IREE_VM_CCONV_TYPE_I32:
149 fprintf(stdout, "i32");
150 break;
151 case IREE_VM_CCONV_TYPE_F32:
152 fprintf(stdout, "f32");
153 break;
154 case IREE_VM_CCONV_TYPE_I64:
155 fprintf(stdout, "i64");
156 break;
157 case IREE_VM_CCONV_TYPE_F64:
158 fprintf(stdout, "f64");
159 break;
160 case IREE_VM_CCONV_TYPE_REF:
161 fprintf(stdout, "!vm.ref<?>");
162 break;
163 case IREE_VM_CCONV_TYPE_SPAN_START: {
164 iree_host_size_t end_pos = iree_string_view_find_char(
165 cconv_fragment, IREE_VM_CCONV_TYPE_SPAN_END, i + 1);
166 if (end_pos == IREE_STRING_VIEW_NPOS) {
167 return iree_make_status(IREE_STATUS_FAILED_PRECONDITION,
168 "unterminated cconv span");
169 }
170 fprintf(stdout, "tuple<");
171 IREE_RETURN_IF_ERROR(iree_tooling_print_cconv_fragment(
172 iree_string_view_substr(cconv_fragment, i + 1, end_pos - i - 1)));
173 fprintf(stdout, ">...");
Ben Vanik129ad452024-09-25 08:13:05 -0700174 i = end_pos; // +1 from the for-loop
Ben Vanik163547a2023-05-15 11:59:13 -0700175 } break;
176 default:
177 return iree_make_status(IREE_STATUS_UNIMPLEMENTED,
178 "unsupported cconv type '%c'",
179 cconv_fragment.data[i]);
180 }
181 }
182 return iree_ok_status();
183}
184
185static void iree_tooling_print_function_cconv(flatbuffers_string_t cconv) {
186 iree_vm_function_signature_t signature = {
187 .calling_convention = iree_make_cstring_view(cconv),
188 };
189 iree_string_view_t arguments, results;
190 IREE_CHECK_OK(iree_vm_function_call_get_cconv_fragments(
191 &signature, &arguments, &results));
192 fprintf(stdout, "(");
193 IREE_CHECK_OK(iree_tooling_print_cconv_fragment(arguments));
194 fprintf(stdout, ") -> (");
195 IREE_CHECK_OK(iree_tooling_print_cconv_fragment(results));
196 fprintf(stdout, ")");
197}
198
199static void iree_tooling_print_imported_function_def(
200 iree_vm_ImportFunctionDef_table_t function_def, int indent) {
201 if (iree_vm_ImportFunctionDef_flags(function_def) &
202 iree_vm_ImportFlagBits_OPTIONAL) {
203 fprintf(stdout, "?");
204 }
205 fprintf(stdout, "%s", iree_vm_ImportFunctionDef_full_name(function_def));
206 iree_vm_FunctionSignatureDef_table_t signature_def =
207 iree_vm_ImportFunctionDef_signature(function_def);
208 if (iree_vm_FunctionSignatureDef_calling_convention_is_present(
209 signature_def)) {
210 iree_tooling_print_function_cconv(
211 iree_vm_FunctionSignatureDef_calling_convention(signature_def));
212 }
213 fprintf(stdout, "\n");
214 if (iree_vm_FunctionSignatureDef_attrs_is_present(signature_def)) {
215 iree_tooling_print_attr_defs(
216 iree_vm_FunctionSignatureDef_attrs(signature_def), indent);
217 }
218}
219
220static void iree_tooling_print_imported_function_defs(
221 iree_vm_ImportFunctionDef_vec_t function_defs, int indent) {
222 for (size_t i = 0; i < iree_vm_ImportFunctionDef_vec_len(function_defs);
223 ++i) {
224 iree_tooling_print_indent(indent);
225 fprintf(stdout, "[%3zu] ", i);
226 iree_tooling_print_imported_function_def(
227 iree_vm_ImportFunctionDef_vec_at(function_defs, i), indent + 6);
228 }
229}
230
231static void iree_tooling_print_exported_function_def(
232 iree_vm_ExportFunctionDef_table_t function_def,
233 iree_vm_FunctionSignatureDef_vec_t function_signature_defs) {
234 fprintf(stdout, "%s", iree_vm_ExportFunctionDef_local_name(function_def));
235 iree_vm_FunctionSignatureDef_table_t signature_def =
236 iree_vm_FunctionSignatureDef_vec_at(
237 function_signature_defs,
238 iree_vm_ExportFunctionDef_internal_ordinal(function_def));
239 if (iree_vm_FunctionSignatureDef_calling_convention_is_present(
240 signature_def)) {
241 iree_tooling_print_function_cconv(
242 iree_vm_FunctionSignatureDef_calling_convention(signature_def));
243 }
244 fprintf(stdout, "\n");
Ben Vanikac9d6d52023-12-03 20:20:31 -0800245 if (iree_vm_FunctionSignatureDef_attrs_is_present(signature_def)) {
246 iree_tooling_print_attr_defs(
247 iree_vm_FunctionSignatureDef_attrs(signature_def), 8);
248 }
Ben Vanik163547a2023-05-15 11:59:13 -0700249}
250
251static void iree_tooling_print_exported_function_defs(
252 iree_vm_ExportFunctionDef_vec_t function_defs,
253 iree_vm_FunctionSignatureDef_vec_t function_signature_defs, int indent) {
254 for (size_t i = 0; i < iree_vm_ExportFunctionDef_vec_len(function_defs);
255 ++i) {
256 iree_tooling_print_indent(indent);
257 fprintf(stdout, "[%3zu] ", i);
258 iree_tooling_print_exported_function_def(
259 iree_vm_ExportFunctionDef_vec_at(function_defs, i),
260 function_signature_defs);
261 }
262}
263
264static size_t iree_tooling_calculate_external_rodata_size(
265 iree_vm_RodataSegmentDef_vec_t segment_defs) {
266 size_t total_size = 0;
267 for (size_t i = 0; i < iree_vm_RodataSegmentDef_vec_len(segment_defs); ++i) {
268 iree_vm_RodataSegmentDef_table_t segment_def =
269 iree_vm_RodataSegmentDef_vec_at(segment_defs, i);
270 if (!iree_vm_RodataSegmentDef_embedded_data_is_present(segment_def)) {
271 total_size += iree_vm_RodataSegmentDef_external_data_length(segment_def);
272 }
273 }
274 return total_size;
275}
276
277// Returns true if |data| is likely a string. The string may not have a NUL
278// terminator and the length is returned in |out_length|. Note that string
279// tables may have NUL terminators and this will only return the first string.
280static bool iree_tooling_data_is_string(flatbuffers_uint8_vec_t data,
281 size_t* out_length) {
282 *out_length = 0;
283 size_t length = flatbuffers_uint8_vec_scan(data, 0);
284 if (length == flatbuffers_not_found) {
285 length = flatbuffers_uint8_vec_len(data);
286 }
287 for (size_t i = 0; i < length; ++i) {
288 char c = flatbuffers_uint8_vec_at(data, i);
289 if (!isprint(c)) return false;
290 }
291 *out_length = length;
292 return true;
293}
294
295static void iree_tooling_print_rodata_segment_defs(
296 iree_vm_RodataSegmentDef_vec_t segment_defs, int indent) {
297 for (size_t i = 0; i < iree_vm_RodataSegmentDef_vec_len(segment_defs); ++i) {
298 iree_tooling_print_indent(indent);
299 iree_vm_RodataSegmentDef_table_t segment_def =
300 iree_vm_RodataSegmentDef_vec_at(segment_defs, i);
301 fprintf(stdout, ".rodata[%3zu] ", i);
302 switch (iree_vm_RodataSegmentDef_compression_type_type(segment_def)) {
303 case iree_vm_CompressionTypeDef_UncompressedDataDef:
304 fprintf(stdout, "uncompressed ");
305 break;
306 default:
307 break;
308 }
309 if (iree_vm_RodataSegmentDef_embedded_data_is_present(segment_def)) {
310 flatbuffers_uint8_vec_t data =
311 iree_vm_RodataSegmentDef_embedded_data(segment_def);
312 fprintf(stdout, "embedded %8zu bytes", flatbuffers_uint8_vec_len(data));
313 size_t string_length = 0;
314 if (iree_tooling_data_is_string(data, &string_length)) {
315 static const size_t MAX_LENGTH = 32;
316 fprintf(stdout, " `%.*s`", (int)iree_min(MAX_LENGTH, string_length),
317 (const char*)data);
318 if (string_length >= MAX_LENGTH) fprintf(stdout, "...");
319 }
320 } else {
321 fprintf(stdout,
322 "external %8" PRIu64 " bytes (offset %" PRIu64 " / %" PRIX64
323 "h to %" PRIX64 "h)",
324 iree_vm_RodataSegmentDef_external_data_length(segment_def),
325 iree_vm_RodataSegmentDef_external_data_offset(segment_def),
326 iree_vm_RodataSegmentDef_external_data_offset(segment_def),
327 iree_vm_RodataSegmentDef_external_data_offset(segment_def) +
328 iree_vm_RodataSegmentDef_external_data_length(segment_def));
329 }
330 fprintf(stdout, "\n");
331 }
332}
333
334static void iree_tooling_print_rwdata_segment_defs(
335 iree_vm_RwdataSegmentDef_vec_t segment_defs, int indent) {
336 for (size_t i = 0; i < iree_vm_RwdataSegmentDef_vec_len(segment_defs); ++i) {
337 iree_tooling_print_indent(indent);
338 iree_vm_RwdataSegmentDef_table_t segment_def =
339 iree_vm_RwdataSegmentDef_vec_at(segment_defs, i);
340 fprintf(stdout, ".rwdata[%3zu] %d bytes\n", i,
341 iree_vm_RwdataSegmentDef_byte_size(segment_def));
342 }
343}
344
345static void iree_tooling_print_function_descriptors(
346 iree_vm_FunctionDescriptor_vec_t descriptors,
347 iree_vm_ExportFunctionDef_vec_t export_defs) {
348 fprintf(stdout,
349 " # | Offset | Length | Blocks | i32 # | ref # | Requirements | "
350 "Aliases\n");
351 fprintf(stdout,
352 "----+----------+----------+--------+-------+-------+--------------+-"
353 "----------------------------------------------------\n");
354 for (size_t i = 0; i < iree_vm_FunctionDescriptor_vec_len(descriptors); ++i) {
355 iree_vm_FunctionDescriptor_struct_t descriptor =
356 iree_vm_FunctionDescriptor_vec_at(descriptors, i);
357 fprintf(stdout, "%3zu | %08X | %8d | %6d | %5d | %5d | ", i,
358 iree_vm_FunctionDescriptor_bytecode_offset(descriptor),
359 iree_vm_FunctionDescriptor_bytecode_length(descriptor),
360 iree_vm_FunctionDescriptor_block_count(descriptor),
361 iree_vm_FunctionDescriptor_i32_register_count(descriptor),
362 iree_vm_FunctionDescriptor_ref_register_count(descriptor));
363 size_t pos = iree_tooling_print_feature_bits(
364 iree_vm_FunctionDescriptor_requirements(descriptor));
365 if (pos < 12) iree_tooling_print_indent(12 - pos);
366 fprintf(stdout, " | ");
367 bool any_aliases = false;
368 for (size_t j = 0; j < iree_vm_ExportFunctionDef_vec_len(export_defs);
369 ++j) {
370 iree_vm_ExportFunctionDef_table_t export_def =
371 iree_vm_ExportFunctionDef_vec_at(export_defs, j);
372 if (iree_vm_ExportFunctionDef_internal_ordinal(export_def) == i) {
373 if (any_aliases) fprintf(stdout, ", ");
374 fprintf(stdout, "%s", iree_vm_ExportFunctionDef_local_name(export_def));
375 any_aliases = true;
376 }
377 }
378 fprintf(stdout, "\n");
379 }
380}
381
382static iree_status_t iree_tooling_dump_module_metadata(
383 iree_const_byte_span_t flatbuffer_contents,
384 iree_const_byte_span_t rodata_contents) {
385 iree_vm_BytecodeModuleDef_table_t module_def =
386 iree_vm_BytecodeModuleDef_as_root(flatbuffer_contents.data);
387
388 iree_tooling_printf_section_header(
389 "@%s : version %d", iree_vm_BytecodeModuleDef_name(module_def),
390 iree_vm_BytecodeModuleDef_version(module_def));
391 fprintf(stdout, "\n");
392
393 if (iree_vm_BytecodeModuleDef_requirements_is_present(module_def)) {
394 fprintf(stdout, "Requirements: ");
395 iree_tooling_print_feature_bits(
396 iree_vm_BytecodeModuleDef_requirements(module_def));
397 fprintf(stdout, "\n\n");
Stella Laurenzof4469e72019-11-11 18:08:55 -0800398 }
Ben Vanik35bc9a12022-03-09 09:05:58 -0800399
Ben Vanik163547a2023-05-15 11:59:13 -0700400 if (iree_vm_BytecodeModuleDef_attrs_is_present(module_def)) {
401 fprintf(stdout, "Attributes:\n");
402 iree_tooling_print_attr_defs(iree_vm_BytecodeModuleDef_attrs(module_def),
403 2);
Ben Vanik6ab1ed82024-01-17 15:00:33 -0800404 fprintf(stdout, "\n");
Ben Vanik163547a2023-05-15 11:59:13 -0700405 }
Ben Vanik9a286392022-05-20 19:45:23 -0700406
Ben Vanik163547a2023-05-15 11:59:13 -0700407 if (iree_vm_BytecodeModuleDef_types_is_present(module_def)) {
408 fprintf(stdout, "Required Types:\n");
409 iree_tooling_print_type_defs(iree_vm_BytecodeModuleDef_types(module_def),
410 2);
411 fprintf(stdout, "\n");
412 }
Ben Vanikbc685ed2020-11-14 17:09:46 -0800413
Ben Vanik163547a2023-05-15 11:59:13 -0700414 if (iree_vm_BytecodeModuleDef_dependencies_is_present(module_def)) {
415 fprintf(stdout, "Module Dependencies:\n");
416 iree_tooling_print_module_dependency_defs(
417 iree_vm_BytecodeModuleDef_dependencies(module_def), 2);
418 fprintf(stdout, "\n");
419 }
420
421 if (iree_vm_BytecodeModuleDef_imported_functions_is_present(module_def)) {
422 fprintf(stdout, "Imported Functions:\n");
423 iree_tooling_print_imported_function_defs(
424 iree_vm_BytecodeModuleDef_imported_functions(module_def), 2);
425 fprintf(stdout, "\n");
426 }
427
428 if (iree_vm_BytecodeModuleDef_exported_functions_is_present(module_def)) {
429 fprintf(stdout, "Exported Functions:\n");
430 iree_tooling_print_exported_function_defs(
431 iree_vm_BytecodeModuleDef_exported_functions(module_def),
432 iree_vm_BytecodeModuleDef_function_signatures(module_def), 2);
433 fprintf(stdout, "\n");
434 }
435
436 iree_tooling_printf_section_header("Sections");
437 fprintf(stdout, "\n");
438
439 if (iree_vm_BytecodeModuleDef_module_state_is_present(module_def)) {
440 iree_vm_ModuleStateDef_table_t module_state_def =
441 iree_vm_BytecodeModuleDef_module_state(module_def);
442 fprintf(stdout, "Module State:\n");
443 fprintf(stdout, " %d bytes, %d refs, ~%zu bytes total\n",
444 iree_vm_ModuleStateDef_global_bytes_capacity(module_state_def),
445 iree_vm_ModuleStateDef_global_ref_count(module_state_def),
446 iree_vm_ModuleStateDef_global_bytes_capacity(module_state_def) +
447 sizeof(iree_vm_ref_t) *
448 iree_vm_ModuleStateDef_global_ref_count(module_state_def));
449 fprintf(stdout, "\n");
450 }
451
Scott Todd60b07642023-06-15 09:41:01 -0700452 fprintf(stdout, "FlatBuffer: %" PRIhsz " bytes\n",
453 flatbuffer_contents.data_length);
Ben Vanik163547a2023-05-15 11:59:13 -0700454 if (iree_vm_BytecodeModuleDef_bytecode_data_is_present(module_def)) {
455 flatbuffers_uint8_vec_t bytecode_data =
456 iree_vm_BytecodeModuleDef_bytecode_data(module_def);
457 fprintf(stdout, " Bytecode: %zu bytes\n",
458 flatbuffers_uint8_vec_len(bytecode_data));
459 }
460 if (iree_vm_BytecodeModuleDef_rodata_segments_is_present(module_def)) {
461 iree_tooling_print_rodata_segment_defs(
462 iree_vm_BytecodeModuleDef_rodata_segments(module_def), 2);
463 }
464 if (iree_vm_BytecodeModuleDef_rwdata_segments_is_present(module_def)) {
465 iree_tooling_print_rwdata_segment_defs(
466 iree_vm_BytecodeModuleDef_rwdata_segments(module_def), 2);
467 }
468 fprintf(stdout, "\n");
469 size_t external_size = iree_tooling_calculate_external_rodata_size(
470 iree_vm_BytecodeModuleDef_rodata_segments(module_def));
471 if (external_size > 0) {
472 fprintf(stdout, "External .rodata: ~%zu bytes\n\n", external_size);
473 }
474
475 iree_tooling_printf_section_header(
476 "Bytecode : version %d", iree_vm_BytecodeModuleDef_version(module_def));
477 fprintf(stdout, "\n");
478
479 if (iree_vm_BytecodeModuleDef_function_descriptors_is_present(module_def)) {
480 iree_tooling_print_function_descriptors(
481 iree_vm_BytecodeModuleDef_function_descriptors(module_def),
482 iree_vm_BytecodeModuleDef_exported_functions(module_def));
483 }
484
485 fprintf(stdout, "\n");
486
487 if (iree_vm_BytecodeModuleDef_debug_database_is_present(module_def)) {
488 iree_tooling_printf_section_header("Debug Information");
489 iree_vm_DebugDatabaseDef_table_t database_def =
490 iree_vm_BytecodeModuleDef_debug_database(module_def);
491 fprintf(stdout,
492 "// NOTE: debug databases are large and should be stripped in "
493 "deployed artifacts.\n");
494 fprintf(stdout, "\n");
495
496 // TODO(benvanik): some kind of informative output; for now just counts to
497 // indicate how much is present (would be nice to calculate full sizing).
498 fprintf(stdout, "Locations: %zu\n",
499 flatbuffers_generic_vec_len(
500 iree_vm_DebugDatabaseDef_location_table(database_def)));
501
502 fprintf(stdout, "\n");
503 }
504
505 return iree_ok_status();
506}
507
508//===----------------------------------------------------------------------===//
509// --output=flatbuffer-binary
510//===----------------------------------------------------------------------===//
511
512static iree_status_t iree_tooling_dump_module_flatbuffer_binary(
513 iree_const_byte_span_t flatbuffer_contents) {
514 IREE_SET_BINARY_MODE(stdout); // ensure binary output mode
515 fwrite(flatbuffer_contents.data, 1, flatbuffer_contents.data_length, stdout);
516 return iree_ok_status();
517}
518
519//===----------------------------------------------------------------------===//
520// --output=flatbuffer-json
521//===----------------------------------------------------------------------===//
522
523IREE_FLAG(bool, flatbuffer_pretty, false, "Pretty print flatbuffer JSON.");
524
525static iree_status_t iree_tooling_dump_module_flatbuffer_json(
526 iree_const_byte_span_t flatbuffer_contents) {
Ben Vanikbc685ed2020-11-14 17:09:46 -0800527 flatcc_json_printer_t printer;
Ben Vanik163547a2023-05-15 11:59:13 -0700528 flatcc_json_printer_init(&printer, NULL);
529 if (FLAG_flatbuffer_pretty) {
530 flatcc_json_printer_set_flags(&printer, flatcc_json_printer_f_pretty);
531 }
Ben Vanikbc685ed2020-11-14 17:09:46 -0800532 flatcc_json_printer_set_skip_default(&printer, true);
Ben Vanik9a286392022-05-20 19:45:23 -0700533 bytecode_module_def_print_json(&printer,
534 (const char*)flatbuffer_contents.data,
535 flatbuffer_contents.data_length);
Ben Vanik163547a2023-05-15 11:59:13 -0700536 flatcc_json_printer_flush(&printer);
Ben Vanikbc685ed2020-11-14 17:09:46 -0800537 flatcc_json_printer_clear(&printer);
Ben Vanik163547a2023-05-15 11:59:13 -0700538 return iree_ok_status();
539}
540
541//===----------------------------------------------------------------------===//
542// main
543//===----------------------------------------------------------------------===//
544
545IREE_FLAG(string, output, "metadata",
546 "Output mode:\n"
547 " 'metadata': module metadata and size breakdown.\n"
548 " 'flatbuffer-binary': module flatbuffer in binary format.\n"
549 " 'flatbuffer-json': module flatbuffer in JSON format.\n");
550
551int main(int argc, char** argv) {
Ben Vanik23f28282024-02-23 11:14:25 -0800552 IREE_TRACE_APP_ENTER();
553
Ben Vanik163547a2023-05-15 11:59:13 -0700554 iree_allocator_t host_allocator = iree_allocator_system();
555 int exit_code = EXIT_SUCCESS;
556
557 // Parse command line flags.
558 iree_flags_set_usage("iree-dump-module",
Ben Vanik11ced0c2023-11-03 14:24:08 -0700559 "Dumps IREE VM module details to stdout.\n"
560 "$ iree-dump-module [--output=...] module.vmfb\n");
Ben Vanik163547a2023-05-15 11:59:13 -0700561 iree_flags_parse_checked(IREE_FLAGS_PARSE_MODE_DEFAULT, &argc, &argv);
562
563 if (argc < 2) {
564 fprintf(stderr, "Syntax: iree-dump-module [--output=...] module.vmfb\n");
Ben Vanik23f28282024-02-23 11:14:25 -0800565 IREE_TRACE_APP_EXIT(EXIT_FAILURE);
Ben Vanik163547a2023-05-15 11:59:13 -0700566 return EXIT_FAILURE;
567 }
568
569 iree_file_contents_t* file_contents = NULL;
Ben Vanik9d15f362023-08-03 10:18:58 -0700570 iree_status_t status = iree_file_read_contents(
571 argv[1], IREE_FILE_READ_FLAG_DEFAULT, host_allocator, &file_contents);
Ben Vanik163547a2023-05-15 11:59:13 -0700572
573 iree_const_byte_span_t flatbuffer_contents = iree_const_byte_span_empty();
574 iree_const_byte_span_t rodata_contents = iree_const_byte_span_empty();
575 if (iree_status_is_ok(status)) {
576 iree_host_size_t rodata_offset = 0;
577 status = iree_vm_bytecode_archive_parse_header(
578 file_contents->const_buffer, &flatbuffer_contents, &rodata_offset);
579 rodata_contents = iree_make_const_byte_span(
580 file_contents->const_buffer.data + rodata_offset,
581 file_contents->const_buffer.data_length - rodata_offset);
582 }
583 if (iree_status_is_ok(status)) {
584 int verify_ret = iree_vm_BytecodeModuleDef_verify_as_root(
585 flatbuffer_contents.data, flatbuffer_contents.data_length);
586 if (verify_ret != flatcc_verify_ok) {
587 status = iree_make_status(IREE_STATUS_INVALID_ARGUMENT,
588 "FlatBuffer verification failed: %s",
589 flatcc_verify_error_string(verify_ret));
590 }
591 }
592 if (iree_status_is_ok(status)) {
593 if (strcmp(FLAG_output, "metadata") == 0) {
594 status = iree_tooling_dump_module_metadata(flatbuffer_contents,
595 rodata_contents);
596 } else if (strcmp(FLAG_output, "flatbuffer-binary") == 0) {
597 status = iree_tooling_dump_module_flatbuffer_binary(flatbuffer_contents);
598 } else if (strcmp(FLAG_output, "flatbuffer-json") == 0) {
599 status = iree_tooling_dump_module_flatbuffer_json(flatbuffer_contents);
600 } else {
601 status = iree_make_status(IREE_STATUS_INVALID_ARGUMENT,
602 "unrecognized --output= flag value '%s'",
603 FLAG_output);
604 }
605 }
Ben Vanikbc685ed2020-11-14 17:09:46 -0800606
Ben Vanik9a286392022-05-20 19:45:23 -0700607 iree_file_contents_free(file_contents);
Ben Vanik35bc9a12022-03-09 09:05:58 -0800608
Ben Vanik163547a2023-05-15 11:59:13 -0700609 fflush(stdout);
610 if (!iree_status_is_ok(status)) {
611 iree_status_fprint(stderr, status);
612 iree_status_free(status);
613 exit_code = EXIT_FAILURE;
614 }
615 fflush(stderr);
Ben Vanik23f28282024-02-23 11:14:25 -0800616 IREE_TRACE_APP_EXIT(exit_code);
Ben Vanik163547a2023-05-15 11:59:13 -0700617 return exit_code;
Stella Laurenzof4469e72019-11-11 18:08:55 -0800618}