Skip to content

Commit a15a978

Browse files
committed
[llvm-advisor] Add support for detecting compilation units
Adds logic to scan the origin compiler arguments, find source files, figure out compile flags and output paths, and create a description of each compilation unit. This is the entry point for the analysis pipeline.
1 parent a4ab9b9 commit a15a978

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#include "UnitDetector.h"
2+
#include "llvm/ADT/Hashing.h"
3+
#include "llvm/Support/Path.h"
4+
5+
namespace llvm {
6+
namespace advisor {
7+
8+
UnitDetector::UnitDetector(const AdvisorConfig &config) : config_(config) {}
9+
10+
Expected<std::vector<CompilationUnitInfo>>
11+
UnitDetector::detectUnits(const std::string &compiler,
12+
const std::vector<std::string> &args) {
13+
14+
auto sources = findSourceFiles(args);
15+
if (sources.empty()) {
16+
return createStringError(std::make_error_code(std::errc::invalid_argument),
17+
"No source files found");
18+
}
19+
20+
CompilationUnitInfo unit;
21+
unit.name = generateUnitName(sources);
22+
unit.sources = sources;
23+
24+
// Store original args but filter out source files for the compile flags
25+
for (const auto &arg : args) {
26+
// Skip source files when adding to compile flags
27+
StringRef extension = sys::path::extension(arg);
28+
if (!arg.empty() && arg[0] != '-' &&
29+
(extension == ".c" || extension == ".cpp" || extension == ".cc" ||
30+
extension == ".cxx" || extension == ".C")) {
31+
continue;
32+
}
33+
unit.compileFlags.push_back(arg);
34+
}
35+
36+
// Extract output files and features
37+
extractBuildInfo(args, unit);
38+
39+
return std::vector<CompilationUnitInfo>{unit};
40+
}
41+
42+
std::vector<SourceFile>
43+
UnitDetector::findSourceFiles(const std::vector<std::string> &args) const {
44+
std::vector<SourceFile> sources;
45+
46+
for (const auto &arg : args) {
47+
if (arg.empty() || arg[0] == '-')
48+
continue;
49+
50+
StringRef extension = sys::path::extension(arg);
51+
if (extension == ".c" || extension == ".cpp" || extension == ".cc" ||
52+
extension == ".cxx" || extension == ".C") {
53+
54+
SourceFile source;
55+
source.path = arg;
56+
source.language = classifier_.getLanguage(arg);
57+
source.isHeader = false;
58+
sources.push_back(source);
59+
}
60+
}
61+
62+
return sources;
63+
}
64+
65+
void UnitDetector::extractBuildInfo(const std::vector<std::string> &args,
66+
CompilationUnitInfo &unit) {
67+
for (size_t i = 0; i < args.size(); ++i) {
68+
const auto &arg = args[i];
69+
70+
if (arg == "-o" && i + 1 < args.size()) {
71+
StringRef output = args[i + 1];
72+
StringRef ext = sys::path::extension(output);
73+
if (ext == ".o") {
74+
unit.outputObject = args[i + 1];
75+
} else {
76+
unit.outputExecutable = args[i + 1];
77+
}
78+
}
79+
80+
if (arg.find("openmp") != std::string::npos ||
81+
arg.find("offload") != std::string::npos ||
82+
arg.find("cuda") != std::string::npos) {
83+
unit.hasOffloading = true;
84+
}
85+
86+
if (StringRef(arg).starts_with("-march=")) {
87+
unit.targetArch = arg.substr(7);
88+
}
89+
}
90+
}
91+
92+
std::string
93+
UnitDetector::generateUnitName(const std::vector<SourceFile> &sources) const {
94+
if (sources.empty())
95+
return "unknown";
96+
97+
// Use first source file name as base
98+
std::string baseName = sys::path::stem(sources[0].path).str();
99+
100+
// Add hash for uniqueness when multiple sources
101+
if (sources.size() > 1) {
102+
std::string combined;
103+
for (const auto &source : sources) {
104+
combined += source.path;
105+
}
106+
auto hash = hash_value(combined);
107+
baseName += "_" + std::to_string(static_cast<size_t>(hash) % 10000);
108+
}
109+
110+
return baseName;
111+
}
112+
113+
} // namespace advisor
114+
} // namespace llvm
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#ifndef LLVM_ADVISOR_UNIT_DETECTOR_H
2+
#define LLVM_ADVISOR_UNIT_DETECTOR_H
3+
4+
#include "../Config/AdvisorConfig.h"
5+
#include "../Core/CompilationUnit.h"
6+
#include "../Utils/FileClassifier.h"
7+
#include "llvm/Support/Error.h"
8+
#include <vector>
9+
10+
namespace llvm {
11+
namespace advisor {
12+
13+
class UnitDetector {
14+
public:
15+
explicit UnitDetector(const AdvisorConfig &config);
16+
17+
Expected<std::vector<CompilationUnitInfo>>
18+
detectUnits(const std::string &compiler,
19+
const std::vector<std::string> &args);
20+
21+
private:
22+
std::vector<SourceFile>
23+
findSourceFiles(const std::vector<std::string> &args) const;
24+
void extractBuildInfo(const std::vector<std::string> &args,
25+
CompilationUnitInfo &unit);
26+
std::string generateUnitName(const std::vector<SourceFile> &sources) const;
27+
28+
const AdvisorConfig &config_;
29+
FileClassifier classifier_;
30+
};
31+
32+
} // namespace advisor
33+
} // namespace llvm
34+
35+
#endif

0 commit comments

Comments
 (0)