Error SyncBEFFunction::Init()

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();
}