in lib/bef_executor/bef_file.cc [617:707]
Error SyncBEFFunction::Init() {
assert(register_infos_.empty());
assert(kernels_.empty());
assert(kernel_offsets_.empty());
assert(result_regs_.empty());
auto format_error = [&](const char* msg) -> Error {
return MakeStringError("Invalid SyncBEFFunction(", msg, ")");
};
auto function_section = bef_file_->function_section();
if (function_offset_ >= function_section.size())
return format_error("Invalid function offset");
BEFReader reader(function_section.drop_front(function_offset_));
// First we have the location info and register info table.
size_t num_registers;
size_t location_offset;
if (!reader.ReadVbrInt(&location_offset) ||
!reader.ReadVbrInt(&num_registers))
return format_error("Failed to read location_offset or num_registers");
register_infos_.reserve(num_registers);
for (size_t reg_index = 0; reg_index < num_registers; ++reg_index) {
size_t user_count;
if (!reader.ReadVbrInt(&user_count))
return format_error("Failed to read register user_count");
bool is_arg = (reg_index < num_arguments());
if (is_arg) {
// +1 on the user count so that we do not reset the argument Value in the
// function evaluation.
++user_count;
}
register_infos_.push_back(
RegisterInfo{static_cast<uint32_t>(user_count), is_arg});
}
// Next we have the kernel index table.
size_t num_kernels;
if (!reader.ReadVbrInt(&num_kernels))
return format_error("Failed to read num_kernels");
kernel_offsets_.reserve(num_kernels);
size_t offset, num_operands, stream_id;
// Skip the first kernel which is the pseudo kernel used in BEF executor.
if (!reader.ReadVbrInt(&offset) || !reader.ReadVbrInt(&num_operands) ||
!reader.ReadVbrInt(&stream_id))
return format_error("Failed to read kernel offset or num_operands");
for (size_t kernel_index = 1; kernel_index < num_kernels; ++kernel_index) {
if (!reader.ReadVbrInt(&offset) || !reader.ReadVbrInt(&num_operands) ||
!reader.ReadVbrInt(&stream_id))
return format_error("Failed to read kernel offset or num_operands");
kernel_offsets_.push_back(offset);
}
// Read the result registers.
size_t num_results = result_types().size();
result_regs_.reserve(num_results);
for (unsigned i = 0, e = num_results; i != e; ++i) {
size_t result_reg;
if (!reader.ReadVbrInt(&result_reg) || result_reg >= num_registers)
return format_error("Failed to read result_reg");
result_regs_.push_back(result_reg);
// +1 on the user count so that we do not reset the result Value in the
// function evaluation.
auto& reg_info = register_infos_[result_reg];
if (reg_info.is_arg_or_result) {
return format_error("Result cannot be an argument or another result");
}
reg_info.is_arg_or_result = true;
++reg_info.user_count;
}
// Kernels are aligned to kKernelEntryAlignment.
if (!reader.ReadAlignment(kKernelEntryAlignment))
return format_error("Failed to align BEF to kKernelEntryAlignment");
// We found the start of our kernel section.
kernels_ = llvm::makeArrayRef(
reinterpret_cast<const uint32_t*>(reader.file().begin()),
reader.file().size() / kKernelEntryAlignment);
return Error::success();
}