Geoffrey Martin-Noble | 552d3f8 | 2021-05-25 17:56:09 -0700 | [diff] [blame] | 1 | // Copyright 2019 The IREE Authors |
Stella Laurenzo | f4469e7 | 2019-11-11 18:08:55 -0800 | [diff] [blame] | 2 | // |
Geoffrey Martin-Noble | 552d3f8 | 2021-05-25 17:56:09 -0700 | [diff] [blame] | 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 |
Stella Laurenzo | f4469e7 | 2019-11-11 18:08:55 -0800 | [diff] [blame] | 6 | |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 7 | // 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 Vanik | 35bc9a1 | 2022-03-09 09:05:58 -0800 | [diff] [blame] | 16 | #include <stdio.h> |
Stella Laurenzo | f4469e7 | 2019-11-11 18:08:55 -0800 | [diff] [blame] | 17 | |
Ben Vanik | 931a3b1 | 2021-05-20 13:27:13 -0700 | [diff] [blame] | 18 | #include "iree/base/api.h" |
Ben Vanik | 5507c6e | 2021-02-02 21:27:08 -0800 | [diff] [blame] | 19 | #include "iree/base/internal/file_io.h" |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 20 | #include "iree/base/internal/flags.h" |
Ben Vanik | 784db04 | 2023-02-25 11:10:21 -0800 | [diff] [blame] | 21 | #include "iree/vm/bytecode/archive.h" |
Ben Vanik | cf49d69 | 2023-02-24 20:24:09 -0800 | [diff] [blame] | 22 | #include "iree/vm/bytecode/module.h" |
Stella Laurenzo | f4469e7 | 2019-11-11 18:08:55 -0800 | [diff] [blame] | 23 | |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 24 | // 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 | |
| 42 | static void iree_tooling_print_indent(int indent) { |
| 43 | fprintf(stdout, "%*s", indent, ""); |
| 44 | } |
| 45 | |
| 46 | static 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 | |
| 67 | static 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 | |
| 89 | static 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 | |
| 94 | static 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 | |
| 103 | static 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 | |
| 107 | static 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 | |
| 117 | static 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 | |
| 130 | static 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 | |
| 141 | static 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 Vanik | 129ad45 | 2024-09-25 08:13:05 -0700 | [diff] [blame] | 174 | i = end_pos; // +1 from the for-loop |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 175 | } 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 | |
| 185 | static 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 | |
| 199 | static 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 | |
| 220 | static 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 | |
| 231 | static 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 Vanik | ac9d6d5 | 2023-12-03 20:20:31 -0800 | [diff] [blame] | 245 | 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 Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 249 | } |
| 250 | |
| 251 | static 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 | |
| 264 | static 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. |
| 280 | static 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 | |
| 295 | static 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 | |
| 334 | static 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 | |
| 345 | static 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 | |
| 382 | static 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 Laurenzo | f4469e7 | 2019-11-11 18:08:55 -0800 | [diff] [blame] | 398 | } |
Ben Vanik | 35bc9a1 | 2022-03-09 09:05:58 -0800 | [diff] [blame] | 399 | |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 400 | 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 Vanik | 6ab1ed8 | 2024-01-17 15:00:33 -0800 | [diff] [blame] | 404 | fprintf(stdout, "\n"); |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 405 | } |
Ben Vanik | 9a28639 | 2022-05-20 19:45:23 -0700 | [diff] [blame] | 406 | |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 407 | 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 Vanik | bc685ed | 2020-11-14 17:09:46 -0800 | [diff] [blame] | 413 | |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 414 | 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 Todd | 60b0764 | 2023-06-15 09:41:01 -0700 | [diff] [blame] | 452 | fprintf(stdout, "FlatBuffer: %" PRIhsz " bytes\n", |
| 453 | flatbuffer_contents.data_length); |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 454 | 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 | |
| 512 | static 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 | |
| 523 | IREE_FLAG(bool, flatbuffer_pretty, false, "Pretty print flatbuffer JSON."); |
| 524 | |
| 525 | static iree_status_t iree_tooling_dump_module_flatbuffer_json( |
| 526 | iree_const_byte_span_t flatbuffer_contents) { |
Ben Vanik | bc685ed | 2020-11-14 17:09:46 -0800 | [diff] [blame] | 527 | flatcc_json_printer_t printer; |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 528 | 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 Vanik | bc685ed | 2020-11-14 17:09:46 -0800 | [diff] [blame] | 532 | flatcc_json_printer_set_skip_default(&printer, true); |
Ben Vanik | 9a28639 | 2022-05-20 19:45:23 -0700 | [diff] [blame] | 533 | bytecode_module_def_print_json(&printer, |
| 534 | (const char*)flatbuffer_contents.data, |
| 535 | flatbuffer_contents.data_length); |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 536 | flatcc_json_printer_flush(&printer); |
Ben Vanik | bc685ed | 2020-11-14 17:09:46 -0800 | [diff] [blame] | 537 | flatcc_json_printer_clear(&printer); |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 538 | return iree_ok_status(); |
| 539 | } |
| 540 | |
| 541 | //===----------------------------------------------------------------------===// |
| 542 | // main |
| 543 | //===----------------------------------------------------------------------===// |
| 544 | |
| 545 | IREE_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 | |
| 551 | int main(int argc, char** argv) { |
Ben Vanik | 23f2828 | 2024-02-23 11:14:25 -0800 | [diff] [blame] | 552 | IREE_TRACE_APP_ENTER(); |
| 553 | |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 554 | 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 Vanik | 11ced0c | 2023-11-03 14:24:08 -0700 | [diff] [blame] | 559 | "Dumps IREE VM module details to stdout.\n" |
| 560 | "$ iree-dump-module [--output=...] module.vmfb\n"); |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 561 | 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 Vanik | 23f2828 | 2024-02-23 11:14:25 -0800 | [diff] [blame] | 565 | IREE_TRACE_APP_EXIT(EXIT_FAILURE); |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 566 | return EXIT_FAILURE; |
| 567 | } |
| 568 | |
| 569 | iree_file_contents_t* file_contents = NULL; |
Ben Vanik | 9d15f36 | 2023-08-03 10:18:58 -0700 | [diff] [blame] | 570 | iree_status_t status = iree_file_read_contents( |
| 571 | argv[1], IREE_FILE_READ_FLAG_DEFAULT, host_allocator, &file_contents); |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 572 | |
| 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 Vanik | bc685ed | 2020-11-14 17:09:46 -0800 | [diff] [blame] | 606 | |
Ben Vanik | 9a28639 | 2022-05-20 19:45:23 -0700 | [diff] [blame] | 607 | iree_file_contents_free(file_contents); |
Ben Vanik | 35bc9a1 | 2022-03-09 09:05:58 -0800 | [diff] [blame] | 608 | |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 609 | 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 Vanik | 23f2828 | 2024-02-23 11:14:25 -0800 | [diff] [blame] | 616 | IREE_TRACE_APP_EXIT(exit_code); |
Ben Vanik | 163547a | 2023-05-15 11:59:13 -0700 | [diff] [blame] | 617 | return exit_code; |
Stella Laurenzo | f4469e7 | 2019-11-11 18:08:55 -0800 | [diff] [blame] | 618 | } |