aboutsummaryrefslogtreecommitdiff
path: root/tools/driver/main.cc
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-14 09:25:42 +0000
committer_ov4 <ov4@ov4.org>2026-10-14 09:25:42 +0000
commit580ad606e29057a1faeaf0d3ec402f0a98edf998 (patch)
tree4bc3eaf6ff208771ef29589f15e13d61c3eba1ab /tools/driver/main.cc
parent83c5d8ecbf019a4f3cea6874566a5631764d3d9b (diff)
fix(driver)!: validate lli 23 before PATH execution
Check the selected lli only when PATH mode uses -r. Reject missing, mismatched or unreadable versions before compiling or writing IR, and limit version detection to five seconds. Keep unused tools unchecked. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'tools/driver/main.cc')
-rw-r--r--tools/driver/main.cc47
1 files changed, 46 insertions, 1 deletions
diff --git a/tools/driver/main.cc b/tools/driver/main.cc
index a4616bd..55d666f 100644
--- a/tools/driver/main.cc
+++ b/tools/driver/main.cc
@@ -7,6 +7,10 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
+#ifdef CPSC_RUN_PATH
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Regex.h"
+#endif
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
@@ -20,6 +24,46 @@ int compilationTerminated() {
return 1;
}
+#ifdef CPSC_RUN_PATH
+bool checkLliVersion(llvm::StringRef LliPath) {
+ llvm::SmallString<256> VersionPath;
+ if (auto EC = llvm::sys::fs::createTemporaryFile("cpsc-lli-version", "txt", VersionPath)) {
+ llvm::errs() << "cpsc: fatal error: cannot check lli version: " << EC.message() << "\n";
+ return false;
+ }
+ llvm::FileRemover TemporaryVersion(VersionPath);
+ std::string ExecutionError;
+ int Result = llvm::sys::ExecuteAndWait(LliPath, {LliPath, "--version"},
+ std::nullopt, {llvm::StringRef(""), llvm::StringRef(VersionPath), llvm::StringRef("")},
+ 5, 0, &ExecutionError);
+ if (Result != 0) {
+ llvm::errs() << "cpsc: fatal error: cannot check lli version at '" << LliPath
+ << "' (status " << Result << ")";
+ if (!ExecutionError.empty()) llvm::errs() << ": " << ExecutionError;
+ llvm::errs() << "\n";
+ return false;
+ }
+ auto Version = llvm::MemoryBuffer::getFile(VersionPath);
+ if (!Version) {
+ llvm::errs() << "cpsc: fatal error: cannot read lli version: "
+ << Version.getError().message() << "\n";
+ return false;
+ }
+ llvm::SmallVector<llvm::StringRef, 2> Matches;
+ if (!llvm::Regex("LLVM version ([0-9]+)\\.").match((*Version)->getBuffer(), &Matches)) {
+ llvm::errs() << "cpsc: fatal error: cannot identify LLVM version of lli at '"
+ << LliPath << "'; LLVM 23 is required\n";
+ return false;
+ }
+ if (Matches[1] != "23") {
+ llvm::errs() << "cpsc: fatal error: -r requires lli from LLVM 23; found LLVM "
+ << Matches[1] << " at '" << LliPath << "'\n";
+ return false;
+ }
+ return true;
+}
+#endif
+
} // namespace
int main(int argc, char **argv) {
@@ -73,10 +117,11 @@ int main(int argc, char **argv) {
#ifdef CPSC_RUN_PATH
auto Lli = llvm::sys::findProgramByName("lli");
if (!Lli) {
- llvm::errs() << "cpsc: fatal error: -r requires lli in PATH: " << Lli.getError().message() << "\n";
+ llvm::errs() << "cpsc: fatal error: -r requires lli from LLVM 23 in PATH: " << Lli.getError().message() << "\n";
return compilationTerminated();
}
LliPath = *Lli;
+ if (!checkLliVersion(LliPath)) return compilationTerminated();
#elif defined(CPSC_RUN_NONE)
llvm::errs() << "cpsc: fatal error: -r is disabled in this build (CPSC_RUN_MODE=NONE)\n";
return compilationTerminated();