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