[llvm] [tools] LLVM Advisor - optimization analysis and performance guidance tool (PR #147451)
Miguel Cárdenas via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 12 21:30:00 PDT 2025
https://github.com/miguelcsx updated https://github.com/llvm/llvm-project/pull/147451
>From 429ae143a09775ea9e5ab8854b9b695edd7cf63f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miguel=20C=C3=A1rdenas?= <miguelecsx at gmail.com>
Date: Tue, 8 Jul 2025 04:41:10 +0200
Subject: [PATCH 1/5] [llvm-advisor] add initial project structure and
configuration
The AdvisorConfig class provides JSON based configuration loading
with file classification patterns and output directory management.
---
llvm/tools/llvm-advisor/CMakeLists.txt | 15 +++++
llvm/tools/llvm-advisor/config/config.json | 7 ++
llvm/tools/llvm-advisor/src/CMakeLists.txt | 35 ++++++++++
.../llvm-advisor/src/Config/AdvisorConfig.cpp | 64 +++++++++++++++++++
.../llvm-advisor/src/Config/AdvisorConfig.h | 41 ++++++++++++
5 files changed, 162 insertions(+)
create mode 100644 llvm/tools/llvm-advisor/CMakeLists.txt
create mode 100644 llvm/tools/llvm-advisor/config/config.json
create mode 100644 llvm/tools/llvm-advisor/src/CMakeLists.txt
create mode 100644 llvm/tools/llvm-advisor/src/Config/AdvisorConfig.cpp
create mode 100644 llvm/tools/llvm-advisor/src/Config/AdvisorConfig.h
diff --git a/llvm/tools/llvm-advisor/CMakeLists.txt b/llvm/tools/llvm-advisor/CMakeLists.txt
new file mode 100644
index 0000000000000..d2389bdd1e0fa
--- /dev/null
+++ b/llvm/tools/llvm-advisor/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.18)
+
+set(LLVM_TOOL_LLVM_ADVISOR_BUILD_DEFAULT ON)
+set(LLVM_REQUIRE_EXE_NAMES llvm-advisor)
+
+add_subdirectory(src)
+
+# Set the executable name
+set_target_properties(llvm-advisor PROPERTIES
+ OUTPUT_NAME llvm-advisor)
+
+# Install the binary
+install(TARGETS llvm-advisor
+ RUNTIME DESTINATION bin
+ COMPONENT llvm-advisor)
diff --git a/llvm/tools/llvm-advisor/config/config.json b/llvm/tools/llvm-advisor/config/config.json
new file mode 100644
index 0000000000000..9e94a41ff46c4
--- /dev/null
+++ b/llvm/tools/llvm-advisor/config/config.json
@@ -0,0 +1,7 @@
+{
+ "outputDir": ".llvm-advisor",
+ "verbose": false,
+ "keepTemps": false,
+ "runProfiler": true,
+ "timeout": 60
+}
diff --git a/llvm/tools/llvm-advisor/src/CMakeLists.txt b/llvm/tools/llvm-advisor/src/CMakeLists.txt
new file mode 100644
index 0000000000000..81088f8231625
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/CMakeLists.txt
@@ -0,0 +1,35 @@
+# Gather all .cpp sources in this directory tree
+file(GLOB_RECURSE LLVM_ADVISOR_SOURCES CONFIGURE_DEPENDS
+ ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
+)
+
+# Define the executable target
+add_llvm_tool(llvm-advisor
+ ${LLVM_ADVISOR_SOURCES}
+)
+
+# Link required LLVM libraries
+target_link_libraries(llvm-advisor PRIVATE
+ LLVMSupport
+ LLVMCore
+ LLVMIRReader
+ LLVMBitWriter
+ LLVMRemarks
+ LLVMProfileData
+)
+
+# Set include directories
+target_include_directories(llvm-advisor PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+# Install the Python view module alongside the binary
+install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../view/
+ DESTINATION ${CMAKE_INSTALL_BINDIR}/view
+ FILES_MATCHING
+ PATTERN "*.py"
+ PATTERN "*.html"
+ PATTERN "*.css"
+ PATTERN "*.js"
+ PATTERN "*.md"
+)
diff --git a/llvm/tools/llvm-advisor/src/Config/AdvisorConfig.cpp b/llvm/tools/llvm-advisor/src/Config/AdvisorConfig.cpp
new file mode 100644
index 0000000000000..69f1e3d52702e
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Config/AdvisorConfig.cpp
@@ -0,0 +1,64 @@
+#include "AdvisorConfig.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+
+namespace llvm {
+namespace advisor {
+
+AdvisorConfig::AdvisorConfig() {
+ // Use relative path as default, will be resolved by CompilationManager
+ OutputDir_ = ".llvm-advisor";
+}
+
+Expected<bool> AdvisorConfig::loadFromFile(const std::string &path) {
+ auto BufferOrError = MemoryBuffer::getFile(path);
+ if (!BufferOrError) {
+ return createStringError(BufferOrError.getError(),
+ "Cannot read config file");
+ }
+
+ auto Buffer = std::move(*BufferOrError);
+ Expected<json::Value> JsonOrError = json::parse(Buffer->getBuffer());
+ if (!JsonOrError) {
+ return JsonOrError.takeError();
+ }
+
+ auto &Json = *JsonOrError;
+ auto *Obj = Json.getAsObject();
+ if (!Obj) {
+ return createStringError(std::make_error_code(std::errc::invalid_argument),
+ "Config file must contain JSON object");
+ }
+
+ if (auto outputDirOpt = Obj->getString("outputDir"); outputDirOpt) {
+ OutputDir_ = outputDirOpt->str();
+ }
+
+ if (auto verboseOpt = Obj->getBoolean("verbose"); verboseOpt) {
+ Verbose_ = *verboseOpt;
+ }
+
+ if (auto keepTempsOpt = Obj->getBoolean("keepTemps"); keepTempsOpt) {
+ KeepTemps_ = *keepTempsOpt;
+ }
+
+ if (auto runProfileOpt = Obj->getBoolean("runProfiler"); runProfileOpt) {
+ RunProfiler_ = *runProfileOpt;
+ }
+
+ if (auto timeoutOpt = Obj->getInteger("timeout"); timeoutOpt) {
+ TimeoutSeconds_ = static_cast<int>(*timeoutOpt);
+ }
+
+ return true;
+}
+
+std::string AdvisorConfig::getToolPath(const std::string &tool) const {
+ // For now, just return the tool name and rely on PATH
+ return tool;
+}
+
+} // namespace advisor
+} // namespace llvm
diff --git a/llvm/tools/llvm-advisor/src/Config/AdvisorConfig.h b/llvm/tools/llvm-advisor/src/Config/AdvisorConfig.h
new file mode 100644
index 0000000000000..b7f553fddbb23
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Config/AdvisorConfig.h
@@ -0,0 +1,41 @@
+#ifndef LLVM_ADVISOR_CONFIG_H
+#define LLVM_ADVISOR_CONFIG_H
+
+#include "llvm/Support/Error.h"
+#include <string>
+
+namespace llvm {
+namespace advisor {
+
+class AdvisorConfig {
+public:
+ AdvisorConfig();
+
+ Expected<bool> loadFromFile(const std::string &path);
+
+ void setOutputDir(const std::string &dir) { OutputDir_ = dir; }
+ void setVerbose(bool verbose) { Verbose_ = verbose; }
+ void setKeepTemps(bool keep) { KeepTemps_ = keep; }
+ void setRunProfiler(bool run) { RunProfiler_ = run; }
+ void setTimeout(int seconds) { TimeoutSeconds_ = seconds; }
+
+ const std::string &getOutputDir() const { return OutputDir_; }
+ bool getVerbose() const { return Verbose_; }
+ bool getKeepTemps() const { return KeepTemps_; }
+ bool getRunProfiler() const { return RunProfiler_; }
+ int getTimeout() const { return TimeoutSeconds_; }
+
+ std::string getToolPath(const std::string &tool) const;
+
+private:
+ std::string OutputDir_;
+ bool Verbose_ = false;
+ bool KeepTemps_ = false;
+ bool RunProfiler_ = true;
+ int TimeoutSeconds_ = 60;
+};
+
+} // namespace advisor
+} // namespace llvm
+
+#endif
>From 65ce6d57cb17abfe0226eb847dcfc98fe04518ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miguel=20C=C3=A1rdenas?= <miguelecsx at gmail.com>
Date: Sun, 13 Jul 2025 05:51:00 +0200
Subject: [PATCH 2/5] [llvm-advisor] Add utility for file and process
management
- Add FileManager for file operations.
- Add FileClassifier for compilation artifact categorization.
- Add ProcessRunner for subprocess execution.
---
.../llvm-advisor/src/Utils/FileClassifier.cpp | 136 ++++++++++++
.../llvm-advisor/src/Utils/FileClassifier.h | 26 +++
.../llvm-advisor/src/Utils/FileManager.cpp | 205 ++++++++++++++++++
.../llvm-advisor/src/Utils/FileManager.h | 46 ++++
.../llvm-advisor/src/Utils/ProcessRunner.cpp | 69 ++++++
.../llvm-advisor/src/Utils/ProcessRunner.h | 32 +++
6 files changed, 514 insertions(+)
create mode 100644 llvm/tools/llvm-advisor/src/Utils/FileClassifier.cpp
create mode 100644 llvm/tools/llvm-advisor/src/Utils/FileClassifier.h
create mode 100644 llvm/tools/llvm-advisor/src/Utils/FileManager.cpp
create mode 100644 llvm/tools/llvm-advisor/src/Utils/FileManager.h
create mode 100644 llvm/tools/llvm-advisor/src/Utils/ProcessRunner.cpp
create mode 100644 llvm/tools/llvm-advisor/src/Utils/ProcessRunner.h
diff --git a/llvm/tools/llvm-advisor/src/Utils/FileClassifier.cpp b/llvm/tools/llvm-advisor/src/Utils/FileClassifier.cpp
new file mode 100644
index 0000000000000..e9b39f984c771
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Utils/FileClassifier.cpp
@@ -0,0 +1,136 @@
+#include "FileClassifier.h"
+#include "llvm/Support/Path.h"
+
+namespace llvm {
+namespace advisor {
+
+FileClassification
+FileClassifier::classifyFile(const std::string &filePath) const {
+ StringRef filename = sys::path::filename(filePath);
+ StringRef extension = sys::path::extension(filePath);
+
+ FileClassification classification;
+ classification.isGenerated = true;
+ classification.isTemporary = false;
+
+ // LLVM IR files
+ if (extension == ".ll") {
+ classification.category = "ir";
+ classification.description = "LLVM IR text";
+ return classification;
+ }
+
+ // Assembly files
+ if (extension == ".s" || extension == ".S") {
+ classification.category = "assembly";
+ classification.description = "Assembly";
+ return classification;
+ }
+
+ // Optimization remarks
+ if (filename.ends_with(".opt.yaml") || filename.ends_with(".opt.yml")) {
+ classification.category = "remarks";
+ classification.description = "Optimization remarks";
+ return classification;
+ }
+
+ // Preprocessed files
+ if (extension == ".i" || extension == ".ii") {
+ classification.category = "preprocessed";
+ classification.description = "Preprocessed source";
+ return classification;
+ }
+
+ // AST dumps
+ if (extension == ".ast" || filename.contains("ast-dump")) {
+ classification.category = "ast";
+ classification.description = "AST dump";
+ return classification;
+ }
+
+ // Profile data
+ if (extension == ".profraw" || extension == ".profdata") {
+ classification.category = "profile";
+ classification.description = "Profile data";
+ return classification;
+ }
+
+ // Include trees
+ if (filename.contains(".include.") || filename.contains("include-tree")) {
+ classification.category = "include-tree";
+ classification.description = "Include tree";
+ return classification;
+ }
+
+ // Debug info
+ if (filename.contains("debug") || filename.contains("dwarf")) {
+ classification.category = "debug";
+ classification.description = "Debug information";
+ return classification;
+ }
+
+ // Static analyzer output
+ if (filename.contains("analysis") || filename.contains("analyzer")) {
+ classification.category = "static-analyzer";
+ classification.description = "Static analyzer output";
+ return classification;
+ }
+
+ // Macro expansion
+ if (filename.contains("macro-expanded")) {
+ classification.category = "macro-expansion";
+ classification.description = "Macro expansion";
+ return classification;
+ }
+
+ // Compilation phases
+ if (filename.contains("phases")) {
+ classification.category = "compilation-phases";
+ classification.description = "Compilation phases";
+ return classification;
+ }
+
+ // Control flow graph
+ if (extension == ".dot" || filename.contains("cfg")) {
+ classification.category = "cfg";
+ classification.description = "Control flow graph";
+ return classification;
+ }
+
+ // Template instantiation
+ if (filename.contains("template") || filename.contains("instantiation")) {
+ classification.category = "template-instantiation";
+ classification.description = "Template instantiation";
+ return classification;
+ }
+
+ // Default for unknown files
+ classification.category = "unknown";
+ classification.description = "Unknown file type";
+ classification.isGenerated = false;
+ return classification;
+}
+
+bool FileClassifier::shouldCollect(const std::string &filePath) const {
+ auto classification = classifyFile(filePath);
+ return classification.category != "unknown" && classification.isGenerated &&
+ !classification.isTemporary;
+}
+
+std::string FileClassifier::getLanguage(const std::string &filePath) const {
+ StringRef extension = sys::path::extension(filePath);
+
+ if (extension == ".c")
+ return "C";
+ if (extension == ".cpp" || extension == ".cc" || extension == ".cxx" ||
+ extension == ".C")
+ return "C++";
+ if (extension == ".h" || extension == ".hpp" || extension == ".hh" ||
+ extension == ".hxx")
+ return "Header";
+
+ return "Unknown";
+}
+
+} // namespace advisor
+} // namespace llvm
diff --git a/llvm/tools/llvm-advisor/src/Utils/FileClassifier.h b/llvm/tools/llvm-advisor/src/Utils/FileClassifier.h
new file mode 100644
index 0000000000000..6bf7c43ba4ffc
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Utils/FileClassifier.h
@@ -0,0 +1,26 @@
+#ifndef LLVM_ADVISOR_FILE_CLASSIFIER_H
+#define LLVM_ADVISOR_FILE_CLASSIFIER_H
+
+#include <string>
+
+namespace llvm {
+namespace advisor {
+
+struct FileClassification {
+ std::string category;
+ std::string description;
+ bool isTemporary = false;
+ bool isGenerated = true;
+};
+
+class FileClassifier {
+public:
+ FileClassification classifyFile(const std::string &filePath) const;
+ bool shouldCollect(const std::string &filePath) const;
+ std::string getLanguage(const std::string &filePath) const;
+};
+
+} // namespace advisor
+} // namespace llvm
+
+#endif
diff --git a/llvm/tools/llvm-advisor/src/Utils/FileManager.cpp b/llvm/tools/llvm-advisor/src/Utils/FileManager.cpp
new file mode 100644
index 0000000000000..7083d7edb7f3d
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Utils/FileManager.cpp
@@ -0,0 +1,205 @@
+#include "FileManager.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+#include <system_error>
+
+namespace llvm {
+namespace advisor {
+
+Expected<std::string> FileManager::createTempDir(const std::string &prefix) {
+ SmallString<128> tempDirPath;
+ if (std::error_code ec =
+ sys::fs::createUniqueDirectory(prefix, tempDirPath)) {
+ return createStringError(ec, "Failed to create unique temporary directory");
+ }
+ return std::string(tempDirPath.str());
+}
+
+Error FileManager::copyDirectory(const std::string &source,
+ const std::string &dest) {
+ std::error_code EC;
+
+ SmallString<128> sourcePathNorm(source);
+ // Remove trailing slash manually if present
+ if (sourcePathNorm.ends_with("/") && sourcePathNorm.size() > 1) {
+ sourcePathNorm.pop_back();
+ }
+
+ for (sys::fs::recursive_directory_iterator I(source, EC), E; I != E && !EC;
+ I.increment(EC)) {
+ StringRef currentPath = I->path();
+ SmallString<128> destPath(dest);
+
+ StringRef relativePath = currentPath;
+ if (!relativePath.consume_front(sourcePathNorm)) {
+ return createStringError(
+ std::make_error_code(std::errc::invalid_argument),
+ "Path '" + currentPath.str() + "' not in source dir '" + source +
+ "'");
+ }
+ // Remove leading slash manually if present
+ if (relativePath.starts_with("/")) {
+ relativePath = relativePath.drop_front(1);
+ }
+
+ sys::path::append(destPath, relativePath);
+
+ if (sys::fs::is_directory(currentPath)) {
+ if (sys::fs::create_directories(destPath)) {
+ return createStringError(std::make_error_code(std::errc::io_error),
+ "Failed to create directory: " +
+ destPath.str().str());
+ }
+ } else {
+ if (sys::fs::create_directories(sys::path::parent_path(destPath))) {
+ return createStringError(std::make_error_code(std::errc::io_error),
+ "Failed to create parent directory for: " +
+ destPath.str().str());
+ }
+ if (sys::fs::copy_file(currentPath, destPath)) {
+ return createStringError(std::make_error_code(std::errc::io_error),
+ "Failed to copy file: " + currentPath.str());
+ }
+ }
+ }
+
+ if (EC) {
+ return createStringError(EC, "Failed to iterate directory: " + source);
+ }
+
+ return Error::success();
+}
+
+Error FileManager::removeDirectory(const std::string &path) {
+ if (!sys::fs::exists(path)) {
+ return Error::success();
+ }
+
+ std::error_code EC;
+ std::vector<std::string> Dirs;
+ for (sys::fs::recursive_directory_iterator I(path, EC), E; I != E && !EC;
+ I.increment(EC)) {
+ if (I->type() == sys::fs::file_type::directory_file) {
+ Dirs.push_back(I->path());
+ } else {
+ if (auto E = sys::fs::remove(I->path())) {
+ return createStringError(E, "Failed to remove file: " + I->path());
+ }
+ }
+ }
+
+ if (EC) {
+ return createStringError(EC, "Error iterating directory " + path);
+ }
+
+ for (const auto &Dir : llvm::reverse(Dirs)) {
+ if (auto E = sys::fs::remove(Dir)) {
+ return createStringError(E, "Failed to remove directory: " + Dir);
+ }
+ }
+
+ if (auto E = sys::fs::remove(path)) {
+ return createStringError(E,
+ "Failed to remove top-level directory: " + path);
+ }
+
+ return Error::success();
+}
+
+std::vector<std::string> FileManager::findFiles(const std::string &directory,
+ const std::string &pattern) {
+ std::vector<std::string> files;
+ std::error_code EC;
+ for (sys::fs::recursive_directory_iterator I(directory, EC), E; I != E && !EC;
+ I.increment(EC)) {
+ if (I->type() != sys::fs::file_type::directory_file) {
+ StringRef filename = sys::path::filename(I->path());
+ if (filename.find(pattern) != StringRef::npos) {
+ files.push_back(I->path());
+ }
+ }
+ }
+ return files;
+}
+
+std::vector<std::string>
+FileManager::findFilesByExtension(const std::string &directory,
+ const std::vector<std::string> &extensions) {
+ std::vector<std::string> files;
+ std::error_code EC;
+ for (sys::fs::recursive_directory_iterator I(directory, EC), E; I != E && !EC;
+ I.increment(EC)) {
+ if (I->type() != sys::fs::file_type::directory_file) {
+ StringRef filepath = I->path();
+ for (const auto &ext : extensions) {
+ if (filepath.ends_with(ext)) {
+ files.push_back(filepath.str());
+ break;
+ }
+ }
+ }
+ }
+ return files;
+}
+
+Error FileManager::moveFile(const std::string &source,
+ const std::string &dest) {
+ if (source == dest) {
+ return Error::success();
+ }
+
+ if (sys::fs::create_directories(sys::path::parent_path(dest))) {
+ return createStringError(
+ std::make_error_code(std::errc::io_error),
+ "Failed to create parent directory for destination: " + dest);
+ }
+
+ if (sys::fs::rename(source, dest)) {
+ // If rename fails, try copy and remove
+ if (sys::fs::copy_file(source, dest)) {
+ return createStringError(std::make_error_code(std::errc::io_error),
+ "Failed to move file (copy failed): " + source);
+ }
+ if (sys::fs::remove(source)) {
+ return createStringError(std::make_error_code(std::errc::io_error),
+ "Failed to move file (source removal failed): " +
+ source);
+ }
+ }
+
+ return Error::success();
+}
+
+Error FileManager::copyFile(const std::string &source,
+ const std::string &dest) {
+ if (source == dest) {
+ return Error::success();
+ }
+
+ if (sys::fs::create_directories(sys::path::parent_path(dest))) {
+ return createStringError(
+ std::make_error_code(std::errc::io_error),
+ "Failed to create parent directory for destination: " + dest);
+ }
+
+ if (sys::fs::copy_file(source, dest)) {
+ return createStringError(std::make_error_code(std::errc::io_error),
+ "Failed to copy file: " + source);
+ }
+
+ return Error::success();
+}
+
+Expected<size_t> FileManager::getFileSize(const std::string &path) {
+ sys::fs::file_status status;
+ if (auto EC = sys::fs::status(path, status)) {
+ return createStringError(EC, "File not found: " + path);
+ }
+
+ return status.getSize();
+}
+
+} // namespace advisor
+} // namespace llvm
\ No newline at end of file
diff --git a/llvm/tools/llvm-advisor/src/Utils/FileManager.h b/llvm/tools/llvm-advisor/src/Utils/FileManager.h
new file mode 100644
index 0000000000000..07b49e647f542
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Utils/FileManager.h
@@ -0,0 +1,46 @@
+#ifndef LLVM_ADVISOR_FILE_MANAGER_H
+#define LLVM_ADVISOR_FILE_MANAGER_H
+
+#include "llvm/Support/Error.h"
+#include <string>
+#include <vector>
+
+namespace llvm {
+namespace advisor {
+
+class FileManager {
+public:
+ /// Create unique temporary directory with pattern llvm-advisor-xxxxx
+ static Expected<std::string>
+ createTempDir(const std::string &prefix = "llvm-advisor");
+
+ /// Recursively copy directory
+ static Error copyDirectory(const std::string &source,
+ const std::string &dest);
+
+ /// Remove directory and contents
+ static Error removeDirectory(const std::string &path);
+
+ /// Find files matching pattern
+ static std::vector<std::string> findFiles(const std::string &directory,
+ const std::string &pattern);
+
+ /// Find files by extension
+ static std::vector<std::string>
+ findFilesByExtension(const std::string &directory,
+ const std::vector<std::string> &extensions);
+
+ /// Move file from source to destination
+ static Error moveFile(const std::string &source, const std::string &dest);
+
+ /// Copy file from source to destination
+ static Error copyFile(const std::string &source, const std::string &dest);
+
+ /// Get file size
+ static Expected<size_t> getFileSize(const std::string &path);
+};
+
+} // namespace advisor
+} // namespace llvm
+
+#endif
diff --git a/llvm/tools/llvm-advisor/src/Utils/ProcessRunner.cpp b/llvm/tools/llvm-advisor/src/Utils/ProcessRunner.cpp
new file mode 100644
index 0000000000000..b08b3cc88a434
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Utils/ProcessRunner.cpp
@@ -0,0 +1,69 @@
+#include "ProcessRunner.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+
+namespace llvm {
+namespace advisor {
+
+Expected<ProcessRunner::ProcessResult>
+ProcessRunner::run(const std::string &program,
+ const std::vector<std::string> &args, int timeoutSeconds) {
+
+ auto programPath = sys::findProgramByName(program);
+ if (!programPath) {
+ return createStringError(programPath.getError(),
+ "Tool not found: " + program);
+ }
+
+ std::vector<StringRef> execArgs;
+ execArgs.push_back(program);
+ for (const auto &arg : args) {
+ execArgs.push_back(arg);
+ }
+
+ SmallString<128> stdoutPath, stderrPath;
+ sys::fs::createTemporaryFile("stdout", "tmp", stdoutPath);
+ sys::fs::createTemporaryFile("stderr", "tmp", stderrPath);
+
+ std::optional<StringRef> redirects[] = {
+ std::nullopt, // stdin
+ StringRef(stdoutPath), // stdout
+ StringRef(stderrPath) // stderr
+ };
+
+ int exitCode = sys::ExecuteAndWait(*programPath, execArgs, std::nullopt,
+ redirects, timeoutSeconds);
+
+ ProcessResult result;
+ result.exitCode = exitCode;
+ // TODO: Collect information about compilation time
+ result.executionTime = 0; // not tracking time
+
+ auto stdoutBuffer = MemoryBuffer::getFile(stdoutPath);
+ if (stdoutBuffer) {
+ result.stdout = (*stdoutBuffer)->getBuffer().str();
+ }
+
+ auto stderrBuffer = MemoryBuffer::getFile(stderrPath);
+ if (stderrBuffer) {
+ result.stderr = (*stderrBuffer)->getBuffer().str();
+ }
+
+ sys::fs::remove(stdoutPath);
+ sys::fs::remove(stderrPath);
+
+ return result;
+}
+
+Expected<ProcessRunner::ProcessResult> ProcessRunner::runWithEnv(
+ const std::string &program, const std::vector<std::string> &args,
+ const std::vector<std::string> &env, int timeoutSeconds) {
+
+ // For simplicity, just use the regular run method
+ // Environment variables can be added later if needed
+ return run(program, args, timeoutSeconds);
+}
+
+} // namespace advisor
+} // namespace llvm
diff --git a/llvm/tools/llvm-advisor/src/Utils/ProcessRunner.h b/llvm/tools/llvm-advisor/src/Utils/ProcessRunner.h
new file mode 100644
index 0000000000000..ffd0ef353ba16
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Utils/ProcessRunner.h
@@ -0,0 +1,32 @@
+#ifndef LLVM_ADVISOR_PROCESS_RUNNER_H
+#define LLVM_ADVISOR_PROCESS_RUNNER_H
+
+#include "llvm/Support/Error.h"
+#include <string>
+#include <vector>
+
+namespace llvm {
+namespace advisor {
+
+class ProcessRunner {
+public:
+ struct ProcessResult {
+ int exitCode;
+ std::string stdout;
+ std::string stderr;
+ double executionTime;
+ };
+
+ static Expected<ProcessResult> run(const std::string &program,
+ const std::vector<std::string> &args,
+ int timeoutSeconds = 60);
+
+ static Expected<ProcessResult>
+ runWithEnv(const std::string &program, const std::vector<std::string> &args,
+ const std::vector<std::string> &env, int timeoutSeconds = 60);
+};
+
+} // namespace advisor
+} // namespace llvm
+
+#endif
>From cc3e1ed4848ff6b7753cf731779602e4e7593309 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miguel=20C=C3=A1rdenas?= <miguelecsx at gmail.com>
Date: Sun, 13 Jul 2025 06:09:39 +0200
Subject: [PATCH 3/5] [llvm-advisor] Add basic build/compilation data models
Introduce data structures that represent a single build phase
and compilation unit.
---
.../llvm-advisor/src/Core/BuildContext.h | 52 +++++++++++++++
.../llvm-advisor/src/Core/CompilationUnit.cpp | 66 +++++++++++++++++++
.../llvm-advisor/src/Core/CompilationUnit.h | 58 ++++++++++++++++
3 files changed, 176 insertions(+)
create mode 100644 llvm/tools/llvm-advisor/src/Core/BuildContext.h
create mode 100644 llvm/tools/llvm-advisor/src/Core/CompilationUnit.cpp
create mode 100644 llvm/tools/llvm-advisor/src/Core/CompilationUnit.h
diff --git a/llvm/tools/llvm-advisor/src/Core/BuildContext.h b/llvm/tools/llvm-advisor/src/Core/BuildContext.h
new file mode 100644
index 0000000000000..4f40c37ca8706
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Core/BuildContext.h
@@ -0,0 +1,52 @@
+#ifndef LLVM_ADVISOR_BUILD_CONTEXT_H
+#define LLVM_ADVISOR_BUILD_CONTEXT_H
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace llvm {
+namespace advisor {
+
+enum class BuildPhase {
+ Unknown,
+ Preprocessing,
+ Compilation,
+ Assembly,
+ Linking,
+ Archiving,
+ CMakeConfigure,
+ CMakeBuild,
+ MakefileBuild
+};
+
+enum class BuildTool {
+ Unknown,
+ Clang,
+ GCC,
+ LLVM_Tools,
+ CMake,
+ Make,
+ Ninja,
+ Linker,
+ Archiver
+};
+
+struct BuildContext {
+ BuildPhase phase;
+ BuildTool tool;
+ std::string workingDirectory;
+ std::string outputDirectory;
+ std::vector<std::string> inputFiles;
+ std::vector<std::string> outputFiles;
+ std::vector<std::string> expectedGeneratedFiles;
+ std::map<std::string, std::string> metadata;
+ bool hasOffloading = false;
+ bool hasDebugInfo = false;
+ bool hasOptimization = false;
+};
+
+} // namespace advisor
+} // namespace llvm
+
+#endif
diff --git a/llvm/tools/llvm-advisor/src/Core/CompilationUnit.cpp b/llvm/tools/llvm-advisor/src/Core/CompilationUnit.cpp
new file mode 100644
index 0000000000000..8b6a478cfaf63
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Core/CompilationUnit.cpp
@@ -0,0 +1,66 @@
+#include "CompilationUnit.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+namespace llvm {
+namespace advisor {
+
+CompilationUnit::CompilationUnit(const CompilationUnitInfo &info,
+ const std::string &workDir)
+ : info_(info), workDir_(workDir) {
+ // Create unit-specific data directory
+ SmallString<128> dataDir;
+ sys::path::append(dataDir, workDir, "units", info.name);
+ sys::fs::create_directories(dataDir);
+}
+
+std::string CompilationUnit::getPrimarySource() const {
+ if (info_.sources.empty()) {
+ return "";
+ }
+ return info_.sources[0].path;
+}
+
+std::string CompilationUnit::getDataDir() const {
+ SmallString<128> dataDir;
+ sys::path::append(dataDir, workDir_, "units", info_.name);
+ return dataDir.str().str();
+}
+
+std::string CompilationUnit::getExecutablePath() const {
+ return info_.outputExecutable;
+}
+
+void CompilationUnit::addGeneratedFile(const std::string &type,
+ const std::string &path) {
+ generatedFiles_[type].push_back(path);
+}
+
+bool CompilationUnit::hasGeneratedFiles(const std::string &type) const {
+ if (type.empty()) {
+ return !generatedFiles_.empty();
+ }
+ auto it = generatedFiles_.find(type);
+ return it != generatedFiles_.end() && !it->second.empty();
+}
+
+std::vector<std::string>
+CompilationUnit::getGeneratedFiles(const std::string &type) const {
+ if (type.empty()) {
+ std::vector<std::string> allFiles;
+ for (const auto &pair : generatedFiles_) {
+ allFiles.insert(allFiles.end(), pair.second.begin(), pair.second.end());
+ }
+ return allFiles;
+ }
+ auto it = generatedFiles_.find(type);
+ return it != generatedFiles_.end() ? it->second : std::vector<std::string>();
+}
+
+const std::unordered_map<std::string, std::vector<std::string>> &
+CompilationUnit::getAllGeneratedFiles() const {
+ return generatedFiles_;
+}
+
+} // namespace advisor
+} // namespace llvm
\ No newline at end of file
diff --git a/llvm/tools/llvm-advisor/src/Core/CompilationUnit.h b/llvm/tools/llvm-advisor/src/Core/CompilationUnit.h
new file mode 100644
index 0000000000000..18dbc35ab5aec
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Core/CompilationUnit.h
@@ -0,0 +1,58 @@
+#ifndef LLVM_ADVISOR_COMPILATION_UNIT_H
+#define LLVM_ADVISOR_COMPILATION_UNIT_H
+
+#include "llvm/Support/Error.h"
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace llvm {
+namespace advisor {
+
+struct SourceFile {
+ std::string path;
+ std::string language;
+ bool isHeader = false;
+ std::vector<std::string> dependencies;
+};
+
+struct CompilationUnitInfo {
+ std::string name;
+ std::vector<SourceFile> sources;
+ std::vector<std::string> compileFlags;
+ std::string targetArch;
+ bool hasOffloading = false;
+ std::string outputObject;
+ std::string outputExecutable;
+};
+
+class CompilationUnit {
+public:
+ CompilationUnit(const CompilationUnitInfo &info, const std::string &workDir);
+
+ const std::string &getName() const { return info_.name; }
+ const CompilationUnitInfo &getInfo() const { return info_; }
+ const std::string &getWorkDir() const { return workDir_; }
+ std::string getPrimarySource() const;
+
+ std::string getDataDir() const;
+ std::string getExecutablePath() const;
+
+ void addGeneratedFile(const std::string &type, const std::string &path);
+
+ bool hasGeneratedFiles(const std::string &type) const;
+ std::vector<std::string>
+ getGeneratedFiles(const std::string &type = "") const;
+ const std::unordered_map<std::string, std::vector<std::string>> &
+ getAllGeneratedFiles() const;
+
+private:
+ CompilationUnitInfo info_;
+ std::string workDir_;
+ std::unordered_map<std::string, std::vector<std::string>> generatedFiles_;
+};
+
+} // namespace advisor
+} // namespace llvm
+
+#endif
\ No newline at end of file
>From 336db515d67b787c3e63d33e77f2c70787f1a578 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miguel=20C=C3=A1rdenas?= <miguelecsx at gmail.com>
Date: Sun, 13 Jul 2025 06:18:52 +0200
Subject: [PATCH 4/5] [llvm-advisor] Add command analyzer helper
CommandAnalyzer inspects an incoming compiler or build-system
invocation and classifies the tool in use, the build phase,
input/output files and notable flags.
---
.../llvm-advisor/src/Core/CommandAnalyzer.cpp | 167 ++++++++++++++++++
.../llvm-advisor/src/Core/CommandAnalyzer.h | 32 ++++
2 files changed, 199 insertions(+)
create mode 100644 llvm/tools/llvm-advisor/src/Core/CommandAnalyzer.cpp
create mode 100644 llvm/tools/llvm-advisor/src/Core/CommandAnalyzer.h
diff --git a/llvm/tools/llvm-advisor/src/Core/CommandAnalyzer.cpp b/llvm/tools/llvm-advisor/src/Core/CommandAnalyzer.cpp
new file mode 100644
index 0000000000000..3192c42669e65
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Core/CommandAnalyzer.cpp
@@ -0,0 +1,167 @@
+#include "CommandAnalyzer.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+namespace llvm {
+namespace advisor {
+
+CommandAnalyzer::CommandAnalyzer(const std::string &command,
+ const std::vector<std::string> &args)
+ : command_(command), args_(args) {}
+
+BuildContext CommandAnalyzer::analyze() const {
+ BuildContext context;
+ SmallString<256> cwd;
+ sys::fs::current_path(cwd);
+ context.workingDirectory = cwd.str().str();
+
+ context.tool = detectBuildTool();
+ context.phase = detectBuildPhase(context.tool);
+ context.inputFiles = extractInputFiles();
+ context.outputFiles = extractOutputFiles();
+ detectBuildFeatures(context);
+
+ return context;
+}
+
+BuildTool CommandAnalyzer::detectBuildTool() const {
+ return StringSwitch<BuildTool>(sys::path::filename(command_))
+ .StartsWith("clang", BuildTool::Clang)
+ .StartsWith("gcc", BuildTool::GCC)
+ .StartsWith("g++", BuildTool::GCC)
+ .Case("cmake", BuildTool::CMake)
+ .Case("make", BuildTool::Make)
+ .Case("ninja", BuildTool::Ninja)
+ .EndsWith("-ld", BuildTool::Linker)
+ .Case("ld", BuildTool::Linker)
+ .Case("ar", BuildTool::Archiver)
+ .Case("llvm-ar", BuildTool::Archiver)
+ .StartsWith("llvm-", BuildTool::LLVM_Tools)
+ .Default(BuildTool::Unknown);
+}
+
+BuildPhase CommandAnalyzer::detectBuildPhase(BuildTool tool) const {
+ if (tool == BuildTool::CMake) {
+ for (const auto &arg : args_) {
+ if (arg == "--build")
+ return BuildPhase::CMakeBuild;
+ }
+ return BuildPhase::CMakeConfigure;
+ }
+
+ if (tool == BuildTool::Make || tool == BuildTool::Ninja) {
+ return BuildPhase::MakefileBuild;
+ }
+
+ if (tool == BuildTool::Linker) {
+ return BuildPhase::Linking;
+ }
+
+ if (tool == BuildTool::Archiver) {
+ return BuildPhase::Archiving;
+ }
+
+ if (tool == BuildTool::Clang || tool == BuildTool::GCC) {
+ for (const auto &arg : args_) {
+ if (arg == "-E")
+ return BuildPhase::Preprocessing;
+ if (arg == "-S")
+ return BuildPhase::Assembly;
+ if (arg == "-c")
+ return BuildPhase::Compilation;
+ }
+
+ bool hasObjectFile = false;
+ for (const auto &Arg : args_) {
+ StringRef argRef(Arg);
+ if (argRef.ends_with(".o") || argRef.ends_with(".O") ||
+ argRef.ends_with(".obj") || argRef.ends_with(".OBJ")) {
+ hasObjectFile = true;
+ break;
+ }
+ }
+ if (hasObjectFile) {
+ return BuildPhase::Linking;
+ }
+
+ bool hasSourceFile = false;
+ for (const auto &Arg : args_) {
+ StringRef argRef(Arg);
+ if (argRef.ends_with(".c") || argRef.ends_with(".C") ||
+ argRef.ends_with(".cpp") || argRef.ends_with(".CPP") ||
+ argRef.ends_with(".cc") || argRef.ends_with(".CC") ||
+ argRef.ends_with(".cxx") || argRef.ends_with(".CXX")) {
+ hasSourceFile = true;
+ break;
+ }
+ }
+ if (hasSourceFile) {
+ return BuildPhase::Compilation; // Default for source files
+ }
+ }
+
+ return BuildPhase::Unknown;
+}
+
+void CommandAnalyzer::detectBuildFeatures(BuildContext &context) const {
+ for (const auto &arg : args_) {
+ if (arg == "-g" || StringRef(arg).starts_with("-g")) {
+ context.hasDebugInfo = true;
+ }
+
+ if (StringRef(arg).starts_with("-O") && arg.length() > 2) {
+ context.hasOptimization = true;
+ }
+
+ if (arg.find("openmp") != std::string::npos ||
+ arg.find("openacc") != std::string::npos ||
+ arg.find("cuda") != std::string::npos ||
+ arg.find("offload") != std::string::npos) {
+ context.hasOffloading = true;
+ }
+
+ if (StringRef(arg).starts_with("-march=")) {
+ context.metadata["target_arch"] = arg.substr(7);
+ }
+ if (StringRef(arg).starts_with("-mtune=")) {
+ context.metadata["tune"] = arg.substr(7);
+ }
+ if (StringRef(arg).starts_with("--offload-arch=")) {
+ context.metadata["offload_arch"] = arg.substr(15);
+ }
+ }
+}
+
+std::vector<std::string> CommandAnalyzer::extractInputFiles() const {
+ std::vector<std::string> inputs;
+ for (size_t i = 0; i < args_.size(); ++i) {
+ const auto &arg = args_[i];
+ if (StringRef(arg).starts_with("-")) {
+ if (arg == "-o" || arg == "-I" || arg == "-L" || arg == "-D") {
+ i++;
+ }
+ continue;
+ }
+ if (sys::fs::exists(arg)) {
+ inputs.push_back(arg);
+ }
+ }
+ return inputs;
+}
+
+std::vector<std::string> CommandAnalyzer::extractOutputFiles() const {
+ std::vector<std::string> outputs;
+ for (size_t i = 0; i < args_.size(); ++i) {
+ const auto &arg = args_[i];
+ if (arg == "-o" && i + 1 < args_.size()) {
+ outputs.push_back(args_[i + 1]);
+ i++;
+ }
+ }
+ return outputs;
+}
+
+} // namespace advisor
+} // namespace llvm
diff --git a/llvm/tools/llvm-advisor/src/Core/CommandAnalyzer.h b/llvm/tools/llvm-advisor/src/Core/CommandAnalyzer.h
new file mode 100644
index 0000000000000..c3efdff147e5f
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Core/CommandAnalyzer.h
@@ -0,0 +1,32 @@
+#ifndef LLVM_ADVISOR_COMMAND_ANALYZER_H
+#define LLVM_ADVISOR_COMMAND_ANALYZER_H
+
+#include "BuildContext.h"
+#include <string>
+#include <vector>
+
+namespace llvm {
+namespace advisor {
+
+class CommandAnalyzer {
+public:
+ CommandAnalyzer(const std::string &command,
+ const std::vector<std::string> &args);
+
+ BuildContext analyze() const;
+
+private:
+ BuildTool detectBuildTool() const;
+ BuildPhase detectBuildPhase(BuildTool tool) const;
+ void detectBuildFeatures(BuildContext &context) const;
+ std::vector<std::string> extractInputFiles() const;
+ std::vector<std::string> extractOutputFiles() const;
+
+ std::string command_;
+ std::vector<std::string> args_;
+};
+
+} // namespace advisor
+} // namespace llvm
+
+#endif
>From ebdb0b26b8ef67ce3e71c02a8e90232d9018a567 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miguel=20C=C3=A1rdenas?= <miguelecsx at gmail.com>
Date: Sun, 13 Jul 2025 06:24:53 +0200
Subject: [PATCH 5/5] [llvm-advisor] Add support for builds with extra compiler
data
This change adds logic to run compiler processes and automatically
add options to collect optimization remarks, profiling data, and
debug information when needed.
---
.../llvm-advisor/src/Core/BuildExecutor.cpp | 109 ++++++++++++++++++
.../llvm-advisor/src/Core/BuildExecutor.h | 34 ++++++
2 files changed, 143 insertions(+)
create mode 100644 llvm/tools/llvm-advisor/src/Core/BuildExecutor.cpp
create mode 100644 llvm/tools/llvm-advisor/src/Core/BuildExecutor.h
diff --git a/llvm/tools/llvm-advisor/src/Core/BuildExecutor.cpp b/llvm/tools/llvm-advisor/src/Core/BuildExecutor.cpp
new file mode 100644
index 0000000000000..a4af5a660c80e
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Core/BuildExecutor.cpp
@@ -0,0 +1,109 @@
+#include "BuildExecutor.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace advisor {
+
+BuildExecutor::BuildExecutor(const AdvisorConfig &config) : config_(config) {}
+
+Expected<int> BuildExecutor::execute(const std::string &compiler,
+ const std::vector<std::string> &args,
+ BuildContext &buildContext,
+ const std::string &tempDir) {
+ auto instrumentedArgs = instrumentCompilerArgs(args, buildContext, tempDir);
+
+ auto compilerPath = sys::findProgramByName(compiler);
+ if (!compilerPath) {
+ return createStringError(
+ std::make_error_code(std::errc::no_such_file_or_directory),
+ "Compiler not found: " + compiler);
+ }
+
+ std::vector<StringRef> execArgs;
+ execArgs.push_back(compiler);
+ for (const auto &arg : instrumentedArgs) {
+ execArgs.push_back(arg);
+ }
+
+ if (config_.getVerbose()) {
+ outs() << "Executing: " << compiler;
+ for (const auto &arg : instrumentedArgs) {
+ outs() << " " << arg;
+ }
+ outs() << "\n";
+ }
+
+ return sys::ExecuteAndWait(*compilerPath, execArgs);
+}
+
+std::vector<std::string>
+BuildExecutor::instrumentCompilerArgs(const std::vector<std::string> &args,
+ BuildContext &buildContext,
+ const std::string &tempDir) {
+
+ std::vector<std::string> result = args;
+ std::set<std::string> existingFlags;
+
+ // Scan existing flags to avoid duplication
+ for (const auto &arg : args) {
+ if (arg.find("-g") == 0)
+ existingFlags.insert("debug");
+ if (arg.find("-fsave-optimization-record") != std::string::npos)
+ existingFlags.insert("remarks");
+ if (arg.find("-fprofile-instr-generate") != std::string::npos)
+ existingFlags.insert("profile");
+ }
+
+ // Add debug info if not present
+ if (existingFlags.find("debug") == existingFlags.end()) {
+ result.push_back("-g");
+ }
+
+ // Add optimization remarks with proper redirection
+ if (existingFlags.find("remarks") == existingFlags.end()) {
+ result.push_back("-fsave-optimization-record");
+ result.push_back("-foptimization-record-file=" + tempDir +
+ "/remarks.opt.yaml");
+ buildContext.expectedGeneratedFiles.push_back(tempDir +
+ "/remarks.opt.yaml");
+ } else {
+ // If user already specified remarks, find and redirect the file
+ bool foundFileFlag = false;
+ for (auto &arg : result) {
+ if (arg.find("-foptimization-record-file=") != std::string::npos) {
+ // Extract filename and redirect to temp
+ StringRef existingPath = StringRef(arg).substr(26);
+ StringRef filename = sys::path::filename(existingPath);
+ arg = "-foptimization-record-file=" + tempDir + "/" + filename.str();
+ buildContext.expectedGeneratedFiles.push_back(tempDir + "/" +
+ filename.str());
+ foundFileFlag = true;
+ break;
+ }
+ }
+ // If no explicit file specified, add our own
+ if (!foundFileFlag) {
+ result.push_back("-foptimization-record-file=" + tempDir +
+ "/remarks.opt.yaml");
+ buildContext.expectedGeneratedFiles.push_back(tempDir +
+ "/remarks.opt.yaml");
+ }
+ }
+
+ // Add profiling if enabled and not present, redirect to temp directory
+ if (config_.getRunProfiler() &&
+ existingFlags.find("profile") == existingFlags.end()) {
+ result.push_back("-fprofile-instr-generate=" + tempDir +
+ "/profile.profraw");
+ result.push_back("-fcoverage-mapping");
+ buildContext.expectedGeneratedFiles.push_back(tempDir + "/profile.profraw");
+ }
+
+ return result;
+}
+
+} // namespace advisor
+} // namespace llvm
diff --git a/llvm/tools/llvm-advisor/src/Core/BuildExecutor.h b/llvm/tools/llvm-advisor/src/Core/BuildExecutor.h
new file mode 100644
index 0000000000000..a77ffd70c9b57
--- /dev/null
+++ b/llvm/tools/llvm-advisor/src/Core/BuildExecutor.h
@@ -0,0 +1,34 @@
+#ifndef LLVM_ADVISOR_BUILD_EXECUTOR_H
+#define LLVM_ADVISOR_BUILD_EXECUTOR_H
+
+#include "../Config/AdvisorConfig.h"
+#include "BuildContext.h"
+#include "llvm/Support/Error.h"
+#include <set>
+#include <string>
+#include <vector>
+
+namespace llvm {
+namespace advisor {
+
+class BuildExecutor {
+public:
+ BuildExecutor(const AdvisorConfig &config);
+
+ Expected<int> execute(const std::string &compiler,
+ const std::vector<std::string> &args,
+ BuildContext &buildContext, const std::string &tempDir);
+
+private:
+ std::vector<std::string>
+ instrumentCompilerArgs(const std::vector<std::string> &args,
+ BuildContext &buildContext,
+ const std::string &tempDir);
+
+ const AdvisorConfig &config_;
+};
+
+} // namespace advisor
+} // namespace llvm
+
+#endif
More information about the llvm-commits
mailing list