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/ExecutionUtils.h" 21 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" 22 #include "llvm/ExecutionEngine/Orc/LLJIT.h" 23 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" 24 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h" 25 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 26 #include "llvm/IR/Module.h" 27 #include "llvm/Support/ManagedStatic.h" 28 #include "llvm/Support/TargetSelect.h" 29 30 // Force linking some of the runtimes that helps attaching to a debugger. 31 LLVM_ATTRIBUTE_USED void linkComponents() { 32 llvm::errs() << (void *)&llvm_orc_registerJITLoaderGDBWrapper 33 << (void *)&llvm_orc_registerJITLoaderGDBAllocAction; 34 } 35 36 namespace clang { 37 38 IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, 39 llvm::Error &Err, 40 const clang::TargetInfo &TI) 41 : TSCtx(TSC) { 42 using namespace llvm::orc; 43 llvm::ErrorAsOutParameter EAO(&Err); 44 45 auto JTMB = JITTargetMachineBuilder(TI.getTriple()); 46 JTMB.addFeatures(TI.getTargetOpts().Features); 47 LLJITBuilder Builder; 48 Builder.setJITTargetMachineBuilder(JTMB); 49 // Enable debugging of JIT'd code (only works on JITLink for ELF and MachO). 50 Builder.setEnableDebuggerSupport(true); 51 52 if (auto JitOrErr = Builder.create()) 53 Jit = std::move(*JitOrErr); 54 else { 55 Err = JitOrErr.takeError(); 56 return; 57 } 58 } 59 60 IncrementalExecutor::~IncrementalExecutor() {} 61 62 llvm::Error IncrementalExecutor::addModule(PartialTranslationUnit &PTU) { 63 llvm::orc::ResourceTrackerSP RT = 64 Jit->getMainJITDylib().createResourceTracker(); 65 ResourceTrackers[&PTU] = RT; 66 67 return Jit->addIRModule(RT, {std::move(PTU.TheModule), TSCtx}); 68 } 69 70 llvm::Error IncrementalExecutor::removeModule(PartialTranslationUnit &PTU) { 71 72 llvm::orc::ResourceTrackerSP RT = std::move(ResourceTrackers[&PTU]); 73 if (!RT) 74 return llvm::Error::success(); 75 76 ResourceTrackers.erase(&PTU); 77 if (llvm::Error Err = RT->remove()) 78 return Err; 79 return llvm::Error::success(); 80 } 81 82 // Clean up the JIT instance. 83 llvm::Error IncrementalExecutor::cleanUp() { 84 // This calls the global dtors of registered modules. 85 return Jit->deinitialize(Jit->getMainJITDylib()); 86 } 87 88 llvm::Error IncrementalExecutor::runCtors() const { 89 return Jit->initialize(Jit->getMainJITDylib()); 90 } 91 92 llvm::Expected<llvm::orc::ExecutorAddr> 93 IncrementalExecutor::getSymbolAddress(llvm::StringRef Name, 94 SymbolNameKind NameKind) const { 95 using namespace llvm::orc; 96 auto SO = makeJITDylibSearchOrder({&Jit->getMainJITDylib(), 97 Jit->getPlatformJITDylib().get(), 98 Jit->getProcessSymbolsJITDylib().get()}); 99 100 ExecutionSession &ES = Jit->getExecutionSession(); 101 102 auto SymOrErr = 103 ES.lookup(SO, (NameKind == LinkerName) ? ES.intern(Name) 104 : Jit->mangleAndIntern(Name)); 105 if (auto Err = SymOrErr.takeError()) 106 return std::move(Err); 107 return SymOrErr->getAddress(); 108 } 109 110 } // end namespace clang 111