Status LlvmSession::runOptWithArgs()

in compiler_gym/envs/llvm/service/LlvmSession.cc [256:318]


Status LlvmSession::runOptWithArgs(const std::vector<std::string>& optArgs) {
  // Create temporary files for `opt` to read from and write to.
  const auto before_path = fs::unique_path(workingDirectory() / "module-%%%%%%%%.bc");
  const auto after_path = fs::unique_path(workingDirectory() / "module-%%%%%%%%.bc");
  RETURN_IF_ERROR(writeBitcodeFile(benchmark().module(), before_path));

  // Build a command line invocation: `opt input.bc -o output.bc <optArgs...>`.
  const auto optPath = util::getSiteDataPath("llvm-v0/bin/opt");
  if (!fs::exists(optPath)) {
    return Status(StatusCode::INTERNAL, fmt::format("File not found: {}", optPath.string()));
  }

  std::string optCmd =
      fmt::format("{} {} -o {}", optPath.string(), before_path.string(), after_path.string());
  for (const auto& arg : optArgs) {
    optCmd += " " + arg;
  }

  // Run the opt command line.
  try {
    boost::asio::io_context optStderrStream;
    std::future<std::string> optStderrFuture;

    bp::child opt(optCmd, bp::std_in.close(), bp::std_out > bp::null, bp::std_err > optStderrFuture,
                  optStderrStream);

    if (!util::wait_for(opt, std::chrono::seconds(60))) {
      return Status(StatusCode::DEADLINE_EXCEEDED,
                    fmt::format("Failed to run opt within 60 seconds: {}", optCmd));
    }
    optStderrStream.run();
    if (opt.exit_code()) {
      const std::string stderr = optStderrFuture.get();
      return Status(StatusCode::INTERNAL,
                    fmt::format("Opt command '{}' failed with return code {}: {}", optCmd,
                                opt.exit_code(), stderr));
    }
    fs::remove(before_path);
  } catch (bp::process_error& e) {
    fs::remove(before_path);
    return Status(StatusCode::INTERNAL,
                  fmt::format("Failed to run opt command '{}': {}", optCmd, e.what()));
  }

  if (!fs::exists(after_path)) {
    return Status(StatusCode::INTERNAL, "Failed to generate output file");
  }

  // Read the bitcode file generated by `opt`.
  Bitcode bitcode;
  auto status = readBitcodeFile(after_path, &bitcode);
  fs::remove(after_path);
  if (!status.ok()) {
    return status;
  }

  // Replace the benchmark's module with the one generated by `opt`.
  auto module = makeModule(benchmark().context(), bitcode, benchmark().name(), &status);
  RETURN_IF_ERROR(status);
  benchmark().replaceModule(std::move(module));

  return Status::OK;
}