llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Vassil Vassilev (vgvassilev) <details> <summary>Changes</summary> cc: @<!-- -->aaronj0, @<!-- -->Vipul-Cariappa --- Patch is 31.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/175322.diff 7 Files Affected: - (modified) clang/include/clang/Interpreter/Interpreter.h (+55-36) - (modified) clang/lib/Interpreter/IncrementalExecutor.cpp (+1-2) - (modified) clang/lib/Interpreter/IncrementalExecutor.h (+1-5) - (modified) clang/lib/Interpreter/Interpreter.cpp (+108-107) - (modified) clang/tools/clang-repl/ClangRepl.cpp (+18-13) - (modified) clang/unittests/Interpreter/InterpreterExtensionsTest.cpp (-39) - (modified) clang/unittests/Interpreter/OutOfProcessInterpreterTests.cpp (+57-41) ``````````diff diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 078d70b3b1749..4a69b37338349 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -38,7 +38,7 @@ class ThreadSafeContext; namespace clang { namespace driver { -class ToolChain; +class Compilation; } // namespace driver class CompilerInstance; @@ -50,6 +50,8 @@ class IncrementalCUDADeviceParser; /// Create a pre-configured \c CompilerInstance for incremental processing. class IncrementalCompilerBuilder { + using DriverCompilationFn = llvm::Error(const driver::Compilation &); + public: IncrementalCompilerBuilder() {} @@ -68,11 +70,16 @@ class IncrementalCompilerBuilder { // CUDA specific void SetCudaSDK(llvm::StringRef path) { CudaSDKPath = path; }; + // Hand over the compilation. + void SetDriverCompilationCallback(std::function<DriverCompilationFn> C) { + CompilationCB = C; + } + llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaHost(); llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaDevice(); private: - static llvm::Expected<std::unique_ptr<CompilerInstance>> + llvm::Expected<std::unique_ptr<CompilerInstance>> create(std::string TT, std::vector<const char *> &ClangArgv); llvm::Expected<std::unique_ptr<CompilerInstance>> createCuda(bool device); @@ -82,6 +89,46 @@ class IncrementalCompilerBuilder { llvm::StringRef OffloadArch; llvm::StringRef CudaSDKPath; + + 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; + /// An optional external IncrementalExecutor + // std::unique_ptr<IncrementalExecutor> IE; + 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; @@ -120,42 +167,16 @@ class Interpreter { /// An optional compiler instance for CUDA offloading std::unique_ptr<CompilerInstance> DeviceCI; -public: - struct JITConfig { - /// 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; - - JITConfig() - : IsOutOfProcess(false), OOPExecutor(""), OOPExecutorConnect(""), - UseSharedMemory(false), SlabAllocateSize(0), OrcRuntimePath(""), - ExecutorPID(0), CustomizeFork(nullptr), CM(std::nullopt) {} - }; - 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, - JITConfig Config = JITConfig()); + std::unique_ptr<IncrementalExecutorBuilder> IEB = nullptr); // Create the internal IncrementalExecutor, or re-create it after calling // ResetExecutor(). - llvm::Error CreateExecutor(JITConfig Config = JITConfig()); + llvm::Error CreateExecutor(); // Delete the internal IncrementalExecutor. This causes a hard shutdown of the // JIT engine. In particular, it doesn't run cleanup or destructors. @@ -164,18 +185,14 @@ class Interpreter { public: virtual ~Interpreter(); static llvm::Expected<std::unique_ptr<Interpreter>> - create(std::unique_ptr<CompilerInstance> CI, JITConfig Config = {}); + create(std::unique_ptr<CompilerInstance> CI, + std::unique_ptr<IncrementalExecutorBuilder> IEB = nullptr); 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); - static llvm::Expected< - std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, uint32_t>> - outOfProcessJITBuilder(JITConfig Config); - static llvm::Expected<std::string> - getOrcRuntimePath(const driver::ToolChain &TC); const ASTContext &getASTContext() const; ASTContext &getASTContext(); @@ -221,6 +238,8 @@ class Interpreter { std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder; + std::unique_ptr<IncrementalExecutorBuilder> IncrExecutorBuilder; + /// @} /// @name Value and pretty printing support /// @{ diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp index 11ab2cfaac17a..f0069c4924f7a 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.cpp +++ b/clang/lib/Interpreter/IncrementalExecutor.cpp @@ -69,9 +69,8 @@ IncrementalExecutor::createDefaultJITBuilder( IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, llvm::orc::LLJITBuilder &JITBuilder, - Interpreter::JITConfig Config, llvm::Error &Err) - : TSCtx(TSC), OutOfProcessChildPid(Config.ExecutorPID) { + : TSCtx(TSC) { using namespace llvm::orc; llvm::ErrorAsOutParameter EAO(&Err); diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h index bb1ec33452515..c11c99b9bff8d 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.h +++ b/clang/lib/Interpreter/IncrementalExecutor.h @@ -46,7 +46,6 @@ class IncrementalExecutor { using CtorDtorIterator = llvm::orc::CtorDtorIterator; std::unique_ptr<llvm::orc::LLJIT> Jit; llvm::orc::ThreadSafeContext &TSCtx; - uint32_t OutOfProcessChildPid = -1; llvm::DenseMap<const PartialTranslationUnit *, llvm::orc::ResourceTrackerSP> ResourceTrackers; @@ -58,8 +57,7 @@ class IncrementalExecutor { enum SymbolNameKind { IRName, LinkerName }; IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, - llvm::orc::LLJITBuilder &JITBuilder, - Interpreter::JITConfig Config, llvm::Error &Err); + llvm::orc::LLJITBuilder &JITBuilder, llvm::Error &Err); virtual ~IncrementalExecutor(); virtual llvm::Error addModule(PartialTranslationUnit &PTU); @@ -71,8 +69,6 @@ class IncrementalExecutor { llvm::orc::LLJIT &GetExecutionEngine() { return *Jit; } - uint32_t getOutOfProcessChildPid() const { return OutOfProcessChildPid; } - static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB); diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 1a6f6ea0813b7..01e534416152b 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -182,6 +182,10 @@ IncrementalCompilerBuilder::create(std::string TT, llvm::ArrayRef<const char *> RF = llvm::ArrayRef(ClangArgv); std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF)); + if (CompilationCB) + if (auto Err = (*CompilationCB)(*Compilation.get())) + return std::move(Err); + if (Compilation->getArgs().hasArg(options::OPT_v)) Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false); @@ -247,12 +251,83 @@ IncrementalCompilerBuilder::CreateCudaHost() { return IncrementalCompilerBuilder::createCuda(false); } +IncrementalExecutorBuilder::~IncrementalExecutorBuilder() = default; + +llvm::Expected<std::unique_ptr<IncrementalExecutor>> +IncrementalExecutorBuilder::create(llvm::orc::ThreadSafeContext &TSC, + llvm::orc::LLJITBuilder &JITBuilder) { + // if (IE) + // return std::move(IE); + + llvm::Error Err = llvm::Error::success(); + std::unique_ptr<IncrementalExecutor> Executor; +#ifdef __EMSCRIPTEN__ + Executor = std::make_unique<WasmIncrementalExecutor>(TSC); +#else + Executor = std::make_unique<IncrementalExecutor>(TSC, JITBuilder, Err); +#endif + + if (Err) + return std::move(Err); + + return std::move(Executor); +} + +llvm::Error +IncrementalExecutorBuilder::UpdateOrcRuntimePath(const driver::Compilation &C) { + if (!IsOutOfProcess) + return llvm::Error::success(); + + const std::array<const char *, 3> OrcRTLibNames = { + "liborc_rt.a", "liborc_rt_osx.a", "liborc_rt-x86_64.a"}; + + auto findInDir = [&](llvm::StringRef Base) -> std::optional<std::string> { + for (const char *LibName : OrcRTLibNames) { + llvm::SmallString<256> CandidatePath(Base); + llvm::sys::path::append(CandidatePath, LibName); + if (llvm::sys::fs::exists(CandidatePath)) + return std::string(CandidatePath.str()); + } + return std::nullopt; + }; + + const driver::ToolChain &TC = C.getDefaultToolChain(); + std::string SearchedPaths; + if (std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath()) { + if (auto Found = findInDir(*CompilerRTPath)) { + OrcRuntimePath = *Found; + return llvm::Error::success(); + } + SearchedPaths += *CompilerRTPath; + } else { + return llvm::make_error<llvm::StringError>("CompilerRT path not found", + std::error_code()); + } + + if (std::optional<std::string> ResourceDir = TC.getRuntimePath()) { + if (auto Found = findInDir(*ResourceDir)) { + OrcRuntimePath = *Found; + return llvm::Error::success(); + } + if (!SearchedPaths.empty()) + SearchedPaths += "; "; + SearchedPaths += *ResourceDir; + } else { + return llvm::make_error<llvm::StringError>("ResourceDir path not found", + std::error_code()); + } + + return llvm::make_error<llvm::StringError>( + llvm::Twine("OrcRuntime library not found in: ") + SearchedPaths, + std::error_code()); +} + Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance, llvm::Error &ErrOut, std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder, std::unique_ptr<clang::ASTConsumer> Consumer, - JITConfig Config) - : JITBuilder(std::move(JITBuilder)) { + std::unique_ptr<IncrementalExecutorBuilder> IEB) + : JITBuilder(std::move(JITBuilder)), IncrExecutorBuilder(std::move(IEB)) { CI = std::move(Instance); llvm::ErrorAsOutParameter EAO(&ErrOut); auto LLVMCtx = std::make_unique<llvm::LLVMContext>(); @@ -286,7 +361,7 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance, ASTContext &C = CI->getASTContext(); IncrParser->RegisterPTU(C.getTranslationUnitDecl(), std::move(M)); } - if (llvm::Error Err = CreateExecutor(Config)) { + if (llvm::Error Err = CreateExecutor()) { ErrOut = joinErrors(std::move(ErrOut), std::move(Err)); return; } @@ -348,25 +423,28 @@ const char *const Runtimes = R"( EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...); )"; -llvm::Expected<std::pair<std::unique_ptr<llvm::orc::LLJITBuilder>, uint32_t>> -Interpreter::outOfProcessJITBuilder(JITConfig Config) { +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 (!Config.OOPExecutor.empty()) { + if (!IncrExecutorBuilder.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); + 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 (Config.OOPExecutorConnect != "") { + } else if (IncrExecutorBuilder.OOPExecutorConnect != "") { #if LLVM_ON_UNIX && LLVM_ENABLE_THREADS auto EPCOrErr = IncrementalExecutor::connectTCPSocket( - Config.OOPExecutorConnect, Config.UseSharedMemory, - Config.SlabAllocateSize); + IncrExecutorBuilder.OOPExecutorConnect, + IncrExecutorBuilder.UseSharedMemory, + IncrExecutorBuilder.SlabAllocateSize); if (!EPCOrErr) return EPCOrErr.takeError(); EPC = std::move(*EPCOrErr); @@ -380,7 +458,7 @@ Interpreter::outOfProcessJITBuilder(JITConfig Config) { std::unique_ptr<llvm::orc::LLJITBuilder> JB; if (EPC) { auto JBOrErr = clang::Interpreter::createLLJITBuilder( - std::move(EPC), Config.OrcRuntimePath); + std::move(EPC), IncrExecutorBuilder.OrcRuntimePath); if (!JBOrErr) return JBOrErr.takeError(); JB = std::move(*JBOrErr); @@ -389,84 +467,14 @@ Interpreter::outOfProcessJITBuilder(JITConfig Config) { return std::make_pair(std::move(JB), childPid); } -llvm::Expected<std::string> -Interpreter::getOrcRuntimePath(const driver::ToolChain &TC) { - const std::array<const char *, 3> OrcRTLibNames = { - "liborc_rt.a", "liborc_rt_osx.a", "liborc_rt-x86_64.a"}; - - auto findInDir = [&](llvm::StringRef Base) -> std::optional<std::string> { - for (const char *LibName : OrcRTLibNames) { - llvm::SmallString<256> CandidatePath(Base); - llvm::sys::path::append(CandidatePath, LibName); - if (llvm::sys::fs::exists(CandidatePath)) - return std::string(CandidatePath.str()); - } - return std::nullopt; - }; - - std::string SearchedPaths; - - if (std::optional<std::string> CompilerRTPath = TC.getCompilerRTPath()) { - if (auto Found = findInDir(*CompilerRTPath)) - return *Found; - SearchedPaths += *CompilerRTPath; - } else { - return llvm::make_error<llvm::StringError>("CompilerRT path not found", - std::error_code()); - } - - if (std::optional<std::string> ResourceDir = TC.getRuntimePath()) { - if (auto Found = findInDir(*ResourceDir)) - return *Found; - if (!SearchedPaths.empty()) - SearchedPaths += "; "; - SearchedPaths += *ResourceDir; - } else { - return llvm::make_error<llvm::StringError>("ResourceDir path not found", - std::error_code()); - } - - return llvm::make_error<llvm::StringError>( - llvm::Twine("OrcRuntime library not found in: ") + SearchedPaths, - std::error_code()); -} - -llvm::Expected<std::unique_ptr<Interpreter>> -Interpreter::create(std::unique_ptr<CompilerInstance> CI, JITConfig Config) { - - if (Config.IsOutOfProcess) { - const TargetInfo &TI = CI->getTarget(); - const llvm::Triple &Triple = TI.getTriple(); - - DiagnosticsEngine &Diags = CI->getDiagnostics(); - std::string BinaryName = llvm::sys::fs::getMainExecutable(nullptr, nullptr); - driver::Driver Driver(BinaryName, Triple.str(), Diags); - // Need fake args to get the driver to create a compilation. - std::vector<const char *> Args = {"clang", "--version"}; - std::unique_ptr<clang::driver::Compilation> C( - Driver.BuildCompilation(Args)); - if (!C) { - return llvm::make_error<llvm::StringError>( - "Failed to create driver compilation for out-of-process JIT", - std::error_code()); - } - if (Config.OrcRuntimePath == "") { - const clang::driver::ToolChain &TC = C->getDefaultToolChain(); - - auto OrcRuntimePathOrErr = getOrcRuntimePath(TC); - if (!OrcRuntimePathOrErr) { - return OrcRuntimePathOrErr.takeError(); - } - - Config.OrcRuntimePath = *OrcRuntimePathOrErr; - } - } - +llvm::Expected<std::unique_ptr<Interpreter>> Interpreter::create( + std::unique_ptr<CompilerInstance> CI, + std::unique_ptr<IncrementalExecutorBuilder> IEB /*=nullptr*/) { llvm::Error Err = llvm::Error::success(); std::unique_ptr<llvm::orc::LLJITBuilder> JB; auto Interp = std::unique_ptr<Interpreter>(new Interpreter( - std::move(CI), Err, std::move(JB), /*Consumer=*/nullptr, Config)); + std::move(CI), Err, std::move(JB), /*Consumer=*/nullptr, std::move(IEB))); if (auto E = std::move(Err)) return std::move(E); @@ -560,7 +568,7 @@ size_t Interpreter::getEffectivePTUSize() const { uint32_t Interpreter::getOutOfProcessExecutorPID() const { if (IncrExecutor) - return IncrExecutor->getOutOfProcessChildPid(); + return IncrExecutorBuilder->ExecutorPID; return -1; } @@ -627,7 +635,7 @@ Interpreter::createLLJITBuilder( return std::move(*JB); } -llvm::Error Interpreter::CreateExecutor(JITConfig Config) { +llvm::Error Interpreter::CreateExecutor() { if (IncrExecutor) return llvm::make_error<llvm::StringError>("Operation failed. " "Execution engine exists", @@ -641,13 +649,16 @@ llvm::Error Interpreter::CreateExecutor(JITConfig Config) { llvm::Triple TargetTriple(TT); bool IsWindowsTarget = TargetTriple.isOSWindows(); - if (!IsWindowsTarget && Config.IsOutOfProcess) { + if (!IncrExecutorBuilder) + IncrExecutorBuilder = std::make_unique<IncrementalExecutorBuilder>(); + + if (!IsWindowsTarget && IncrExecutorBuilder->IsOutOfProcess) { if (!JITBuilder) { - auto ResOrErr = outOfProcessJITBuilder(Config); + auto ResOrErr = outOfProcessJITBuilder(*IncrExecutorBuilder); if (!ResOrErr) return ResOrErr.takeError(); JITBuilder = std::move(ResOrErr->first); - Config.ExecutorPID = ResOrErr->second; + IncrExecutorBuilder->ExecutorPID = ResOrErr->second; } if (!JITBuilder) return llvm::make_error<llvm::StringError>( @@ -659,29 +670,19 @@ llvm::Error Interpreter::CreateExecutor(JITConfig Config) { auto JTMB = createJITTargetMachineBuilder(TT); if (!JTMB) return JTMB.takeError(); - if (Config.CM) - JTMB->setCodeModel(Config.CM); + if (IncrExecutorBuilder->CM) + JTMB->setCodeModel(IncrExecutorBuilder->CM); auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB)); if (!JB) return JB.takeError(); JITBuilder = std::move(*JB); } - llvm::Error Err = llvm::Error::success(); - - // Fix: Declare Execu... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/175322 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
