https://github.com/kr-2003 updated https://github.com/llvm/llvm-project/pull/159693
>From 733ffcdabee19cae2557f7dad8754c55ddf29314 Mon Sep 17 00:00:00 2001 From: kr-2003 <kumar.kr.abhi...@gmail.com> Date: Fri, 19 Sep 2025 07:21:22 +0530 Subject: [PATCH 1/3] LLJITBuilder in JITConfig --- clang/include/clang/Interpreter/Interpreter.h | 29 +++-- clang/lib/Interpreter/Interpreter.cpp | 115 ++++++++++-------- 2 files changed, 82 insertions(+), 62 deletions(-) diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 078d70b3b1749..7d734897e5584 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -1,4 +1,5 @@ -//===--- Interpreter.h - Incremental Compilation and Execution---*- C++ -*-===// +//===------ Interpreter.h - Incremental Compilation and Execution---*- C++ +//-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -19,12 +20,14 @@ #include "clang/Interpreter/Value.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FunctionExtras.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" #include "llvm/Support/Error.h" #include <cstdint> #include <memory> +#include <optional> #include <vector> namespace llvm { @@ -32,6 +35,7 @@ namespace orc { class LLJIT; class LLJITBuilder; class ThreadSafeContext; +class JITTargetMachineBuilder; } // namespace orc } // namespace llvm @@ -132,18 +136,25 @@ class Interpreter { /// Representing the slab allocation size for memory management in kb. unsigned SlabAllocateSize = 0; /// Path to the ORC runtime library. - std::string OrcRuntimePath = ""; + std::optional<std::string> OrcRuntimePath; /// PID of the out-of-process JIT executor. uint32_t ExecutorPID = 0; - /// Custom lambda to be executed inside child process/executor - std::function<void()> CustomizeFork = nullptr; - /// An optional code model to provide to the JITTargetMachineBuilder - std::optional<llvm::CodeModel::Model> CM = std::nullopt; + + /// Factory function for creating LLJITBuilder instances. + /// This allows clients to customize JIT builder creation while still + /// providing sensible defaults. + llvm::unique_function<llvm::Expected< + std::unique_ptr<llvm::orc::LLJITBuilder>>(const JITConfig &)> + MakeJITBuilder = makeDefaultJITBuilder; JITConfig() : IsOutOfProcess(false), OOPExecutor(""), OOPExecutorConnect(""), - UseSharedMemory(false), SlabAllocateSize(0), OrcRuntimePath(""), - ExecutorPID(0), CustomizeFork(nullptr), CM(std::nullopt) {} + UseSharedMemory(false), SlabAllocateSize(0), OrcRuntimePath(), + ExecutorPID(0) {} + + /// Default JIT builder factory function + static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> + makeDefaultJITBuilder(const JITConfig &Config); }; protected: @@ -237,4 +248,4 @@ class Interpreter { }; } // namespace clang -#endif // LLVM_CLANG_INTERPRETER_INTERPRETER_H +#endif // LLVM_CLANG_INTERPRETER_INTERPRETER_H \ No newline at end of file diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 9cc1c450b7650..a613fbf1b8370 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -350,15 +350,26 @@ const char *const Runtimes = R"( EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...); )"; +static llvm::Expected<llvm::orc::JITTargetMachineBuilder> +createJITTargetMachineBuilder(const std::string &TT) { + if (TT == llvm::sys::getProcessTriple()) + // This fails immediately if the target backend is not registered + return llvm::orc::JITTargetMachineBuilder::detectHost(); + + // If the target backend is not registered, LLJITBuilder::create() will fail + return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT)); +} + +// 5. Update outOfProcessJITBuilder to work with the new system llvm::Expected<std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, uint32_t>> Interpreter::outOfProcessJITBuilder(JITConfig Config) { std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC; uint32_t childPid = -1; + if (!Config.OOPExecutor.empty()) { // Launch an out-of-process executor locally in a child process. auto ResultOrErr = IncrementalExecutor::launchExecutor( - Config.OOPExecutor, Config.UseSharedMemory, Config.SlabAllocateSize, - Config.CustomizeFork); + Config.OOPExecutor, Config.UseSharedMemory, Config.SlabAllocateSize); if (!ResultOrErr) return ResultOrErr.takeError(); childPid = ResultOrErr->second; @@ -381,8 +392,10 @@ Interpreter::outOfProcessJITBuilder(JITConfig Config) { std::unique_ptr<llvm::orc::LLJITBuilder> JB; if (EPC) { - auto JBOrErr = clang::Interpreter::createLLJITBuilder( - std::move(EPC), Config.OrcRuntimePath); + std::string RuntimePath = + Config.OrcRuntimePath ? *Config.OrcRuntimePath : ""; + auto JBOrErr = + clang::Interpreter::createLLJITBuilder(std::move(EPC), RuntimePath); if (!JBOrErr) return JBOrErr.takeError(); JB = std::move(*JBOrErr); @@ -422,9 +435,9 @@ llvm::Expected<std::unique_ptr<Interpreter>> Interpreter::create(std::unique_ptr<CompilerInstance> CI, JITConfig Config) { llvm::Error Err = llvm::Error::success(); - std::unique_ptr<llvm::orc::LLJITBuilder> JB; - - if (Config.IsOutOfProcess) { + // Auto-discover ORC runtime path if not provided and out-of-process is + // enabled + if (Config.IsOutOfProcess && !Config.OrcRuntimePath) { const TargetInfo &TI = CI->getTarget(); const llvm::Triple &Triple = TI.getTriple(); @@ -440,16 +453,22 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI, JITConfig Config) { "Failed to create driver compilation for out-of-process JIT", std::error_code()); } - if (Config.OrcRuntimePath == "") { - const clang::driver::ToolChain &TC = C->getDefaultToolChain(); + const clang::driver::ToolChain &TC = C->getDefaultToolChain(); + auto OrcRuntimePathOrErr = getOrcRuntimePath(TC); + if (!OrcRuntimePathOrErr) { + return OrcRuntimePathOrErr.takeError(); + } - auto OrcRuntimePathOrErr = getOrcRuntimePath(TC); - if (!OrcRuntimePathOrErr) { - return OrcRuntimePathOrErr.takeError(); - } + Config.OrcRuntimePath = *OrcRuntimePathOrErr; + } - Config.OrcRuntimePath = *OrcRuntimePathOrErr; - } + std::unique_ptr<llvm::orc::LLJITBuilder> JB; + if (Config.IsOutOfProcess || + /* other conditions where we need custom builder */) { + auto JBOrErr = Config.MakeJITBuilder(Config); + if (!JBOrErr) + return JBOrErr.takeError(); + JB = std::move(*JBOrErr); } auto Interp = std::unique_ptr<Interpreter>(new Interpreter( @@ -590,16 +609,6 @@ Interpreter::Parse(llvm::StringRef Code) { return LastPTU; } -static llvm::Expected<llvm::orc::JITTargetMachineBuilder> -createJITTargetMachineBuilder(const std::string &TT) { - if (TT == llvm::sys::getProcessTriple()) - // This fails immediately if the target backend is not registered - return llvm::orc::JITTargetMachineBuilder::detectHost(); - - // If the target backend is not registered, LLJITBuilder::create() will fail - return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT)); -} - llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> Interpreter::createLLJITBuilder( std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC, @@ -629,39 +638,16 @@ llvm::Error Interpreter::CreateExecutor(JITConfig Config) { "No code generator available", std::error_code()); - const std::string &TT = getCompilerInstance()->getTargetOpts().Triple; - llvm::Triple TargetTriple(TT); - bool IsWindowsTarget = TargetTriple.isOSWindows(); - - if (!IsWindowsTarget && Config.IsOutOfProcess) { - if (!JITBuilder) { - auto ResOrErr = outOfProcessJITBuilder(Config); - if (!ResOrErr) - return ResOrErr.takeError(); - JITBuilder = std::move(ResOrErr->first); - Config.ExecutorPID = ResOrErr->second; - } - if (!JITBuilder) - return llvm::make_error<llvm::StringError>( - "Operation failed. No LLJITBuilder for out-of-process JIT", - std::error_code()); - } - if (!JITBuilder) { - auto JTMB = createJITTargetMachineBuilder(TT); - if (!JTMB) - return JTMB.takeError(); - if (Config.CM) - JTMB->setCodeModel(Config.CM); - auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB)); - if (!JB) - return JB.takeError(); - JITBuilder = std::move(*JB); + // Use the factory function to create the builder + auto JBOrErr = Config.MakeJITBuilder(Config); + if (!JBOrErr) + return JBOrErr.takeError(); + JITBuilder = std::move(*JBOrErr); } llvm::Error Err = llvm::Error::success(); - // Fix: Declare Executor as the appropriate unique_ptr type std::unique_ptr<IncrementalExecutor> Executor; #ifdef __EMSCRIPTEN__ @@ -803,4 +789,27 @@ llvm::Error Interpreter::LoadDynamicLibrary(const char *name) { return llvm::Error::success(); } + +llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> +Interpreter::JITConfig::makeDefaultJITBuilder(const JITConfig &Config) { + // Handle out-of-process JIT case + if (Config.IsOutOfProcess) { + if (!Config.OOPExecutor.empty() || !Config.OOPExecutorConnect.empty()) { + auto ResOrErr = Interpreter::outOfProcessJITBuilder(Config); + if (!ResOrErr) + return ResOrErr.takeError(); + return std::move(ResOrErr->first); + } + } + + // Handle in-process JIT case + // This would typically extract the target triple from somewhere accessible + // For now, we'll assume it's passed via some mechanism or use process triple + std::string TT = llvm::sys::getProcessTriple(); // This might need adjustment + auto JTMB = createJITTargetMachineBuilder(TT); + if (!JTMB) + return JTMB.takeError(); + + return IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB)); +} } // end namespace clang >From 53b25f4839b5e354d3e1174bd29aec26dd36bcb3 Mon Sep 17 00:00:00 2001 From: kr-2003 <kumar.kr.abhi...@gmail.com> Date: Fri, 19 Sep 2025 08:01:35 +0530 Subject: [PATCH 2/3] Refactoring code --- clang/include/clang/Interpreter/Interpreter.h | 4 ++-- clang/lib/Interpreter/Interpreter.cpp | 13 ++----------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 7d734897e5584..ef56f319e00ef 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -1,5 +1,5 @@ -//===------ Interpreter.h - Incremental Compilation and Execution---*- C++ -//-*-===// +//===--- Interpreter.h - Incremental Compilation and Execution---*- C++ -*-===// + // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index a613fbf1b8370..c33a037408d61 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -353,14 +353,11 @@ const char *const Runtimes = R"( static llvm::Expected<llvm::orc::JITTargetMachineBuilder> createJITTargetMachineBuilder(const std::string &TT) { if (TT == llvm::sys::getProcessTriple()) - // This fails immediately if the target backend is not registered return llvm::orc::JITTargetMachineBuilder::detectHost(); - // If the target backend is not registered, LLJITBuilder::create() will fail return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT)); } -// 5. Update outOfProcessJITBuilder to work with the new system llvm::Expected<std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, uint32_t>> Interpreter::outOfProcessJITBuilder(JITConfig Config) { std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC; @@ -435,8 +432,6 @@ llvm::Expected<std::unique_ptr<Interpreter>> Interpreter::create(std::unique_ptr<CompilerInstance> CI, JITConfig Config) { llvm::Error Err = llvm::Error::success(); - // Auto-discover ORC runtime path if not provided and out-of-process is - // enabled if (Config.IsOutOfProcess && !Config.OrcRuntimePath) { const TargetInfo &TI = CI->getTarget(); const llvm::Triple &Triple = TI.getTriple(); @@ -463,8 +458,7 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI, JITConfig Config) { } std::unique_ptr<llvm::orc::LLJITBuilder> JB; - if (Config.IsOutOfProcess || - /* other conditions where we need custom builder */) { + if (Config.IsOutOfProcess) { auto JBOrErr = Config.MakeJITBuilder(Config); if (!JBOrErr) return JBOrErr.takeError(); @@ -802,10 +796,7 @@ Interpreter::JITConfig::makeDefaultJITBuilder(const JITConfig &Config) { } } - // Handle in-process JIT case - // This would typically extract the target triple from somewhere accessible - // For now, we'll assume it's passed via some mechanism or use process triple - std::string TT = llvm::sys::getProcessTriple(); // This might need adjustment + std::string TT = llvm::sys::getProcessTriple(); auto JTMB = createJITTargetMachineBuilder(TT); if (!JTMB) return JTMB.takeError(); >From 88fd4cfda4d187b049282ff5068d96f7fffd1cbe Mon Sep 17 00:00:00 2001 From: kr-2003 <kumar.kr.abhi...@gmail.com> Date: Fri, 19 Sep 2025 19:11:14 +0530 Subject: [PATCH 3/3] Resolving unique function --- clang/include/clang/Interpreter/Interpreter.h | 5 +++-- clang/lib/Interpreter/Interpreter.cpp | 5 ----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index ef56f319e00ef..e066e05c20406 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -23,6 +23,7 @@ #include "llvm/ADT/FunctionExtras.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" +#include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" #include "llvm/Support/Error.h" #include <cstdint> @@ -143,8 +144,8 @@ class Interpreter { /// Factory function for creating LLJITBuilder instances. /// This allows clients to customize JIT builder creation while still /// providing sensible defaults. - llvm::unique_function<llvm::Expected< - std::unique_ptr<llvm::orc::LLJITBuilder>>(const JITConfig &)> + std::function<llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>( + const JITConfig &)> MakeJITBuilder = makeDefaultJITBuilder; JITConfig() diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index c33a037408d61..5847d85154a80 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -278,12 +278,7 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance, if (Act->getCodeGen()) { Act->CacheCodeGenModule(); - // The initial PTU is filled by `-include` or by CUDA includes - // automatically. if (!CI->getPreprocessorOpts().Includes.empty()) { - // We can't really directly pass the CachedInCodeGenModule to the Jit - // because it will steal it, causing dangling references as explained in - // Interpreter::Execute auto M = llvm::CloneModule(*Act->getCachedCodeGenModule()); ASTContext &C = CI->getASTContext(); IncrParser->RegisterPTU(C.getTranslationUnitDecl(), std::move(M)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits