From e28cbb2efac9ed6e56cd9ab6eb1a3f16810d575a Mon Sep 17 00:00:00 2001 From: _ov4 Date: Tue, 13 Oct 2026 03:54:49 +0000 Subject: feat: embed a statically linked LLVM execution engine Add EMBEDDED mode to run generated modules in-process without lli or PATH lookup. Link LLVM and support archives plus the C++ runtime statically, while retaining the system C runtime on Linux. Co-Authored-By: Claude Fable 5.1 --- tools/driver/EmbeddedRunner.cc | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tools/driver/EmbeddedRunner.cc (limited to 'tools/driver/EmbeddedRunner.cc') diff --git a/tools/driver/EmbeddedRunner.cc b/tools/driver/EmbeddedRunner.cc new file mode 100644 index 0000000..81a2265 --- /dev/null +++ b/tools/driver/EmbeddedRunner.cc @@ -0,0 +1,45 @@ +#include "EmbeddedRunner.h" +#include "cps/CodeGen.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/TargetParser/Host.h" +#include "llvm/Transforms/Utils/Cloning.h" + +int runEmbedded(const cps::CodeGen &CG) { + if (llvm::InitializeNativeTarget() || llvm::InitializeNativeTargetAsmPrinter()) { + llvm::errs() << "Error: cannot initialize the embedded LLVM target\n"; + return 1; + } + std::string Error; + if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr, &Error)) { + llvm::errs() << "Error: cannot load process symbols: " << Error << "\n"; + return 1; + } + // Keep CodeGen's module and context alive while the engine owns its clone. + auto Module = llvm::CloneModule(CG.getModule()); + Module->setTargetTriple(llvm::sys::getProcessTriple()); + llvm::EngineBuilder Builder(std::move(Module)); + Builder.setEngineKind(llvm::EngineKind::JIT); + Builder.setErrorStr(&Error); + Builder.setMCJITMemoryManager(std::make_unique()); + std::unique_ptr Engine(Builder.create()); + if (!Engine) { + llvm::errs() << "Error: cannot create the embedded LLVM engine: " << Error << "\n"; + return 1; + } + Engine->finalizeObject(); + if (Engine->hasError()) { + llvm::errs() << "Error: embedded LLVM execution failed: " << Engine->getErrorMessage() << "\n"; + return 1; + } + auto MainAddress = Engine->getFunctionAddress("main"); + if (!MainAddress) { + llvm::errs() << "Error: embedded LLVM could not resolve main\n"; + return 1; + } + auto Main = reinterpret_cast(MainAddress); + return Main(); +} -- cgit v1.3.1-4-g156e