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