Skip to content

Commit ebdb0b2

Browse files
committed
[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.
1 parent 336db51 commit ebdb0b2

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#include "BuildExecutor.h"
2+
#include "llvm/Support/FileSystem.h"
3+
#include "llvm/Support/Path.h"
4+
#include "llvm/Support/Program.h"
5+
#include "llvm/Support/raw_ostream.h"
6+
7+
namespace llvm {
8+
namespace advisor {
9+
10+
BuildExecutor::BuildExecutor(const AdvisorConfig &config) : config_(config) {}
11+
12+
Expected<int> BuildExecutor::execute(const std::string &compiler,
13+
const std::vector<std::string> &args,
14+
BuildContext &buildContext,
15+
const std::string &tempDir) {
16+
auto instrumentedArgs = instrumentCompilerArgs(args, buildContext, tempDir);
17+
18+
auto compilerPath = sys::findProgramByName(compiler);
19+
if (!compilerPath) {
20+
return createStringError(
21+
std::make_error_code(std::errc::no_such_file_or_directory),
22+
"Compiler not found: " + compiler);
23+
}
24+
25+
std::vector<StringRef> execArgs;
26+
execArgs.push_back(compiler);
27+
for (const auto &arg : instrumentedArgs) {
28+
execArgs.push_back(arg);
29+
}
30+
31+
if (config_.getVerbose()) {
32+
outs() << "Executing: " << compiler;
33+
for (const auto &arg : instrumentedArgs) {
34+
outs() << " " << arg;
35+
}
36+
outs() << "\n";
37+
}
38+
39+
return sys::ExecuteAndWait(*compilerPath, execArgs);
40+
}
41+
42+
std::vector<std::string>
43+
BuildExecutor::instrumentCompilerArgs(const std::vector<std::string> &args,
44+
BuildContext &buildContext,
45+
const std::string &tempDir) {
46+
47+
std::vector<std::string> result = args;
48+
std::set<std::string> existingFlags;
49+
50+
// Scan existing flags to avoid duplication
51+
for (const auto &arg : args) {
52+
if (arg.find("-g") == 0)
53+
existingFlags.insert("debug");
54+
if (arg.find("-fsave-optimization-record") != std::string::npos)
55+
existingFlags.insert("remarks");
56+
if (arg.find("-fprofile-instr-generate") != std::string::npos)
57+
existingFlags.insert("profile");
58+
}
59+
60+
// Add debug info if not present
61+
if (existingFlags.find("debug") == existingFlags.end()) {
62+
result.push_back("-g");
63+
}
64+
65+
// Add optimization remarks with proper redirection
66+
if (existingFlags.find("remarks") == existingFlags.end()) {
67+
result.push_back("-fsave-optimization-record");
68+
result.push_back("-foptimization-record-file=" + tempDir +
69+
"/remarks.opt.yaml");
70+
buildContext.expectedGeneratedFiles.push_back(tempDir +
71+
"/remarks.opt.yaml");
72+
} else {
73+
// If user already specified remarks, find and redirect the file
74+
bool foundFileFlag = false;
75+
for (auto &arg : result) {
76+
if (arg.find("-foptimization-record-file=") != std::string::npos) {
77+
// Extract filename and redirect to temp
78+
StringRef existingPath = StringRef(arg).substr(26);
79+
StringRef filename = sys::path::filename(existingPath);
80+
arg = "-foptimization-record-file=" + tempDir + "/" + filename.str();
81+
buildContext.expectedGeneratedFiles.push_back(tempDir + "/" +
82+
filename.str());
83+
foundFileFlag = true;
84+
break;
85+
}
86+
}
87+
// If no explicit file specified, add our own
88+
if (!foundFileFlag) {
89+
result.push_back("-foptimization-record-file=" + tempDir +
90+
"/remarks.opt.yaml");
91+
buildContext.expectedGeneratedFiles.push_back(tempDir +
92+
"/remarks.opt.yaml");
93+
}
94+
}
95+
96+
// Add profiling if enabled and not present, redirect to temp directory
97+
if (config_.getRunProfiler() &&
98+
existingFlags.find("profile") == existingFlags.end()) {
99+
result.push_back("-fprofile-instr-generate=" + tempDir +
100+
"/profile.profraw");
101+
result.push_back("-fcoverage-mapping");
102+
buildContext.expectedGeneratedFiles.push_back(tempDir + "/profile.profraw");
103+
}
104+
105+
return result;
106+
}
107+
108+
} // namespace advisor
109+
} // namespace llvm
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#ifndef LLVM_ADVISOR_BUILD_EXECUTOR_H
2+
#define LLVM_ADVISOR_BUILD_EXECUTOR_H
3+
4+
#include "../Config/AdvisorConfig.h"
5+
#include "BuildContext.h"
6+
#include "llvm/Support/Error.h"
7+
#include <set>
8+
#include <string>
9+
#include <vector>
10+
11+
namespace llvm {
12+
namespace advisor {
13+
14+
class BuildExecutor {
15+
public:
16+
BuildExecutor(const AdvisorConfig &config);
17+
18+
Expected<int> execute(const std::string &compiler,
19+
const std::vector<std::string> &args,
20+
BuildContext &buildContext, const std::string &tempDir);
21+
22+
private:
23+
std::vector<std::string>
24+
instrumentCompilerArgs(const std::vector<std::string> &args,
25+
BuildContext &buildContext,
26+
const std::string &tempDir);
27+
28+
const AdvisorConfig &config_;
29+
};
30+
31+
} // namespace advisor
32+
} // namespace llvm
33+
34+
#endif

0 commit comments

Comments
 (0)