diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-22 03:41:04 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-22 03:58:36 +0000 |
| commit | eba981b4f515010f8f6e9602c563d2074d8bd915 (patch) | |
| tree | 632e5b72446e5fdfa8b575e19fd6d01ea25598de | |
| parent | 6f11b59dff6ddc84c20fc1847a42344bfdddf066 (diff) | |
refactor(driver): move PATH-mode lli runner into PathRunner
PathRunner.cc holds the lli lookup, LLVM 23 version check and lli
execution, and is built only with CPSC_RUN_MODE=PATH like
EmbeddedRunner.cc is for EMBEDDED.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | AGENTS/ARCH/DRIVER.md | 5 | ||||
| -rw-r--r-- | AGENTS/ARCH/LAYOUT.md | 1 | ||||
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | tools/driver/PathRunner.cc | 83 | ||||
| -rw-r--r-- | tools/driver/PathRunner.h | 13 | ||||
| -rw-r--r-- | tools/driver/main.cc | 84 |
6 files changed, 105 insertions, 83 deletions
diff --git a/AGENTS/ARCH/DRIVER.md b/AGENTS/ARCH/DRIVER.md index 1b37d01..ef739b2 100644 --- a/AGENTS/ARCH/DRIVER.md +++ b/AGENTS/ARCH/DRIVER.md @@ -47,8 +47,9 @@ style is in [CONVENTIONS/SYMBOLS_AND_ERRORS.md](../CONVENTIONS/SYMBOLS_AND_ERROR than grepping stderr. - Successful compilation overwrites the output, but paths aliasing any input source (including symlinks/hard links) are rejected. -- In PATH mode, `-r` executes PATH's `lli` using LLVM Support process APIs, with - inherited stdin/stdout/stderr and no shell. Missing lli is rejected before +- In PATH mode (`tools/driver/PathRunner.cc`, built only in that mode), `-r` + executes PATH's `lli` using LLVM Support process APIs, with inherited + stdin/stdout/stderr and no shell. Missing lli is rejected before compiling or writing output. The selected `lli --version` must identify LLVM 23 and succeed within five seconds; other or unrecognized versions fail before source compilation. Without `-r`, no external tools are checked; clang/clang++ diff --git a/AGENTS/ARCH/LAYOUT.md b/AGENTS/ARCH/LAYOUT.md index 4abe414..6c70d3b 100644 --- a/AGENTS/ARCH/LAYOUT.md +++ b/AGENTS/ARCH/LAYOUT.md @@ -28,6 +28,7 @@ | `CMakeLists.txt` | 3 static libs (CPSLexer, CPSParser, CPSCodeGen) + `cpsc`. **New .cc files must be added to the source lists here** | | `tools/driver/NativeCompiler.cc`, `cmake/NativeCompiler.cmake` | Host object generation, embedded Clang/LLD linking and compressed link resources | | `tools/driver/EmbeddedRunner.cc`, `tools/driver/MinGWJIT.cc`, `cmake/EmbeddedLLVM.cmake` | EMBEDDED-only LLJIT/JITLink runner and MinGW COFF/SEH support; static support-library selection for all modes | +| `tools/driver/PathRunner.cc` | PATH-only `-r` runner: lli lookup, LLVM 23 version check and lli execution | | `cmake/LocalDependencies.cmake`, `cmake/*Packages.cmake` | Local package extraction and platform relocation | | `cmake/DependencyPaths.cmake`, `cmake/FindDependency.cmake` | Shared local paths and local-first/system-fallback lookup | | `cmake/BuildTools.cmake`, `cmake/LLVMDependencies.cmake` | Compiler/build tool selection and LLVM dependency discovery | diff --git a/CMakeLists.txt b/CMakeLists.txt index 3dea04e..32e6c1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,6 +101,8 @@ if(CPSC_RUN_MODE STREQUAL "EMBEDDED") target_sources(cpsc PRIVATE tools/driver/EmbeddedRunner.cc tools/driver/MinGWJIT.cc) +elseif(CPSC_RUN_MODE STREQUAL "PATH") + target_sources(cpsc PRIVATE tools/driver/PathRunner.cc) endif() if(MINGW) target_link_options(cpsc PRIVATE -static) diff --git a/tools/driver/PathRunner.cc b/tools/driver/PathRunner.cc new file mode 100644 index 0000000..01d8478 --- /dev/null +++ b/tools/driver/PathRunner.cc @@ -0,0 +1,83 @@ +#include "PathRunner.h" +#include "cps/Diagnostics.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Regex.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + +bool checkLliVersion(llvm::StringRef LliPath) { + llvm::SmallString<256> VersionPath; + if (auto EC = llvm::sys::fs::createTemporaryFile("cpsc-lli-version", "txt", VersionPath)) { + llvm::errs() << cps::diagnosticPrefix(cps::Severity::Fatal) << "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() << cps::diagnosticPrefix(cps::Severity::Fatal) << "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() << cps::diagnosticPrefix(cps::Severity::Fatal) << "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() << cps::diagnosticPrefix(cps::Severity::Fatal) << "cannot identify LLVM version of lli at '" + << LliPath << "'; LLVM 23 is required\n"; + return false; + } + if (Matches[1] != "23") { + llvm::errs() << cps::diagnosticPrefix(cps::Severity::Fatal) << "-r requires lli from LLVM 23; found LLVM " + << Matches[1] << " at '" << LliPath << "'\n"; + return false; + } + return true; +} + +} // namespace + +bool findLli(std::string &LliPath) { + auto Lli = llvm::sys::findProgramByName("lli"); + if (!Lli) { + llvm::errs() << cps::diagnosticPrefix(cps::Severity::Fatal) << "-r requires lli from LLVM 23 in PATH: " << Lli.getError().message() << "\n"; + return false; + } + LliPath = *Lli; + return checkLliVersion(LliPath); +} + +int runLli(const std::string &LliPath, const std::string &IRPath, + const std::vector<std::string> &Objects) { + llvm::SmallString<256> RunPath(IRPath); + if (auto PathError = llvm::sys::fs::make_absolute(RunPath)) { + llvm::errs() << cps::diagnosticPrefix(cps::Severity::Error) << "cannot resolve IR path: " << PathError.message() << "\n"; + return 1; + } + std::string ExecutionError; + std::vector<std::string> LliArgs = {LliPath}; + for (const auto &Object : Objects) LliArgs.push_back("-extra-object=" + Object); + LliArgs.push_back(std::string(RunPath)); + std::vector<llvm::StringRef> LliArgv(LliArgs.begin(), LliArgs.end()); + int Result = llvm::sys::ExecuteAndWait(LliPath, LliArgv, + std::nullopt, {}, 0, 0, &ExecutionError); + if (Result < 0) { + llvm::errs() << cps::diagnosticPrefix(cps::Severity::Error) << "lli execution failed (status " << Result << "): " + << ExecutionError << "\n"; + return 1; + } + return Result; +} diff --git a/tools/driver/PathRunner.h b/tools/driver/PathRunner.h new file mode 100644 index 0000000..2043d4f --- /dev/null +++ b/tools/driver/PathRunner.h @@ -0,0 +1,13 @@ +#pragma once + +#include <string> +#include <vector> + +// Finds PATH's lli for -r and checks that it is from LLVM 23. Reports a fatal +// error and returns false otherwise. +bool findLli(std::string &LliPath); + +// Executes the IR at IRPath with lli and returns the program's status. +// Objects named by INCLUDE_OBJ are passed to lli as extra objects. +int runLli(const std::string &LliPath, const std::string &IRPath, + const std::vector<std::string> &Objects); diff --git a/tools/driver/main.cc b/tools/driver/main.cc index 6893a63..d1dda81 100644 --- a/tools/driver/main.cc +++ b/tools/driver/main.cc @@ -7,16 +7,14 @@ #ifdef CPSC_RUN_EMBEDDED #include "EmbeddedRunner.h" #endif +#ifdef CPSC_RUN_PATH +#include "PathRunner.h" +#endif #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSet.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" #include <fstream> #include <string> @@ -74,82 +72,6 @@ llvm::SmallString<256> relativeToUnit(llvm::StringRef UnitPath, llvm::StringRef return Result; } -#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() << cps::diagnosticPrefix(cps::Severity::Fatal) << "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() << cps::diagnosticPrefix(cps::Severity::Fatal) << "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() << cps::diagnosticPrefix(cps::Severity::Fatal) << "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() << cps::diagnosticPrefix(cps::Severity::Fatal) << "cannot identify LLVM version of lli at '" - << LliPath << "'; LLVM 23 is required\n"; - return false; - } - if (Matches[1] != "23") { - llvm::errs() << cps::diagnosticPrefix(cps::Severity::Fatal) << "-r requires lli from LLVM 23; found LLVM " - << Matches[1] << " at '" << LliPath << "'\n"; - return false; - } - return true; -} -#endif - -#ifdef CPSC_RUN_PATH -// Finds PATH's lli for -r and checks that it is from LLVM 23. -bool findLli(std::string &LliPath) { - auto Lli = llvm::sys::findProgramByName("lli"); - if (!Lli) { - llvm::errs() << cps::diagnosticPrefix(cps::Severity::Fatal) << "-r requires lli from LLVM 23 in PATH: " << Lli.getError().message() << "\n"; - return false; - } - LliPath = *Lli; - return checkLliVersion(LliPath); -} - -// Executes the IR at IRPath with lli and returns the program's status. -int runLli(const std::string &LliPath, const std::string &IRPath, - const std::vector<std::string> &Objects) { - llvm::SmallString<256> RunPath(IRPath); - if (auto PathError = llvm::sys::fs::make_absolute(RunPath)) { - llvm::errs() << cps::diagnosticPrefix(cps::Severity::Error) << "cannot resolve IR path: " << PathError.message() << "\n"; - return 1; - } - std::string ExecutionError; - std::vector<std::string> LliArgs = {LliPath}; - for (const auto &Object : Objects) LliArgs.push_back("-extra-object=" + Object); - LliArgs.push_back(std::string(RunPath)); - std::vector<llvm::StringRef> LliArgv(LliArgs.begin(), LliArgs.end()); - int Result = llvm::sys::ExecuteAndWait(LliPath, LliArgv, - std::nullopt, {}, 0, 0, &ExecutionError); - if (Result < 0) { - llvm::errs() << cps::diagnosticPrefix(cps::Severity::Error) << "lli execution failed (status " << Result << "): " - << ExecutionError << "\n"; - return 1; - } - return Result; -} -#endif - // -h anywhere prints a documentation pointer instead of compiling. bool printHelp(int argc, char **argv) { for (int I = 1; I < argc; ++I) { |
