blob: b055880069d405443d7cec0f60dc47f64e873da0 [file] [log] [blame]
// Copyright 2023 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/tooling/instrument_util.h"
#include <memory.h>
#include <stdio.h>
#include <string.h>
#include "iree/base/internal/flags.h"
#include "iree/modules/hal/types.h"
//===----------------------------------------------------------------------===//
// Instrument data management
//===----------------------------------------------------------------------===//
IREE_FLAG(string, instrument_file, "",
"File to populate with instrument data from the program.");
static iree_status_t iree_tooling_write_iovec(iree_vm_ref_t iovec, FILE* file) {
IREE_TRACE_ZONE_BEGIN(z0);
bool write_ok = false;
if (iree_vm_buffer_isa(iovec)) {
iree_vm_buffer_t* buffer = iree_vm_buffer_deref(iovec);
IREE_TRACE_ZONE_APPEND_VALUE_I64(z0,
(int64_t)iree_vm_buffer_length(buffer));
write_ok =
fwrite(iree_vm_buffer_data(buffer), 1, iree_vm_buffer_length(buffer),
file) == iree_vm_buffer_length(buffer);
} else if (iree_hal_buffer_view_isa(iovec)) {
iree_hal_buffer_view_t* buffer_view = iree_hal_buffer_view_deref(iovec);
IREE_TRACE_ZONE_APPEND_VALUE_I64(
z0, (int64_t)iree_hal_buffer_view_byte_length(buffer_view));
iree_hal_buffer_mapping_t mapping;
IREE_RETURN_AND_END_ZONE_IF_ERROR(
z0, iree_hal_buffer_map_range(iree_hal_buffer_view_buffer(buffer_view),
IREE_HAL_MAPPING_MODE_SCOPED,
IREE_HAL_MEMORY_ACCESS_READ, 0,
IREE_HAL_WHOLE_BUFFER, &mapping));
write_ok = fwrite(mapping.contents.data, 1, mapping.contents.data_length,
file) == mapping.contents.data_length;
IREE_IGNORE_ERROR(iree_hal_buffer_unmap_range(&mapping));
}
IREE_TRACE_ZONE_END(z0);
return write_ok ? iree_ok_status()
: iree_make_status(iree_status_code_from_errno(errno),
"failed to write iovec to file");
}
iree_status_t iree_tooling_process_instrument_data(
iree_vm_context_t* context, iree_allocator_t host_allocator) {
// If no flag was specified we ignore instrument data.
if (strlen(FLAG_instrument_file) == 0) return iree_ok_status();
IREE_TRACE_ZONE_BEGIN(z0);
IREE_TRACE_ZONE_APPEND_TEXT(z0, FLAG_instrument_file);
// Open the file for overwriting. We do this even if there is no instrument
// data in the program as we'd rather have the user end up with a 0-byte file
// when they explicitly ask for it instead of stale data from previous runs.
FILE* file = fopen(FLAG_instrument_file, "wb");
if (!file) {
IREE_TRACE_ZONE_END(z0);
return iree_make_status(iree_status_code_from_errno(errno),
"failed to open instrument file '%s' for writing",
FLAG_instrument_file);
}
// Each query function pushes iovecs on to a list we provide; we create one
// list and use that across all of them.
iree_vm_list_t* iovec_list = NULL;
IREE_RETURN_AND_END_ZONE_IF_ERROR(
z0, iree_vm_list_create(iree_vm_make_undefined_type_def(), 8,
host_allocator, &iovec_list));
iree_vm_list_t* input_list = NULL;
iree_status_t status = iree_vm_list_create(iree_vm_make_undefined_type_def(),
8, host_allocator, &input_list);
if (iree_status_is_ok(status)) {
iree_vm_ref_t iovec_list_ref = iree_vm_list_retain_ref(iovec_list);
status = iree_vm_list_push_ref_move(input_list, &iovec_list_ref);
}
// Process instrument data from all modules in the context.
if (iree_status_is_ok(status)) {
for (iree_host_size_t i = 0; i < iree_vm_context_module_count(context);
++i) {
iree_vm_module_t* module = iree_vm_context_module_at(context, i);
if (!module) continue;
// Find the query function, if present.
iree_vm_function_t query_func;
iree_status_t lookup_status = iree_vm_module_lookup_function_by_name(
module, IREE_VM_FUNCTION_LINKAGE_EXPORT_OPTIONAL,
IREE_SV("__query_instruments"), &query_func);
if (!iree_status_is_ok(lookup_status)) {
// Skip missing/invalid query function.
iree_status_ignore(lookup_status);
continue;
}
IREE_TRACE_ZONE_BEGIN(z1);
IREE_TRACE_ZONE_APPEND_TEXT(z1, iree_vm_module_name(module).data,
iree_vm_module_name(module).size);
status = iree_vm_invoke(context, query_func, IREE_VM_INVOCATION_FLAG_NONE,
NULL, input_list, NULL, host_allocator);
IREE_TRACE_ZONE_END(z1);
if (!iree_status_is_ok(status)) break;
}
}
if (iree_status_is_ok(status)) {
for (iree_host_size_t i = 0; i < iree_vm_list_size(iovec_list); ++i) {
iree_vm_ref_t iovec = iree_vm_ref_null();
status = iree_vm_list_get_ref_assign(iovec_list, i, &iovec);
if (!iree_status_is_ok(status)) break;
status = iree_tooling_write_iovec(iovec, file);
if (!iree_status_is_ok(status)) break;
}
}
iree_vm_list_release(input_list);
iree_vm_list_release(iovec_list);
fclose(file);
IREE_TRACE_ZONE_END(z0);
return status;
}