1 //===--- IncrementalExecutor.cpp - Incremental Execution --------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the class which performs incremental code execution. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "IncrementalExecutor.h" 14 15 #include "clang/Basic/TargetInfo.h" 16 #include "clang/Basic/TargetOptions.h" 17 #include "clang/Interpreter/PartialTranslationUnit.h" 18 #include "llvm/ExecutionEngine/ExecutionEngine.h" 19 #include "llvm/ExecutionEngine/Orc/CompileUtils.h" 20 #include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h" 21 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 22 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" 23 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" 24 #include "llvm/ExecutionEngine/Orc/LLJIT.h" 25 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" 26 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h" 27 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 28 #include "llvm/IR/Module.h" 29 #include "llvm/Support/ManagedStatic.h" 30 #include "llvm/Support/TargetSelect.h" 31 32 // Force linking some of the runtimes that helps attaching to a debugger. 33 LLVM_ATTRIBUTE_USED void linkComponents() { 34 llvm::errs() << (void *)&llvm_orc_registerJITLoaderGDBWrapper 35 << (void *)&llvm_orc_registerJITLoaderGDBAllocAction; 36 } 37 38 namespace clang { 39 IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC) 40 : TSCtx(TSC) {} 41 42 llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> 43 IncrementalExecutor::createDefaultJITBuilder( 44 llvm::orc::JITTargetMachineBuilder JTMB) { 45 auto JITBuilder = std::make_unique<llvm::orc::LLJITBuilder>(); 46 JITBuilder->setJITTargetMachineBuilder(std::move(JTMB)); 47 JITBuilder->setPrePlatformSetup([](llvm::orc::LLJIT &J) { 48 // Try to enable debugging of JIT'd code (only works with JITLink for 49 // ELF and MachO). 50 consumeError(llvm::orc::enableDebuggerSupport(J)); 51 return llvm::Error::success(); 52 }); 53 return std::move(JITBuilder); 54 } 55 56 IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, 57 llvm::orc::LLJITBuilder &JITBuilder, 58 llvm::Error &Err) 59 : TSCtx(TSC) { 60 using namespace llvm::orc; 61 llvm::ErrorAsOutParameter EAO(&Err); 62 63 if (auto JitOrErr = JITBuilder.create()) 64 Jit = std::move(*JitOrErr); 65 else { 66 Err = JitOrErr.takeError(); 67 return; 68 } 69 } 70 71 IncrementalExecutor::~IncrementalExecutor() {} 72 73 llvm::Error IncrementalExecutor::addModule(PartialTranslationUnit &PTU) { 74 llvm::orc::ResourceTrackerSP RT = 75 Jit->getMainJITDylib().createResourceTracker(); 76 ResourceTrackers[&PTU] = RT; 77 78 return Jit->addIRModule(RT, {std::move(PTU.TheModule), TSCtx}); 79 } 80 81 llvm::Error IncrementalExecutor::removeModule(PartialTranslationUnit &PTU) { 82 83 llvm::orc::ResourceTrackerSP RT = std::move(ResourceTrackers[&PTU]); 84 if (!RT) 85 return llvm::Error::success(); 86 87 ResourceTrackers.erase(&PTU); 88 if (llvm::Error Err = RT->remove()) 89 return Err; 90 return llvm::Error::success(); 91 } 92 93 // Clean up the JIT instance. 94 llvm::Error IncrementalExecutor::cleanUp() { 95 // This calls the global dtors of registered modules. 96 return Jit->deinitialize(Jit->getMainJITDylib()); 97 } 98 99 llvm::Error IncrementalExecutor::runCtors() const { 100 return Jit->initialize(Jit->getMainJITDylib()); 101 } 102 103 llvm::Expected<llvm::orc::ExecutorAddr> 104 IncrementalExecutor::getSymbolAddress(llvm::StringRef Name, 105 SymbolNameKind NameKind) const { 106 using namespace llvm::orc; 107 auto SO = makeJITDylibSearchOrder({&Jit->getMainJITDylib(), 108 Jit->getPlatformJITDylib().get(), 109 Jit->getProcessSymbolsJITDylib().get()}); 110 111 ExecutionSession &ES = Jit->getExecutionSession(); 112 113 auto SymOrErr = 114 ES.lookup(SO, (NameKind == LinkerName) ? ES.intern(Name) 115 : Jit->mangleAndIntern(Name)); 116 if (auto Err = SymOrErr.takeError()) 117 return std::move(Err); 118 return SymOrErr->getAddress(); 119 } 120 121 } // end namespace clang 122