llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Vassil Vassilev (vgvassilev) <details> <summary>Changes</summary> The original Interpreter implementation had a hard dependency on ORC and grew organically with the addition of out-of-process JIT support. This tightly coupled the Interpreter to a specific execution engine and leaked ORC-specific assumptions (runtime layout, symbol lookup, exception model) into higher layers. The WebAssembly integration demonstrated that incremental execution can be implemented without ORC, exposing the need for a cleaner abstraction boundary. This change introduces an IncrementalExecutor interface and moves ORC-based execution behind a concrete implementation. The Interpreter now depends only on the abstract executor, improving layering and encapsulation. In addition, the Interpreter can be configured with user-provided incremental executor implementations, enabling ORC-independent execution, easier testing, and future extensions without modifying the core Interpreter. --- Patch is 53.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/175448.diff 13 Files Affected: - (added) clang/include/clang/Interpreter/IncrementalExecutor.h (+95) - (modified) clang/include/clang/Interpreter/Interpreter.h (+5-49) - (modified) clang/lib/Interpreter/CMakeLists.txt (+1) - (modified) clang/lib/Interpreter/IncrementalExecutor.cpp (+250-100) - (removed) clang/lib/Interpreter/IncrementalExecutor.h (-90) - (modified) clang/lib/Interpreter/Interpreter.cpp (+10-255) - (added) clang/lib/Interpreter/OrcIncrementalExecutor.cpp (+121) - (added) clang/lib/Interpreter/OrcIncrementalExecutor.h (+71) - (modified) clang/lib/Interpreter/Wasm.cpp (+3-2) - (modified) clang/lib/Interpreter/Wasm.h (+3-3) - (modified) clang/tools/clang-repl/ClangRepl.cpp (+1) - (modified) clang/unittests/Interpreter/InterpreterExtensionsTest.cpp (+67-4) - (modified) clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp (+4-2) ``````````diff diff --git a/clang/include/clang/Interpreter/IncrementalExecutor.h b/clang/include/clang/Interpreter/IncrementalExecutor.h new file mode 100644 index 0000000000000..5dfc02e46e6ce --- /dev/null +++ b/clang/include/clang/Interpreter/IncrementalExecutor.h @@ -0,0 +1,95 @@ +//===--- IncrementalExecutor.h - Base Incremental 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. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the base class that performs incremental code execution. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_INTERPRETER_INCREMENTALEXECUTOR_H +#define LLVM_CLANG_LIB_INTERPRETER_INCREMENTALEXECUTOR_H + +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace orc { +class ExecutorAddr; +class LLJITBuilder; +class ThreadSafeContext; +} // namespace orc +} // namespace llvm + +namespace clang { +class IncrementalExecutor; +class TargetInfo; +namespace driver { +class Compilation; +} // namespace driver + +// FIXME: Consider deriving from the LLJITBuilder into a common interpreter +// creation configuraion class. +class IncrementalExecutorBuilder { +public: + /// Indicates whether out-of-process JIT execution is enabled. + bool IsOutOfProcess = false; + /// Path to the out-of-process JIT executor. + std::string OOPExecutor = ""; + std::string OOPExecutorConnect = ""; + /// Indicates whether to use shared memory for communication. + bool UseSharedMemory = false; + /// Representing the slab allocation size for memory management in kb. + unsigned SlabAllocateSize = 0; + /// Path to the ORC runtime library. + 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; + /// An optional external IncrementalExecutor + std::unique_ptr<IncrementalExecutor> IE; + /// An optional external orc jit builder + std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder; + /// A default callback that can be used in the IncrementalCompilerBuilder to + /// retrieve the path to the orc runtime. + std::function<llvm::Error(const driver::Compilation &)> + UpdateOrcRuntimePathCB = [this](const driver::Compilation &C) { + return UpdateOrcRuntimePath(C); + }; + + ~IncrementalExecutorBuilder(); + + llvm::Expected<std::unique_ptr<IncrementalExecutor>> + create(llvm::orc::ThreadSafeContext &TSC, const clang::TargetInfo &TI); + +private: + llvm::Error UpdateOrcRuntimePath(const driver::Compilation &C); +}; + +struct PartialTranslationUnit; + +class IncrementalExecutor { +public: + enum SymbolNameKind { IRName, LinkerName }; + + virtual ~IncrementalExecutor() = default; + + virtual llvm::Error addModule(PartialTranslationUnit &PTU) = 0; + virtual llvm::Error removeModule(PartialTranslationUnit &PTU) = 0; + virtual llvm::Error runCtors() const = 0; + virtual llvm::Error cleanUp() = 0; + + virtual llvm::Expected<llvm::orc::ExecutorAddr> + getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const = 0; + virtual llvm::Error LoadDynamicLibrary(const char *name) = 0; +}; + +} // namespace clang + +#endif // LLVM_CLANG_LIB_INTERPRETER_INCREMENTALEXECUTOR_H diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index c4ddfb067be0f..4af5a55e6860e 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_INTERPRETER_INTERPRETER_H #include "clang/AST/GlobalDecl.h" +#include "clang/Interpreter/IncrementalExecutor.h" #include "clang/Interpreter/PartialTranslationUnit.h" #include "clang/Interpreter/Value.h" @@ -29,8 +30,6 @@ namespace llvm { namespace orc { -class LLJIT; -class LLJITBuilder; class ThreadSafeContext; } // namespace orc } // namespace llvm @@ -44,7 +43,6 @@ class Compilation; class CompilerInstance; class CXXRecordDecl; class Decl; -class IncrementalExecutor; class IncrementalParser; class IncrementalCUDADeviceParser; @@ -93,42 +91,6 @@ class IncrementalCompilerBuilder { std::optional<std::function<DriverCompilationFn>> CompilationCB; }; -// FIXME: Consider deriving from the LLJITBuilder into a common interpreter -// creation configuraion class. -class IncrementalExecutorBuilder { -public: - /// Indicates whether out-of-process JIT execution is enabled. - bool IsOutOfProcess = false; - /// Path to the out-of-process JIT executor. - std::string OOPExecutor = ""; - std::string OOPExecutorConnect = ""; - /// Indicates whether to use shared memory for communication. - bool UseSharedMemory = false; - /// Representing the slab allocation size for memory management in kb. - unsigned SlabAllocateSize = 0; - /// Path to the ORC runtime library. - 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; - std::function<llvm::Error(const driver::Compilation &)> - UpdateOrcRuntimePathCB = [this](const driver::Compilation &C) { - return UpdateOrcRuntimePath(C); - }; - - ~IncrementalExecutorBuilder(); - - llvm::Expected<std::unique_ptr<IncrementalExecutor>> - create(llvm::orc::ThreadSafeContext &TSC, - llvm::orc::LLJITBuilder &JITBuilder); - -private: - llvm::Error UpdateOrcRuntimePath(const driver::Compilation &C); -}; - class IncrementalAction; class InProcessPrintingASTConsumer; @@ -168,9 +130,8 @@ class Interpreter { protected: // Derived classes can use an extended interface of the Interpreter. Interpreter(std::unique_ptr<CompilerInstance> Instance, llvm::Error &Err, - std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder = nullptr, - std::unique_ptr<clang::ASTConsumer> Consumer = nullptr, - std::unique_ptr<IncrementalExecutorBuilder> IEB = nullptr); + std::unique_ptr<IncrementalExecutorBuilder> IEB = nullptr, + std::unique_ptr<clang::ASTConsumer> Consumer = nullptr); // Create the internal IncrementalExecutor, or re-create it after calling // ResetExecutor(). @@ -178,7 +139,7 @@ class Interpreter { // Delete the internal IncrementalExecutor. This causes a hard shutdown of the // JIT engine. In particular, it doesn't run cleanup or destructors. - void ResetExecutor(); + void ResetExecutor() { IncrExecutor.reset(); } public: virtual ~Interpreter(); @@ -188,15 +149,12 @@ class Interpreter { static llvm::Expected<std::unique_ptr<Interpreter>> createWithCUDA(std::unique_ptr<CompilerInstance> CI, std::unique_ptr<CompilerInstance> DCI); - static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> - createLLJITBuilder(std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC, - llvm::StringRef OrcRuntimePath); const ASTContext &getASTContext() const; ASTContext &getASTContext(); const CompilerInstance *getCompilerInstance() const; CompilerInstance *getCompilerInstance(); - llvm::Expected<llvm::orc::LLJIT &> getExecutionEngine(); + llvm::Expected<IncrementalExecutor &> getExecutionEngine(); llvm::Expected<PartialTranslationUnit &> Parse(llvm::StringRef Code); llvm::Error Execute(PartialTranslationUnit &T); @@ -234,8 +192,6 @@ class Interpreter { std::array<Expr *, 4> ValuePrintingInfo = {0}; - std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder; - std::unique_ptr<IncrementalExecutorBuilder> IncrExecutorBuilder; /// @} diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt index 9a597146b2fc4..01d3295d1ac30 100644 --- a/clang/lib/Interpreter/CMakeLists.txt +++ b/clang/lib/Interpreter/CMakeLists.txt @@ -24,6 +24,7 @@ add_clang_library(clangInterpreter CodeCompletion.cpp IncrementalAction.cpp IncrementalExecutor.cpp + OrcIncrementalExecutor.cpp IncrementalParser.cpp Interpreter.cpp InterpreterValuePrinter.cpp diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp index f0069c4924f7a..282138e5c0ab2 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.cpp +++ b/clang/lib/Interpreter/IncrementalExecutor.cpp @@ -6,56 +6,75 @@ // //===----------------------------------------------------------------------===// // -// This file implements the class which performs incremental code execution. +// This has the implementation of the base facilities for incremental execution. // //===----------------------------------------------------------------------===// -#include "IncrementalExecutor.h" +#include "clang/Interpreter/IncrementalExecutor.h" +#include "OrcIncrementalExecutor.h" +#ifdef __EMSCRIPTEN__ +#include "Wasm.h" +#endif // __EMSCRIPTEN__ #include "clang/Basic/TargetInfo.h" -#include "clang/Basic/TargetOptions.h" -#include "clang/Interpreter/PartialTranslationUnit.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/ToolChain.h" + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" + +#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h" #include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h" #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" -#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h" #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h" -#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" #include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h" -#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h" -#include "llvm/ExecutionEngine/SectionMemoryManager.h" -#include "llvm/IR/Module.h" +#include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h" + +#include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" -#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" + #include "llvm/TargetParser/Host.h" +#include <array> +#include <functional> +#include <memory> +#include <optional> +#include <string> +#include <utility> + #ifdef LLVM_ON_UNIX #include <netdb.h> #include <netinet/in.h> #include <sys/socket.h> #include <unistd.h> -#endif // LLVM_ON_UNIX - -// Force linking some of the runtimes that helps attaching to a debugger. -LLVM_ATTRIBUTE_USED void linkComponents() { - llvm::errs() << (void *)&llvm_orc_registerJITLoaderGDBAllocAction; -} +#endif namespace clang { -IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC) - : TSCtx(TSC) {} +IncrementalExecutorBuilder::~IncrementalExecutorBuilder() = default; -llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> -IncrementalExecutor::createDefaultJITBuilder( - llvm::orc::JITTargetMachineBuilder JTMB) { +static llvm::Expected<llvm::orc::JITTargetMachineBuilder> +createJITTargetMachineBuilder(const llvm::Triple &TT) { + if (TT.getTriple() == 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(TT); +} + +static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> +createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB) { auto JITBuilder = std::make_unique<llvm::orc::LLJITBuilder>(); JITBuilder->setJITTargetMachineBuilder(std::move(JTMB)); JITBuilder->setPrePlatformSetup([](llvm::orc::LLJIT &J) { @@ -67,71 +86,6 @@ IncrementalExecutor::createDefaultJITBuilder( return std::move(JITBuilder); } -IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, - llvm::orc::LLJITBuilder &JITBuilder, - llvm::Error &Err) - : TSCtx(TSC) { - using namespace llvm::orc; - llvm::ErrorAsOutParameter EAO(&Err); - - if (auto JitOrErr = JITBuilder.create()) - Jit = std::move(*JitOrErr); - else { - Err = JitOrErr.takeError(); - return; - } -} - -IncrementalExecutor::~IncrementalExecutor() {} - -llvm::Error IncrementalExecutor::addModule(PartialTranslationUnit &PTU) { - llvm::orc::ResourceTrackerSP RT = - Jit->getMainJITDylib().createResourceTracker(); - ResourceTrackers[&PTU] = RT; - - return Jit->addIRModule(RT, {std::move(PTU.TheModule), TSCtx}); -} - -llvm::Error IncrementalExecutor::removeModule(PartialTranslationUnit &PTU) { - - llvm::orc::ResourceTrackerSP RT = std::move(ResourceTrackers[&PTU]); - if (!RT) - return llvm::Error::success(); - - ResourceTrackers.erase(&PTU); - if (llvm::Error Err = RT->remove()) - return Err; - return llvm::Error::success(); -} - -// Clean up the JIT instance. -llvm::Error IncrementalExecutor::cleanUp() { - // This calls the global dtors of registered modules. - return Jit->deinitialize(Jit->getMainJITDylib()); -} - -llvm::Error IncrementalExecutor::runCtors() const { - return Jit->initialize(Jit->getMainJITDylib()); -} - -llvm::Expected<llvm::orc::ExecutorAddr> -IncrementalExecutor::getSymbolAddress(llvm::StringRef Name, - SymbolNameKind NameKind) const { - using namespace llvm::orc; - auto SO = makeJITDylibSearchOrder({&Jit->getMainJITDylib(), - Jit->getPlatformJITDylib().get(), - Jit->getProcessSymbolsJITDylib().get()}); - - ExecutionSession &ES = Jit->getExecutionSession(); - - auto SymOrErr = - ES.lookup(SO, (NameKind == LinkerName) ? ES.intern(Name) - : Jit->mangleAndIntern(Name)); - if (auto Err = SymOrErr.takeError()) - return std::move(Err); - return SymOrErr->getAddress(); -} - Expected<std::unique_ptr<llvm::jitlink::JITLinkMemoryManager>> createSharedMemoryManager(llvm::orc::SimpleRemoteEPC &SREPC, unsigned SlabAllocateSize) { @@ -165,11 +119,10 @@ createSharedMemoryManager(llvm::orc::SimpleRemoteEPC &SREPC, llvm::orc::SharedMemoryMapper>(SlabSize, SREPC, SAs); } -llvm::Expected<std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, uint32_t>> -IncrementalExecutor::launchExecutor(llvm::StringRef ExecutablePath, - bool UseSharedMemory, - unsigned SlabAllocateSize, - std::function<void()> CustomizeFork) { +static llvm::Expected< + std::pair<std::unique_ptr<llvm::orc::SimpleRemoteEPC>, uint32_t>> +launchExecutor(llvm::StringRef ExecutablePath, bool UseSharedMemory, + unsigned SlabAllocateSize, std::function<void()> CustomizeFork) { #ifndef LLVM_ON_UNIX // FIXME: Add support for Windows. return llvm::make_error<llvm::StringError>( @@ -302,10 +255,9 @@ static Expected<int> connectTCPSocketImpl(std::string Host, return SockFD; } -llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>> -IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress, - bool UseSharedMemory, - unsigned SlabAllocateSize) { +static llvm::Expected<std::unique_ptr<llvm::orc::SimpleRemoteEPC>> +connectTCPSocket(llvm::StringRef NetworkAddress, bool UseSharedMemory, + unsigned SlabAllocateSize) { #ifndef LLVM_ON_UNIX // FIXME: Add TCP support for Windows. return llvm::make_error<llvm::StringError>( @@ -357,4 +309,202 @@ IncrementalExecutor::connectTCPSocket(llvm::StringRef NetworkAddress, } #endif // _WIN32 -} // namespace clang +static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> +createLLJITBuilder(std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC, + llvm::StringRef OrcRuntimePath) { + auto JTMB = createJITTargetMachineBuilder(EPC->getTargetTriple()); + if (!JTMB) + return JTMB.takeError(); + auto JB = createDefaultJITBuilder(std::move(*JTMB)); + if (!JB) + return JB.takeError(); + + (*JB)->setExecutorProcessControl(std::move(EPC)); + (*JB)->setPlatformSetUp( + llvm::orc::ExecutorNativePlatform(OrcRuntimePath.str())); + + return std::move(*JB); +} + +static llvm::Expected< + std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, uint32_t>> +outOfProcessJITBuilder(const IncrementalExecutorBuilder &IncrExecutorBuilder) { + std::unique_ptr<llvm::orc::ExecutorProcessControl> EPC; + uint32_t childPid = -1; + if (!IncrExecutorBuilder.OOPExecutor.empty()) { + // Launch an out-of-process executor locally in a child process. + auto ResultOrErr = launchExecutor(IncrExecutorBuilder.OOPExecutor, + IncrExecutorBuilder.UseSharedMemory, + IncrExecutorBuilder.SlabAllocateSize, + IncrExecutorBuilder.CustomizeFork); + if (!ResultOrErr) + return ResultOrErr.takeError(); + childPid = ResultOrErr->second; + auto EPCOrErr = std::move(ResultOrErr->first); + EPC = std::move(EPCOrErr); + } else if (IncrExecutorBuilder.OOPExecutorConnect != "") { +#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS + auto EPCOrErr = connectTCPSocket(IncrExecutorBuilder.OOPExecutorConnect, + IncrExecutorBuilder.UseSharedMemory, + IncrExecutorBuilder.SlabAllocateSize); + if (!EPCOrErr) + return EPCOrErr.takeError(); + EPC = std::move(*EPCOrErr); +#else + return llvm::make_error<llvm::StringError>( + "Out-of-process JIT over TCP is not supported on this platform", + std::error_code()); +#endif + } + + std::unique_ptr<llvm::orc::LLJITBuilder> JB; + if (EPC) { + auto JBOrErr = + createLLJITBuilder(std::move(EPC), IncrExecutorBuilder.OrcRuntimePath); + if (!JBOrErr) + return JBOrErr.takeError(); + JB = std::move(*JBOrErr); + } + + return std::make_pair(std::move(JB), childPid); +} + +llvm::Expected<std::unique_ptr<IncrementalExecutor>> +IncrementalExecutorBuilder::create(llvm::orc::ThreadSafeContext &TSC, + const clang::TargetInfo &TI) { + if (IE) + return std::move(IE); + llvm::Triple TT = TI.getTriple(); + if (!TT.isOSWindows() && IsOutOfProcess) { + if (!JITBuilder) { + auto ResOrErr = outOfProcessJITBuilder(*this); + if (!ResOrErr) + return ResOrErr.takeError(); + JITBuilder = std::move(ResOrErr->first); + 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 (CM) + JTMB->setCodeModel(CM); + auto JB = createDefaultJITBuilder(std::move(*JTMB)); + if (!JB) + return JB.takeError(); + JITBuilder = std::move(*JB); + } + + llvm::Error Err = llvm::Error::success(); + std::unique_ptr<IncrementalExecutor> Executor; +#ifdef __EMSCRIPTEN__ + Executor = std::make_unique<WasmIncrementalExecutor>(TSC); +#else + Executor = s... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/175448 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
